Commit 9723c2be authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

example/statfs: use new nodefs library

parent afbcb85e
......@@ -13,32 +13,27 @@ import (
"path/filepath"
"runtime"
"sort"
"syscall"
"testing"
"time"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/internal/testutil"
"github.com/hanwen/go-fuse/nodefs"
)
func setupFs(fs pathfs.FileSystem, N int) (string, func()) {
opts := &nodefs.Options{
EntryTimeout: 0.0,
AttrTimeout: 0.0,
NegativeTimeout: 0.0,
}
func setupFs(fs nodefs.InodeEmbedder, N int) (string, func()) {
opts := &nodefs.Options{}
opts.Debug = testutil.VerboseTest()
mountPoint := testutil.TempDir()
nfs := pathfs.NewPathNodeFs(fs, nil)
state, _, err := nodefs.MountRoot(mountPoint, nfs.Root(), opts)
server, err := nodefs.Mount(mountPoint, fs, opts)
if err != nil {
panic(fmt.Sprintf("cannot mount %v", err)) // ugh - benchmark has no error methods.
log.Panicf("cannot mount %v", err)
}
lmap := NewLatencyMap()
if testutil.VerboseTest() {
state.RecordLatencies(lmap)
server.RecordLatencies(lmap)
}
go state.Serve()
return mountPoint, func() {
if testutil.VerboseTest() {
var total time.Duration
......@@ -55,7 +50,7 @@ func setupFs(fs pathfs.FileSystem, N int) (string, func()) {
log.Printf("total %v, %v/bench op", total, total/time.Duration(N))
}
err := state.Unmount()
err := server.Unmount()
if err != nil {
log.Println("error during unmount", err)
} else {
......@@ -65,11 +60,11 @@ func setupFs(fs pathfs.FileSystem, N int) (string, func()) {
}
func TestNewStatFs(t *testing.T) {
fs := NewStatFS()
fs := &StatFS{}
for _, n := range []string{
"file.txt", "sub/dir/foo.txt",
"sub/dir/bar.txt", "sub/marine.txt"} {
fs.AddFile(n)
fs.AddFile(n, fuse.Attr{Mode: syscall.S_IFREG})
}
wd, clean := setupFs(fs, 1)
......@@ -116,13 +111,13 @@ func TestNewStatFs(t *testing.T) {
func BenchmarkGoFuseStat(b *testing.B) {
b.StopTimer()
fs := NewStatFS()
fs := &StatFS{}
wd, _ := os.Getwd()
fileList := wd + "/testpaths.txt"
files := ReadLines(fileList)
for _, fn := range files {
fs.AddFile(fn)
fs.AddFile(fn, fuse.Attr{Mode: syscall.S_IFREG})
}
wd, clean := setupFs(fs, b.N)
......@@ -151,13 +146,13 @@ func readdir(d string) error {
func BenchmarkGoFuseReaddir(b *testing.B) {
b.StopTimer()
fs := NewStatFS()
fs := &StatFS{}
wd, _ := os.Getwd()
dirSet := map[string]struct{}{}
for _, fn := range ReadLines(wd + "/testpaths.txt") {
fs.AddFile(fn)
fs.AddFile(fn, fuse.Attr{Mode: syscall.S_IFREG})
dirSet[filepath.Dir(fn)] = struct{}{}
}
......
......@@ -5,65 +5,66 @@
package benchmark
import (
"context"
"path/filepath"
"strings"
"syscall"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/nodefs"
)
type StatFS struct {
pathfs.FileSystem
entries map[string]*fuse.Attr
dirs map[string][]fuse.DirEntry
nodefs.Inode
files map[string]fuse.Attr
}
func (fs *StatFS) Add(name string, a *fuse.Attr) {
name = strings.TrimRight(name, "/")
_, ok := fs.entries[name]
if ok {
return
var _ = (nodefs.OnAdder)((*StatFS)(nil))
func (r *StatFS) OnAdd(ctx context.Context) {
for nm, a := range r.files {
r.addFile(nm, a)
}
r.files = nil
}
fs.entries[name] = a
if name == "/" || name == "" {
return
func (r *StatFS) AddFile(name string, a fuse.Attr) {
if r.files == nil {
r.files = map[string]fuse.Attr{}
}
dir, base := filepath.Split(name)
dir = strings.TrimRight(dir, "/")
fs.dirs[dir] = append(fs.dirs[dir], fuse.DirEntry{Name: base, Mode: a.Mode})
fs.Add(dir, &fuse.Attr{Mode: fuse.S_IFDIR | 0755})
r.files[name] = a
}
func (fs *StatFS) AddFile(name string) {
fs.Add(name, &fuse.Attr{Mode: fuse.S_IFREG | 0644})
}
func (r *StatFS) addFile(name string, a fuse.Attr) {
dir, base := filepath.Split(name)
func (fs *StatFS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
if d := fs.dirs[name]; d != nil {
return &fuse.Attr{Mode: 0755 | fuse.S_IFDIR}, fuse.OK
}
e := fs.entries[name]
if e == nil {
return nil, fuse.ENOENT
}
p := r.EmbeddedInode()
return e, fuse.OK
}
// Add directories leading up to the file.
for _, component := range strings.Split(dir, "/") {
if len(component) == 0 {
continue
}
ch := p.GetChild(component)
if ch == nil {
// Create a directory
ch = p.NewPersistentInode(context.Background(), &nodefs.Inode{},
nodefs.NodeAttr{Mode: syscall.S_IFDIR})
// Add it
p.AddChild(component, ch, true)
}
func (fs *StatFS) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
entries := fs.dirs[name]
if entries == nil {
return nil, fuse.ENOENT
p = ch
}
return entries, fuse.OK
}
func NewStatFS() *StatFS {
return &StatFS{
FileSystem: pathfs.NewDefaultFileSystem(),
entries: make(map[string]*fuse.Attr),
dirs: make(map[string][]fuse.DirEntry),
}
// Create the file
child := p.NewPersistentInode(context.Background(), &nodefs.MemRegularFile{
Data: make([]byte, a.Size),
Attr: a,
}, nodefs.NodeAttr{})
// And add it
p.AddChild(base, child, true)
}
......@@ -14,11 +14,12 @@ import (
"runtime"
"runtime/pprof"
"strings"
"syscall"
"time"
"github.com/hanwen/go-fuse/benchmark"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/nodefs"
)
func main() {
......@@ -27,7 +28,7 @@ func main() {
profile := flag.String("profile", "", "record cpu profile.")
mem_profile := flag.String("mem-profile", "", "record memory profile.")
command := flag.String("run", "", "run this command after mounting.")
ttl := flag.Float64("ttl", 1.0, "attribute/entry cache TTL.")
ttl := flag.Duration("ttl", time.Second, "attribute/entry cache TTL.")
flag.Parse()
if flag.NArg() < 2 {
fmt.Fprintf(os.Stderr, "usage: %s MOUNTPOINT FILENAMES-FILE\n", os.Args[0])
......@@ -48,21 +49,21 @@ func main() {
log.Fatalf("os.Create: %v", err)
}
}
fs := benchmark.NewStatFS()
fs := &benchmark.StatFS{}
lines := benchmark.ReadLines(flag.Arg(1))
for _, l := range lines {
fs.AddFile(l)
fs.AddFile(strings.TrimSpace(l),
fuse.Attr{Mode: syscall.S_IFREG})
}
nfs := pathfs.NewPathNodeFs(fs, nil)
opts := &nodefs.Options{
AttrTimeout: time.Duration(*ttl * float64(time.Second)),
EntryTimeout: time.Duration(*ttl * float64(time.Second)),
Debug: *debug,
AttrTimeout: ttl,
EntryTimeout: ttl,
}
state, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), opts)
opts.Debug = *debug
server, err := nodefs.Mount(flag.Arg(0), fs, opts)
if err != nil {
fmt.Printf("Mount fail: %v\n", err)
os.Exit(1)
log.Fatalf("Mount fail: %v\n", err)
}
runtime.GC()
......@@ -78,7 +79,7 @@ func main() {
cmd.Start()
}
state.Serve()
server.Wait()
if memProfFile != nil {
pprof.WriteHeapProfile(memProfFile)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment