// Send transmits an RPC command if a server is available. func (c *Client) Send(request datastore.Request) error { var reply datastore.Response if c.client != nil { err := c.client.Call("RPCConnection.Do", request, &reply) if err != nil { return fmt.Errorf("RPC error for '%s': %v", request.Command, err) } } else { reply.Output = []byte(fmt.Sprintf("No DVID server is available: %s\n", request.Command)) } return reply.Write(os.Stdout) }
// Do handles command-line requests to the Google BrainMaps API func (dtype *Type) Do(cmd datastore.Request, reply *datastore.Response) error { switch cmd.Argument(1) { case "volumes": // Read in the JSON Web Token jwtdata, err := ioutil.ReadFile(cmd.Argument(2)) if err != nil { return fmt.Errorf("Cannot load JSON Web Token file (%s): %v", cmd.Argument(2), err) } conf, err := google.JWTConfigFromJSON(jwtdata, "https://www.googleapis.com/auth/brainmaps") if err != nil { return fmt.Errorf("Cannot establish JWT Config file from Google: %v", err) } client := conf.Client(oauth2.NoContext) // Make the call. url := fmt.Sprintf("%s/volumes", bmapsPrefix) resp, err := client.Get(url) if err != nil { return fmt.Errorf("Error getting volumes metadata from Google: %v", err) } if resp.StatusCode != http.StatusOK { return fmt.Errorf("Unexpected status code %d returned when getting volumes for user", resp.StatusCode) } metadata, err := ioutil.ReadAll(resp.Body) if err != nil { return err } resp.Body.Close() reply.Text = string(metadata) return nil default: return fmt.Errorf("unknown command for type %s", dtype.GetTypeName()) } }
// put handles a PUT command-line request. func (d *Data) put(cmd datastore.Request, reply *datastore.Response) error { if len(cmd.Command) < 5 { return fmt.Errorf("The key name must be specified after 'put'") } if len(cmd.Input) == 0 { return fmt.Errorf("No data was passed into standard input") } var uuidStr, dataName, cmdStr, keyStr string cmd.CommandArgs(1, &uuidStr, &dataName, &cmdStr, &keyStr) _, versionID, err := datastore.MatchingUUID(uuidStr) if err != nil { return err } // Store data if !d.Versioned() { // Map everything to root version. versionID, err = datastore.GetRepoRootVersion(versionID) if err != nil { return err } } ctx := datastore.NewVersionedCtx(d, versionID) if err = d.PutData(ctx, keyStr, cmd.Input); err != nil { return fmt.Errorf("Error on put to key %q for keyvalue %q: %v\n", keyStr, d.DataName(), err) } reply.Output = []byte(fmt.Sprintf("Put %d bytes into key %q for keyvalue %q, uuid %s\n", len(cmd.Input), keyStr, d.DataName(), uuidStr)) return nil }
// DoRPC handles the 'generate' command. func (d *Data) DoRPC(request datastore.Request, reply *datastore.Response) error { if request.TypeCommand() != "generate" { return fmt.Errorf("Unknown command. Data instance '%s' [%s] does not support '%s' command.", d.DataName(), d.TypeName(), request.TypeCommand()) } var uuidStr, dataName, cmdStr string request.CommandArgs(1, &uuidStr, &dataName, &cmdStr) // Get the imagetile generation configuration from a file or stdin. var err error var tileSpec TileSpec if request.Input != nil { tileSpec, err = LoadTileSpec(request.Input) if err != nil { return err } } else { config := request.Settings() filename, found, err := config.GetString("filename") if err != nil { return err } if found { configData, err := storage.DataFromFile(filename) if err != nil { return err } tileSpec, err = LoadTileSpec(configData) if err != nil { return err } dvid.Infof("Using tile spec file: %s\n", filename) } else { dvid.Infof("Using default tile generation method since no tile spec file was given...\n") tileSpec, err = d.DefaultTileSpec(uuidStr) if err != nil { return err } } } reply.Text = fmt.Sprintf("Tiling data instance %q @ node %s...\n", dataName, uuidStr) go func() { err := d.ConstructTiles(uuidStr, tileSpec, request) if err != nil { dvid.Errorf("Cannot construct tiles for data instance %q @ node %s: %v\n", dataName, uuidStr, err) } }() return nil }
// LoadLocal adds image data to a version node. See HelpMessage for example of // command-line use of "load local". func (d *Data) LoadLocal(request datastore.Request, reply *datastore.Response) error { timedLog := dvid.NewTimeLog() // Parse the request var uuidStr, dataName, cmdStr, sourceStr, filename string _ = request.CommandArgs(1, &uuidStr, &dataName, &cmdStr, &sourceStr, &filename) // Get the uuid from a uniquely identifiable string uuid, versionID, err := datastore.MatchingUUID(uuidStr) if err != nil { return fmt.Errorf("Could not find node with UUID %s: %v", uuidStr, err) } // Load the V3D Raw file. ext := filepath.Ext(filename) switch ext { case ".raw", ".v3draw": default: return fmt.Errorf("Unknown extension '%s' when expected V3D Raw file", ext) } file, err := os.Open(filename) if err != nil { return err } unmarshaler := V3DRawMarshaler{} channels, err := unmarshaler.UnmarshalV3DRaw(file) if err != nil { return err } // Store the metadata d.NumChannels = len(channels) d.Properties.Values = make(dvid.DataValues, d.NumChannels) if d.NumChannels > 0 { reply.Text = fmt.Sprintf("Loaded %s into data '%s': found %d channels\n", d.DataName(), filename, d.NumChannels) reply.Text += fmt.Sprintf(" %s", channels[0]) } else { reply.Text = fmt.Sprintf("Found no channels in file %s\n", filename) return nil } for i, channel := range channels { d.Properties.Values[i] = channel.Voxels.Values()[0] } // Get repo and save it. if err := datastore.SaveDataByUUID(uuid, d); err != nil { return err } // PUT each channel of the file into the datastore using a separate data name. for _, channel := range channels { dvid.Infof("Processing channel %d... \n", channel.channelNum) err = d.PutVoxels(versionID, channel.Voxels, nil) if err != nil { return err } } // Create a RGB composite from the first 3 channels. This is considered to be channel 0 // or can be accessed with the base data name. dvid.Infof("Creating composite image from channels...\n") err = d.storeComposite(versionID, channels) if err != nil { return err } timedLog.Infof("RPC load local '%s' completed", filename) return nil }
// Do acts as a switchboard for remote command execution func (c *RPCConnection) Do(cmd datastore.Request, reply *datastore.Response) error { if reply == nil { dvid.Debugf("reply is nil coming in!\n") return nil } if cmd.Name() == "" { return fmt.Errorf("Server error: got empty command!") } switch cmd.Name() { case "help": reply.Text = fmt.Sprintf(RPCHelpMessage, config.RPCAddress(), config.HTTPAddress()) case "shutdown": Shutdown() // Make this process shutdown in a second to allow time for RPC to finish. // TODO -- Better way to do this? log.Printf("DVID server halted due to 'shutdown' command.") reply.Text = fmt.Sprintf("DVID server at %s has been halted.\n", config.RPCAddress()) go func() { time.Sleep(1 * time.Second) os.Exit(0) }() case "types": if len(cmd.Command) == 1 { text := "\nData Types within this DVID Server\n" text += "----------------------------------\n" mapTypes, err := datastore.Types() if err != nil { return fmt.Errorf("Error trying to retrieve data types within this DVID server!") } for url, typeservice := range mapTypes { text += fmt.Sprintf("%-20s %s\n", typeservice.GetTypeName(), url) } reply.Text = text } else { if len(cmd.Command) != 3 || cmd.Command[2] != "help" { return fmt.Errorf("Unknown types command: %q", cmd.Command) } var typename string cmd.CommandArgs(1, &typename) typeservice, err := datastore.TypeServiceByName(dvid.TypeString(typename)) if err != nil { return err } reply.Text = typeservice.Help() } case "repos": var subcommand, alias, description, uuidStr string cmd.CommandArgs(1, &subcommand, &alias, &description, &uuidStr) switch subcommand { case "new": var assign *dvid.UUID if uuidStr == "" { assign = nil } else { u := dvid.UUID(uuidStr) assign = &u } root, err := datastore.NewRepo(alias, description, assign) if err != nil { return err } if err := datastore.SetRepoAlias(root, alias); err != nil { return err } if err := datastore.SetRepoDescription(root, description); err != nil { return err } reply.Text = fmt.Sprintf("New repo %q created with head node %s\n", alias, root) default: return fmt.Errorf("Unknown repos command: %q", subcommand) } case "repo": var uuidStr, subcommand string cmd.CommandArgs(1, &uuidStr, &subcommand) uuid, _, err := datastore.MatchingUUID(uuidStr) if err != nil { return err } switch subcommand { case "new": var typename, dataname string cmd.CommandArgs(3, &typename, &dataname) // Get TypeService typeservice, err := datastore.TypeServiceByName(dvid.TypeString(typename)) if err != nil { return err } // Create new data config := cmd.Settings() _, err = datastore.NewData(uuid, typeservice, dvid.InstanceName(dataname), config) if err != nil { return err } reply.Text = fmt.Sprintf("Data %q [%s] added to node %s\n", dataname, typename, uuid) datastore.AddToRepoLog(uuid, []string{cmd.String()}) case "branch": cmd.CommandArgs(3, &uuidStr) var assign *dvid.UUID if uuidStr == "" { assign = nil } else { u := dvid.UUID(uuidStr) assign = &u } child, err := datastore.NewVersion(uuid, fmt.Sprintf("branch of %s", uuid), assign) if err != nil { return err } reply.Text = fmt.Sprintf("Branch %s added to node %s\n", child, uuid) datastore.AddToRepoLog(uuid, []string{cmd.String()}) case "merge": uuids := cmd.CommandArgs(2) parents := make([]dvid.UUID, len(uuids)+1) parents[0] = dvid.UUID(uuid) i := 1 for uuid := range uuids { parents[i] = dvid.UUID(uuid) i++ } child, err := datastore.Merge(parents, fmt.Sprintf("merge of parents %v", parents), datastore.MergeConflictFree) if err != nil { return err } reply.Text = fmt.Sprintf("Parents %v merged into node %s\n", parents, child) datastore.AddToRepoLog(uuid, []string{cmd.String()}) case "push": /* var target string cmd.CommandArgs(3, &target) config := cmd.Settings() if err = datastore.Push(repo, target, config); err != nil { return err } reply.Text = fmt.Sprintf("Repo %q pushed to %q\n", repo.RootUUID(), target) */ return fmt.Errorf("push command has been temporarily suspended") default: return fmt.Errorf("Unknown command: %q", cmd) } case "node": var uuidStr, descriptor string cmd.CommandArgs(1, &uuidStr, &descriptor) uuid, _, err := datastore.MatchingUUID(uuidStr) if err != nil { return err } // Get the DataService dataname := dvid.InstanceName(descriptor) var subcommand string cmd.CommandArgs(3, &subcommand) dataservice, err := datastore.GetDataByUUID(uuid, dataname) if err != nil { return err } if subcommand == "help" { reply.Text = dataservice.Help() return nil } return dataservice.DoRPC(cmd, reply) default: return fmt.Errorf("Unknown command: '%s'", cmd) } return nil }