func stats(args []string) { flags := flag.NewFlagSet("gumtool stats", flag.ExitOnError) dir := flags.String("dir", "", "DB dir") parallelism := flags.Int("parallelism", 4, "Parallelism for reading the DB") numOpenFiles := flags.Int("rlimit-nofile", 10000, "The value to set RLIMIT_NOFILE") flags.Parse(args) if *dir == "" { fatalln("-dir must be provided") } setRlimit(*numOpenFiles) db, err := gumshoe.OpenDBDir(*dir) if err != nil { log.Fatal(err) } mins, maxes := getColumnExtrema(db, *parallelism) fmt.Println("Dimension columns:") printStatsRow("name", "min", "max") printStatsRow("----", "---", "---") for i, col := range db.DimensionColumns { printStatsRow(col.Name, mins[i], maxes[i]) } fmt.Println("\nMetric columns:") printStatsRow("name", "min", "max") printStatsRow("----", "---", "---") offset := len(db.DimensionColumns) for i, col := range db.MetricColumns { printStatsRow(col.Name, mins[i+offset], maxes[i+offset]) } }
func merge(args []string) { flags := flag.NewFlagSet("gumtool merge", flag.ExitOnError) var ( newConfigFilename string oldDBPaths stringsFlag parallelism int numOpenFiles int flushSegments int ) flags.StringVar(&newConfigFilename, "new-db-config", "", "Filename of the new DB config") flags.Var(&oldDBPaths, "db-paths", "Paths to dirs of DBs to merge") flags.IntVar(¶llelism, "parallelism", 4, "Parallelism for merge workers") flags.IntVar(&numOpenFiles, "rlimit-nofile", 10000, "Value for RLIMIT_NOFILE") flags.IntVar(&flushSegments, "flush-segments", 500, "Flush after merging each N segments") flags.Parse(args) if len(oldDBPaths) == 0 { log.Fatalln("Need at least one entry in -db-paths; got 0") } setRlimit(numOpenFiles) f, err := os.Open(newConfigFilename) if err != nil { log.Fatal(err) } defer f.Close() _, schema, err := config.LoadTOMLConfig(f) if err != nil { log.Fatal(err) } newDB, err := gumshoe.NewDB(schema) if err != nil { log.Fatal(err) } defer newDB.Close() dbs := make([]*gumshoe.DB, len(oldDBPaths)) for i, path := range oldDBPaths { db, err := gumshoe.OpenDBDir(path) if err != nil { log.Fatalf("Error opening DB at %s: %s", path, err) } if err := db.Schema.Equivalent(schema); err != nil { log.Fatalf("Schema of DB at %s didn't match config at %s: %s", path, newConfigFilename, err) } dbs[i] = db } for _, db := range dbs { log.Printf("Merging db %s", db.Schema.Dir) if err := mergeDB(newDB, db, parallelism, flushSegments); err != nil { log.Fatalln("Error merging:", err) } db.Close() } }
func migrate(args []string) { flags := flag.NewFlagSet("gumtool migrate", flag.ExitOnError) oldDBPath := flags.String("old-db-path", "", "Path of old DB directory") newConfigFilename := flags.String("new-db-config", "", "Filename of new DB config file") parallelism := flags.Int("parallelism", 4, "Parallelism for reading old DB") numOpenFiles := flags.Int("rlimit-nofile", 10000, "The value to set RLIMIT_NOFILE") flushSegments := flags.Int("flush-segments", 500, "Flush after every N (old) segments") flags.Parse(args) // Attempt to raise the open file limit; necessary for big migrations setRlimit(*numOpenFiles) oldDB, err := gumshoe.OpenDBDir(*oldDBPath) if err != nil { log.Fatal(err) } defer oldDB.Close() f, err := os.Open(*newConfigFilename) if err != nil { log.Fatal(err) } defer f.Close() _, schema, err := config.LoadTOMLConfig(f) if err != nil { log.Fatal(err) } newDB, err := gumshoe.NewDB(schema) if err != nil { log.Fatal(err) } defer newDB.Close() if err := migrateDBs(newDB, oldDB, *parallelism, *flushSegments); err != nil { log.Fatal(err) } fmt.Println("done") }