[#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 <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-09-14 17:44:07 +03:00 committed by Leonard Lyubich
parent cc5d3288a1
commit f73c5c2259
4 changed files with 27 additions and 7 deletions

View file

@ -106,3 +106,10 @@ func WithLogger(l *logger.Logger) Option {
c.log = l.With(zap.String("component", "Blobovnicza")) 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
}
}

View file

@ -16,17 +16,24 @@ import (
func (b *Blobovnicza) Open() error { func (b *Blobovnicza) Open() error {
b.log.Debug("creating directory for BoltDB", b.log.Debug("creating directory for BoltDB",
zap.String("path", b.path), zap.String("path", b.path),
zap.Bool("ro", b.boltOptions.ReadOnly),
) )
err := util.MkdirAllX(path.Dir(b.path), b.perm) var err error
if err == nil {
if !b.boltOptions.ReadOnly {
err = util.MkdirAllX(path.Dir(b.path), b.perm)
if err != nil {
return err
}
}
b.log.Debug("opening BoltDB", b.log.Debug("opening BoltDB",
zap.String("path", b.path), zap.String("path", b.path),
zap.Stringer("permissions", b.perm), zap.Stringer("permissions", b.perm),
) )
b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions) b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions)
}
return err return err
} }
@ -34,6 +41,8 @@ func (b *Blobovnicza) Open() error {
// Init initializes internal database structure. // Init initializes internal database structure.
// //
// If Blobovnicza is already initialized, then no action is taken. // If Blobovnicza is already initialized, then no action is taken.
//
// Should not be called in read-only configuration.
func (b *Blobovnicza) Init() error { func (b *Blobovnicza) Init() error {
b.log.Debug("initializing...", b.log.Debug("initializing...",
zap.Uint64("object size limit", b.objSizeLimit), zap.Uint64("object size limit", b.objSizeLimit),

View file

@ -27,6 +27,8 @@ func (p *DeletePrm) SetAddress(addr *objectSDK.Address) {
// did not allow to completely delete the object. // did not allow to completely delete the object.
// //
// Returns ErrNotFound if the object to be deleted is not in blobovnicza. // 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) { func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) {
addrKey := addressKey(prm.addr) addrKey := addressKey(prm.addr)

View file

@ -47,6 +47,8 @@ func (p *PutPrm) SetMarshaledObject(data []byte) {
// did not allow to completely save the object. // did not allow to completely save the object.
// //
// Returns ErrFull if blobovnicza is filled. // Returns ErrFull if blobovnicza is filled.
//
// Should not be called in read-only configuration.
func (b *Blobovnicza) Put(prm *PutPrm) (*PutRes, error) { func (b *Blobovnicza) Put(prm *PutPrm) (*PutRes, error) {
addr := prm.addr addr := prm.addr
if addr == nil { if addr == nil {