github.com/daeglee/go-ethereum@v0.0.0-20190504220456-cad3e8d18e9b/swarm/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  
    22  	"github.com/syndtr/goleveldb/leveldb"
    23  	"github.com/syndtr/goleveldb/leveldb/iterator"
    24  )
    25  
    26  // Item holds fields relevant to Swarm Chunk data and metadata.
    27  // All information required for swarm storage and operations
    28  // on that storage must be defined here.
    29  // This structure is logically connected to swarm storage,
    30  // the only part of this package that is not generalized,
    31  // mostly for performance reasons.
    32  //
    33  // Item is a type that is used for retrieving, storing and encoding
    34  // chunk data and metadata. It is passed as an argument to Index encoding
    35  // functions, get function and put function.
    36  // But it is also returned with additional data from get function call
    37  // and as the argument in iterator function definition.
    38  type Item struct {
    39  	Address         []byte
    40  	Data            []byte
    41  	AccessTimestamp int64
    42  	StoreTimestamp  int64
    43  	// UseMockStore is a pointer to identify
    44  	// an unset state of the field in Join function.
    45  	UseMockStore *bool
    46  }
    47  
    48  // Merge is a helper method to construct a new
    49  // Item by filling up fields with default values
    50  // of a particular Item with values from another one.
    51  func (i Item) Merge(i2 Item) (new Item) {
    52  	if i.Address == nil {
    53  		i.Address = i2.Address
    54  	}
    55  	if i.Data == nil {
    56  		i.Data = i2.Data
    57  	}
    58  	if i.AccessTimestamp == 0 {
    59  		i.AccessTimestamp = i2.AccessTimestamp
    60  	}
    61  	if i.StoreTimestamp == 0 {
    62  		i.StoreTimestamp = i2.StoreTimestamp
    63  	}
    64  	if i.UseMockStore == nil {
    65  		i.UseMockStore = i2.UseMockStore
    66  	}
    67  	return i
    68  }
    69  
    70  // Index represents a set of LevelDB key value pairs that have common
    71  // prefix. It holds functions for encoding and decoding keys and values
    72  // to provide transparent actions on saved data which inclide:
    73  // - getting a particular Item
    74  // - saving a particular Item
    75  // - iterating over a sorted LevelDB keys
    76  // It implements IndexIteratorInterface interface.
    77  type Index struct {
    78  	db              *DB
    79  	prefix          []byte
    80  	encodeKeyFunc   func(fields Item) (key []byte, err error)
    81  	decodeKeyFunc   func(key []byte) (e Item, err error)
    82  	encodeValueFunc func(fields Item) (value []byte, err error)
    83  	decodeValueFunc func(keyFields Item, value []byte) (e Item, err error)
    84  }
    85  
    86  // IndexFuncs structure defines functions for encoding and decoding
    87  // LevelDB keys and values for a specific index.
    88  type IndexFuncs struct {
    89  	EncodeKey   func(fields Item) (key []byte, err error)
    90  	DecodeKey   func(key []byte) (e Item, err error)
    91  	EncodeValue func(fields Item) (value []byte, err error)
    92  	DecodeValue func(keyFields Item, value []byte) (e Item, err error)
    93  }
    94  
    95  // NewIndex returns a new Index instance with defined name and
    96  // encoding functions. The name must be unique and will be validated
    97  // on database schema for a key prefix byte.
    98  func (db *DB) NewIndex(name string, funcs IndexFuncs) (f Index, err error) {
    99  	id, err := db.schemaIndexPrefix(name)
   100  	if err != nil {
   101  		return f, err
   102  	}
   103  	prefix := []byte{id}
   104  	return Index{
   105  		db:     db,
   106  		prefix: prefix,
   107  		// This function adjusts Index LevelDB key
   108  		// by appending the provided index id byte.
   109  		// This is needed to avoid collisions between keys of different
   110  		// indexes as all index ids are unique.
   111  		encodeKeyFunc: func(e Item) (key []byte, err error) {
   112  			key, err = funcs.EncodeKey(e)
   113  			if err != nil {
   114  				return nil, err
   115  			}
   116  			return append(append(make([]byte, 0, len(key)+1), prefix...), key...), nil
   117  		},
   118  		// This function reverses the encodeKeyFunc constructed key
   119  		// to transparently work with index keys without their index ids.
   120  		// It assumes that index keys are prefixed with only one byte.
   121  		decodeKeyFunc: func(key []byte) (e Item, err error) {
   122  			return funcs.DecodeKey(key[1:])
   123  		},
   124  		encodeValueFunc: funcs.EncodeValue,
   125  		decodeValueFunc: funcs.DecodeValue,
   126  	}, nil
   127  }
   128  
   129  // Get accepts key fields represented as Item to retrieve a
   130  // value from the index and return maximum available information
   131  // from the index represented as another Item.
   132  func (f Index) Get(keyFields Item) (out Item, err error) {
   133  	key, err := f.encodeKeyFunc(keyFields)
   134  	if err != nil {
   135  		return out, err
   136  	}
   137  	value, err := f.db.Get(key)
   138  	if err != nil {
   139  		return out, err
   140  	}
   141  	out, err = f.decodeValueFunc(keyFields, value)
   142  	if err != nil {
   143  		return out, err
   144  	}
   145  	return out.Merge(keyFields), nil
   146  }
   147  
   148  // Has accepts key fields represented as Item to check
   149  // if there this Item's encoded key is stored in
   150  // the index.
   151  func (f Index) Has(keyFields Item) (bool, error) {
   152  	key, err := f.encodeKeyFunc(keyFields)
   153  	if err != nil {
   154  		return false, err
   155  	}
   156  	return f.db.Has(key)
   157  }
   158  
   159  // Put accepts Item to encode information from it
   160  // and save it to the database.
   161  func (f Index) Put(i Item) (err error) {
   162  	key, err := f.encodeKeyFunc(i)
   163  	if err != nil {
   164  		return err
   165  	}
   166  	value, err := f.encodeValueFunc(i)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	return f.db.Put(key, value)
   171  }
   172  
   173  // PutInBatch is the same as Put method, but it just
   174  // saves the key/value pair to the batch instead
   175  // directly to the database.
   176  func (f Index) PutInBatch(batch *leveldb.Batch, i Item) (err error) {
   177  	key, err := f.encodeKeyFunc(i)
   178  	if err != nil {
   179  		return err
   180  	}
   181  	value, err := f.encodeValueFunc(i)
   182  	if err != nil {
   183  		return err
   184  	}
   185  	batch.Put(key, value)
   186  	return nil
   187  }
   188  
   189  // Delete accepts Item to remove a key/value pair
   190  // from the database based on its fields.
   191  func (f Index) Delete(keyFields Item) (err error) {
   192  	key, err := f.encodeKeyFunc(keyFields)
   193  	if err != nil {
   194  		return err
   195  	}
   196  	return f.db.Delete(key)
   197  }
   198  
   199  // DeleteInBatch is the same as Delete just the operation
   200  // is performed on the batch instead on the database.
   201  func (f Index) DeleteInBatch(batch *leveldb.Batch, keyFields Item) (err error) {
   202  	key, err := f.encodeKeyFunc(keyFields)
   203  	if err != nil {
   204  		return err
   205  	}
   206  	batch.Delete(key)
   207  	return nil
   208  }
   209  
   210  // IndexIterFunc is a callback on every Item that is decoded
   211  // by iterating on an Index keys.
   212  // By returning a true for stop variable, iteration will
   213  // stop, and by returning the error, that error will be
   214  // propagated to the called iterator method on Index.
   215  type IndexIterFunc func(item Item) (stop bool, err error)
   216  
   217  // IterateOptions defines optional parameters for Iterate function.
   218  type IterateOptions struct {
   219  	// StartFrom is the Item to start the iteration from.
   220  	StartFrom *Item
   221  	// If SkipStartFromItem is true, StartFrom item will not
   222  	// be iterated on.
   223  	SkipStartFromItem bool
   224  	// Iterate over items which keys have a common prefix.
   225  	Prefix []byte
   226  }
   227  
   228  // Iterate function iterates over keys of the Index.
   229  // If IterateOptions is nil, the iterations is over all keys.
   230  func (f Index) Iterate(fn IndexIterFunc, options *IterateOptions) (err error) {
   231  	if options == nil {
   232  		options = new(IterateOptions)
   233  	}
   234  	// construct a prefix with Index prefix and optional common key prefix
   235  	prefix := append(f.prefix, options.Prefix...)
   236  	// start from the prefix
   237  	startKey := prefix
   238  	if options.StartFrom != nil {
   239  		// start from the provided StartFrom Item key value
   240  		startKey, err = f.encodeKeyFunc(*options.StartFrom)
   241  		if err != nil {
   242  			return err
   243  		}
   244  	}
   245  	it := f.db.NewIterator()
   246  	defer it.Release()
   247  
   248  	// move the cursor to the start key
   249  	ok := it.Seek(startKey)
   250  	if !ok {
   251  		// stop iterator if seek has failed
   252  		return it.Error()
   253  	}
   254  	if options.SkipStartFromItem && bytes.Equal(startKey, it.Key()) {
   255  		// skip the start from Item if it is the first key
   256  		// and it is explicitly configured to skip it
   257  		ok = it.Next()
   258  	}
   259  	for ; ok; ok = it.Next() {
   260  		item, err := f.itemFromIterator(it, prefix)
   261  		if err != nil {
   262  			if err == leveldb.ErrNotFound {
   263  				break
   264  			}
   265  			return err
   266  		}
   267  		stop, err := fn(item)
   268  		if err != nil {
   269  			return err
   270  		}
   271  		if stop {
   272  			break
   273  		}
   274  	}
   275  	return it.Error()
   276  }
   277  
   278  // First returns the first item in the Index which encoded key starts with a prefix.
   279  // If the prefix is nil, the first element of the whole index is returned.
   280  // If Index has no elements, a leveldb.ErrNotFound error is returned.
   281  func (f Index) First(prefix []byte) (i Item, err error) {
   282  	it := f.db.NewIterator()
   283  	defer it.Release()
   284  
   285  	totalPrefix := append(f.prefix, prefix...)
   286  	it.Seek(totalPrefix)
   287  
   288  	return f.itemFromIterator(it, totalPrefix)
   289  }
   290  
   291  // itemFromIterator returns the Item from the current iterator position.
   292  // If the complete encoded key does not start with totalPrefix,
   293  // leveldb.ErrNotFound is returned. Value for totalPrefix must start with
   294  // Index prefix.
   295  func (f Index) itemFromIterator(it iterator.Iterator, totalPrefix []byte) (i Item, err error) {
   296  	key := it.Key()
   297  	if !bytes.HasPrefix(key, totalPrefix) {
   298  		return i, leveldb.ErrNotFound
   299  	}
   300  	// create a copy of key byte slice not to share leveldb underlaying slice array
   301  	keyItem, err := f.decodeKeyFunc(append([]byte(nil), key...))
   302  	if err != nil {
   303  		return i, err
   304  	}
   305  	// create a copy of value byte slice not to share leveldb underlaying slice array
   306  	valueItem, err := f.decodeValueFunc(keyItem, append([]byte(nil), it.Value()...))
   307  	if err != nil {
   308  		return i, err
   309  	}
   310  	return keyItem.Merge(valueItem), it.Error()
   311  }
   312  
   313  // Last returns the last item in the Index which encoded key starts with a prefix.
   314  // If the prefix is nil, the last element of the whole index is returned.
   315  // If Index has no elements, a leveldb.ErrNotFound error is returned.
   316  func (f Index) Last(prefix []byte) (i Item, err error) {
   317  	it := f.db.NewIterator()
   318  	defer it.Release()
   319  
   320  	// get the next prefix in line
   321  	// since leveldb iterator Seek seeks to the
   322  	// next key if the key that it seeks to is not found
   323  	// and by getting the previous key, the last one for the
   324  	// actual prefix is found
   325  	nextPrefix := incByteSlice(prefix)
   326  	l := len(prefix)
   327  
   328  	if l > 0 && nextPrefix != nil {
   329  		it.Seek(append(f.prefix, nextPrefix...))
   330  		it.Prev()
   331  	} else {
   332  		it.Last()
   333  	}
   334  
   335  	totalPrefix := append(f.prefix, prefix...)
   336  	return f.itemFromIterator(it, totalPrefix)
   337  }
   338  
   339  // incByteSlice returns the byte slice of the same size
   340  // of the provided one that is by one incremented in its
   341  // total value. If all bytes in provided slice are equal
   342  // to 255 a nil slice would be returned indicating that
   343  // increment can not happen for the same length.
   344  func incByteSlice(b []byte) (next []byte) {
   345  	l := len(b)
   346  	next = make([]byte, l)
   347  	copy(next, b)
   348  	for i := l - 1; i >= 0; i-- {
   349  		if b[i] == 255 {
   350  			next[i] = 0
   351  		} else {
   352  			next[i] = b[i] + 1
   353  			return next
   354  		}
   355  	}
   356  	return nil
   357  }
   358  
   359  // Count returns the number of items in index.
   360  func (f Index) Count() (count int, err error) {
   361  	it := f.db.NewIterator()
   362  	defer it.Release()
   363  
   364  	for ok := it.Seek(f.prefix); ok; ok = it.Next() {
   365  		key := it.Key()
   366  		if key[0] != f.prefix[0] {
   367  			break
   368  		}
   369  		count++
   370  	}
   371  	return count, it.Error()
   372  }
   373  
   374  // CountFrom returns the number of items in index keys
   375  // starting from the key encoded from the provided Item.
   376  func (f Index) CountFrom(start Item) (count int, err error) {
   377  	startKey, err := f.encodeKeyFunc(start)
   378  	if err != nil {
   379  		return 0, err
   380  	}
   381  	it := f.db.NewIterator()
   382  	defer it.Release()
   383  
   384  	for ok := it.Seek(startKey); ok; ok = it.Next() {
   385  		key := it.Key()
   386  		if key[0] != f.prefix[0] {
   387  			break
   388  		}
   389  		count++
   390  	}
   391  	return count, it.Error()
   392  }