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)