blob: 9d93685d6dbc03866bff1881e5276377e29aefad [file] [log] [blame]
package modules
import (
"fmt"
"os"
"strings"
"time"
"veyron/lib/testutil/blackbox"
"veyron2/ipc"
"veyron2/naming"
"veyron2/rt"
)
func init() {
blackbox.CommandTable["clock"] = clockChild
blackbox.CommandTable["echo"] = echoChild
}
func clockChild(args []string) {
serve("clock", ipc.SoloDispatcher(NewServerClock(&clockServer{}), nil), args)
}
func echoChild(args []string) {
serve("echo", ipc.SoloDispatcher(NewServerEcho(&echoServer{}), nil), args)
}
func serve(msg string, dispatcher ipc.Dispatcher, args []string) {
rt.Init()
if len(args) != 3 {
bbExitWithError("wrong #args")
}
root := args[0]
prefix := args[1]
mp := args[2]
publish := true
if len(root) == 0 {
publish = false
}
fmt.Println("ready")
server, err := rt.R().NewServer()
if err != nil {
bbExitWithError(fmt.Sprintf("%s failed: %v", msg, err))
}
if err := server.Register(prefix, dispatcher); err != nil {
bbExitWithError(fmt.Sprintf("%s failed: %v", msg, err))
}
ep, err := server.Listen("tcp", "127.0.0.1:0")
if err != nil {
bbExitWithError(fmt.Sprintf("%s failed: %v", msg, err))
}
// Sadly, the name a client needs to use to invoke RPCs on us
// depends on whether we are using a MountTable or not. If we're
// not using a MountTable then the name is /<ep>/<prefix>, but if we
// are then it's /<ep of mount table>/<mp>!!
if publish {
fmt.Printf("NAME=%s\n", naming.MakeTerminal(naming.JoinAddressName(ep.String(), mp)))
if err := server.Publish(mp); err != nil {
bbExitWithError(fmt.Sprintf("%s failed: %v", msg, err))
}
} else {
fmt.Printf("NAME=%s\n", naming.MakeTerminal(naming.JoinAddressName(ep.String(), prefix)))
}
fmt.Printf("ADDR=%s\n", ep)
fmt.Printf("PID=%d\n", os.Getpid())
fmt.Println("running")
blackbox.WaitForEOFOnStdin()
}
type clockServer struct{}
func (*clockServer) Time(_ ipc.ServerContext, m string) (string, error) {
return fmt.Sprintf("(%s) %s", time.Now(), m), nil
}
type echoServer struct{}
func (*echoServer) Echo(_ ipc.ServerContext, m string) (string, error) {
return m, nil
}
type clock struct{ client bool }
func NewClockServer() T {
return &clock{false}
}
func NewClockClient() T {
return &clock{true}
}
func (c *clock) Help() string {
if c.client {
return `<name> <message>
executes name.Time(message)`
}
return `<root> <prefix> <suffix>
runs a clock server with root as its root mountTable, Register(prefix...) and Pubish(suffix)`
}
func (c *clock) Daemon() bool { return !c.client }
func (c *clock) Run(args []string) (Variables, []string, Handle, error) {
if !c.client {
if len(args) != 3 {
return nil, nil, nil, fmt.Errorf("wrong #args: %s", c.Help())
}
return runServer("clock", args)
}
if len(args) != 2 {
return nil, nil, nil, fmt.Errorf("wrong #args: %s", c.Help())
}
name := args[0]
message := args[1]
stub, err := BindClock(name)
if err != nil {
return nil, nil, nil, err
}
r, err := stub.Time(rt.R().NewContext(), message)
if err != nil {
return nil, nil, nil, err
}
v := make(Variables)
v.Update("TIME", strings.TrimRight(r, "\n"))
return v, []string{r}, nil, nil
}
type echo struct{ client bool }
func NewEchoServer() T {
return &echo{false}
}
func NewEchoClient() T {
return &echo{true}
}
func (e *echo) Help() string {
if e.client {
return `<name> <message>
executes name.Echo(message)`
}
return `<root> <prefix> <suffix>
runs a clock server with root as its root mountTable, Register(prefix...) and Pubish(suffix)`
}
func (e *echo) Daemon() bool { return !e.client }
func (e *echo) Run(args []string) (Variables, []string, Handle, error) {
if !e.client {
if len(args) != 3 {
return nil, nil, nil, fmt.Errorf("wrong #args: %s", e.Help())
}
return runServer("echo", args)
}
if len(args) != 2 {
return nil, nil, nil, fmt.Errorf("wrong #args: %s", e.Help())
}
name := args[0]
message := args[1]
stub, err := BindEcho(name)
if err != nil {
return nil, nil, nil, err
}
r, err := stub.Echo(rt.R().NewContext(), message)
if err != nil {
return nil, nil, nil, err
}
v := make(Variables)
v.Update("ECHO", strings.TrimRight(r, "\n"))
return v, []string{r}, nil, nil
}
func runServer(name string, args []string) (Variables, []string, Handle, error) {
env := []string{"MOUNTTABLE_ROOT=" + args[0]}
c, v, r, err := bbSpawn(name, args, env)
if err != nil {
return v, r, nil, err
}
h := &handle{c}
children.add(h)
return v, r, h, nil
}