From fddd3ac7f799cbb22871ad0760ffbf28646d204c Mon Sep 17 00:00:00 2001 From: Benjamin Wang Date: Fri, 26 May 2023 16:13:13 +0800 Subject: [PATCH] remove field 'filesz' from DB There is no reason to maintain a file size. It's only used when mapping the db or growing the db; obviously neither are hot path. Signed-off-by: Benjamin Wang --- db.go | 35 ++++++++++++++++++++++------------- db_test.go | 3 ++- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/db.go b/db.go index 4b8a4b8..4a73ce1 100644 --- a/db.go +++ b/db.go @@ -119,7 +119,6 @@ type DB struct { dataref []byte // mmap'ed readonly, write throws SEGV data *[maxMapSize]byte datasz int - filesz int // current on disk file size meta0 *common.Meta meta1 *common.Meta pageSize int @@ -402,21 +401,29 @@ func (db *DB) hasSyncedFreelist() bool { return db.meta().Freelist() != common.PgidNoFreelist } +func (db *DB) fileSize() (int, error) { + info, err := db.file.Stat() + if err != nil { + return 0, fmt.Errorf("file stat error: %w", err) + } + sz := int(info.Size()) + if sz < db.pageSize*2 { + return 0, fmt.Errorf("file size too small %d", sz) + } + return sz, nil +} + // mmap opens the underlying memory-mapped file and initializes the meta references. // minsz is the minimum size that the new mmap can be. func (db *DB) mmap(minsz int) (err error) { db.mmaplock.Lock() defer db.mmaplock.Unlock() - info, err := db.file.Stat() - if err != nil { - return fmt.Errorf("mmap stat error: %s", err) - } else if int(info.Size()) < db.pageSize*2 { - return fmt.Errorf("file size too small") - } - // Ensure the size is at least the minimum size. - fileSize := int(info.Size()) + fileSize, err := db.fileSize() + if err != nil { + return err + } var size = fileSize if size < minsz { size = minsz @@ -610,7 +617,6 @@ func (db *DB) init() error { if err := fdatasync(db); err != nil { return err } - db.filesz = len(buf) return nil } @@ -1120,7 +1126,11 @@ func (db *DB) allocate(txid common.Txid, count int) (*common.Page, error) { // grow grows the size of the database to the given sz. func (db *DB) grow(sz int) error { // Ignore if the new size is less than available file size. - if sz <= db.filesz { + fileSize, err := db.fileSize() + if err != nil { + return err + } + if sz <= fileSize { return nil } @@ -1147,13 +1157,12 @@ func (db *DB) grow(sz int) error { } if db.Mlock { // unlock old file and lock new one - if err := db.mrelock(db.filesz, sz); err != nil { + if err := db.mrelock(fileSize, sz); err != nil { return fmt.Errorf("mlock/munlock error: %s", err) } } } - db.filesz = sz return nil } diff --git a/db_test.go b/db_test.go index 1b10367..5700f86 100644 --- a/db_test.go +++ b/db_test.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "reflect" + "strings" "sync" "testing" "time" @@ -443,7 +444,7 @@ func TestOpen_FileTooSmall(t *testing.T) { } _, err = bolt.Open(path, 0666, nil) - if err == nil || err.Error() != "file size too small" { + if err == nil || !strings.Contains(err.Error(), "file size too small") { t.Fatalf("unexpected error: %s", err) } }