github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/routing/kbucket/bucket.go (about) 1 package kbucket 2 3 import ( 4 "container/list" 5 "sync" 6 7 peer "github.com/ipfs/go-ipfs/p2p/peer" 8 ) 9 10 // Bucket holds a list of peers. 11 type Bucket struct { 12 lk sync.RWMutex 13 list *list.List 14 } 15 16 func newBucket() *Bucket { 17 b := new(Bucket) 18 b.list = list.New() 19 return b 20 } 21 22 func (b *Bucket) Peers() []peer.ID { 23 b.lk.RLock() 24 defer b.lk.RUnlock() 25 ps := make([]peer.ID, 0, b.list.Len()) 26 for e := b.list.Front(); e != nil; e = e.Next() { 27 id := e.Value.(peer.ID) 28 ps = append(ps, id) 29 } 30 return ps 31 } 32 33 func (b *Bucket) Has(id peer.ID) bool { 34 b.lk.RLock() 35 defer b.lk.RUnlock() 36 for e := b.list.Front(); e != nil; e = e.Next() { 37 if e.Value.(peer.ID) == id { 38 return true 39 } 40 } 41 return false 42 } 43 44 func (b *Bucket) Remove(id peer.ID) { 45 b.lk.Lock() 46 defer b.lk.Unlock() 47 for e := b.list.Front(); e != nil; e = e.Next() { 48 if e.Value.(peer.ID) == id { 49 b.list.Remove(e) 50 } 51 } 52 } 53 54 func (b *Bucket) MoveToFront(id peer.ID) { 55 b.lk.Lock() 56 defer b.lk.Unlock() 57 for e := b.list.Front(); e != nil; e = e.Next() { 58 if e.Value.(peer.ID) == id { 59 b.list.MoveToFront(e) 60 } 61 } 62 } 63 64 func (b *Bucket) PushFront(p peer.ID) { 65 b.lk.Lock() 66 b.list.PushFront(p) 67 b.lk.Unlock() 68 } 69 70 func (b *Bucket) PopBack() peer.ID { 71 b.lk.Lock() 72 defer b.lk.Unlock() 73 last := b.list.Back() 74 b.list.Remove(last) 75 return last.Value.(peer.ID) 76 } 77 78 func (b *Bucket) Len() int { 79 b.lk.RLock() 80 defer b.lk.RUnlock() 81 return b.list.Len() 82 } 83 84 // Split splits a buckets peers into two buckets, the methods receiver will have 85 // peers with CPL equal to cpl, the returned bucket will have peers with CPL 86 // greater than cpl (returned bucket has closer peers) 87 func (b *Bucket) Split(cpl int, target ID) *Bucket { 88 b.lk.Lock() 89 defer b.lk.Unlock() 90 91 out := list.New() 92 newbuck := newBucket() 93 newbuck.list = out 94 e := b.list.Front() 95 for e != nil { 96 peerID := ConvertPeerID(e.Value.(peer.ID)) 97 peerCPL := commonPrefixLen(peerID, target) 98 if peerCPL > cpl { 99 cur := e 100 out.PushBack(e.Value) 101 e = e.Next() 102 b.list.Remove(cur) 103 continue 104 } 105 e = e.Next() 106 } 107 return newbuck 108 }