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

     1  package db
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"path/filepath"
     7  
     8  	"github.com/syndtr/goleveldb/leveldb"
     9  	"github.com/syndtr/goleveldb/leveldb/errors"
    10  	"github.com/syndtr/goleveldb/leveldb/iterator"
    11  	"github.com/syndtr/goleveldb/leveldb/opt"
    12  )
    13  
    14  func init() {
    15  	dbCreator := func(name string, dir string) (DB, error) {
    16  		return NewGoLevelDB(name, dir)
    17  	}
    18  	registerDBCreator(GoLevelDBBackend, dbCreator, false)
    19  }
    20  
    21  var _ DB = (*GoLevelDB)(nil)
    22  
    23  type GoLevelDB struct {
    24  	db *leveldb.DB
    25  }
    26  
    27  func NewGoLevelDB(name string, dir string) (*GoLevelDB, error) {
    28  	return NewGoLevelDBWithOpts(name, dir, nil)
    29  }
    30  
    31  func NewGoLevelDBWithOpts(name string, dir string, o *opt.Options) (*GoLevelDB, error) {
    32  	dbPath := filepath.Join(dir, name+".db")
    33  	db, err := leveldb.OpenFile(dbPath, o)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	database := &GoLevelDB{
    38  		db: db,
    39  	}
    40  	return database, nil
    41  }
    42  
    43  // Implements DB.
    44  func (db *GoLevelDB) Get(key []byte) []byte {
    45  	key = nonNilBytes(key)
    46  	res, err := db.db.Get(key, nil)
    47  	if err != nil {
    48  		if err == errors.ErrNotFound {
    49  			return nil
    50  		}
    51  		panic(err)
    52  	}
    53  	return res
    54  }
    55  
    56  // Implements DB.
    57  func (db *GoLevelDB) Has(key []byte) bool {
    58  	return db.Get(key) != nil
    59  }
    60  
    61  // Implements DB.
    62  func (db *GoLevelDB) Set(key []byte, value []byte) {
    63  	key = nonNilBytes(key)
    64  	value = nonNilBytes(value)
    65  	err := db.db.Put(key, value, nil)
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  }
    70  
    71  // Implements DB.
    72  func (db *GoLevelDB) SetSync(key []byte, value []byte) {
    73  	key = nonNilBytes(key)
    74  	value = nonNilBytes(value)
    75  	err := db.db.Put(key, value, &opt.WriteOptions{Sync: true})
    76  	if err != nil {
    77  		panic(err)
    78  	}
    79  }
    80  
    81  // Implements DB.
    82  func (db *GoLevelDB) Delete(key []byte) {
    83  	key = nonNilBytes(key)
    84  	err := db.db.Delete(key, nil)
    85  	if err != nil {
    86  		panic(err)
    87  	}
    88  }
    89  
    90  // Implements DB.
    91  func (db *GoLevelDB) DeleteSync(key []byte) {
    92  	key = nonNilBytes(key)
    93  	err := db.db.Delete(key, &opt.WriteOptions{Sync: true})
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  }
    98  
    99  func (db *GoLevelDB) DB() *leveldb.DB {
   100  	return db.db
   101  }
   102  
   103  // Implements DB.
   104  func (db *GoLevelDB) Close() {
   105  	db.db.Close()
   106  }
   107  
   108  // Implements DB.
   109  func (db *GoLevelDB) Print() {
   110  	str, _ := db.db.GetProperty("leveldb.stats")
   111  	fmt.Printf("%v\n", str)
   112  
   113  	itr := db.db.NewIterator(nil, nil)
   114  	for itr.Next() {
   115  		key := itr.Key()
   116  		value := itr.Value()
   117  		fmt.Printf("[%X]:\t[%X]\n", key, value)
   118  	}
   119  }
   120  
   121  // Implements DB.
   122  func (db *GoLevelDB) Stats() map[string]string {
   123  	keys := []string{
   124  		"leveldb.num-files-at-level{n}",
   125  		"leveldb.stats",
   126  		"leveldb.sstables",
   127  		"leveldb.blockpool",
   128  		"leveldb.cachedblock",
   129  		"leveldb.openedtables",
   130  		"leveldb.alivesnaps",
   131  		"leveldb.aliveiters",
   132  	}
   133  
   134  	stats := make(map[string]string)
   135  	for _, key := range keys {
   136  		str, err := db.db.GetProperty(key)
   137  		if err == nil {
   138  			stats[key] = str
   139  		}
   140  	}
   141  	return stats
   142  }
   143  
   144  //----------------------------------------
   145  // Batch
   146  
   147  // Implements DB.
   148  func (db *GoLevelDB) NewBatch() Batch {
   149  	batch := new(leveldb.Batch)
   150  	return &goLevelDBBatch{db, batch}
   151  }
   152  
   153  type goLevelDBBatch struct {
   154  	db    *GoLevelDB
   155  	batch *leveldb.Batch
   156  }
   157  
   158  // Implements Batch.
   159  func (mBatch *goLevelDBBatch) Set(key, value []byte) {
   160  	mBatch.batch.Put(key, value)
   161  }
   162  
   163  // Implements Batch.
   164  func (mBatch *goLevelDBBatch) Delete(key []byte) {
   165  	mBatch.batch.Delete(key)
   166  }
   167  
   168  // Implements Batch.
   169  func (mBatch *goLevelDBBatch) Write() {
   170  	err := mBatch.db.db.Write(mBatch.batch, &opt.WriteOptions{Sync: false})
   171  	if err != nil {
   172  		panic(err)
   173  	}
   174  }
   175  
   176  // Implements Batch.
   177  func (mBatch *goLevelDBBatch) WriteSync() {
   178  	err := mBatch.db.db.Write(mBatch.batch, &opt.WriteOptions{Sync: true})
   179  	if err != nil {
   180  		panic(err)
   181  	}
   182  }
   183  
   184  // Implements Batch.
   185  // Close is no-op for goLevelDBBatch.
   186  func (mBatch *goLevelDBBatch) Close() {}
   187  
   188  //----------------------------------------
   189  // Iterator
   190  // NOTE This is almost identical to db/c_level_db.Iterator
   191  // Before creating a third version, refactor.
   192  
   193  // Implements DB.
   194  func (db *GoLevelDB) Iterator(start, end []byte) Iterator {
   195  	itr := db.db.NewIterator(nil, nil)
   196  	return newGoLevelDBIterator(itr, start, end, false)
   197  }
   198  
   199  // Implements DB.
   200  func (db *GoLevelDB) ReverseIterator(start, end []byte) Iterator {
   201  	itr := db.db.NewIterator(nil, nil)
   202  	return newGoLevelDBIterator(itr, start, end, true)
   203  }
   204  
   205  type goLevelDBIterator struct {
   206  	source    iterator.Iterator
   207  	start     []byte
   208  	end       []byte
   209  	isReverse bool
   210  	isInvalid bool
   211  }
   212  
   213  var _ Iterator = (*goLevelDBIterator)(nil)
   214  
   215  func newGoLevelDBIterator(source iterator.Iterator, start, end []byte, isReverse bool) *goLevelDBIterator {
   216  	if isReverse {
   217  		if end == nil {
   218  			source.Last()
   219  		} else {
   220  			valid := source.Seek(end)
   221  			if valid {
   222  				eoakey := source.Key() // end or after key
   223  				if bytes.Compare(end, eoakey) <= 0 {
   224  					source.Prev()
   225  				}
   226  			} else {
   227  				source.Last()
   228  			}
   229  		}
   230  	} else {
   231  		if start == nil {
   232  			source.First()
   233  		} else {
   234  			source.Seek(start)
   235  		}
   236  	}
   237  	return &goLevelDBIterator{
   238  		source:    source,
   239  		start:     start,
   240  		end:       end,
   241  		isReverse: isReverse,
   242  		isInvalid: false,
   243  	}
   244  }
   245  
   246  // Implements Iterator.
   247  func (itr *goLevelDBIterator) Domain() ([]byte, []byte) {
   248  	return itr.start, itr.end
   249  }
   250  
   251  // Implements Iterator.
   252  func (itr *goLevelDBIterator) Valid() bool {
   253  
   254  	// Once invalid, forever invalid.
   255  	if itr.isInvalid {
   256  		return false
   257  	}
   258  
   259  	// Panic on DB error.  No way to recover.
   260  	itr.assertNoError()
   261  
   262  	// If source is invalid, invalid.
   263  	if !itr.source.Valid() {
   264  		itr.isInvalid = true
   265  		return false
   266  	}
   267  
   268  	// If key is end or past it, invalid.
   269  	var start = itr.start
   270  	var end = itr.end
   271  	var key = itr.source.Key()
   272  
   273  	if itr.isReverse {
   274  		if start != nil && bytes.Compare(key, start) < 0 {
   275  			itr.isInvalid = true
   276  			return false
   277  		}
   278  	} else {
   279  		if end != nil && bytes.Compare(end, key) <= 0 {
   280  			itr.isInvalid = true
   281  			return false
   282  		}
   283  	}
   284  
   285  	// Valid
   286  	return true
   287  }
   288  
   289  // Implements Iterator.
   290  func (itr *goLevelDBIterator) Key() []byte {
   291  	// Key returns a copy of the current key.
   292  	// See https://github.com/syndtr/goleveldb/blob/52c212e6c196a1404ea59592d3f1c227c9f034b2/leveldb/iterator/iter.go#L88
   293  	itr.assertNoError()
   294  	itr.assertIsValid()
   295  	return cp(itr.source.Key())
   296  }
   297  
   298  // Implements Iterator.
   299  func (itr *goLevelDBIterator) Value() []byte {
   300  	// Value returns a copy of the current value.
   301  	// See https://github.com/syndtr/goleveldb/blob/52c212e6c196a1404ea59592d3f1c227c9f034b2/leveldb/iterator/iter.go#L88
   302  	itr.assertNoError()
   303  	itr.assertIsValid()
   304  	return cp(itr.source.Value())
   305  }
   306  
   307  // Implements Iterator.
   308  func (itr *goLevelDBIterator) Next() {
   309  	itr.assertNoError()
   310  	itr.assertIsValid()
   311  	if itr.isReverse {
   312  		itr.source.Prev()
   313  	} else {
   314  		itr.source.Next()
   315  	}
   316  }
   317  
   318  // Implements Iterator.
   319  func (itr *goLevelDBIterator) Close() {
   320  	itr.source.Release()
   321  }
   322  
   323  func (itr *goLevelDBIterator) assertNoError() {
   324  	if err := itr.source.Error(); err != nil {
   325  		panic(err)
   326  	}
   327  }
   328  
   329  func (itr goLevelDBIterator) assertIsValid() {
   330  	if !itr.Valid() {
   331  		panic("goLevelDBIterator is invalid")
   332  	}
   333  }