github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bithash/block.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 bithash 16 17 import ( 18 "encoding/binary" 19 "errors" 20 "unsafe" 21 22 "github.com/zuoyebang/bitalosdb/internal/base" 23 "github.com/zuoyebang/bitalosdb/internal/cache/lrucache" 24 ) 25 26 type BlockHandle struct { 27 Offset, Length uint32 28 } 29 30 func encodeBlockHandle(dst []byte, b BlockHandle) { 31 binary.LittleEndian.PutUint32(dst[0:4], b.Offset) 32 binary.LittleEndian.PutUint32(dst[4:8], b.Length) 33 } 34 35 func decodeBlockHandle(src []byte) BlockHandle { 36 offset := binary.LittleEndian.Uint32(src[0:4]) 37 length := binary.LittleEndian.Uint32(src[4:8]) 38 return BlockHandle{offset, length} 39 } 40 41 type blockEntry struct { 42 offset int32 43 keyStart int32 44 keyEnd int32 45 valStart int32 46 valSize int32 47 } 48 49 type blockIter struct { 50 cmp Compare 51 offset int32 52 nextOffset int32 53 restarts int32 54 numRestarts int32 55 globalSeqNum uint64 56 ptr unsafe.Pointer 57 data []byte 58 key []byte 59 fullKey []byte 60 val []byte 61 ikey InternalKey 62 cached []blockEntry 63 cachedBuf []byte 64 cacheHandle lrucache.Handle 65 firstKey InternalKey 66 } 67 68 type block []byte 69 70 func newBlockIter(cmp Compare, block block) (*blockIter, error) { 71 i := &blockIter{} 72 return i, i.init(cmp, block, 0) 73 } 74 75 func (i *blockIter) init(cmp Compare, block block, globalSeqNum uint64) error { 76 numRestarts := int32(binary.LittleEndian.Uint32(block[len(block)-4:])) 77 if numRestarts == 0 { 78 return errors.New("bithash invalid table block has no restart points") 79 } 80 i.cmp = cmp 81 i.restarts = int32(len(block)) - 4*(1+numRestarts) 82 i.numRestarts = numRestarts 83 i.globalSeqNum = globalSeqNum 84 i.ptr = unsafe.Pointer(&block[0]) 85 i.data = block 86 i.fullKey = i.fullKey[:0] 87 i.val = nil 88 i.clearCache() 89 if i.restarts > 0 { 90 if err := i.readFirstKey(); err != nil { 91 return err 92 } 93 } else { 94 i.firstKey = InternalKey{} 95 } 96 return nil 97 } 98 99 func (i *blockIter) isDataInvalidated() bool { 100 return i.data == nil 101 } 102 103 func (i *blockIter) resetForReuse() blockIter { 104 return blockIter{ 105 fullKey: i.fullKey[:0], 106 cached: i.cached[:0], 107 cachedBuf: i.cachedBuf[:0], 108 data: nil, 109 } 110 } 111 112 func (i *blockIter) readEntry() { 113 ptr := unsafe.Pointer(uintptr(i.ptr) + uintptr(i.offset)) 114 115 var shared uint32 116 if a := *((*uint8)(ptr)); a < 128 { 117 shared = uint32(a) 118 ptr = unsafe.Pointer(uintptr(ptr) + 1) 119 } else if a, b := a&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); b < 128 { 120 shared = uint32(b)<<7 | uint32(a) 121 ptr = unsafe.Pointer(uintptr(ptr) + 2) 122 } else if b, c := b&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); c < 128 { 123 shared = uint32(c)<<14 | uint32(b)<<7 | uint32(a) 124 ptr = unsafe.Pointer(uintptr(ptr) + 3) 125 } else if c, d := c&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); d < 128 { 126 shared = uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 127 ptr = unsafe.Pointer(uintptr(ptr) + 4) 128 } else { 129 d, e := d&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 4))) 130 shared = uint32(e)<<28 | uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 131 ptr = unsafe.Pointer(uintptr(ptr) + 5) 132 } 133 134 var unshared uint32 135 if a := *((*uint8)(ptr)); a < 128 { 136 unshared = uint32(a) 137 ptr = unsafe.Pointer(uintptr(ptr) + 1) 138 } else if a, b := a&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); b < 128 { 139 unshared = uint32(b)<<7 | uint32(a) 140 ptr = unsafe.Pointer(uintptr(ptr) + 2) 141 } else if b, c := b&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); c < 128 { 142 unshared = uint32(c)<<14 | uint32(b)<<7 | uint32(a) 143 ptr = unsafe.Pointer(uintptr(ptr) + 3) 144 } else if c, d := c&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); d < 128 { 145 unshared = uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 146 ptr = unsafe.Pointer(uintptr(ptr) + 4) 147 } else { 148 d, e := d&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 4))) 149 unshared = uint32(e)<<28 | uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 150 ptr = unsafe.Pointer(uintptr(ptr) + 5) 151 } 152 153 var value uint32 154 if a := *((*uint8)(ptr)); a < 128 { 155 value = uint32(a) 156 ptr = unsafe.Pointer(uintptr(ptr) + 1) 157 } else if a, b := a&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); b < 128 { 158 value = uint32(b)<<7 | uint32(a) 159 ptr = unsafe.Pointer(uintptr(ptr) + 2) 160 } else if b, c := b&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); c < 128 { 161 value = uint32(c)<<14 | uint32(b)<<7 | uint32(a) 162 ptr = unsafe.Pointer(uintptr(ptr) + 3) 163 } else if c, d := c&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); d < 128 { 164 value = uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 165 ptr = unsafe.Pointer(uintptr(ptr) + 4) 166 } else { 167 d, e := d&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 4))) 168 value = uint32(e)<<28 | uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 169 ptr = unsafe.Pointer(uintptr(ptr) + 5) 170 } 171 172 unsharedKey := getBytes(ptr, int(unshared)) 173 i.fullKey = append(i.fullKey[:shared], unsharedKey...) 174 if shared == 0 { 175 i.key = unsharedKey 176 } else { 177 i.key = i.fullKey 178 } 179 ptr = unsafe.Pointer(uintptr(ptr) + uintptr(unshared)) 180 i.val = getBytes(ptr, int(value)) 181 i.nextOffset = int32(uintptr(ptr)-uintptr(i.ptr)) + int32(value) 182 } 183 184 func (i *blockIter) decodeInternalKey(key []byte) { 185 if n := len(key) - 8; n >= 0 { 186 i.ikey.Trailer = binary.LittleEndian.Uint64(key[n:]) 187 i.ikey.UserKey = key[:n:n] 188 if i.globalSeqNum != 0 { 189 i.ikey.SetSeqNum(i.globalSeqNum) 190 } 191 } else { 192 i.ikey.Trailer = uint64(InternalKeyKindInvalid) 193 i.ikey.UserKey = nil 194 } 195 } 196 197 func (i *blockIter) clearCache() { 198 i.cached = i.cached[:0] 199 i.cachedBuf = i.cachedBuf[:0] 200 } 201 202 func (i *blockIter) readFirstKey() error { 203 ptr := i.ptr 204 205 if shared := *((*uint8)(ptr)); shared == 0 { 206 ptr = unsafe.Pointer(uintptr(ptr) + 1) 207 } else { 208 panic("first key in block must have zero shared length") 209 } 210 211 var unshared uint32 212 if a := *((*uint8)(ptr)); a < 128 { 213 unshared = uint32(a) 214 ptr = unsafe.Pointer(uintptr(ptr) + 1) 215 } else if a, b := a&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); b < 128 { 216 unshared = uint32(b)<<7 | uint32(a) 217 ptr = unsafe.Pointer(uintptr(ptr) + 2) 218 } else if b, c := b&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); c < 128 { 219 unshared = uint32(c)<<14 | uint32(b)<<7 | uint32(a) 220 ptr = unsafe.Pointer(uintptr(ptr) + 3) 221 } else if c, d := c&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); d < 128 { 222 unshared = uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 223 ptr = unsafe.Pointer(uintptr(ptr) + 4) 224 } else { 225 d, e := d&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 4))) 226 unshared = uint32(e)<<28 | uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 227 ptr = unsafe.Pointer(uintptr(ptr) + 5) 228 } 229 230 if a := *((*uint8)(ptr)); a < 128 { 231 ptr = unsafe.Pointer(uintptr(ptr) + 1) 232 } else if a := *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); a < 128 { 233 ptr = unsafe.Pointer(uintptr(ptr) + 2) 234 } else if a := *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); a < 128 { 235 ptr = unsafe.Pointer(uintptr(ptr) + 3) 236 } else if a := *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); a < 128 { 237 ptr = unsafe.Pointer(uintptr(ptr) + 4) 238 } else { 239 ptr = unsafe.Pointer(uintptr(ptr) + 5) 240 } 241 242 firstKey := getBytes(ptr, int(unshared)) 243 if n := len(firstKey) - 8; n >= 0 { 244 i.firstKey.Trailer = binary.LittleEndian.Uint64(firstKey[n:]) 245 i.firstKey.UserKey = firstKey[:n:n] 246 if i.globalSeqNum != 0 { 247 i.firstKey.SetSeqNum(i.globalSeqNum) 248 } 249 } else { 250 i.firstKey.Trailer = uint64(InternalKeyKindInvalid) 251 i.firstKey.UserKey = nil 252 return base.CorruptionErrorf("bitalosdb: invalid firstKey in block") 253 } 254 return nil 255 } 256 257 func (i *blockIter) cacheEntry() { 258 var valStart int32 259 valSize := int32(len(i.val)) 260 if valSize > 0 { 261 valStart = int32(uintptr(unsafe.Pointer(&i.val[0])) - uintptr(i.ptr)) 262 } 263 264 i.cached = append(i.cached, blockEntry{ 265 offset: i.offset, 266 keyStart: int32(len(i.cachedBuf)), 267 keyEnd: int32(len(i.cachedBuf) + len(i.key)), 268 valStart: valStart, 269 valSize: valSize, 270 }) 271 i.cachedBuf = append(i.cachedBuf, i.key...) 272 } 273 274 func (i *blockIter) SeekGE(key []byte) (*InternalKey, []byte) { 275 i.clearCache() 276 277 ikey := base.MakeSearchKey(key) 278 279 i.offset = 0 280 var index int32 281 282 { 283 upper := i.numRestarts 284 for index < upper { 285 h := int32(uint(index+upper) >> 1) 286 offset := int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*h:])) 287 ptr := unsafe.Pointer(uintptr(i.ptr) + uintptr(offset+1)) 288 289 var v1 uint32 290 if a := *((*uint8)(ptr)); a < 128 { 291 v1 = uint32(a) 292 ptr = unsafe.Pointer(uintptr(ptr) + 1) 293 } else if a, b := a&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); b < 128 { 294 v1 = uint32(b)<<7 | uint32(a) 295 ptr = unsafe.Pointer(uintptr(ptr) + 2) 296 } else if b, c := b&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); c < 128 { 297 v1 = uint32(c)<<14 | uint32(b)<<7 | uint32(a) 298 ptr = unsafe.Pointer(uintptr(ptr) + 3) 299 } else if c, d := c&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); d < 128 { 300 v1 = uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 301 ptr = unsafe.Pointer(uintptr(ptr) + 4) 302 } else { 303 d, e := d&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 4))) 304 v1 = uint32(e)<<28 | uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 305 ptr = unsafe.Pointer(uintptr(ptr) + 5) 306 } 307 308 if *((*uint8)(ptr)) < 128 { 309 ptr = unsafe.Pointer(uintptr(ptr) + 1) 310 } else if *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))) < 128 { 311 ptr = unsafe.Pointer(uintptr(ptr) + 2) 312 } else if *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))) < 128 { 313 ptr = unsafe.Pointer(uintptr(ptr) + 3) 314 } else if *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))) < 128 { 315 ptr = unsafe.Pointer(uintptr(ptr) + 4) 316 } else { 317 ptr = unsafe.Pointer(uintptr(ptr) + 5) 318 } 319 320 s := getBytes(ptr, int(v1)) 321 var k InternalKey 322 if n := len(s) - 8; n >= 0 { 323 k.Trailer = binary.LittleEndian.Uint64(s[n:]) 324 k.UserKey = s[:n:n] 325 } else { 326 k.Trailer = uint64(InternalKeyKindInvalid) 327 } 328 329 if base.InternalCompare(i.cmp, ikey, k) >= 0 { 330 index = h + 1 331 } else { 332 upper = h 333 } 334 } 335 } 336 337 if index > 0 { 338 i.offset = int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*(index-1):])) 339 } 340 i.readEntry() 341 i.decodeInternalKey(i.key) 342 343 for ; i.Valid(); i.Next() { 344 if base.InternalCompare(i.cmp, i.ikey, ikey) >= 0 { 345 return &i.ikey, i.val 346 } 347 } 348 349 return nil, nil 350 } 351 352 func (i *blockIter) SeekPrefixGE( 353 prefix, key []byte, trySeekUsingNext bool, 354 ) (*base.InternalKey, []byte) { 355 panic("bitalosdb: SeekPrefixGE unimplemented") 356 } 357 358 func (i *blockIter) SeekLT(key []byte) (*InternalKey, []byte) { 359 i.clearCache() 360 361 ikey := base.MakeSearchKey(key) 362 363 i.offset = 0 364 var index int32 365 366 { 367 upper := i.numRestarts 368 for index < upper { 369 h := int32(uint(index+upper) >> 1) 370 offset := int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*h:])) 371 ptr := unsafe.Pointer(uintptr(i.ptr) + uintptr(offset+1)) 372 373 var v1 uint32 374 if a := *((*uint8)(ptr)); a < 128 { 375 v1 = uint32(a) 376 ptr = unsafe.Pointer(uintptr(ptr) + 1) 377 } else if a, b := a&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))); b < 128 { 378 v1 = uint32(b)<<7 | uint32(a) 379 ptr = unsafe.Pointer(uintptr(ptr) + 2) 380 } else if b, c := b&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))); c < 128 { 381 v1 = uint32(c)<<14 | uint32(b)<<7 | uint32(a) 382 ptr = unsafe.Pointer(uintptr(ptr) + 3) 383 } else if c, d := c&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))); d < 128 { 384 v1 = uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 385 ptr = unsafe.Pointer(uintptr(ptr) + 4) 386 } else { 387 d, e := d&0x7f, *((*uint8)(unsafe.Pointer(uintptr(ptr) + 4))) 388 v1 = uint32(e)<<28 | uint32(d)<<21 | uint32(c)<<14 | uint32(b)<<7 | uint32(a) 389 ptr = unsafe.Pointer(uintptr(ptr) + 5) 390 } 391 392 if *((*uint8)(ptr)) < 128 { 393 ptr = unsafe.Pointer(uintptr(ptr) + 1) 394 } else if *((*uint8)(unsafe.Pointer(uintptr(ptr) + 1))) < 128 { 395 ptr = unsafe.Pointer(uintptr(ptr) + 2) 396 } else if *((*uint8)(unsafe.Pointer(uintptr(ptr) + 2))) < 128 { 397 ptr = unsafe.Pointer(uintptr(ptr) + 3) 398 } else if *((*uint8)(unsafe.Pointer(uintptr(ptr) + 3))) < 128 { 399 ptr = unsafe.Pointer(uintptr(ptr) + 4) 400 } else { 401 ptr = unsafe.Pointer(uintptr(ptr) + 5) 402 } 403 404 s := getBytes(ptr, int(v1)) 405 var k InternalKey 406 if n := len(s) - 8; n >= 0 { 407 k.Trailer = binary.LittleEndian.Uint64(s[n:]) 408 k.UserKey = s[:n:n] 409 } else { 410 k.Trailer = uint64(InternalKeyKindInvalid) 411 } 412 413 if base.InternalCompare(i.cmp, ikey, k) > 0 { 414 index = h + 1 415 } else { 416 upper = h 417 } 418 } 419 } 420 421 targetOffset := i.restarts 422 if index > 0 { 423 i.offset = int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*(index-1):])) 424 if index < i.numRestarts { 425 targetOffset = int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*(index):])) 426 } 427 } else if index == 0 { 428 i.offset = -1 429 i.nextOffset = 0 430 return nil, nil 431 } 432 433 i.nextOffset = i.offset 434 435 for { 436 i.offset = i.nextOffset 437 i.readEntry() 438 i.decodeInternalKey(i.key) 439 440 if i.cmp(i.ikey.UserKey, ikey.UserKey) >= 0 { 441 i.Prev() 442 return &i.ikey, i.val 443 } 444 445 if i.nextOffset >= targetOffset { 446 break 447 } 448 449 i.cacheEntry() 450 } 451 452 if !i.Valid() { 453 return nil, nil 454 } 455 return &i.ikey, i.val 456 } 457 458 func (i *blockIter) First() (*InternalKey, []byte) { 459 i.offset = 0 460 if !i.Valid() { 461 return nil, nil 462 } 463 i.clearCache() 464 i.readEntry() 465 i.decodeInternalKey(i.key) 466 return &i.ikey, i.val 467 } 468 469 func (i *blockIter) Last() (*InternalKey, []byte) { 470 i.offset = int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*(i.numRestarts-1):])) 471 if !i.Valid() { 472 return nil, nil 473 } 474 475 i.readEntry() 476 i.clearCache() 477 478 for i.nextOffset < i.restarts { 479 i.cacheEntry() 480 i.offset = i.nextOffset 481 i.readEntry() 482 } 483 484 i.decodeInternalKey(i.key) 485 return &i.ikey, i.val 486 } 487 488 func (i *blockIter) Next() (*InternalKey, []byte) { 489 if len(i.cachedBuf) > 0 { 490 i.fullKey = append(i.fullKey[:0], i.key...) 491 i.clearCache() 492 } 493 494 i.offset = i.nextOffset 495 if !i.Valid() { 496 return nil, nil 497 } 498 i.readEntry() 499 500 if n := len(i.key) - 8; n >= 0 { 501 i.ikey.Trailer = binary.LittleEndian.Uint64(i.key[n:]) 502 i.ikey.UserKey = i.key[:n:n] 503 if i.globalSeqNum != 0 { 504 i.ikey.SetSeqNum(i.globalSeqNum) 505 } 506 } else { 507 i.ikey.Trailer = uint64(InternalKeyKindInvalid) 508 i.ikey.UserKey = nil 509 } 510 return &i.ikey, i.val 511 } 512 513 func (i *blockIter) Prev() (*InternalKey, []byte) { 514 if n := len(i.cached) - 1; n >= 0 { 515 i.nextOffset = i.offset 516 e := &i.cached[n] 517 i.offset = e.offset 518 i.val = getBytes(unsafe.Pointer(uintptr(i.ptr)+uintptr(e.valStart)), int(e.valSize)) 519 i.key = i.cachedBuf[e.keyStart:e.keyEnd] 520 if n := len(i.key) - 8; n >= 0 { 521 i.ikey.Trailer = binary.LittleEndian.Uint64(i.key[n:]) 522 i.ikey.UserKey = i.key[:n:n] 523 if i.globalSeqNum != 0 { 524 i.ikey.SetSeqNum(i.globalSeqNum) 525 } 526 } else { 527 i.ikey.Trailer = uint64(InternalKeyKindInvalid) 528 i.ikey.UserKey = nil 529 } 530 i.cached = i.cached[:n] 531 return &i.ikey, i.val 532 } 533 534 i.clearCache() 535 if i.offset <= 0 { 536 i.offset = -1 537 i.nextOffset = 0 538 return nil, nil 539 } 540 541 targetOffset := i.offset 542 var index int32 543 544 { 545 upper := i.numRestarts 546 for index < upper { 547 h := int32(uint(index+upper) >> 1) 548 offset := int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*h:])) 549 if offset < targetOffset { 550 index = h + 1 551 } else { 552 upper = h 553 } 554 } 555 } 556 557 i.offset = 0 558 if index > 0 { 559 i.offset = int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*(index-1):])) 560 } 561 562 i.readEntry() 563 564 for i.nextOffset < targetOffset { 565 i.cacheEntry() 566 i.offset = i.nextOffset 567 i.readEntry() 568 } 569 570 i.decodeInternalKey(i.key) 571 return &i.ikey, i.val 572 } 573 574 func (i *blockIter) Key() *InternalKey { 575 return &i.ikey 576 } 577 578 func (i *blockIter) Value() []byte { 579 return i.val 580 } 581 582 func (i *blockIter) Valid() bool { 583 return i.offset >= 0 && i.offset < i.restarts 584 } 585 586 func (i *blockIter) Error() error { 587 return nil 588 } 589 590 func (i *blockIter) Close() error { 591 i.cacheHandle.Release() 592 i.cacheHandle = lrucache.Handle{} 593 i.val = nil 594 return nil 595 } 596 597 func (i *blockIter) SetBounds(lower, upper []byte) { 598 panic("bitalosdb: SetBounds unimplemented") 599 } 600 601 type blockWriter struct { 602 restartInterval int 603 nEntries int 604 nextRestart int 605 buf []byte 606 restarts []uint32 607 curKey []byte 608 curValue []byte 609 prevKey []byte 610 tmp [4]byte 611 } 612 613 func (w *blockWriter) store(keySize int, value []byte) { 614 shared := 0 615 if w.nEntries == w.nextRestart { 616 w.nextRestart = w.nEntries + w.restartInterval 617 w.restarts = append(w.restarts, uint32(len(w.buf))) 618 } else { 619 n := len(w.curKey) 620 if n > len(w.prevKey) { 621 n = len(w.prevKey) 622 } 623 asUint64 := func(b []byte, i int) uint64 { 624 return binary.LittleEndian.Uint64(b[i:]) 625 } 626 for shared < n-7 && asUint64(w.curKey, shared) == asUint64(w.prevKey, shared) { 627 shared += 8 628 } 629 for shared < n && w.curKey[shared] == w.prevKey[shared] { 630 shared++ 631 } 632 } 633 634 needed := 3*binary.MaxVarintLen32 + len(w.curKey[shared:]) + len(value) 635 n := len(w.buf) 636 if cap(w.buf) < n+needed { 637 newCap := 2 * cap(w.buf) 638 if newCap == 0 { 639 newCap = 1024 640 } 641 for newCap < n+needed { 642 newCap *= 2 643 } 644 newBuf := make([]byte, n, newCap) 645 copy(newBuf, w.buf) 646 w.buf = newBuf 647 } 648 w.buf = w.buf[:n+needed] 649 650 { 651 x := uint32(shared) 652 for x >= 0x80 { 653 w.buf[n] = byte(x) | 0x80 654 x >>= 7 655 n++ 656 } 657 w.buf[n] = byte(x) 658 n++ 659 } 660 661 { 662 x := uint32(keySize - shared) 663 for x >= 0x80 { 664 w.buf[n] = byte(x) | 0x80 665 x >>= 7 666 n++ 667 } 668 w.buf[n] = byte(x) 669 n++ 670 } 671 672 { 673 x := uint32(len(value)) 674 for x >= 0x80 { 675 w.buf[n] = byte(x) | 0x80 676 x >>= 7 677 n++ 678 } 679 w.buf[n] = byte(x) 680 n++ 681 } 682 683 n += copy(w.buf[n:], w.curKey[shared:]) 684 n += copy(w.buf[n:], value) 685 w.buf = w.buf[:n] 686 687 w.curValue = w.buf[n-len(value):] 688 689 w.nEntries++ 690 } 691 692 func (w *blockWriter) add(key InternalKey, value []byte) { 693 w.curKey, w.prevKey = w.prevKey, w.curKey 694 695 size := key.Size() 696 if cap(w.curKey) < size { 697 w.curKey = make([]byte, 0, size*2) 698 } 699 w.curKey = w.curKey[:size] 700 key.Encode(w.curKey) 701 702 w.store(size, value) 703 } 704 705 func (w *blockWriter) finish() []byte { 706 // Write the restart points to the buffer. 707 if w.nEntries == 0 { 708 // Every block must have at least one restart point. 709 if cap(w.restarts) > 0 { 710 w.restarts = w.restarts[:1] 711 w.restarts[0] = 0 712 } else { 713 w.restarts = append(w.restarts, 0) 714 } 715 } 716 tmp4 := w.tmp[:4] 717 for _, x := range w.restarts { 718 binary.LittleEndian.PutUint32(tmp4, x) 719 w.buf = append(w.buf, tmp4...) 720 } 721 binary.LittleEndian.PutUint32(tmp4, uint32(len(w.restarts))) 722 w.buf = append(w.buf, tmp4...) 723 result := w.buf 724 725 // Reset the block state. 726 w.nEntries = 0 727 w.nextRestart = 0 728 w.buf = w.buf[:0] 729 w.restarts = w.restarts[:0] 730 return result 731 } 732 733 func (w *blockWriter) estimatedSize() int { 734 return len(w.buf) + 4*(len(w.restarts)+1) 735 }