From 4cc569a9c42bcd78f9796c0dd9b5159b4827bf08 Mon Sep 17 00:00:00 2001 From: mars Date: Tue, 2 Jul 2019 15:17:31 +0800 Subject: [PATCH] fix paging --- database/leveldb/db.go | 2 +- database/leveldb/db_test.go | 53 ++++++++++++++++++++++++++++++++++++----- database/leveldb/go_level_db.go | 34 +++++++++++++++++++------- database/leveldb/mem_db.go | 10 ++++---- wallet/indexer.go | 4 +++- wallet/unconfirmed.go | 7 ++++++ 6 files changed, 89 insertions(+), 21 deletions(-) diff --git a/database/leveldb/db.go b/database/leveldb/db.go index 39f0772f..80eb08d0 100644 --- a/database/leveldb/db.go +++ b/database/leveldb/db.go @@ -12,7 +12,7 @@ type DB interface { NewBatch() Batch Iterator() Iterator IteratorPrefix([]byte) Iterator - IteratorPrefixWithStart(Prefix, start []byte) Iterator + IteratorPrefixWithStart(Prefix, start []byte, isReverse bool) Iterator // For debugging Print() diff --git a/database/leveldb/db_test.go b/database/leveldb/db_test.go index ccd37ed9..5f1da045 100644 --- a/database/leveldb/db_test.go +++ b/database/leveldb/db_test.go @@ -22,7 +22,7 @@ func TestDBIteratorSingleKey(t *testing.T) { defer os.RemoveAll(dir) db.Set([]byte("1"), []byte("value_1")) - itr := db.IteratorPrefixWithStart(nil, nil) + itr := db.IteratorPrefixWithStart(nil, nil, false) require.Equal(t, []byte(""), itr.Key()) require.Equal(t, true, itr.Next()) require.Equal(t, []byte("1"), itr.Key()) @@ -39,12 +39,12 @@ func TestDBIteratorTwoKeys(t *testing.T) { db.SetSync([]byte("1"), []byte("value_1")) db.SetSync([]byte("2"), []byte("value_1")) - itr := db.IteratorPrefixWithStart(nil, []byte("1")) + itr := db.IteratorPrefixWithStart(nil, []byte("1"), false) require.Equal(t, []byte("1"), itr.Key()) require.Equal(t, true, itr.Next()) - itr = db.IteratorPrefixWithStart(nil, []byte("2")) + itr = db.IteratorPrefixWithStart(nil, []byte("2"), false) require.Equal(t, false, itr.Next()) }) @@ -69,7 +69,7 @@ func TestDBIterator(t *testing.T) { db.SetSync([]byte("aaa22"), []byte("value_2")) db.SetSync([]byte("bbb22"), []byte("value_3")) - itr := db.IteratorPrefixWithStart([]byte("aaa"), []byte("aaa1")) + itr := db.IteratorPrefixWithStart([]byte("aaa"), []byte("aaa1"), false) defer itr.Release() require.Equal(t, true, itr.Next()) @@ -77,7 +77,7 @@ func TestDBIterator(t *testing.T) { require.Equal(t, false, itr.Next()) - itr = db.IteratorPrefixWithStart([]byte("aaa"), nil) + itr = db.IteratorPrefixWithStart([]byte("aaa"), nil, false) require.Equal(t, true, itr.Next()) require.Equal(t, []byte("aaa1"), itr.Key()) @@ -87,6 +87,47 @@ func TestDBIterator(t *testing.T) { require.Equal(t, false, itr.Next()) - itr = db.IteratorPrefixWithStart([]byte("bbb"), []byte("aaa1")) + itr = db.IteratorPrefixWithStart([]byte("bbb"), []byte("aaa1"), false) + require.Equal(t, false, itr.Next()) +} + +func TestDBIteratorReverse(t *testing.T) { + dirname, err := ioutil.TempDir("", "db_common_test") + require.Nil(t, err) + + db, err := NewGoLevelDB("testdb", dirname) + if err != nil { + t.Fatal(err) + } + + defer func() { + db.Close() + os.RemoveAll(dirname) + }() + + db.SetSync([]byte("aaa1"), []byte("value_1")) + db.SetSync([]byte("aaa22"), []byte("value_2")) + db.SetSync([]byte("bbb22"), []byte("value_3")) + + itr := db.IteratorPrefixWithStart([]byte("aaa"), []byte("aaa22"), true) + defer itr.Release() + + require.Equal(t, true, itr.Next()) + require.Equal(t, []byte("aaa1"), itr.Key()) + + require.Equal(t, false, itr.Next()) + + itr = db.IteratorPrefixWithStart([]byte("aaa"), nil, true) + + require.Equal(t, []byte("aaa22"), itr.Key()) + + require.Equal(t, true, itr.Next()) + require.Equal(t, []byte("aaa1"), itr.Key()) + + require.Equal(t, false, itr.Next()) + + require.Equal(t, false, itr.Next()) + + itr = db.IteratorPrefixWithStart([]byte("bbb"), []byte("aaa1"), true) require.Equal(t, false, itr.Next()) } diff --git a/database/leveldb/go_level_db.go b/database/leveldb/go_level_db.go index 7a2b8927..a0eac36f 100644 --- a/database/leveldb/go_level_db.go +++ b/database/leveldb/go_level_db.go @@ -118,18 +118,31 @@ func (db *GoLevelDB) Stats() map[string]string { } type goLevelDBIterator struct { - source iterator.Iterator - start []byte + source iterator.Iterator + start []byte + isReverse bool } -func newGoLevelDBIterator(source iterator.Iterator, start []byte) *goLevelDBIterator { - if start != nil { - source.Seek(start) +func newGoLevelDBIterator(source iterator.Iterator, start []byte, isReverse bool) *goLevelDBIterator { + if isReverse { + if start == nil { + source.Last() + } else { + valid := source.Seek(start) + if !valid { + source.Last() + } + } + } else { + if start != nil { + source.Seek(start) + } } return &goLevelDBIterator{ - source: source, - start: start, + source: source, + start: start, + isReverse: isReverse, } } @@ -161,6 +174,9 @@ func (it *goLevelDBIterator) Error() error { func (it *goLevelDBIterator) Next() bool { it.assertNoError() + if it.isReverse { + return it.source.Prev() + } return it.source.Next() } @@ -182,9 +198,9 @@ func (db *GoLevelDB) IteratorPrefix(prefix []byte) Iterator { return &goLevelDBIterator{source: db.db.NewIterator(util.BytesPrefix(prefix), nil)} } -func (db *GoLevelDB) IteratorPrefixWithStart(Prefix, start []byte) Iterator { +func (db *GoLevelDB) IteratorPrefixWithStart(Prefix, start []byte, isReverse bool) Iterator { itr := db.db.NewIterator(util.BytesPrefix(Prefix), nil) - return newGoLevelDBIterator(itr, start) + return newGoLevelDBIterator(itr, start, isReverse) } func (db *GoLevelDB) NewBatch() Batch { diff --git a/database/leveldb/mem_db.go b/database/leveldb/mem_db.go index 63e2b76c..f7b9a602 100644 --- a/database/leveldb/mem_db.go +++ b/database/leveldb/mem_db.go @@ -9,9 +9,11 @@ import ( ) func init() { - registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) { - return NewMemDB(), nil - }, false) + /* + registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) { + return NewMemDB(), nil + }, false) + */ } type MemDB struct { @@ -163,7 +165,7 @@ func (db *MemDB) IteratorPrefix(prefix []byte) Iterator { return it } -func (db *MemDB) IteratorPrefixWithStart(Prefix, start []byte) Iterator { +func (db *MemDB) IteratorPrefixWithStart(Prefix, start []byte, isReverse bool) Iterator { db.mtx.Lock() defer db.mtx.Unlock() diff --git a/wallet/indexer.go b/wallet/indexer.go index 46017791..4bff9c94 100644 --- a/wallet/indexer.go +++ b/wallet/indexer.go @@ -310,7 +310,7 @@ func (w *Wallet) GetTransactions(accountID string, StartTxID string, count uint, preFix = UnconfirmedTxPrefix } - itr := w.DB.IteratorPrefixWithStart([]byte(preFix), startKey) + itr := w.DB.IteratorPrefixWithStart([]byte(preFix), startKey, true) defer itr.Release() for txNum := count; itr.Next() && txNum > 0; txNum-- { @@ -327,6 +327,8 @@ func (w *Wallet) GetTransactions(accountID string, StartTxID string, count uint, if unconfirmed { sort.Sort(SortByTimestamp(annotatedTxs)) + } else { + sort.Sort(SortByHeight(annotatedTxs)) } return annotatedTxs, nil diff --git a/wallet/unconfirmed.go b/wallet/unconfirmed.go index 4eec6a2a..843c289c 100644 --- a/wallet/unconfirmed.go +++ b/wallet/unconfirmed.go @@ -33,6 +33,13 @@ func (a SortByTimestamp) Len() int { return len(a) } func (a SortByTimestamp) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a SortByTimestamp) Less(i, j int) bool { return a[i].Timestamp > a[j].Timestamp } +// SortByHeight implements sort.Interface for AnnotatedTx slices +type SortByHeight []*query.AnnotatedTx + +func (a SortByHeight) Len() int { return len(a) } +func (a SortByHeight) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a SortByHeight) Less(i, j int) bool { return a[i].BlockHeight > a[j].BlockHeight } + // AddUnconfirmedTx handle wallet status update when tx add into txpool func (w *Wallet) AddUnconfirmedTx(txD *protocol.TxDesc) { if err := w.saveUnconfirmedTx(txD.Tx); err != nil { -- 2.11.0