blob: 6c68c834320ef27267c59f4c8786fbdf6d774ab6 [file] [log] [blame]
package naming
import (
"fmt"
"strings"
"sync"
"time"
"v.io/core/veyron2/context"
"v.io/core/veyron2/naming"
verror "v.io/core/veyron2/verror2"
"v.io/core/veyron2/vlog"
vnamespace "v.io/core/veyron/runtimes/google/naming/namespace"
)
// NewSimpleNamespace returns a simple implementation of a Namespace
// server for use in tests. In particular, it ignores TTLs and not
// allow fully overlapping mount names.
func NewSimpleNamespace() naming.Namespace {
ns, err := vnamespace.New()
if err != nil {
panic(err)
}
return &namespace{mounts: make(map[string][]string), ns: ns}
}
// namespace is a simple partial implementation of naming.Namespace.
type namespace struct {
sync.Mutex
mounts map[string][]string
ns naming.Namespace
}
func (ns *namespace) Mount(ctx context.T, name, server string, _ time.Duration, _ ...naming.MountOpt) error {
defer vlog.LogCall()()
ns.Lock()
defer ns.Unlock()
for n, _ := range ns.mounts {
if n != name && (strings.HasPrefix(name, n) || strings.HasPrefix(n, name)) {
return fmt.Errorf("simple mount table does not allow names that are a prefix of each other")
}
}
ns.mounts[name] = append(ns.mounts[name], server)
return nil
}
func (ns *namespace) Unmount(ctx context.T, name, server string) error {
defer vlog.LogCall()()
var servers []string
ns.Lock()
defer ns.Unlock()
for _, s := range ns.mounts[name] {
// When server is "", we remove all servers under name.
if len(server) > 0 && s != server {
servers = append(servers, s)
}
}
if len(servers) > 0 {
ns.mounts[name] = servers
} else {
delete(ns.mounts, name)
}
return nil
}
func (ns *namespace) Resolve(ctx context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
defer vlog.LogCall()()
if address, _ := naming.SplitAddressName(name); len(address) > 0 {
return []string{name}, nil
}
ns.Lock()
defer ns.Unlock()
for prefix, servers := range ns.mounts {
if strings.HasPrefix(name, prefix) {
suffix := strings.TrimLeft(strings.TrimPrefix(name, prefix), "/")
var ret []string
for _, s := range servers {
ret = append(ret, naming.Join(s, suffix))
}
return ret, nil
}
}
return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
}
func (ns *namespace) ResolveX(ctx context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
defer vlog.LogCall()()
e, err := ns.ns.ResolveX(ctx, name, naming.SkipResolveOpt{})
if err != nil {
return e, err
}
if len(e.Servers) > 0 {
e.Servers[0].Server = naming.JoinAddressName(e.Servers[0].Server, e.Name)
e.Name = ""
return e, nil
}
ns.Lock()
defer ns.Unlock()
name = e.Name
for prefix, servers := range ns.mounts {
if strings.HasPrefix(name, prefix) {
e.Name = strings.TrimLeft(strings.TrimPrefix(name, prefix), "/")
for _, s := range servers {
e.Servers = append(e.Servers, naming.MountedServer{Server: s, Expires: time.Now().Add(1000 * time.Hour)})
}
return e, nil
}
}
return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
}
func (ns *namespace) ResolveToMountTableX(ctx context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
defer vlog.LogCall()()
// TODO(mattr): Implement this method for tests that might need it.
panic("ResolveToMountTable not implemented")
return nil, nil
}
func (ns *namespace) ResolveToMountTable(ctx context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
defer vlog.LogCall()()
// TODO(mattr): Implement this method for tests that might need it.
panic("ResolveToMountTable not implemented")
return nil, nil
}
func (ns *namespace) Unresolve(ctx context.T, name string) ([]string, error) {
defer vlog.LogCall()()
// TODO(mattr): Implement this method for tests that might need it.
panic("Unresolve not implemented")
return nil, nil
}
func (ns *namespace) FlushCacheEntry(name string) bool {
defer vlog.LogCall()()
return false
}
func (ns *namespace) CacheCtl(ctls ...naming.CacheCtl) []naming.CacheCtl {
defer vlog.LogCall()()
return nil
}
func (ns *namespace) Glob(ctx context.T, pattern string) (chan naming.MountEntry, error) {
defer vlog.LogCall()()
// TODO(mattr): Implement this method for tests that might need it.
panic("Glob not implemented")
return nil, nil
}
func (ns *namespace) SetRoots(...string) error {
defer vlog.LogCall()()
panic("Calling SetRoots on a mock namespace. This is not supported.")
return nil
}
func (ns *namespace) Roots() []string {
defer vlog.LogCall()()
panic("Calling Roots on a mock namespace. This is not supported.")
return nil
}