veyron/tools/naming/simulator: reworked to use new modules and to be more useful.
Change-Id: Ieef4412b995b289957326cc06f2c48990ba99112
diff --git a/lib/modules/core/core.go b/lib/modules/core/core.go
index 980313e..98a6656 100644
--- a/lib/modules/core/core.go
+++ b/lib/modules/core/core.go
@@ -53,6 +53,10 @@
ResolveMTCommand = "resolveMT"
EchoServerCommand = "echoServer"
EchoClientCommand = "echoClient"
+ SleepCommand = "sleep"
+ TimeCommand = "time"
+ MountCommand = "mount"
+ NamespaceCacheCommand = "cache"
)
// NewShell returns a new Shell instance with the core commands installed.
@@ -77,6 +81,14 @@
resolves name to obtain a mount table address`)
shell.AddFunction(SetNamespaceRootsCommand, setNamespaceRoots, `<name>...
set the in-process namespace roots to <name>...`)
+ shell.AddFunction(SleepCommand, sleep, `[duration]
+ sleep for a time (in go time.Duration format): defaults to 1s`)
+ shell.AddFunction(TimeCommand, now, `
+ prints the current time`)
+ shell.AddFunction(NamespaceCacheCommand, namespaceCache, `on|off
+ turns the namespace cache on or off`)
+ shell.AddFunction(MountCommand, mountServer, `<mountpoint> <server> <ttl>
+ invokes namespace.Mount(<mountpoint>, <server>, <ttl>)`)
shell.AddSubprocess(EchoClientCommand, `<name> <message>...
invokes name.Echo(message)`)
shell.AddSubprocess(EchoServerCommand, `<name> <text>
diff --git a/lib/modules/core/echo.go b/lib/modules/core/echo.go
index ae37372..55bc787 100644
--- a/lib/modules/core/echo.go
+++ b/lib/modules/core/echo.go
@@ -8,6 +8,7 @@
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
+ "veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron/lib/modules"
)
@@ -17,19 +18,29 @@
modules.RegisterChild(EchoClientCommand, echoClient)
}
+type treeDispatcher struct{ id string }
+
+func (d treeDispatcher) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
+ return ipc.ReflectInvoker(&echoServerObject{d.id, suffix}), nil, nil
+}
+
type echoServerObject struct {
- id string
+ id, suffix string
}
func (es *echoServerObject) Echo(call ipc.ServerCall, m string) (string, error) {
- return es.id + ": " + m + "\n", nil
+ if len(es.suffix) > 0 {
+ return fmt.Sprintf("%s.%s: %s\n", es.id, es.suffix, m), nil
+ }
+ return fmt.Sprintf("%s: %s\n", es.id, m), nil
}
func echoServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
if len(args) != 2 {
return fmt.Errorf("wrong # args")
}
- id, mountPoint := args[0], args[1]
+ id, mp := args[0], args[1]
+ disp := &treeDispatcher{id: id}
server, err := rt.R().NewServer()
if err != nil {
return err
@@ -39,7 +50,7 @@
if err != nil {
return err
}
- if err := server.Serve(mountPoint, ipc.LeafDispatcher(&echoServerObject{id: id}, nil)); err != nil {
+ if err := server.Serve(mp, disp); err != nil {
return err
}
fmt.Fprintf(stdout, "NAME=%s\n", naming.MakeTerminal(naming.JoinAddressName(ep.String(), "")))
@@ -50,7 +61,6 @@
}
func echoClient(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
-
if len(args) < 2 {
return fmt.Errorf("wrong # args")
}
diff --git a/lib/modules/core/misc.go b/lib/modules/core/misc.go
new file mode 100644
index 0000000..e0c1496
--- /dev/null
+++ b/lib/modules/core/misc.go
@@ -0,0 +1,64 @@
+package core
+
+import (
+ "fmt"
+ "io"
+ "time"
+
+ "veyron.io/veyron/veyron2/naming"
+ "veyron.io/veyron/veyron2/rt"
+)
+
+func sleep(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+ d := time.Second
+ if len(args) > 0 {
+ var err error
+ if d, err = time.ParseDuration(args[0]); err != nil {
+ return err
+ }
+ }
+ fmt.Fprintf(stdout, "Sleeping for %s", d)
+ // TODO(cnicolaou): we should probably also listen for stdin closing
+ // and return before the sleep completes.
+ time.Sleep(d)
+ return nil
+}
+
+func now(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+ fmt.Fprintf(stdout, "%s\n", time.Now())
+ return nil
+}
+
+func mountServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+ if len(args) != 3 {
+ return fmt.Errorf("wrong # args")
+ }
+ mp, server, ttlstr := args[0], args[1], args[2]
+ ttl, err := time.ParseDuration(ttlstr)
+ if err != nil {
+ return fmt.Errorf("failed to parse time from %q", ttlstr)
+ }
+ ns := rt.R().Namespace()
+ if err := ns.Mount(rt.R().NewContext(), mp, server, ttl); err != nil {
+ return err
+ }
+ fmt.Fprintf(stdout, "Mount(%s, %s, %s)\n", mp, server, ttl)
+ return nil
+}
+
+func namespaceCache(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+ if len(args) != 1 {
+ return fmt.Errorf("wrong # args")
+ }
+ disable := true
+ switch args[0] {
+ case "on":
+ disable = false
+ case "off":
+ disable = true
+ default:
+ return fmt.Errorf("arg must be 'on' or 'off'")
+ }
+ rt.R().Namespace().CacheCtl(naming.DisableCache(disable))
+ return nil
+}
diff --git a/lib/modules/core/mounttable.go b/lib/modules/core/mounttable.go
index 1c523e0..8d63006 100644
--- a/lib/modules/core/mounttable.go
+++ b/lib/modules/core/mounttable.go
@@ -58,6 +58,7 @@
}
name := naming.JoinAddressName(ep.String(), "")
fmt.Fprintf(stdout, "MT_NAME=%s\n", name)
+ fmt.Fprintf(stdout, "MT_ADDR=%s\n", ep.String())
fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
modules.WaitForEOF(stdin)
return nil
@@ -82,7 +83,7 @@
output += fmt.Sprintf("R%d=%s[", entry, n.Name)
t := ""
for _, s := range n.Servers {
- output += fmt.Sprintf("%s:%ss, ", s.Server, s.TTL)
+ t += fmt.Sprintf("%s:%s, ", s.Server, s.TTL)
}
t = strings.TrimSuffix(t, ", ")
output += fmt.Sprintf("%s]\n", t)
@@ -110,6 +111,7 @@
name := args[0]
servers, err := fn(rt.R().NewContext(), name)
if err != nil {
+ fmt.Fprintf(stdout, "RN=0\n")
return err
}
fmt.Fprintf(stdout, "RN=%d\n", len(servers))
diff --git a/lib/modules/exec.go b/lib/modules/exec.go
index 20137b1..e2e35db 100644
--- a/lib/modules/exec.go
+++ b/lib/modules/exec.go
@@ -54,8 +54,9 @@
return fl
}
-// IsTestSubprocess returns true if it is called in via -run=TestHelperProcess
-// which normally only ever happens for subprocess run from tests.
+// IsTestHelperProces returns true if it is called in via
+// -run=TestHelperProcess which normally only ever happens for subprocesses
+// run from tests.
func IsTestHelperProcess() bool {
runFlag := flag.Lookup("test.run")
if runFlag == nil {
@@ -188,7 +189,7 @@
return eh.cmd.Wait()
}
-const shellEntryPoint = "VEYRON_SHELL_HELPER_PROCESS_ENTRY_POINT"
+const ShellEntryPoint = "VEYRON_SHELL_HELPER_PROCESS_ENTRY_POINT"
func RegisterChild(name string, main Main) {
child.Lock()
@@ -208,9 +209,9 @@
}
func (child *childRegistrar) dispatch() error {
- command := os.Getenv(shellEntryPoint)
+ command := os.Getenv(ShellEntryPoint)
if len(command) == 0 {
- return fmt.Errorf("Failed to find entrypoint %q", shellEntryPoint)
+ return fmt.Errorf("Failed to find entrypoint %q", ShellEntryPoint)
}
child.Lock()
m := child.mains[command]
diff --git a/lib/modules/func.go b/lib/modules/func.go
index f44127b..319a673 100644
--- a/lib/modules/func.go
+++ b/lib/modules/func.go
@@ -70,6 +70,9 @@
err := main(stdin, stdout, stderr, sh.mergeOSEnv(), args...)
if err != nil {
+ // Print the error to stdout to ensure that anyone reading
+ // only stdout sees the error.
+ fmt.Fprintf(stdout, "%s\n", err)
fmt.Fprintf(stderr, "%s\n", err)
}
diff --git a/lib/modules/modules_internal_test.go b/lib/modules/modules_internal_test.go
index 920538d..000819b 100644
--- a/lib/modules/modules_internal_test.go
+++ b/lib/modules/modules_internal_test.go
@@ -31,6 +31,7 @@
func TestState(t *testing.T) {
sh := NewShell()
+
sh.AddSubprocess("echonotregistered", "[args]*")
sh.AddSubprocess("echos", "[args]*")
sh.AddFunction("echof", Echo, "[args]*")
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index 2e35c97..561e3b2 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -129,7 +129,7 @@
if !child.hasCommand(name) {
vlog.Infof("Warning: %q is not registered with modules.Dispatcher", name)
}
- entryPoint := shellEntryPoint + "=" + name
+ entryPoint := ShellEntryPoint + "=" + name
sh.mu.Lock()
sh.cmds[name] = &commandDesc{func() command { return newExecHandle(entryPoint) }, help}
sh.mu.Unlock()