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  }