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 }