2020-05-30 08:12:21 +00:00
|
|
|
// Copyright 2014 The go-ethereum Authors
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
// Package ethdb defines the interfaces for an Ethereum data store.
|
2021-07-28 02:47:38 +00:00
|
|
|
package olddb
|
2020-05-30 08:12:21 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-08-05 10:13:35 +00:00
|
|
|
"fmt"
|
2020-10-12 08:39:04 +00:00
|
|
|
|
2021-07-29 11:53:13 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
2021-05-20 18:25:53 +00:00
|
|
|
"github.com/ledgerwatch/erigon/common"
|
2021-06-19 08:21:53 +00:00
|
|
|
"github.com/ledgerwatch/erigon/ethdb"
|
2021-07-29 10:23:23 +00:00
|
|
|
"github.com/ledgerwatch/log/v3"
|
2020-05-30 08:12:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ObjectDatabase - is an object-style interface of DB accessing
|
|
|
|
type ObjectDatabase struct {
|
2021-07-28 02:47:38 +00:00
|
|
|
kv kv.RwDB
|
2020-05-30 08:12:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewObjectDatabase returns a AbstractDB wrapper.
|
2022-08-10 12:04:13 +00:00
|
|
|
// Deprecated
|
2021-07-28 02:47:38 +00:00
|
|
|
func NewObjectDatabase(kv kv.RwDB) *ObjectDatabase {
|
2020-05-30 08:12:21 +00:00
|
|
|
return &ObjectDatabase{
|
2021-03-24 22:48:08 +00:00
|
|
|
kv: kv,
|
2020-05-30 08:12:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put inserts or updates a single entry.
|
2022-07-26 05:47:05 +00:00
|
|
|
func (db *ObjectDatabase) Put(table string, k, v []byte) error {
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
2022-07-26 05:47:05 +00:00
|
|
|
return tx.Put(table, k, v)
|
2020-05-30 08:12:21 +00:00
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-09-01 06:48:25 +00:00
|
|
|
// Append appends a single entry to the end of the bucket.
|
|
|
|
func (db *ObjectDatabase) Append(bucket string, key []byte, value []byte) error {
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
2021-04-02 06:36:49 +00:00
|
|
|
c, err := tx.RwCursor(bucket)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return c.Append(key, value)
|
2020-09-01 06:48:25 +00:00
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-28 14:24:47 +00:00
|
|
|
// AppendDup appends a single entry to the end of the bucket.
|
|
|
|
func (db *ObjectDatabase) AppendDup(bucket string, key []byte, value []byte) error {
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
2021-04-02 06:36:49 +00:00
|
|
|
c, err := tx.RwCursorDupSort(bucket)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return c.AppendDup(key, value)
|
2020-11-28 14:24:47 +00:00
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-08-10 23:55:32 +00:00
|
|
|
func (db *ObjectDatabase) Has(bucket string, key []byte) (bool, error) {
|
2020-05-30 08:12:21 +00:00
|
|
|
var has bool
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2020-10-24 08:09:20 +00:00
|
|
|
v, err := tx.GetOne(bucket, key)
|
2020-08-14 06:41:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-05-30 08:12:21 +00:00
|
|
|
has = v != nil
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return has, err
|
|
|
|
}
|
|
|
|
|
2021-03-20 14:12:54 +00:00
|
|
|
func (db *ObjectDatabase) IncrementSequence(bucket string, amount uint64) (res uint64, err error) {
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
2021-03-20 14:12:54 +00:00
|
|
|
res, err = tx.IncrementSequence(bucket, amount)
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
func (db *ObjectDatabase) ReadSequence(bucket string) (res uint64, err error) {
|
2021-07-28 02:47:38 +00:00
|
|
|
err = db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2021-03-20 14:12:54 +00:00
|
|
|
res, err = tx.ReadSequence(bucket)
|
2020-11-14 13:48:29 +00:00
|
|
|
return err
|
|
|
|
})
|
|
|
|
return res, err
|
|
|
|
}
|
|
|
|
|
2020-05-30 08:12:21 +00:00
|
|
|
// Get returns the value for a given key if it's present.
|
2021-04-05 13:04:58 +00:00
|
|
|
func (db *ObjectDatabase) GetOne(bucket string, key []byte) ([]byte, error) {
|
2020-08-14 06:41:18 +00:00
|
|
|
var dat []byte
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2020-10-24 08:09:20 +00:00
|
|
|
v, err := tx.GetOne(bucket, key)
|
2020-08-14 06:41:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-05-30 08:12:21 +00:00
|
|
|
if v != nil {
|
|
|
|
dat = make([]byte, len(v))
|
|
|
|
copy(dat, v)
|
|
|
|
}
|
|
|
|
return nil
|
2021-04-05 13:04:58 +00:00
|
|
|
})
|
|
|
|
return dat, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *ObjectDatabase) Get(bucket string, key []byte) ([]byte, error) {
|
|
|
|
dat, err := db.GetOne(bucket, key)
|
2021-06-19 08:21:53 +00:00
|
|
|
return ethdb.GetOneWrapper(dat, err)
|
2020-05-30 08:12:21 +00:00
|
|
|
}
|
|
|
|
|
2020-08-12 03:49:52 +00:00
|
|
|
func (db *ObjectDatabase) Last(bucket string) ([]byte, []byte, error) {
|
|
|
|
var key, value []byte
|
2021-07-28 02:47:38 +00:00
|
|
|
if err := db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2021-04-02 06:36:49 +00:00
|
|
|
c, err := tx.Cursor(bucket)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
k, v, err := c.Last()
|
2020-08-12 03:49:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if k != nil {
|
|
|
|
key, value = common.CopyBytes(k), common.CopyBytes(v)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
return key, value, nil
|
|
|
|
}
|
|
|
|
|
2021-06-05 15:17:04 +00:00
|
|
|
func (db *ObjectDatabase) ForEach(bucket string, fromPrefix []byte, walker func(k, v []byte) error) error {
|
2021-07-28 02:47:38 +00:00
|
|
|
return db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-05 15:17:04 +00:00
|
|
|
return tx.ForEach(bucket, fromPrefix, walker)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
func (db *ObjectDatabase) ForAmount(bucket string, fromPrefix []byte, amount uint32, walker func(k, v []byte) error) error {
|
2021-07-28 02:47:38 +00:00
|
|
|
return db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-05 15:17:04 +00:00
|
|
|
return tx.ForAmount(bucket, fromPrefix, amount, walker)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *ObjectDatabase) ForPrefix(bucket string, prefix []byte, walker func(k, v []byte) error) error {
|
2021-07-28 02:47:38 +00:00
|
|
|
return db.kv.View(context.Background(), func(tx kv.Tx) error {
|
2021-06-05 15:17:04 +00:00
|
|
|
return tx.ForPrefix(bucket, prefix, walker)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-05-30 08:12:21 +00:00
|
|
|
// Delete deletes the key from the queue and database
|
2022-07-26 05:47:05 +00:00
|
|
|
func (db *ObjectDatabase) Delete(table string, k []byte) error {
|
2020-05-30 08:12:21 +00:00
|
|
|
// Execute the actual operation
|
2021-07-28 02:47:38 +00:00
|
|
|
err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
2022-07-26 05:47:05 +00:00
|
|
|
return tx.Delete(table, k)
|
2020-05-30 08:12:21 +00:00
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-08-10 23:55:32 +00:00
|
|
|
func (db *ObjectDatabase) BucketExists(name string) (bool, error) {
|
2020-08-05 10:13:35 +00:00
|
|
|
exists := false
|
2021-07-28 02:47:38 +00:00
|
|
|
if err := db.kv.View(context.Background(), func(tx kv.Tx) (err error) {
|
|
|
|
migrator, ok := tx.(kv.BucketMigrator)
|
2020-08-05 10:13:35 +00:00
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("%T doesn't implement ethdb.TxMigrator interface", db.kv)
|
|
|
|
}
|
2021-07-24 04:28:05 +00:00
|
|
|
exists, err = migrator.ExistsBucket(name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-08-05 10:13:35 +00:00
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
return exists, nil
|
|
|
|
}
|
|
|
|
|
2020-08-10 23:55:32 +00:00
|
|
|
func (db *ObjectDatabase) ClearBuckets(buckets ...string) error {
|
2020-08-05 10:13:35 +00:00
|
|
|
for i := range buckets {
|
|
|
|
name := buckets[i]
|
2021-07-28 02:47:38 +00:00
|
|
|
if err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
|
|
|
migrator, ok := tx.(kv.BucketMigrator)
|
2020-08-05 10:13:35 +00:00
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("%T doesn't implement ethdb.TxMigrator interface", db.kv)
|
|
|
|
}
|
2020-08-14 06:41:18 +00:00
|
|
|
if err := migrator.ClearBucket(name); err != nil {
|
2020-08-05 10:13:35 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2020-08-04 10:05:27 +00:00
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-06-16 13:36:16 +00:00
|
|
|
}
|
|
|
|
|
2020-08-04 10:05:27 +00:00
|
|
|
return nil
|
2020-05-30 08:12:21 +00:00
|
|
|
}
|
|
|
|
|
2020-08-10 23:55:32 +00:00
|
|
|
func (db *ObjectDatabase) DropBuckets(buckets ...string) error {
|
2020-08-05 10:13:35 +00:00
|
|
|
for i := range buckets {
|
|
|
|
name := buckets[i]
|
2020-08-13 06:40:28 +00:00
|
|
|
log.Info("Dropping bucket", "name", name)
|
2021-07-28 02:47:38 +00:00
|
|
|
if err := db.kv.Update(context.Background(), func(tx kv.RwTx) error {
|
|
|
|
migrator, ok := tx.(kv.BucketMigrator)
|
2020-08-05 10:13:35 +00:00
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("%T doesn't implement ethdb.TxMigrator interface", db.kv)
|
|
|
|
}
|
2020-08-14 06:41:18 +00:00
|
|
|
if err := migrator.DropBucket(name); err != nil {
|
2020-08-05 10:13:35 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-05-30 08:12:21 +00:00
|
|
|
func (db *ObjectDatabase) Close() {
|
|
|
|
db.kv.Close()
|
|
|
|
}
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
func (db *ObjectDatabase) RwKV() kv.RwDB {
|
2020-05-30 08:12:21 +00:00
|
|
|
return db.kv
|
|
|
|
}
|
|
|
|
|
2021-07-28 02:47:38 +00:00
|
|
|
func (db *ObjectDatabase) SetRwKV(kv kv.RwDB) {
|
2020-10-13 12:56:16 +00:00
|
|
|
db.kv = kv
|
|
|
|
}
|
|
|
|
|
2021-06-19 08:21:53 +00:00
|
|
|
func (db *ObjectDatabase) Begin(ctx context.Context, flags ethdb.TxFlags) (ethdb.DbWithPendingMutations, error) {
|
2020-10-25 08:38:55 +00:00
|
|
|
batch := &TxDb{db: db}
|
2021-02-10 17:04:22 +00:00
|
|
|
if err := batch.begin(ctx, flags); err != nil {
|
2021-03-22 15:45:24 +00:00
|
|
|
return batch, err
|
2020-08-17 06:45:52 +00:00
|
|
|
}
|
|
|
|
return batch, nil
|
|
|
|
}
|