github.com/evdatsion/aphelion-dpos-bft@v0.32.1/libs/db/prefix_db.go (about)

     1  package db
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sync"
     7  )
     8  
     9  // IteratePrefix is a convenience function for iterating over a key domain
    10  // restricted by prefix.
    11  func IteratePrefix(db DB, prefix []byte) Iterator {
    12  	var start, end []byte
    13  	if len(prefix) == 0 {
    14  		start = nil
    15  		end = nil
    16  	} else {
    17  		start = cp(prefix)
    18  		end = cpIncr(prefix)
    19  	}
    20  	return db.Iterator(start, end)
    21  }
    22  
    23  /*
    24  TODO: Make test, maybe rename.
    25  // Like IteratePrefix but the iterator strips the prefix from the keys.
    26  func IteratePrefixStripped(db DB, prefix []byte) Iterator {
    27  	start, end := ...
    28  	return newPrefixIterator(prefix, start, end, IteratePrefix(db, prefix))
    29  }
    30  */
    31  
    32  //----------------------------------------
    33  // prefixDB
    34  
    35  type prefixDB struct {
    36  	mtx    sync.Mutex
    37  	prefix []byte
    38  	db     DB
    39  }
    40  
    41  // NewPrefixDB lets you namespace multiple DBs within a single DB.
    42  func NewPrefixDB(db DB, prefix []byte) *prefixDB {
    43  	return &prefixDB{
    44  		prefix: prefix,
    45  		db:     db,
    46  	}
    47  }
    48  
    49  // Implements atomicSetDeleter.
    50  func (pdb *prefixDB) Mutex() *sync.Mutex {
    51  	return &(pdb.mtx)
    52  }
    53  
    54  // Implements DB.
    55  func (pdb *prefixDB) Get(key []byte) []byte {
    56  	pdb.mtx.Lock()
    57  	defer pdb.mtx.Unlock()
    58  
    59  	pkey := pdb.prefixed(key)
    60  	value := pdb.db.Get(pkey)
    61  	return value
    62  }
    63  
    64  // Implements DB.
    65  func (pdb *prefixDB) Has(key []byte) bool {
    66  	pdb.mtx.Lock()
    67  	defer pdb.mtx.Unlock()
    68  
    69  	return pdb.db.Has(pdb.prefixed(key))
    70  }
    71  
    72  // Implements DB.
    73  func (pdb *prefixDB) Set(key []byte, value []byte) {
    74  	pdb.mtx.Lock()
    75  	defer pdb.mtx.Unlock()
    76  
    77  	pkey := pdb.prefixed(key)
    78  	pdb.db.Set(pkey, value)
    79  }
    80  
    81  // Implements DB.
    82  func (pdb *prefixDB) SetSync(key []byte, value []byte) {
    83  	pdb.mtx.Lock()
    84  	defer pdb.mtx.Unlock()
    85  
    86  	pdb.db.SetSync(pdb.prefixed(key), value)
    87  }
    88  
    89  // Implements DB.
    90  func (pdb *prefixDB) Delete(key []byte) {
    91  	pdb.mtx.Lock()
    92  	defer pdb.mtx.Unlock()
    93  
    94  	pdb.db.Delete(pdb.prefixed(key))
    95  }
    96  
    97  // Implements DB.
    98  func (pdb *prefixDB) DeleteSync(key []byte) {
    99  	pdb.mtx.Lock()
   100  	defer pdb.mtx.Unlock()
   101  
   102  	pdb.db.DeleteSync(pdb.prefixed(key))
   103  }
   104  
   105  // Implements DB.
   106  func (pdb *prefixDB) Iterator(start, end []byte) Iterator {
   107  	pdb.mtx.Lock()
   108  	defer pdb.mtx.Unlock()
   109  
   110  	var pstart, pend []byte
   111  	pstart = append(cp(pdb.prefix), start...)
   112  	if end == nil {
   113  		pend = cpIncr(pdb.prefix)
   114  	} else {
   115  		pend = append(cp(pdb.prefix), end...)
   116  	}
   117  	return newPrefixIterator(
   118  		pdb.prefix,
   119  		start,
   120  		end,
   121  		pdb.db.Iterator(
   122  			pstart,
   123  			pend,
   124  		),
   125  	)
   126  }
   127  
   128  // Implements DB.
   129  func (pdb *prefixDB) ReverseIterator(start, end []byte) Iterator {
   130  	pdb.mtx.Lock()
   131  	defer pdb.mtx.Unlock()
   132  
   133  	var pstart, pend []byte
   134  	pstart = append(cp(pdb.prefix), start...)
   135  	if end == nil {
   136  		pend = cpIncr(pdb.prefix)
   137  	} else {
   138  		pend = append(cp(pdb.prefix), end...)
   139  	}
   140  	ritr := pdb.db.ReverseIterator(pstart, pend)
   141  	return newPrefixIterator(
   142  		pdb.prefix,
   143  		start,
   144  		end,
   145  		ritr,
   146  	)
   147  }
   148  
   149  // Implements DB.
   150  // Panics if the underlying DB is not an
   151  // atomicSetDeleter.
   152  func (pdb *prefixDB) NewBatch() Batch {
   153  	pdb.mtx.Lock()
   154  	defer pdb.mtx.Unlock()
   155  
   156  	return newPrefixBatch(pdb.prefix, pdb.db.NewBatch())
   157  }
   158  
   159  /* NOTE: Uncomment to use memBatch instead of prefixBatch
   160  // Implements atomicSetDeleter.
   161  func (pdb *prefixDB) SetNoLock(key []byte, value []byte) {
   162  	pdb.db.(atomicSetDeleter).SetNoLock(pdb.prefixed(key), value)
   163  }
   164  
   165  // Implements atomicSetDeleter.
   166  func (pdb *prefixDB) SetNoLockSync(key []byte, value []byte) {
   167  	pdb.db.(atomicSetDeleter).SetNoLockSync(pdb.prefixed(key), value)
   168  }
   169  
   170  // Implements atomicSetDeleter.
   171  func (pdb *prefixDB) DeleteNoLock(key []byte) {
   172  	pdb.db.(atomicSetDeleter).DeleteNoLock(pdb.prefixed(key))
   173  }
   174  
   175  // Implements atomicSetDeleter.
   176  func (pdb *prefixDB) DeleteNoLockSync(key []byte) {
   177  	pdb.db.(atomicSetDeleter).DeleteNoLockSync(pdb.prefixed(key))
   178  }
   179  */
   180  
   181  // Implements DB.
   182  func (pdb *prefixDB) Close() {
   183  	pdb.mtx.Lock()
   184  	defer pdb.mtx.Unlock()
   185  
   186  	pdb.db.Close()
   187  }
   188  
   189  // Implements DB.
   190  func (pdb *prefixDB) Print() {
   191  	fmt.Printf("prefix: %X\n", pdb.prefix)
   192  
   193  	itr := pdb.Iterator(nil, nil)
   194  	defer itr.Close()
   195  	for ; itr.Valid(); itr.Next() {
   196  		key := itr.Key()
   197  		value := itr.Value()
   198  		fmt.Printf("[%X]:\t[%X]\n", key, value)
   199  	}
   200  }
   201  
   202  // Implements DB.
   203  func (pdb *prefixDB) Stats() map[string]string {
   204  	stats := make(map[string]string)
   205  	stats["prefixdb.prefix.string"] = string(pdb.prefix)
   206  	stats["prefixdb.prefix.hex"] = fmt.Sprintf("%X", pdb.prefix)
   207  	source := pdb.db.Stats()
   208  	for key, value := range source {
   209  		stats["prefixdb.source."+key] = value
   210  	}
   211  	return stats
   212  }
   213  
   214  func (pdb *prefixDB) prefixed(key []byte) []byte {
   215  	return append(cp(pdb.prefix), key...)
   216  }
   217  
   218  //----------------------------------------
   219  // prefixBatch
   220  
   221  type prefixBatch struct {
   222  	prefix []byte
   223  	source Batch
   224  }
   225  
   226  func newPrefixBatch(prefix []byte, source Batch) prefixBatch {
   227  	return prefixBatch{
   228  		prefix: prefix,
   229  		source: source,
   230  	}
   231  }
   232  
   233  func (pb prefixBatch) Set(key, value []byte) {
   234  	pkey := append(cp(pb.prefix), key...)
   235  	pb.source.Set(pkey, value)
   236  }
   237  
   238  func (pb prefixBatch) Delete(key []byte) {
   239  	pkey := append(cp(pb.prefix), key...)
   240  	pb.source.Delete(pkey)
   241  }
   242  
   243  func (pb prefixBatch) Write() {
   244  	pb.source.Write()
   245  }
   246  
   247  func (pb prefixBatch) WriteSync() {
   248  	pb.source.WriteSync()
   249  }
   250  
   251  func (pb prefixBatch) Close() {
   252  	pb.source.Close()
   253  }
   254  
   255  //----------------------------------------
   256  // prefixIterator
   257  
   258  var _ Iterator = (*prefixIterator)(nil)
   259  
   260  // Strips prefix while iterating from Iterator.
   261  type prefixIterator struct {
   262  	prefix []byte
   263  	start  []byte
   264  	end    []byte
   265  	source Iterator
   266  	valid  bool
   267  }
   268  
   269  func newPrefixIterator(prefix, start, end []byte, source Iterator) *prefixIterator {
   270  	if !source.Valid() || !bytes.HasPrefix(source.Key(), prefix) {
   271  		return &prefixIterator{
   272  			prefix: prefix,
   273  			start:  start,
   274  			end:    end,
   275  			source: source,
   276  			valid:  false,
   277  		}
   278  	} else {
   279  		return &prefixIterator{
   280  			prefix: prefix,
   281  			start:  start,
   282  			end:    end,
   283  			source: source,
   284  			valid:  true,
   285  		}
   286  	}
   287  }
   288  
   289  func (itr *prefixIterator) Domain() (start []byte, end []byte) {
   290  	return itr.start, itr.end
   291  }
   292  
   293  func (itr *prefixIterator) Valid() bool {
   294  	return itr.valid && itr.source.Valid()
   295  }
   296  
   297  func (itr *prefixIterator) Next() {
   298  	if !itr.valid {
   299  		panic("prefixIterator invalid, cannot call Next()")
   300  	}
   301  	itr.source.Next()
   302  	if !itr.source.Valid() || !bytes.HasPrefix(itr.source.Key(), itr.prefix) {
   303  		itr.valid = false
   304  		return
   305  	}
   306  }
   307  
   308  func (itr *prefixIterator) Key() (key []byte) {
   309  	if !itr.valid {
   310  		panic("prefixIterator invalid, cannot call Key()")
   311  	}
   312  	return stripPrefix(itr.source.Key(), itr.prefix)
   313  }
   314  
   315  func (itr *prefixIterator) Value() (value []byte) {
   316  	if !itr.valid {
   317  		panic("prefixIterator invalid, cannot call Value()")
   318  	}
   319  	return itr.source.Value()
   320  }
   321  
   322  func (itr *prefixIterator) Close() {
   323  	itr.source.Close()
   324  }
   325  
   326  //----------------------------------------
   327  
   328  func stripPrefix(key []byte, prefix []byte) (stripped []byte) {
   329  	if len(key) < len(prefix) {
   330  		panic("should not happen")
   331  	}
   332  	if !bytes.Equal(key[:len(prefix)], prefix) {
   333  		panic("should not happne")
   334  	}
   335  	return key[len(prefix):]
   336  }