提交 55228dae 作者: Tommi Virtanen

Simplify FSRepo life cycle, it's either open or closed

上级 384ca525
package fsrepo package fsrepo
import ( import (
"fmt"
"io" "io"
"os" "os"
"path" "path"
...@@ -52,14 +51,13 @@ var ( ...@@ -52,14 +51,13 @@ var (
// FSRepo represents an IPFS FileSystem Repo. It is safe for use by multiple // FSRepo represents an IPFS FileSystem Repo. It is safe for use by multiple
// callers. // callers.
type FSRepo struct { type FSRepo struct {
// state is the FSRepo's state (unopened, opened, closed) // has Close been called already
state state closed bool
// path is the file-system path // path is the file-system path
path string path string
// lockfile is the file system lock to prevent others from opening // lockfile is the file system lock to prevent others from opening
// the same fsrepo path concurrently // the same fsrepo path concurrently
lockfile io.Closer lockfile io.Closer
// config is set on Open, guarded by packageLock
config *config.Config config *config.Config
// ds is set on Open // ds is set on Open
ds ds2.ThreadSafeDatastoreCloser ds ds2.ThreadSafeDatastoreCloser
...@@ -110,9 +108,11 @@ func open(repoPath string) (repo.Repo, error) { ...@@ -110,9 +108,11 @@ func open(repoPath string) (repo.Repo, error) {
// log.Debugf("writing eventlogs to ...", c.path) // log.Debugf("writing eventlogs to ...", c.path)
configureEventLoggerAtRepoPath(r.config, r.path) configureEventLoggerAtRepoPath(r.config, r.path)
if err := r.transitionToOpened(); err != nil { closer, err := lockfile.Lock(r.path)
if err != nil {
return nil, err return nil, err
} }
r.lockfile = closer
return r, nil return r, nil
} }
...@@ -255,8 +255,8 @@ func (r *FSRepo) Close() error { ...@@ -255,8 +255,8 @@ func (r *FSRepo) Close() error {
packageLock.Lock() packageLock.Lock()
defer packageLock.Unlock() defer packageLock.Unlock()
if r.state != opened { if r.closed {
return debugerror.Errorf("repo is %s", r.state) return debugerror.New("repo is closed")
} }
if err := r.ds.Close(); err != nil { if err := r.ds.Close(); err != nil {
...@@ -271,7 +271,11 @@ func (r *FSRepo) Close() error { ...@@ -271,7 +271,11 @@ func (r *FSRepo) Close() error {
// to disable logging once the component is closed. // to disable logging once the component is closed.
// eventlog.Configure(eventlog.Output(os.Stderr)) // eventlog.Configure(eventlog.Output(os.Stderr))
return r.transitionToClosed() r.closed = true
if err := r.lockfile.Close(); err != nil {
return err
}
return nil
} }
// Config returns the FSRepo's config. This method must not be called if the // Config returns the FSRepo's config. This method must not be called if the
...@@ -288,8 +292,8 @@ func (r *FSRepo) Config() *config.Config { ...@@ -288,8 +292,8 @@ func (r *FSRepo) Config() *config.Config {
packageLock.Lock() packageLock.Lock()
defer packageLock.Unlock() defer packageLock.Unlock()
if r.state != opened { if r.closed {
panic(fmt.Sprintln("repo is", r.state)) panic("repo is closed")
} }
return r.config return r.config
} }
...@@ -336,8 +340,8 @@ func (r *FSRepo) GetConfigKey(key string) (interface{}, error) { ...@@ -336,8 +340,8 @@ func (r *FSRepo) GetConfigKey(key string) (interface{}, error) {
packageLock.Lock() packageLock.Lock()
defer packageLock.Unlock() defer packageLock.Unlock()
if r.state != opened { if r.closed {
return nil, debugerror.Errorf("repo is %s", r.state) return nil, debugerror.New("repo is closed")
} }
filename, err := config.Filename(r.path) filename, err := config.Filename(r.path)
...@@ -356,8 +360,8 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error { ...@@ -356,8 +360,8 @@ func (r *FSRepo) SetConfigKey(key string, value interface{}) error {
packageLock.Lock() packageLock.Lock()
defer packageLock.Unlock() defer packageLock.Unlock()
if r.state != opened { if r.closed {
return debugerror.Errorf("repo is %s", r.state) return debugerror.New("repo is closed")
} }
filename, err := config.Filename(r.path) filename, err := config.Filename(r.path)
...@@ -422,25 +426,3 @@ func isInitializedUnsynced(repoPath string) bool { ...@@ -422,25 +426,3 @@ func isInitializedUnsynced(repoPath string) bool {
} }
return true return true
} }
// transitionToOpened manages the state transition to |opened|. Caller must hold
// the package mutex.
func (r *FSRepo) transitionToOpened() error {
r.state = opened
closer, err := lockfile.Lock(r.path)
if err != nil {
return err
}
r.lockfile = closer
return nil
}
// transitionToClosed manages the state transition to |closed|. Caller must
// hold the package mutex.
func (r *FSRepo) transitionToClosed() error {
r.state = closed
if err := r.lockfile.Close(); err != nil {
return err
}
return nil
}
package fsrepo
type state int
const (
unopened = iota
opened
closed
)
func (s state) String() string {
switch s {
case unopened:
return "unopened"
case opened:
return "opened"
case closed:
return "closed"
default:
return "invalid"
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论