| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- // Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
- // Use of this source code is governed by an MIT-style license that can be
- // found in the LICENSE file.
- package model
- import (
- "fmt"
- "path/filepath"
- "sync"
- "time"
- "github.com/calmh/syncthing/protocol"
- "github.com/calmh/syncthing/scanner"
- )
- func fileFromFileInfo(f protocol.FileInfo) scanner.File {
- var blocks = make([]scanner.Block, len(f.Blocks))
- var offset int64
- for i, b := range f.Blocks {
- blocks[i] = scanner.Block{
- Offset: offset,
- Size: b.Size,
- Hash: b.Hash,
- }
- offset += int64(b.Size)
- }
- return scanner.File{
- // Name is with native separator and normalization
- Name: filepath.FromSlash(f.Name),
- Size: offset,
- Flags: f.Flags &^ protocol.FlagInvalid,
- Modified: f.Modified,
- Version: f.Version,
- Blocks: blocks,
- Suppressed: f.Flags&protocol.FlagInvalid != 0,
- }
- }
- func fileInfoFromFile(f scanner.File) protocol.FileInfo {
- var blocks = make([]protocol.BlockInfo, len(f.Blocks))
- for i, b := range f.Blocks {
- blocks[i] = protocol.BlockInfo{
- Size: b.Size,
- Hash: b.Hash,
- }
- }
- pf := protocol.FileInfo{
- Name: filepath.ToSlash(f.Name),
- Flags: f.Flags,
- Modified: f.Modified,
- Version: f.Version,
- Blocks: blocks,
- }
- if f.Suppressed {
- pf.Flags |= protocol.FlagInvalid
- }
- return pf
- }
- func cmMap(cm protocol.ClusterConfigMessage) map[string]map[protocol.NodeID]uint32 {
- m := make(map[string]map[protocol.NodeID]uint32)
- for _, repo := range cm.Repositories {
- m[repo.ID] = make(map[protocol.NodeID]uint32)
- for _, node := range repo.Nodes {
- var id protocol.NodeID
- copy(id[:], node.ID)
- m[repo.ID][id] = node.Flags
- }
- }
- return m
- }
- type ClusterConfigMismatch error
- // compareClusterConfig returns nil for two equivalent configurations,
- // otherwise a descriptive error
- 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
- }
- 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")
- }
- }
- }()
- }
|