diff --git a/cache/cache.go b/cache/cache.go index 5de251bfc..4603fe7ed 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -330,9 +330,9 @@ func NewFs(name, rpath string) (fs.Fs, error) { dbPath = filepath.Join(dbPath, name+".db") fs.Infof(name, "Storage DB path: %v", dbPath) - f.cache = GetPersistent(dbPath, *cacheDbPurge) + f.cache, err = GetPersistent(dbPath, *cacheDbPurge) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "failed to start cache db") } // Trap SIGINT and SIGTERM to close the DB handle gracefully c := make(chan os.Signal, 1) diff --git a/cache/cache_internal_test.go b/cache/cache_internal_test.go index 18107863b..04b2a5070 100644 --- a/cache/cache_internal_test.go +++ b/cache/cache_internal_test.go @@ -44,7 +44,8 @@ func TestInternalInit(t *testing.T) { // delete the default path dbPath := filepath.Join(fs.CacheDir, "cache-backend", *RemoteName+".db") - boltDb = cache.GetPersistent(dbPath, true) + boltDb, err = cache.GetPersistent(dbPath, true) + require.NoError(t, err) fstest.Initialise() if len(*WrapRemote) == 0 { diff --git a/cache/storage_persistent.go b/cache/storage_persistent.go index b6545986a..7e2c7cfe5 100644 --- a/cache/storage_persistent.go +++ b/cache/storage_persistent.go @@ -30,27 +30,23 @@ const ( ) var boltMap = make(map[string]*Persistent) -var boltMapMx sync.RWMutex +var boltMapMx sync.Mutex // GetPersistent returns a single instance for the specific store -func GetPersistent(dbPath string, refreshDb bool) *Persistent { - // read lock to check if it exists - boltMapMx.RLock() - if b, ok := boltMap[dbPath]; ok { - boltMapMx.RUnlock() - return b - } - boltMapMx.RUnlock() - - // write lock to create one but let's check a 2nd time +func GetPersistent(dbPath string, refreshDb bool) (*Persistent, error) { + // write lock to create one boltMapMx.Lock() defer boltMapMx.Unlock() if b, ok := boltMap[dbPath]; ok { - return b + return b, nil } - boltMap[dbPath] = newPersistent(dbPath, refreshDb) - return boltMap[dbPath] + bb, err := newPersistent(dbPath, refreshDb) + if err != nil { + return nil, err + } + boltMap[dbPath] = bb + return boltMap[dbPath], nil } // Persistent is a wrapper of persistent storage for a bolt.DB file @@ -64,7 +60,7 @@ type Persistent struct { } // newPersistent builds a new wrapper and connects to the bolt.DB file -func newPersistent(dbPath string, refreshDb bool) *Persistent { +func newPersistent(dbPath string, refreshDb bool) (*Persistent, error) { dataPath := strings.TrimSuffix(dbPath, filepath.Ext(dbPath)) b := &Persistent{ @@ -74,10 +70,11 @@ func newPersistent(dbPath string, refreshDb bool) *Persistent { err := b.Connect(refreshDb) if err != nil { - fs.Errorf(dbPath, "error opening storage cache: %v", err) + fs.Errorf(dbPath, "Error opening storage cache. Is there another rclone running on the same remote? %v", err) + return nil, err } - return b + return b, nil } // String will return a human friendly string for this DB (currently the dbPath)