Fix sized filesystem

If purging is enabled, overwriting a file with a file of the same
or smaller size will not result in an error.

It is now possible to change the purging mode on an existing sized
filesystem.
This commit is contained in:
Ingo Oppermann
2023-09-22 14:16:46 +02:00
parent 0f4c88be39
commit c3b63c4480
5 changed files with 68 additions and 9 deletions

View File

@@ -426,7 +426,7 @@ func (a *api) start() error {
} else { } else {
a.memfs.SetMetadata("base", baseMemFS.String()) a.memfs.SetMetadata("base", baseMemFS.String())
if sizedfs, ok := a.memfs.(fs.SizedFilesystem); ok { if sizedfs, ok := a.memfs.(fs.SizedFilesystem); ok {
sizedfs.Resize(cfg.Storage.Memory.Size * 1024 * 1024) sizedfs.Resize(cfg.Storage.Memory.Size*1024*1024, cfg.Storage.Memory.Purge)
} }
} }

View File

@@ -49,6 +49,6 @@ func (r *readOnlyFilesystem) Purge(size int64) int64 {
return 0 return 0
} }
func (r *readOnlyFilesystem) Resize(size int64) error { func (r *readOnlyFilesystem) Resize(size int64, purge bool) error {
return os.ErrPermission return os.ErrPermission
} }

View File

@@ -45,6 +45,6 @@ func TestReadOnly(t *testing.T) {
ros, ok := ro.(SizedFilesystem) ros, ok := ro.(SizedFilesystem)
require.True(t, ok, "must implement SizedFilesystem") require.True(t, ok, "must implement SizedFilesystem")
err = ros.Resize(100) err = ros.Resize(100, false)
require.Error(t, err) require.Error(t, err)
} }

View File

@@ -10,7 +10,7 @@ type SizedFilesystem interface {
Filesystem Filesystem
// Resize resizes the filesystem to the new size. Files may need to be deleted. // Resize resizes the filesystem to the new size. Files may need to be deleted.
Resize(size int64) error Resize(size int64, purge bool) error
} }
type PurgeFilesystem interface { type PurgeFilesystem interface {
@@ -48,7 +48,9 @@ func (r *sizedFilesystem) Size() (int64, int64) {
return currentSize, r.maxSize return currentSize, r.maxSize
} }
func (r *sizedFilesystem) Resize(size int64) error { func (r *sizedFilesystem) Resize(size int64, purge bool) error {
r.purge = purge
currentSize, _ := r.Size() currentSize, _ := r.Size()
if size >= currentSize { if size >= currentSize {
// If the new size is the same or larger than the current size, // If the new size is the same or larger than the current size,
@@ -82,9 +84,15 @@ func (r *sizedFilesystem) WriteFileReader(path string, rd io.Reader) (int64, boo
return -1, false, fmt.Errorf("File is too big") return -1, false, fmt.Errorf("File is too big")
} }
// Calculate the new size of the filesystem
newSize := currentSize + size newSize := currentSize + size
// Calculate the new size of the filesystem
finfo, err := r.Filesystem.Stat(path)
if err == nil {
// If the file already exist, take it's size into account
newSize -= finfo.Size()
}
// If the the new size is larger than the allowed size, we have to free // If the the new size is larger than the allowed size, we have to free
// some space. // some space.
if newSize > maxSize { if newSize > maxSize {
@@ -117,9 +125,15 @@ func (r *sizedFilesystem) WriteFileSafe(path string, data []byte) (int64, bool,
return -1, false, fmt.Errorf("File is too big") return -1, false, fmt.Errorf("File is too big")
} }
// Calculate the new size of the filesystem
newSize := currentSize + size newSize := currentSize + size
// Calculate the new size of the filesystem
finfo, err := r.Filesystem.Stat(path)
if err == nil {
// If the file already exist, take it's size into account
newSize -= finfo.Size()
}
// If the the new size is larger than the allowed size, we have to free // If the the new size is larger than the allowed size, we have to free
// some space. // some space.
if newSize > maxSize { if newSize > maxSize {

View File

@@ -35,7 +35,7 @@ func TestSizedResize(t *testing.T) {
require.Equal(t, int64(0), cur) require.Equal(t, int64(0), cur)
require.Equal(t, int64(10), max) require.Equal(t, int64(10), max)
err := fs.Resize(20) err := fs.Resize(20, false)
require.NoError(t, err) require.NoError(t, err)
cur, max = fs.Size() cur, max = fs.Size()
@@ -44,6 +44,26 @@ func TestSizedResize(t *testing.T) {
require.Equal(t, int64(20), max) require.Equal(t, int64(20), max)
} }
func TestSizedResizeSetPurge(t *testing.T) {
fs, _ := NewSizedFilesystem(newMemFS(), 10, false)
_, _, err := fs.WriteFileReader("/foobar1", strings.NewReader("xxxxx"))
require.NoError(t, err)
_, _, err = fs.WriteFileReader("/foobar2", strings.NewReader("xxxxx"))
require.NoError(t, err)
_, _, err = fs.WriteFileReader("/foobar3", strings.NewReader("xxxxx"))
require.Error(t, err)
fs.Resize(10, true)
_, _, err = fs.WriteFileReader("/foobar3", strings.NewReader("xxxxx"))
require.NoError(t, err)
require.Equal(t, int64(2), fs.Files())
}
func TestSizedResizePurge(t *testing.T) { func TestSizedResizePurge(t *testing.T) {
fs, _ := NewSizedFilesystem(newMemFS(), 10, false) fs, _ := NewSizedFilesystem(newMemFS(), 10, false)
@@ -59,7 +79,7 @@ func TestSizedResizePurge(t *testing.T) {
require.Equal(t, int64(10), cur) require.Equal(t, int64(10), cur)
require.Equal(t, int64(10), max) require.Equal(t, int64(10), max)
err := fs.Resize(5) err := fs.Resize(5, false)
require.NoError(t, err) require.NoError(t, err)
cur, max = fs.Size() cur, max = fs.Size()
@@ -132,6 +152,31 @@ func TestSizedReplaceNoPurge(t *testing.T) {
cur = fs.Files() cur = fs.Files()
require.Equal(t, int64(1), cur) require.Equal(t, int64(1), cur)
data = strings.NewReader("zzzzzzz")
size, created, err = fs.WriteFileReader("/foobar", data)
require.Nil(t, err)
require.Equal(t, int64(7), size)
require.Equal(t, false, created)
cur, max = fs.Size()
require.Equal(t, int64(7), cur)
require.Equal(t, int64(10), max)
cur = fs.Files()
require.Equal(t, int64(1), cur)
data = strings.NewReader("zzzzzzzz")
size, created, err = fs.WriteFileReader("/foobar", data)
require.Nil(t, err)
require.Equal(t, int64(8), size)
require.Equal(t, false, created)
} }
func TestSizedReplacePurge(t *testing.T) { func TestSizedReplacePurge(t *testing.T) {