TBR: PROTOTYPE: discovery proto #3

  Implement prototype #3
    - Allow a server to publish suffixes
    - Glob will go to the server only if the mounted suffixes can't cover the glob pattern.

  https://docs.google.com/a/google.com/document/d/1qFvWn66WgwCyKhxJ4HE4_7iCzRQ4dLtQ0HlcRxIY7uo/edit?usp=sharing

Multipart: 1/2

PresubmitTest: none
Change-Id: Ibc7a80c755069cd92fbba9c21cf9461b86c6e249
diff --git a/naming/.api b/naming/.api
index e5165f4..e445f64 100644
--- a/naming/.api
+++ b/naming/.api
@@ -38,6 +38,7 @@
 pkg naming, method (RoutingID) Write(io.Writer) error
 pkg naming, method (ServesMountTable) EndpointOpt()
 pkg naming, method (ServesMountTable) NSOpt()
+pkg naming, method (Suffixes) NSOpt()
 pkg naming, type BlessingOpt string
 pkg naming, type CacheCtl interface { CacheCtl }
 pkg naming, type CacheCtl interface, CacheCtl()
@@ -69,6 +70,7 @@
 pkg naming, type MountEntry struct
 pkg naming, type MountEntry struct, IsLeaf bool
 pkg naming, type MountEntry struct, Name string
+pkg naming, type MountEntry struct, NotFollow bool
 pkg naming, type MountEntry struct, NotMatched bool
 pkg naming, type MountEntry struct, Servers []MountedServer
 pkg naming, type MountEntry struct, ServesMountTable bool
@@ -82,6 +84,11 @@
 pkg naming, type ReplaceMount bool
 pkg naming, type RoutingID struct
 pkg naming, type ServesMountTable bool
+pkg naming, type Suffix struct
+pkg naming, type Suffix struct, IsLeaf bool
+pkg naming, type Suffix struct, Name string
+pkg naming, type Suffix struct, Properties Properties
+pkg naming, type Suffixes []Suffix
 pkg naming, var ErrNameExists verror.IDAction
 pkg naming, var ErrNoMountTable verror.IDAction
 pkg naming, var ErrNoSuchName verror.IDAction
diff --git a/naming/model.go b/naming/model.go
index 8849dae..aa1e26c 100644
--- a/naming/model.go
+++ b/naming/model.go
@@ -114,8 +114,8 @@
 
 func (IsLeaf) NSOpt() {}
 
-// Properties is a set of properties for a name.
-func (Properties) NSOpt() {}
+// Suffixes is a list of suffixes of a mount point.
+func (Suffixes) NSOpt() {}
 
 // BlessingOpt is used to add a blessing name to the endpoint.
 type BlessingOpt string
diff --git a/naming/types.vdl b/naming/types.vdl
index 8c5bb64..dfd2fcc 100644
--- a/naming/types.vdl
+++ b/naming/types.vdl
@@ -15,14 +15,25 @@
 	Leaf    = MountFlag(1 << 2) // Leaf means that the target server is a leaf.
 )
 
-// Properties is a set of properties for a name.
-// TODO(jhahn): Where should this be defined?
+// TODO(jhahn): Support generic property types.
 type Properties map[string][]string
 
 const (
   PropInterface = "interface"
 )
 
+// Suffix represents a suffix mounted under a mounted point.
+type Suffix struct {
+	// Name is a suffix name.
+	Name string
+	// IsLeaf is true if this suffix represents a leaf.
+	IsLeaf bool
+	// Properties is a set of properties of this suffix.
+	Properties Properties
+}
+
+type Suffixes []Suffix
+
 // MountedServer represents a server mounted on a specific name.
 type MountedServer struct {
 	// Server is the OA that's mounted.
@@ -45,6 +56,8 @@
 	// Mounttable replies non-matched entries if they're not leaves so that Glob
 	// can follow non-leaf servers recursively.
 	NotMatched bool
+	// NotFollow means don't send Glob requests to this server.
+	NotFollow bool
 }
 
 // GlobError is returned by namespace.Glob to indicate a subtree of the namespace
