| 421 | } |
| 422 | |
| 423 | func (a *segment) findKeyPos(key []byte) (int, error) { |
| 424 | kvs := a.kvs |
| 425 | buf := a.buf |
| 426 | |
| 427 | if len(kvs) < 2 { |
| 428 | return -1, nil |
| 429 | } |
| 430 | |
| 431 | startKeyLen := int((maskKeyLength & kvs[0]) >> 32) |
| 432 | startKeyBeg := int(kvs[1]) |
| 433 | if startKeyBeg+startKeyLen > len(buf) { |
| 434 | return -1, ErrSegmentCorrupted |
| 435 | } |
| 436 | // If key smaller than smallest key, return early. |
| 437 | startCmp := bytes.Compare(key, buf[startKeyBeg:startKeyBeg+startKeyLen]) |
| 438 | if startCmp < 0 { |
| 439 | return -1, nil |
| 440 | } |
| 441 | |
| 442 | i, j := a.searchIndex(key) |
| 443 | if i == j { |
| 444 | return -1, nil |
| 445 | } |
| 446 | |
| 447 | // additional best effort guard against mmap buf beyond eof |
| 448 | x := 2 * (j - 1) |
| 449 | if x+1 > len(kvs) { |
| 450 | return -1, ErrSegmentCorrupted |
| 451 | } |
| 452 | endKeyLen := int((maskKeyLength & kvs[x]) >> 32) |
| 453 | endKeyBeg := int(kvs[x+1]) |
| 454 | if endKeyBeg+endKeyLen > len(buf) { |
| 455 | return -1, ErrSegmentCorrupted |
| 456 | } |
| 457 | |
| 458 | for i < j { |
| 459 | h := i + (j-i)/2 // Keep i <= h < j. |
| 460 | x := h * 2 |
| 461 | klen := int((maskKeyLength & kvs[x]) >> 32) |
| 462 | kbeg := int(kvs[x+1]) |
| 463 | if kbeg+klen > len(buf) { |
| 464 | return -1, ErrSegmentCorrupted |
| 465 | } |
| 466 | |
| 467 | cmp := bytes.Compare(buf[kbeg:kbeg+klen], key) |
| 468 | if cmp == 0 { |
| 469 | return h, nil |
| 470 | } else if cmp < 0 { |
| 471 | i = h + 1 |
| 472 | } else { |
| 473 | j = h |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | return -1, nil |
| 478 | } |
| 479 | |
| 480 | // FindStartKeyInclusivePos() returns the logical entry position for |