github.com/klaytn/klaytn@v1.10.2/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 27 "gopkg.in/urfave/cli.v1" 28 ) 29 30 var ( 31 dbFlags = []cli.Flag{ 32 // src DB 33 utils.DbTypeFlag, 34 utils.SingleDBFlag, 35 utils.NumStateTrieShardsFlag, 36 utils.DynamoDBTableNameFlag, 37 utils.DynamoDBRegionFlag, 38 utils.DynamoDBIsProvisionedFlag, 39 utils.DynamoDBReadCapacityFlag, 40 utils.DynamoDBWriteCapacityFlag, 41 utils.LevelDBCompressionTypeFlag, 42 utils.DataDirFlag, 43 } 44 dbMigrationFlags = append(dbFlags, DBMigrationFlags...) 45 46 MigrationCommand = cli.Command{ 47 Name: "db-migration", 48 Usage: "db migration", 49 Flags: []cli.Flag{}, 50 Category: "DB MIGRATION COMMANDS", 51 Description: ` 52 The migration command migrates a DB to another DB. 53 The type of DBs can be different. 54 (e.g. LevelDB -> LevelDB, LevelDB -> BadgerDB, LevelDB -> DynamoDB) 55 Note: This feature is only provided when srcDB is single LevelDB. 56 Note: Do not use db migration while a node is executing. 57 `, 58 Subcommands: []cli.Command{ 59 { 60 Name: "start", 61 Usage: "Start db migration", 62 Flags: dbMigrationFlags, 63 Action: utils.MigrateFlags(startMigration), 64 Description: ` 65 This command starts DB migration. 66 67 Even if db dir names are changed in srcDB, the original db dir names are used in dstDB. 68 (e.g. use 'statetrie' instead of 'statetrie_migrated_xxxxx') 69 If dst db is singleDB, you should set dst.datadir or db.dst.dynamo.tablename 70 to the original db dir name. 71 (e.g. Data dir : 'chaindata/klay/statetrie', Dynamo table name : 'klaytn-statetrie') 72 73 Note: This feature is only provided when srcDB is single LevelDB.`, 74 }, 75 }, 76 } 77 ) 78 79 func startMigration(ctx *cli.Context) error { 80 srcDBManager, dstDBManager, err := createDBManagerForMigration(ctx) 81 if err != nil { 82 return err 83 } 84 defer srcDBManager.Close() 85 defer dstDBManager.Close() 86 87 return srcDBManager.StartDBMigration(dstDBManager) 88 } 89 90 func createDBManagerForMigration(ctx *cli.Context) (database.DBManager, database.DBManager, error) { 91 // create db config from ctx 92 srcDBConfig, dstDBConfig, dbManagerCreationErr := createDBConfigForMigration(ctx) 93 if dbManagerCreationErr != nil { 94 return nil, nil, dbManagerCreationErr 95 } 96 97 // log 98 s, _ := json.Marshal(srcDBConfig) 99 d, _ := json.Marshal(dstDBConfig) 100 logger.Info("dbManager created", "\nsrcDB", string(s), "\ndstDB", string(d)) 101 102 // create DBManager 103 srcDBManager := database.NewDBManager(srcDBConfig) 104 dstDBManager := database.NewDBManager(dstDBConfig) 105 106 return srcDBManager, dstDBManager, nil 107 } 108 109 func createDBConfigForMigration(ctx *cli.Context) (*database.DBConfig, *database.DBConfig, error) { 110 // srcDB 111 srcDBC := &database.DBConfig{ 112 Dir: ctx.GlobalString(utils.DataDirFlag.Name), 113 DBType: database.DBType(ctx.GlobalString(utils.DbTypeFlag.Name)).ToValid(), 114 SingleDB: ctx.GlobalBool(utils.SingleDBFlag.Name), 115 NumStateTrieShards: ctx.GlobalUint(utils.NumStateTrieShardsFlag.Name), 116 OpenFilesLimit: database.GetOpenFilesLimit(), 117 118 LevelDBCacheSize: ctx.GlobalInt(utils.LevelDBCacheSizeFlag.Name), 119 LevelDBCompression: database.LevelDBCompressionType(ctx.GlobalInt(utils.LevelDBCompressionTypeFlag.Name)), 120 EnableDBPerfMetrics: !ctx.IsSet(utils.DBNoPerformanceMetricsFlag.Name), 121 122 DynamoDBConfig: &database.DynamoDBConfig{ 123 TableName: ctx.GlobalString(utils.DynamoDBTableNameFlag.Name), 124 Region: ctx.GlobalString(utils.DynamoDBRegionFlag.Name), 125 IsProvisioned: ctx.GlobalBool(utils.DynamoDBIsProvisionedFlag.Name), 126 ReadCapacityUnits: ctx.GlobalInt64(utils.DynamoDBReadCapacityFlag.Name), 127 WriteCapacityUnits: ctx.GlobalInt64(utils.DynamoDBWriteCapacityFlag.Name), 128 PerfCheck: !ctx.IsSet(utils.DBNoPerformanceMetricsFlag.Name), 129 }, 130 } 131 if len(srcDBC.DBType) == 0 { // changed to invalid type 132 return nil, nil, errors.New("srcDB is not specified or invalid : " + ctx.GlobalString(utils.DbTypeFlag.Name)) 133 } 134 135 // dstDB 136 dstDBC := &database.DBConfig{ 137 Dir: ctx.GlobalString(utils.DstDataDirFlag.Name), 138 DBType: database.DBType(ctx.GlobalString(utils.DstDbTypeFlag.Name)).ToValid(), 139 SingleDB: ctx.GlobalBool(utils.DstSingleDBFlag.Name), 140 NumStateTrieShards: ctx.GlobalUint(utils.DstNumStateTrieShardsFlag.Name), 141 OpenFilesLimit: database.GetOpenFilesLimit(), 142 143 LevelDBCacheSize: ctx.GlobalInt(utils.DstLevelDBCacheSizeFlag.Name), 144 LevelDBCompression: database.LevelDBCompressionType(ctx.GlobalInt(utils.DstLevelDBCompressionTypeFlag.Name)), 145 EnableDBPerfMetrics: !ctx.IsSet(utils.DBNoPerformanceMetricsFlag.Name), 146 147 DynamoDBConfig: &database.DynamoDBConfig{ 148 TableName: ctx.GlobalString(utils.DstDynamoDBTableNameFlag.Name), 149 Region: ctx.GlobalString(utils.DstDynamoDBRegionFlag.Name), 150 IsProvisioned: ctx.GlobalBool(utils.DstDynamoDBIsProvisionedFlag.Name), 151 ReadCapacityUnits: ctx.GlobalInt64(utils.DstDynamoDBReadCapacityFlag.Name), 152 WriteCapacityUnits: ctx.GlobalInt64(utils.DstDynamoDBWriteCapacityFlag.Name), 153 PerfCheck: !ctx.IsSet(utils.DBNoPerformanceMetricsFlag.Name), 154 }, 155 } 156 if len(dstDBC.DBType) == 0 { // changed to invalid type 157 return nil, nil, errors.New("dstDB is not specified or invalid : " + ctx.GlobalString(utils.DstDbTypeFlag.Name)) 158 } 159 160 return srcDBC, dstDBC, nil 161 } 162 163 // TODO When it is stopped, store previous db migration info. 164 // Continue migration on next call with the same setting.