// SliceAt implements the fs.SlicerAt interface func (s *Store) SliceAt(sz, off int64) (p []byte, err error) { fn := func(i, start, end int64) (stop bool, err error) { s.segmx.RLock() if i >= int64(len(s.segs)) { s.segmx.RUnlock() return false, io.EOF } s.segmx.RUnlock() seg := s.segs[i] p = seg.Data[start:end] // mark that the mmap may have changed (sliced data can be changed) // TODO We're setting this as changed but the change is going to // happen later (if it happens at all). Try to fix this problem. atomic.StoreUint32(&seg.dirty, 1) return true, nil } if err := segments.Bounds(s.size, off, off+sz, fn); err != nil { return nil, err } return p, nil }
// WriteAt implements the io.WriterAt interface func (s *Store) WriteAt(p []byte, off int64) (n int, err error) { sz := int64(len(p)) towrite := p[:] var toalloc int64 fn := func(i, start, end int64) (stop bool, err error) { if err := s.ensure(i); err != nil { return false, err } seg := s.segs[i] c := copy(seg.Data[start:end], towrite) // mark the segment as changed atomic.StoreUint32(&seg.dirty, 1) n += c towrite = towrite[c:] toalloc = i + 1 return false, nil } if err := segments.Bounds(s.size, off, off+sz, fn); err != nil { return n, err } return n, nil }
// ReadAt implements the io.ReaderAt interface func (s *Store) ReadAt(p []byte, off int64) (n int, err error) { sz := int64(len(p)) toread := p[:] fn := func(i, start, end int64) (stop bool, err error) { s.segmx.RLock() if i >= int64(len(s.segs)) { s.segmx.RUnlock() return false, io.EOF } s.segmx.RUnlock() var done int64 req := end - start seg := s.segs[i] for done < req { c, err := seg.ReadAt(toread[:req-done], start+done) if err != nil { return false, err } n += c done += int64(c) toread = toread[c:] } return false, nil } err = segments.Bounds(s.size, off, off+sz, fn) return n, err }
// ReadAt implements the io.ReaderAt interface func (s *Store) ReadAt(p []byte, off int64) (n int, err error) { sz := int64(len(p)) toread := p[:] fn := func(i, start, end int64) (stop bool, err error) { s.segmx.RLock() if i >= int64(len(s.segs)) { s.segmx.RUnlock() return false, io.EOF } s.segmx.RUnlock() seg := s.segs[i] c := copy(toread, seg.Data[start:end]) n += c toread = toread[c:] return false, nil } err = segments.Bounds(s.size, off, off+sz, fn) return n, err }
// WriteAt implements the io.WriterAt interface func (s *Store) WriteAt(p []byte, off int64) (n int, err error) { sz := int64(len(p)) towrite := p[:] fn := func(i, start, end int64) (stop bool, err error) { if err := s.ensure(i); err != nil { return false, err } var done int64 req := end - start seg := s.segs[i] for done < req { c, err := seg.WriteAt(towrite[:req-done], start+done) if err != nil { return false, err } n += c done += int64(c) towrite = towrite[c:] } // mark the segment as changed atomic.StoreUint32(&seg.dirty, 1) return false, nil } if err := segments.Bounds(s.size, off, off+sz, fn); err != nil { return n, err } return n, nil }