use functional options in the BlockstoreGC interface

This commit is contained in:
vyzo 2021-07-27 09:50:44 +03:00
parent 938330e6c3
commit 96c1123c33
3 changed files with 43 additions and 55 deletions

View File

@ -222,15 +222,14 @@ func (b *Blockstore) unlockMove(state int) {
b.moveMx.Unlock()
}
// moveTo moves the blockstore to path, and creates a symlink from the current path
// to the new path; the old blockstore is deleted.
// If path is empty, then a new path adjacent to the current path is created
// automatically.
// The blockstore must accept new writes during the move and ensure that these
// movingGC moves the blockstore to a new path, adjacent to the current path, and creates
// a symlink from the current path to the new path; the old blockstore is deleted.
//
// The blockstore MUST accept new writes during the move and ensure that these
// are persisted to the new blockstore; if a failure occurs aboring the move,
// then they must be peristed to the old blockstore.
// In short, the blockstore must not lose data from new writes during the move.
func (b *Blockstore) moveTo(path string) error {
func (b *Blockstore) movingGC() error {
// this inlines moveLock/moveUnlock for the initial state check to prevent a second move
// while one is in progress without clobbering state
b.moveMx.Lock()
@ -248,9 +247,7 @@ func (b *Blockstore) moveTo(path string) error {
b.moveCond.Broadcast()
b.moveMx.Unlock()
if path == "" {
path = fmt.Sprintf("%s.%d", b.opts.Dir, time.Now().Unix())
}
path := fmt.Sprintf("%s.%d", b.opts.Dir, time.Now().Unix())
defer func() {
b.lockMove()
@ -469,39 +466,6 @@ func (b *Blockstore) deleteDB(path string) {
}
}
// CollectGarbage compacts and runs garbage collection on the value log;
// implements the BlockstoreGC trait
func (b *Blockstore) CollectGarbage(options map[interface{}]interface{}) error {
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
var movingGC bool
movingGCOpt, ok := options[blockstore.BlockstoreMovingGC]
if ok {
movingGC, ok = movingGCOpt.(bool)
if !ok {
return fmt.Errorf("incorrect type for moving gc option; expected bool but got %T", movingGCOpt)
}
}
if !movingGC {
return b.onlineGC()
}
var movingGCPath string
movingGCPathOpt, ok := options[blockstore.BlockstoreMovingGCPath]
if ok {
movingGCPath, ok = movingGCPathOpt.(string)
if !ok {
return fmt.Errorf("incorrect type for moving gc path option; expected string but got %T", movingGCPathOpt)
}
}
return b.moveTo(movingGCPath)
}
func (b *Blockstore) onlineGC() error {
b.lockDB()
defer b.unlockDB()
@ -529,6 +493,29 @@ func (b *Blockstore) onlineGC() error {
return err
}
// CollectGarbage compacts and runs garbage collection on the value log;
// implements the BlockstoreGC trait
func (b *Blockstore) CollectGarbage(opts ...blockstore.BlockstoreGCOption) error {
if err := b.access(); err != nil {
return err
}
defer b.viewers.Done()
var options blockstore.BlockstoreGCOptions
for _, opt := range opts {
err := opt(&options)
if err != nil {
return err
}
}
if options.FullGC {
return b.movingGC()
}
return b.onlineGC()
}
// Size returns the aggregate size of the blockstore
func (b *Blockstore) Size() (int64, error) {
if err := b.access(); err != nil {

View File

@ -154,9 +154,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
return nil
})
g.Go(func() error {
return db.CollectGarbage(map[interface{}]interface{}{
blockstore.BlockstoreMovingGC: true,
})
return db.CollectGarbage(blockstore.WithFullGC(true))
})
err = g.Wait()

View File

@ -37,20 +37,23 @@ type BlockstoreIterator interface {
// BlockstoreGC is a trait for blockstores that support online garbage collection
type BlockstoreGC interface {
CollectGarbage(options map[interface{}]interface{}) error
CollectGarbage(options ...BlockstoreGCOption) error
}
// garbage collection options
type blockstoreMovingGCKey struct{}
type blockstoreMovingGCPath struct{}
// BlockstoreGCOption is a functional interface for controlling blockstore GC options
type BlockstoreGCOption = func(*BlockstoreGCOptions) error
// BlockstoreMovingGC is a garbage collection option that instructs the blockstore
// to use moving GC if supported.
var BlockstoreMovingGC = blockstoreMovingGCKey{}
// BlockstoreGCOptions is a struct with GC options
type BlockstoreGCOptions struct {
FullGC bool
}
// BlockstoreMovingGCPath is a garbage collection option that specifies an optional
// target path for moving GC.
var BlockstoreMovingGCPath = blockstoreMovingGCPath{}
func WithFullGC(fullgc bool) BlockstoreGCOption {
return func(opts *BlockstoreGCOptions) error {
opts.FullGC = fullgc
return nil
}
}
// BlockstoreSize is a trait for on-disk blockstores that can report their size
type BlockstoreSize interface {