bucket.go 1.58 KB
Newer Older
1 2 3 4
package dht

import (
	"container/list"
5
	"sync"
6 7 8

	peer "github.com/jbenet/go-ipfs/peer"
)
Jeromy's avatar
Jeromy committed
9

10
// Bucket holds a list of peers.
11 12 13 14 15 16 17 18 19 20
type Bucket struct {
	lk   sync.RWMutex
	list *list.List
}

func NewBucket() *Bucket {
	b := new(Bucket)
	b.list = list.New()
	return b
}
21 22

func (b *Bucket) Find(id peer.ID) *list.Element {
23 24 25
	b.lk.RLock()
	defer b.lk.RUnlock()
	for e := b.list.Front(); e != nil; e = e.Next() {
26 27 28 29 30 31 32 33
		if e.Value.(*peer.Peer).ID.Equal(id) {
			return e
		}
	}
	return nil
}

func (b *Bucket) MoveToFront(e *list.Element) {
34 35 36
	b.lk.Lock()
	b.list.MoveToFront(e)
	b.lk.Unlock()
37 38 39
}

func (b *Bucket) PushFront(p *peer.Peer) {
40 41 42
	b.lk.Lock()
	b.list.PushFront(p)
	b.lk.Unlock()
43 44 45
}

func (b *Bucket) PopBack() *peer.Peer {
46 47 48 49
	b.lk.Lock()
	defer b.lk.Unlock()
	last := b.list.Back()
	b.list.Remove(last)
50 51 52 53
	return last.Value.(*peer.Peer)
}

func (b *Bucket) Len() int {
54 55 56
	b.lk.RLock()
	defer b.lk.RUnlock()
	return b.list.Len()
57 58 59 60 61 62
}

// 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 {
63 64 65
	b.lk.Lock()
	defer b.lk.Unlock()

66
	out := list.New()
67 68 69
	newbuck := NewBucket()
	newbuck.list = out
	e := b.list.Front()
70 71 72 73 74 75 76
	for e != nil {
		peer_id := ConvertPeerID(e.Value.(*peer.Peer).ID)
		peer_cpl := prefLen(peer_id, target)
		if peer_cpl > cpl {
			cur := e
			out.PushBack(e.Value)
			e = e.Next()
77
			b.list.Remove(cur)
78 79 80 81
			continue
		}
		e = e.Next()
	}
82
	return newbuck
83 84 85
}

func (b *Bucket) getIter() *list.Element {
86
	return b.list.Front()
87
}