github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/routing/kbucket/bucket.go (about) 1 package kbucket 2 3 import ( 4 "container/list" 5 "sync" 6 7 peer "github.com/jbenet/go-ipfs/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) find(id peer.ID) *list.Element { 23 b.lk.RLock() 24 defer b.lk.RUnlock() 25 for e := b.list.Front(); e != nil; e = e.Next() { 26 if e.Value.(peer.Peer).ID().Equal(id) { 27 return e 28 } 29 } 30 return nil 31 } 32 33 func (b *Bucket) moveToFront(e *list.Element) { 34 b.lk.Lock() 35 b.list.MoveToFront(e) 36 b.lk.Unlock() 37 } 38 39 func (b *Bucket) pushFront(p peer.Peer) { 40 b.lk.Lock() 41 b.list.PushFront(p) 42 b.lk.Unlock() 43 } 44 45 func (b *Bucket) popBack() peer.Peer { 46 b.lk.Lock() 47 defer b.lk.Unlock() 48 last := b.list.Back() 49 b.list.Remove(last) 50 return last.Value.(peer.Peer) 51 } 52 53 func (b *Bucket) len() int { 54 b.lk.RLock() 55 defer b.lk.RUnlock() 56 return b.list.Len() 57 } 58 59 // Split splits a buckets peers into two buckets, the methods receiver will have 60 // peers with CPL equal to cpl, the returned bucket will have peers with CPL 61 // greater than cpl (returned bucket has closer peers) 62 func (b *Bucket) Split(cpl int, target ID) *Bucket { 63 b.lk.Lock() 64 defer b.lk.Unlock() 65 66 out := list.New() 67 newbuck := newBucket() 68 newbuck.list = out 69 e := b.list.Front() 70 for e != nil { 71 peerID := ConvertPeerID(e.Value.(peer.Peer).ID()) 72 peerCPL := commonPrefixLen(peerID, target) 73 if peerCPL > cpl { 74 cur := e 75 out.PushBack(e.Value) 76 e = e.Next() 77 b.list.Remove(cur) 78 continue 79 } 80 e = e.Next() 81 } 82 return newbuck 83 } 84 85 func (b *Bucket) getIter() *list.Element { 86 return b.list.Front() 87 }