erigon-pulse/cmd/integration/commands/reset_state.go
Alex Sharov e02d6acc7d
bitmap indices for logs (#1124)
* save progress

* try now

* don't create bloom inside rlpDecode

* don't create bloom inside ApplyTransaction

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* rename method

* print timings

* print timings

* print timings

* sort before flush

* fix err lint

* clean

* move tests to transactions

* compressed version

* up bound

* up bound

* more tests

* more tests

* more tests

* more tests

* better removal

* clean

* better performance of get/put methods

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* optimize rpcdaemon

* fix test

* fix rpcdaemon

* fix test

* simplify

* simplify

* fix nil pointer

* clean

* revert some changes

* add some logs

* clean

* try without optimize

* clean

* clean

* clean

* clean

* try

* move log_index to own stage

* move log_index to own stage

* integration add log_index stage

* integration add log_index stage

* clean

* clean

* print timing

* remove duplicates at unwind

* extract truncateBitmaps func

* try detect

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* add blackList of topics

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* clean

* sharding 1

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 2

* sharded 3

* sharded 3

* sharded 3

* speedup things by putCurrent and putReserve

* clean

* optimize trim

* clean

* remove blacklist

* add more info to err

* ?

* clean

* clean

* clean

* clean

* clean

* working version

* switch to cgo version of roaring bitmaps

* clean

* clean

* clean

* clean

* more docs

* clean

* clean

* fix logs bloom field

* Fix debug_getModifiedAccountsByNumber

* Try to fix crash

* fix problem with "absent block"

* fix problem with "absent block"

* remove optimize method call

* remove roaring iterator

* fix problem with rebuild indicess

* remove debug prints

* tests for eth_getLogs involving topics

* add tests for new stage, speparate topics into 2 buckets

* version up

* remove debug logs

* remove debug logs

* remove bloom filter implementation

* Optimisation

* Optimisatin not required, make rpctest lenient to geth errors

* Lenient to geth failures

Co-authored-by: Alexey Akhunov <akhounov@gmail.com>
2020-09-28 18:18:36 +01:00

331 lines
7.0 KiB
Go

package commands
import (
"context"
"fmt"
"os"
"path"
"sync"
"text/tabwriter"
"time"
"github.com/ledgerwatch/turbo-geth/cmd/utils"
"github.com/ledgerwatch/lmdb-go/lmdb"
"github.com/ledgerwatch/turbo-geth/common"
"github.com/ledgerwatch/turbo-geth/common/dbutils"
"github.com/ledgerwatch/turbo-geth/core"
"github.com/ledgerwatch/turbo-geth/eth/stagedsync"
"github.com/ledgerwatch/turbo-geth/eth/stagedsync/stages"
"github.com/ledgerwatch/turbo-geth/ethdb"
"github.com/ledgerwatch/turbo-geth/log"
"github.com/spf13/cobra"
)
var cmdResetState = &cobra.Command{
Use: "reset_state",
Short: "Reset StateStages (5,6,7,8,9,10) and buckets",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := utils.RootContext()
err := resetState(ctx)
if err != nil {
log.Error(err.Error())
return err
}
if compact {
if err := copyCompact(); err != nil {
return err
}
}
return nil
},
}
var cmdClearUnwindStack = &cobra.Command{
Use: "clear_unwind_stack",
Short: "Clear unwind stack",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := utils.RootContext()
err := clearUnwindStack(ctx)
if err != nil {
log.Error(err.Error())
return err
}
return nil
},
}
func init() {
withChaindata(cmdResetState)
withCompact(cmdResetState)
rootCmd.AddCommand(cmdResetState)
withChaindata(cmdClearUnwindStack)
rootCmd.AddCommand(cmdClearUnwindStack)
}
func clearUnwindStack(_ context.Context) error {
db := ethdb.MustOpen(chaindata)
defer db.Close()
for _, stage := range stages.AllStages {
if err := stages.SaveStageUnwind(db, stage, 0, nil); err != nil {
return err
}
}
return nil
}
func resetState(_ context.Context) error {
db := ethdb.MustOpen(chaindata)
defer db.Close()
fmt.Printf("Before reset: \n")
if err := printStages(db); err != nil {
return err
}
core.UsePlainStateExecution = true
// don't reset senders here
if err := resetExec(db); err != nil {
return err
}
if err := stagedsync.ResetHashState(db); err != nil {
return err
}
if err := resetHistory(db); err != nil {
return err
}
if err := resetLogIndex(db); err != nil {
return err
}
if err := resetTxLookup(db); err != nil {
return err
}
if err := resetTxPool(db); err != nil {
return err
}
if err := resetFinish(db); err != nil {
return err
}
// set genesis after reset all buckets
if _, _, err := core.DefaultGenesisBlock().CommitGenesisState(db, false); err != nil {
return err
}
fmt.Printf("After reset: \n")
if err := printStages(db); err != nil {
return err
}
return nil
}
func resetSenders(db *ethdb.ObjectDatabase) error {
if err := db.ClearBuckets(
dbutils.Senders,
); err != nil {
return err
}
if err := stages.SaveStageProgress(db, stages.Senders, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.Senders, 0, nil); err != nil {
return err
}
return nil
}
func resetExec(db *ethdb.ObjectDatabase) error {
if err := db.ClearBuckets(
dbutils.CurrentStateBucket,
dbutils.AccountChangeSetBucket,
dbutils.StorageChangeSetBucket,
dbutils.ContractCodeBucket,
dbutils.PlainStateBucket,
dbutils.PlainAccountChangeSetBucket,
dbutils.PlainStorageChangeSetBucket,
dbutils.PlainContractCodeBucket,
dbutils.BlockReceiptsPrefix,
dbutils.IncarnationMapBucket,
dbutils.CodeBucket,
); err != nil {
return err
}
if err := stages.SaveStageProgress(db, stages.Execution, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.Execution, 0, nil); err != nil {
return err
}
return nil
}
func resetHistory(db *ethdb.ObjectDatabase) error {
if err := db.ClearBuckets(
dbutils.AccountsHistoryBucket,
dbutils.StorageHistoryBucket,
); err != nil {
return err
}
if err := stages.SaveStageProgress(db, stages.AccountHistoryIndex, 0, nil); err != nil {
return err
}
if err := stages.SaveStageProgress(db, stages.StorageHistoryIndex, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.AccountHistoryIndex, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.StorageHistoryIndex, 0, nil); err != nil {
return err
}
return nil
}
func resetLogIndex(db *ethdb.ObjectDatabase) error {
if err := db.ClearBuckets(
dbutils.LogAddressIndex,
dbutils.LogTopicIndex,
); err != nil {
return err
}
if err := stages.SaveStageProgress(db, stages.LogIndex, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.LogIndex, 0, nil); err != nil {
return err
}
return nil
}
func resetTxLookup(db *ethdb.ObjectDatabase) error {
if err := db.ClearBuckets(
dbutils.TxLookupPrefix,
); err != nil {
return err
}
if err := stages.SaveStageProgress(db, stages.TxLookup, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.TxLookup, 0, nil); err != nil {
return err
}
return nil
}
func resetTxPool(db ethdb.Putter) error {
if err := stages.SaveStageProgress(db, stages.TxPool, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.TxPool, 0, nil); err != nil {
return err
}
return nil
}
func resetFinish(db ethdb.Putter) error {
if err := stages.SaveStageProgress(db, stages.Finish, 0, nil); err != nil {
return err
}
if err := stages.SaveStageUnwind(db, stages.Finish, 0, nil); err != nil {
return err
}
return nil
}
func printStages(db *ethdb.ObjectDatabase) error {
var err error
var progress uint64
w := new(tabwriter.Writer)
defer w.Flush()
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
for _, stage := range stages.AllStages {
if progress, _, err = stages.GetStageProgress(db, stage); err != nil {
return err
}
fmt.Fprintf(w, "%s \t %d\n", string(stage), progress)
}
return nil
}
func copyCompact() error {
from := chaindata
backup := from + "_backup"
to := chaindata + "_copy"
log.Info("Start db copy-compact")
env, errOpen := lmdb.NewEnv()
if errOpen != nil {
return errOpen
}
if err := env.Open(from, lmdb.Readonly, 0644); err != nil {
return err
}
_ = os.RemoveAll(to)
if err := os.MkdirAll(to, 0744); err != nil {
return fmt.Errorf("could not create dir: %s, %w", to, err)
}
if err := env.SetMapSize(int64(ethdb.LMDBMapSize.Bytes())); err != nil {
return err
}
f, err := os.Stat(path.Join(from, "data.mdb"))
if err != nil {
return err
}
ctx, stopLogging := context.WithCancel(context.Background())
defer stopLogging()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
for {
time.Sleep(20 * time.Second)
select {
case <-ctx.Done():
return
default:
}
f2, err := os.Stat(path.Join(to, "data.mdb"))
if err != nil {
log.Error("Progress check failed", "err", err)
return
}
log.Info("Progress", "done", common.StorageSize(f2.Size()), "from", common.StorageSize(f.Size()))
}
}()
if err := env.CopyFlag(to, lmdb.CopyCompact); err != nil {
return fmt.Errorf("%w, from: %s, to: %s", err, from, to)
}
stopLogging()
wg.Wait()
if err := os.Rename(from, backup); err != nil {
return err
}
if err := os.Rename(to, from); err != nil {
return err
}
if err := os.RemoveAll(backup); err != nil {
return err
}
return nil
}