store: Improved locking API and added mocks.

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
Andrea Luzzardi 2015-05-19 19:22:08 -07:00
parent 2ff9679938
commit 78839ba4ea
5 changed files with 45 additions and 19 deletions

View File

@ -302,13 +302,16 @@ func (s *Consul) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*KVP
return watchCh, nil
}
// CreateLock returns a handle to a lock struct which can be used
// to acquire and release the mutex.
func (s *Consul) CreateLock(key string, value []byte) (Locker, error) {
l, err := s.client.LockOpts(&api.LockOptions{
Key: s.normalize(key),
Value: value,
})
// NewLock returns a handle to a lock struct which can be used to acquire and
// release the mutex.
func (s *Consul) NewLock(key string, options *LockOptions) (Locker, error) {
consulOpts := &api.LockOptions{
Key: s.normalize(key),
}
if options != nil {
consulOpts.Value = options.Value
}
l, err := s.client.LockOpts(consulOpts)
if err != nil {
return nil, err
}

View File

@ -277,8 +277,8 @@ func (s *Etcd) DeleteTree(prefix string) error {
return nil
}
// CreateLock returns a handle to a lock struct which can be used
// to acquire and release the mutex.
func (s *Etcd) CreateLock(key string, value []byte) (Locker, error) {
// NewLock returns a handle to a lock struct which can be used to acquire and
// release the mutex.
func (s *Etcd) NewLock(key string, options *LockOptions) (Locker, error) {
return nil, ErrNotImplemented
}

View File

@ -56,9 +56,9 @@ func (s *Mock) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*KVPai
return args.Get(0).(chan []*KVPair), args.Error(1)
}
// CreateLock mock
func (s *Mock) CreateLock(key string, value []byte) (Locker, error) {
args := s.Mock.Called(key, value)
// NewLock mock
func (s *Mock) NewLock(key string, options *LockOptions) (Locker, error) {
args := s.Mock.Called(key, options)
return args.Get(0).(Locker), args.Error(1)
}
@ -85,3 +85,20 @@ func (s *Mock) AtomicDelete(key string, previous *KVPair) (bool, error) {
args := s.Mock.Called(key, previous)
return args.Bool(0), args.Error(1)
}
// MockLock mock implementation of Locker
type MockLock struct {
mock.Mock
}
// Lock mock
func (l *MockLock) Lock() (<-chan struct{}, error) {
args := l.Mock.Called()
return args.Get(0).(<-chan struct{}), args.Error(1)
}
// Unlock mock
func (l *MockLock) Unlock() error {
args := l.Mock.Called()
return args.Error(0)
}

View File

@ -78,7 +78,7 @@ type Store interface {
// CreateLock for a given key.
// The returned Locker is not held and must be acquired with `.Lock`.
// value is optional.
CreateLock(key string, value []byte) (Locker, error)
NewLock(key string, options *LockOptions) (Locker, error)
// List the content of a given prefix
List(prefix string) ([]*KVPair, error)
@ -106,6 +106,11 @@ type WriteOptions struct {
Ephemeral bool
}
// LockOptions contains optional request parameters
type LockOptions struct {
Value []byte // Optional, value to associate with the lock
}
// WatchCallback is used for watch methods on keys
// and is triggered on key change
type WatchCallback func(entries ...*KVPair)
@ -130,7 +135,7 @@ var (
}
)
// CreateStore creates a an instance of store
// NewStore creates a an instance of store
func NewStore(backend Backend, addrs []string, options *Config) (Store, error) {
if init, exists := initializers[backend]; exists {
log.WithFields(log.Fields{"backend": backend}).Debug("Initializing store service")

View File

@ -222,10 +222,11 @@ func (s *Zookeeper) AtomicDelete(key string, previous *KVPair) (bool, error) {
return false, ErrNotImplemented
}
// CreateLock returns a handle to a lock struct which can be used
// to acquire and release the mutex.
func (s *Zookeeper) CreateLock(key string, value []byte) (Locker, error) {
// FIXME: `value` is not being used since there is no support in zk.NewLock().
// NewLock returns a handle to a lock struct which can be used to acquire and
// release the mutex.
func (s *Zookeeper) NewLock(key string, options *LockOptions) (Locker, error) {
// FIXME: `options.Value` is not being used since there is no support in
// zk.NewLock().
return &zookeeperLock{
lock: zk.NewLock(s.client, normalize(key), zk.WorldACL(zk.PermAll)),
}, nil