Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for memo backend. #172

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ before_script:
- script/travis_consul.sh 0.6.3
- script/travis_etcd.sh 3.0.0
- script/travis_zk.sh 3.5.1-alpha
- script/travis_memo.sh 0.9.2

script:
- ./consul agent -server -bootstrap -advertise=127.0.0.1 -data-dir /tmp/consul -config-file=./config.json 1>/dev/null &
- ./etcd/etcd --listen-client-urls 'http://0.0.0.0:4001' --advertise-client-urls 'http://127.0.0.1:4001' >/dev/null 2>&1 &
- ./zk/bin/zkServer.sh start ./zk/conf/zoo.cfg 1> /dev/null
- ./script/travis_start_zk.sh
- ./memo/bin/memo kvs run kvs --allow-root-creation --grpc localhost:9000 >/dev/null 2>&1 &
- script/validate-gofmt
- go vet ./...
- fgt golint ./...
- go test -v -race ./...
- script/coverage
- goveralls -service=travis-ci -coverprofile=goverage.report

dist: trusty
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ You can find examples of usage for `libkv` under in `docs/examples.go`. Optional
- Etcd versions >= `2.0` because it uses the new `coreos/etcd/client`, this might change in the future as the support for `APIv3` comes along and adds more capabilities.
- Zookeeper versions >= `3.4.5`. Although this might work with previous version but this remains untested as of now.
- Boltdb, which shouldn't be subject to any version dependencies.
- Memo version >= 0.9.2.

## Interface

Expand Down Expand Up @@ -62,19 +63,19 @@ Backend drivers in `libkv` are generally divided between **local drivers** and *

Local drivers are usually used in complement to the distributed drivers to store informations that only needs to be available locally.

| Calls | Consul | Etcd | Zookeeper | BoltDB |
|-----------------------|:----------:|:------:|:-----------:|:--------:|
| Put | X | X | X | X |
| Get | X | X | X | X |
| Delete | X | X | X | X |
| Exists | X | X | X | X |
| Watch | X | X | X | |
| WatchTree | X | X | X | |
| NewLock (Lock/Unlock) | X | X | X | |
| List | X | X | X | X |
| DeleteTree | X | X | X | X |
| AtomicPut | X | X | X | X |
| Close | X | X | X | X |
| Calls | Consul | Etcd | Zookeeper | BoltDB | Memo |
|-----------------------|:----------:|:------:|:-----------:|:--------:|:------:|
| Put | X | X | X | X | X |
| Get | X | X | X | X | X |
| Delete | X | X | X | X | X |
| Exists | X | X | X | X | X |
| Watch | X | X | X | | |
| WatchTree | X | X | X | | |
| NewLock (Lock/Unlock) | X | X | X | | |
| List | X | X | X | X | X |
| DeleteTree | X | X | X | X | X |
| AtomicPut | X | X | X | X | |
| Close | X | X | X | X | X |

## Limitations

