github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/cmd/u2u/launcher/dbcmd.go (about) 1 package launcher 2 3 import ( 4 "fmt" 5 "path" 6 7 "github.com/syndtr/goleveldb/leveldb/opt" 8 "github.com/unicornultrafoundation/go-helios/u2udb" 9 "github.com/unicornultrafoundation/go-helios/u2udb/cachedproducer" 10 "github.com/unicornultrafoundation/go-helios/u2udb/multidb" 11 "github.com/unicornultrafoundation/go-u2u/cmd/utils" 12 "github.com/unicornultrafoundation/go-u2u/ethdb" 13 "github.com/unicornultrafoundation/go-u2u/log" 14 "gopkg.in/urfave/cli.v1" 15 16 "github.com/unicornultrafoundation/go-u2u/gossip" 17 "github.com/unicornultrafoundation/go-u2u/integration" 18 "github.com/unicornultrafoundation/go-u2u/utils/dbutil/compactdb" 19 ) 20 21 var ( 22 experimentalFlag = cli.BoolFlag{ 23 Name: "experimental", 24 Usage: "Allow experimental DB fixing", 25 } 26 dbCommand = cli.Command{ 27 Name: "db", 28 Usage: "A set of commands related to leveldb database", 29 Category: "DB COMMANDS", 30 Description: "", 31 Subcommands: []cli.Command{ 32 { 33 Name: "compact", 34 Usage: "Compact all databases", 35 ArgsUsage: "", 36 Action: utils.MigrateFlags(compact), 37 Category: "DB COMMANDS", 38 Flags: []cli.Flag{ 39 utils.DataDirFlag, 40 }, 41 Description: ` 42 u2u db compact 43 will compact all databases under datadir's chaindata. 44 `, 45 }, 46 { 47 Name: "transform", 48 Usage: "Transform DBs layout", 49 ArgsUsage: "", 50 Action: utils.MigrateFlags(dbTransform), 51 Category: "DB COMMANDS", 52 Flags: []cli.Flag{ 53 utils.DataDirFlag, 54 }, 55 Description: ` 56 u2u db transform 57 will migrate tables layout according to the configuration. 58 `, 59 }, 60 { 61 Name: "heal", 62 Usage: "Experimental - try to heal dirty DB", 63 ArgsUsage: "", 64 Action: utils.MigrateFlags(healDirty), 65 Category: "DB COMMANDS", 66 Flags: []cli.Flag{ 67 utils.DataDirFlag, 68 experimentalFlag, 69 }, 70 Description: ` 71 u2u db heal --experimental 72 Experimental - try to heal dirty DB. 73 `, 74 }, 75 }, 76 } 77 ) 78 79 func makeUncheckedDBsProducers(cfg *config) map[multidb.TypeName]u2udb.IterableDBProducer { 80 dbsList, _ := integration.SupportedDBs(path.Join(cfg.Node.DataDir, "chaindata"), cfg.DBs.RuntimeCache) 81 return dbsList 82 } 83 84 func makeUncheckedCachedDBsProducers(chaindataDir string) map[multidb.TypeName]u2udb.FullDBProducer { 85 dbTypes, _ := integration.SupportedDBs(chaindataDir, integration.DBsCacheConfig{ 86 Table: map[string]integration.DBCacheConfig{ 87 "": { 88 Cache: 1024 * opt.MiB, 89 Fdlimit: uint64(utils.MakeDatabaseHandles() / 2), 90 }, 91 }, 92 }) 93 wrappedDbTypes := make(map[multidb.TypeName]u2udb.FullDBProducer) 94 for typ, producer := range dbTypes { 95 wrappedDbTypes[typ] = cachedproducer.WrapAll(&integration.DummyScopedProducer{IterableDBProducer: producer}) 96 } 97 return wrappedDbTypes 98 } 99 100 func makeCheckedDBsProducers(cfg *config) map[multidb.TypeName]u2udb.IterableDBProducer { 101 if err := integration.CheckStateInitialized(path.Join(cfg.Node.DataDir, "chaindata"), cfg.DBs); err != nil { 102 utils.Fatalf(err.Error()) 103 } 104 return makeUncheckedDBsProducers(cfg) 105 } 106 107 func makeDirectDBsProducerFrom(dbsList map[multidb.TypeName]u2udb.IterableDBProducer, cfg *config) u2udb.FullDBProducer { 108 multiRawDbs, err := integration.MakeDirectMultiProducer(dbsList, cfg.DBs.Routing) 109 if err != nil { 110 utils.Fatalf("Failed to initialize multi DB producer: %v", err) 111 } 112 return multiRawDbs 113 } 114 115 func makeDirectDBsProducer(cfg *config) u2udb.FullDBProducer { 116 dbsList := makeCheckedDBsProducers(cfg) 117 return makeDirectDBsProducerFrom(dbsList, cfg) 118 } 119 120 func makeGossipStore(producer u2udb.FlushableDBProducer, cfg *config) *gossip.Store { 121 return gossip.NewStore(producer, cfg.U2UStore) 122 } 123 124 func compact(ctx *cli.Context) error { 125 126 cfg := makeAllConfigs(ctx) 127 128 producers := makeCheckedDBsProducers(cfg) 129 for typ, p := range producers { 130 for _, name := range p.Names() { 131 if err := compactDB(typ, name, p); err != nil { 132 return err 133 } 134 } 135 } 136 137 return nil 138 } 139 140 func compactDB(typ multidb.TypeName, name string, producer u2udb.DBProducer) error { 141 humanName := path.Join(string(typ), name) 142 db, err := producer.OpenDB(name) 143 defer db.Close() 144 if err != nil { 145 log.Error("Cannot open db or db does not exists", "db", humanName) 146 return err 147 } 148 149 log.Info("Stats before compaction", "db", humanName) 150 showDbStats(db) 151 152 err = compactdb.Compact(db, humanName, 64*opt.GiB) 153 if err != nil { 154 log.Error("Database compaction failed", "err", err) 155 return err 156 } 157 158 log.Info("Stats after compaction", "db", humanName) 159 showDbStats(db) 160 161 return nil 162 } 163 164 func showDbStats(db ethdb.KeyValueStater) { 165 if stats, err := db.Stat("stats"); err != nil { 166 log.Warn("Failed to read database stats", "error", err) 167 } else { 168 fmt.Println(stats) 169 } 170 if ioStats, err := db.Stat("iostats"); err != nil { 171 log.Warn("Failed to read database iostats", "error", err) 172 } else { 173 fmt.Println(ioStats) 174 } 175 }