// DoCommand serves as a switchboard for commands, handling local ones and // sending via rpc those commands that need a running server. func DoCommand(cmd dvid.Command) error { if len(cmd) == 0 { return fmt.Errorf("Blank command!") } switch cmd.Name() { // Handle commands that don't require server connection case "serve": return DoServe(cmd) case "repair": return DoRepair(cmd) case "about": fmt.Println(server.About()) // Send everything else to server via DVID terminal default: request := datastore.Request{Command: cmd} if *useStdin { var err error request.Input, err = ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("Error in reading from standard input: %v", err) } } return server.SendRPC(*rpcAddress, request) } return nil }
// DoServe opens a datastore then creates both web and rpc servers for the datastore func DoServe(cmd dvid.Command) error { // Capture ctrl+c and other interrupts. Then handle graceful shutdown. stopSig := make(chan os.Signal) go func() { for sig := range stopSig { log.Printf("Stop signal captured: %q. Shutting down...\n", sig) if *memprofile != "" { log.Printf("Storing memory profiling to %s...\n", *memprofile) f, err := os.Create(*memprofile) if err != nil { log.Fatal(err) } pprof.WriteHeapProfile(f) f.Close() } if *cpuprofile != "" { log.Printf("Stopping CPU profiling to %s...\n", *cpuprofile) pprof.StopCPUProfile() } server.Shutdown() time.Sleep(1 * time.Second) os.Exit(0) } }() signal.Notify(stopSig, os.Interrupt, os.Kill, syscall.SIGTERM) // Check if there is a configuration file, and if so, set logger. logConfig, err := server.LoadConfig(*configfile) if err != nil { return fmt.Errorf("Error loading configuration file %q: %v\n", *configfile, err) } logConfig.SetLogger() // Load datastore metadata and initialize datastore dbpath := cmd.Argument(1) if dbpath == "" { return fmt.Errorf("serve command must be followed by the path to the datastore") } if err := local.Initialize(dbpath, cmd.Settings()); err != nil { return fmt.Errorf("Unable to initialize local storage: %v\n", err) } if err := datastore.Initialize(); err != nil { return fmt.Errorf("Unable to initialize datastore: %v\n", err) } // add handlers to help us track memory usage - they don't track memory until they're told to profiler.AddMemoryProfilingHandlers() // Uncomment if you want to start profiling automatically // profiler.StartProfiling() // listen on port 6060 (pick a port) go http.ListenAndServe(":6060", nil) // Serve HTTP and RPC if err := server.Serve(*httpAddress, *clientDir, *rpcAddress); err != nil { return err } return nil }
// DoCreate creates a new DVID datastore. func DoCreate(cmd dvid.Command) error { datastorePath := cmd.Argument(1) if datastorePath == "" { return fmt.Errorf("create command must be followed by the path to the datastore") } kvCanStoreMetadata := true // We assume this for local key value stores. return datastore.Create(datastorePath, kvCanStoreMetadata, cmd.Settings()) }
// DoRepair performs the "repair" command, trying to repair a storage engine func DoRepair(cmd dvid.Command) error { datastorePath := cmd.Argument(1) if datastorePath == "" { return fmt.Errorf("repair command must be followed by the path to the datastore") } if err := datastore.Repair(datastorePath, cmd.Settings()); err != nil { return err } fmt.Printf("Ran repair on database at %s.\n", datastorePath) return nil }
// DoRepair performs the "repair" command, trying to repair a storage engine func DoRepair(cmd dvid.Command) error { engineName := cmd.Argument(1) path := cmd.Argument(2) if path == "" { return fmt.Errorf("repair command must be followed by engine name and path to the datastore") } if err := storage.Repair(engineName, path); err != nil { return err } fmt.Printf("Ran repair on %q database at %s.\n", engineName, path) return nil }