From 466ac8ec269653df73c11a7e0fdfb23485c89047 Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Wed, 17 Jun 2015 16:41:43 +0900 Subject: [PATCH] Work in progress --- database.go | 8 ++--- dir.go | 38 +++++++--------------- file.go | 28 +++++++--------- node.go | 93 +++++++++++++++++++++++------------------------------ version.go | 29 ++++++++--------- 5 files changed, 80 insertions(+), 116 deletions(-) diff --git a/database.go b/database.go index 543fbcd..7057a9c 100644 --- a/database.go +++ b/database.go @@ -57,7 +57,7 @@ func (this *database) load(dir string) error { } if err := buildNewVersion(this.base); err != nil { - return nil + return err } this.vers, err = this.buildVersions(this.base) @@ -109,10 +109,10 @@ func (this *database) buildVersions(base string) (versionList, error) { sort.Sort(vers) - var parentVer *version + var parVer *version for _, ver := range vers { - ver.parent = parentVer - parentVer = ver + ver.parent = parVer + parVer = ver } return vers, nil diff --git a/dir.go b/dir.go index ef42675..0ed477d 100644 --- a/dir.go +++ b/dir.go @@ -51,23 +51,17 @@ func newVersionedDir(node *versionedNode, parent *versionedDir) *versionedDir { } func (this *versionedDir) version() error { - if this.node.versioned { + if this.node.flags&NodeFlagVer == NodeFlagVer { return nil } - version := this.node.ver.db.lastVersion() - if err := os.MkdirAll(version.rebasePath(this.node.path), 0755); err != nil { + node := newVersionedNode(this.node.path, this.node.ver.db.lastVersion(), this.node, NodeFlagDir|NodeFlagVer) + + if err := os.MkdirAll(node.rebasedPath(), 0755); err != nil { return err } - node, err := newVersionedNode(this.node.path, version, this.node) - if err != nil { - return err - } - - node.versioned = true this.node = node - return nil } @@ -81,11 +75,7 @@ func (this *versionedDir) createDir(name string) (*versionedDir, error) { return nil, err } - node, err := newVersionedNode(childPath, this.node.ver, nil) - if err != nil { - return nil, err - } - + node := newVersionedNode(childPath, this.node.ver, nil, NodeFlagDir) dir := newVersionedDir(node, this) this.dirs[name] = dir @@ -103,11 +93,7 @@ func (this *versionedDir) createFile(name string, flags int) (*versionedFile, er return nil, err } - node, err := newVersionedNode(childPath, this.node.ver, nil) - if err != nil { - return nil, err - } - + node := newVersionedNode(childPath, this.node.ver, nil, 0) file := newVersionedFile(node, this) file.handle = handle this.files[name] = file @@ -116,18 +102,16 @@ func (this *versionedDir) createFile(name string, flags int) (*versionedFile, er } func (this *versionedDir) Attr(ctx context.Context, attr *fuse.Attr) error { - this.node.attr(attr) + if err := this.node.attr(attr); err != nil { + return err + } + attr.Inode = this.inode return nil } func (this *versionedDir) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error { - if err := this.node.sync(); err != nil { - return err - } - - this.Attr(ctx, &resp.Attr) - return nil + return this.Attr(ctx, &resp.Attr) } func (this *versionedDir) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { diff --git a/file.go b/file.go index 904e874..2f98a93 100644 --- a/file.go +++ b/file.go @@ -47,23 +47,17 @@ func newVersionedFile(node *versionedNode, parent *versionedDir) *versionedFile } func (this *versionedFile) version() error { - if this.node.versioned { + if this.node.flags&NodeFlagVer == NodeFlagVer { return nil } - version := this.node.ver.db.lastVersion() - if _, err := fileCopy(this.node.rebasedPath(), version.rebasePath(this.node.path)); err != nil { + node := newVersionedNode(this.node.path, this.node.ver.db.lastVersion(), this.node, NodeFlagVer) + + if _, err := fileCopy(this.node.rebasedPath(), node.rebasedPath()); err != nil { return err } - node, err := newVersionedNode(this.node.path, version, this.node) - if err != nil { - return err - } - - node.versioned = true this.node = node - return nil } @@ -94,12 +88,7 @@ func (this *versionedFile) Attr(ctx context.Context, attr *fuse.Attr) error { } func (this *versionedFile) Getattr(ctx context.Context, req *fuse.GetattrRequest, resp *fuse.GetattrResponse) error { - if err := this.node.sync(); err != nil { - return err - } - - this.Attr(ctx, &resp.Attr) - return nil + return this.Attr(ctx, &resp.Attr) } func (this *versionedFile) Setattr(ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { @@ -124,7 +113,12 @@ func (this *versionedFile) ReadAll(ctx context.Context) ([]byte, error) { return nil, errors.New("attempted to read from unopened file") } - data := make([]byte, this.node.info.Size()) + info, err := os.Stat(this.node.rebasedPath()) + if err != nil { + return nil, err + } + + data := make([]byte, info.Size()) if _, err := this.handle.Read(data); err != nil { return nil, err } diff --git a/node.go b/node.go index 9dc38c7..e77a15d 100644 --- a/node.go +++ b/node.go @@ -33,84 +33,68 @@ import ( // versionedNode // +const ( + NodeFlagDir = 1 << iota + NodeFlagVer +) + type versionedNode struct { - path string - info os.FileInfo - ver *version - parent *versionedNode - versioned bool + path string + ver *version + parent *versionedNode + flags int } -func newVersionedNode(path string, ver *version, parent *versionedNode) (*versionedNode, error) { - info, err := os.Stat(ver.rebasePath(path)) - if err != nil { - return nil, err - } - - return newVersionedNodeStat(path, ver, parent, info), nil -} - -func newVersionedNodeStat(path string, ver *version, parent *versionedNode, info os.FileInfo) *versionedNode { - return &versionedNode{path, info, ver, parent, false} +func newVersionedNode(path string, ver *version, parent *versionedNode, flags int) *versionedNode { + return &versionedNode{path, ver, parent, flags} } func (this *versionedNode) setAttr(req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error { + if err := this.attr(&resp.Attr); err != nil { + return err + } + if req.Valid&fuse.SetattrMode != 0 { if err := os.Chmod(this.rebasedPath(), req.Mode); err != nil { return err } + + resp.Attr.Mode = req.Mode } if setGid, setUid := req.Valid&fuse.SetattrGid != 0, req.Valid&fuse.SetattrUid != 0; setGid || setUid { - gid, uid := this.owner() if setGid { - gid = req.Gid + resp.Attr.Gid = req.Gid } if setUid { - uid = req.Uid + resp.Attr.Uid = req.Uid } - if err := os.Chown(this.rebasedPath(), int(uid), int(gid)); err != nil { + if err := os.Chown(this.rebasedPath(), int(resp.Attr.Uid), int(resp.Attr.Gid)); err != nil { return err } } if setAtime, setMtime := req.Valid&fuse.SetattrAtime != 0, req.Valid&fuse.SetattrMtime != 0; setAtime || setMtime { - atime, mtime, _ := this.times() if setAtime { - atime = req.Atime + resp.Attr.Atime = req.Atime } if setMtime { - mtime = req.Mtime + resp.Attr.Mtime = req.Mtime } - if err := os.Chtimes(this.rebasedPath(), atime, mtime); err != nil { + if err := os.Chtimes(this.rebasedPath(), resp.Attr.Atime, resp.Attr.Mtime); err != nil { return err } } - if err := this.sync(); err != nil { - return err - } - - this.attr(&resp.Attr) - return nil -} - -func (this *versionedNode) sync() error { - info, err := os.Stat(this.rebasedPath()) - if err != nil { - return err - } - - this.info = info return nil } func (this *versionedNode) remove() error { ver := this.ver - if this.versioned { + if this.flags&NodeFlagVer == NodeFlagVer { if err := os.Remove(this.rebasedPath()); err != nil { return err } @@ -126,33 +110,36 @@ func (this *versionedNode) rebasedPath() string { return this.ver.rebasePath(this.path) } -func (this *versionedNode) owner() (gid, uid uint32) { - stat := this.info.Sys().(*syscall.Stat_t) - +func (this *versionedNode) owner(stat syscall.Stat_t) (gid, uid uint32) { gid = stat.Gid uid = stat.Uid return } -func (this *versionedNode) times() (atime, mtime, ctime time.Time) { - stat := this.info.Sys().(*syscall.Stat_t) - +func (this *versionedNode) times(stat syscall.Stat_t) (atime, mtime, ctime time.Time) { atime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) - mtime = this.info.ModTime() + mtime = time.Unix(int64(stat.Mtim.Sec), int64(stat.Mtim.Nsec)) ctime = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)) return } -func (this *versionedNode) attr(attr *fuse.Attr) { - stat := this.info.Sys().(*syscall.Stat_t) +func (this *versionedNode) attr(attr *fuse.Attr) error { + info, err := os.Stat(this.rebasedPath()) + if err != nil { + return err + } - attr.Size = uint64(this.info.Size()) + stat := info.Sys().(*syscall.Stat_t) + + attr.Size = uint64(stat.Size) attr.Blocks = uint64(stat.Blocks) - attr.Atime, attr.Mtime, attr.Ctime = this.times() - attr.Mode = this.info.Mode() + attr.Atime, attr.Mtime, attr.Ctime = this.times(*stat) + attr.Mode = info.Mode() attr.Nlink = uint32(stat.Nlink) - attr.Gid, attr.Uid = this.owner() + attr.Gid, attr.Uid = this.owner(*stat) attr.Rdev = uint32(stat.Rdev) + + return nil } // diff --git a/version.go b/version.go index 2f4b5d5..b034e8a 100644 --- a/version.go +++ b/version.go @@ -79,9 +79,15 @@ func (this *version) scanDir(path string) (versionedNodeMap, error) { } for _, info := range infos { + childFlags := 0 + if info.IsDir() { + childFlags |= NodeFlagDir + } + childName := info.Name() childPath := filepath.Join(path, childName) - ownNodes[childName] = newVersionedNodeStat(childPath, this, nil, info) + + ownNodes[childName] = newVersionedNode(childPath, this, nil, childFlags) } } @@ -100,16 +106,16 @@ func (this *version) scanDir(path string) (versionedNodeMap, error) { return baseNodes, nil } -func (this *version) buildVerDir(dir *versionedDir) error { +func (this *version) buildDir(dir *versionedDir) error { nodes, err := this.scanDir(dir.node.path) if err != nil { return err } for name, node := range nodes { - if node.info.IsDir() { + if node.flags&NodeFlagDir == NodeFlagDir { subDir := newVersionedDir(node, dir) - if err := this.buildVerDir(subDir); err != nil { + if err := this.buildDir(subDir); err != nil { return err } @@ -123,13 +129,10 @@ func (this *version) buildVerDir(dir *versionedDir) error { } func (this *version) resolve() error { - node, err := newVersionedNode("/", this, nil) - if err != nil { - return err - } - + node := newVersionedNode("/", this, nil, NodeFlagDir) root := newVersionedDir(node, nil) - if err = this.buildVerDir(root); err != nil { + + if err := this.buildDir(root); err != nil { return err } @@ -178,11 +181,7 @@ func (this versionList) Less(i, j int) bool { func buildNewVersion(base string) error { name := buildVerName(time.Now()) - - if err := os.Mkdir(path.Join(base, name), 0755); err != nil { - return err - } - if err := os.Mkdir(path.Join(base, name, "root"), 0755); err != nil { + if err := os.MkdirAll(path.Join(base, name, "root"), 0755); err != nil { return err }