From 721cd740d84675e7aa87703ac0e37a258b21c753 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Sat, 11 Sep 2021 17:14:47 +0200 Subject: [PATCH] lib/model: Don't reset db while folder is running (fixes #7935) (#7936) --- lib/api/api.go | 10 ++++++++-- lib/model/mocks/model.go | 43 ++++++++++++++++++++++++++++++++++++---- lib/model/model.go | 11 ++++++++-- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/lib/api/api.go b/lib/api/api.go index 2d627ddb1..360e94212 100644 --- a/lib/api/api.go +++ b/lib/api/api.go @@ -1016,12 +1016,18 @@ func (s *service) postSystemReset(w http.ResponseWriter, r *http.Request) { if len(folder) == 0 { // Reset all folders. for folder := range s.cfg.Folders() { - s.model.ResetFolder(folder) + if err := s.model.ResetFolder(folder); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } } s.flushResponse(`{"ok": "resetting database"}`, w) } else { // Reset a specific folder, assuming it's supposed to exist. - s.model.ResetFolder(folder) + if err := s.model.ResetFolder(folder); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } s.flushResponse(`{"ok": "resetting folder `+folder+`"}`, w) } diff --git a/lib/model/mocks/model.go b/lib/model/mocks/model.go index 4b60f8a9e..db19252c7 100644 --- a/lib/model/mocks/model.go +++ b/lib/model/mocks/model.go @@ -468,11 +468,17 @@ type Model struct { result1 protocol.RequestResponse result2 error } - ResetFolderStub func(string) + ResetFolderStub func(string) error resetFolderMutex sync.RWMutex resetFolderArgsForCall []struct { arg1 string } + resetFolderReturns struct { + result1 error + } + resetFolderReturnsOnCall map[int]struct { + result1 error + } RestoreFolderVersionsStub func(string, map[string]time.Time) (map[string]error, error) restoreFolderVersionsMutex sync.RWMutex restoreFolderVersionsArgsForCall []struct { @@ -2737,17 +2743,23 @@ func (fake *Model) RequestReturnsOnCall(i int, result1 protocol.RequestResponse, }{result1, result2} } -func (fake *Model) ResetFolder(arg1 string) { +func (fake *Model) ResetFolder(arg1 string) error { fake.resetFolderMutex.Lock() + ret, specificReturn := fake.resetFolderReturnsOnCall[len(fake.resetFolderArgsForCall)] fake.resetFolderArgsForCall = append(fake.resetFolderArgsForCall, struct { arg1 string }{arg1}) stub := fake.ResetFolderStub + fakeReturns := fake.resetFolderReturns fake.recordInvocation("ResetFolder", []interface{}{arg1}) fake.resetFolderMutex.Unlock() if stub != nil { - fake.ResetFolderStub(arg1) + return stub(arg1) } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 } func (fake *Model) ResetFolderCallCount() int { @@ -2756,7 +2768,7 @@ func (fake *Model) ResetFolderCallCount() int { return len(fake.resetFolderArgsForCall) } -func (fake *Model) ResetFolderCalls(stub func(string)) { +func (fake *Model) ResetFolderCalls(stub func(string) error) { fake.resetFolderMutex.Lock() defer fake.resetFolderMutex.Unlock() fake.ResetFolderStub = stub @@ -2769,6 +2781,29 @@ func (fake *Model) ResetFolderArgsForCall(i int) string { return argsForCall.arg1 } +func (fake *Model) ResetFolderReturns(result1 error) { + fake.resetFolderMutex.Lock() + defer fake.resetFolderMutex.Unlock() + fake.ResetFolderStub = nil + fake.resetFolderReturns = struct { + result1 error + }{result1} +} + +func (fake *Model) ResetFolderReturnsOnCall(i int, result1 error) { + fake.resetFolderMutex.Lock() + defer fake.resetFolderMutex.Unlock() + fake.ResetFolderStub = nil + if fake.resetFolderReturnsOnCall == nil { + fake.resetFolderReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.resetFolderReturnsOnCall[i] = struct { + result1 error + }{result1} +} + func (fake *Model) RestoreFolderVersions(arg1 string, arg2 map[string]time.Time) (map[string]error, error) { fake.restoreFolderVersionsMutex.Lock() ret, specificReturn := fake.restoreFolderVersionsReturnsOnCall[len(fake.restoreFolderVersionsArgsForCall)] diff --git a/lib/model/model.go b/lib/model/model.go index 02bec7b92..2218bd802 100644 --- a/lib/model/model.go +++ b/lib/model/model.go @@ -72,7 +72,7 @@ type Model interface { connections.Model - ResetFolder(folder string) + ResetFolder(folder string) error DelayScan(folder string, next time.Duration) ScanFolder(folder string) error ScanFolders() map[string]error @@ -2764,9 +2764,16 @@ func (m *model) BringToFront(folder, file string) { } } -func (m *model) ResetFolder(folder string) { +func (m *model) ResetFolder(folder string) error { + m.fmut.RLock() + defer m.fmut.RUnlock() + _, ok := m.folderRunners[folder] + if ok { + return errors.New("folder must be paused when resetting") + } l.Infof("Cleaning metadata for reset folder %q", folder) db.DropFolder(m.db, folder) + return nil } func (m *model) String() string {