use functional options in the BlockstoreGC interface
This commit is contained in:
parent
938330e6c3
commit
96c1123c33
@ -222,15 +222,14 @@ func (b *Blockstore) unlockMove(state int) {
|
|||||||
b.moveMx.Unlock()
|
b.moveMx.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// moveTo moves the blockstore to path, and creates a symlink from the current path
|
// movingGC moves the blockstore to a new path, adjacent to the current path, and creates
|
||||||
// to the new path; the old blockstore is deleted.
|
// 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
|
||||||
// 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,
|
// are persisted to the new blockstore; if a failure occurs aboring the move,
|
||||||
// then they must be peristed to the old blockstore.
|
// then they must be peristed to the old blockstore.
|
||||||
// In short, the blockstore must not lose data from new writes during the move.
|
// 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
|
// this inlines moveLock/moveUnlock for the initial state check to prevent a second move
|
||||||
// while one is in progress without clobbering state
|
// while one is in progress without clobbering state
|
||||||
b.moveMx.Lock()
|
b.moveMx.Lock()
|
||||||
@ -248,9 +247,7 @@ func (b *Blockstore) moveTo(path string) error {
|
|||||||
b.moveCond.Broadcast()
|
b.moveCond.Broadcast()
|
||||||
b.moveMx.Unlock()
|
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() {
|
defer func() {
|
||||||
b.lockMove()
|
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 {
|
func (b *Blockstore) onlineGC() error {
|
||||||
b.lockDB()
|
b.lockDB()
|
||||||
defer b.unlockDB()
|
defer b.unlockDB()
|
||||||
@ -529,6 +493,29 @@ func (b *Blockstore) onlineGC() error {
|
|||||||
return err
|
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
|
// Size returns the aggregate size of the blockstore
|
||||||
func (b *Blockstore) Size() (int64, error) {
|
func (b *Blockstore) Size() (int64, error) {
|
||||||
if err := b.access(); err != nil {
|
if err := b.access(); err != nil {
|
||||||
|
@ -154,9 +154,7 @@ func testMove(t *testing.T, optsF func(string) Options) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return db.CollectGarbage(map[interface{}]interface{}{
|
return db.CollectGarbage(blockstore.WithFullGC(true))
|
||||||
blockstore.BlockstoreMovingGC: true,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
err = g.Wait()
|
err = g.Wait()
|
||||||
|
@ -37,20 +37,23 @@ type BlockstoreIterator interface {
|
|||||||
|
|
||||||
// BlockstoreGC is a trait for blockstores that support online garbage collection
|
// BlockstoreGC is a trait for blockstores that support online garbage collection
|
||||||
type BlockstoreGC interface {
|
type BlockstoreGC interface {
|
||||||
CollectGarbage(options map[interface{}]interface{}) error
|
CollectGarbage(options ...BlockstoreGCOption) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// garbage collection options
|
// BlockstoreGCOption is a functional interface for controlling blockstore GC options
|
||||||
type blockstoreMovingGCKey struct{}
|
type BlockstoreGCOption = func(*BlockstoreGCOptions) error
|
||||||
type blockstoreMovingGCPath struct{}
|
|
||||||
|
|
||||||
// BlockstoreMovingGC is a garbage collection option that instructs the blockstore
|
// BlockstoreGCOptions is a struct with GC options
|
||||||
// to use moving GC if supported.
|
type BlockstoreGCOptions struct {
|
||||||
var BlockstoreMovingGC = blockstoreMovingGCKey{}
|
FullGC bool
|
||||||
|
}
|
||||||
|
|
||||||
// BlockstoreMovingGCPath is a garbage collection option that specifies an optional
|
func WithFullGC(fullgc bool) BlockstoreGCOption {
|
||||||
// target path for moving GC.
|
return func(opts *BlockstoreGCOptions) error {
|
||||||
var BlockstoreMovingGCPath = blockstoreMovingGCPath{}
|
opts.FullGC = fullgc
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BlockstoreSize is a trait for on-disk blockstores that can report their size
|
// BlockstoreSize is a trait for on-disk blockstores that can report their size
|
||||||
type BlockstoreSize interface {
|
type BlockstoreSize interface {
|
||||||
|
Loading…
Reference in New Issue
Block a user