Expand Down Expand Up @@ -104,4 +105,4 @@ Want to hack on libkv? [Docker's contributions guidelines](https://github.com/do

## Copyright and license

Copyright © 2014-2016 Docker, Inc. All rights reserved, except as follows. Code is released under the Apache 2.0 license. The README.md file, and files in the "docs" folder are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file "LICENSE.docs". You may obtain a duplicate copy of the same license, titled CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.
Copyright © 2014-2017 Docker, Inc. All rights reserved, except as follows. Code is released under the Apache 2.0 license. The README.md file, and files in the "docs" folder are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file "LICENSE.docs". You may obtain a duplicate copy of the same license, titled CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.
17 changes: 17 additions & 0 deletions script/travis_memo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

VERSION=$1
if test -z "$VERSION"; then
VERSION=0.9.2
fi

tarball=https://storage.googleapis.com/sh_infinit_releases/linux64/memo-x86_64-linux_debian_oldstable-gcc4-$VERSION.tbz

wget "$tarball"
tar -xvf memo-x86_64-linux_debian_oldstable-gcc4-$VERSION.tbz
mv memo-x86_64-linux_debian_oldstable-gcc4-$VERSION memo

memo/bin/memo user create
memo/bin/memo silo create filesystem silo
memo/bin/memo network create network --silo silo
memo/bin/memo kvs create --name kvs --network network
11 changes: 11 additions & 0 deletions script/travis_start_zk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#! /bin/bash

while true; do
./zk/bin/zkServer.sh start ./zk/conf/zoo.cfg
sleep 3
if echo stat |nc localhost 2181 |grep -q Mode; then
break
fi
echo zk did not start properly, retrying...
./zk/bin/zkServer.sh stop
done
137 changes: 137 additions & 0 deletions store/memo/memo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package memo

import (
"github.com/docker/libkv"
"github.com/docker/libkv/store"
kvs "github.com/docker/libkv/store/memo/memo_kvs"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
)

// Memo is the receiver type for the Store interface
type Memo struct {
kvs kvs.KeyValueStoreClient
}

// Register registers memo to libkv
func Register() {
libkv.AddStore("memo", New)
}

// New creates a new memo client
func New(addrs []string, options *store.Config) (store.Store, error) {
conn, err := grpc.Dial(addrs[0], grpc.WithInsecure())
if err != nil {
return nil, err
}
kvs := kvs.NewKeyValueStoreClient(conn)
return &Memo{kvs: kvs}, nil
}

// Get current value at "key".
func (s *Memo) Get(key string) (*store.KVPair, error) {
res, err := s.kvs.Fetch(context.Background(), &kvs.FetchRequest{Key: key})
if err != nil {
if grpc.Code(err) == codes.NotFound {
return nil, store.ErrKeyNotFound
}
return nil, err
}
return &store.KVPair{
Key: key,
Value: res.Value,
LastIndex: 0,
}, nil
}

// Put value at "key"
func (s *Memo) Put(key string, value []byte, options *store.WriteOptions) error {
_, err := s.kvs.Upsert(context.Background(),
&kvs.UpsertRequest{Key: key, Value: value})
return err
}

// Delete value at "key"
func (s *Memo) Delete(key string) error {
_, err := s.kvs.Delete(context.Background(), &kvs.DeleteRequest{Key: key})
if err != nil && grpc.Code(err) == codes.NotFound {
return store.ErrKeyNotFound
}
return err
}

// Exists checks if "key" is present in the store
func (s *Memo) Exists(key string) (bool, error) {
_, err := s.kvs.Fetch(context.Background(), &kvs.FetchRequest{Key: key})
if err == nil {
return true, nil
}
if grpc.Code(err) == codes.NotFound {
return false, nil
}
return false, err
}

// Watch for changes. Not supported by memo.
func (s *Memo) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) {
return nil, store.ErrCallNotSupported
}

// WatchTree for changes. Not supported by memo.
func (s *Memo) WatchTree(directory string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) {
return nil, store.ErrCallNotSupported
}

// NewLock is not supported by memo.
func (s *Memo) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
return nil, store.ErrCallNotSupported
}

// List keys with given prefix.
func (s *Memo) List(directory string) ([]*store.KVPair, error) {
keys, err := s.kvs.List(context.Background(),
&kvs.ListRequest{Prefix: directory, MaxKeys: 1000000000})
if err != nil {
return nil, err
}
var res []*store.KVPair
for _, k := range keys.Items {
kv, err := s.Get(k.Key)
if err != nil {
return nil, err
}
res = append(res, kv)
}
if len(res) == 0 {
return nil, store.ErrKeyNotFound
}
return res, nil
}

// DeleteTree deletes all entries with given prefix.
func (s *Memo) DeleteTree(directory string) error {
keys, err := s.kvs.List(context.Background(),
&kvs.ListRequest{Prefix: directory, MaxKeys: 1000000000})
if err != nil {
return err
}
for _, k := range keys.Items {
s.Delete(k.Key)
}
return nil
}

// AtomicPut is not supported by memo.
func (s *Memo) AtomicPut(key string, value []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) {
return false, nil, store.ErrCallNotSupported
}

// AtomicDelete is not supported by memo.
func (s *Memo) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
return false, store.ErrCallNotSupported
}

// Close the connection
func (s *Memo) Close() {
}
Loading