From f73c5c2259a1390afeee13e2c431f9a098135150 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 14 Sep 2021 17:44:07 +0300 Subject: [PATCH] [#791] blobovnicza: Support read-only mode There is a need to open Blobovnicza instances in read-only mode in some cases. Add `ReadOnly` option. Do not create dir path in RO. Open underlying BoltDB instance with ReadOnly flag. Document thal all writing operations should not be called in ro (otherwise BoltDB txs fail). Signed-off-by: Leonard Lyubich --- .../blobovnicza/blobovnicza.go | 7 ++++++ .../blobovnicza/control.go | 23 +++++++++++++------ .../blobovnicza/delete.go | 2 ++ pkg/local_object_storage/blobovnicza/put.go | 2 ++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza.go b/pkg/local_object_storage/blobovnicza/blobovnicza.go index fc7795d3..dd8dbbba 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza.go @@ -106,3 +106,10 @@ func WithLogger(l *logger.Logger) Option { c.log = l.With(zap.String("component", "Blobovnicza")) } } + +// ReadOnly returns option to open Blobovnicza in read-only mode. +func ReadOnly() Option { + return func(c *cfg) { + c.boltOptions.ReadOnly = true + } +} diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index 7c39717c..5c214131 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -16,24 +16,33 @@ import ( func (b *Blobovnicza) Open() error { b.log.Debug("creating directory for BoltDB", zap.String("path", b.path), + zap.Bool("ro", b.boltOptions.ReadOnly), ) - err := util.MkdirAllX(path.Dir(b.path), b.perm) - if err == nil { - b.log.Debug("opening BoltDB", - zap.String("path", b.path), - zap.Stringer("permissions", b.perm), - ) + var err error - b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions) + if !b.boltOptions.ReadOnly { + err = util.MkdirAllX(path.Dir(b.path), b.perm) + if err != nil { + return err + } } + b.log.Debug("opening BoltDB", + zap.String("path", b.path), + zap.Stringer("permissions", b.perm), + ) + + b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions) + return err } // Init initializes internal database structure. // // If Blobovnicza is already initialized, then no action is taken. +// +// Should not be called in read-only configuration. func (b *Blobovnicza) Init() error { b.log.Debug("initializing...", zap.Uint64("object size limit", b.objSizeLimit), diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index a7974d63..0100e651 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -27,6 +27,8 @@ func (p *DeletePrm) SetAddress(addr *objectSDK.Address) { // did not allow to completely delete the object. // // Returns ErrNotFound if the object to be deleted is not in blobovnicza. +// +// Should not be called in read-only configuration. func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) { addrKey := addressKey(prm.addr) diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index 0160f308..5075697f 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -47,6 +47,8 @@ func (p *PutPrm) SetMarshaledObject(data []byte) { // did not allow to completely save the object. // // Returns ErrFull if blobovnicza is filled. +// +// Should not be called in read-only configuration. func (b *Blobovnicza) Put(prm *PutPrm) (*PutRes, error) { addr := prm.addr if addr == nil {