From 4854d7f69d9bfc2f16cda403ab75b1844eefcce8 Mon Sep 17 00:00:00 2001 From: Anthony Romano Date: Fri, 12 Feb 2016 09:43:39 -0800 Subject: [PATCH] storage: support ranges for >= key If end == "", range(key, end) will give all keys >= key. --- clientv3/kv.go | 3 ++- etcdserver/etcdserverpb/rpc.proto | 3 ++- storage/index.go | 4 ++-- storage/kv.go | 3 ++- storage/kv_test.go | 5 +++++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/clientv3/kv.go b/clientv3/kv.go index 6f9a81532..9efc2dc23 100644 --- a/clientv3/kv.go +++ b/clientv3/kv.go @@ -38,7 +38,8 @@ type KV interface { // Get retrieves keys. // By default, Get will return the value for "key", if any. - // When passed WithRange(end), Get will return the keys in the range [key, end). + // When passed WithRange(end), Get will return the keys in the range [key, end) if + // end is non-empty, otherwise it returns keys greater than or equal to key. // When passed WithRev(rev) with rev > 0, Get retrieves keys at the given revision; // if the required revision is compacted, the request will fail with ErrCompacted . // When passed WithLimit(limit), the number of returned keys is bounded by limit. diff --git a/etcdserver/etcdserverpb/rpc.proto b/etcdserver/etcdserverpb/rpc.proto index 8734c6fb1..dcf0e0be0 100644 --- a/etcdserver/etcdserverpb/rpc.proto +++ b/etcdserver/etcdserverpb/rpc.proto @@ -101,7 +101,8 @@ message RangeRequest { // if the range_end is not given, the request returns the key. bytes key = 1; - // if the range_end is given, it gets the keys in range [key, range_end). + // if the range_end is given, it gets the keys in range [key, range_end) + // if range_end is nonempty, otherwise it returns all keys >= key. bytes range_end = 2; // limit the number of keys returned. int64 limit = 3; diff --git a/storage/index.go b/storage/index.go index cb196fed8..df0be99f6 100644 --- a/storage/index.go +++ b/storage/index.go @@ -104,7 +104,7 @@ func (ti *treeIndex) Range(key, end []byte, atRev int64) (keys [][]byte, revs [] defer ti.RUnlock() ti.tree.AscendGreaterOrEqual(keyi, func(item btree.Item) bool { - if !item.Less(endi) { + if len(endi.key) > 0 && !item.Less(endi) { return false } curKeyi := item.(*keyIndex) @@ -154,7 +154,7 @@ func (ti *treeIndex) RangeSince(key, end []byte, rev int64) []revision { endi := &keyIndex{key: end} var revs []revision ti.tree.AscendGreaterOrEqual(keyi, func(item btree.Item) bool { - if !item.Less(endi) { + if len(endi.key) > 0 && !item.Less(endi) { return false } curKeyi := item.(*keyIndex) diff --git a/storage/kv.go b/storage/kv.go index a68e12060..9bcde9c86 100644 --- a/storage/kv.go +++ b/storage/kv.go @@ -33,7 +33,8 @@ type KV interface { // The returned rev is the current revision of the KV when the operation is executed. // If rangeRev <=0, range gets the keys at currentRev. // If `end` is nil, the request returns the key. - // If `end` is not nil, it gets the keys in range [key, range_end). + // If `end` is not nil and not empty, it gets the keys in range [key, range_end). + // If `end` is not nil and empty, it gets the keys greater than or equal to key. // Limit limits the number of keys returned. // If the required rev is compacted, ErrCompacted will be returned. Range(key, end []byte, limit, rangeRev int64) (kvs []storagepb.KeyValue, rev int64, err error) diff --git a/storage/kv_test.go b/storage/kv_test.go index 89f2b2863..cf0f9183b 100644 --- a/storage/kv_test.go +++ b/storage/kv_test.go @@ -120,6 +120,11 @@ func testKVRange(t *testing.T, f rangeFunc) { []byte("foo"), nil, kvs[:1], }, + // get entire keyspace + { + []byte(""), []byte(""), + kvs, + }, } for i, tt := range tests {