github.com/ethersphere/bee/v2@v2.2.0/pkg/shed/index.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package shed 18 19 import ( 20 "bytes" 21 "errors" 22 "fmt" 23 24 "github.com/syndtr/goleveldb/leveldb" 25 "github.com/syndtr/goleveldb/leveldb/iterator" 26 ) 27 28 // Item holds fields relevant to Swarm Chunk data and metadata. 29 // All information required for swarm storage and operations 30 // on that storage must be defined here. 31 // This structure is logically connected to swarm storage, 32 // the only part of this package that is not generalized, 33 // mostly for performance reasons. 34 // 35 // Item is a type that is used for retrieving, storing and encoding 36 // chunk data and metadata. It is passed as an argument to Index encoding 37 // functions, get function and put function. 38 // But it is also returned with additional data from get function call 39 // and as the argument in iterator function definition. 40 type Item struct { 41 Address []byte 42 Data []byte 43 Location []byte // Location of the chunk in sharky context 44 AccessTimestamp int64 45 StoreTimestamp int64 46 BinID uint64 47 PinCounter uint64 // maintains the no of time a chunk is pinned 48 Tag uint32 49 BatchID []byte // postage batch ID 50 Index []byte // postage stamp within-batch: index 51 Timestamp []byte // postage stamp validity 52 Sig []byte // postage stamp signature 53 BucketDepth uint8 // postage batch bucket depth (for collision sets) 54 Depth uint8 // postage batch depth (for size) 55 Radius uint8 // postage batch reserve radius, po upto and excluding which chunks are unpinned 56 Immutable bool // whether postage batch can be diluted and drained, and indexes overwritten - nullable bool 57 } 58 59 // Merge is a helper method to construct a new 60 // Item by filling up fields with default values 61 // of a particular Item with values from another one. 62 func (i Item) Merge(i2 Item) Item { 63 if i.Address == nil { 64 i.Address = i2.Address 65 } 66 if i.Data == nil { 67 i.Data = i2.Data 68 } 69 if i.Location == nil { 70 i.Location = i2.Location 71 } 72 if i.AccessTimestamp == 0 { 73 i.AccessTimestamp = i2.AccessTimestamp 74 } 75 if i.StoreTimestamp == 0 { 76 i.StoreTimestamp = i2.StoreTimestamp 77 } 78 if i.BinID == 0 { 79 i.BinID = i2.BinID 80 } 81 if i.PinCounter == 0 { 82 i.PinCounter = i2.PinCounter 83 } 84 if i.Tag == 0 { 85 i.Tag = i2.Tag 86 } 87 if len(i.BatchID) == 0 { 88 i.BatchID = i2.BatchID 89 } 90 if len(i.Index) == 0 { 91 i.Index = i2.Index 92 } 93 if len(i.Timestamp) == 0 { 94 i.Timestamp = i2.Timestamp 95 } 96 if len(i.Sig) == 0 { 97 i.Sig = i2.Sig 98 } 99 if i.BucketDepth == 0 { 100 i.BucketDepth = i2.BucketDepth 101 } 102 if i.Depth == 0 { 103 i.Depth = i2.Depth 104 } 105 if i.Radius == 0 { 106 i.Radius = i2.Radius 107 } 108 if !i.Immutable { 109 i.Immutable = i2.Immutable 110 } 111 return i 112 } 113 114 // Index represents a set of LevelDB key value pairs that have common 115 // prefix. It holds functions for encoding and decoding keys and values 116 // to provide transparent actions on saved data which inclide: 117 // - getting a particular Item 118 // - saving a particular Item 119 // - iterating over a sorted LevelDB keys 120 // It implements IndexIteratorInterface interface. 121 type Index struct { 122 db *DB 123 prefix []byte 124 encodeKeyFunc func(fields Item) (key []byte, err error) 125 decodeKeyFunc func(key []byte) (e Item, err error) 126 encodeValueFunc func(fields Item) (value []byte, err error) 127 decodeValueFunc func(keyFields Item, value []byte) (e Item, err error) 128 } 129 130 // IndexFuncs structure defines functions for encoding and decoding 131 // LevelDB keys and values for a specific index. 132 type IndexFuncs struct { 133 EncodeKey func(fields Item) (key []byte, err error) 134 DecodeKey func(key []byte) (e Item, err error) 135 EncodeValue func(fields Item) (value []byte, err error) 136 DecodeValue func(keyFields Item, value []byte) (e Item, err error) 137 } 138 139 // NewIndex returns a new Index instance with defined name and 140 // encoding functions. The name must be unique and will be validated 141 // on database schema for a key prefix byte. 142 func (db *DB) NewIndex(name string, funcs IndexFuncs) (f Index, err error) { 143 id, err := db.schemaIndexPrefix(name) 144 if err != nil { 145 return f, fmt.Errorf("get schema index prefix: %w", err) 146 } 147 prefix := []byte{id} 148 return Index{ 149 db: db, 150 prefix: prefix, 151 // This function adjusts Index LevelDB key 152 // by appending the provided index id byte. 153 // This is needed to avoid collisions between keys of different 154 // indexes as all index ids are unique. 155 encodeKeyFunc: func(e Item) (key []byte, err error) { 156 key, err = funcs.EncodeKey(e) 157 if err != nil { 158 return nil, err 159 } 160 return append(append(make([]byte, 0, len(key)+1), prefix...), key...), nil 161 }, 162 // This function reverses the encodeKeyFunc constructed key 163 // to transparently work with index keys without their index ids. 164 // It assumes that index keys are prefixed with only one byte. 165 decodeKeyFunc: func(key []byte) (e Item, err error) { 166 return funcs.DecodeKey(key[1:]) 167 }, 168 encodeValueFunc: funcs.EncodeValue, 169 decodeValueFunc: funcs.DecodeValue, 170 }, nil 171 } 172 173 // ItemKey accepts an Item and returns generated key for it. 174 func (f Index) ItemKey(item Item) (key []byte, err error) { 175 return f.encodeKeyFunc(item) 176 } 177 178 // Get accepts key fields represented as Item to retrieve a 179 // value from the index and return maximum available information 180 // from the index represented as another Item. 181 func (f Index) Get(keyFields Item) (out Item, err error) { 182 key, err := f.encodeKeyFunc(keyFields) 183 if err != nil { 184 return out, fmt.Errorf("encode key: %w", err) 185 } 186 value, err := f.db.Get(key) 187 if err != nil { 188 return out, fmt.Errorf("get value: %w", err) 189 } 190 out, err = f.decodeValueFunc(keyFields, value) 191 if err != nil { 192 return out, fmt.Errorf("decode value: %w", err) 193 } 194 return out.Merge(keyFields), nil 195 } 196 197 // Fill populates fields on provided items that are part of the 198 // encoded value by getting them based on information passed in their 199 // fields. Every item must have all fields needed for encoding the 200 // key set. The passed slice items will be changed so that they 201 // contain data from the index values. No new slice is allocated. 202 // This function uses a single leveldb snapshot. 203 func (f Index) Fill(items []Item) (err error) { 204 snapshot, err := f.db.ldb.GetSnapshot() 205 if err != nil { 206 return fmt.Errorf("get snapshot: %w", err) 207 } 208 defer snapshot.Release() 209 210 for i, item := range items { 211 key, err := f.encodeKeyFunc(item) 212 if err != nil { 213 return fmt.Errorf("encode key: %w", err) 214 } 215 value, err := snapshot.Get(key, nil) 216 if err != nil { 217 return fmt.Errorf("get value: %w", err) 218 } 219 v, err := f.decodeValueFunc(item, value) 220 if err != nil { 221 return fmt.Errorf("decode value: %w", err) 222 } 223 items[i] = v.Merge(item) 224 } 225 return nil 226 } 227 228 // Has accepts key fields represented as Item to check 229 // if there this Item's encoded key is stored in 230 // the index. 231 func (f Index) Has(keyFields Item) (bool, error) { 232 key, err := f.encodeKeyFunc(keyFields) 233 if err != nil { 234 return false, fmt.Errorf("encode key: %w", err) 235 } 236 return f.db.Has(key) 237 } 238 239 // HasMulti accepts multiple multiple key fields represented as Item to check if 240 // there this Item's encoded key is stored in the index for each of them. 241 func (f Index) HasMulti(items ...Item) ([]bool, error) { 242 have := make([]bool, len(items)) 243 snapshot, err := f.db.ldb.GetSnapshot() 244 if err != nil { 245 return nil, fmt.Errorf("get snapshot: %w", err) 246 } 247 defer snapshot.Release() 248 for i, keyFields := range items { 249 key, err := f.encodeKeyFunc(keyFields) 250 if err != nil { 251 return nil, fmt.Errorf("encode key for address %x: %w", keyFields.Address, err) 252 } 253 have[i], err = snapshot.Has(key, nil) 254 if err != nil { 255 return nil, fmt.Errorf("has key for address %x: %w", keyFields.Address, err) 256 } 257 } 258 return have, nil 259 } 260 261 // Put accepts Item to encode information from it 262 // and save it to the database. 263 func (f Index) Put(i Item) (err error) { 264 key, err := f.encodeKeyFunc(i) 265 if err != nil { 266 return fmt.Errorf("encode key: %w", err) 267 } 268 value, err := f.encodeValueFunc(i) 269 if err != nil { 270 return fmt.Errorf("encode value: %w", err) 271 } 272 return f.db.Put(key, value) 273 } 274 275 // PutInBatch is the same as Put method, but it just 276 // saves the key/value pair to the batch instead 277 // directly to the database. 278 func (f Index) PutInBatch(batch *leveldb.Batch, i Item) (err error) { 279 key, err := f.encodeKeyFunc(i) 280 if err != nil { 281 return fmt.Errorf("encode key: %w", err) 282 } 283 value, err := f.encodeValueFunc(i) 284 if err != nil { 285 return fmt.Errorf("encode value: %w", err) 286 } 287 batch.Put(key, value) 288 return nil 289 } 290 291 // Delete accepts Item to remove a key/value pair 292 // from the database based on its fields. 293 func (f Index) Delete(keyFields Item) (err error) { 294 key, err := f.encodeKeyFunc(keyFields) 295 if err != nil { 296 return fmt.Errorf("encode key: %w", err) 297 } 298 return f.db.Delete(key) 299 } 300 301 // DeleteInBatch is the same as Delete just the operation 302 // is performed on the batch instead on the database. 303 func (f Index) DeleteInBatch(batch *leveldb.Batch, keyFields Item) (err error) { 304 key, err := f.encodeKeyFunc(keyFields) 305 if err != nil { 306 return fmt.Errorf("encode key: %w", err) 307 } 308 batch.Delete(key) 309 return nil 310 } 311 312 // IndexIterFunc is a callback on every Item that is decoded 313 // by iterating on an Index keys. 314 // By returning a true for stop variable, iteration will 315 // stop, and by returning the error, that error will be 316 // propagated to the called iterator method on Index. 317 type IndexIterFunc func(item Item) (stop bool, err error) 318 319 // IterateOptions defines optional parameters for Iterate function. 320 type IterateOptions struct { 321 // StartFrom is the Item to start the iteration from. 322 StartFrom *Item 323 // If SkipStartFromItem is true, StartFrom item will not 324 // be iterated on. 325 SkipStartFromItem bool 326 // Iterate over items which keys have a common prefix. 327 Prefix []byte 328 // Iterate over items in reverse order. 329 Reverse bool 330 } 331 332 // Iterate function iterates over keys of the Index. 333 // If IterateOptions is nil, the iterations is over all keys. 334 func (f Index) Iterate(fn IndexIterFunc, options *IterateOptions) (err error) { 335 if options == nil { 336 options = new(IterateOptions) 337 } 338 // construct a prefix with Index prefix and optional common key prefix 339 prefix := append(f.prefix, options.Prefix...) 340 // start from the prefix 341 startKey := prefix 342 if options.StartFrom != nil { 343 // start from the provided StartFrom Item key value 344 startKey, err = f.encodeKeyFunc(*options.StartFrom) 345 if err != nil { 346 return fmt.Errorf("encode key: %w", err) 347 } 348 } 349 350 it := f.db.NewIterator() 351 defer it.Release() 352 353 var ok bool 354 355 // move the cursor to the start key 356 ok = it.Seek(startKey) 357 358 if !options.Reverse { 359 if !ok { 360 // stop iterator if seek has failed 361 return it.Error() 362 } 363 } else { 364 // reverse seeker 365 if options.StartFrom != nil { 366 if !ok { 367 return it.Error() 368 } 369 } else { 370 // find last key for this index (and prefix) 371 372 // move cursor to last key 373 ok = it.Last() 374 if !ok { 375 return it.Error() 376 } 377 378 if lastKeyHasPrefix := bytes.HasPrefix(it.Key(), prefix); !lastKeyHasPrefix { 379 // increment last prefix byte (that is not 0xFF) to try to find last key 380 incrementedPrefix := bytesIncrement(prefix) 381 if incrementedPrefix == nil { 382 return fmt.Errorf("index iterator invalid prefix: %v -> %v", prefix, string(prefix)) 383 } 384 385 // should find first key after prefix (same or different index) 386 ok = it.Seek(incrementedPrefix) 387 if !ok { 388 return it.Error() 389 } 390 391 // previous key should have proper prefix 392 ok = it.Prev() 393 if !ok { 394 return it.Error() 395 } 396 } 397 } 398 } 399 400 itSeekerFn := it.Next 401 if options.Reverse { 402 itSeekerFn = it.Prev 403 } 404 if options.SkipStartFromItem && bytes.Equal(startKey, it.Key()) { 405 // skip the start from Item if it is the first key 406 // and it is explicitly configured to skip it 407 ok = itSeekerFn() 408 } 409 for ; ok; ok = itSeekerFn() { 410 item, err := f.itemFromIterator(it, prefix) 411 if err != nil { 412 if errors.Is(err, leveldb.ErrNotFound) { 413 break 414 } 415 return fmt.Errorf("get item from iterator: %w", err) 416 } 417 stop, err := fn(item) 418 if err != nil { 419 return fmt.Errorf("index iterator function: %w", err) 420 } 421 if stop { 422 break 423 } 424 } 425 return it.Error() 426 } 427 428 // bytesIncrement increments the last byte that is not 0xFF, and returns 429 // a new byte array truncated after the position that was incremented. 430 func bytesIncrement(bytes []byte) []byte { 431 b := append(bytes[:0:0], bytes...) 432 433 for i := len(bytes) - 1; i >= 0; { 434 if b[i] == 0xFF { 435 i-- 436 continue 437 } 438 439 // found byte smaller than 0xFF: increment and truncate 440 b[i]++ 441 return b[:i+1] 442 } 443 444 // input contained only 0xFF bytes 445 return nil 446 } 447 448 // First returns the first item in the Index which encoded key starts with a prefix. 449 // If the prefix is nil, the first element of the whole index is returned. 450 // If Index has no elements, a leveldb.ErrNotFound error is returned. 451 func (f Index) First(prefix []byte) (i Item, err error) { 452 it := f.db.NewIterator() 453 defer it.Release() 454 455 totalPrefix := append(f.prefix, prefix...) 456 it.Seek(totalPrefix) 457 458 return f.itemFromIterator(it, totalPrefix) 459 } 460 461 // itemFromIterator returns the Item from the current iterator position. 462 // If the complete encoded key does not start with totalPrefix, 463 // leveldb.ErrNotFound is returned. Value for totalPrefix must start with 464 // Index prefix. 465 func (f Index) itemFromIterator(it iterator.Iterator, totalPrefix []byte) (i Item, err error) { 466 key := it.Key() 467 if !bytes.HasPrefix(key, totalPrefix) { 468 return i, leveldb.ErrNotFound 469 } 470 // create a copy of key byte slice not to share leveldb underlying slice array 471 keyItem, err := f.decodeKeyFunc(append([]byte(nil), key...)) 472 if err != nil { 473 return i, fmt.Errorf("decode key: %w", err) 474 } 475 // create a copy of value byte slice not to share leveldb underlying slice array 476 valueItem, err := f.decodeValueFunc(keyItem, append([]byte(nil), it.Value()...)) 477 if err != nil { 478 return i, fmt.Errorf("decode value: %w", err) 479 } 480 return keyItem.Merge(valueItem), it.Error() 481 } 482 483 // Last returns the last item in the Index which encoded key starts with a prefix. 484 // If the prefix is nil, the last element of the whole index is returned. 485 // If Index has no elements, a leveldb.ErrNotFound error is returned. 486 func (f Index) Last(prefix []byte) (i Item, err error) { 487 it := f.db.NewIterator() 488 defer it.Release() 489 490 // get the next prefix in line 491 // since leveldb iterator Seek seeks to the 492 // next key if the key that it seeks to is not found 493 // and by getting the previous key, the last one for the 494 // actual prefix is found 495 nextPrefix := incByteSlice(prefix) 496 l := len(prefix) 497 498 if l > 0 && nextPrefix != nil { 499 it.Seek(append(f.prefix, nextPrefix...)) 500 it.Prev() 501 } else { 502 it.Last() 503 } 504 505 totalPrefix := append(f.prefix, prefix...) 506 return f.itemFromIterator(it, totalPrefix) 507 } 508 509 // incByteSlice returns the byte slice of the same size 510 // of the provided one that is by one incremented in its 511 // total value. If all bytes in provided slice are equal 512 // to 255 a nil slice would be returned indicating that 513 // increment can not happen for the same length. 514 func incByteSlice(b []byte) (next []byte) { 515 l := len(b) 516 next = make([]byte, l) 517 copy(next, b) 518 for i := l - 1; i >= 0; i-- { 519 if b[i] == 255 { 520 next[i] = 0 521 } else { 522 next[i] = b[i] + 1 523 return next 524 } 525 } 526 return nil 527 } 528 529 // Count returns the number of items in index. 530 func (f Index) Count() (count int, err error) { 531 it := f.db.NewIterator() 532 defer it.Release() 533 534 for ok := it.Seek(f.prefix); ok; ok = it.Next() { 535 key := it.Key() 536 if key[0] != f.prefix[0] { 537 break 538 } 539 count++ 540 } 541 return count, it.Error() 542 } 543 544 // CountFrom returns the number of items in index keys 545 // starting from the key encoded from the provided Item. 546 func (f Index) CountFrom(start Item) (count int, err error) { 547 startKey, err := f.encodeKeyFunc(start) 548 if err != nil { 549 return 0, fmt.Errorf("encode key: %w", err) 550 } 551 it := f.db.NewIterator() 552 defer it.Release() 553 554 for ok := it.Seek(startKey); ok; ok = it.Next() { 555 key := it.Key() 556 if key[0] != f.prefix[0] { 557 break 558 } 559 count++ 560 } 561 return count, it.Error() 562 }