mirror of
https://github.com/ipfs/kubo.git
synced 2025-09-10 05:52:20 +08:00
88 lines
1.6 KiB
Go
88 lines
1.6 KiB
Go
package kbucket
|
|
|
|
import (
|
|
"container/list"
|
|
"sync"
|
|
|
|
peer "github.com/jbenet/go-ipfs/peer"
|
|
)
|
|
|
|
// Bucket holds a list of peers.
|
|
type Bucket struct {
|
|
lk sync.RWMutex
|
|
list *list.List
|
|
}
|
|
|
|
func newBucket() *Bucket {
|
|
b := new(Bucket)
|
|
b.list = list.New()
|
|
return b
|
|
}
|
|
|
|
func (b *Bucket) find(id peer.ID) *list.Element {
|
|
b.lk.RLock()
|
|
defer b.lk.RUnlock()
|
|
for e := b.list.Front(); e != nil; e = e.Next() {
|
|
if e.Value.(peer.Peer).ID().Equal(id) {
|
|
return e
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *Bucket) moveToFront(e *list.Element) {
|
|
b.lk.Lock()
|
|
b.list.MoveToFront(e)
|
|
b.lk.Unlock()
|
|
}
|
|
|
|
func (b *Bucket) pushFront(p peer.Peer) {
|
|
b.lk.Lock()
|
|
b.list.PushFront(p)
|
|
b.lk.Unlock()
|
|
}
|
|
|
|
func (b *Bucket) popBack() peer.Peer {
|
|
b.lk.Lock()
|
|
defer b.lk.Unlock()
|
|
last := b.list.Back()
|
|
b.list.Remove(last)
|
|
return last.Value.(peer.Peer)
|
|
}
|
|
|
|
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 ID) *Bucket {
|
|
b.lk.Lock()
|
|
defer b.lk.Unlock()
|
|
|
|
out := list.New()
|
|
newbuck := newBucket()
|
|
newbuck.list = out
|
|
e := b.list.Front()
|
|
for e != nil {
|
|
peerID := ConvertPeerID(e.Value.(peer.Peer).ID())
|
|
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
|
|
}
|
|
|
|
func (b *Bucket) getIter() *list.Element {
|
|
return b.list.Front()
|
|
}
|