From 4060955efe29b9428d31285a61fd4447622f2f7c Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Fri, 11 Aug 2023 12:48:47 +0400 Subject: [PATCH] peapod: Optimize read-only mode It makes no sense to repeatedly begin writeable BoltDB transactions and start flushing routine when underlying BoltDB instance is read-only. Require root bucket to be presented in the BoltDB instance in read-only configuration. Signed-off-by: Leonard Lyubich --- pkg/local_object_storage/peapod/peapod.go | 33 ++++++++++++++++++----- pkg/local_object_storage/peapod/write.go | 4 +++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/peapod/peapod.go b/pkg/local_object_storage/peapod/peapod.go index ea74665734c..fb1de76fb89 100644 --- a/pkg/local_object_storage/peapod/peapod.go +++ b/pkg/local_object_storage/peapod/peapod.go @@ -30,6 +30,8 @@ type batch struct { // Peapod is a single low-level key/value database optimized to work with big // number of stored units. type Peapod struct { + readOnly bool + bolt *bbolt.DB currentBatchMtx sync.RWMutex @@ -52,14 +54,29 @@ func New(path string, perm fs.FileMode, readOnly bool) (*Peapod, error) { return nil, fmt.Errorf("open BoltDB instance: %w", err) } - if !readOnly { - err = db.Update(func(tx *bbolt.Tx) error { - _, err = tx.CreateBucketIfNotExists(rootBucket) - return err + if readOnly { + err = db.View(func(tx *bbolt.Tx) error { + if tx.Bucket(rootBucket) == nil { + return errMissingRootBucket + } + return nil }) if err != nil { - return nil, fmt.Errorf("create root bucket in BoltDB instance: %w", err) + return nil, fmt.Errorf("check root bucket presence in BoltDB instance: %w", err) } + + return &Peapod{ + readOnly: true, + bolt: db, + }, nil + } + + err = db.Update(func(tx *bbolt.Tx) error { + _, err = tx.CreateBucketIfNotExists(rootBucket) + return err + }) + if err != nil { + return nil, fmt.Errorf("create root bucket in BoltDB instance: %w", err) } res := &Peapod{ @@ -77,8 +94,10 @@ func New(path string, perm fs.FileMode, readOnly bool) (*Peapod, error) { // Close syncs data and closes the database. func (x *Peapod) Close() error { - close(x.chClose) - <-x.chFlushDone + if !x.readOnly { + close(x.chClose) + <-x.chFlushDone + } return x.bolt.Close() } diff --git a/pkg/local_object_storage/peapod/write.go b/pkg/local_object_storage/peapod/write.go index 19720e3ccca..2a6f4aee107 100644 --- a/pkg/local_object_storage/peapod/write.go +++ b/pkg/local_object_storage/peapod/write.go @@ -38,6 +38,10 @@ func (x *Peapod) Delete(ctx context.Context, addr oid.Address) error { } func (x *Peapod) batch(ctx context.Context, fBktRoot func(bktRoot *bbolt.Bucket) error) error { + if x.readOnly { + return bbolt.ErrDatabaseReadOnly + } + x.currentBatchMtx.RLock() currentBatch := x.currentBatch