github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/ipnsfs/file.go (about)

     1  package ipnsfs
     2  
     3  import (
     4  	"sync"
     5  
     6  	chunk "github.com/ipfs/go-ipfs/importer/chunk"
     7  	dag "github.com/ipfs/go-ipfs/merkledag"
     8  	mod "github.com/ipfs/go-ipfs/unixfs/mod"
     9  
    10  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    11  )
    12  
    13  type File struct {
    14  	parent childCloser
    15  	fs     *Filesystem
    16  
    17  	name       string
    18  	hasChanges bool
    19  
    20  	mod  *mod.DagModifier
    21  	lock sync.Mutex
    22  }
    23  
    24  // NewFile returns a NewFile object with the given parameters
    25  func NewFile(name string, node *dag.Node, parent childCloser, fs *Filesystem) (*File, error) {
    26  	dmod, err := mod.NewDagModifier(context.Background(), node, fs.dserv, fs.pins.GetManual(), chunk.DefaultSplitter)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	return &File{
    32  		fs:     fs,
    33  		parent: parent,
    34  		name:   name,
    35  		mod:    dmod,
    36  	}, nil
    37  }
    38  
    39  // Write writes the given data to the file at its current offset
    40  func (fi *File) Write(b []byte) (int, error) {
    41  	fi.Lock()
    42  	defer fi.Unlock()
    43  	fi.hasChanges = true
    44  	return fi.mod.Write(b)
    45  }
    46  
    47  // Read reads into the given buffer from the current offset
    48  func (fi *File) Read(b []byte) (int, error) {
    49  	fi.Lock()
    50  	defer fi.Unlock()
    51  	return fi.mod.Read(b)
    52  }
    53  
    54  // Read reads into the given buffer from the current offset
    55  func (fi *File) CtxReadFull(ctx context.Context, b []byte) (int, error) {
    56  	fi.Lock()
    57  	defer fi.Unlock()
    58  	return fi.mod.CtxReadFull(ctx, b)
    59  }
    60  
    61  // Close flushes, then propogates the modified dag node up the directory structure
    62  // and signals a republish to occur
    63  func (fi *File) Close() error {
    64  	fi.Lock()
    65  	defer fi.Unlock()
    66  	if fi.hasChanges {
    67  		err := fi.mod.Sync()
    68  		if err != nil {
    69  			return err
    70  		}
    71  
    72  		nd, err := fi.mod.GetNode()
    73  		if err != nil {
    74  			return err
    75  		}
    76  
    77  		fi.Unlock()
    78  		err = fi.parent.closeChild(fi.name, nd)
    79  		fi.Lock()
    80  		if err != nil {
    81  			return err
    82  		}
    83  
    84  		fi.hasChanges = false
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  // Sync flushes the changes in the file to disk
    91  func (fi *File) Sync() error {
    92  	fi.Lock()
    93  	defer fi.Unlock()
    94  	return fi.mod.Sync()
    95  }
    96  
    97  // Seek implements io.Seeker
    98  func (fi *File) Seek(offset int64, whence int) (int64, error) {
    99  	fi.Lock()
   100  	defer fi.Unlock()
   101  	return fi.mod.Seek(offset, whence)
   102  }
   103  
   104  // Write At writes the given bytes at the offset 'at'
   105  func (fi *File) WriteAt(b []byte, at int64) (int, error) {
   106  	fi.Lock()
   107  	defer fi.Unlock()
   108  	fi.hasChanges = true
   109  	return fi.mod.WriteAt(b, at)
   110  }
   111  
   112  // Size returns the size of this file
   113  func (fi *File) Size() (int64, error) {
   114  	fi.Lock()
   115  	defer fi.Unlock()
   116  	return fi.mod.Size()
   117  }
   118  
   119  // GetNode returns the dag node associated with this file
   120  func (fi *File) GetNode() (*dag.Node, error) {
   121  	fi.Lock()
   122  	defer fi.Unlock()
   123  	return fi.mod.GetNode()
   124  }
   125  
   126  // Truncate truncates the file to size
   127  func (fi *File) Truncate(size int64) error {
   128  	fi.Lock()
   129  	defer fi.Unlock()
   130  	fi.hasChanges = true
   131  	return fi.mod.Truncate(size)
   132  }
   133  
   134  // Type returns the type FSNode this is
   135  func (fi *File) Type() NodeType {
   136  	return TFile
   137  }
   138  
   139  // Lock the file
   140  func (fi *File) Lock() {
   141  	fi.lock.Lock()
   142  }
   143  
   144  // Unlock the file
   145  func (fi *File) Unlock() {
   146  	fi.lock.Unlock()
   147  }