github.com/klaytn/klaytn@v1.12.1/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 defer batch.Release() 44 // Iterate over the key-range and delete all of them 45 start, logged := time.Now(), time.Now() 46 47 it := db.NewSnapshotDBIterator(prefix, origin) 48 var stop []byte 49 if limit != nil { 50 stop = append(prefix, limit...) 51 } 52 for it.Next() { 53 // Skip any keys with the correct prefix but wrong length (trie nodes) 54 key := it.Key() 55 if !bytes.HasPrefix(key, prefix) { 56 break 57 } 58 if len(key) != keylen { 59 continue 60 } 61 if stop != nil && bytes.Compare(key, stop) >= 0 { 62 break 63 } 64 // Delete the key and periodically recreate the batch and iterator 65 batch.Delete(key) 66 items++ 67 68 if items%10000 == 0 { 69 // Batch too large (or iterator too long lived, flush and recreate) 70 it.Release() 71 if err := batch.Write(); err != nil { 72 return err 73 } 74 batch.Reset() 75 seekPos := key[len(prefix):] 76 it = db.NewSnapshotDBIterator(prefix, seekPos) 77 78 if time.Since(logged) > 8*time.Second && report { 79 logger.Info("Deleting state snapshot leftovers", "kind", kind, "wiped", items, "elapsed", common.PrettyDuration(time.Since(start))) 80 logged = time.Now() 81 } 82 } 83 } 84 it.Release() 85 if err := batch.Write(); err != nil { 86 return err 87 } 88 if meter != nil { 89 meter.Mark(int64(items)) 90 } 91 if report { 92 logger.Info("Deleted state snapshot leftovers", "kind", kind, "wiped", items, "elapsed", common.PrettyDuration(time.Since(start))) 93 } 94 return nil 95 }