mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 03:18:59 +00:00
8f3effed32
New node ID:s contain four Luhn check digits and are grouped differently. Code uses NodeID type instead of string, so it's formatted homogenously everywhere.
121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
// 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")
|
|
}
|
|
}
|
|
}()
|
|
}
|