lib/model: Use read-locks wherever possible (#6005)

This commit is contained in:
Simon Frei 2019-09-12 06:55:24 +02:00 committed by Jakob Borg
parent c0b3de2680
commit f7b2e79fdc

View File

@ -644,9 +644,11 @@ func (m *model) ConnectionStats() map[string]interface{} {
// DeviceStatistics returns statistics about each device // DeviceStatistics returns statistics about each device
func (m *model) DeviceStatistics() map[string]stats.DeviceStatistics { func (m *model) DeviceStatistics() map[string]stats.DeviceStatistics {
res := make(map[string]stats.DeviceStatistics) m.fmut.RLock()
for id := range m.cfg.Devices() { defer m.fmut.RUnlock()
res[id.String()] = m.deviceStatRef(id).GetStatistics() res := make(map[string]stats.DeviceStatistics, len(m.deviceStatRefs))
for id, sr := range m.deviceStatRefs {
res[id.String()] = sr.GetStatistics()
} }
return res return res
} }
@ -1449,14 +1451,14 @@ func (m *model) Closed(conn protocol.Connection, err error) {
func (m *model) closeConns(devs []protocol.DeviceID, err error) config.Waiter { func (m *model) closeConns(devs []protocol.DeviceID, err error) config.Waiter {
conns := make([]connections.Connection, 0, len(devs)) conns := make([]connections.Connection, 0, len(devs))
closed := make([]chan struct{}, 0, len(devs)) closed := make([]chan struct{}, 0, len(devs))
m.pmut.Lock() m.pmut.RLock()
for _, dev := range devs { for _, dev := range devs {
if conn, ok := m.conn[dev]; ok { if conn, ok := m.conn[dev]; ok {
conns = append(conns, conn) conns = append(conns, conn)
closed = append(closed, m.closed[dev]) closed = append(closed, m.closed[dev])
} }
} }
m.pmut.Unlock() m.pmut.RUnlock()
for _, conn := range conns { for _, conn := range conns {
conn.Close(err) conn.Close(err)
} }
@ -1906,21 +1908,13 @@ func (m *model) DownloadProgress(device protocol.DeviceID, folder string, update
}) })
} }
func (m *model) deviceStatRef(deviceID protocol.DeviceID) *stats.DeviceStatisticsReference {
m.fmut.Lock()
defer m.fmut.Unlock()
if sr, ok := m.deviceStatRefs[deviceID]; ok {
return sr
}
sr := stats.NewDeviceStatisticsReference(m.db, deviceID.String())
m.deviceStatRefs[deviceID] = sr
return sr
}
func (m *model) deviceWasSeen(deviceID protocol.DeviceID) { func (m *model) deviceWasSeen(deviceID protocol.DeviceID) {
m.deviceStatRef(deviceID).WasSeen() m.fmut.RLock()
sr, ok := m.deviceStatRefs[deviceID]
m.fmut.RUnlock()
if ok {
sr.WasSeen()
}
} }
type indexSender struct { type indexSender struct {
@ -2125,9 +2119,9 @@ func (m *model) ScanFolderSubdirs(folder string, subs []string) error {
} }
func (m *model) DelayScan(folder string, next time.Duration) { func (m *model) DelayScan(folder string, next time.Duration) {
m.fmut.Lock() m.fmut.RLock()
runner, ok := m.folderRunners[folder] runner, ok := m.folderRunners[folder]
m.fmut.Unlock() m.fmut.RUnlock()
if !ok { if !ok {
return return
} }
@ -2137,10 +2131,10 @@ func (m *model) DelayScan(folder string, next time.Duration) {
// numHashers returns the number of hasher routines to use for a given folder, // numHashers returns the number of hasher routines to use for a given folder,
// taking into account configuration and available CPU cores. // taking into account configuration and available CPU cores.
func (m *model) numHashers(folder string) int { func (m *model) numHashers(folder string) int {
m.fmut.Lock() m.fmut.RLock()
folderCfg := m.folderCfgs[folder] folderCfg := m.folderCfgs[folder]
numFolders := len(m.folderCfgs) numFolders := len(m.folderCfgs)
m.fmut.Unlock() m.fmut.RUnlock()
if folderCfg.Hashers > 0 { if folderCfg.Hashers > 0 {
// Specific value set in the config, use that. // Specific value set in the config, use that.
@ -2553,7 +2547,15 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
toDevices := to.DeviceMap() toDevices := to.DeviceMap()
for deviceID, toCfg := range toDevices { for deviceID, toCfg := range toDevices {
fromCfg, ok := fromDevices[deviceID] fromCfg, ok := fromDevices[deviceID]
if !ok || fromCfg.Paused == toCfg.Paused { if !ok {
sr := stats.NewDeviceStatisticsReference(m.db, deviceID.String())
m.fmut.Lock()
m.deviceStatRefs[deviceID] = sr
m.fmut.Unlock()
continue
}
delete(fromDevices, deviceID)
if fromCfg.Paused == toCfg.Paused {
continue continue
} }
@ -2570,6 +2572,11 @@ func (m *model) CommitConfiguration(from, to config.Configuration) bool {
m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()}) m.evLogger.Log(events.DeviceResumed, map[string]string{"device": deviceID.String()})
} }
} }
m.fmut.Lock()
for deviceID := range fromDevices {
delete(m.deviceStatRefs, deviceID)
}
m.fmut.Unlock()
scanLimiter.setCapacity(to.Options.MaxConcurrentScans) scanLimiter.setCapacity(to.Options.MaxConcurrentScans)