kubo/mfs/file.go
Jeromy 78a8088410 Refactor ipnsfs into a more generic and well tested mfs
License: MIT
Signed-off-by: Jeromy <jeromyj@gmail.com>
2016-01-12 08:22:55 -08:00

146 lines
2.9 KiB
Go

package mfs
import (
"sync"
chunk "github.com/ipfs/go-ipfs/importer/chunk"
dag "github.com/ipfs/go-ipfs/merkledag"
mod "github.com/ipfs/go-ipfs/unixfs/mod"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
)
type File struct {
parent childCloser
name string
hasChanges bool
mod *mod.DagModifier
lock sync.Mutex
}
// NewFile returns a NewFile object with the given parameters
func NewFile(name string, node *dag.Node, parent childCloser, dserv dag.DAGService) (*File, error) {
dmod, err := mod.NewDagModifier(context.Background(), node, dserv, chunk.DefaultSplitter)
if err != nil {
return nil, err
}
return &File{
parent: parent,
name: name,
mod: dmod,
}, nil
}
// Write writes the given data to the file at its current offset
func (fi *File) Write(b []byte) (int, error) {
fi.Lock()
defer fi.Unlock()
fi.hasChanges = true
return fi.mod.Write(b)
}
// Read reads into the given buffer from the current offset
func (fi *File) Read(b []byte) (int, error) {
fi.Lock()
defer fi.Unlock()
return fi.mod.Read(b)
}
// Read reads into the given buffer from the current offset
func (fi *File) CtxReadFull(ctx context.Context, b []byte) (int, error) {
fi.Lock()
defer fi.Unlock()
return fi.mod.CtxReadFull(ctx, b)
}
// Close flushes, then propogates the modified dag node up the directory structure
// and signals a republish to occur
func (fi *File) Close() error {
fi.Lock()
defer fi.Unlock()
if fi.hasChanges {
err := fi.mod.Sync()
if err != nil {
return err
}
nd, err := fi.mod.GetNode()
if err != nil {
return err
}
fi.Unlock()
err = fi.parent.closeChild(fi.name, nd)
fi.Lock()
if err != nil {
return err
}
fi.hasChanges = false
}
return nil
}
// Sync flushes the changes in the file to disk
func (fi *File) Sync() error {
fi.Lock()
defer fi.Unlock()
return fi.mod.Sync()
}
// Seek implements io.Seeker
func (fi *File) Seek(offset int64, whence int) (int64, error) {
fi.Lock()
defer fi.Unlock()
return fi.mod.Seek(offset, whence)
}
// Write At writes the given bytes at the offset 'at'
func (fi *File) WriteAt(b []byte, at int64) (int, error) {
fi.Lock()
defer fi.Unlock()
fi.hasChanges = true
return fi.mod.WriteAt(b, at)
}
// Size returns the size of this file
func (fi *File) Size() (int64, error) {
fi.Lock()
defer fi.Unlock()
return fi.mod.Size()
}
// GetNode returns the dag node associated with this file
func (fi *File) GetNode() (*dag.Node, error) {
fi.Lock()
defer fi.Unlock()
return fi.mod.GetNode()
}
// Truncate truncates the file to size
func (fi *File) Truncate(size int64) error {
fi.Lock()
defer fi.Unlock()
fi.hasChanges = true
return fi.mod.Truncate(size)
}
// Type returns the type FSNode this is
func (fi *File) Type() NodeType {
return TFile
}
// Lock the file
func (fi *File) Lock() {
fi.lock.Lock()
}
// Unlock the file
func (fi *File) Unlock() {
fi.lock.Unlock()
}