From 56f28145dd19105a023fd54d6a7f24c3181fae95 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 30 Mar 2018 22:36:04 +0200 Subject: [PATCH 1/9] working on it --- Gopkg.lock | 2 +- store/iavlstore.go | 19 ++++++++++++++- store/iavlstore_test.go | 52 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 267acf32b..377390297 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -458,6 +458,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "cce90fda84a63ae5b41b40f0edc357eec4020d17fdd61585960ad537418749ea" + inputs-digest = "ed1f3f7f1728cd02945f90ca780e9bdc982573a36a5cc8d7e9f19fb40ba2ca19" solver-name = "gps-cdcl" solver-version = 1 diff --git a/store/iavlstore.go b/store/iavlstore.go index 96110c59c..5f1917e2c 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -122,7 +122,24 @@ func (st *iavlStore) Iterator(start, end []byte) Iterator { func (st *iavlStore) Subspace(prefix []byte) Iterator { end := make([]byte, len(prefix)) copy(end, prefix) - end[len(end)-1]++ + finished := false + i := 1 + + for !finished { + fmt.Printf("%v %v \n", len(end), i) + fmt.Printf("%v \n", end) + if end[len(end)-i] != byte(255) { + end[len(end)-i]++ + finished = true + } else { + end[len(end)-i]++ + i++ + if i > len(end) { + end = []byte{} + finished = true + } + } + } return st.Iterator(prefix, end) } diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 7adae625e..85e02ba25 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -73,13 +73,26 @@ func TestIAVLIterator(t *testing.T) { iavlStore := newIAVLStore(tree, numHistory) iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz")) expected := []string{"aloha", "hello"} - for i := 0; iter.Valid(); iter.Next() { + i := 0 + for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, treeData[expectedKey]) i += 1 } + assert.Equal(t, i, len(expected)) + + iter = iavlStore.Iterator([]byte("golang"), []byte("rocks")) + expected = []string{"hello"} + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, treeData[expectedKey]) + i += 1 + } + assert.Equal(t, i, len(expected)) } func TestIAVLSubspace(t *testing.T) { @@ -90,16 +103,51 @@ func TestIAVLSubspace(t *testing.T) { iavlStore.Set([]byte("test1"), []byte("test1")) iavlStore.Set([]byte("test2"), []byte("test2")) iavlStore.Set([]byte("test3"), []byte("test3")) + iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4")) + iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4")) + iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4")) + i := 0 iter := iavlStore.Subspace([]byte("test")) expected := []string{"test1", "test2", "test3"} - for i := 0; iter.Valid(); iter.Next() { + for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] key, value := iter.Key(), iter.Value() assert.EqualValues(t, key, expectedKey) assert.EqualValues(t, value, expectedKey) i += 1 } + assert.Equal(t, i, len(expected)) + + iter = iavlStore.Subspace([]byte{byte(55), byte(255), byte(255)}) + expected2 := [][]byte{ + []byte{byte(55), byte(255), byte(255), byte(0)}, + []byte{byte(55), byte(255), byte(255), byte(1)}, + []byte{byte(55), byte(255), byte(255), byte(255)}, + } + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected2[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, []byte("test4")) + i += 1 + } + assert.Equal(t, i, len(expected)) + + iter = iavlStore.Subspace([]byte{byte(255), byte(255)}) + expected2 = [][]byte{ + []byte{byte(255), byte(255), byte(0)}, + []byte{byte(255), byte(255), byte(1)}, + []byte{byte(255), byte(255), byte(255)}, + } + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected2[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, []byte("test4")) + i += 1 + } + assert.Equal(t, i, len(expected)) } func TestIAVLStoreQuery(t *testing.T) { From 271d240897a6826074125eb29fd754692dad3984 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sat, 31 Mar 2018 19:30:25 +0200 Subject: [PATCH 2/9] trying to figure it out --- store/iavlstore.go | 6 +++--- store/iavlstore_test.go | 21 ++++++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/store/iavlstore.go b/store/iavlstore.go index 5f1917e2c..a1a48722c 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -126,8 +126,6 @@ func (st *iavlStore) Subspace(prefix []byte) Iterator { i := 1 for !finished { - fmt.Printf("%v %v \n", len(end), i) - fmt.Printf("%v \n", end) if end[len(end)-i] != byte(255) { end[len(end)-i]++ finished = true @@ -135,11 +133,12 @@ func (st *iavlStore) Subspace(prefix []byte) Iterator { end[len(end)-i]++ i++ if i > len(end) { - end = []byte{} + end = nil finished = true } } } + fmt.Printf("%v \n", end) return st.Iterator(prefix, end) } @@ -243,6 +242,7 @@ func newIAVLIterator(tree *iavl.Tree, start, end []byte, ascending bool) *iavlIt quitCh: make(chan struct{}), initCh: make(chan struct{}), } + fmt.Printf("%v %v \n", iter.start, iter.end) go iter.iterateRoutine() go iter.initRoutine() return iter diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 85e02ba25..6e276c3d2 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -81,7 +81,7 @@ func TestIAVLIterator(t *testing.T) { assert.EqualValues(t, value, treeData[expectedKey]) i += 1 } - assert.Equal(t, i, len(expected)) + assert.Equal(t, len(expected), i) iter = iavlStore.Iterator([]byte("golang"), []byte("rocks")) expected = []string{"hello"} @@ -92,7 +92,18 @@ func TestIAVLIterator(t *testing.T) { assert.EqualValues(t, value, treeData[expectedKey]) i += 1 } - assert.Equal(t, i, len(expected)) + assert.Equal(t, len(expected), i) + + iter = iavlStore.Iterator([]byte("golang"), nil) + expected = []string{"hello"} + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, treeData[expectedKey]) + i += 1 + } + assert.Equal(t, len(expected), i) } func TestIAVLSubspace(t *testing.T) { @@ -117,7 +128,7 @@ func TestIAVLSubspace(t *testing.T) { assert.EqualValues(t, value, expectedKey) i += 1 } - assert.Equal(t, i, len(expected)) + assert.Equal(t, len(expected), i) iter = iavlStore.Subspace([]byte{byte(55), byte(255), byte(255)}) expected2 := [][]byte{ @@ -132,7 +143,7 @@ func TestIAVLSubspace(t *testing.T) { assert.EqualValues(t, value, []byte("test4")) i += 1 } - assert.Equal(t, i, len(expected)) + assert.Equal(t, len(expected), i) iter = iavlStore.Subspace([]byte{byte(255), byte(255)}) expected2 = [][]byte{ @@ -147,7 +158,7 @@ func TestIAVLSubspace(t *testing.T) { assert.EqualValues(t, value, []byte("test4")) i += 1 } - assert.Equal(t, i, len(expected)) + assert.Equal(t, len(expected), i) } func TestIAVLStoreQuery(t *testing.T) { From 3f1362f838c22fcb71ecfcb7217f27992e2b6c63 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 1 Apr 2018 00:02:29 +0200 Subject: [PATCH 3/9] why u no work --- store/iavlstore_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 6e276c3d2..02b0d58bb 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -94,6 +94,39 @@ func TestIAVLIterator(t *testing.T) { } assert.Equal(t, len(expected), i) + iter = iavlStore.Iterator(nil, []byte("golang")) + expected = []string{"aloha"} + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, treeData[expectedKey]) + i += 1 + } + assert.Equal(t, len(expected), i) + + iter = iavlStore.Iterator(nil, []byte("shalom")) + expected = []string{"aloha", "hello"} + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, treeData[expectedKey]) + i += 1 + } + assert.Equal(t, len(expected), i) + + iter = iavlStore.Iterator(nil, nil) + expected = []string{"aloha", "hello"} + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, treeData[expectedKey]) + i += 1 + } + assert.Equal(t, len(expected), i) + iter = iavlStore.Iterator([]byte("golang"), nil) expected = []string{"hello"} for i = 0; iter.Valid(); iter.Next() { From d98ea3764f2d654570c9310a68bbb1c39655e1c8 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 1 Apr 2018 00:26:00 +0200 Subject: [PATCH 4/9] it works --- store/iavlstore.go | 5 +++-- store/iavlstore_test.go | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/store/iavlstore.go b/store/iavlstore.go index a1a48722c..330358d8d 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -138,7 +138,6 @@ func (st *iavlStore) Subspace(prefix []byte) Iterator { } } } - fmt.Printf("%v \n", end) return st.Iterator(prefix, end) } @@ -242,7 +241,6 @@ func newIAVLIterator(tree *iavl.Tree, start, end []byte, ascending bool) *iavlIt quitCh: make(chan struct{}), initCh: make(chan struct{}), } - fmt.Printf("%v %v \n", iter.start, iter.end) go iter.iterateRoutine() go iter.initRoutine() return iter @@ -356,6 +354,9 @@ func (iter *iavlIterator) assertIsValid() { //---------------------------------------- func cp(bz []byte) (ret []byte) { + if bz == nil { + return nil + } ret = make([]byte, len(bz)) copy(ret, bz) return ret diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 02b0d58bb..406d26926 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -150,6 +150,10 @@ func TestIAVLSubspace(t *testing.T) { iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4")) iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4")) iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4")) + iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4")) + iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4")) + iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4")) + i := 0 iter := iavlStore.Subspace([]byte("test")) From c441ccdf01efdbbb11ea5116b58dc76672558e06 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 1 Apr 2018 18:00:28 +0200 Subject: [PATCH 5/9] added more test --- store/cachekvstore.go | 11 ++++++++ store/dbstoreadapter.go | 8 ++++++ store/iavlstore.go | 34 ++++++++---------------- store/iavlstore_test.go | 59 +++++++++++++++++++++++++++++++++++++++++ types/store.go | 33 +++++++++++++++++++++++ 5 files changed, 122 insertions(+), 23 deletions(-) diff --git a/store/cachekvstore.go b/store/cachekvstore.go index e075e7847..f6b0e7a5e 100644 --- a/store/cachekvstore.go +++ b/store/cachekvstore.go @@ -5,6 +5,7 @@ import ( "sort" "sync" + sdk "github.com/cosmos/cosmos-sdk/types" cmn "github.com/tendermint/tmlibs/common" ) @@ -134,6 +135,16 @@ func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator { return ci.iterator(start, end, false) } +// Implements KVStore. +func (ci *cacheKVStore) Subspace(prefix []byte) Iterator { + return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), true) +} + +// Implements KVStore. +func (ci *cacheKVStore) ReverseSubspace(prefix []byte) Iterator { + return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), false) +} + func (ci *cacheKVStore) iterator(start, end []byte, ascending bool) Iterator { var parent, cache Iterator if ascending { diff --git a/store/dbstoreadapter.go b/store/dbstoreadapter.go index a1b580fd4..39309aaf2 100644 --- a/store/dbstoreadapter.go +++ b/store/dbstoreadapter.go @@ -19,5 +19,13 @@ func (dsa dbStoreAdapter) CacheWrap() CacheWrap { return NewCacheKVStore(dsa) } +func (dsa dbStoreAdapter) Subspace(prefix []byte) Iterator { + return dsa.Iterator(prefix, sdk.PrefixEndBytes(prefix)) +} + +func (dsa dbStoreAdapter) ReverseSubspace(prefix []byte) Iterator { + return dsa.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix)) +} + // dbm.DB implements KVStore so we can CacheKVStore it. var _ KVStore = dbStoreAdapter{dbm.DB(nil)} diff --git a/store/iavlstore.go b/store/iavlstore.go index 330358d8d..b27aacb2b 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -119,33 +119,21 @@ func (st *iavlStore) Iterator(start, end []byte) Iterator { return newIAVLIterator(st.tree.Tree(), start, end, true) } -func (st *iavlStore) Subspace(prefix []byte) Iterator { - end := make([]byte, len(prefix)) - copy(end, prefix) - finished := false - i := 1 - - for !finished { - if end[len(end)-i] != byte(255) { - end[len(end)-i]++ - finished = true - } else { - end[len(end)-i]++ - i++ - if i > len(end) { - end = nil - finished = true - } - } - } - return st.Iterator(prefix, end) -} - -// Implements IterKVStore. +// Implements KVStore. func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { return newIAVLIterator(st.tree.Tree(), start, end, false) } +// Implements KVStore. +func (st *iavlStore) Subspace(prefix []byte) Iterator { + return st.Iterator(prefix, sdk.PrefixEndBytes(prefix)) +} + +// Implements KVStore. +func (st *iavlStore) ReverseSubspace(prefix []byte) Iterator { + return st.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix)) +} + // Query implements ABCI interface, allows queries // // by default we will return from (latest height -1), diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 406d26926..2c4c0ea00 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -198,6 +198,65 @@ func TestIAVLSubspace(t *testing.T) { assert.Equal(t, len(expected), i) } +func TestIAVLReverseSubspace(t *testing.T) { + db := dbm.NewMemDB() + tree, _ := newTree(t, db) + iavlStore := newIAVLStore(tree, numHistory) + + iavlStore.Set([]byte("test1"), []byte("test1")) + iavlStore.Set([]byte("test2"), []byte("test2")) + iavlStore.Set([]byte("test3"), []byte("test3")) + iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4")) + iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4")) + iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4")) + iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4")) + iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4")) + iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4")) + + i := 0 + + iter := iavlStore.ReverseSubspace([]byte("test")) + expected := []string{"test3", "test2", "test1"} + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, expectedKey) + i += 1 + } + assert.Equal(t, len(expected), i) + + iter = iavlStore.ReverseSubspace([]byte{byte(55), byte(255), byte(255)}) + expected2 := [][]byte{ + []byte{byte(55), byte(255), byte(255), byte(255)}, + []byte{byte(55), byte(255), byte(255), byte(1)}, + []byte{byte(55), byte(255), byte(255), byte(0)}, + } + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected2[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, []byte("test4")) + i += 1 + } + assert.Equal(t, len(expected), i) + + iter = iavlStore.ReverseSubspace([]byte{byte(255), byte(255)}) + expected2 = [][]byte{ + []byte{byte(255), byte(255), byte(255)}, + []byte{byte(255), byte(255), byte(1)}, + []byte{byte(255), byte(255), byte(0)}, + } + for i = 0; iter.Valid(); iter.Next() { + expectedKey := expected2[i] + key, value := iter.Key(), iter.Value() + assert.EqualValues(t, key, expectedKey) + assert.EqualValues(t, value, []byte("test4")) + i += 1 + } + assert.Equal(t, len(expected), i) +} + func TestIAVLStoreQuery(t *testing.T) { db := dbm.NewMemDB() tree := iavl.NewVersionedTree(db, cacheSize) diff --git a/types/store.go b/types/store.go index ef2e9154b..9034ea6f3 100644 --- a/types/store.go +++ b/types/store.go @@ -111,6 +111,14 @@ type KVStore interface { // CONTRACT: No writes may happen within a domain while an iterator exists over it. ReverseIterator(start, end []byte) Iterator + // Iterator over all the keys with a certain prefix in ascending order. + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + Subspace(prefix []byte) Iterator + + // Iterator over all the keys with a certain prefix in descending order. + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + ReverseSubspace(prefix []byte) Iterator + // TODO Not yet implemented. // CreateSubKVStore(key *storeKey) (KVStore, error) @@ -222,3 +230,28 @@ func (key *KVStoreKey) Name() string { func (key *KVStoreKey) String() string { return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) } + +// TODO: Move to TmLibs +func PrefixEndBytes(prefix []byte) []byte { + if prefix == nil { + return nil + } + + end := make([]byte, len(prefix)) + copy(end, prefix) + finished := false + + for !finished { + if end[len(end)-1] != byte(255) { + end[len(end)-1]++ + finished = true + } else { + end = end[:len(end)-1] + if len(end) == 0 { + end = nil + finished = true + } + } + } + return end +} From f10983ba06e0ed5aded8d473b6c42100c91b1371 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Thu, 5 Apr 2018 21:54:30 +0200 Subject: [PATCH 6/9] address review --- store/cachekvstore.go | 4 ++-- store/dbstoreadapter.go | 4 ++-- store/iavlstore.go | 4 ++-- store/iavlstore_test.go | 19 ++++++++++--------- types/store.go | 4 ++-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/store/cachekvstore.go b/store/cachekvstore.go index f6b0e7a5e..6c5cc9542 100644 --- a/store/cachekvstore.go +++ b/store/cachekvstore.go @@ -136,12 +136,12 @@ func (ci *cacheKVStore) ReverseIterator(start, end []byte) Iterator { } // Implements KVStore. -func (ci *cacheKVStore) Subspace(prefix []byte) Iterator { +func (ci *cacheKVStore) SubspaceIterator(prefix []byte) Iterator { return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), true) } // Implements KVStore. -func (ci *cacheKVStore) ReverseSubspace(prefix []byte) Iterator { +func (ci *cacheKVStore) ReverseSubspaceIterator(prefix []byte) Iterator { return ci.iterator(prefix, sdk.PrefixEndBytes(prefix), false) } diff --git a/store/dbstoreadapter.go b/store/dbstoreadapter.go index 39309aaf2..10c175a99 100644 --- a/store/dbstoreadapter.go +++ b/store/dbstoreadapter.go @@ -19,11 +19,11 @@ func (dsa dbStoreAdapter) CacheWrap() CacheWrap { return NewCacheKVStore(dsa) } -func (dsa dbStoreAdapter) Subspace(prefix []byte) Iterator { +func (dsa dbStoreAdapter) SubspaceIterator(prefix []byte) Iterator { return dsa.Iterator(prefix, sdk.PrefixEndBytes(prefix)) } -func (dsa dbStoreAdapter) ReverseSubspace(prefix []byte) Iterator { +func (dsa dbStoreAdapter) ReverseSubspaceIterator(prefix []byte) Iterator { return dsa.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix)) } diff --git a/store/iavlstore.go b/store/iavlstore.go index b27aacb2b..e0b93a1ab 100644 --- a/store/iavlstore.go +++ b/store/iavlstore.go @@ -125,12 +125,12 @@ func (st *iavlStore) ReverseIterator(start, end []byte) Iterator { } // Implements KVStore. -func (st *iavlStore) Subspace(prefix []byte) Iterator { +func (st *iavlStore) SubspaceIterator(prefix []byte) Iterator { return st.Iterator(prefix, sdk.PrefixEndBytes(prefix)) } // Implements KVStore. -func (st *iavlStore) ReverseSubspace(prefix []byte) Iterator { +func (st *iavlStore) ReverseSubspaceIterator(prefix []byte) Iterator { return st.ReverseIterator(prefix, sdk.PrefixEndBytes(prefix)) } diff --git a/store/iavlstore_test.go b/store/iavlstore_test.go index 2c4c0ea00..824617c26 100644 --- a/store/iavlstore_test.go +++ b/store/iavlstore_test.go @@ -73,7 +73,8 @@ func TestIAVLIterator(t *testing.T) { iavlStore := newIAVLStore(tree, numHistory) iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz")) expected := []string{"aloha", "hello"} - i := 0 + var i int + for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] key, value := iter.Key(), iter.Value() @@ -139,7 +140,7 @@ func TestIAVLIterator(t *testing.T) { assert.Equal(t, len(expected), i) } -func TestIAVLSubspace(t *testing.T) { +func TestIAVLSubspaceIterator(t *testing.T) { db := dbm.NewMemDB() tree, _ := newTree(t, db) iavlStore := newIAVLStore(tree, numHistory) @@ -156,7 +157,7 @@ func TestIAVLSubspace(t *testing.T) { i := 0 - iter := iavlStore.Subspace([]byte("test")) + iter := iavlStore.SubspaceIterator([]byte("test")) expected := []string{"test1", "test2", "test3"} for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] @@ -167,7 +168,7 @@ func TestIAVLSubspace(t *testing.T) { } assert.Equal(t, len(expected), i) - iter = iavlStore.Subspace([]byte{byte(55), byte(255), byte(255)}) + iter = iavlStore.SubspaceIterator([]byte{byte(55), byte(255), byte(255)}) expected2 := [][]byte{ []byte{byte(55), byte(255), byte(255), byte(0)}, []byte{byte(55), byte(255), byte(255), byte(1)}, @@ -182,7 +183,7 @@ func TestIAVLSubspace(t *testing.T) { } assert.Equal(t, len(expected), i) - iter = iavlStore.Subspace([]byte{byte(255), byte(255)}) + iter = iavlStore.SubspaceIterator([]byte{byte(255), byte(255)}) expected2 = [][]byte{ []byte{byte(255), byte(255), byte(0)}, []byte{byte(255), byte(255), byte(1)}, @@ -198,7 +199,7 @@ func TestIAVLSubspace(t *testing.T) { assert.Equal(t, len(expected), i) } -func TestIAVLReverseSubspace(t *testing.T) { +func TestIAVLReverseSubspaceIterator(t *testing.T) { db := dbm.NewMemDB() tree, _ := newTree(t, db) iavlStore := newIAVLStore(tree, numHistory) @@ -215,7 +216,7 @@ func TestIAVLReverseSubspace(t *testing.T) { i := 0 - iter := iavlStore.ReverseSubspace([]byte("test")) + iter := iavlStore.ReverseSubspaceIterator([]byte("test")) expected := []string{"test3", "test2", "test1"} for i = 0; iter.Valid(); iter.Next() { expectedKey := expected[i] @@ -226,7 +227,7 @@ func TestIAVLReverseSubspace(t *testing.T) { } assert.Equal(t, len(expected), i) - iter = iavlStore.ReverseSubspace([]byte{byte(55), byte(255), byte(255)}) + iter = iavlStore.ReverseSubspaceIterator([]byte{byte(55), byte(255), byte(255)}) expected2 := [][]byte{ []byte{byte(55), byte(255), byte(255), byte(255)}, []byte{byte(55), byte(255), byte(255), byte(1)}, @@ -241,7 +242,7 @@ func TestIAVLReverseSubspace(t *testing.T) { } assert.Equal(t, len(expected), i) - iter = iavlStore.ReverseSubspace([]byte{byte(255), byte(255)}) + iter = iavlStore.ReverseSubspaceIterator([]byte{byte(255), byte(255)}) expected2 = [][]byte{ []byte{byte(255), byte(255), byte(255)}, []byte{byte(255), byte(255), byte(1)}, diff --git a/types/store.go b/types/store.go index 9034ea6f3..9034e7930 100644 --- a/types/store.go +++ b/types/store.go @@ -113,11 +113,11 @@ type KVStore interface { // Iterator over all the keys with a certain prefix in ascending order. // CONTRACT: No writes may happen within a domain while an iterator exists over it. - Subspace(prefix []byte) Iterator + SubspaceIterator(prefix []byte) Iterator // Iterator over all the keys with a certain prefix in descending order. // CONTRACT: No writes may happen within a domain while an iterator exists over it. - ReverseSubspace(prefix []byte) Iterator + ReverseSubspaceIterator(prefix []byte) Iterator // TODO Not yet implemented. // CreateSubKVStore(key *storeKey) (KVStore, error) From 4bcfcd5cc8972b723e006e7ebc8c13cb6f4373fe Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 6 Apr 2018 11:29:25 +0200 Subject: [PATCH 7/9] added comments and got rid of fixed variable --- Gopkg.lock | 2 +- types/store.go | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 50a17e1fb..2de9e117e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -458,6 +458,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "ed1f3f7f1728cd02945f90ca780e9bdc982573a36a5cc8d7e9f19fb40ba2ca19" + inputs-digest = "67298e1f8058b85f082dbd32123f2779b11bda282616e595141dba41a8675c39" solver-name = "gps-cdcl" solver-version = 1 diff --git a/types/store.go b/types/store.go index 9034e7930..7b73570ca 100644 --- a/types/store.go +++ b/types/store.go @@ -231,7 +231,9 @@ func (key *KVStoreKey) String() string { return fmt.Sprintf("KVStoreKey{%p, %s}", key, key.name) } -// TODO: Move to TmLibs +// PrefixEndBytes returns the []byte that would end a +// range query for all []byte with a certain prefix +// Deals with last byte of prefix being FF without overflowing func PrefixEndBytes(prefix []byte) []byte { if prefix == nil { return nil @@ -239,17 +241,16 @@ func PrefixEndBytes(prefix []byte) []byte { end := make([]byte, len(prefix)) copy(end, prefix) - finished := false - for !finished { + for { if end[len(end)-1] != byte(255) { end[len(end)-1]++ - finished = true + break } else { end = end[:len(end)-1] if len(end) == 0 { end = nil - finished = true + break } } } From 9b40cf184f6b05594e7e5064d88afc18a7d3e525 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 8 Apr 2018 00:58:03 +0200 Subject: [PATCH 8/9] added PrefixBytesTest --- types/store_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 types/store_test.go diff --git a/types/store_test.go b/types/store_test.go new file mode 100644 index 000000000..2fd944185 --- /dev/null +++ b/types/store_test.go @@ -0,0 +1,28 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPrefixEndBytes(t *testing.T) { + assert := assert.New(t) + + var testCases = []struct { + prefix []byte + expected []byte + }{ + {[]byte{byte(55), byte(255), byte(255), byte(0)}, []byte{byte(55), byte(255), byte(255), byte(1)}}, + {[]byte{byte(55), byte(255), byte(255), byte(15)}, []byte{byte(55), byte(255), byte(255), byte(16)}}, + {[]byte{byte(55), byte(200), byte(255)}, []byte{byte(55), byte(201)}}, + {[]byte{byte(55), byte(255), byte(255)}, []byte{byte(56)}}, + {[]byte{byte(255), byte(255), byte(255)}, nil}, + {nil, nil}, + } + + for _, test := range testCases { + end := PrefixEndBytes(test.prefix) + assert.Equal(test.expected, end) + } +} From 69448f90e5f796146ce343241431bc5b96015e17 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Tue, 10 Apr 2018 01:32:04 +0200 Subject: [PATCH 9/9] added just FF byte --- types/store_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/store_test.go b/types/store_test.go index 2fd944185..43dd1f5d3 100644 --- a/types/store_test.go +++ b/types/store_test.go @@ -18,6 +18,7 @@ func TestPrefixEndBytes(t *testing.T) { {[]byte{byte(55), byte(200), byte(255)}, []byte{byte(55), byte(201)}}, {[]byte{byte(55), byte(255), byte(255)}, []byte{byte(56)}}, {[]byte{byte(255), byte(255), byte(255)}, nil}, + {[]byte{byte(255)}, nil}, {nil, nil}, }