0eef0ede89
Badger can take 1000x the amount of needed space if not GC'ed or compacted (#1320), even for non heavy usage. Cluster has no provisions to run datastore GC operations and while they could be added, they are not ensured to help. Improvements on Badger v3 might help but would still need to GC explicitally. Cluster was however designed to support any go-datastore as backend. This commit adds LevelDB support. LevelDB go-datastore wrapper is mature, does not need GC and should work well for most cluster usecases, which are not overly demanding. A new `--datastore` flag has been added on init. The store backend is selected based on the value in the configuration, similar to how raft/crdt is. The default is set to leveldb. From now on it should be easier to add additional backends, i.e. badgerv3.
72 lines
1.6 KiB
Go
72 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"path"
|
|
|
|
fslock "github.com/ipfs/go-fs-lock"
|
|
"github.com/ipfs/ipfs-cluster/cmdutils"
|
|
)
|
|
|
|
// lock logic heavily inspired by go-ipfs/repo/fsrepo/lock/lock.go
|
|
|
|
// The name of the file used for locking
|
|
const lockFileName = "cluster.lock"
|
|
|
|
var locker *lock
|
|
|
|
// lock helps to coordinate proceeds via a lock file
|
|
type lock struct {
|
|
lockCloser io.Closer
|
|
path string
|
|
}
|
|
|
|
func (l *lock) lock() {
|
|
if l.lockCloser != nil {
|
|
checkErr("", errors.New("cannot acquire lock twice"))
|
|
}
|
|
|
|
// we should have a config folder whenever we try to lock
|
|
cfgHelper := cmdutils.NewConfigHelper(configPath, identityPath, "", "")
|
|
cfgHelper.MakeConfigFolder()
|
|
|
|
// set the lock file within this function
|
|
logger.Debug("checking lock")
|
|
lk, err := fslock.Lock(l.path, lockFileName)
|
|
if err != nil {
|
|
logger.Debug(err)
|
|
l.lockCloser = nil
|
|
errStr := "%s. If no other "
|
|
errStr += "%s process is running, remove %s, or make sure "
|
|
errStr += "that the config folder is writable for the user "
|
|
errStr += "running %s."
|
|
errStr = fmt.Sprintf(
|
|
errStr,
|
|
err,
|
|
programName,
|
|
path.Join(l.path, lockFileName),
|
|
programName,
|
|
)
|
|
checkErr("obtaining execution lock", errors.New(errStr))
|
|
}
|
|
logger.Debugf("%s execution lock acquired", programName)
|
|
l.lockCloser = lk
|
|
}
|
|
|
|
func (l *lock) tryUnlock() error {
|
|
// Noop in the uninitialized case
|
|
if l.lockCloser == nil {
|
|
logger.Debug("locking not initialized, unlock is noop")
|
|
return nil
|
|
}
|
|
err := l.lockCloser.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Debug("successfully released execution lock")
|
|
l.lockCloser = nil
|
|
return nil
|
|
}
|