github.com/klaytn/klaytn@v1.10.2/snapshot/wipe.go (about) 1 // Modifications Copyright 2021 The klaytn Authors 2 // Copyright 2019 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/state/snapshot/wipe.go (2021/10/21). 19 // Modified and improved for the klaytn development. 20 21 package snapshot 22 23 import ( 24 "bytes" 25 "time" 26 27 "github.com/klaytn/klaytn/common" 28 "github.com/klaytn/klaytn/storage/database" 29 "github.com/rcrowley/go-metrics" 30 ) 31 32 // wipeKeyRange deletes a range of keys from the database starting with prefix 33 // and having a specific total key length. The start and limit is optional for 34 // specifying a particular key range for deletion. 35 // 36 // Origin is included for wiping and limit is excluded if they are specified. 37 func wipeKeyRange(db database.DBManager, kind string, prefix []byte, origin []byte, limit []byte, keylen int, meter metrics.Meter, report bool) error { 38 // Batch deletions together to avoid holding an iterator for too long 39 var ( 40 batch = db.NewSnapshotDBBatch() 41 items int 42 ) 43 // Iterate over the key-range and delete all of them 44 start, logged := time.Now(), time.Now() 45 46 it := db.NewSnapshotDBIterator(prefix, origin) 47 var stop []byte 48 if limit != nil { 49 stop = append(prefix, limit...) 50 } 51 for it.Next() { 52 // Skip any keys with the correct prefix but wrong length (trie nodes) 53 key := it.Key() 54 if !bytes.HasPrefix(key, prefix) { 55 break 56 } 57 if len(key) != keylen { 58 continue 59 } 60 if stop != nil && bytes.Compare(key, stop) >= 0 { 61 break 62 } 63 // Delete the key and periodically recreate the batch and iterator 64 batch.Delete(key) 65 items++ 66 67 if items%10000 == 0 { 68 // Batch too large (or iterator too long lived, flush and recreate) 69 it.Release() 70 if err := batch.Write(); err != nil { 71 return err 72 } 73 batch.Reset() 74 seekPos := key[len(prefix):] 75 it = db.NewSnapshotDBIterator(prefix, seekPos) 76 77 if time.Since(logged) > 8*time.Second && report { 78 logger.Info("Deleting state snapshot leftovers", "kind", kind, "wiped", items, "elapsed", common.PrettyDuration(time.Since(start))) 79 logged = time.Now() 80 } 81 } 82 } 83 it.Release() 84 if err := batch.Write(); err != nil { 85 return err 86 } 87 if meter != nil { 88 meter.Mark(int64(items)) 89 } 90 if report { 91 logger.Info("Deleted state snapshot leftovers", "kind", kind, "wiped", items, "elapsed", common.PrettyDuration(time.Since(start))) 92 } 93 return nil 94 }