1
0
Эх сурвалжийг харах

lib/db: Reinstate database update locking

The previous commit loosened the locking around database updates.
Apparently that was not fine - what happens is that parallell updates
to the same file for different devices stomp on each others updates to
the global index, leaving it missing one of the two devices.
Jakob Borg 9 жил өмнө
parent
commit
694da60659
1 өөрчлөгдсөн 12 нэмэгдсэн , 8 устгасан
  1. 12 8
      lib/db/set.go

+ 12 - 8
lib/db/set.go

@@ -30,7 +30,7 @@ type FileSet struct {
 	globalSize   sizeTracker
 
 	remoteLocalVersion map[protocol.DeviceID]int64 // Highest seen local versions for other devices
-	rlvMutex           sync.Mutex                  // protects remoteLocalVersion
+	updateMutex        sync.Mutex                  // protects remoteLocalVersion and database updates
 }
 
 // FileIntf is the set of methods implemented by both protocol.FileInfo and
@@ -102,7 +102,7 @@ func NewFileSet(folder string, db *Instance) *FileSet {
 		folder:             folder,
 		db:                 db,
 		blockmap:           NewBlockMap(db, db.folderIdx.ID([]byte(folder))),
-		rlvMutex:           sync.NewMutex(),
+		updateMutex:        sync.NewMutex(),
 	}
 
 	s.db.checkGlobals([]byte(folder), &s.globalSize)
@@ -128,6 +128,10 @@ func NewFileSet(folder string, db *Instance) *FileSet {
 func (s *FileSet) Replace(device protocol.DeviceID, fs []protocol.FileInfo) {
 	l.Debugf("%s Replace(%v, [%d])", s.folder, device, len(fs))
 	normalizeFilenames(fs)
+
+	s.updateMutex.Lock()
+	defer s.updateMutex.Unlock()
+
 	if device == protocol.LocalDeviceID {
 		if len(fs) == 0 {
 			s.localVersion = 0
@@ -140,9 +144,7 @@ func (s *FileSet) Replace(device protocol.DeviceID, fs []protocol.FileInfo) {
 			}
 		}
 	} else {
-		s.rlvMutex.Lock()
 		s.remoteLocalVersion[device] = maxLocalVersion(fs)
-		s.rlvMutex.Unlock()
 	}
 	s.db.replace([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
 	if device == protocol.LocalDeviceID {
@@ -154,6 +156,10 @@ func (s *FileSet) Replace(device protocol.DeviceID, fs []protocol.FileInfo) {
 func (s *FileSet) Update(device protocol.DeviceID, fs []protocol.FileInfo) {
 	l.Debugf("%s Update(%v, [%d])", s.folder, device, len(fs))
 	normalizeFilenames(fs)
+
+	s.updateMutex.Lock()
+	defer s.updateMutex.Unlock()
+
 	if device == protocol.LocalDeviceID {
 		discards := make([]protocol.FileInfo, 0, len(fs))
 		updates := make([]protocol.FileInfo, 0, len(fs))
@@ -168,9 +174,7 @@ func (s *FileSet) Update(device protocol.DeviceID, fs []protocol.FileInfo) {
 		s.blockmap.Discard(discards)
 		s.blockmap.Update(updates)
 	} else {
-		s.rlvMutex.Lock()
 		s.remoteLocalVersion[device] = maxLocalVersion(fs)
-		s.rlvMutex.Unlock()
 	}
 	s.db.updateFiles([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
 }
@@ -249,8 +253,8 @@ func (s *FileSet) LocalVersion(device protocol.DeviceID) int64 {
 		return atomic.LoadInt64(&s.localVersion)
 	}
 
-	s.rlvMutex.Lock()
-	defer s.rlvMutex.Unlock()
+	s.updateMutex.Lock()
+	defer s.updateMutex.Unlock()
 	return s.remoteLocalVersion[device]
 }