2014-07-12 22:45:33 +00:00
|
|
|
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
|
|
|
|
// All rights reserved. Use of this source code is governed by an MIT-style
|
|
|
|
// license that can be found in the LICENSE file.
|
2014-06-01 20:50:14 +00:00
|
|
|
|
2014-05-15 03:26:55 +00:00
|
|
|
package model
|
2014-03-02 22:58:14 +00:00
|
|
|
|
2014-03-28 13:36:57 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
2014-06-21 07:43:12 +00:00
|
|
|
"sync"
|
|
|
|
"time"
|
2014-04-13 13:28:26 +00:00
|
|
|
|
|
|
|
"github.com/calmh/syncthing/protocol"
|
2014-03-28 13:36:57 +00:00
|
|
|
)
|
2014-03-02 22:58:14 +00:00
|
|
|
|
2014-06-29 23:42:03 +00:00
|
|
|
func cmMap(cm protocol.ClusterConfigMessage) map[string]map[protocol.NodeID]uint32 {
|
|
|
|
m := make(map[string]map[protocol.NodeID]uint32)
|
2014-04-13 13:28:26 +00:00
|
|
|
for _, repo := range cm.Repositories {
|
2014-06-29 23:42:03 +00:00
|
|
|
m[repo.ID] = make(map[protocol.NodeID]uint32)
|
2014-04-13 13:28:26 +00:00
|
|
|
for _, node := range repo.Nodes {
|
2014-06-29 23:42:03 +00:00
|
|
|
var id protocol.NodeID
|
|
|
|
copy(id[:], node.ID)
|
|
|
|
m[repo.ID][id] = node.Flags
|
2014-04-13 13:28:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
type ClusterConfigMismatch error
|
|
|
|
|
|
|
|
// compareClusterConfig returns nil for two equivalent configurations,
|
2014-06-29 23:42:03 +00:00
|
|
|
// otherwise a descriptive error
|
2014-04-13 13:28:26 +00:00
|
|
|
func compareClusterConfig(local, remote protocol.ClusterConfigMessage) error {
|
|
|
|
lm := cmMap(local)
|
|
|
|
rm := cmMap(remote)
|
|
|
|
|
|
|
|
for repo, lnodes := range lm {
|
|
|
|
_ = lnodes
|
|
|
|
if rnodes, ok := rm[repo]; ok {
|
|
|
|
for node, lflags := range lnodes {
|
|
|
|
if rflags, ok := rnodes[node]; ok {
|
|
|
|
if lflags&protocol.FlagShareBits != rflags&protocol.FlagShareBits {
|
|
|
|
return ClusterConfigMismatch(fmt.Errorf("remote has different sharing flags for node %q in repository %q", node, repo))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2014-06-21 07:43:12 +00:00
|
|
|
|
|
|
|
func deadlockDetect(mut sync.Locker, timeout time.Duration) {
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
time.Sleep(timeout / 4)
|
|
|
|
ok := make(chan bool, 2)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
mut.Lock()
|
|
|
|
mut.Unlock()
|
|
|
|
ok <- true
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
time.Sleep(timeout)
|
|
|
|
ok <- false
|
|
|
|
}()
|
|
|
|
|
|
|
|
if r := <-ok; !r {
|
|
|
|
panic("deadlock detected")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|