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  }