update to allow a WriteAt call for cirfiles

This commit is contained in:
sawka 2022-08-19 12:51:37 -07:00
parent e1eecae6d3
commit 26bd499fac
2 changed files with 91 additions and 6 deletions

View File

@ -307,18 +307,24 @@ func (f *File) getFreeChunks() []fileChunk {
return rtn
}
// returns (realOffset, data, error)
// will only return io.EOF when len(data) == 0, otherwise will just do a short read
func (f *File) ReadNext(ctx context.Context, buf []byte, offset int64) (int64, int, error) {
func (f *File) ReadAll(ctx context.Context) (int64, []byte, error) {
err := f.flock(ctx, syscall.LOCK_SH)
if err != nil {
return 0, 0, err
return 0, nil, err
}
defer f.unflock()
err = f.readMeta()
if err != nil {
return 0, 0, err
return 0, nil, err
}
chunks := f.getFileChunks()
curSize := totalChunksSize(chunks)
buf := make([]byte, curSize)
realOffset, nr, err := f.internalReadNext(buf, 0)
return realOffset, buf[0:nr], err
}
func (f *File) internalReadNext(buf []byte, offset int64) (int64, int, error) {
if offset < f.FileOffset {
offset = f.FileOffset
}
@ -347,6 +353,21 @@ func (f *File) ReadNext(ctx context.Context, buf []byte, offset int64) (int64, i
return offset, numRead, nil
}
// returns (realOffset, numread, error)
// will only return io.EOF when len(data) == 0, otherwise will just do a short read
func (f *File) ReadNext(ctx context.Context, buf []byte, offset int64) (int64, int, error) {
err := f.flock(ctx, syscall.LOCK_SH)
if err != nil {
return 0, 0, err
}
defer f.unflock()
err = f.readMeta()
if err != nil {
return 0, 0, err
}
return f.internalReadNext(buf, offset)
}
func (f *File) ensureFreeSpace(requiredSpace int64) error {
chunks := f.getFileChunks()
curSpace := f.MaxSize - totalChunksSize(chunks)

View File

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path"
"strings"
"syscall"
"testing"
"time"
@ -28,7 +29,9 @@ func validateMeta(t *testing.T, desc string, f *File, startPos int64, endPos int
func dumpFile(name string) {
barr, _ := os.ReadFile(name)
fmt.Printf("<<<\n%s\n>>>", string(barr))
str := string(barr)
str = strings.ReplaceAll(str, "\x00", ".")
fmt.Printf("%s<<<\n%s\n>>>\n", name, str)
}
func makeData(size int) string {
@ -216,3 +219,64 @@ func TestFlock(t *testing.T) {
t.Fatalf("append error (should work fd2 was closed): %v", err)
}
}
func TestWriteAt(t *testing.T) {
tempDir := t.TempDir()
f1Name := path.Join(tempDir, "f1.cf")
f, err := CreateCirFile(f1Name, 100)
if err != nil {
t.Fatalf("cannot create cirfile: %v", err)
}
err = f.WriteAt(nil, []byte("hello\nmike"), 4)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
err = f.WriteAt(nil, []byte("t"), 2)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
err = f.WriteAt(nil, []byte("more"), 30)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
err = f.WriteAt(nil, []byte("\n"), 19)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
dumpFile(f1Name)
err = f.WriteAt(nil, []byte("hello"), 200)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
buf := make([]byte, 10)
realOffset, nr, err := f.ReadNext(context.Background(), buf, 200)
if err != nil || realOffset != 200 || nr != 5 || string(buf[0:nr]) != "hello" {
t.Fatalf("invalid readnext: err[%v] realoffset[%d] nr[%d] buf[%s]", err, realOffset, nr, string(buf[0:nr]))
}
err = f.WriteAt(nil, []byte("0123456789\n"), 100)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
dumpFile(f1Name)
dataStr := makeData(200)
err = f.WriteAt(nil, []byte(dataStr), 50)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
dumpFile(f1Name)
dataStr = makeData(1000)
err = f.WriteAt(nil, []byte(dataStr), 1002)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
err = f.WriteAt(nil, []byte("hello\n"), 2010)
if err != nil {
t.Fatalf("writeat error: %v", err)
}
err = f.AppendData(nil, []byte("foo\n"))
if err != nil {
t.Fatalf("appenddata error: %v", err)
}
dumpFile(f1Name)
}