From e7aa1166bcbaa57e20512467cb6661bca2da4aeb Mon Sep 17 00:00:00 2001 From: Jeromy <jeromyj@gmail.com> Date: Fri, 3 Oct 2014 23:04:41 +0000 Subject: [PATCH] add writerAt for fuse writes --- fuse/ipns/ipns_unix.go | 40 ++++++++++++++++++++++------------------ fuse/ipns/writerat.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 fuse/ipns/writerat.go diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index 4a9db2bce..83146c3fd 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -1,14 +1,13 @@ package ipns import ( + "bytes" "fmt" "io/ioutil" "os" "path/filepath" "time" - "bytes" - "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse" "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse/fs" "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" @@ -205,7 +204,7 @@ type Node struct { cached *mdag.PBData // For writing - dataBuf *bytes.Buffer + writerBuf WriteAtBuf } func (s *Node) loadData() error { @@ -290,21 +289,25 @@ func (s *Node) ReadAll(intr fs.Intr) ([]byte, fuse.Error) { } // this is a terrible function... 'ReadAll'? // what if i have a 6TB file? GG RAM. - return ioutil.ReadAll(r) + b, err := ioutil.ReadAll(r) + if err != nil { + log.Error("[%s] Readall error: %s", s.name, err) + return nil, err + } + if len(b) > 4 { + log.Debug("ReadAll trailing bytes: %v", b[len(b)-4:]) + } + return b, nil } func (n *Node) Write(req *fuse.WriteRequest, resp *fuse.WriteResponse, intr fs.Intr) fuse.Error { log.Debug("ipns: Node Write [%s]: flags = %s, offset = %d, size = %d", n.name, req.Flags.String(), req.Offset, len(req.Data)) - if n.dataBuf == nil { - n.dataBuf = new(bytes.Buffer) + if n.writerBuf == nil { + n.writerBuf = NewWriterAtFromBytes(nil) } - if req.Offset == 0 { - n.dataBuf.Reset() - n.dataBuf.Write(req.Data) - resp.Size = len(req.Data) - } else { - log.Error("Unhandled write to offset!") - n.dataBuf = nil + _, err := n.writerBuf.WriteAt(req.Data, req.Offset) + if err != nil { + return err } return nil } @@ -312,7 +315,7 @@ func (n *Node) Write(req *fuse.WriteRequest, resp *fuse.WriteResponse, intr fs.I func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error { log.Debug("Got flush request [%s]!", n.name) - if n.dataBuf != nil { + if n.writerBuf != nil { //TODO: // This operation holds everything in memory, // should be changed to stream the block creation/storage @@ -321,9 +324,10 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error { //NOTE: // This should only occur on a file object, if this were to be a // folder, bad things would happen. - newNode, err := imp.NewDagFromReader(n.dataBuf) + buf := bytes.NewReader(n.writerBuf.Bytes()) + newNode, err := imp.NewDagFromReader(buf) if err != nil { - log.Critical("error creating dag from dataBuf: %s", err) + log.Critical("error creating dag from writerBuf: %s", err) return fuse.ENODATA } if n.parent != nil { @@ -350,7 +354,7 @@ func (n *Node) Flush(req *fuse.FlushRequest, intr fs.Intr) fuse.Error { fmt.Println(string(b)) // - n.dataBuf = nil + n.writerBuf = nil n.wasChanged() } @@ -382,7 +386,7 @@ func (n *Node) republishRoot() error { return err } - n.dataBuf = nil + n.writerBuf = nil ndkey, err := root.Nd.Key() if err != nil { diff --git a/fuse/ipns/writerat.go b/fuse/ipns/writerat.go new file mode 100644 index 000000000..c5ddf5c5c --- /dev/null +++ b/fuse/ipns/writerat.go @@ -0,0 +1,29 @@ +package ipns + +import "io" + +type WriteAtBuf interface { + io.WriterAt + Bytes() []byte +} + +type writerAt struct { + buf []byte +} + +func NewWriterAtFromBytes(b []byte) WriteAtBuf { + return &writerAt{b} +} + +// TODO: make this better in the future, this is just a quick hack for now +func (wa *writerAt) WriteAt(p []byte, off int64) (int, error) { + if off+int64(len(p)) > int64(len(wa.buf)) { + wa.buf = append(wa.buf, make([]byte, (int(off)+len(p))-len(wa.buf))...) + } + copy(wa.buf[off:], p) + return len(p), nil +} + +func (wa *writerAt) Bytes() []byte { + return wa.buf +} -- GitLab