// meaningless anyway
return
} else if ptr.off >= fn.fileinfo.size {
- ptr.off = fn.fileinfo.size
ptr.extentIdx = len(fn.extents)
ptr.extentOff = 0
ptr.repacked = fn.repacked
func (fn *filenode) Truncate(size int64) error {
fn.Lock()
defer fn.Unlock()
+ return fn.truncate(size)
+}
+
+func (fn *filenode) truncate(size int64) error {
+ if size == fn.fileinfo.size {
+ return nil
+ }
+ fn.repacked++
if size < fn.fileinfo.size {
- ptr := fn.seek(filenodePtr{off: size, repacked: fn.repacked - 1})
+ ptr := fn.seek(filenodePtr{off: size})
for i := ptr.extentIdx; i < len(fn.extents); i++ {
if ext, ok := fn.extents[i].(*memExtent); ok {
fn.memsize -= int64(ext.Len())
}
}
fn.fileinfo.size = size
- fn.repacked++
return nil
}
for size > fn.fileinfo.size {
} else if e, ok = fn.extents[len(fn.extents)-1].(writableExtent); !ok || e.Len() >= maxBlockSize {
e = &memExtent{}
fn.extents = append(fn.extents, e)
- } else {
- fn.repacked++
}
if maxgrow := int64(maxBlockSize - e.Len()); maxgrow < grow {
grow = maxgrow
return nil
}
+// Caller must hold lock.
func (fn *filenode) Write(p []byte, startPtr filenodePtr) (n int, ptr filenodePtr, err error) {
+ if startPtr.off > fn.fileinfo.size {
+ if err = fn.truncate(startPtr.off); err != nil {
+ return 0, startPtr, err
+ }
+ }
ptr = fn.seek(startPtr)
if ptr.off < 0 {
err = ErrNegativeOffset
if ptr.off < 0 {
return f.ptr.off, ErrNegativeOffset
}
- if ptr.off > size {
- ptr.off = size
- }
if ptr.off != f.ptr.off {
f.ptr = ptr
// force filenode to recompute f.ptr fields on next
c.Check(string(buf2), check.Equals, "f0123456789abcd\x00\x00\x00\x00\x00")
f.Truncate(0)
+ f2.Seek(0, os.SEEK_SET)
f2.Write([]byte("12345678abcdefghijkl"))
// grow to block/extent boundary
c.Check(m, check.Equals, "./dir1 3858f62230ac3c915f300c664312c63f+6 25d55ad283aa400af464c76d713c07ad+8 3:3:bar 6:3:foo\n")
}
+func (s *CollectionFSSuite) TestSeekSparse(c *check.C) {
+ fs, err := (&Collection{}).FileSystem(s.client, s.kc)
+ c.Assert(err, check.IsNil)
+ f, err := fs.OpenFile("test", os.O_CREATE|os.O_RDWR, 0755)
+ c.Assert(err, check.IsNil)
+ defer f.Close()
+
+ checkSize := func(size int64) {
+ fi, err := f.Stat()
+ c.Check(fi.Size(), check.Equals, size)
+
+ f, err := fs.OpenFile("test", os.O_CREATE|os.O_RDWR, 0755)
+ c.Assert(err, check.IsNil)
+ defer f.Close()
+ fi, err = f.Stat()
+ c.Check(fi.Size(), check.Equals, size)
+ pos, err := f.Seek(0, os.SEEK_END)
+ c.Check(pos, check.Equals, size)
+ }
+
+ f.Seek(2, os.SEEK_END)
+ checkSize(0)
+ f.Write([]byte{1})
+ checkSize(3)
+
+ f.Seek(2, os.SEEK_CUR)
+ checkSize(3)
+ f.Write([]byte{})
+ checkSize(5)
+
+ f.Seek(8, os.SEEK_SET)
+ checkSize(5)
+ n, err := f.Read(make([]byte, 1))
+ c.Check(n, check.Equals, 0)
+ c.Check(err, check.Equals, io.EOF)
+ checkSize(5)
+ f.Write([]byte{1, 2, 3})
+ checkSize(11)
+}
+
func (s *CollectionFSSuite) TestMarshalSmallBlocks(c *check.C) {
maxBlockSize = 8
defer func() { maxBlockSize = 2 << 26 }()