blob: ef7a60b70007dfcd59330ad709013764652ec02c [file] [log] [blame]
package impl
import (
"os"
"path"
"path/filepath"
"veyron.io/veyron/veyron/lib/glob"
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/services/mounttable/types"
"veyron.io/veyron/veyron2/vlog"
)
// logDirectoryInvoker holds the state of an invocation.
type logDirectoryInvoker struct {
// root is the root directory from which the object names are based.
root string
// suffix is the suffix of the current invocation that is assumed to
// be used as a relative object name to identify a log directory.
suffix string
}
// NewLogDirectoryInvoker is the invoker factory.
func NewLogDirectoryInvoker(root, suffix string) ipc.Invoker {
return ipc.ReflectInvoker(&logDirectoryInvoker{filepath.Clean(root), suffix})
}
// Glob streams the name of all the objects that match pattern.
func (i *logDirectoryInvoker) Glob(call ipc.ServerCall, pattern string) error {
vlog.VI(1).Infof("%v.Glob(%v)", i.suffix, pattern)
g, err := glob.Parse(pattern)
if err != nil {
return err
}
i.root, err = translateNameToFilename(i.root, i.suffix)
if err != nil {
return err
}
fi, err := os.Stat(i.root)
if err != nil {
if os.IsNotExist(err) {
return errNotFound
}
return errOperationFailed
}
return i.globStep("", g, fi.IsDir(), call)
}
// globStep applies a glob recursively.
func (i *logDirectoryInvoker) globStep(name string, g *glob.Glob, isDir bool, call ipc.ServerCall) error {
if g.Len() == 0 {
if err := call.Send(types.MountEntry{Name: name}); err != nil {
return err
}
}
if g.Finished() || !isDir {
return nil
}
dirName, err := translateNameToFilename(i.root, name)
if err != nil {
return err
}
f, err := os.Open(dirName)
if err != nil {
if os.IsNotExist(err) {
return errNotFound
}
return errOperationFailed
}
fi, err := f.Readdir(0)
if err != nil {
return errOperationFailed
}
f.Close()
for _, file := range fi {
fileName := file.Name()
if fileName == "." || fileName == ".." {
continue
}
if ok, _, left := g.MatchInitialSegment(fileName); ok {
if err := i.globStep(path.Join(name, fileName), left, file.IsDir(), call); err != nil {
return err
}
}
}
return nil
}