github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/peer/peerstore.go (about)

     1  package peer
     2  
     3  import (
     4  	"errors"
     5  	"sync"
     6  
     7  	u "github.com/jbenet/go-ipfs/util"
     8  
     9  	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
    10  )
    11  
    12  // Peerstore provides a threadsafe collection for peers.
    13  type Peerstore interface {
    14  	Get(ID) (Peer, error)
    15  	Add(Peer) (Peer, error)
    16  	Delete(ID) error
    17  	All() (*Map, error)
    18  }
    19  
    20  type peerstore struct {
    21  	sync.RWMutex
    22  	peers ds.Datastore
    23  }
    24  
    25  // NewPeerstore creates a threadsafe collection of peers.
    26  func NewPeerstore() Peerstore {
    27  	return &peerstore{
    28  		peers: ds.NewMapDatastore(),
    29  	}
    30  }
    31  
    32  func (p *peerstore) Get(i ID) (Peer, error) {
    33  	p.Lock()
    34  	defer p.Unlock()
    35  
    36  	if i == nil {
    37  		panic("wat")
    38  	}
    39  
    40  	k := u.Key(i).DsKey()
    41  	val, err := p.peers.Get(k)
    42  	switch err {
    43  
    44  	// some other datastore error
    45  	default:
    46  		return nil, err
    47  
    48  	// not found, construct it ourselves, add it to datastore, and return.
    49  	case ds.ErrNotFound:
    50  		peer := &peer{id: i}
    51  		if err := p.peers.Put(k, peer); err != nil {
    52  			return nil, err
    53  		}
    54  		return peer, nil
    55  
    56  	// no error, got it back fine
    57  	case nil:
    58  		peer, ok := val.(*peer)
    59  		if !ok {
    60  			return nil, errors.New("stored value was not a Peer")
    61  		}
    62  		return peer, nil
    63  	}
    64  }
    65  
    66  func (p *peerstore) Add(peer Peer) (Peer, error) {
    67  	p.Lock()
    68  	defer p.Unlock()
    69  
    70  	k := peer.Key().DsKey()
    71  	val, err := p.peers.Get(k)
    72  	switch err {
    73  	// some other datastore error
    74  	default:
    75  		return nil, err
    76  
    77  	// not found? just add and return.
    78  	case ds.ErrNotFound:
    79  		err := p.peers.Put(k, peer)
    80  		return peer, err
    81  
    82  	// no error, already here.
    83  	case nil:
    84  		peer2, ok := val.(Peer)
    85  		if !ok {
    86  			return nil, errors.New("stored value was not a Peer")
    87  		}
    88  
    89  		if peer == peer2 {
    90  			return peer, nil
    91  		}
    92  
    93  		// must do some merging.
    94  		peer2.Update(peer)
    95  		return peer2, nil
    96  	}
    97  }
    98  
    99  func (p *peerstore) Delete(i ID) error {
   100  	p.Lock()
   101  	defer p.Unlock()
   102  
   103  	k := u.Key(i).DsKey()
   104  	return p.peers.Delete(k)
   105  }
   106  
   107  func (p *peerstore) All() (*Map, error) {
   108  	p.RLock()
   109  	defer p.RUnlock()
   110  
   111  	l, err := p.peers.KeyList()
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	ps := &Map{}
   117  	for _, k := range l {
   118  		val, err := p.peers.Get(k)
   119  		if err != nil {
   120  			continue
   121  		}
   122  
   123  		pval, ok := val.(*peer)
   124  		if ok {
   125  			(*ps)[pval.Key()] = pval
   126  		}
   127  	}
   128  	return ps, nil
   129  }