From 52c2781548c208090cc51c15f01e0942fe6c8972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Thu, 30 Jul 2020 08:49:03 +0200 Subject: [PATCH] Add write mutexes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- changelog/unreleased/add-write-mutexes.md | 5 +++++ pkg/service/v0/accounts.go | 6 ++++++ pkg/service/v0/groups.go | 6 ++++++ 3 files changed, 17 insertions(+) create mode 100644 changelog/unreleased/add-write-mutexes.md diff --git a/changelog/unreleased/add-write-mutexes.md b/changelog/unreleased/add-write-mutexes.md new file mode 100644 index 000000000..ec16003a1 --- /dev/null +++ b/changelog/unreleased/add-write-mutexes.md @@ -0,0 +1,5 @@ +Bugfix: Add write mutexes + +Concurrent account or groups writes would corrupt the json file on disk, because the different goroutines would be treated as a single thread from the os. We introduce a mutex for account and group file writes each. This locks the update frequency for all accounts/groups and could be further improved by using a concurrent map of mutexes with a mutex per account / group. PR welcome. + +https://github.com/owncloud/ocis-accounts/pull/71 \ No newline at end of file diff --git a/pkg/service/v0/accounts.go b/pkg/service/v0/accounts.go index a72179451..6a3e8ec2c 100644 --- a/pkg/service/v0/accounts.go +++ b/pkg/service/v0/accounts.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "regexp" + "sync" "time" fieldmask_utils "github.com/mennanov/fieldmask-utils" @@ -84,6 +85,8 @@ func (s Service) loadAccount(id string, a *proto.Account) (err error) { return } +var accountMutex sync.Mutex + func (s Service) writeAccount(a *proto.Account) (err error) { // leave only the group id @@ -95,6 +98,9 @@ func (s Service) writeAccount(a *proto.Account) (err error) { } path := filepath.Join(s.Config.Server.AccountsDataPath, "accounts", a.Id) + + accountMutex.Lock() + defer accountMutex.Unlock() if err = ioutil.WriteFile(path, bytes, 0600); err != nil { return merrors.InternalServerError(s.id, "could not write account: %v", err.Error()) } diff --git a/pkg/service/v0/groups.go b/pkg/service/v0/groups.go index 666d8608d..150dc7d60 100644 --- a/pkg/service/v0/groups.go +++ b/pkg/service/v0/groups.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "sync" "github.com/CiscoM31/godata" "github.com/blevesearch/bleve" @@ -66,6 +67,8 @@ func (s Service) loadGroup(id string, g *proto.Group) (err error) { return } +var groupMutex sync.Mutex + func (s Service) writeGroup(g *proto.Group) (err error) { // leave only the member id @@ -77,6 +80,9 @@ func (s Service) writeGroup(g *proto.Group) (err error) { } path := filepath.Join(s.Config.Server.AccountsDataPath, "groups", g.Id) + + groupMutex.Lock() + defer groupMutex.Unlock() if err = ioutil.WriteFile(path, bytes, 0600); err != nil { return merrors.InternalServerError(s.id, "could not write group: %v", err.Error()) }