Don't deadlock while sending and receiving large indexes

This commit is contained in:
Jakob Borg 2014-05-20 18:41:01 +02:00
parent 1aef03288a
commit 95f5e5fa9a
2 changed files with 19 additions and 9 deletions

View File

@ -215,6 +215,7 @@ func main() {
if profiler := os.Getenv("STPROFILER"); len(profiler) > 0 {
go func() {
l.Debugln("Starting profiler on", profiler)
runtime.SetBlockProfileRate(1)
err := http.ListenAndServe(profiler, nil)
if err != nil {
l.Fatalln(err)

View File

@ -47,10 +47,12 @@ type Model struct {
repoFiles map[string]*files.Set // repo -> files
repoNodes map[string][]string // repo -> nodeIDs
nodeRepos map[string][]string // nodeID -> repos
repoState map[string]repoState // repo -> state
suppressor map[string]*suppressor // repo -> suppressor
rmut sync.RWMutex // protects the above
repoState map[string]repoState // repo -> state
smut sync.RWMutex
cm *cid.Map
protoConn map[string]protocol.Connection
@ -537,7 +539,10 @@ func (m *Model) broadcastIndexLoop() {
m.pmut.RLock()
m.rmut.RLock()
var indexWg sync.WaitGroup
for repo, fs := range m.repoFiles {
repo := repo
c := fs.Changes(cid.LocalID)
if c == lastChange[repo] {
continue
@ -545,10 +550,14 @@ func (m *Model) broadcastIndexLoop() {
lastChange[repo] = c
idx := m.protocolIndex(repo)
m.saveIndex(repo, m.indexDir, idx)
indexWg.Add(1)
go func() {
m.saveIndex(repo, m.indexDir, idx)
indexWg.Done()
}()
var indexWg sync.WaitGroup
for _, nodeID := range m.repoNodes[repo] {
nodeID := nodeID
if conn, ok := m.protoConn[nodeID]; ok {
indexWg.Add(1)
if debug {
@ -560,12 +569,12 @@ func (m *Model) broadcastIndexLoop() {
}()
}
}
indexWg.Wait()
}
m.rmut.RUnlock()
m.pmut.RUnlock()
indexWg.Wait()
}
}
@ -749,15 +758,15 @@ func (m *Model) clusterConfig(node string) protocol.ClusterConfigMessage {
}
func (m *Model) setState(repo string, state repoState) {
m.rmut.Lock()
m.smut.Lock()
m.repoState[repo] = state
m.rmut.Unlock()
m.smut.Unlock()
}
func (m *Model) State(repo string) string {
m.rmut.RLock()
m.smut.RLock()
state := m.repoState[repo]
m.rmut.RUnlock()
m.smut.RUnlock()
switch state {
case RepoIdle:
return "idle"