veyron/services/mgmt/debug: Invoke Glob on the leaves directly.

Instead of sending a local RPC to Glob the leaves, use the invoker
directly. This is more correct and more efficient, especially when the
local endpoint is not actually local, i.e. goes through a proxy.

Also change the Glob method of the logdir invoker to return directories
so that log directories can be traversed one level at a time.

Change-Id: I9d1ff10caa93233a7c234b648fced5630791b670
diff --git a/services/mgmt/debug/dispatcher.go b/services/mgmt/debug/dispatcher.go
index 71aa23e..8360a68 100644
--- a/services/mgmt/debug/dispatcher.go
+++ b/services/mgmt/debug/dispatcher.go
@@ -13,7 +13,7 @@
 	"veyron2/naming"
 	"veyron2/security"
 	"veyron2/services/mounttable/types"
-	"veyron2/vlog"
+	"veyron2/verror"
 )
 
 // dispatcher holds the state of the debug dispatcher.
@@ -33,7 +33,7 @@
 	}
 	if len(suffix) == 0 {
 		leaves := []string{"logs", "stats"}
-		return ipc.ReflectInvoker(&topLevelGlobInvoker{d.rt, leaves}), d.auth, nil
+		return ipc.ReflectInvoker(&topLevelGlobInvoker{d, leaves}), d.auth, nil
 	}
 	parts := strings.SplitN(suffix, "/", 2)
 	if len(parts) == 2 {
@@ -54,12 +54,11 @@
 }
 
 type topLevelGlobInvoker struct {
-	rt     veyron2.Runtime
+	d      *dispatcher
 	leaves []string
 }
 
 func (i *topLevelGlobInvoker) Glob(call ipc.ServerCall, pattern string) error {
-	vlog.VI(1).Infof("Glob(%v)", pattern)
 	g, err := glob.Parse(pattern)
 	if err != nil {
 		return err
@@ -75,18 +74,49 @@
 }
 
 func (i *topLevelGlobInvoker) leafGlob(call ipc.ServerCall, leaf string, pattern string) error {
-	addr := naming.JoinAddressName(call.LocalEndpoint().String(), leaf)
-	pattern = naming.Join(addr, pattern)
-	c, err := i.rt.Namespace().Glob(call, pattern)
+	invoker, _, err := i.d.Lookup(leaf, "Glob")
 	if err != nil {
-		vlog.VI(1).Infof("Glob(%v) failed: %v", pattern, err)
 		return err
 	}
-	for me := range c {
-		_, name := naming.SplitAddressName(me.Name)
-		if err := call.Send(types.MountEntry{Name: name}); err != nil {
-			return err
-		}
+	argptrs := []interface{}{&pattern}
+	leafCall := &localServerCall{call, leaf}
+	results, err := invoker.Invoke("Glob", leafCall, argptrs)
+	if err != nil {
+		return err
 	}
+	if len(results) != 1 {
+		return verror.BadArgf("unexpected number of results. Got %d, want 1", len(results))
+	}
+	res := results[0]
+	if res == nil {
+		return nil
+	}
+	err, ok := res.(error)
+	if !ok {
+		return verror.BadArgf("unexpected result type. Got %T, want error", res)
+	}
+	return err
+}
+
+// An ipc.ServerCall implementation used to Invoke methods on the invokers
+// directly. Everything is the same as the original ServerCall, except the
+// Stream implementation.
+type localServerCall struct {
+	ipc.ServerCall
+	name string
+}
+
+// Re-Implement ipc.Stream
+func (c *localServerCall) Recv(v interface{}) error {
+	panic("Recv not implemented")
 	return nil
 }
+
+func (c *localServerCall) Send(v interface{}) error {
+	me, ok := v.(types.MountEntry)
+	if !ok {
+		return verror.BadArgf("unexpected stream type. Got %T, want MountEntry", v)
+	}
+	me.Name = naming.Join(c.name, me.Name)
+	return c.ServerCall.Send(me)
+}
diff --git a/services/mgmt/logreader/impl/logdir_invoker.go b/services/mgmt/logreader/impl/logdir_invoker.go
index e7c2c69..30d86f5 100644
--- a/services/mgmt/logreader/impl/logdir_invoker.go
+++ b/services/mgmt/logreader/impl/logdir_invoker.go
@@ -49,7 +49,7 @@
 
 // globStep applies a glob recursively.
 func (i *logDirectoryInvoker) globStep(name string, g *glob.Glob, isDir bool, call ipc.ServerCall) error {
-	if g.Len() == 0 && !isDir {
+	if g.Len() == 0 {
 		if err := call.Send(types.MountEntry{Name: name}); err != nil {
 			return err
 		}
diff --git a/services/mgmt/logreader/impl/logdir_invoker_test.go b/services/mgmt/logreader/impl/logdir_invoker_test.go
index efde612..1cdda4e 100644
--- a/services/mgmt/logreader/impl/logdir_invoker_test.go
+++ b/services/mgmt/logreader/impl/logdir_invoker_test.go
@@ -84,14 +84,16 @@
 			t.Errorf("Glob failed: %v", err)
 		}
 		results := []string{}
+		expected := []string{"", "subdir"}
+		expected = append(expected, tests...)
 		iterator := stream.RecvStream()
 		for count := 0; iterator.Advance(); count++ {
 			results = append(results, iterator.Value().Name)
 		}
-		sort.Strings(tests)
+		sort.Strings(expected)
 		sort.Strings(results)
-		if !reflect.DeepEqual(tests, results) {
-			t.Errorf("unexpected result. Got %v, want %v", results, tests)
+		if !reflect.DeepEqual(expected, results) {
+			t.Errorf("unexpected result. Got %v, want %v", results, expected)
 		}
 
 		if err := iterator.Err(); err != nil {
@@ -111,9 +113,10 @@
 			results = append(results, iterator.Value().Name)
 		}
 		sort.Strings(results)
-		expected := []string{
+		expected = []string{
 			"bar.txt",
 			"foo.txt",
+			"subdir",
 		}
 		if !reflect.DeepEqual(expected, results) {
 			t.Errorf("unexpected result. Got %v, want %v", results, expected)