github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/iterator.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bitalosdb 16 17 import ( 18 "bytes" 19 "unsafe" 20 21 "github.com/zuoyebang/bitalosdb/internal/consts" 22 "github.com/zuoyebang/bitalosdb/internal/invariants" 23 "github.com/zuoyebang/bitalosdb/internal/utils" 24 25 "github.com/cockroachdb/errors" 26 "github.com/cockroachdb/redact" 27 ) 28 29 type iterPos int8 30 31 const ( 32 iterPosCurForward iterPos = 0 33 iterPosNext iterPos = 1 34 iterPosPrev iterPos = -1 35 iterPosCurReverse iterPos = -2 36 iterPosCurForwardPaused iterPos = 2 37 iterPosCurReversePaused iterPos = -3 38 ) 39 40 const maxKeyBufCacheSize = 4 << 10 41 42 const iterAllFlag = -1 43 44 var errReversePrefixIteration = errors.New("bitalosdb: unsupported reverse prefix iteration") 45 46 type IteratorMetrics struct { 47 ReadAmp int 48 } 49 50 type IteratorStatsKind int8 51 52 const ( 53 InterfaceCall IteratorStatsKind = iota 54 InternalIterCall 55 NumStatsKind 56 ) 57 58 type IteratorStats struct { 59 ForwardSeekCount [NumStatsKind]int 60 ReverseSeekCount [NumStatsKind]int 61 ForwardStepCount [NumStatsKind]int 62 ReverseStepCount [NumStatsKind]int 63 } 64 65 var _ redact.SafeFormatter = &IteratorStats{} 66 67 type Iterator struct { 68 opts IterOptions 69 cmp Compare 70 equal Equal 71 split Split 72 iter internalIterator 73 err error 74 key []byte 75 keyBuf []byte 76 value []byte 77 valueBuf []byte 78 iterKey *InternalKey 79 iterValue []byte 80 alloc *iterAlloc 81 prefixOrFullSeekKey []byte 82 stats IteratorStats 83 seqNum uint64 84 iterValidityState IterValidityState 85 pos iterPos 86 hasPrefix bool 87 lastPositioningOp lastPositioningOpKind 88 index int 89 bitower *Bitower 90 readState *readState 91 readStates []*readState 92 } 93 94 type lastPositioningOpKind int8 95 96 const ( 97 unknownLastPositionOp lastPositioningOpKind = iota 98 seekPrefixGELastPositioningOp 99 seekGELastPositioningOp 100 seekLTLastPositioningOp 101 ) 102 103 type IterValidityState int8 104 105 const ( 106 IterExhausted IterValidityState = iota 107 IterValid 108 ) 109 110 func (i *Iterator) findNextEntry() { 111 i.iterValidityState = IterExhausted 112 i.pos = iterPosCurForward 113 114 for i.iterKey != nil { 115 key := *i.iterKey 116 117 if i.hasPrefix { 118 if n := i.split(key.UserKey); !bytes.Equal(i.prefixOrFullSeekKey, key.UserKey[:n]) { 119 return 120 } 121 } 122 123 switch key.Kind() { 124 case InternalKeyKindDelete, InternalKeyKindPrefixDelete: 125 i.nextUserKey() 126 continue 127 case InternalKeyKindSet: 128 i.keyBuf = append(i.keyBuf[:0], key.UserKey...) 129 i.key = i.keyBuf 130 i.value = i.iterValue 131 i.iterValidityState = IterValid 132 return 133 default: 134 i.err = errors.Errorf("bitalosdb: invalid internal key kind %d", key.Kind()) 135 i.iterValidityState = IterExhausted 136 return 137 } 138 } 139 } 140 141 func (i *Iterator) nextUserKey() { 142 if i.iterKey == nil { 143 return 144 } 145 done := i.iterKey.SeqNum() == 0 146 if i.iterValidityState != IterValid { 147 i.keyBuf = append(i.keyBuf[:0], i.iterKey.UserKey...) 148 i.key = i.keyBuf 149 } 150 for { 151 i.iterKey, i.iterValue = i.iter.Next() 152 i.stats.ForwardStepCount[InternalIterCall]++ 153 if done || i.iterKey == nil { 154 break 155 } 156 if !i.equal(i.key, i.iterKey.UserKey) { 157 break 158 } 159 done = i.iterKey.SeqNum() == 0 160 } 161 } 162 163 func (i *Iterator) findPrevEntry() { 164 i.iterValidityState = IterExhausted 165 i.pos = iterPosCurReverse 166 167 for i.iterKey != nil { 168 key := *i.iterKey 169 170 if i.iterValidityState == IterValid { 171 if !i.equal(key.UserKey, i.key) { 172 i.pos = iterPosPrev 173 if i.err != nil { 174 i.iterValidityState = IterExhausted 175 } 176 return 177 } 178 } 179 180 switch key.Kind() { 181 case InternalKeyKindDelete, InternalKeyKindPrefixDelete: 182 i.value = nil 183 i.iterValidityState = IterExhausted 184 i.iterKey, i.iterValue = i.iter.Prev() 185 i.stats.ReverseStepCount[InternalIterCall]++ 186 case InternalKeyKindSet: 187 i.keyBuf = append(i.keyBuf[:0], key.UserKey...) 188 i.key = i.keyBuf 189 i.value = i.iterValue 190 i.iterValidityState = IterValid 191 i.iterKey, i.iterValue = i.iter.Prev() 192 i.stats.ReverseStepCount[InternalIterCall]++ 193 default: 194 i.err = errors.Errorf("bitalosdb: invalid internal key kind %d", key.Kind()) 195 i.iterValidityState = IterExhausted 196 return 197 } 198 } 199 200 if i.iterValidityState == IterValid { 201 i.pos = iterPosPrev 202 if i.err != nil { 203 i.iterValidityState = IterExhausted 204 } 205 } 206 } 207 208 func (i *Iterator) prevUserKey() { 209 if i.iterKey == nil { 210 return 211 } 212 if i.iterValidityState != IterValid { 213 i.keyBuf = append(i.keyBuf[:0], i.iterKey.UserKey...) 214 i.key = i.keyBuf 215 } 216 for { 217 i.iterKey, i.iterValue = i.iter.Prev() 218 i.stats.ReverseStepCount[InternalIterCall]++ 219 if i.iterKey == nil { 220 break 221 } 222 if !i.equal(i.key, i.iterKey.UserKey) { 223 break 224 } 225 } 226 } 227 228 func (i *Iterator) SeekGE(key []byte) bool { 229 return i.SeekGEWithLimit(key) == IterValid 230 } 231 232 func (i *Iterator) SeekGEWithLimit(key []byte) IterValidityState { 233 lastPositioningOp := i.lastPositioningOp 234 i.lastPositioningOp = unknownLastPositionOp 235 236 i.err = nil 237 i.hasPrefix = false 238 i.stats.ForwardSeekCount[InterfaceCall]++ 239 if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 { 240 key = lowerBound 241 } else if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 { 242 key = upperBound 243 } 244 seekInternalIter := true 245 if lastPositioningOp == seekGELastPositioningOp { 246 cmp := i.cmp(i.prefixOrFullSeekKey, key) 247 if cmp <= 0 { 248 if i.iterValidityState == IterExhausted || 249 (i.iterValidityState == IterValid && i.cmp(key, i.key) <= 0) { 250 if !invariants.Enabled || !disableSeekOpt(key, uintptr(unsafe.Pointer(i))) { 251 i.lastPositioningOp = seekGELastPositioningOp 252 return i.iterValidityState 253 } 254 } 255 if i.pos == iterPosCurForwardPaused && i.cmp(key, i.iterKey.UserKey) <= 0 { 256 seekInternalIter = false 257 } 258 } 259 } 260 if seekInternalIter { 261 i.iterKey, i.iterValue = i.iter.SeekGE(key) 262 i.stats.ForwardSeekCount[InternalIterCall]++ 263 } 264 i.findNextEntry() 265 if i.Error() == nil { 266 i.prefixOrFullSeekKey = append(i.prefixOrFullSeekKey[:0], key...) 267 i.lastPositioningOp = seekGELastPositioningOp 268 } 269 return i.iterValidityState 270 } 271 272 func (i *Iterator) SeekPrefixGE(key []byte) bool { 273 lastPositioningOp := i.lastPositioningOp 274 i.lastPositioningOp = unknownLastPositionOp 275 i.err = nil 276 i.stats.ForwardSeekCount[InterfaceCall]++ 277 278 prefixLen := i.split(key) 279 keyPrefix := key[:prefixLen] 280 trySeekUsingNext := false 281 if lastPositioningOp == seekPrefixGELastPositioningOp { 282 cmp := i.cmp(i.prefixOrFullSeekKey, keyPrefix) 283 trySeekUsingNext = cmp < 0 284 if invariants.Enabled && trySeekUsingNext && disableSeekOpt(key, uintptr(unsafe.Pointer(i))) { 285 trySeekUsingNext = false 286 } 287 } 288 if cap(i.prefixOrFullSeekKey) < prefixLen { 289 i.prefixOrFullSeekKey = make([]byte, prefixLen) 290 } else { 291 i.prefixOrFullSeekKey = i.prefixOrFullSeekKey[:prefixLen] 292 } 293 i.hasPrefix = true 294 copy(i.prefixOrFullSeekKey, keyPrefix) 295 296 if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 { 297 if n := i.split(lowerBound); !bytes.Equal(i.prefixOrFullSeekKey, lowerBound[:n]) { 298 i.err = errors.New("bitalosdb: SeekPrefixGE supplied with key outside of lower bound") 299 return false 300 } 301 key = lowerBound 302 } else if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 { 303 if n := i.split(upperBound); !bytes.Equal(i.prefixOrFullSeekKey, upperBound[:n]) { 304 i.err = errors.New("bitalosdb: SeekPrefixGE supplied with key outside of upper bound") 305 return false 306 } 307 key = upperBound 308 } 309 310 i.iterKey, i.iterValue = i.iter.SeekPrefixGE(i.prefixOrFullSeekKey, key, trySeekUsingNext) 311 i.stats.ForwardSeekCount[InternalIterCall]++ 312 i.findNextEntry() 313 if i.Error() == nil { 314 i.lastPositioningOp = seekPrefixGELastPositioningOp 315 } 316 return i.iterValidityState == IterValid 317 } 318 319 func disableSeekOpt(key []byte, ptr uintptr) bool { 320 simpleHash := (11400714819323198485 * uint64(ptr)) >> 63 321 return key != nil && key[0]&byte(1) == 0 && simpleHash == 0 322 } 323 324 func (i *Iterator) SeekLT(key []byte) bool { 325 return i.SeekLTWithLimit(key) == IterValid 326 } 327 328 func (i *Iterator) SeekLTWithLimit(key []byte) IterValidityState { 329 lastPositioningOp := i.lastPositioningOp 330 i.lastPositioningOp = unknownLastPositionOp 331 i.err = nil 332 i.hasPrefix = false 333 i.stats.ReverseSeekCount[InterfaceCall]++ 334 if upperBound := i.opts.GetUpperBound(); upperBound != nil && i.cmp(key, upperBound) > 0 { 335 key = upperBound 336 } else if lowerBound := i.opts.GetLowerBound(); lowerBound != nil && i.cmp(key, lowerBound) < 0 { 337 key = lowerBound 338 } 339 seekInternalIter := true 340 if lastPositioningOp == seekLTLastPositioningOp { 341 cmp := i.cmp(key, i.prefixOrFullSeekKey) 342 if cmp <= 0 { 343 if i.iterValidityState == IterExhausted || 344 (i.iterValidityState == IterValid && i.cmp(i.key, key) < 0) { 345 if !invariants.Enabled || !disableSeekOpt(key, uintptr(unsafe.Pointer(i))) { 346 i.lastPositioningOp = seekLTLastPositioningOp 347 return i.iterValidityState 348 } 349 } 350 if i.pos == iterPosCurReversePaused && i.cmp(i.iterKey.UserKey, key) < 0 { 351 seekInternalIter = false 352 } 353 } 354 } 355 if seekInternalIter { 356 i.iterKey, i.iterValue = i.iter.SeekLT(key) 357 i.stats.ReverseSeekCount[InternalIterCall]++ 358 } 359 i.findPrevEntry() 360 if i.Error() == nil { 361 i.prefixOrFullSeekKey = append(i.prefixOrFullSeekKey[:0], key...) 362 i.lastPositioningOp = seekLTLastPositioningOp 363 } 364 return i.iterValidityState 365 } 366 367 func (i *Iterator) First() bool { 368 i.err = nil 369 i.hasPrefix = false 370 i.lastPositioningOp = unknownLastPositionOp 371 i.stats.ForwardSeekCount[InterfaceCall]++ 372 if lowerBound := i.opts.GetLowerBound(); lowerBound != nil { 373 i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound) 374 i.stats.ForwardSeekCount[InternalIterCall]++ 375 } else { 376 i.iterKey, i.iterValue = i.iter.First() 377 i.stats.ForwardSeekCount[InternalIterCall]++ 378 } 379 i.findNextEntry() 380 return i.iterValidityState == IterValid 381 } 382 383 func (i *Iterator) Last() bool { 384 i.err = nil 385 i.hasPrefix = false 386 i.lastPositioningOp = unknownLastPositionOp 387 i.stats.ReverseSeekCount[InterfaceCall]++ 388 if upperBound := i.opts.GetUpperBound(); upperBound != nil { 389 i.iterKey, i.iterValue = i.iter.SeekLT(upperBound) 390 i.stats.ReverseSeekCount[InternalIterCall]++ 391 } else { 392 i.iterKey, i.iterValue = i.iter.Last() 393 i.stats.ReverseSeekCount[InternalIterCall]++ 394 } 395 i.findPrevEntry() 396 return i.iterValidityState == IterValid 397 } 398 399 func (i *Iterator) Next() bool { 400 return i.NextWithLimit() == IterValid 401 } 402 403 func (i *Iterator) NextWithLimit() IterValidityState { 404 i.stats.ForwardStepCount[InterfaceCall]++ 405 406 if i.err != nil { 407 return i.iterValidityState 408 } 409 i.lastPositioningOp = unknownLastPositionOp 410 switch i.pos { 411 case iterPosCurForward: 412 i.nextUserKey() 413 case iterPosCurForwardPaused: 414 case iterPosCurReverse: 415 if i.iterKey != nil { 416 i.err = errors.New("bitalosdb: switching from reverse to forward but iter is not at prev") 417 i.iterValidityState = IterExhausted 418 return i.iterValidityState 419 } 420 421 if lowerBound := i.opts.GetLowerBound(); lowerBound != nil { 422 i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound) 423 i.stats.ForwardSeekCount[InternalIterCall]++ 424 } else { 425 i.iterKey, i.iterValue = i.iter.First() 426 i.stats.ForwardSeekCount[InternalIterCall]++ 427 } 428 case iterPosCurReversePaused: 429 if i.iterKey == nil { 430 i.err = errors.New("bitalosdb: switching paused from reverse to forward but iter is exhausted") 431 i.iterValidityState = IterExhausted 432 return i.iterValidityState 433 } 434 i.nextUserKey() 435 case iterPosPrev: 436 i.iterValidityState = IterExhausted 437 if i.iterKey == nil { 438 if lowerBound := i.opts.GetLowerBound(); lowerBound != nil { 439 i.iterKey, i.iterValue = i.iter.SeekGE(lowerBound) 440 i.stats.ForwardSeekCount[InternalIterCall]++ 441 } else { 442 i.iterKey, i.iterValue = i.iter.First() 443 i.stats.ForwardSeekCount[InternalIterCall]++ 444 } 445 } else { 446 i.nextUserKey() 447 } 448 i.nextUserKey() 449 case iterPosNext: 450 } 451 i.findNextEntry() 452 return i.iterValidityState 453 } 454 455 func (i *Iterator) Prev() bool { 456 return i.PrevWithLimit() == IterValid 457 } 458 459 func (i *Iterator) PrevWithLimit() IterValidityState { 460 i.stats.ReverseStepCount[InterfaceCall]++ 461 if i.err != nil { 462 return i.iterValidityState 463 } 464 i.lastPositioningOp = unknownLastPositionOp 465 if i.hasPrefix { 466 i.err = errReversePrefixIteration 467 i.iterValidityState = IterExhausted 468 return i.iterValidityState 469 } 470 switch i.pos { 471 case iterPosCurForward: 472 case iterPosCurForwardPaused: 473 case iterPosCurReverse: 474 i.prevUserKey() 475 case iterPosCurReversePaused: 476 case iterPosNext: 477 case iterPosPrev: 478 } 479 if i.pos == iterPosCurForward || i.pos == iterPosNext || i.pos == iterPosCurForwardPaused { 480 stepAgain := i.pos == iterPosNext 481 i.iterValidityState = IterExhausted 482 if i.iterKey == nil { 483 if upperBound := i.opts.GetUpperBound(); upperBound != nil { 484 i.iterKey, i.iterValue = i.iter.SeekLT(upperBound) 485 i.stats.ReverseSeekCount[InternalIterCall]++ 486 } else { 487 i.iterKey, i.iterValue = i.iter.Last() 488 i.stats.ReverseSeekCount[InternalIterCall]++ 489 } 490 } else { 491 i.prevUserKey() 492 } 493 if stepAgain { 494 i.prevUserKey() 495 } 496 } 497 i.findPrevEntry() 498 return i.iterValidityState 499 } 500 501 func (i *Iterator) Key() []byte { 502 return i.key 503 } 504 505 func (i *Iterator) Value() []byte { 506 return i.value 507 } 508 509 func (i *Iterator) Valid() bool { 510 return i.iterValidityState == IterValid 511 } 512 513 func (i *Iterator) Error() error { 514 err := i.err 515 if i.iter != nil { 516 err = utils.FirstError(i.err, i.iter.Error()) 517 } 518 return err 519 } 520 521 func (i *Iterator) Close() error { 522 if i.bitower != nil && i.getInternalStepCount() > consts.IterSlowCountThreshold { 523 i.bitower.iterSlowCount.Add(1) 524 } 525 526 if i.iter != nil { 527 i.err = utils.FirstError(i.err, i.iter.Close()) 528 } 529 err := i.err 530 531 if i.readState != nil { 532 i.readState.unref() 533 i.readState = nil 534 } else if i.readStates != nil { 535 for j := range i.readStates { 536 i.readStates[j].unref() 537 i.readStates[j] = nil 538 } 539 i.readStates = nil 540 } 541 542 if alloc := i.alloc; alloc != nil { 543 if cap(i.keyBuf) >= maxKeyBufCacheSize { 544 alloc.keyBuf = nil 545 } else { 546 alloc.keyBuf = i.keyBuf 547 } 548 if cap(i.prefixOrFullSeekKey) >= maxKeyBufCacheSize { 549 alloc.prefixOrFullSeekKey = nil 550 } else { 551 alloc.prefixOrFullSeekKey = i.prefixOrFullSeekKey 552 } 553 *i = Iterator{} 554 iterAllocPool.Put(alloc) 555 } 556 return err 557 } 558 559 func (i *Iterator) SetBounds(lower, upper []byte) { 560 i.lastPositioningOp = unknownLastPositionOp 561 i.hasPrefix = false 562 i.iterKey = nil 563 i.iterValue = nil 564 565 switch i.pos { 566 case iterPosCurForward, iterPosNext, iterPosCurForwardPaused: 567 i.pos = iterPosCurForward 568 case iterPosCurReverse, iterPosPrev, iterPosCurReversePaused: 569 i.pos = iterPosCurReverse 570 } 571 i.iterValidityState = IterExhausted 572 573 i.opts.LowerBound = lower 574 i.opts.UpperBound = upper 575 i.iter.SetBounds(lower, upper) 576 } 577 578 func (i *Iterator) Metrics() IteratorMetrics { 579 m := IteratorMetrics{ 580 ReadAmp: 1, 581 } 582 if mi, ok := i.iter.(*mergingIter); ok { 583 m.ReadAmp = len(mi.levels) 584 } 585 return m 586 } 587 588 func (i *Iterator) ResetStats() { 589 i.stats = IteratorStats{} 590 } 591 592 func (i *Iterator) Stats() IteratorStats { 593 return i.stats 594 } 595 596 func (i *Iterator) getInternalStepCount() int { 597 return i.stats.ForwardStepCount[1] + i.stats.ReverseStepCount[1] 598 } 599 600 func (i *Iterator) getInterfaceStepCount() int { 601 return i.stats.ForwardStepCount[0] + i.stats.ReverseStepCount[0] 602 } 603 604 func (i *Iterator) getInternalSeekCount() int { 605 return i.stats.ForwardSeekCount[1] + i.stats.ForwardSeekCount[1] 606 } 607 608 func (i *Iterator) getInterfaceSeekCount() int { 609 return i.stats.ForwardSeekCount[0] + i.stats.ForwardSeekCount[0] 610 } 611 612 func (stats *IteratorStats) String() string { 613 return redact.StringWithoutMarkers(stats) 614 } 615 616 func (stats *IteratorStats) SafeFormat(s redact.SafePrinter, verb rune) { 617 for i := range stats.ForwardStepCount { 618 switch IteratorStatsKind(i) { 619 case InterfaceCall: 620 s.SafeString("(interface (dir, seek, step): ") 621 case InternalIterCall: 622 s.SafeString(", (internal (dir, seek, step): ") 623 } 624 s.Printf("(fwd, %d, %d), (rev, %d, %d))", 625 stats.ForwardSeekCount[i], stats.ForwardStepCount[i], 626 stats.ReverseSeekCount[i], stats.ReverseStepCount[i]) 627 } 628 }