1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-20 02:21:48 +08:00

fix context respect through fuse reading

This commit is contained in:
Jeromy
2015-03-23 14:01:42 -07:00
parent d8bc95f43e
commit 13c489eca1
8 changed files with 65 additions and 36 deletions

View File

@ -254,7 +254,7 @@ func (rw *RefWriter) writeRefsRecursive(n *dag.Node) (int, error) {
return count, err
}
nd, err := ng.Get()
nd, err := ng.Get(rw.Ctx)
if err != nil {
return count, err
}

View File

@ -6,7 +6,6 @@ package ipns
import (
"errors"
"io"
"os"
fuse "github.com/jbenet/go-ipfs/Godeps/_workspace/src/bazil.org/fuse"
@ -274,32 +273,26 @@ func (dir *Directory) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
}
func (fi *File) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
errs := make(chan error, 1)
go func() {
_, err := fi.fi.Seek(req.Offset, os.SEEK_SET)
if err != nil {
errs <- err
return
return err
}
fisize, err := fi.fi.Size()
if err != nil {
errs <- err
return
return err
}
readsize := min(req.Size, int(fisize-req.Offset))
n, err := io.ReadFull(fi.fi, resp.Data[:readsize])
resp.Data = resp.Data[:n]
errs <- err
}()
select {
case <-ctx.Done():
return ctx.Err()
case err := <-errs:
return err
default:
}
readsize := min(req.Size, int(fisize-req.Offset))
n, err := fi.fi.CtxReadFull(ctx, resp.Data[:readsize])
resp.Data = resp.Data[:n]
return err
}
func (fi *File) Write(ctx context.Context, req *fuse.WriteRequest, resp *fuse.WriteResponse) error {

View File

@ -51,6 +51,13 @@ func (fi *File) Read(b []byte) (int, error) {
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 {

View File

@ -257,10 +257,10 @@ type nodePromise struct {
// from its internal channels, subsequent calls will return the
// cached node.
type NodeGetter interface {
Get() (*Node, error)
Get(context.Context) (*Node, error)
}
func (np *nodePromise) Get() (*Node, error) {
func (np *nodePromise) Get(ctx context.Context) (*Node, error) {
if np.cache != nil {
return np.cache, nil
}
@ -270,6 +270,8 @@ func (np *nodePromise) Get() (*Node, error) {
np.cache = blk
case <-np.ctx.Done():
return nil, np.ctx.Err()
case <-ctx.Done():
return nil, ctx.Err()
}
return np.cache, nil
}

View File

@ -177,7 +177,7 @@ func (p *pinner) pinLinks(node *mdag.Node) error {
defer cancel()
for _, ng := range p.dserv.GetDAG(ctx, node) {
subnode, err := ng.Get()
subnode, err := ng.Get(ctx)
if err != nil {
// TODO: Maybe just log and continue?
return err

View File

@ -100,12 +100,13 @@ func newDataFileReader(ctx context.Context, n *mdag.Node, pb *ftpb.Data, serv md
// precalcNextBuf follows the next link in line and loads it from the DAGService,
// setting the next buffer to read from
func (dr *DagReader) precalcNextBuf() error {
func (dr *DagReader) precalcNextBuf(ctx context.Context) error {
dr.buf.Close() // Just to make sure
if dr.linkPosition >= len(dr.promises) {
return io.EOF
}
nxt, err := dr.promises[dr.linkPosition].Get()
nxt, err := dr.promises[dr.linkPosition].Get(ctx)
if err != nil {
return err
}
@ -141,6 +142,11 @@ func (dr *DagReader) Size() int64 {
// Read reads data from the DAG structured file
func (dr *DagReader) Read(b []byte) (int, error) {
return dr.CtxReadFull(dr.ctx, b)
}
// CtxReadFull reads data from the DAG structured file
func (dr *DagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) {
// If no cached buffer, load one
total := 0
for {
@ -161,7 +167,7 @@ func (dr *DagReader) Read(b []byte) (int, error) {
}
// Otherwise, load up the next block
err = dr.precalcNextBuf()
err = dr.precalcNextBuf(ctx)
if err != nil {
return total, err
}
@ -183,7 +189,7 @@ func (dr *DagReader) WriteTo(w io.Writer) (int64, error) {
}
// Otherwise, load up the next block
err = dr.precalcNextBuf()
err = dr.precalcNextBuf(dr.ctx)
if err != nil {
if err == io.EOF {
return total, nil
@ -239,7 +245,7 @@ func (dr *DagReader) Seek(offset int64, whence int) (int64, error) {
}
// start sub-block request
err := dr.precalcNextBuf()
err := dr.precalcNextBuf(dr.ctx)
if err != nil {
return 0, err
}

View File

@ -315,32 +315,53 @@ func (dm *DagModifier) appendData(node *mdag.Node, blks <-chan []byte) (*mdag.No
// Read data from this dag starting at the current offset
func (dm *DagModifier) Read(b []byte) (int, error) {
err := dm.Sync()
err := dm.readPrep()
if err != nil {
return 0, err
}
n, err := dm.read.Read(b)
dm.curWrOff += uint64(n)
return n, err
}
func (dm *DagModifier) readPrep() error {
err := dm.Sync()
if err != nil {
return err
}
if dm.read == nil {
ctx, cancel := context.WithCancel(dm.ctx)
dr, err := uio.NewDagReader(ctx, dm.curNode, dm.dagserv)
if err != nil {
return 0, err
return err
}
i, err := dr.Seek(int64(dm.curWrOff), os.SEEK_SET)
if err != nil {
return 0, err
return err
}
if i != int64(dm.curWrOff) {
return 0, ErrSeekFail
return ErrSeekFail
}
dm.readCancel = cancel
dm.read = dr
}
n, err := dm.read.Read(b)
return nil
}
// Read data from this dag starting at the current offset
func (dm *DagModifier) CtxReadFull(ctx context.Context, b []byte) (int, error) {
err := dm.readPrep()
if err != nil {
return 0, err
}
n, err := dm.read.CtxReadFull(ctx, b)
dm.curWrOff += uint64(n)
return n, err
}

View File

@ -90,7 +90,7 @@ func (r *Reader) writeToBuf(dagnode *mdag.Node, path string, depth int) {
defer cancel()
for i, ng := range r.dag.GetDAG(ctx, dagnode) {
childNode, err := ng.Get()
childNode, err := ng.Get(ctx)
if err != nil {
r.emitError(err)
return