github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/sstable/raw_block.go (about) 1 // Copyright 2018 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 package sstable 6 7 import ( 8 "encoding/binary" 9 "errors" 10 "sort" 11 "unsafe" 12 ) 13 14 type rawBlockWriter struct { 15 blockWriter 16 } 17 18 func (w *rawBlockWriter) add(key InternalKey, value []byte) { 19 w.curKey, w.prevKey = w.prevKey, w.curKey 20 21 size := len(key.UserKey) 22 if cap(w.curKey) < size { 23 w.curKey = make([]byte, 0, size*2) 24 } 25 w.curKey = w.curKey[:size] 26 copy(w.curKey, key.UserKey) 27 28 w.store(size, value) 29 } 30 31 // rawBlockIter is an iterator over a single block of data. Unlike blockIter, 32 // keys are stored in "raw" format (i.e. not as internal keys). Note that there 33 // is significant similarity between this code and the code in blockIter. Yet 34 // reducing duplication is difficult due to the blockIter being performance 35 // critical. 36 type rawBlockIter struct { 37 cmp Compare 38 offset int32 39 nextOffset int32 40 restarts int32 41 numRestarts int32 42 ptr unsafe.Pointer 43 data []byte 44 key, val []byte 45 ikey InternalKey 46 cached []blockEntry 47 cachedBuf []byte 48 err error 49 } 50 51 func newRawBlockIter(cmp Compare, block block) (*rawBlockIter, error) { 52 i := &rawBlockIter{} 53 return i, i.init(cmp, block) 54 } 55 56 func (i *rawBlockIter) init(cmp Compare, block block) error { 57 numRestarts := int32(binary.LittleEndian.Uint32(block[len(block)-4:])) 58 if numRestarts == 0 { 59 return errors.New("pebble/table: invalid table (block has no restart points)") 60 } 61 i.cmp = cmp 62 i.restarts = int32(len(block)) - 4*(1+numRestarts) 63 i.numRestarts = numRestarts 64 i.ptr = unsafe.Pointer(&block[0]) 65 i.data = block 66 if i.key == nil { 67 i.key = make([]byte, 0, 256) 68 } else { 69 i.key = i.key[:0] 70 } 71 i.val = nil 72 i.clearCache() 73 return nil 74 } 75 76 func (i *rawBlockIter) readEntry() { 77 ptr := unsafe.Pointer(uintptr(i.ptr) + uintptr(i.offset)) 78 shared, ptr := decodeVarint(ptr) 79 unshared, ptr := decodeVarint(ptr) 80 value, ptr := decodeVarint(ptr) 81 i.key = append(i.key[:shared], getBytes(ptr, int(unshared))...) 82 i.key = i.key[:len(i.key):len(i.key)] 83 ptr = unsafe.Pointer(uintptr(ptr) + uintptr(unshared)) 84 i.val = getBytes(ptr, int(value)) 85 i.nextOffset = int32(uintptr(ptr)-uintptr(i.ptr)) + int32(value) 86 } 87 88 func (i *rawBlockIter) loadEntry() { 89 i.readEntry() 90 i.ikey.UserKey = i.key 91 } 92 93 func (i *rawBlockIter) clearCache() { 94 i.cached = i.cached[:0] 95 i.cachedBuf = i.cachedBuf[:0] 96 } 97 98 func (i *rawBlockIter) cacheEntry() { 99 var valStart int32 100 valSize := int32(len(i.val)) 101 if valSize > 0 { 102 valStart = int32(uintptr(unsafe.Pointer(&i.val[0])) - uintptr(i.ptr)) 103 } 104 105 i.cached = append(i.cached, blockEntry{ 106 offset: i.offset, 107 keyStart: int32(len(i.cachedBuf)), 108 keyEnd: int32(len(i.cachedBuf) + len(i.key)), 109 valStart: valStart, 110 valSize: valSize, 111 }) 112 i.cachedBuf = append(i.cachedBuf, i.key...) 113 } 114 115 // SeekGE implements internalIterator.SeekGE, as documented in the pebble 116 // package. 117 func (i *rawBlockIter) SeekGE(key []byte) bool { 118 // Find the index of the smallest restart point whose key is > the key 119 // sought; index will be numRestarts if there is no such restart point. 120 i.offset = 0 121 index := sort.Search(int(i.numRestarts), func(j int) bool { 122 offset := int32(binary.LittleEndian.Uint32(i.data[int(i.restarts)+4*j:])) 123 // For a restart point, there are 0 bytes shared with the previous key. 124 // The varint encoding of 0 occupies 1 byte. 125 ptr := unsafe.Pointer(uintptr(i.ptr) + uintptr(offset+1)) 126 // Decode the key at that restart point, and compare it to the key sought. 127 v1, ptr := decodeVarint(ptr) 128 _, ptr = decodeVarint(ptr) 129 s := getBytes(ptr, int(v1)) 130 return i.cmp(key, s) < 0 131 }) 132 133 // Since keys are strictly increasing, if index > 0 then the restart point at 134 // index-1 will be the largest whose key is <= the key sought. If index == 135 // 0, then all keys in this block are larger than the key sought, and offset 136 // remains at zero. 137 if index > 0 { 138 i.offset = int32(binary.LittleEndian.Uint32(i.data[int(i.restarts)+4*(index-1):])) 139 } 140 i.loadEntry() 141 142 // Iterate from that restart point to somewhere >= the key sought. 143 for valid := i.Valid(); valid; valid = i.Next() { 144 if i.cmp(key, i.key) <= 0 { 145 break 146 } 147 } 148 return i.Valid() 149 } 150 151 // SeekPrefixGE implements internalIterator.SeekPrefixGE, as documented in the 152 // pebble package. 153 func (i *rawBlockIter) SeekPrefixGE(key []byte) bool { 154 // This should never be called as prefix iteration is never used with raw blocks. 155 panic("pebble: SeekPrefixGE unimplemented") 156 } 157 158 // SeekLT implements internalIterator.SeekLT, as documented in the pebble 159 // package. 160 func (i *rawBlockIter) SeekLT(key []byte) bool { 161 panic("pebble/table: SeekLT unimplemented") 162 } 163 164 // First implements internalIterator.First, as documented in the pebble 165 // package. 166 func (i *rawBlockIter) First() bool { 167 i.offset = 0 168 i.loadEntry() 169 return i.Valid() 170 } 171 172 // Last implements internalIterator.Last, as documented in the pebble package. 173 func (i *rawBlockIter) Last() bool { 174 // Seek forward from the last restart point. 175 i.offset = int32(binary.LittleEndian.Uint32(i.data[i.restarts+4*(i.numRestarts-1):])) 176 177 i.readEntry() 178 i.clearCache() 179 i.cacheEntry() 180 181 for i.nextOffset < i.restarts { 182 i.offset = i.nextOffset 183 i.readEntry() 184 i.cacheEntry() 185 } 186 187 i.ikey.UserKey = i.key 188 return i.Valid() 189 } 190 191 // Next implements internalIterator.Next, as documented in the pebble 192 // package. 193 func (i *rawBlockIter) Next() bool { 194 i.offset = i.nextOffset 195 if !i.Valid() { 196 return false 197 } 198 i.loadEntry() 199 return true 200 } 201 202 // Prev implements internalIterator.Prev, as documented in the pebble 203 // package. 204 func (i *rawBlockIter) Prev() bool { 205 if n := len(i.cached) - 1; n > 0 && i.cached[n].offset == i.offset { 206 i.nextOffset = i.offset 207 e := &i.cached[n-1] 208 i.offset = e.offset 209 i.val = getBytes(unsafe.Pointer(uintptr(i.ptr)+uintptr(e.valStart)), int(e.valSize)) 210 i.ikey.UserKey = i.cachedBuf[e.keyStart:e.keyEnd] 211 i.cached = i.cached[:n] 212 return true 213 } 214 215 if i.offset == 0 { 216 i.offset = -1 217 i.nextOffset = 0 218 return false 219 } 220 221 targetOffset := i.offset 222 index := sort.Search(int(i.numRestarts), func(j int) bool { 223 offset := int32(binary.LittleEndian.Uint32(i.data[int(i.restarts)+4*j:])) 224 return offset >= targetOffset 225 }) 226 i.offset = 0 227 if index > 0 { 228 i.offset = int32(binary.LittleEndian.Uint32(i.data[int(i.restarts)+4*(index-1):])) 229 } 230 231 i.readEntry() 232 i.clearCache() 233 i.cacheEntry() 234 235 for i.nextOffset < targetOffset { 236 i.offset = i.nextOffset 237 i.readEntry() 238 i.cacheEntry() 239 } 240 241 i.ikey.UserKey = i.key 242 return true 243 } 244 245 // Key implements internalIterator.Key, as documented in the pebble package. 246 func (i *rawBlockIter) Key() InternalKey { 247 return i.ikey 248 } 249 250 // Value implements internalIterator.Value, as documented in the pebble 251 // package. 252 func (i *rawBlockIter) Value() []byte { 253 return i.val 254 } 255 256 func (i *rawBlockIter) valueOffset() uint64 { 257 ptr := unsafe.Pointer(uintptr(i.ptr) + uintptr(i.offset)) 258 shared, ptr := decodeVarint(ptr) 259 unshared, _ := decodeVarint(ptr) 260 return uint64(i.offset) + uint64(shared+unshared) 261 } 262 263 // Valid implements internalIterator.Valid, as documented in the pebble 264 // package. 265 func (i *rawBlockIter) Valid() bool { 266 return i.offset >= 0 && i.offset < i.restarts 267 } 268 269 // Error implements internalIterator.Error, as documented in the pebble 270 // package. 271 func (i *rawBlockIter) Error() error { 272 return i.err 273 } 274 275 // Close implements internalIterator.Close, as documented in the pebble 276 // package. 277 func (i *rawBlockIter) Close() error { 278 i.val = nil 279 return i.err 280 }