package dht 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() }