Work in progress

This commit is contained in:
Alex Yatskov 2015-06-17 16:41:43 +09:00
parent 4de3dcc799
commit 466ac8ec26
5 changed files with 80 additions and 116 deletions

View File

@ -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

38
dir.go
View File

@ -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 {

28
file.go
View File

@ -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
}

87
node.go
View File

@ -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
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
}
//

View File

@ -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
}