veyron2/ipc/model.go: Normalize the Glob interfaces
With this change, the Glob__ and GlobChildren__ methods both take a
ServerContext as first argument and return a channel.
All the Glob() implementations are updated to use the AllGlobber
interface from ipc/model.go. This means that the mounttable.Globbable
interface is no longer needed and can now be removed.
The VGlob interface is renamed to Globber.
Change-Id: Idf1cd4663375eb3f1fc3baf7ca7606f59f7ded19
diff --git a/runtimes/google/ipc/benchmarks/service.vdl.go b/runtimes/google/ipc/benchmarks/service.vdl.go
index 117fbe6..117bb1e 100644
--- a/runtimes/google/ipc/benchmarks/service.vdl.go
+++ b/runtimes/google/ipc/benchmarks/service.vdl.go
@@ -254,7 +254,7 @@
return s.impl.EchoStream(ctx)
}
-func (s implBenchmarkServerStub) VGlob() *__ipc.GlobState {
+func (s implBenchmarkServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/runtimes/google/ipc/glob.go b/runtimes/google/ipc/glob.go
index 33c897c..c320a82 100644
--- a/runtimes/google/ipc/glob.go
+++ b/runtimes/google/ipc/glob.go
@@ -131,7 +131,7 @@
return objectToInvoker(obj).MethodSignature(ctx, ctx.Method())
}
-func (r *reservedMethods) Glob(ctx *ipc.GlobContextStub, pattern string) error {
+func (r *reservedMethods) Glob(ctx ipc.ServerCall, pattern string) error {
// Copy the original call to shield ourselves from changes the flowServer makes.
glob := globInternal{r.dispNormal, r.dispReserved, ctx.Suffix()}
return glob.Glob(copyMutableCall(ctx), pattern)
@@ -232,7 +232,7 @@
// If the object implements both AllGlobber and ChildrenGlobber, we'll
// use AllGlobber.
- gs := objectToInvoker(obj).VGlob()
+ gs := objectToInvoker(obj).Globber()
if gs == nil || (gs.AllGlobber == nil && gs.ChildrenGlobber == nil) {
if state.glob.Len() == 0 {
call.Send(naming.VDLMountEntry{Name: state.name})
@@ -241,12 +241,22 @@
}
if gs.AllGlobber != nil {
vlog.VI(3).Infof("ipc Glob: %q implements AllGlobber", call.Suffix())
- childCtx := &ipc.GlobContextStub{&localServerCall{call, state.name}}
- gs.AllGlobber.Glob(childCtx, state.glob.String())
+ ch, err := gs.AllGlobber.Glob__(call, state.glob.String())
+ if err != nil {
+ vlog.VI(3).Infof("ipc Glob: %q.Glob(%q) failed: %v", call.Suffix(), state.glob, err)
+ continue
+ }
+ if ch == nil {
+ continue
+ }
+ for me := range ch {
+ me.Name = naming.Join(state.name, me.Name)
+ call.Send(me)
+ }
continue
}
vlog.VI(3).Infof("ipc Glob: %q implements ChildrenGlobber", call.Suffix())
- children, err := gs.ChildrenGlobber.GlobChildren__()
+ children, err := gs.ChildrenGlobber.GlobChildren__(call)
// The requested object doesn't exist.
if err != nil {
continue
@@ -278,24 +288,6 @@
return nil
}
-// An ipc.ServerCall that prepends a name to all the names in the streamed
-// MountEntry objects.
-type localServerCall struct {
- ipc.ServerCall
- basename string
-}
-
-var _ ipc.ServerCall = (*localServerCall)(nil)
-
-func (c *localServerCall) Send(v interface{}) error {
- me, ok := v.(naming.VDLMountEntry)
- if !ok {
- return verror.BadArgf("unexpected stream type. Got %T, want MountEntry", v)
- }
- me.Name = naming.Join(c.basename, me.Name)
- return c.ServerCall.Send(me)
-}
-
// copyMutableCall returns a new mutableCall copied from call. Changes to the
// original call don't affect the mutable fields in the returned object.
func copyMutableCall(call ipc.ServerCall) *mutableCall {
diff --git a/runtimes/google/ipc/glob_test.go b/runtimes/google/ipc/glob_test.go
index 79e9859..cf2c0e4 100644
--- a/runtimes/google/ipc/glob_test.go
+++ b/runtimes/google/ipc/glob_test.go
@@ -197,29 +197,33 @@
suffix []string
}
-func (o *globObject) Glob(ctx *ipc.GlobContextStub, pattern string) error {
+func (o *globObject) Glob__(ctx ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
g, err := glob.Parse(pattern)
if err != nil {
- return err
+ return nil, err
}
n := o.n.find(o.suffix, false)
if n == nil {
- return nil
+ return nil, nil
}
- o.globLoop(ctx, "", g, n)
- return nil
+ ch := make(chan naming.VDLMountEntry)
+ go func() {
+ o.globLoop(ch, "", g, n)
+ close(ch)
+ }()
+ return ch, nil
}
-func (o *globObject) globLoop(ctx *ipc.GlobContextStub, name string, g *glob.Glob, n *node) {
+func (o *globObject) globLoop(ch chan<- naming.VDLMountEntry, name string, g *glob.Glob, n *node) {
if g.Len() == 0 {
- ctx.SendStream().Send(naming.VDLMountEntry{Name: name})
+ ch <- naming.VDLMountEntry{Name: name}
}
if g.Finished() {
return
}
for leaf, child := range n.children {
if ok, _, left := g.MatchInitialSegment(leaf); ok {
- o.globLoop(ctx, naming.Join(name, leaf), left, child)
+ o.globLoop(ch, naming.Join(name, leaf), left, child)
}
}
}
@@ -229,7 +233,7 @@
suffix []string
}
-func (o *vChildrenObject) GlobChildren__() (<-chan string, error) {
+func (o *vChildrenObject) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
n := o.n.find(o.suffix, false)
if n == nil {
return nil, fmt.Errorf("object does not exist")
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index 4043d3a..272bbfe 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -16,11 +16,9 @@
"veyron.io/veyron/veyron2/options"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
- "veyron.io/veyron/veyron2/services/mounttable"
verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
- "veyron.io/veyron/veyron/lib/glob"
"veyron.io/veyron/veyron/lib/testutil"
"veyron.io/veyron/veyron/lib/websocket"
_ "veyron.io/veyron/veyron/profiles"
@@ -108,40 +106,20 @@
return "Who's there?"
}
-// Glob applies pattern to the following tree:
+// testServer has the following namespace:
// "" -> {level1} -> {level2}
-// "".Glob("*") returns "level1"
-// "".Glob("...") returns "level1" and "level1/level2"
-// "level1".Glob("*") returns "level2"
-func (t *testServer) Glob(ctx *ipc.GlobContextStub, pattern string) error {
- g, err := glob.Parse(pattern)
- if err != nil {
- return err
+func (t *testServer) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
+ ch := make(chan string, 1)
+ switch t.suffix {
+ case "":
+ ch <- "level1"
+ case "level1":
+ ch <- "level2"
+ default:
+ return nil, nil
}
- tree := []string{"", "level1", "level2"}
- for i, leaf := range tree {
- if leaf == t.suffix {
- return t.globLoop(ctx, "", g, tree[i+1:])
- }
- }
- return nil
-}
-
-func (t *testServer) globLoop(ctx *ipc.GlobContextStub, prefix string, g *glob.Glob, tree []string) error {
- if g.Len() == 0 {
- if err := ctx.SendStream().Send(naming.VDLMountEntry{Name: prefix}); err != nil {
- return err
- }
- }
- if g.Finished() || len(tree) == 0 {
- return nil
- }
- if ok, _, left := g.MatchInitialSegment(tree[0]); ok {
- if err := t.globLoop(ctx, naming.Join(prefix, tree[0]), left, tree[1:]); err != nil {
- return err
- }
- }
- return nil
+ close(ch)
+ return ch, nil
}
type allowEveryoneAuthorizer struct{}
@@ -504,11 +482,11 @@
mu sync.Mutex
}
-func (g *GlobbableServer) Glob(ipc.GlobContext, string) error {
+func (g *GlobbableServer) Glob__(ipc.ServerContext, string) (<-chan naming.VDLMountEntry, error) {
g.mu.Lock()
defer g.mu.Unlock()
g.callCount++
- return nil
+ return nil, nil
}
func (g *GlobbableServer) GetAndResetCount() int {
@@ -531,7 +509,7 @@
globServer := &GlobbableServer{}
name := naming.JoinAddressName(mts["mt4/foo/bar"].name, "glob")
- runningGlobServer := runServer(t, r, ipc.LeafDispatcher(mounttable.GlobbableServer(globServer), nil), name)
+ runningGlobServer := runServer(t, r, ipc.LeafDispatcher(globServer, nil), name)
defer runningGlobServer.server.Stop()
ns := r.Namespace()
diff --git a/security/agent/pingpong/wire.vdl.go b/security/agent/pingpong/wire.vdl.go
index 256a030..690f928 100644
--- a/security/agent/pingpong/wire.vdl.go
+++ b/security/agent/pingpong/wire.vdl.go
@@ -125,7 +125,7 @@
return s.impl.Ping(ctx, i0)
}
-func (s implPingPongServerStub) VGlob() *__ipc.GlobState {
+func (s implPingPongServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index 6f8475b..fa5832b 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -344,7 +344,7 @@
return s.impl.BlessingRootsDebugString(ctx)
}
-func (s implAgentServerStub) VGlob() *__ipc.GlobState {
+func (s implAgentServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/services/identity/identity.vdl.go b/services/identity/identity.vdl.go
index 6dda7f3..0546020 100644
--- a/services/identity/identity.vdl.go
+++ b/services/identity/identity.vdl.go
@@ -156,7 +156,7 @@
return s.impl.BlessUsingAccessToken(ctx, i0)
}
-func (s implOAuthBlesserServerStub) VGlob() *__ipc.GlobState {
+func (s implOAuthBlesserServerStub) Globber() *__ipc.GlobState {
return s.gs
}
@@ -346,7 +346,7 @@
return s.impl.Bless(ctx, i0)
}
-func (s implMacaroonBlesserServerStub) VGlob() *__ipc.GlobState {
+func (s implMacaroonBlesserServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/services/mgmt/application/impl/service.go b/services/mgmt/application/impl/service.go
index a42dcab..dd44662 100644
--- a/services/mgmt/application/impl/service.go
+++ b/services/mgmt/application/impl/service.go
@@ -176,7 +176,7 @@
return versions, nil
}
-func (i *appRepoService) GlobChildren__() (<-chan string, error) {
+func (i *appRepoService) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
vlog.VI(0).Infof("%v.GlobChildren__()", i.suffix)
i.store.Lock()
defer i.store.Unlock()
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index a1999c6..e88028d 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -325,7 +325,7 @@
return nil
}
-func (i *binaryService) GlobChildren__() (<-chan string, error) {
+func (i *binaryService) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
elems := strings.Split(i.suffix, "/")
if len(elems) == 1 && elems[0] == "" {
elems = nil
diff --git a/services/mgmt/logreader/impl/logfile.go b/services/mgmt/logreader/impl/logfile.go
index 0011fa8..cbf4606 100644
--- a/services/mgmt/logreader/impl/logfile.go
+++ b/services/mgmt/logreader/impl/logfile.go
@@ -112,7 +112,7 @@
// GlobChildren__ returns the list of files in a directory streamed on a
// channel. The list is empty if the object is a file.
-func (i *logfileService) GlobChildren__() (<-chan string, error) {
+func (i *logfileService) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
vlog.VI(1).Infof("%v.GlobChildren__()", i.suffix)
dirName, err := translateNameToFilename(i.root, i.suffix)
if err != nil {
diff --git a/services/mgmt/node/config.vdl.go b/services/mgmt/node/config.vdl.go
index 212ab5d..42bb189 100644
--- a/services/mgmt/node/config.vdl.go
+++ b/services/mgmt/node/config.vdl.go
@@ -127,7 +127,7 @@
return s.impl.Set(ctx, i0, i1)
}
-func (s implConfigServerStub) VGlob() *__ipc.GlobState {
+func (s implConfigServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/services/mgmt/node/impl/app_service.go b/services/mgmt/node/impl/app_service.go
index b5ab1ab..4c4d43e 100644
--- a/services/mgmt/node/impl/app_service.go
+++ b/services/mgmt/node/impl/app_service.go
@@ -1194,7 +1194,7 @@
}
}
-func (i *appService) GlobChildren__() (<-chan string, error) {
+func (i *appService) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
tree := newTreeNode()
switch len(i.suffix) {
case 0:
diff --git a/services/mgmt/node/impl/proxy_invoker.go b/services/mgmt/node/impl/proxy_invoker.go
index 1f8cf98..a7ab7c4 100644
--- a/services/mgmt/node/impl/proxy_invoker.go
+++ b/services/mgmt/node/impl/proxy_invoker.go
@@ -5,6 +5,7 @@
"io"
"veyron.io/veyron/veyron2/ipc"
+ "veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/services/security/access"
)
@@ -184,27 +185,31 @@
return res, nil
}
-func (p *proxyInvoker) VGlob() *ipc.GlobState {
+func (p *proxyInvoker) Globber() *ipc.GlobState {
return &ipc.GlobState{AllGlobber: p}
}
-func (p *proxyInvoker) Glob(ctx *ipc.GlobContextStub, pattern string) error {
- argptrs := []interface{}{&pattern}
- results, err := p.Invoke(ipc.GlobMethod, ctx, argptrs)
- if err != nil {
- return err
- }
- if len(results) != 1 {
- return fmt.Errorf("unexpected number of result values. Got %d, want 1.", len(results))
- }
- if results[0] == nil {
- return nil
- }
- err, ok := results[0].(error)
- if !ok {
- return fmt.Errorf("unexpected result value type. Got %T, want error.", err)
- }
- return err
+type call struct {
+ ipc.ServerContext
+ ch chan<- naming.VDLMountEntry
+}
+
+func (c *call) Recv(v interface{}) error {
+ return io.EOF
+}
+
+func (c *call) Send(v interface{}) error {
+ c.ch <- v.(naming.VDLMountEntry)
+ return nil
+}
+
+func (p *proxyInvoker) Glob__(ctx ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
+ ch := make(chan naming.VDLMountEntry)
+ go func() {
+ p.Invoke(ipc.GlobMethod, &call{ctx, ch}, []interface{}{&pattern})
+ close(ch)
+ }()
+ return ch, nil
}
// numResults returns the number of result values for the given method.
diff --git a/services/mgmt/node/impl/proxy_invoker_test.go b/services/mgmt/node/impl/proxy_invoker_test.go
index b729d10..813e868 100644
--- a/services/mgmt/node/impl/proxy_invoker_test.go
+++ b/services/mgmt/node/impl/proxy_invoker_test.go
@@ -2,7 +2,6 @@
import (
"reflect"
- "sort"
"testing"
"veyron.io/veyron/veyron2/ipc"
@@ -10,8 +9,9 @@
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/services/mgmt/stats"
- "veyron.io/veyron/veyron2/services/mounttable"
"veyron.io/veyron/veyron2/services/security/access"
+
+ "veyron.io/veyron/veyron/lib/testutil"
)
// TODO(toddw): Add tests of Signature and MethodSignature.
@@ -60,7 +60,10 @@
}
// Call Glob()
- results := doGlob(t, naming.JoinAddressName(ep2.String(), "system"), "start-time-*")
+ results, err := testutil.GlobName(r.NewContext(), naming.JoinAddressName(ep2.String(), "system"), "start-time-*")
+ if err != nil {
+ t.Fatalf("Glob failed: %v", err)
+ }
expected := []string{
"start-time-rfc1123",
"start-time-unix",
@@ -70,27 +73,6 @@
}
}
-func doGlob(t *testing.T, name, pattern string) []string {
- c := mounttable.GlobbableClient(name)
- stream, err := c.Glob(rt.R().NewContext(), pattern)
- if err != nil {
- t.Fatalf("Glob failed: %v", err)
- }
- results := []string{}
- iterator := stream.RecvStream()
- for iterator.Advance() {
- results = append(results, iterator.Value().Name)
- }
- if err := iterator.Err(); err != nil {
- t.Errorf("unexpected stream error: %v", err)
- }
- if err := stream.Finish(); err != nil {
- t.Errorf("Finish failed: %v", err)
- }
- sort.Strings(results)
- return results
-}
-
type dummy struct{}
func (*dummy) Method(_ ipc.ServerContext) error { return nil }
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 48541ae..e1202c7 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -202,7 +202,7 @@
return s.impl.Remove(ctx, i0)
}
-func (s implApplicationServerStub) VGlob() *__ipc.GlobState {
+func (s implApplicationServerStub) Globber() *__ipc.GlobState {
return s.gs
}
@@ -509,7 +509,7 @@
return s.impl.Remove(ctx)
}
-func (s implProfileServerStub) VGlob() *__ipc.GlobState {
+func (s implProfileServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/services/mgmt/root/root.vdl.go b/services/mgmt/root/root.vdl.go
index 081e7ba..5fdd66c 100644
--- a/services/mgmt/root/root.vdl.go
+++ b/services/mgmt/root/root.vdl.go
@@ -133,7 +133,7 @@
return s.impl.Reset(ctx, i0)
}
-func (s implRootServerStub) VGlob() *__ipc.GlobState {
+func (s implRootServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/services/mgmt/stats/impl/stats.go b/services/mgmt/stats/impl/stats.go
index b398ee8..f51b12b 100644
--- a/services/mgmt/stats/impl/stats.go
+++ b/services/mgmt/stats/impl/stats.go
@@ -35,21 +35,22 @@
return stats.StatsServer(&statsService{suffix, watchFreq})
}
-// Glob returns the name of all objects that match pattern.
-func (i *statsService) Glob(ctx ipc.GlobContext, pattern string) error {
- vlog.VI(1).Infof("%v.Glob(%q)", i.suffix, pattern)
+// Glob__ returns the name of all objects that match pattern.
+func (i *statsService) Glob__(ctx ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
+ vlog.VI(1).Infof("%v.Glob__(%q)", i.suffix, pattern)
- it := libstats.Glob(i.suffix, pattern, time.Time{}, false)
- for it.Advance() {
- ctx.SendStream().Send(naming.VDLMountEntry{Name: it.Value().Key})
- }
- if err := it.Err(); err != nil {
- if err == libstats.ErrNotFound {
- return errNotFound
+ ch := make(chan naming.VDLMountEntry)
+ go func() {
+ defer close(ch)
+ it := libstats.Glob(i.suffix, pattern, time.Time{}, false)
+ for it.Advance() {
+ ch <- naming.VDLMountEntry{Name: it.Value().Key}
}
- return errOperationFailed
- }
- return nil
+ if err := it.Err(); err != nil {
+ vlog.VI(1).Infof("libstats.Glob(%q, %q) failed: %v", i.suffix, pattern, err)
+ }
+ }()
+ return ch, nil
}
// WatchGlob returns the name and value of the objects that match the request,
diff --git a/services/mgmt/stats/impl/stats_test.go b/services/mgmt/stats/impl/stats_test.go
index fe502c4..661f6f4 100644
--- a/services/mgmt/stats/impl/stats_test.go
+++ b/services/mgmt/stats/impl/stats_test.go
@@ -6,6 +6,7 @@
"testing"
"time"
+ "veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
@@ -14,6 +15,7 @@
libstats "veyron.io/veyron/veyron/lib/stats"
"veyron.io/veyron/veyron/lib/stats/histogram"
+ "veyron.io/veyron/veyron/lib/testutil"
"veyron.io/veyron/veyron/profiles"
istats "veyron.io/veyron/veyron/services/mgmt/stats"
"veyron.io/veyron/veyron/services/mgmt/stats/impl"
@@ -26,9 +28,9 @@
return impl.NewStatsService(suffix, 100*time.Millisecond), nil, nil
}
-func startServer(t *testing.T) (string, func()) {
+func startServer(t *testing.T, runtime veyron2.Runtime) (string, func()) {
disp := &statsDispatcher{}
- server, err := rt.R().NewServer()
+ server, err := runtime.NewServer()
if err != nil {
t.Fatalf("NewServer failed: %v", err)
return "", nil
@@ -46,9 +48,10 @@
}
func TestStatsImpl(t *testing.T) {
- rt.Init()
+ runtime, _ := rt.New()
+ defer runtime.Cleanup()
- endpoint, stop := startServer(t)
+ endpoint, stop := startServer(t, runtime)
defer stop()
counter := libstats.NewCounter("testing/foo/bar")
@@ -64,29 +67,14 @@
histogram.Add(int64(i))
}
- c := stats.StatsClient(naming.JoinAddressName(endpoint, ""))
+ name := naming.JoinAddressName(endpoint, "")
+ c := stats.StatsClient(name)
// Test Glob()
{
- stream, err := c.Glob(rt.R().NewContext(), "testing/foo/...")
+ results, err := testutil.GlobName(runtime.NewContext(), name, "testing/foo/...")
if err != nil {
- t.Fatalf("c.Glob failed: %v", err)
- }
- iterator := stream.RecvStream()
- results := []string{}
- for iterator.Advance() {
- me := iterator.Value()
- if len(me.Servers) > 0 {
- t.Errorf("unexpected servers. Got %v, want none", me.Servers)
- }
- results = append(results, me.Name)
- }
- if err := iterator.Err(); err != nil {
- t.Errorf("unexpected stream error: %v", err)
- }
- err = stream.Finish()
- if err != nil {
- t.Errorf("gstream.Finish failed: %v", err)
+ t.Fatalf("testutil.GlobName failed: %v", err)
}
expected := []string{
"testing/foo",
@@ -109,7 +97,7 @@
{
noRM := types.ResumeMarker{}
_ = noRM
- stream, err := c.WatchGlob(rt.R().NewContext(), types.GlobRequest{Pattern: "testing/foo/bar"})
+ stream, err := c.WatchGlob(runtime.NewContext(), types.GlobRequest{Pattern: "testing/foo/bar"})
if err != nil {
t.Fatalf("c.WatchGlob failed: %v", err)
}
@@ -160,7 +148,7 @@
// Test Value()
{
c := stats.StatsClient(naming.JoinAddressName(endpoint, "testing/foo/bar"))
- value, err := c.Value(rt.R().NewContext())
+ value, err := c.Value(runtime.NewContext())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
@@ -172,7 +160,7 @@
// Test Value() with Histogram
{
c := stats.StatsClient(naming.JoinAddressName(endpoint, "testing/hist/foo"))
- value, err := c.Value(rt.R().NewContext())
+ value, err := c.Value(runtime.NewContext())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
diff --git a/services/mounttable/lib/collection_test_interface.vdl.go b/services/mounttable/lib/collection_test_interface.vdl.go
index 55d4de0..40ae1fe 100644
--- a/services/mounttable/lib/collection_test_interface.vdl.go
+++ b/services/mounttable/lib/collection_test_interface.vdl.go
@@ -150,7 +150,7 @@
return s.impl.Lookup(ctx)
}
-func (s implCollectionServerStub) VGlob() *__ipc.GlobState {
+func (s implCollectionServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/services/mounttable/lib/mounttable.go b/services/mounttable/lib/mounttable.go
index ed5d57b..4d63067 100644
--- a/services/mounttable/lib/mounttable.go
+++ b/services/mounttable/lib/mounttable.go
@@ -361,7 +361,7 @@
name string
}
-func (mt *mountTable) globStep(n *node, name string, pattern *glob.Glob, context ipc.GlobContext) {
+func (mt *mountTable) globStep(n *node, name string, pattern *glob.Glob, context ipc.ServerContext, ch chan<- naming.VDLMountEntry) {
vlog.VI(2).Infof("globStep(%s, %s)", name, pattern)
if mt.acls != nil {
@@ -374,7 +374,6 @@
}
}
- sender := context.SendStream()
// If this is a mount point, we're done.
if m := n.mount; m != nil {
// Garbage-collect if expired.
@@ -382,11 +381,11 @@
n.removeUseless()
return
}
- sender.Send(
- naming.VDLMountEntry{
- Name: name, Servers: m.servers.copyToSlice(),
- MT: n.mount.mt,
- })
+ ch <- naming.VDLMountEntry{
+ Name: name,
+ Servers: m.servers.copyToSlice(),
+ MT: n.mount.mt,
+ }
return
}
@@ -396,7 +395,7 @@
n.removeUseless()
return
}
- sender.Send(naming.VDLMountEntry{Name: name})
+ ch <- naming.VDLMountEntry{Name: name}
}
if pattern.Finished() {
@@ -406,7 +405,7 @@
// Recurse through the children.
for k, c := range n.children {
if ok, _, suffix := pattern.MatchInitialSegment(k); ok {
- mt.globStep(c, naming.Join(name, k), suffix, context)
+ mt.globStep(c, naming.Join(name, k), suffix, context, ch)
}
}
}
@@ -414,36 +413,40 @@
// Glob finds matches in the namespace. If we reach a mount point before matching the
// whole pattern, return that mount point.
// pattern is a glob pattern as defined by the veyron/lib/glob package.
-func (ms *mountContext) Glob(context ipc.GlobContext, pattern string) error {
+func (ms *mountContext) Glob__(context ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
vlog.VI(2).Infof("mt.Glob %v", ms.elems)
g, err := glob.Parse(pattern)
if err != nil {
- return err
+ return nil, err
}
mt := ms.mt
- // TODO(caprita): we need to grab a write lock because globStep may
- // garbage-collect expired servers. Rework this to avoid this potential
- // bottleneck.
- mt.Lock()
- defer mt.Unlock()
+ ch := make(chan naming.VDLMountEntry)
+ go func() {
+ defer close(ch)
+ // TODO(caprita): we need to grab a write lock because globStep may
+ // garbage-collect expired servers. Rework this to avoid this potential
+ // bottleneck.
+ mt.Lock()
+ defer mt.Unlock()
- // If the current name is not fully resolvable on this nameserver we
- // don't need to evaluate the glob expression. Send a partially resolved
- // name back to the client.
- n := mt.findNode(ms.cleanedElems, false)
- if n == nil {
- ms.linkToLeaf(context)
- return nil
- }
+ // If the current name is not fully resolvable on this nameserver we
+ // don't need to evaluate the glob expression. Send a partially resolved
+ // name back to the client.
+ n := mt.findNode(ms.cleanedElems, false)
+ if n == nil {
+ ms.linkToLeaf(ch)
+ return
+ }
- mt.globStep(n, "", g, context)
- return nil
+ mt.globStep(n, "", g, context, ch)
+ }()
+ return ch, nil
}
-func (ms *mountContext) linkToLeaf(stream ipc.GlobServerStream) {
+func (ms *mountContext) linkToLeaf(ch chan<- naming.VDLMountEntry) {
n, elems := ms.mt.walk(ms.mt.root, ms.cleanedElems)
if n == nil {
return
@@ -452,5 +455,5 @@
for i, s := range servers {
servers[i].Server = naming.Join(s.Server, strings.Join(elems, "/"))
}
- stream.SendStream().Send(naming.VDLMountEntry{Name: "", Servers: servers})
+ ch <- naming.VDLMountEntry{Name: "", Servers: servers}
}
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index ee79761..c0b8494 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -275,7 +275,7 @@
name := naming.JoinAddressName(ep, suffix)
ctx := as.NewContext()
client := as.Client()
- call, err := client.StartCall(ctx, name, "Glob", []interface{}{pattern}, options.NoResolve(true))
+ call, err := client.StartCall(ctx, name, ipc.GlobMethod, []interface{}{pattern}, options.NoResolve(true))
if err != nil {
boom(t, "Glob.StartCall %s %s: %s", name, pattern, err)
}
diff --git a/services/mounttable/lib/neighborhood.go b/services/mounttable/lib/neighborhood.go
index 278b0f4..e307143 100644
--- a/services/mounttable/lib/neighborhood.go
+++ b/services/mounttable/lib/neighborhood.go
@@ -255,35 +255,39 @@
return errors.New("this server does not implement Unmount")
}
-// Glob implements Glob
-func (ns *neighborhoodService) Glob(ctx ipc.GlobContext, pattern string) error {
+// Glob__ implements ipc.AllGlobber
+func (ns *neighborhoodService) Glob__(ctx ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
g, err := glob.Parse(pattern)
if err != nil {
- return err
+ return nil, err
}
// return all neighbors that match the first element of the pattern.
nh := ns.nh
- sender := ctx.SendStream()
switch len(ns.elems) {
case 0:
- for k, n := range nh.neighbors() {
- if ok, _, _ := g.MatchInitialSegment(k); !ok {
- continue
+ ch := make(chan naming.VDLMountEntry)
+ go func() {
+ defer close(ch)
+ for k, n := range nh.neighbors() {
+ if ok, _, _ := g.MatchInitialSegment(k); !ok {
+ continue
+ }
+ ch <- naming.VDLMountEntry{Name: k, Servers: n, MT: true}
}
- if err := sender.Send(naming.VDLMountEntry{Name: k, Servers: n, MT: true}); err != nil {
- return err
- }
- }
- return nil
+ }()
+ return ch, nil
case 1:
neighbor := nh.neighbor(ns.elems[0])
if neighbor == nil {
- return verror.Make(naming.ErrNoSuchName, ctx, ns.elems[0])
+ return nil, verror.Make(naming.ErrNoSuchName, ctx, ns.elems[0])
}
- return sender.Send(naming.VDLMountEntry{Name: "", Servers: neighbor, MT: true})
+ ch := make(chan naming.VDLMountEntry, 1)
+ ch <- naming.VDLMountEntry{Name: "", Servers: neighbor, MT: true}
+ close(ch)
+ return ch, nil
default:
- return verror.Make(naming.ErrNoSuchName, ctx, ns.elems)
+ return nil, verror.Make(naming.ErrNoSuchName, ctx, ns.elems)
}
}
diff --git a/services/mounttable/mounttabled/test.sh b/services/mounttable/mounttabled/test.sh
index 2ebdc7f..76bdd25 100755
--- a/services/mounttable/mounttabled/test.sh
+++ b/services/mounttable/mounttabled/test.sh
@@ -51,8 +51,7 @@
GOT=$(${MOUNTTABLE_BIN} glob "${EP}" '*' | \
sed -e 's/ \/@.@ws@[^ ]* (TTL .m..s)//' -e 's/TTL [^)]*/TTL XmXXs/' | sort) \
|| shell_test::fail "line ${LINENO}: failed to run mounttable"
- WANT="[${EP}]
-google /www.google.com:80 (TTL XmXXs)
+ WANT="google /www.google.com:80 (TTL XmXXs)
myself ${EP} (TTL XmXXs)
nh ${NHEP} (TTL XmXXs)"
shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
@@ -60,8 +59,7 @@
# <neighborhood>.Glob('NHNAME')
GOT=$("${MOUNTTABLE_BIN}" glob "${NHEP}" "${NHNAME}" | sed 's/TTL [^)]*/TTL XmXXs/' | sort) \
|| shell_test::fail "line ${LINENO}: failed to run mounttable"
- WANT="[${NHEP}]
-${NHNAME} ${EP} (TTL XmXXs)"
+ WANT="${NHNAME} ${EP} (TTL XmXXs)"
shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
shell_test::pass
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index 8fbf3c6..4c914e7d 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -143,7 +143,7 @@
return s.impl.Discharge(ctx, i0, i1)
}
-func (s implDischargerServerStub) VGlob() *__ipc.GlobState {
+func (s implDischargerServerStub) Globber() *__ipc.GlobState {
return s.gs
}
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index 6afca98..9116972 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -1,32 +1,16 @@
package main
import (
+ "errors"
"fmt"
"time"
"veyron.io/lib/cmdline"
- "veyron.io/veyron/veyron2/context"
+ "veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/options"
- "veyron.io/veyron/veyron2/services/mounttable"
)
-func bindMT(ctx context.T, name string) (mounttable.MountTableClientMethods, error) {
- e, err := runtime.Namespace().ResolveToMountTableX(ctx, name)
- if err != nil {
- return nil, err
- }
- if len(e.Servers) == 0 {
- return nil, fmt.Errorf("Failed to find any mount tables at %q", name)
- }
- var servers []string
- for _, s := range e.Servers {
- servers = append(servers, naming.JoinAddressName(s.Server, e.Name))
- }
- fmt.Println(servers)
- return mounttable.MountTableClient(servers[0]), nil
-}
-
var cmdGlob = &cmdline.Command{
Run: runGlob,
Name: "glob",
@@ -42,40 +26,37 @@
func runGlob(cmd *cmdline.Command, args []string) error {
if len(args) == 1 {
- args = append([]string{""}, args...)
+ roots := runtime.Namespace().Roots()
+ if len(roots) == 0 {
+ return errors.New("no namespace root")
+ }
+ args = append([]string{roots[0]}, args...)
}
if expected, got := 2, len(args); expected != got {
return cmd.UsageErrorf("glob: incorrect number of arguments, expected %d, got %d", expected, got)
}
ctx, cancel := runtime.NewContext().WithTimeout(time.Minute)
defer cancel()
- c, err := bindMT(ctx, args[0])
- if err != nil {
- return fmt.Errorf("bind error: %v", err)
- }
- stream, err := c.Glob(ctx, args[1])
+ name, pattern := args[0], args[1]
+ call, err := runtime.Client().StartCall(ctx, name, ipc.GlobMethod, []interface{}{pattern}, options.NoResolve(true))
if err != nil {
return err
}
- rStream := stream.RecvStream()
- for rStream.Advance() {
- buf := rStream.Value()
-
- fmt.Fprint(cmd.Stdout(), buf.Name)
- for _, s := range buf.Servers {
+ for {
+ var me naming.VDLMountEntry
+ if err := call.Recv(&me); err != nil {
+ break
+ }
+ fmt.Fprint(cmd.Stdout(), me.Name)
+ for _, s := range me.Servers {
fmt.Fprintf(cmd.Stdout(), " %s (TTL %s)", s.Server, time.Duration(s.TTL)*time.Second)
}
fmt.Fprintln(cmd.Stdout())
}
-
- if err := rStream.Err(); err != nil {
- return fmt.Errorf("advance error: %v", err)
+ if ferr := call.Finish(&err); ferr != nil {
+ err = ferr
}
- err = stream.Finish()
- if err != nil {
- return fmt.Errorf("finish error: %v", err)
- }
- return nil
+ return err
}
var cmdMount = &cmdline.Command{
@@ -123,7 +104,10 @@
return err
}
if ierr := call.Finish(&err); ierr != nil {
- return ierr
+ err = ierr
+ }
+ if err != nil {
+ return err
}
fmt.Fprintln(cmd.Stdout(), "Name mounted successfully.")
@@ -153,11 +137,14 @@
return err
}
if ierr := call.Finish(&err); ierr != nil {
- return ierr
+ err = ierr
+ }
+ if err != nil {
+ return err
}
fmt.Fprintln(cmd.Stdout(), "Name unmounted successfully.")
- return nil
+ return err
}
var cmdResolveStep = &cmdline.Command{
@@ -183,7 +170,7 @@
}
var entry naming.VDLMountEntry
if ierr := call.Finish(&entry, &err); ierr != nil {
- return ierr
+ err = ierr
}
if err != nil {
return err
diff --git a/tools/mounttable/impl_test.go b/tools/mounttable/impl_test.go
index 9c59eb6..ae9fa48 100644
--- a/tools/mounttable/impl_test.go
+++ b/tools/mounttable/impl_test.go
@@ -20,12 +20,13 @@
suffix string
}
-func (s *server) Glob(ctx ipc.GlobContext, pattern string) error {
+func (s *server) Glob__(ctx ipc.ServerContext, pattern string) (<-chan naming.VDLMountEntry, error) {
vlog.VI(2).Infof("Glob() was called. suffix=%v pattern=%q", s.suffix, pattern)
- sender := ctx.SendStream()
- sender.Send(naming.VDLMountEntry{"name1", []naming.VDLMountedServer{{"server1", 123}}, false})
- sender.Send(naming.VDLMountEntry{"name2", []naming.VDLMountedServer{{"server2", 456}, {"server3", 789}}, false})
- return nil
+ ch := make(chan naming.VDLMountEntry, 2)
+ ch <- naming.VDLMountEntry{"name1", []naming.VDLMountedServer{{"server1", 123}}, false}
+ ch <- naming.VDLMountEntry{"name2", []naming.VDLMountedServer{{"server2", 456}, {"server3", 789}}, false}
+ close(ch)
+ return ch, nil
}
func (s *server) Mount(_ ipc.ServerContext, server string, ttl uint32, flags naming.MountFlag) error {
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index a411da3..3a8e3ab 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -565,7 +565,7 @@
return s.impl.StreamingOutput(ctx, i0, i1)
}
-func (s implTypeTesterServerStub) VGlob() *__ipc.GlobState {
+func (s implTypeTesterServerStub) Globber() *__ipc.GlobState {
return s.gs
}