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  }