浏览代码

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 年之前
父节点
当前提交
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]
 }