feat: Enable re-using write buffer and reading existing content into write buffer
This commit is contained in:
@@ -2,6 +2,7 @@ package fs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
@@ -208,12 +209,70 @@ func (f *File) Sync() error {
|
||||
}
|
||||
|
||||
func (f *File) enterWriteMode() error {
|
||||
log.Println("File.enterWriteMode")
|
||||
|
||||
if f.readOpReader != nil || f.readOpWriter != nil {
|
||||
if err := f.closeWithoutLocking(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if f.writeBuf == nil {
|
||||
exists := false
|
||||
_, err := inventory.Stat(
|
||||
f.metadata,
|
||||
|
||||
f.path,
|
||||
|
||||
f.onHeader,
|
||||
)
|
||||
if err == nil {
|
||||
exists = true
|
||||
} else {
|
||||
if err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create new buffer
|
||||
writeBuf, cleanWriteBuf, err := f.getFileBuffer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.writeBuf = writeBuf
|
||||
f.cleanWriteBuf = cleanWriteBuf
|
||||
|
||||
// Read existing file into buffer
|
||||
if exists {
|
||||
if err := f.readOps.Restore(
|
||||
func(path string, mode fs.FileMode) (io.WriteCloser, error) {
|
||||
// Don't close the file here, we want to re-use it!
|
||||
return ioext.AddCloseNopToWriter(f.writeBuf), nil
|
||||
},
|
||||
func(path string, mode fs.FileMode) error {
|
||||
// Not necessary; can't read on a directory
|
||||
return nil
|
||||
},
|
||||
|
||||
f.path,
|
||||
"",
|
||||
true,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Don't do this if O_APPEND is set
|
||||
if err := f.writeBuf.Truncate(0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := f.writeBuf.Seek(0, io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -231,17 +290,7 @@ func (f *File) Truncate(size int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if f.writeBuf == nil {
|
||||
writeBuf, cleanWriteBuf, err := f.getFileBuffer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.writeBuf = writeBuf
|
||||
f.cleanWriteBuf = cleanWriteBuf
|
||||
}
|
||||
|
||||
return f.writeBuf.Truncate(0)
|
||||
return f.writeBuf.Truncate(size)
|
||||
}
|
||||
|
||||
func (f *File) WriteString(s string) (ret int, err error) {
|
||||
@@ -258,16 +307,6 @@ func (f *File) WriteString(s string) (ret int, err error) {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if f.writeBuf == nil {
|
||||
writeBuf, cleanWriteBuf, err := f.getFileBuffer()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
f.writeBuf = writeBuf
|
||||
f.cleanWriteBuf = cleanWriteBuf
|
||||
}
|
||||
|
||||
return f.writeBuf.Write([]byte(s))
|
||||
}
|
||||
|
||||
@@ -314,6 +353,8 @@ func (f *File) Close() error {
|
||||
}
|
||||
|
||||
func (f *File) enterReadMode(lock bool) error {
|
||||
log.Println("File.enterReadMode", lock)
|
||||
|
||||
if lock {
|
||||
f.ioLock.Lock()
|
||||
defer f.ioLock.Unlock()
|
||||
@@ -499,16 +540,6 @@ func (f *File) Write(p []byte) (n int, err error) {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if f.writeBuf == nil {
|
||||
writeBuf, cleanWriteBuf, err := f.getFileBuffer()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
f.writeBuf = writeBuf
|
||||
f.cleanWriteBuf = cleanWriteBuf
|
||||
}
|
||||
|
||||
n, err = f.writeBuf.Write(p)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user