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  }