// WriteAt implements Filer. func (f *MemFiler) WriteAt(b []byte, off int64) (n int, err error) { pgI := off >> pgBits pgO := int(off & pgMask) n = len(b) rem := n var nc int for rem != 0 { if pgO == 0 && rem >= pgSize && bytes.Equal(b[:pgSize], zeroPage[:]) { delete(f.m, pgI) nc = pgSize } else { pg := f.m[pgI] if pg == nil { pg = new([pgSize]byte) f.m[pgI] = pg } nc = copy((*pg)[pgO:], b) } pgI++ pgO = 0 rem -= nc b = b[nc:] } f.size = mathutil.MaxInt64(f.size, off+int64(n)) return }
func newFile(f *os.File, maxSize int64, pgBits uint) (*file, error) { if maxSize < 0 { panic("internal error") } pgSize := 1 << pgBits switch { case sysPage > pgSize: pgBits = uint(mathutil.Log2Uint64(uint64(sysPage))) default: pgBits = uint(mathutil.Log2Uint64(uint64(pgSize / sysPage * sysPage))) } pgSize = 1 << pgBits fi := &file{ f: f, m: fileMap{}, maxPages: int(mathutil.MinInt64( 1024, mathutil.MaxInt64(maxSize/int64(pgSize), 1)), ), pgBits: pgBits, pgMask: pgSize - 1, pgSize: pgSize, } info, err := f.Stat() if err != nil { return nil, err } if err = fi.Truncate(info.Size()); err != nil { return nil, err } return fi, nil }
func (f *bitFiler) WriteAt(b []byte, off int64) (n int, err error) { off0 := off pgI := off >> bfBits pgO := int(off & bfMask) n = len(b) rem := n var nc int for rem != 0 { pg := f.m[pgI] if pg == nil { pg = &bitPage{} pg.pdata = buffer.CGet(bfSize) pg.data = *pg.pdata if f.parent != nil { _, err = f.parent.ReadAt(pg.data, off&^bfMask) if err != nil && !fileutil.IsEOF(err) { return } err = nil } f.m[pgI] = pg } nc = copy(pg.data[pgO:], b) pgI++ pg.dirty = true pgO = 0 rem -= nc b = b[nc:] off += int64(nc) } f.size = mathutil.MaxInt64(f.size, off0+int64(n)) return }
func (f *bitFiler) WriteAt(b []byte, off int64) (n int, err error) { off0 := off pgI := off >> bfBits pgO := int(off & bfMask) n = len(b) rem := n var nc int for rem != 0 { pg := f.m[pgI] if pg == nil { pg = &bitPage{} if f.parent != nil { _, err = f.parent.ReadAt(pg.data[:], off&^bfMask) if err != nil && !fileutil.IsEOF(err) { return } err = nil } f.m[pgI] = pg } nc = copy(pg.data[pgO:], b) pgI++ pg.dirty = true for i := pgO; i < pgO+nc; i++ { pg.flags[i>>3] |= bitmask[i&7] } pgO = 0 rem -= nc b = b[nc:] off += int64(nc) } f.size = mathutil.MaxInt64(f.size, off0+int64(n)) return }
// Size implements Filer. func (f *InnerFiler) Size() (int64, error) { sz, err := f.outer.Size() if err != nil { return 0, err } return mathutil.MaxInt64(sz-f.off, 0), nil }
func copyBlockData(blockData []byte, readStart int64, blockStart int64, readEnd int64, blockEnd int64, data []byte) { for j := mathutil.MaxInt64(readStart, blockStart); j < readEnd && j < blockEnd; j++ { outputItr := j - readStart inputItr := j - blockStart data[outputItr] = blockData[inputItr] } }
// WriteAt implements Filer. func (f *SimpleFileFiler) WriteAt(b []byte, off int64) (n int, err error) { if f.size < 0 { // boot fi, err := os.Stat(f.file.Name()) if err != nil { return 0, err } f.size = fi.Size() } f.size = mathutil.MaxInt64(f.size, int64(len(b))+off) return f.file.WriteAt(b, off) }
func (f *File) writeAt(b []byte, off int64, bits bool) (n int, err error) { var fsize int64 a := (*Array)(f) if !bits { fsize, err = f.Size() if err != nil { return } } pgI := off >> pgBits pgO := int(off & pgMask) rem := len(b) var nc int for rem != 0 { if pgO == 0 && rem >= pgSize && bytes.Equal(b[:pgSize], zeroPage[:]) { if err = a.Delete(pgI); err != nil { return } nc = pgSize n += nc } else { v, err := a.Get(pgI) if err != nil { return n, err } pg, _ := v.([]byte) if len(pg) == 0 { pg = make([]byte, pgSize) } nc = copy(pg[pgO:], b) n += nc if err = a.Set(pg, pgI); err != nil { return n, err } } pgI++ pgO = 0 rem -= nc b = b[nc:] } if !bits { if newSize := mathutil.MaxInt64(fsize, off+int64(n)); newSize != fsize { return n, a.Set(newSize, fSize) } } return }
func (f *mem) WriteAt(b []byte, off int64) (n int, err error) { pi := off >> f.pgBits po := int(off) & f.pgMask n = len(b) rem := n var nc int for rem != 0 { pg := f.m[pi] if pg == nil { pg = buffer.CGet(f.pgSize) f.m[pi] = pg } nc = copy((*pg)[po:], b) pi++ po = 0 rem -= nc b = b[nc:] } f.size = mathutil.MaxInt64(f.size, off+int64(n)) return n, nil }
func (f *file) WriteAt(b []byte, off int64) (n int, err error) { pi := off >> f.pgBits po := int(off) & f.pgMask n = len(b) rem := n var nc int for rem != 0 { pg := f.m[pi] if pg == nil { pg, err = f.page(pi) if err != nil { return n, err } } nc = copy(pg[po:], b) pi++ po = 0 rem -= nc b = b[nc:] } f.size = mathutil.MaxInt64(f.size, off+int64(n)) return n, nil }
// NewACIDFiler0 returns a newly created ACIDFiler0 with WAL in wal. // // If the WAL is zero sized then a previous clean shutdown of db is taken for // granted and no recovery procedure is taken. // // If the WAL is of non zero size then it is checked for having a // commited/fully finished transaction not yet been reflected in db. If such // transaction exists it's committed to db. If the recovery process finishes // successfully, the WAL is truncated to zero size and fsync'ed prior to return // from NewACIDFiler0. func NewACIDFiler(db Filer, wal *os.File) (r *ACIDFiler0, err error) { fi, err := wal.Stat() if err != nil { return } r = &ACIDFiler0{wal: wal} if fi.Size() != 0 { if err = r.recoverDb(db); err != nil { return } } acidWriter := (*acidWriter0)(r) if r.RollbackFiler, err = NewRollbackFiler( db, func(sz int64) (err error) { // Checkpoint if err = acidWriter.writePacket([]interface{}{wpt00Checkpoint, sz}); err != nil { return } if err = r.bwal.Flush(); err != nil { return } r.bwal = nil if err = r.wal.Sync(); err != nil { return } wfi, err := r.wal.Stat() switch err != nil { case true: // unexpected, but ignored case false: r.peakWal = mathutil.MaxInt64(wfi.Size(), r.peakWal) } // Phase 1 commit complete for _, v := range r.data { if _, err := db.WriteAt(v.b, v.off); err != nil { return err } } if err = db.Truncate(sz); err != nil { return } if err = db.Sync(); err != nil { return } // Phase 2 commit complete if !r.testHook { if err = r.wal.Truncate(0); err != nil { return } if _, err = r.wal.Seek(0, 0); err != nil { return } } r.testHook = false return r.wal.Sync() }, acidWriter, ); err != nil { return } return r, nil }