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 }