github.com/klaytn/klaytn@v1.12.1/cmd/utils/nodecmd/migrationcmd.go (about) 1 // Modifications Copyright 2020 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of go-ethereum. 4 // 5 // go-ethereum is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 17 18 package nodecmd 19 20 import ( 21 "encoding/json" 22 23 "github.com/klaytn/klaytn/cmd/utils" 24 "github.com/klaytn/klaytn/storage/database" 25 "github.com/pkg/errors" 26 "github.com/urfave/cli/v2" 27 ) 28 29 var ( 30 dbMigrationFlags = append(utils.DBMigrationSrcFlags, utils.DBMigrationDstFlags...) 31 32 MigrationCommand = &cli.Command{ 33 Name: "db-migration", 34 Usage: "db migration", 35 Flags: []cli.Flag{}, 36 Category: "DB MIGRATION COMMANDS", 37 Description: ` 38 The migration command migrates a DB to another DB. 39 The type of DBs can be different. 40 (e.g. LevelDB -> LevelDB, LevelDB -> BadgerDB, LevelDB -> DynamoDB) 41 Note: This feature is only provided when srcDB is single LevelDB. 42 Note: Do not use db migration while a node is executing. 43 `, 44 Subcommands: []*cli.Command{ 45 { 46 Name: "start", 47 Usage: "Start db migration", 48 Flags: dbMigrationFlags, 49 Action: startMigration, 50 Description: ` 51 This command starts DB migration. 52 53 Even if db dir names are changed in srcDB, the original db dir names are used in dstDB. 54 (e.g. use 'statetrie' instead of 'statetrie_migrated_xxxxx') 55 If dst db is singleDB, you should set dst.datadir or db.dst.dynamo.tablename 56 to the original db dir name. 57 (e.g. Data dir : 'chaindata/klay/statetrie', Dynamo table name : 'klaytn-statetrie') 58 59 Note: This feature is only provided when srcDB is single LevelDB.`, 60 }, 61 }, 62 } 63 ) 64 65 func startMigration(ctx *cli.Context) error { 66 srcDBManager, dstDBManager, err := createDBManagerForMigration(ctx) 67 if err != nil { 68 return err 69 } 70 defer srcDBManager.Close() 71 defer dstDBManager.Close() 72 73 return srcDBManager.StartDBMigration(dstDBManager) 74 } 75 76 func createDBManagerForMigration(ctx *cli.Context) (database.DBManager, database.DBManager, error) { 77 // create db config from ctx 78 srcDBConfig, dstDBConfig, dbManagerCreationErr := createDBConfigForMigration(ctx) 79 if dbManagerCreationErr != nil { 80 return nil, nil, dbManagerCreationErr 81 } 82 83 // log 84 s, _ := json.Marshal(srcDBConfig) 85 d, _ := json.Marshal(dstDBConfig) 86 logger.Info("dbManager created", "\nsrcDB", string(s), "\ndstDB", string(d)) 87 88 // create DBManager 89 srcDBManager := database.NewDBManager(srcDBConfig) 90 dstDBManager := database.NewDBManager(dstDBConfig) 91 92 return srcDBManager, dstDBManager, nil 93 } 94 95 func createDBConfigForMigration(ctx *cli.Context) (*database.DBConfig, *database.DBConfig, error) { 96 // srcDB 97 srcDBC := &database.DBConfig{ 98 Dir: ctx.String(utils.DataDirFlag.Name), 99 DBType: database.DBType(ctx.String(utils.DbTypeFlag.Name)).ToValid(), 100 SingleDB: ctx.Bool(utils.SingleDBFlag.Name), 101 NumStateTrieShards: ctx.Uint(utils.NumStateTrieShardsFlag.Name), 102 OpenFilesLimit: database.GetOpenFilesLimit(), 103 104 LevelDBCacheSize: ctx.Int(utils.LevelDBCacheSizeFlag.Name), 105 LevelDBCompression: database.LevelDBCompressionType(ctx.Int(utils.LevelDBCompressionTypeFlag.Name)), 106 EnableDBPerfMetrics: !ctx.Bool(utils.DBNoPerformanceMetricsFlag.Name), 107 108 DynamoDBConfig: &database.DynamoDBConfig{ 109 TableName: ctx.String(utils.DynamoDBTableNameFlag.Name), 110 Region: ctx.String(utils.DynamoDBRegionFlag.Name), 111 IsProvisioned: ctx.Bool(utils.DynamoDBIsProvisionedFlag.Name), 112 ReadCapacityUnits: ctx.Int64(utils.DynamoDBReadCapacityFlag.Name), 113 WriteCapacityUnits: ctx.Int64(utils.DynamoDBWriteCapacityFlag.Name), 114 PerfCheck: !ctx.Bool(utils.DBNoPerformanceMetricsFlag.Name), 115 }, 116 117 RocksDBConfig: &database.RocksDBConfig{ 118 CacheSize: ctx.Uint64(utils.RocksDBCacheSizeFlag.Name), 119 DumpMallocStat: ctx.Bool(utils.RocksDBDumpMallocStatFlag.Name), 120 DisableMetrics: ctx.Bool(utils.RocksDBDisableMetricsFlag.Name), 121 Secondary: ctx.Bool(utils.RocksDBSecondaryFlag.Name), 122 CompressionType: ctx.String(utils.RocksDBCompressionTypeFlag.Name), 123 BottommostCompressionType: ctx.String(utils.RocksDBBottommostCompressionTypeFlag.Name), 124 FilterPolicy: ctx.String(utils.RocksDBFilterPolicyFlag.Name), 125 MaxOpenFiles: ctx.Int(utils.RocksDBMaxOpenFilesFlag.Name), 126 CacheIndexAndFilter: ctx.Bool(utils.RocksDBCacheIndexAndFilterFlag.Name), 127 }, 128 } 129 if len(srcDBC.DBType) == 0 { // changed to invalid type 130 return nil, nil, errors.New("srcDB is not specified or invalid : " + ctx.String(utils.DbTypeFlag.Name)) 131 } 132 133 // dstDB 134 dstDBC := &database.DBConfig{ 135 Dir: ctx.String(utils.DstDataDirFlag.Name), 136 DBType: database.DBType(ctx.String(utils.DstDbTypeFlag.Name)).ToValid(), 137 SingleDB: ctx.Bool(utils.DstSingleDBFlag.Name), 138 NumStateTrieShards: ctx.Uint(utils.DstNumStateTrieShardsFlag.Name), 139 OpenFilesLimit: database.GetOpenFilesLimit(), 140 141 LevelDBCacheSize: ctx.Int(utils.DstLevelDBCacheSizeFlag.Name), 142 LevelDBCompression: database.LevelDBCompressionType(ctx.Int(utils.DstLevelDBCompressionTypeFlag.Name)), 143 EnableDBPerfMetrics: !ctx.Bool(utils.DBNoPerformanceMetricsFlag.Name), 144 145 DynamoDBConfig: &database.DynamoDBConfig{ 146 TableName: ctx.String(utils.DstDynamoDBTableNameFlag.Name), 147 Region: ctx.String(utils.DstDynamoDBRegionFlag.Name), 148 IsProvisioned: ctx.Bool(utils.DstDynamoDBIsProvisionedFlag.Name), 149 ReadCapacityUnits: ctx.Int64(utils.DstDynamoDBReadCapacityFlag.Name), 150 WriteCapacityUnits: ctx.Int64(utils.DstDynamoDBWriteCapacityFlag.Name), 151 PerfCheck: !ctx.Bool(utils.DBNoPerformanceMetricsFlag.Name), 152 }, 153 154 RocksDBConfig: &database.RocksDBConfig{ 155 CacheSize: ctx.Uint64(utils.DstRocksDBCacheSizeFlag.Name), 156 DumpMallocStat: ctx.Bool(utils.DstRocksDBDumpMallocStatFlag.Name), 157 DisableMetrics: ctx.Bool(utils.DstRocksDBDisableMetricsFlag.Name), 158 Secondary: ctx.Bool(utils.DstRocksDBSecondaryFlag.Name), 159 CompressionType: ctx.String(utils.DstRocksDBCompressionTypeFlag.Name), 160 BottommostCompressionType: ctx.String(utils.DstRocksDBBottommostCompressionTypeFlag.Name), 161 FilterPolicy: ctx.String(utils.DstRocksDBFilterPolicyFlag.Name), 162 MaxOpenFiles: ctx.Int(utils.DstRocksDBMaxOpenFilesFlag.Name), 163 CacheIndexAndFilter: ctx.Bool(utils.DstRocksDBCacheIndexAndFilterFlag.Name), 164 }, 165 } 166 if len(dstDBC.DBType) == 0 { // changed to invalid type 167 return nil, nil, errors.New("dstDB is not specified or invalid : " + ctx.String(utils.DstDbTypeFlag.Name)) 168 } 169 170 return srcDBC, dstDBC, nil 171 } 172 173 // TODO When it is stopped, store previous db migration info. 174 // Continue migration on next call with the same setting.