瀏覽代碼

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
 	globalSize   sizeTracker
 
 
 	remoteLocalVersion map[protocol.DeviceID]int64 // Highest seen local versions for other devices
 	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
 // 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,
 		folder:             folder,
 		db:                 db,
 		db:                 db,
 		blockmap:           NewBlockMap(db, db.folderIdx.ID([]byte(folder))),
 		blockmap:           NewBlockMap(db, db.folderIdx.ID([]byte(folder))),
-		rlvMutex:           sync.NewMutex(),
+		updateMutex:        sync.NewMutex(),
 	}
 	}
 
 
 	s.db.checkGlobals([]byte(folder), &s.globalSize)
 	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) {
 func (s *FileSet) Replace(device protocol.DeviceID, fs []protocol.FileInfo) {
 	l.Debugf("%s Replace(%v, [%d])", s.folder, device, len(fs))
 	l.Debugf("%s Replace(%v, [%d])", s.folder, device, len(fs))
 	normalizeFilenames(fs)
 	normalizeFilenames(fs)
+
+	s.updateMutex.Lock()
+	defer s.updateMutex.Unlock()
+
 	if device == protocol.LocalDeviceID {
 	if device == protocol.LocalDeviceID {
 		if len(fs) == 0 {
 		if len(fs) == 0 {
 			s.localVersion = 0
 			s.localVersion = 0
@@ -140,9 +144,7 @@ func (s *FileSet) Replace(device protocol.DeviceID, fs []protocol.FileInfo) {
 			}
 			}
 		}
 		}
 	} else {
 	} else {
-		s.rlvMutex.Lock()
 		s.remoteLocalVersion[device] = maxLocalVersion(fs)
 		s.remoteLocalVersion[device] = maxLocalVersion(fs)
-		s.rlvMutex.Unlock()
 	}
 	}
 	s.db.replace([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
 	s.db.replace([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
 	if device == protocol.LocalDeviceID {
 	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) {
 func (s *FileSet) Update(device protocol.DeviceID, fs []protocol.FileInfo) {
 	l.Debugf("%s Update(%v, [%d])", s.folder, device, len(fs))
 	l.Debugf("%s Update(%v, [%d])", s.folder, device, len(fs))
 	normalizeFilenames(fs)
 	normalizeFilenames(fs)
+
+	s.updateMutex.Lock()
+	defer s.updateMutex.Unlock()
+
 	if device == protocol.LocalDeviceID {
 	if device == protocol.LocalDeviceID {
 		discards := make([]protocol.FileInfo, 0, len(fs))
 		discards := make([]protocol.FileInfo, 0, len(fs))
 		updates := 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.Discard(discards)
 		s.blockmap.Update(updates)
 		s.blockmap.Update(updates)
 	} else {
 	} else {
-		s.rlvMutex.Lock()
 		s.remoteLocalVersion[device] = maxLocalVersion(fs)
 		s.remoteLocalVersion[device] = maxLocalVersion(fs)
-		s.rlvMutex.Unlock()
 	}
 	}
 	s.db.updateFiles([]byte(s.folder), device[:], fs, &s.localSize, &s.globalSize)
 	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)
 		return atomic.LoadInt64(&s.localVersion)
 	}
 	}
 
 
-	s.rlvMutex.Lock()
-	defer s.rlvMutex.Unlock()
+	s.updateMutex.Lock()
+	defer s.updateMutex.Unlock()
 	return s.remoteLocalVersion[device]
 	return s.remoteLocalVersion[device]
 }
 }