github.com/codysnider/go-ethereum@v1.10.18-0.20220420071915-14f4ae99222a/core/state/snapshot/wipe.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package snapshot 18 19 import ( 20 "bytes" 21 "time" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/ethdb" 25 "github.com/ethereum/go-ethereum/log" 26 "github.com/ethereum/go-ethereum/metrics" 27 ) 28 29 // wipeKeyRange deletes a range of keys from the database starting with prefix 30 // and having a specific total key length. The start and limit is optional for 31 // specifying a particular key range for deletion. 32 // 33 // Origin is included for wiping and limit is excluded if they are specified. 34 func wipeKeyRange(db ethdb.KeyValueStore, kind string, prefix []byte, origin []byte, limit []byte, keylen int, meter metrics.Meter, report bool) error { 35 // Batch deletions together to avoid holding an iterator for too long 36 var ( 37 batch = db.NewBatch() 38 items int 39 ) 40 // Iterate over the key-range and delete all of them 41 start, logged := time.Now(), time.Now() 42 43 it := db.NewIterator(prefix, origin) 44 var stop []byte 45 if limit != nil { 46 stop = append(prefix, limit...) 47 } 48 for it.Next() { 49 // Skip any keys with the correct prefix but wrong length (trie nodes) 50 key := it.Key() 51 if !bytes.HasPrefix(key, prefix) { 52 break 53 } 54 if len(key) != keylen { 55 continue 56 } 57 if stop != nil && bytes.Compare(key, stop) >= 0 { 58 break 59 } 60 // Delete the key and periodically recreate the batch and iterator 61 batch.Delete(key) 62 items++ 63 64 if items%10000 == 0 { 65 // Batch too large (or iterator too long lived, flush and recreate) 66 it.Release() 67 if err := batch.Write(); err != nil { 68 return err 69 } 70 batch.Reset() 71 seekPos := key[len(prefix):] 72 it = db.NewIterator(prefix, seekPos) 73 74 if time.Since(logged) > 8*time.Second && report { 75 log.Info("Deleting state snapshot leftovers", "kind", kind, "wiped", items, "elapsed", common.PrettyDuration(time.Since(start))) 76 logged = time.Now() 77 } 78 } 79 } 80 it.Release() 81 if err := batch.Write(); err != nil { 82 return err 83 } 84 if meter != nil { 85 meter.Mark(int64(items)) 86 } 87 if report { 88 log.Info("Deleted state snapshot leftovers", "kind", kind, "wiped", items, "elapsed", common.PrettyDuration(time.Since(start))) 89 } 90 return nil 91 }