提交 d5ce5da5 作者: Tommi Virtanen

Remove fsrepo Datastore refcounting

repo.Once now does refcounts on a whole Repo level, returning the same
pointer to multiple Openers. This removes the need for the weird model
of separate FSRepo instances pointing to the same underlying storage,
and the races caused by that.
上级 c8992f2c
...@@ -46,11 +46,6 @@ var ( ...@@ -46,11 +46,6 @@ var (
// 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.
openersCounter *counter.Openers openersCounter *counter.Openers
// protects dsOpenersCounter and datastores
dsLock sync.Mutex
dsOpenersCounter *counter.Openers
datastores map[string]ds2.ThreadSafeDatastoreCloser
// onlyOne keeps track of open FSRepo instances. // onlyOne keeps track of open FSRepo instances.
// //
// TODO: once command Context / Repo integration is cleaned up, // TODO: once command Context / Repo integration is cleaned up,
...@@ -69,9 +64,6 @@ var ( ...@@ -69,9 +64,6 @@ var (
func init() { func init() {
openersCounter = counter.NewOpenersCounter() openersCounter = counter.NewOpenersCounter()
lockfiles = make(map[string]io.Closer) lockfiles = make(map[string]io.Closer)
dsOpenersCounter = counter.NewOpenersCounter()
datastores = make(map[string]ds2.ThreadSafeDatastoreCloser)
} }
// 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
...@@ -254,32 +246,14 @@ func (r *FSRepo) openConfig() error { ...@@ -254,32 +246,14 @@ func (r *FSRepo) openConfig() error {
// openDatastore returns an error if the config file is not present. // openDatastore returns an error if the config file is not present.
func (r *FSRepo) openDatastore() error { func (r *FSRepo) openDatastore() error {
dsLock.Lock()
defer dsLock.Unlock()
dsPath := path.Join(r.path, defaultDataStoreDirectory) dsPath := path.Join(r.path, defaultDataStoreDirectory)
ds, err := levelds.NewDatastore(dsPath, &levelds.Options{
// if no other goroutines have the datastore Open, initialize it and assign Compression: ldbopts.NoCompression,
// it to the package-scoped map for the goroutines that follow. })
if dsOpenersCounter.NumOpeners(dsPath) == 0 { if err != nil {
ds, err := levelds.NewDatastore(dsPath, &levelds.Options{ return debugerror.New("unable to open leveldb datastore")
Compression: ldbopts.NoCompression,
})
if err != nil {
return debugerror.New("unable to open leveldb datastore")
}
datastores[dsPath] = ds
}
// get the datastore from the package-scoped map and record self as an
// opener.
ds, dsIsPresent := datastores[dsPath]
if !dsIsPresent {
// This indicates a programmer error has occurred.
return errors.New("datastore should be available, but it isn't")
} }
r.ds = ds r.ds = ds
dsOpenersCounter.AddOpener(dsPath) // only after success
return nil return nil
} }
...@@ -295,24 +269,6 @@ func configureEventLoggerAtRepoPath(c *config.Config, repoPath string) { ...@@ -295,24 +269,6 @@ func configureEventLoggerAtRepoPath(c *config.Config, repoPath string) {
eventlog.Configure(eventlog.OutputRotatingLogFile(rotateConf)) eventlog.Configure(eventlog.OutputRotatingLogFile(rotateConf))
} }
func (r *FSRepo) closeDatastore() error {
dsLock.Lock()
defer dsLock.Unlock()
dsPath := path.Join(r.path, defaultDataStoreDirectory)
// decrement the Opener count. if this goroutine is the last, also close
// the underlying datastore (and remove its reference from the map)
dsOpenersCounter.RemoveOpener(dsPath)
if dsOpenersCounter.NumOpeners(dsPath) == 0 {
delete(datastores, dsPath) // remove the reference
return r.ds.Close()
}
return nil
}
// Close closes the FSRepo, releasing held resources. // Close closes the FSRepo, releasing held resources.
func (r *FSRepo) Close() error { func (r *FSRepo) Close() error {
packageLock.Lock() packageLock.Lock()
...@@ -322,7 +278,7 @@ func (r *FSRepo) Close() error { ...@@ -322,7 +278,7 @@ func (r *FSRepo) Close() error {
return debugerror.Errorf("repo is %s", r.state) return debugerror.Errorf("repo is %s", r.state)
} }
if err := r.closeDatastore(); err != nil { if err := r.ds.Close(); err != nil {
return err return err
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论