github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/table/merge_iterator_test.go (about) 1 /* 2 * Copyright 2017 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package table 18 19 import ( 20 "bytes" 21 "fmt" 22 "sort" 23 "testing" 24 25 "github.com/coocood/badger/cache/z" 26 "github.com/coocood/badger/y" 27 "github.com/stretchr/testify/require" 28 ) 29 30 type SimpleIterator struct { 31 keys []y.Key 32 vals [][]byte 33 idx int 34 reversed bool 35 36 latestOffs []int 37 verIdx int 38 } 39 40 var ( 41 closeCount int 42 ) 43 44 func (s *SimpleIterator) Next() { 45 if !s.reversed { 46 s.idx++ 47 s.verIdx = 0 48 } else { 49 s.idx-- 50 s.verIdx = 0 51 } 52 } 53 54 func (s *SimpleIterator) NextVersion() bool { 55 nextEntryOff := len(s.keys) 56 if s.idx+1 < len(s.latestOffs) { 57 nextEntryOff = s.latestOffs[s.idx+1] 58 } 59 if s.entryIdx()+1 < nextEntryOff { 60 s.verIdx++ 61 return true 62 } 63 return false 64 } 65 66 func (s *SimpleIterator) Rewind() { 67 if !s.reversed { 68 s.idx = 0 69 s.verIdx = 0 70 } else { 71 s.idx = len(s.latestOffs) - 1 72 s.verIdx = 0 73 } 74 } 75 76 func (s *SimpleIterator) Seek(key []byte) { 77 s.idx = sort.Search(len(s.latestOffs), func(i int) bool { 78 return bytes.Compare(s.keys[s.latestOffs[i]].UserKey, key) >= 0 79 }) 80 s.verIdx = 0 81 if s.reversed { 82 if !s.Valid() || !bytes.Equal(s.Key().UserKey, key) { 83 s.idx-- 84 } 85 } 86 } 87 88 func (s *SimpleIterator) Key() y.Key { 89 return s.keys[s.entryIdx()] 90 } 91 92 func (s *SimpleIterator) entryIdx() int { 93 return s.latestOffs[s.idx] + s.verIdx 94 } 95 96 func (s *SimpleIterator) Value() y.ValueStruct { 97 return y.ValueStruct{ 98 Value: s.vals[s.entryIdx()], 99 UserMeta: []byte{55}, 100 Meta: 0, 101 } 102 } 103 func (s *SimpleIterator) FillValue(vs *y.ValueStruct) { 104 vs.Value = s.vals[s.entryIdx()] 105 vs.UserMeta = []byte{55} // arbitrary value for test 106 vs.Meta = 0 107 } 108 func (s *SimpleIterator) Valid() bool { 109 return s.idx >= 0 && s.idx < len(s.latestOffs) 110 } 111 112 func newSimpleIterator(keys []string, vals []string, reversed bool) *SimpleIterator { 113 k := make([]y.Key, len(keys)) 114 v := make([][]byte, len(vals)) 115 lastestOffs := make([]int, len(keys)) 116 y.Assert(len(keys) == len(vals)) 117 for i := 0; i < len(keys); i++ { 118 k[i] = y.KeyWithTs([]byte(keys[i]), 0) 119 v[i] = []byte(vals[i]) 120 lastestOffs[i] = i 121 } 122 return &SimpleIterator{ 123 keys: k, 124 vals: v, 125 idx: -1, 126 reversed: reversed, 127 latestOffs: lastestOffs, 128 } 129 } 130 131 func newMultiVersionSimpleIterator(maxVersion, minVersion uint64, reversed bool) *SimpleIterator { 132 var latestOffs []int 133 var keys []y.Key 134 var vals [][]byte 135 for i := 0; i < 100; i++ { 136 latestOffs = append(latestOffs, len(keys)) 137 key := []byte(fmt.Sprintf("key%.3d", i)) 138 for j := maxVersion; j >= minVersion; j-- { 139 keys = append(keys, y.KeyWithTs(key, j)) 140 vals = append(vals, key) 141 if z.FastRand()%4 == 0 { 142 break 143 } 144 } 145 } 146 return &SimpleIterator{ 147 keys: keys, 148 vals: vals, 149 idx: 0, 150 reversed: reversed, 151 latestOffs: latestOffs, 152 } 153 } 154 155 func getAll(it y.Iterator) ([]string, []string) { 156 var keys, vals []string 157 for ; it.Valid(); it.Next() { 158 k := it.Key() 159 keys = append(keys, string(k.UserKey)) 160 v := it.Value() 161 vals = append(vals, string(v.Value)) 162 } 163 return keys, vals 164 } 165 166 func TestSimpleIterator(t *testing.T) { 167 keys := []string{"1", "2", "3"} 168 vals := []string{"v1", "v2", "v3"} 169 it := newSimpleIterator(keys, vals, false) 170 it.Rewind() 171 k, v := getAll(it) 172 require.EqualValues(t, keys, k) 173 require.EqualValues(t, vals, v) 174 } 175 176 func reversed(a []string) []string { 177 var out []string 178 for i := len(a) - 1; i >= 0; i-- { 179 out = append(out, a[i]) 180 } 181 return out 182 } 183 184 func TestMergeSingle(t *testing.T) { 185 keys := []string{"1", "2", "3"} 186 vals := []string{"v1", "v2", "v3"} 187 it := newSimpleIterator(keys, vals, false) 188 mergeIt := NewMergeIterator([]y.Iterator{it}, false) 189 mergeIt.Rewind() 190 k, v := getAll(mergeIt) 191 require.EqualValues(t, keys, k) 192 require.EqualValues(t, vals, v) 193 } 194 195 func TestMergeSingleReversed(t *testing.T) { 196 keys := []string{"1", "2", "3"} 197 vals := []string{"v1", "v2", "v3"} 198 it := newSimpleIterator(keys, vals, true) 199 mergeIt := NewMergeIterator([]y.Iterator{it}, true) 200 mergeIt.Rewind() 201 k, v := getAll(mergeIt) 202 require.EqualValues(t, reversed(keys), k) 203 require.EqualValues(t, reversed(vals), v) 204 } 205 206 func TestMergeMore(t *testing.T) { 207 it1 := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, false) 208 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, false) 209 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, false) 210 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, false) 211 212 mergeIt := NewMergeIterator([]y.Iterator{it1, it2, it3, it4}, false) 213 expectedKeys := []string{"1", "2", "3", "5", "7", "9"} 214 expectedVals := []string{"a1", "b2", "a3", "b5", "a7", "d9"} 215 mergeIt.Rewind() 216 k, v := getAll(mergeIt) 217 require.EqualValues(t, expectedKeys, k) 218 require.EqualValues(t, expectedVals, v) 219 } 220 221 // Ensure MergeIterator satisfies the Iterator interface 222 func TestMergeIteratorNested(t *testing.T) { 223 keys := []string{"1", "2", "3"} 224 vals := []string{"v1", "v2", "v3"} 225 it := newSimpleIterator(keys, vals, false) 226 mergeIt := NewMergeIterator([]y.Iterator{it}, false) 227 mergeIt2 := NewMergeIterator([]y.Iterator{mergeIt}, false) 228 mergeIt2.Rewind() 229 k, v := getAll(mergeIt2) 230 require.EqualValues(t, keys, k) 231 require.EqualValues(t, vals, v) 232 } 233 234 func TestMergeIteratorSeek(t *testing.T) { 235 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, false) 236 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, false) 237 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, false) 238 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, false) 239 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, false) 240 mergeIt.Seek([]byte("4")) 241 k, v := getAll(mergeIt) 242 require.EqualValues(t, []string{"5", "7", "9"}, k) 243 require.EqualValues(t, []string{"b5", "a7", "d9"}, v) 244 } 245 246 func TestMergeIteratorSeekReversed(t *testing.T) { 247 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, true) 248 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, true) 249 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, true) 250 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, true) 251 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, true) 252 mergeIt.Seek([]byte("5")) 253 k, v := getAll(mergeIt) 254 require.EqualValues(t, []string{"5", "3", "2", "1"}, k) 255 require.EqualValues(t, []string{"b5", "a3", "b2", "a1"}, v) 256 } 257 258 func TestMergeIteratorSeekInvalid(t *testing.T) { 259 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, false) 260 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, false) 261 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, false) 262 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, false) 263 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, false) 264 mergeIt.Seek([]byte("f")) 265 require.False(t, mergeIt.Valid()) 266 } 267 268 func TestMergeIteratorSeekInvalidReversed(t *testing.T) { 269 it := newSimpleIterator([]string{"1", "3", "7"}, []string{"a1", "a3", "a7"}, true) 270 it2 := newSimpleIterator([]string{"2", "3", "5"}, []string{"b2", "b3", "b5"}, true) 271 it3 := newSimpleIterator([]string{"1"}, []string{"c1"}, true) 272 it4 := newSimpleIterator([]string{"1", "7", "9"}, []string{"d1", "d7", "d9"}, true) 273 mergeIt := NewMergeIterator([]y.Iterator{it, it2, it3, it4}, true) 274 mergeIt.Seek([]byte("0")) 275 require.False(t, mergeIt.Valid()) 276 } 277 278 func TestMergeIteratorDuplicate(t *testing.T) { 279 it1 := newSimpleIterator([]string{"0", "1", "2"}, []string{"0", "1", "2"}, false) 280 it2 := newSimpleIterator([]string{"1"}, []string{"1"}, false) 281 it3 := newSimpleIterator([]string{"2"}, []string{"2"}, false) 282 it := NewMergeIterator([]y.Iterator{it3, it2, it1}, false) 283 284 var cnt int 285 for it.Rewind(); it.Valid(); it.Next() { 286 require.EqualValues(t, cnt+48, it.Key().UserKey[0]) 287 cnt++ 288 } 289 require.Equal(t, 3, cnt) 290 } 291 292 func TestMultiVersionMergeIterator(t *testing.T) { 293 for _, reverse := range []bool{true, false} { 294 it1 := newMultiVersionSimpleIterator(100, 90, reverse) 295 it2 := newMultiVersionSimpleIterator(90, 80, reverse) 296 it3 := newMultiVersionSimpleIterator(80, 70, reverse) 297 it4 := newMultiVersionSimpleIterator(70, 60, reverse) 298 it := NewMergeIterator([]y.Iterator{it1, it2, it3, it4}, reverse) 299 300 it.Rewind() 301 curKey := it.Key().UserKey 302 for i := 1; i < 100; i++ { 303 it.Next() 304 require.True(t, it.Valid()) 305 require.False(t, bytes.Equal(curKey, it.Key().UserKey)) 306 curKey = it.Key().UserKey 307 curVer := it.Key().Version 308 for it.NextVersion() { 309 require.True(t, it.Key().Version < curVer) 310 curVer = it.Key().Version 311 } 312 } 313 for i := 0; i < 100; i++ { 314 key := []byte(fmt.Sprintf("key%.3d", z.FastRand()%100)) 315 it.Seek(key) 316 require.True(t, it.Valid()) 317 require.EqualValues(t, it.Key().UserKey, key) 318 curVer := it.Key().Version 319 for it.NextVersion() { 320 require.True(t, it.Key().Version < curVer) 321 curVer = it.Key().Version 322 } 323 require.True(t, curVer <= 70) 324 } 325 } 326 } 327 328 func BenchmarkMergeIterator(b *testing.B) { 329 num := 2 330 simpleIters := make([]y.Iterator, num) 331 for i := 0; i < num; i++ { 332 simpleIters[i] = new(SimpleIterator) 333 } 334 for i := 0; i < num*100; i += num { 335 for j := 0; j < num; j++ { 336 iter := simpleIters[j].(*SimpleIterator) 337 iter.keys = append(iter.keys, y.KeyWithTs([]byte(fmt.Sprintf("key%08d", i+j)), 0)) 338 } 339 } 340 mergeIter := NewMergeIterator(simpleIters, false) 341 b.ResetTimer() 342 for i := 0; i < b.N; i++ { 343 mergeIter.Rewind() 344 for mergeIter.Valid() { 345 mergeIter.Key() 346 mergeIter.Next() 347 } 348 } 349 }