blob: f82d5b32f3c321b58ffc4f6622f3de716a0a0fa7 [file] [log] [blame]
package namespace
import (
"time"
"veyron.io/veyron/veyron2/context"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/options"
"veyron.io/veyron/veyron2/vlog"
)
// mountIntoMountTable mounts a single server into a single mount table.
func mountIntoMountTable(ctx context.T, client ipc.Client, name, server string, ttl time.Duration, flags naming.MountFlag) error {
ctx, _ = ctx.WithTimeout(callTimeout)
call, err := client.StartCall(ctx, name, "Mount", []interface{}{server, uint32(ttl.Seconds()), flags}, options.NoResolve(true))
if err != nil {
return err
}
if ierr := call.Finish(&err); ierr != nil {
return ierr
}
return err
}
// unmountFromMountTable removes a single mounted server from a single mount table.
func unmountFromMountTable(ctx context.T, client ipc.Client, name, server string) error {
ctx, _ = ctx.WithTimeout(callTimeout)
call, err := client.StartCall(ctx, name, "Unmount", []interface{}{server}, options.NoResolve(true))
if err != nil {
return err
}
if ierr := call.Finish(&err); ierr != nil {
return ierr
}
return err
}
func (ns *namespace) Mount(ctx context.T, name, server string, ttl time.Duration, opts ...naming.MountOpt) error {
defer vlog.LogCall()()
var flags naming.MountFlag
for _, o := range opts {
// NB: used a switch since we'll be adding more options.
switch v := o.(type) {
case naming.ReplaceMountOpt:
if v {
flags |= naming.MountFlag(naming.Replace)
}
case naming.ServesMountTableOpt:
if v {
flags |= naming.MountFlag(naming.MT)
}
}
}
// Resolve to all the mount tables implementing name.
mtServers, err := ns.ResolveToMountTable(ctx, name)
if err != nil {
return err
}
// Mount the server in all the returned mount tables.
c := make(chan error, len(mtServers))
for _, mt := range mtServers {
go func() {
c <- mountIntoMountTable(ctx, ns.rt.Client(), mt, server, ttl, flags)
}()
}
// Return error if any mounts failed, since otherwise we'll get
// inconsistent resolutions down the road.
var finalerr error
for _ = range mtServers {
if err := <-c; err != nil {
finalerr = err
}
}
vlog.VI(1).Infof("Mount(%s, %s) -> %v", name, server, finalerr)
// Forget any previous cached information about these names.
ns.resolutionCache.forget(mtServers)
return finalerr
}
func (ns *namespace) Unmount(ctx context.T, name, server string) error {
defer vlog.LogCall()()
mts, err := ns.ResolveToMountTable(ctx, name)
if err != nil {
return err
}
// Unmount the server from all the mount tables.
c := make(chan error, len(mts))
for _, mt := range mts {
go func() {
c <- unmountFromMountTable(ctx, ns.rt.Client(), mt, server)
}()
}
// Return error if any mounts failed, since otherwise we'll get
// inconsistent resolutions down the road.
var finalerr error
for _ = range mts {
if err := <-c; err != nil {
finalerr = err
}
}
ns.resolutionCache.forget(mts)
return finalerr
}