util.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package model
  5. import (
  6. "fmt"
  7. "sync"
  8. "time"
  9. "github.com/calmh/syncthing/protocol"
  10. )
  11. func cmMap(cm protocol.ClusterConfigMessage) map[string]map[protocol.NodeID]uint32 {
  12. m := make(map[string]map[protocol.NodeID]uint32)
  13. for _, repo := range cm.Repositories {
  14. m[repo.ID] = make(map[protocol.NodeID]uint32)
  15. for _, node := range repo.Nodes {
  16. var id protocol.NodeID
  17. copy(id[:], node.ID)
  18. m[repo.ID][id] = node.Flags
  19. }
  20. }
  21. return m
  22. }
  23. type ClusterConfigMismatch error
  24. // compareClusterConfig returns nil for two equivalent configurations,
  25. // otherwise a descriptive error
  26. func compareClusterConfig(local, remote protocol.ClusterConfigMessage) error {
  27. lm := cmMap(local)
  28. rm := cmMap(remote)
  29. for repo, lnodes := range lm {
  30. _ = lnodes
  31. if rnodes, ok := rm[repo]; ok {
  32. for node, lflags := range lnodes {
  33. if rflags, ok := rnodes[node]; ok {
  34. if lflags&protocol.FlagShareBits != rflags&protocol.FlagShareBits {
  35. return ClusterConfigMismatch(fmt.Errorf("remote has different sharing flags for node %q in repository %q", node, repo))
  36. }
  37. }
  38. }
  39. }
  40. }
  41. return nil
  42. }
  43. func deadlockDetect(mut sync.Locker, timeout time.Duration) {
  44. go func() {
  45. for {
  46. time.Sleep(timeout / 4)
  47. ok := make(chan bool, 2)
  48. go func() {
  49. mut.Lock()
  50. mut.Unlock()
  51. ok <- true
  52. }()
  53. go func() {
  54. time.Sleep(timeout)
  55. ok <- false
  56. }()
  57. if r := <-ok; !r {
  58. panic("deadlock detected")
  59. }
  60. }
  61. }()
  62. }