mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-25 04:17:44 +08:00
refactor(fsrepo): move OpenerCounter
This commit is contained in:
parent
97b865ff6f
commit
89afdabb7e
@ -10,23 +10,24 @@ import (
|
||||
repo "github.com/jbenet/go-ipfs/repo"
|
||||
common "github.com/jbenet/go-ipfs/repo/common"
|
||||
config "github.com/jbenet/go-ipfs/repo/config"
|
||||
opener "github.com/jbenet/go-ipfs/repo/fsrepo/opener"
|
||||
util "github.com/jbenet/go-ipfs/util"
|
||||
debugerror "github.com/jbenet/go-ipfs/util/debugerror"
|
||||
)
|
||||
|
||||
var (
|
||||
// pkgLock prevents the fsrepo from being removed while there exist open
|
||||
// openerCounter prevents the fsrepo from being removed while there exist open
|
||||
// FSRepo handles. It also ensures that the Init is atomic.
|
||||
//
|
||||
// packageLock also protects numOpenedRepos
|
||||
//
|
||||
// If an operation is used when repo is Open and the operation does not
|
||||
// change the repo's state, the package lock does not need to be acquired.
|
||||
pkgLock *packageLock
|
||||
openerCounter *opener.Counter
|
||||
)
|
||||
|
||||
func init() {
|
||||
pkgLock = makePackageLock()
|
||||
openerCounter = opener.NewCounter()
|
||||
}
|
||||
|
||||
// FSRepo represents an IPFS FileSystem Repo. It is not thread-safe.
|
||||
@ -47,8 +48,8 @@ func At(path string) *FSRepo {
|
||||
|
||||
// Init initializes a new FSRepo at the given path with the provided config.
|
||||
func Init(path string, conf *config.Config) error {
|
||||
pkgLock.Lock() // lock must be held to ensure atomicity (prevent Removal)
|
||||
defer pkgLock.Unlock()
|
||||
openerCounter.Lock() // lock must be held to ensure atomicity (prevent Removal)
|
||||
defer openerCounter.Unlock()
|
||||
|
||||
if isInitializedUnsynced(path) {
|
||||
return nil
|
||||
@ -65,9 +66,9 @@ func Init(path string, conf *config.Config) error {
|
||||
|
||||
// Remove recursively removes the FSRepo at |path|.
|
||||
func Remove(path string) error {
|
||||
pkgLock.Lock()
|
||||
defer pkgLock.Unlock()
|
||||
if pkgLock.NumOpeners(path) != 0 {
|
||||
openerCounter.Lock()
|
||||
defer openerCounter.Unlock()
|
||||
if openerCounter.NumOpeners(path) != 0 {
|
||||
return errors.New("repo in use")
|
||||
}
|
||||
return os.RemoveAll(path)
|
||||
@ -75,8 +76,8 @@ func Remove(path string) error {
|
||||
|
||||
// Open returns an error if the repo is not initialized.
|
||||
func (r *FSRepo) Open() error {
|
||||
pkgLock.Lock()
|
||||
defer pkgLock.Unlock()
|
||||
openerCounter.Lock()
|
||||
defer openerCounter.Unlock()
|
||||
if r.state != unopened {
|
||||
return debugerror.Errorf("repo is %s", r.state)
|
||||
}
|
||||
@ -118,7 +119,7 @@ func (r *FSRepo) Open() error {
|
||||
}
|
||||
|
||||
r.state = opened
|
||||
pkgLock.AddOpener(r.path)
|
||||
openerCounter.AddOpener(r.path)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -211,12 +212,12 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
|
||||
|
||||
// Close closes the FSRepo, releasing held resources.
|
||||
func (r *FSRepo) Close() error {
|
||||
pkgLock.Lock()
|
||||
defer pkgLock.Unlock()
|
||||
openerCounter.Lock()
|
||||
defer openerCounter.Unlock()
|
||||
if r.state != opened {
|
||||
return debugerror.Errorf("repo is %s", r.state)
|
||||
}
|
||||
pkgLock.RemoveOpener(r.path)
|
||||
openerCounter.RemoveOpener(r.path)
|
||||
return nil // TODO release repo lock
|
||||
}
|
||||
|
||||
@ -225,13 +226,13 @@ var _ repo.Interface = &FSRepo{}
|
||||
|
||||
// IsInitialized returns true if the repo is initialized at provided |path|.
|
||||
func IsInitialized(path string) bool {
|
||||
pkgLock.Lock()
|
||||
defer pkgLock.Unlock()
|
||||
openerCounter.Lock()
|
||||
defer openerCounter.Unlock()
|
||||
return isInitializedUnsynced(path)
|
||||
}
|
||||
|
||||
// isInitializedUnsynced reports whether the repo is initialized. Caller must
|
||||
// hold pkgLock.
|
||||
// hold openerCounter lock.
|
||||
func isInitializedUnsynced(path string) bool {
|
||||
configFilename, err := config.Filename(path)
|
||||
if err != nil {
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type packageLock struct {
|
||||
type Counter struct {
|
||||
// lock protects repos
|
||||
lock sync.Mutex
|
||||
// repos maps repo paths to the number of openers holding an FSRepo handle
|
||||
@ -13,39 +13,39 @@ type packageLock struct {
|
||||
repos map[string]int
|
||||
}
|
||||
|
||||
func makePackageLock() *packageLock {
|
||||
return &packageLock{
|
||||
func NewCounter() *Counter {
|
||||
return &Counter{
|
||||
repos: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
// Lock must be held to while performing any operation that modifies an
|
||||
// FSRepo's state field. This includes Init, Open, Close, and Remove.
|
||||
func (l *packageLock) Lock() {
|
||||
func (l *Counter) Lock() {
|
||||
l.lock.Lock()
|
||||
}
|
||||
|
||||
func (l *packageLock) Unlock() {
|
||||
func (l *Counter) Unlock() {
|
||||
l.lock.Unlock()
|
||||
}
|
||||
|
||||
// NumOpeners returns the number of FSRepos holding a handle to the repo at
|
||||
// this path. This method is not thread-safe. The caller must have this object
|
||||
// locked.
|
||||
func (l *packageLock) NumOpeners(repoPath string) int {
|
||||
func (l *Counter) NumOpeners(repoPath string) int {
|
||||
return l.repos[key(repoPath)]
|
||||
}
|
||||
|
||||
// AddOpener messages that an FSRepo holds a handle to the repo at this path.
|
||||
// This method is not thread-safe. The caller must have this object locked.
|
||||
func (l *packageLock) AddOpener(repoPath string) {
|
||||
func (l *Counter) AddOpener(repoPath string) {
|
||||
l.repos[key(repoPath)]++
|
||||
}
|
||||
|
||||
// RemoveOpener messgaes that an FSRepo no longer holds a handle to the repo at
|
||||
// this path. This method is not thread-safe. The caller must have this object
|
||||
// locked.
|
||||
func (l *packageLock) RemoveOpener(repoPath string) {
|
||||
func (l *Counter) RemoveOpener(repoPath string) {
|
||||
l.repos[key(repoPath)]--
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user