Golang implemented sidechain for Bytom
修订版 | 4cc569a9c42bcd78f9796c0dd9b5159b4827bf08 (tree) |
---|---|
时间 | 2019-07-02 16:17:31 |
作者 | mars <mars@byto...> |
Commiter | mars |
fix paging
@@ -12,7 +12,7 @@ type DB interface { | ||
12 | 12 | NewBatch() Batch |
13 | 13 | Iterator() Iterator |
14 | 14 | IteratorPrefix([]byte) Iterator |
15 | - IteratorPrefixWithStart(Prefix, start []byte) Iterator | |
15 | + IteratorPrefixWithStart(Prefix, start []byte, isReverse bool) Iterator | |
16 | 16 | |
17 | 17 | // For debugging |
18 | 18 | Print() |
@@ -22,7 +22,7 @@ func TestDBIteratorSingleKey(t *testing.T) { | ||
22 | 22 | defer os.RemoveAll(dir) |
23 | 23 | |
24 | 24 | db.Set([]byte("1"), []byte("value_1")) |
25 | - itr := db.IteratorPrefixWithStart(nil, nil) | |
25 | + itr := db.IteratorPrefixWithStart(nil, nil, false) | |
26 | 26 | require.Equal(t, []byte(""), itr.Key()) |
27 | 27 | require.Equal(t, true, itr.Next()) |
28 | 28 | require.Equal(t, []byte("1"), itr.Key()) |
@@ -39,12 +39,12 @@ func TestDBIteratorTwoKeys(t *testing.T) { | ||
39 | 39 | db.SetSync([]byte("1"), []byte("value_1")) |
40 | 40 | db.SetSync([]byte("2"), []byte("value_1")) |
41 | 41 | |
42 | - itr := db.IteratorPrefixWithStart(nil, []byte("1")) | |
42 | + itr := db.IteratorPrefixWithStart(nil, []byte("1"), false) | |
43 | 43 | |
44 | 44 | require.Equal(t, []byte("1"), itr.Key()) |
45 | 45 | |
46 | 46 | require.Equal(t, true, itr.Next()) |
47 | - itr = db.IteratorPrefixWithStart(nil, []byte("2")) | |
47 | + itr = db.IteratorPrefixWithStart(nil, []byte("2"), false) | |
48 | 48 | |
49 | 49 | require.Equal(t, false, itr.Next()) |
50 | 50 | }) |
@@ -69,7 +69,7 @@ func TestDBIterator(t *testing.T) { | ||
69 | 69 | db.SetSync([]byte("aaa22"), []byte("value_2")) |
70 | 70 | db.SetSync([]byte("bbb22"), []byte("value_3")) |
71 | 71 | |
72 | - itr := db.IteratorPrefixWithStart([]byte("aaa"), []byte("aaa1")) | |
72 | + itr := db.IteratorPrefixWithStart([]byte("aaa"), []byte("aaa1"), false) | |
73 | 73 | defer itr.Release() |
74 | 74 | |
75 | 75 | require.Equal(t, true, itr.Next()) |
@@ -77,7 +77,7 @@ func TestDBIterator(t *testing.T) { | ||
77 | 77 | |
78 | 78 | require.Equal(t, false, itr.Next()) |
79 | 79 | |
80 | - itr = db.IteratorPrefixWithStart([]byte("aaa"), nil) | |
80 | + itr = db.IteratorPrefixWithStart([]byte("aaa"), nil, false) | |
81 | 81 | |
82 | 82 | require.Equal(t, true, itr.Next()) |
83 | 83 | require.Equal(t, []byte("aaa1"), itr.Key()) |
@@ -87,6 +87,47 @@ func TestDBIterator(t *testing.T) { | ||
87 | 87 | |
88 | 88 | require.Equal(t, false, itr.Next()) |
89 | 89 | |
90 | - itr = db.IteratorPrefixWithStart([]byte("bbb"), []byte("aaa1")) | |
90 | + itr = db.IteratorPrefixWithStart([]byte("bbb"), []byte("aaa1"), false) | |
91 | + require.Equal(t, false, itr.Next()) | |
92 | +} | |
93 | + | |
94 | +func TestDBIteratorReverse(t *testing.T) { | |
95 | + dirname, err := ioutil.TempDir("", "db_common_test") | |
96 | + require.Nil(t, err) | |
97 | + | |
98 | + db, err := NewGoLevelDB("testdb", dirname) | |
99 | + if err != nil { | |
100 | + t.Fatal(err) | |
101 | + } | |
102 | + | |
103 | + defer func() { | |
104 | + db.Close() | |
105 | + os.RemoveAll(dirname) | |
106 | + }() | |
107 | + | |
108 | + db.SetSync([]byte("aaa1"), []byte("value_1")) | |
109 | + db.SetSync([]byte("aaa22"), []byte("value_2")) | |
110 | + db.SetSync([]byte("bbb22"), []byte("value_3")) | |
111 | + | |
112 | + itr := db.IteratorPrefixWithStart([]byte("aaa"), []byte("aaa22"), true) | |
113 | + defer itr.Release() | |
114 | + | |
115 | + require.Equal(t, true, itr.Next()) | |
116 | + require.Equal(t, []byte("aaa1"), itr.Key()) | |
117 | + | |
118 | + require.Equal(t, false, itr.Next()) | |
119 | + | |
120 | + itr = db.IteratorPrefixWithStart([]byte("aaa"), nil, true) | |
121 | + | |
122 | + require.Equal(t, []byte("aaa22"), itr.Key()) | |
123 | + | |
124 | + require.Equal(t, true, itr.Next()) | |
125 | + require.Equal(t, []byte("aaa1"), itr.Key()) | |
126 | + | |
127 | + require.Equal(t, false, itr.Next()) | |
128 | + | |
129 | + require.Equal(t, false, itr.Next()) | |
130 | + | |
131 | + itr = db.IteratorPrefixWithStart([]byte("bbb"), []byte("aaa1"), true) | |
91 | 132 | require.Equal(t, false, itr.Next()) |
92 | 133 | } |
@@ -118,18 +118,31 @@ func (db *GoLevelDB) Stats() map[string]string { | ||
118 | 118 | } |
119 | 119 | |
120 | 120 | type goLevelDBIterator struct { |
121 | - source iterator.Iterator | |
122 | - start []byte | |
121 | + source iterator.Iterator | |
122 | + start []byte | |
123 | + isReverse bool | |
123 | 124 | } |
124 | 125 | |
125 | -func newGoLevelDBIterator(source iterator.Iterator, start []byte) *goLevelDBIterator { | |
126 | - if start != nil { | |
127 | - source.Seek(start) | |
126 | +func newGoLevelDBIterator(source iterator.Iterator, start []byte, isReverse bool) *goLevelDBIterator { | |
127 | + if isReverse { | |
128 | + if start == nil { | |
129 | + source.Last() | |
130 | + } else { | |
131 | + valid := source.Seek(start) | |
132 | + if !valid { | |
133 | + source.Last() | |
134 | + } | |
135 | + } | |
136 | + } else { | |
137 | + if start != nil { | |
138 | + source.Seek(start) | |
139 | + } | |
128 | 140 | } |
129 | 141 | |
130 | 142 | return &goLevelDBIterator{ |
131 | - source: source, | |
132 | - start: start, | |
143 | + source: source, | |
144 | + start: start, | |
145 | + isReverse: isReverse, | |
133 | 146 | } |
134 | 147 | } |
135 | 148 |
@@ -161,6 +174,9 @@ func (it *goLevelDBIterator) Error() error { | ||
161 | 174 | |
162 | 175 | func (it *goLevelDBIterator) Next() bool { |
163 | 176 | it.assertNoError() |
177 | + if it.isReverse { | |
178 | + return it.source.Prev() | |
179 | + } | |
164 | 180 | return it.source.Next() |
165 | 181 | } |
166 | 182 |
@@ -182,9 +198,9 @@ func (db *GoLevelDB) IteratorPrefix(prefix []byte) Iterator { | ||
182 | 198 | return &goLevelDBIterator{source: db.db.NewIterator(util.BytesPrefix(prefix), nil)} |
183 | 199 | } |
184 | 200 | |
185 | -func (db *GoLevelDB) IteratorPrefixWithStart(Prefix, start []byte) Iterator { | |
201 | +func (db *GoLevelDB) IteratorPrefixWithStart(Prefix, start []byte, isReverse bool) Iterator { | |
186 | 202 | itr := db.db.NewIterator(util.BytesPrefix(Prefix), nil) |
187 | - return newGoLevelDBIterator(itr, start) | |
203 | + return newGoLevelDBIterator(itr, start, isReverse) | |
188 | 204 | } |
189 | 205 | |
190 | 206 | func (db *GoLevelDB) NewBatch() Batch { |
@@ -9,9 +9,11 @@ import ( | ||
9 | 9 | ) |
10 | 10 | |
11 | 11 | func init() { |
12 | - registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) { | |
13 | - return NewMemDB(), nil | |
14 | - }, false) | |
12 | + /* | |
13 | + registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) { | |
14 | + return NewMemDB(), nil | |
15 | + }, false) | |
16 | + */ | |
15 | 17 | } |
16 | 18 | |
17 | 19 | type MemDB struct { |
@@ -163,7 +165,7 @@ func (db *MemDB) IteratorPrefix(prefix []byte) Iterator { | ||
163 | 165 | return it |
164 | 166 | } |
165 | 167 | |
166 | -func (db *MemDB) IteratorPrefixWithStart(Prefix, start []byte) Iterator { | |
168 | +func (db *MemDB) IteratorPrefixWithStart(Prefix, start []byte, isReverse bool) Iterator { | |
167 | 169 | db.mtx.Lock() |
168 | 170 | defer db.mtx.Unlock() |
169 | 171 |
@@ -310,7 +310,7 @@ func (w *Wallet) GetTransactions(accountID string, StartTxID string, count uint, | ||
310 | 310 | preFix = UnconfirmedTxPrefix |
311 | 311 | } |
312 | 312 | |
313 | - itr := w.DB.IteratorPrefixWithStart([]byte(preFix), startKey) | |
313 | + itr := w.DB.IteratorPrefixWithStart([]byte(preFix), startKey, true) | |
314 | 314 | defer itr.Release() |
315 | 315 | |
316 | 316 | for txNum := count; itr.Next() && txNum > 0; txNum-- { |
@@ -327,6 +327,8 @@ func (w *Wallet) GetTransactions(accountID string, StartTxID string, count uint, | ||
327 | 327 | |
328 | 328 | if unconfirmed { |
329 | 329 | sort.Sort(SortByTimestamp(annotatedTxs)) |
330 | + } else { | |
331 | + sort.Sort(SortByHeight(annotatedTxs)) | |
330 | 332 | } |
331 | 333 | |
332 | 334 | return annotatedTxs, nil |
@@ -33,6 +33,13 @@ func (a SortByTimestamp) Len() int { return len(a) } | ||
33 | 33 | func (a SortByTimestamp) Swap(i, j int) { a[i], a[j] = a[j], a[i] } |
34 | 34 | func (a SortByTimestamp) Less(i, j int) bool { return a[i].Timestamp > a[j].Timestamp } |
35 | 35 | |
36 | +// SortByHeight implements sort.Interface for AnnotatedTx slices | |
37 | +type SortByHeight []*query.AnnotatedTx | |
38 | + | |
39 | +func (a SortByHeight) Len() int { return len(a) } | |
40 | +func (a SortByHeight) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | |
41 | +func (a SortByHeight) Less(i, j int) bool { return a[i].BlockHeight > a[j].BlockHeight } | |
42 | + | |
36 | 43 | // AddUnconfirmedTx handle wallet status update when tx add into txpool |
37 | 44 | func (w *Wallet) AddUnconfirmedTx(txD *protocol.TxDesc) { |
38 | 45 | if err := w.saveUnconfirmedTx(txD.Tx); err != nil { |