-
Notifications
You must be signed in to change notification settings - Fork 0
/
bucket.go
123 lines (110 loc) · 2.28 KB
/
bucket.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package kademlia
import (
"bytes"
"container/list"
"sync"
)
// Bucket holds a list of peers.
type Bucket struct {
lk sync.RWMutex
list *list.List
}
func newBucket() *Bucket {
return &Bucket{
list: list.New(),
}
}
func (b *Bucket) Nodes() []Node {
b.lk.RLock()
defer b.lk.RUnlock()
ps := make([]Node, 0, b.list.Len())
for e := b.list.Front(); e != nil; e = e.Next() {
node := e.Value.(Node)
ps = append(ps, node)
}
return ps
}
func (b *Bucket) Has(n Node) bool {
b.lk.RLock()
defer b.lk.RUnlock()
for e := b.list.Front(); e != nil; e = e.Next() {
if bytes.Equal(e.Value.(Node).HashedID, n.HashedID) {
return true
}
}
return false
}
func (b *Bucket) Remove(n Node) bool {
b.lk.Lock()
defer b.lk.Unlock()
for e := b.list.Front(); e != nil; e = e.Next() {
if bytes.Equal(e.Value.(Node).HashedID, n.HashedID) {
b.list.Remove(e)
return true
}
}
return false
}
func (b *Bucket) RemoveDeadNodes() {
var next *list.Element
for e := b.list.Front(); e != nil; e = next {
node := e.Value.(Node)
if !node.IsAlive() {
next = e.Next()
node.Conn.Close()
b.list.Remove(e)
} else {
next = e.Next()
}
}
}
func (b *Bucket) MoveToFront(n Node) {
b.lk.Lock()
defer b.lk.Unlock()
for e := b.list.Front(); e != nil; e = e.Next() {
if bytes.Equal(e.Value.(Node).HashedID, n.HashedID) {
b.list.MoveToFront(e)
}
}
}
func (b *Bucket) PushFront(n Node) {
b.lk.Lock()
defer b.lk.Unlock()
b.list.PushFront(n)
}
func (b *Bucket) PopBack() Node {
b.lk.Lock()
defer b.lk.Unlock()
last := b.list.Back()
b.list.Remove(last)
return last.Value.(Node)
}
func (b *Bucket) Len() int {
b.lk.RLock()
defer b.lk.RUnlock()
return b.list.Len()
}
// Split splits a buckets peers into two buckets, the methods receiver will have
// peers with CPL equal to cpl, the returned bucket will have peers with CPL
// greater than cpl (returned bucket has closer peers)
func (b *Bucket) Split(cpl int, target []byte) *Bucket {
b.lk.Lock()
defer b.lk.Unlock()
out := list.New()
newbuck := newBucket()
newbuck.list = out
e := b.list.Front()
for e != nil {
peerID := e.Value.(Node).HashedID
peerCPL := CommonPrefixLen(peerID, target)
if peerCPL > cpl {
cur := e
out.PushBack(e.Value)
e = e.Next()
b.list.Remove(cur)
continue
}
e = e.Next()
}
return newbuck
}