diff --git a/naming/types.vdl.go b/naming/types.vdl.go
index 7dede2c..48b535d 100644
--- a/naming/types.vdl.go
+++ b/naming/types.vdl.go
@@ -23,8 +23,7 @@
 }) {
 }
 
-// Properties is a set of properties for a name.
-// TODO(jhahn): Where should this be defined?
+// TODO(jhahn): Support generic property types.
 type Properties map[string][]string
 
 func (Properties) __VDLReflect(struct {
@@ -32,6 +31,28 @@
 }) {
 }
 
+// Suffix represents a suffix mounted under a mounted point.
+type Suffix struct {
+	// Name is a suffix name.
+	Name string
+	// IsLeaf is true if this suffix represents a leaf.
+	IsLeaf bool
+	// Properties is a set of properties of this suffix.
+	Properties Properties
+}
+
+func (Suffix) __VDLReflect(struct {
+	Name string `vdl:"v.io/v23/naming.Suffix"`
+}) {
+}
+
+type Suffixes []Suffix
+
+func (Suffixes) __VDLReflect(struct {
+	Name string `vdl:"v.io/v23/naming.Suffixes"`
+}) {
+}
+
 // MountedServer represents a server mounted on a specific name.
 type MountedServer struct {
 	// Server is the OA that's mounted.
@@ -59,6 +80,9 @@
 	// Mounttable replies non-matched entries if they're not leaves so that Glob
 	// can follow non-leaf servers recursively.
 	NotMatched bool
+	// NotFollow is true if the results include all the matched entries
+	// and so Glob doesn't need to follow this server entry recursively.
+	NotFollow bool
 }
 
 func (MountEntry) __VDLReflect(struct {
@@ -122,6 +146,8 @@
 func init() {
 	vdl.Register((*MountFlag)(nil))
 	vdl.Register((*Properties)(nil))
+	vdl.Register((*Suffix)(nil))
+	vdl.Register((*Suffixes)(nil))
 	vdl.Register((*MountedServer)(nil))
 	vdl.Register((*MountEntry)(nil))
 	vdl.Register((*GlobError)(nil))
diff --git a/rpc/.api b/rpc/.api
index 6e9a1f7..957acaa 100644
--- a/rpc/.api
+++ b/rpc/.api
@@ -137,7 +137,7 @@
 pkg rpc, type Server interface, Listen(ListenSpec) ([]naming.Endpoint, error)
 pkg rpc, type Server interface, RemoveName(string)
 pkg rpc, type Server interface, Serve(string, interface{}, security.Authorizer) error
-pkg rpc, type Server interface, ServeDispatcher(string, Dispatcher) error
+pkg rpc, type Server interface, ServeDispatcher(string, Dispatcher, naming.Suffixes) error
 pkg rpc, type Server interface, Status() ServerStatus
 pkg rpc, type Server interface, Stop() error
 pkg rpc, type Server interface, UnwatchNetwork(chan<- NetworkChange)
diff --git a/rpc/model.go b/rpc/model.go
index 5787d11..f5f9e6e 100644
--- a/rpc/model.go
+++ b/rpc/model.go
@@ -195,7 +195,9 @@
 	// It is an error to call ServeDispatcher if Serve has already been
 	// called. It is also an error to call ServeDispatcher multiple times.
 	// It is considered an error to call Listen after ServeDispatcher.
-	ServeDispatcher(name string, disp Dispatcher) error
+	//
+	// TODO(jhahn): a better interface for suffixes/properties.
+	ServeDispatcher(name string, disp Dispatcher, suffixes naming.Suffixes) error
 
 	// AddName adds the specified name to the mount table for the object or
 	// Dispatcher served by this server.
diff --git a/services/mounttable/.api b/services/mounttable/.api
index 30a1468..b1cd2ac 100644
--- a/services/mounttable/.api
+++ b/services/mounttable/.api
@@ -8,21 +8,21 @@
 pkg mounttable, type MountTableClientMethods interface { Delete, GetPermissions, Mount, ResolveStep, SetPermissions, Unmount }
 pkg mounttable, type MountTableClientMethods interface, Delete(*context.T, bool, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientMethods interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
-pkg mounttable, type MountTableClientMethods interface, Mount(*context.T, string, uint32, naming.MountFlag, naming.Properties, ...rpc.CallOpt) error
+pkg mounttable, type MountTableClientMethods interface, Mount(*context.T, string, uint32, naming.MountFlag, naming.Suffixes, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientMethods interface, ResolveStep(*context.T, ...rpc.CallOpt) (naming.MountEntry, error)
 pkg mounttable, type MountTableClientMethods interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientMethods interface, Unmount(*context.T, string, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientStub interface { Delete, GetPermissions, Mount, ResolveStep, SetPermissions, Unmount }
 pkg mounttable, type MountTableClientStub interface, Delete(*context.T, bool, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientStub interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
-pkg mounttable, type MountTableClientStub interface, Mount(*context.T, string, uint32, naming.MountFlag, naming.Properties, ...rpc.CallOpt) error
+pkg mounttable, type MountTableClientStub interface, Mount(*context.T, string, uint32, naming.MountFlag, naming.Suffixes, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientStub interface, ResolveStep(*context.T, ...rpc.CallOpt) (naming.MountEntry, error)
 pkg mounttable, type MountTableClientStub interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
 pkg mounttable, type MountTableClientStub interface, Unmount(*context.T, string, ...rpc.CallOpt) error
 pkg mounttable, type MountTableServerMethods interface { Delete, GetPermissions, Mount, ResolveStep, SetPermissions, Unmount }
 pkg mounttable, type MountTableServerMethods interface, Delete(*context.T, rpc.ServerCall, bool) error
 pkg mounttable, type MountTableServerMethods interface, GetPermissions(*context.T, rpc.ServerCall) (access.Permissions, string, error)
-pkg mounttable, type MountTableServerMethods interface, Mount(*context.T, rpc.ServerCall, string, uint32, naming.MountFlag, naming.Properties) error
+pkg mounttable, type MountTableServerMethods interface, Mount(*context.T, rpc.ServerCall, string, uint32, naming.MountFlag, naming.Suffixes) error
 pkg mounttable, type MountTableServerMethods interface, ResolveStep(*context.T, rpc.ServerCall) (naming.MountEntry, error)
 pkg mounttable, type MountTableServerMethods interface, SetPermissions(*context.T, rpc.ServerCall, access.Permissions, string) error
 pkg mounttable, type MountTableServerMethods interface, Unmount(*context.T, rpc.ServerCall, string) error
diff --git a/services/mounttable/service.vdl b/services/mounttable/service.vdl
index 6366d94..fa29006 100644
--- a/services/mounttable/service.vdl
+++ b/services/mounttable/service.vdl
@@ -59,7 +59,9 @@
 	// was never present as far as the interface is concerned.
 	//
 	// The flags represent a bit mask of options.
-	Mount(server string, ttl uint32, flags naming.MountFlag, properties naming.Properties) error
+	//
+	// TODO(jhahn): Need a better interface for suffix.
+	Mount(server string, ttl uint32, flags naming.MountFlag, suffixes naming.Suffixes) error
 
 	// Unmount removes server from the receiver.  If server is empty, remove all
 	// servers mounted there.  Returns a non-nil error iff server remains mounted
diff --git a/services/mounttable/service.vdl.go b/services/mounttable/service.vdl.go
index 33800f3..655e0f7 100644
--- a/services/mounttable/service.vdl.go
+++ b/services/mounttable/service.vdl.go
@@ -128,7 +128,9 @@
 	// was never present as far as the interface is concerned.
 	//
 	// The flags represent a bit mask of options.
-	Mount(ctx *context.T, server string, ttl uint32, flags naming.MountFlag, properties naming.Properties, opts ...rpc.CallOpt) error
+	//
+	// TODO(jhahn): Need a better interface for suffix.
+	Mount(ctx *context.T, server string, ttl uint32, flags naming.MountFlag, suffixes naming.Suffixes, opts ...rpc.CallOpt) error
 	// Unmount removes server from the receiver.  If server is empty, remove all
 	// servers mounted there.  Returns a non-nil error iff server remains mounted
 	// at the mount point.
@@ -159,7 +161,7 @@
 	permissions.ObjectClientStub
 }
 
-func (c implMountTableClientStub) Mount(ctx *context.T, i0 string, i1 uint32, i2 naming.MountFlag, i3 naming.Properties, opts ...rpc.CallOpt) (err error) {
+func (c implMountTableClientStub) Mount(ctx *context.T, i0 string, i1 uint32, i2 naming.MountFlag, i3 naming.Suffixes, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "Mount", []interface{}{i0, i1, i2, i3}, nil, opts...)
 	return
 }
@@ -244,7 +246,9 @@
 	// was never present as far as the interface is concerned.
 	//
 	// The flags represent a bit mask of options.
-	Mount(ctx *context.T, call rpc.ServerCall, server string, ttl uint32, flags naming.MountFlag, properties naming.Properties) error
+	//
+	// TODO(jhahn): Need a better interface for suffix.
+	Mount(ctx *context.T, call rpc.ServerCall, server string, ttl uint32, flags naming.MountFlag, suffixes naming.Suffixes) error
 	// Unmount removes server from the receiver.  If server is empty, remove all
 	// servers mounted there.  Returns a non-nil error iff server remains mounted
 	// at the mount point.
@@ -295,7 +299,7 @@
 	gs *rpc.GlobState
 }
 
-func (s implMountTableServerStub) Mount(ctx *context.T, call rpc.ServerCall, i0 string, i1 uint32, i2 naming.MountFlag, i3 naming.Properties) error {
+func (s implMountTableServerStub) Mount(ctx *context.T, call rpc.ServerCall, i0 string, i1 uint32, i2 naming.MountFlag, i3 naming.Suffixes) error {
 	return s.impl.Mount(ctx, call, i0, i1, i2, i3)
 }
 
@@ -333,12 +337,12 @@
 	Methods: []rpc.MethodDesc{
 		{
 			Name: "Mount",
-			Doc:  "// Mount Server (a global name) onto the receiver.\n//\n// Subsequent mounts add to the servers mounted there.  The multiple\n// servers are considered equivalent and are meant solely for\n// availability, i.e., no load balancing is guaranteed.\n//\n// The ttl is the number of seconds the mount is to last unless refreshed by\n// another mount of the same server.  A ttl of 0 represents an infinite\n// duration.  A server with an expired ttl should never appear in the results\n// nor affect the operation of any MountTable method, and should act as if it\n// was never present as far as the interface is concerned.\n//\n// The flags represent a bit mask of options.",
+			Doc:  "// Mount Server (a global name) onto the receiver.\n//\n// Subsequent mounts add to the servers mounted there.  The multiple\n// servers are considered equivalent and are meant solely for\n// availability, i.e., no load balancing is guaranteed.\n//\n// The ttl is the number of seconds the mount is to last unless refreshed by\n// another mount of the same server.  A ttl of 0 represents an infinite\n// duration.  A server with an expired ttl should never appear in the results\n// nor affect the operation of any MountTable method, and should act as if it\n// was never present as far as the interface is concerned.\n//\n// The flags represent a bit mask of options.\n//\n// TODO(jhahn): Need a better interface for suffix.",
 			InArgs: []rpc.ArgDesc{
-				{"server", ``},     // string
-				{"ttl", ``},        // uint32
-				{"flags", ``},      // naming.MountFlag
-				{"properties", ``}, // naming.Properties
+				{"server", ``},   // string
+				{"ttl", ``},      // uint32
+				{"flags", ``},    // naming.MountFlag
+				{"suffixes", ``}, // naming.Suffixes
 			},
 		},
 		{