提交 89afdabb 作者: Brian Tiger Chow

refactor(fsrepo): move OpenerCounter

上级 97b865ff
...@@ -10,23 +10,24 @@ import ( ...@@ -10,23 +10,24 @@ import (
repo "github.com/jbenet/go-ipfs/repo" repo "github.com/jbenet/go-ipfs/repo"
common "github.com/jbenet/go-ipfs/repo/common" common "github.com/jbenet/go-ipfs/repo/common"
config "github.com/jbenet/go-ipfs/repo/config" config "github.com/jbenet/go-ipfs/repo/config"
opener "github.com/jbenet/go-ipfs/repo/fsrepo/opener"
util "github.com/jbenet/go-ipfs/util" util "github.com/jbenet/go-ipfs/util"
debugerror "github.com/jbenet/go-ipfs/util/debugerror" debugerror "github.com/jbenet/go-ipfs/util/debugerror"
) )
var ( 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. // FSRepo handles. It also ensures that the Init is atomic.
// //
// packageLock also protects numOpenedRepos // packageLock also protects numOpenedRepos
// //
// If an operation is used when repo is Open and the operation does not // 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. // change the repo's state, the package lock does not need to be acquired.
pkgLock *packageLock openerCounter *opener.Counter
) )
func init() { func init() {
pkgLock = makePackageLock() openerCounter = opener.NewCounter()
} }
// FSRepo represents an IPFS FileSystem Repo. It is not thread-safe. // FSRepo represents an IPFS FileSystem Repo. It is not thread-safe.
...@@ -47,8 +48,8 @@ func At(path string) *FSRepo { ...@@ -47,8 +48,8 @@ func At(path string) *FSRepo {
// Init initializes a new FSRepo at the given path with the provided config. // Init initializes a new FSRepo at the given path with the provided config.
func Init(path string, conf *config.Config) error { func Init(path string, conf *config.Config) error {
pkgLock.Lock() // lock must be held to ensure atomicity (prevent Removal) openerCounter.Lock() // lock must be held to ensure atomicity (prevent Removal)
defer pkgLock.Unlock() defer openerCounter.Unlock()
if isInitializedUnsynced(path) { if isInitializedUnsynced(path) {
return nil return nil
...@@ -65,9 +66,9 @@ func Init(path string, conf *config.Config) error { ...@@ -65,9 +66,9 @@ func Init(path string, conf *config.Config) error {
// Remove recursively removes the FSRepo at |path|. // Remove recursively removes the FSRepo at |path|.
func Remove(path string) error { func Remove(path string) error {
pkgLock.Lock() openerCounter.Lock()
defer pkgLock.Unlock() defer openerCounter.Unlock()
if pkgLock.NumOpeners(path) != 0 { if openerCounter.NumOpeners(path) != 0 {
return errors.New("repo in use") return errors.New("repo in use")
} }
return os.RemoveAll(path) return os.RemoveAll(path)
...@@ -75,8 +76,8 @@ func Remove(path string) error { ...@@ -75,8 +76,8 @@ func Remove(path string) error {
// Open returns an error if the repo is not initialized. // Open returns an error if the repo is not initialized.
func (r *FSRepo) Open() error { func (r *FSRepo) Open() error {
pkgLock.Lock() openerCounter.Lock()
defer pkgLock.Unlock() defer openerCounter.Unlock()
if r.state != unopened { if r.state != unopened {
return debugerror.Errorf("repo is %s", r.state) return debugerror.Errorf("repo is %s", r.state)
} }
...@@ -118,7 +119,7 @@ func (r *FSRepo) Open() error { ...@@ -118,7 +119,7 @@ func (r *FSRepo) Open() error {
} }
r.state = opened r.state = opened
pkgLock.AddOpener(r.path) openerCounter.AddOpener(r.path)
return nil return nil
} }
...@@ -211,12 +212,12 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error { ...@@ -211,12 +212,12 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
// Close closes the FSRepo, releasing held resources. // Close closes the FSRepo, releasing held resources.
func (r *FSRepo) Close() error { func (r *FSRepo) Close() error {
pkgLock.Lock() openerCounter.Lock()
defer pkgLock.Unlock() defer openerCounter.Unlock()
if r.state != opened { if r.state != opened {
return debugerror.Errorf("repo is %s", r.state) return debugerror.Errorf("repo is %s", r.state)
} }
pkgLock.RemoveOpener(r.path) openerCounter.RemoveOpener(r.path)
return nil // TODO release repo lock return nil // TODO release repo lock
} }
...@@ -225,13 +226,13 @@ var _ repo.Interface = &FSRepo{} ...@@ -225,13 +226,13 @@ var _ repo.Interface = &FSRepo{}
// IsInitialized returns true if the repo is initialized at provided |path|. // IsInitialized returns true if the repo is initialized at provided |path|.
func IsInitialized(path string) bool { func IsInitialized(path string) bool {
pkgLock.Lock() openerCounter.Lock()
defer pkgLock.Unlock() defer openerCounter.Unlock()
return isInitializedUnsynced(path) return isInitializedUnsynced(path)
} }
// isInitializedUnsynced reports whether the repo is initialized. Caller must // isInitializedUnsynced reports whether the repo is initialized. Caller must
// hold pkgLock. // hold openerCounter lock.
func isInitializedUnsynced(path string) bool { func isInitializedUnsynced(path string) bool {
configFilename, err := config.Filename(path) configFilename, err := config.Filename(path)
if err != nil { if err != nil {
......
...@@ -5,7 +5,7 @@ import ( ...@@ -5,7 +5,7 @@ import (
"sync" "sync"
) )
type packageLock struct { type Counter struct {
// lock protects repos // lock protects repos
lock sync.Mutex lock sync.Mutex
// repos maps repo paths to the number of openers holding an FSRepo handle // repos maps repo paths to the number of openers holding an FSRepo handle
...@@ -13,39 +13,39 @@ type packageLock struct { ...@@ -13,39 +13,39 @@ type packageLock struct {
repos map[string]int repos map[string]int
} }
func makePackageLock() *packageLock { func NewCounter() *Counter {
return &packageLock{ return &Counter{
repos: make(map[string]int), repos: make(map[string]int),
} }
} }
// Lock must be held to while performing any operation that modifies an // Lock must be held to while performing any operation that modifies an
// FSRepo's state field. This includes Init, Open, Close, and Remove. // FSRepo's state field. This includes Init, Open, Close, and Remove.
func (l *packageLock) Lock() { func (l *Counter) Lock() {
l.lock.Lock() l.lock.Lock()
} }
func (l *packageLock) Unlock() { func (l *Counter) Unlock() {
l.lock.Unlock() l.lock.Unlock()
} }
// NumOpeners returns the number of FSRepos holding a handle to the repo at // 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 // this path. This method is not thread-safe. The caller must have this object
// locked. // locked.
func (l *packageLock) NumOpeners(repoPath string) int { func (l *Counter) NumOpeners(repoPath string) int {
return l.repos[key(repoPath)] return l.repos[key(repoPath)]
} }
// AddOpener messages that an FSRepo holds a handle to the repo at this path. // 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. // 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)]++ l.repos[key(repoPath)]++
} }
// RemoveOpener messgaes that an FSRepo no longer holds a handle to the repo at // 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 // this path. This method is not thread-safe. The caller must have this object
// locked. // locked.
func (l *packageLock) RemoveOpener(repoPath string) { func (l *Counter) RemoveOpener(repoPath string) {
l.repos[key(repoPath)]-- l.repos[key(repoPath)]--
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论