From 59291770d64c32bdc041b024c8b1d76c1e8eb8ee Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Thu, 18 Feb 2016 00:53:04 -0800 Subject: [PATCH] clientv3: WithPrefix operation option --- clientv3/integration/kv_test.go | 51 ++++++++++++++++++++------------- clientv3/op.go | 16 +++++++++++ clientv3/sync/syncer.go | 28 ++---------------- 3 files changed, 49 insertions(+), 46 deletions(-) diff --git a/clientv3/integration/kv_test.go b/clientv3/integration/kv_test.go index 0fbf7d72a..f393f5365 100644 --- a/clientv3/integration/kv_test.go +++ b/clientv3/integration/kv_test.go @@ -96,10 +96,9 @@ func TestKVRange(t *testing.T) { wheader := resp.Header tests := []struct { - begin, end string - rev int64 - sortOption *clientv3.SortOption - serializable bool + begin, end string + rev int64 + opts []clientv3.OpOption wantSet []*storagepb.KeyValue }{ @@ -108,7 +107,6 @@ func TestKVRange(t *testing.T) { "a", "c", 0, nil, - false, []*storagepb.KeyValue{ {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, @@ -119,8 +117,7 @@ func TestKVRange(t *testing.T) { { "a", "c", 0, - nil, - true, + []clientv3.OpOption{clientv3.WithSerializable()}, []*storagepb.KeyValue{ {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, @@ -132,7 +129,6 @@ func TestKVRange(t *testing.T) { "a", "x", 2, nil, - false, []*storagepb.KeyValue{ {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, @@ -142,8 +138,7 @@ func TestKVRange(t *testing.T) { { "a", "x", 0, - &clientv3.SortOption{Target: clientv3.SortByKey, Order: clientv3.SortAscend}, - false, + []clientv3.OpOption{clientv3.WithSort(clientv3.SortByKey, clientv3.SortAscend)}, []*storagepb.KeyValue{ {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, @@ -158,8 +153,7 @@ func TestKVRange(t *testing.T) { { "a", "x", 0, - &clientv3.SortOption{Target: clientv3.SortByCreatedRev, Order: clientv3.SortDescend}, - false, + []clientv3.OpOption{clientv3.WithSort(clientv3.SortByCreatedRev, clientv3.SortDescend)}, []*storagepb.KeyValue{ {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, @@ -174,8 +168,7 @@ func TestKVRange(t *testing.T) { { "a", "x", 0, - &clientv3.SortOption{Target: clientv3.SortByModifiedRev, Order: clientv3.SortDescend}, - false, + []clientv3.OpOption{clientv3.WithSort(clientv3.SortByModifiedRev, clientv3.SortDescend)}, []*storagepb.KeyValue{ {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, @@ -186,16 +179,34 @@ func TestKVRange(t *testing.T) { {Key: []byte("a"), Value: nil, CreateRevision: 2, ModRevision: 2, Version: 1}, }, }, + // WithPrefix + { + "foo", "", + 0, + []clientv3.OpOption{clientv3.WithPrefix()}, + + []*storagepb.KeyValue{ + {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, + {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, + }, + }, + // WithFromKey + { + "fo", "", + 0, + []clientv3.OpOption{clientv3.WithFromKey()}, + + []*storagepb.KeyValue{ + {Key: []byte("foo"), Value: nil, CreateRevision: 7, ModRevision: 7, Version: 1}, + {Key: []byte("foo/abc"), Value: nil, CreateRevision: 8, ModRevision: 8, Version: 1}, + {Key: []byte("fop"), Value: nil, CreateRevision: 9, ModRevision: 9, Version: 1}, + }, + }, } for i, tt := range tests { opts := []clientv3.OpOption{clientv3.WithRange(tt.end), clientv3.WithRev(tt.rev)} - if tt.sortOption != nil { - opts = append(opts, clientv3.WithSort(tt.sortOption.Target, tt.sortOption.Order)) - } - if tt.serializable == true { - opts = append(opts, clientv3.WithSerializable()) - } + opts = append(opts, tt.opts...) resp, err := kv.Get(ctx, tt.begin, opts...) if err != nil { t.Fatalf("#%d: couldn't range (%v)", i, err) diff --git a/clientv3/op.go b/clientv3/op.go index 616f86438..db168e96e 100644 --- a/clientv3/op.go +++ b/clientv3/op.go @@ -129,6 +129,22 @@ func WithSort(tgt SortTarget, order SortOrder) OpOption { op.sort = &SortOption{tgt, order} } } +func WithPrefix() OpOption { + return func(op *Op) { + op.end = make([]byte, len(op.key)) + copy(op.end, op.key) + for i := len(op.end) - 1; i >= 0; i-- { + if op.end[i] < 0xff { + op.end[i] = op.end[i] + 1 + op.end = op.end[:i+1] + return + } + } + // next prefix does not exist (e.g., 0xffff); + // default to WithFromKey policy + op.end = []byte{0} + } +} func WithRange(endKey string) OpOption { return func(op *Op) { op.end = []byte(endKey) } } diff --git a/clientv3/sync/syncer.go b/clientv3/sync/syncer.go index 0a2040b53..d416c660c 100644 --- a/clientv3/sync/syncer.go +++ b/clientv3/sync/syncer.go @@ -65,7 +65,7 @@ func (s *syncer) SyncBase(ctx context.Context) (<-chan clientv3.GetResponse, cha defer close(respchan) defer close(errchan) - var key, end string + var key string opts := []clientv3.OpOption{clientv3.WithLimit(batchLimit), clientv3.WithRev(s.rev)} @@ -78,15 +78,8 @@ func (s *syncer) SyncBase(ctx context.Context) (<-chan clientv3.GetResponse, cha // If len(s.prefix) != 0, we will sync key-value space with given prefix. // We then range from the prefix to the next prefix if exists. Or we will // range from the prefix to the end if the next prefix does not exists. - // (For example, when the given prefix is 0xffff, the next prefix does not - // exist). + opts = append(opts, clientv3.WithPrefix()) key = s.prefix - end = string(incr([]byte(s.prefix))) - if len(end) == 0 { - opts = append(opts, clientv3.WithFromKey()) - } else { - opts = append(opts, clientv3.WithRange(string(end))) - } } for { @@ -131,20 +124,3 @@ func (s *syncer) SyncUpdates(ctx context.Context) clientv3.WatchChan { return respchan } - -func incr(bs []byte) []byte { - c := int8(1) - for i := range bs { - j := len(bs) - i - 1 - n := int8(bs[j]) - n += c - bs[j] = byte(n) - if n == 0 { - c = 1 - } else { - c = 0 - return bs - } - } - return nil -}