go.dedis.ch/onet/v3@v3.2.11-0.20210930124529-e36530bca7ef/dbadmin/main.go (about) 1 package main 2 3 import ( 4 "os" 5 "regexp" 6 7 "go.etcd.io/bbolt" 8 9 "github.com/urfave/cli" 10 "go.dedis.ch/onet/v3/log" 11 "golang.org/x/xerrors" 12 ) 13 14 func main() { 15 cliApp := cli.NewApp() 16 cliApp.Name = "dbadmin" 17 cliApp.Usage = "work with onet service dbs" 18 cliApp.Version = "0.1" 19 cliApp.Commands = cli.Commands{ 20 { 21 Name: "inspect", 22 Usage: "print information about an existing db", 23 Action: inspect, 24 ArgsUsage: "source.db", 25 Flags: cli.FlagsByName{ 26 cli.StringFlag{ 27 Name: "source,src", 28 Usage: "Indicate source database", 29 Required: false, 30 TakesFile: true, 31 }, 32 cli.BoolFlag{ 33 Name: "verbose,v", 34 Usage: "print additional information", 35 }, 36 }, 37 }, 38 { 39 Name: "extract", 40 Usage: "extract information from one db", 41 Action: extract, 42 ArgsUsage: "service1 [service2 [service3...]]", 43 Flags: cli.FlagsByName{ 44 cli.StringFlag{ 45 Name: "source,src", 46 Usage: "Indicate source database", 47 Required: true, 48 TakesFile: true, 49 }, 50 cli.StringFlag{ 51 Name: "destination,dst", 52 Usage: "Indicate destination database - must not" + 53 " exist yet", 54 Required: true, 55 TakesFile: true, 56 }, 57 cli.BoolFlag{ 58 Name: "overwrite", 59 Usage: "allow overwriting of existing dbs and" + 60 " buckets", 61 Required: false, 62 }, 63 }, 64 }, 65 } 66 cliApp.Flags = []cli.Flag{ 67 cli.IntFlag{ 68 Name: "debug, d", 69 Value: 0, 70 Usage: "debug-level: 1 for terse, 5 for maximal", 71 }, 72 } 73 cliApp.Before = func(c *cli.Context) error { 74 log.SetDebugVisible(c.Int("debug")) 75 return nil 76 } 77 78 err := cliApp.Run(os.Args) 79 if err != nil { 80 log.Fatalf("Error while running app: %+v", err) 81 } 82 } 83 84 func inspect(c *cli.Context) error { 85 var dbName string 86 if c.NArg() != 1 { 87 if c.String("source") == "" { 88 return xerrors.New("Please give the following arguments: source.db") 89 } 90 dbName = c.String("source") 91 } else { 92 dbName = c.Args().First() 93 } 94 verbose := c.Bool("verbose") 95 if _, err := os.Stat(dbName); os.IsNotExist(err) { 96 return xerrors.New("this db doesn't exist") 97 } 98 db, err := bbolt.Open(dbName, 0600, nil) 99 if err != nil { 100 return xerrors.Errorf("opening db: %v", err) 101 } 102 103 log.Info("Opened", dbName) 104 105 err = db.View(func(tx *bbolt.Tx) error { 106 return tx.ForEach(func(name []byte, b *bbolt.Bucket) error { 107 log.Info("Bucket:", string(name)) 108 if verbose { 109 stats := b.Stats() 110 log.Infof("Has %d entries using %d bytes", stats.KeyN, 111 stats.LeafAlloc) 112 } 113 return nil 114 }) 115 }) 116 if err != nil { 117 return xerrors.Errorf("couldn't list buckets: %+v", err) 118 } 119 120 return nil 121 } 122 123 func extract(c *cli.Context) error { 124 var buckets []*regexp.Regexp 125 if c.NArg() == 0 { 126 log.Info("No service given - copying all services") 127 buckets = append(buckets, regexp.MustCompile(".*")) 128 } else { 129 for _, b := range c.Args() { 130 buckets = append(buckets, regexp.MustCompile(b)) 131 } 132 } 133 134 overwrite := c.Bool("overwrite") 135 srcName := c.String("source") 136 dstName := c.String("destination") 137 if _, err := os.Stat(srcName); err != nil { 138 return xerrors.Errorf("cannot read '%s': %v", srcName, err) 139 } 140 if _, err := os.Stat(dstName); err == nil && !overwrite { 141 return xerrors.Errorf("destination '%s' will be created, "+ 142 "please remove it first", dstName) 143 } 144 145 dbSrc, err := bbolt.Open(srcName, 0600, nil) 146 if err != nil { 147 return xerrors.Errorf("couldn't open source-DB: %v", err) 148 } 149 dbDst, err := bbolt.Open(dstName, 0600, nil) 150 if err != nil { 151 return xerrors.Errorf("couldn't open destination-DB: %v", err) 152 } 153 154 err = dbSrc.View(func(txSrc *bbolt.Tx) error { 155 return dbDst.Update(func(txDest *bbolt.Tx) error { 156 return txSrc.ForEach(func(name []byte, bSrc *bbolt.Bucket) error { 157 extr := false 158 for _, b := range buckets { 159 if b.Match(name) { 160 extr = true 161 break 162 } 163 } 164 if extr { 165 log.Info("Extracting bucket:", string(name)) 166 bDst, err := txDest.CreateBucket(name) 167 if err != nil { 168 return xerrors.Errorf("couldn't create bucket: %v", err) 169 } 170 return bSrc.ForEach(func(k, v []byte) error { 171 return bDst.Put(k, v) 172 }) 173 } 174 return nil 175 }) 176 }) 177 }) 178 if err != nil { 179 return xerrors.Errorf("error while copying: %v", err) 180 } 181 if err := dbSrc.Close(); err != nil { 182 return xerrors.Errorf("couldn't close source DB: %v", err) 183 } 184 if err := dbDst.Close(); err != nil { 185 return xerrors.Errorf("couldn't close destination DB: %v", err) 186 } 187 return nil 188 }