github.com/amazechain/amc@v0.1.3/modules/ethdb/olddb/object_db.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  // Package ethdb defines the interfaces for an Ethereum data store.
    17  package olddb
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"github.com/amazechain/amc/common/types"
    23  	"github.com/amazechain/amc/log"
    24  
    25  	"github.com/amazechain/amc/modules/ethdb"
    26  	"github.com/ledgerwatch/erigon-lib/kv"
    27  )
    28  
    29  // ObjectDatabase - is an object-style interface of DB accessing
    30  type ObjectDatabase struct {
    31  	kv kv.RwDB
    32  }
    33  
    34  // NewObjectDatabase returns a AbstractDB wrapper.
    35  // Deprecated
    36  func NewObjectDatabase(kv kv.RwDB) *ObjectDatabase {
    37  	return &ObjectDatabase{
    38  		kv: kv,
    39  	}
    40  }
    41  
    42  // Put inserts or updates a single entry.
    43  func (db *ObjectDatabase) Put(table string, k, v []byte) error {
    44  	err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
    45  		return tx.Put(table, k, v)
    46  	})
    47  	return err
    48  }
    49  
    50  // Append appends a single entry to the end of the bucket.
    51  func (db *ObjectDatabase) Append(bucket string, key []byte, value []byte) error {
    52  	err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
    53  		c, err := tx.RwCursor(bucket)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		return c.Append(key, value)
    58  	})
    59  	return err
    60  }
    61  
    62  // AppendDup appends a single entry to the end of the bucket.
    63  func (db *ObjectDatabase) AppendDup(bucket string, key []byte, value []byte) error {
    64  	err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
    65  		c, err := tx.RwCursorDupSort(bucket)
    66  		if err != nil {
    67  			return err
    68  		}
    69  		return c.AppendDup(key, value)
    70  	})
    71  	return err
    72  }
    73  
    74  func (db *ObjectDatabase) Has(bucket string, key []byte) (bool, error) {
    75  	var has bool
    76  	err := db.kv.View(context.Background(), func(tx kv.Tx) error {
    77  		v, err := tx.GetOne(bucket, key)
    78  		if err != nil {
    79  			return err
    80  		}
    81  		has = v != nil
    82  		return nil
    83  	})
    84  	return has, err
    85  }
    86  
    87  func (db *ObjectDatabase) IncrementSequence(bucket string, amount uint64) (res uint64, err error) {
    88  	err = db.kv.Update(context.Background(), func(tx kv.RwTx) error {
    89  		res, err = tx.IncrementSequence(bucket, amount)
    90  		return err
    91  	})
    92  	return res, err
    93  }
    94  func (db *ObjectDatabase) ReadSequence(bucket string) (res uint64, err error) {
    95  	err = db.kv.View(context.Background(), func(tx kv.Tx) error {
    96  		res, err = tx.ReadSequence(bucket)
    97  		return err
    98  	})
    99  	return res, err
   100  }
   101  
   102  // Get returns the value for a given key if it's present.
   103  func (db *ObjectDatabase) GetOne(bucket string, key []byte) ([]byte, error) {
   104  	var dat []byte
   105  	err := db.kv.View(context.Background(), func(tx kv.Tx) error {
   106  		v, err := tx.GetOne(bucket, key)
   107  		if err != nil {
   108  			return err
   109  		}
   110  		if v != nil {
   111  			dat = make([]byte, len(v))
   112  			copy(dat, v)
   113  		}
   114  		return nil
   115  	})
   116  	return dat, err
   117  }
   118  
   119  func (db *ObjectDatabase) Get(bucket string, key []byte) ([]byte, error) {
   120  	dat, err := db.GetOne(bucket, key)
   121  	return ethdb.GetOneWrapper(dat, err)
   122  }
   123  
   124  func (db *ObjectDatabase) Last(bucket string) ([]byte, []byte, error) {
   125  	var key, value []byte
   126  	if err := db.kv.View(context.Background(), func(tx kv.Tx) error {
   127  		c, err := tx.Cursor(bucket)
   128  		if err != nil {
   129  			return err
   130  		}
   131  		k, v, err := c.Last()
   132  		if err != nil {
   133  			return err
   134  		}
   135  		if k != nil {
   136  			key, value = types.CopyBytes(k), types.CopyBytes(v)
   137  		}
   138  		return nil
   139  	}); err != nil {
   140  		return nil, nil, err
   141  	}
   142  	return key, value, nil
   143  }
   144  
   145  func (db *ObjectDatabase) ForEach(bucket string, fromPrefix []byte, walker func(k, v []byte) error) error {
   146  	return db.kv.View(context.Background(), func(tx kv.Tx) error {
   147  		return tx.ForEach(bucket, fromPrefix, walker)
   148  	})
   149  }
   150  func (db *ObjectDatabase) ForAmount(bucket string, fromPrefix []byte, amount uint32, walker func(k, v []byte) error) error {
   151  	return db.kv.View(context.Background(), func(tx kv.Tx) error {
   152  		return tx.ForAmount(bucket, fromPrefix, amount, walker)
   153  	})
   154  }
   155  
   156  func (db *ObjectDatabase) ForPrefix(bucket string, prefix []byte, walker func(k, v []byte) error) error {
   157  	return db.kv.View(context.Background(), func(tx kv.Tx) error {
   158  		return tx.ForPrefix(bucket, prefix, walker)
   159  	})
   160  }
   161  
   162  // Delete deletes the key from the queue and database
   163  func (db *ObjectDatabase) Delete(table string, k []byte) error {
   164  	// Execute the actual operation
   165  	err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
   166  		return tx.Delete(table, k)
   167  	})
   168  	return err
   169  }
   170  
   171  func (db *ObjectDatabase) BucketExists(name string) (bool, error) {
   172  	exists := false
   173  	if err := db.kv.View(context.Background(), func(tx kv.Tx) (err error) {
   174  		migrator, ok := tx.(kv.BucketMigrator)
   175  		if !ok {
   176  			return fmt.Errorf("%T doesn't implement ethdb.TxMigrator interface", db.kv)
   177  		}
   178  		exists, err = migrator.ExistsBucket(name)
   179  		if err != nil {
   180  			return err
   181  		}
   182  		return nil
   183  	}); err != nil {
   184  		return false, err
   185  	}
   186  	return exists, nil
   187  }
   188  
   189  func (db *ObjectDatabase) ClearBuckets(buckets ...string) error {
   190  	for i := range buckets {
   191  		name := buckets[i]
   192  		if err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
   193  			migrator, ok := tx.(kv.BucketMigrator)
   194  			if !ok {
   195  				return fmt.Errorf("%T doesn't implement ethdb.TxMigrator interface", db.kv)
   196  			}
   197  			if err := migrator.ClearBucket(name); err != nil {
   198  				return err
   199  			}
   200  			return nil
   201  		}); err != nil {
   202  			return err
   203  		}
   204  	}
   205  
   206  	return nil
   207  }
   208  
   209  func (db *ObjectDatabase) DropBuckets(buckets ...string) error {
   210  	for i := range buckets {
   211  		name := buckets[i]
   212  		log.Info("Dropping bucket", "name", name)
   213  		if err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
   214  			migrator, ok := tx.(kv.BucketMigrator)
   215  			if !ok {
   216  				return fmt.Errorf("%T doesn't implement ethdb.TxMigrator interface", db.kv)
   217  			}
   218  			if err := migrator.DropBucket(name); err != nil {
   219  				return err
   220  			}
   221  			return nil
   222  		}); err != nil {
   223  			return err
   224  		}
   225  	}
   226  	return nil
   227  }
   228  
   229  func (db *ObjectDatabase) Close() {
   230  	db.kv.Close()
   231  }
   232  
   233  func (db *ObjectDatabase) RwKV() kv.RwDB {
   234  	return db.kv
   235  }
   236  
   237  func (db *ObjectDatabase) SetRwKV(kv kv.RwDB) {
   238  	db.kv = kv
   239  }
   240  
   241  func (db *ObjectDatabase) Begin(ctx context.Context, flags ethdb.TxFlags) (ethdb.DbWithPendingMutations, error) {
   242  	batch := &TxDb{db: db}
   243  	if err := batch.begin(ctx, flags); err != nil {
   244  		return batch, err
   245  	}
   246  	return batch, nil
   247  }