mirror of
https://github.com/octoleo/syncthing.git
synced 2025-01-22 22:58:25 +00:00
Clear availability for disconnected node
This commit is contained in:
parent
ba0e4ded65
commit
8d5aed410f
@ -192,6 +192,15 @@ func (q *FileQueue) deleteAt(i int) {
|
|||||||
q.files = q.files[:i+copy(q.files[i:], q.files[i+1:])]
|
q.files = q.files[:i+copy(q.files[i:], q.files[i+1:])]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *FileQueue) deleteFile(n string) {
|
||||||
|
for i, file := range q.files {
|
||||||
|
if n == file.name {
|
||||||
|
q.deleteAt(i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (q *FileQueue) SetAvailable(file, node string) {
|
func (q *FileQueue) SetAvailable(file, node string) {
|
||||||
q.lock.Lock()
|
q.lock.Lock()
|
||||||
defer q.lock.Unlock()
|
defer q.lock.Unlock()
|
||||||
@ -209,3 +218,19 @@ func (q *FileQueue) AddAvailable(file, node string) {
|
|||||||
}
|
}
|
||||||
q.availability[file] = append(q.availability[file], node)
|
q.availability[file] = append(q.availability[file], node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *FileQueue) RemoveAvailable(toRemove string) {
|
||||||
|
q.lock.Lock()
|
||||||
|
defer q.lock.Unlock()
|
||||||
|
for file, nodes := range q.availability {
|
||||||
|
for i, node := range nodes {
|
||||||
|
if node == toRemove {
|
||||||
|
q.availability[file] = nodes[:i+copy(nodes[i:], nodes[i+1:])]
|
||||||
|
if len(q.availability[file]) == 0 {
|
||||||
|
q.deleteFile(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,30 +2,21 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeResolver struct{}
|
|
||||||
|
|
||||||
func (fakeResolver) WhoHas(n string) []string {
|
|
||||||
if strings.HasPrefix(n, "a-") {
|
|
||||||
return []string{"a", "nodeID"}
|
|
||||||
} else if strings.HasPrefix(n, "b-") {
|
|
||||||
return []string{"b", "nodeID"}
|
|
||||||
}
|
|
||||||
return []string{"a", "b", "nodeID"}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileQueueAdd(t *testing.T) {
|
func TestFileQueueAdd(t *testing.T) {
|
||||||
q := FileQueue{}
|
q := FileQueue{}
|
||||||
q.Add("foo", nil, nil)
|
q.Add("foo", nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFileQueueAddSorting(t *testing.T) {
|
func TestFileQueueAddSorting(t *testing.T) {
|
||||||
q := FileQueue{resolver: fakeResolver{}}
|
q := FileQueue{}
|
||||||
|
q.SetAvailable("zzz", "nodeID")
|
||||||
|
q.SetAvailable("aaa", "nodeID")
|
||||||
|
|
||||||
q.Add("zzz", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
|
q.Add("zzz", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
|
||||||
q.Add("aaa", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
|
q.Add("aaa", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
|
||||||
b, _ := q.Get("nodeID")
|
b, _ := q.Get("nodeID")
|
||||||
@ -33,7 +24,10 @@ func TestFileQueueAddSorting(t *testing.T) {
|
|||||||
t.Errorf("Incorrectly sorted get: %+v", b)
|
t.Errorf("Incorrectly sorted get: %+v", b)
|
||||||
}
|
}
|
||||||
|
|
||||||
q = FileQueue{resolver: fakeResolver{}}
|
q = FileQueue{}
|
||||||
|
q.SetAvailable("zzz", "nodeID")
|
||||||
|
q.SetAvailable("aaa", "nodeID")
|
||||||
|
|
||||||
q.Add("zzz", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
|
q.Add("zzz", []Block{{Offset: 0, Size: 128}, {Offset: 128, Size: 128}}, nil)
|
||||||
b, _ = q.Get("nodeID") // Start on zzzz
|
b, _ = q.Get("nodeID") // Start on zzzz
|
||||||
if b.name != "zzz" {
|
if b.name != "zzz" {
|
||||||
@ -58,7 +52,10 @@ func TestFileQueueLen(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFileQueueGet(t *testing.T) {
|
func TestFileQueueGet(t *testing.T) {
|
||||||
q := FileQueue{resolver: fakeResolver{}}
|
q := FileQueue{}
|
||||||
|
q.SetAvailable("foo", "nodeID")
|
||||||
|
q.SetAvailable("bar", "nodeID")
|
||||||
|
|
||||||
q.Add("foo", []Block{
|
q.Add("foo", []Block{
|
||||||
{Offset: 0, Size: 128, Hash: []byte("some foo hash bytes")},
|
{Offset: 0, Size: 128, Hash: []byte("some foo hash bytes")},
|
||||||
{Offset: 128, Size: 128, Hash: []byte("some other foo hash bytes")},
|
{Offset: 128, Size: 128, Hash: []byte("some other foo hash bytes")},
|
||||||
@ -180,7 +177,12 @@ func TestFileQueueDone(t *testing.T) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
func TestFileQueueGetNodeIDs(t *testing.T) {
|
func TestFileQueueGetNodeIDs(t *testing.T) {
|
||||||
q := FileQueue{resolver: fakeResolver{}}
|
q := FileQueue{}
|
||||||
|
q.SetAvailable("a-foo", "nodeID")
|
||||||
|
q.AddAvailable("a-foo", "a")
|
||||||
|
q.SetAvailable("b-bar", "nodeID")
|
||||||
|
q.AddAvailable("b-bar", "b")
|
||||||
|
|
||||||
q.Add("a-foo", []Block{
|
q.Add("a-foo", []Block{
|
||||||
{Offset: 0, Size: 128, Hash: []byte("some foo hash bytes")},
|
{Offset: 0, Size: 128, Hash: []byte("some foo hash bytes")},
|
||||||
{Offset: 128, Size: 128, Hash: []byte("some other foo hash bytes")},
|
{Offset: 128, Size: 128, Hash: []byte("some other foo hash bytes")},
|
||||||
@ -252,8 +254,9 @@ func TestFileQueueThreadHandling(t *testing.T) {
|
|||||||
total += i
|
total += i
|
||||||
}
|
}
|
||||||
|
|
||||||
q := FileQueue{resolver: fakeResolver{}}
|
q := FileQueue{}
|
||||||
q.Add("foo", blocks, nil)
|
q.Add("foo", blocks, nil)
|
||||||
|
q.SetAvailable("foo", "nodeID")
|
||||||
|
|
||||||
var start = make(chan bool)
|
var start = make(chan bool)
|
||||||
var gotTot uint32
|
var gotTot uint32
|
||||||
|
@ -315,6 +315,7 @@ func (m *Model) Close(node string, err error) {
|
|||||||
delete(m.remote, node)
|
delete(m.remote, node)
|
||||||
delete(m.protoConn, node)
|
delete(m.protoConn, node)
|
||||||
delete(m.rawConn, node)
|
delete(m.rawConn, node)
|
||||||
|
m.fq.RemoveAvailable(node)
|
||||||
|
|
||||||
m.recomputeGlobal()
|
m.recomputeGlobal()
|
||||||
m.recomputeNeed()
|
m.recomputeNeed()
|
||||||
|
@ -303,14 +303,21 @@ func TestForgetNode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
m.Index("42", []protocol.FileInfo{newFile})
|
m.Index("42", []protocol.FileInfo{newFile})
|
||||||
|
|
||||||
|
newFile = protocol.FileInfo{
|
||||||
|
Name: "new file 2",
|
||||||
|
Modified: time.Now().Unix(),
|
||||||
|
Blocks: []protocol.BlockInfo{{100, []byte("some hash bytes")}},
|
||||||
|
}
|
||||||
|
m.Index("43", []protocol.FileInfo{newFile})
|
||||||
|
|
||||||
if l1, l2 := len(m.local), len(fs); l1 != l2 {
|
if l1, l2 := len(m.local), len(fs); l1 != l2 {
|
||||||
t.Errorf("Model len(local) incorrect (%d != %d)", l1, l2)
|
t.Errorf("Model len(local) incorrect (%d != %d)", l1, l2)
|
||||||
}
|
}
|
||||||
if l1, l2 := len(m.global), len(fs)+1; l1 != l2 {
|
if l1, l2 := len(m.global), len(fs)+2; l1 != l2 {
|
||||||
t.Errorf("Model len(global) incorrect (%d != %d)", l1, l2)
|
t.Errorf("Model len(global) incorrect (%d != %d)", l1, l2)
|
||||||
}
|
}
|
||||||
if fs, _ := m.NeedFiles(); len(fs) != 1 {
|
if fs, _ := m.NeedFiles(); len(fs) != 2 {
|
||||||
t.Errorf("Model len(need) incorrect (%d != 1)", len(fs))
|
t.Errorf("Model len(need) incorrect (%d != 2)", len(fs))
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Close("42", nil)
|
m.Close("42", nil)
|
||||||
@ -318,21 +325,13 @@ func TestForgetNode(t *testing.T) {
|
|||||||
if l1, l2 := len(m.local), len(fs); l1 != l2 {
|
if l1, l2 := len(m.local), len(fs); l1 != l2 {
|
||||||
t.Errorf("Model len(local) incorrect (%d != %d)", l1, l2)
|
t.Errorf("Model len(local) incorrect (%d != %d)", l1, l2)
|
||||||
}
|
}
|
||||||
if l1, l2 := len(m.global), len(fs); l1 != l2 {
|
if l1, l2 := len(m.global), len(fs)+1; l1 != l2 {
|
||||||
t.Errorf("Model len(global) incorrect (%d != %d)", l1, l2)
|
t.Errorf("Model len(global) incorrect (%d != %d)", l1, l2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fs, _ := m.NeedFiles(); len(fs) != 1 {
|
if fs, _ := m.NeedFiles(); len(fs) != 1 {
|
||||||
t.Errorf("Model len(need) incorrect (%d != 1)", len(fs))
|
t.Errorf("Model len(need) incorrect (%d != 1)", len(fs))
|
||||||
}
|
}
|
||||||
// The file will be removed from the need list when we notice there are no nodes that can provide it
|
|
||||||
_, ok := m.fq.Get("42")
|
|
||||||
if ok {
|
|
||||||
t.Errorf("Unexpected successfull Get()")
|
|
||||||
}
|
|
||||||
if fs, _ := m.NeedFiles(); len(fs) != 0 {
|
|
||||||
t.Errorf("Model len(need) incorrect (%d != 0)", len(fs))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRequest(t *testing.T) {
|
func TestRequest(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user