peerstore.go 1.43 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
package peer

import (
	"errors"
	"sync"

	u "github.com/jbenet/go-ipfs/util"

	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go"
)

// Peerstore provides a threadsafe collection for peers.
type Peerstore interface {
	Get(ID) (*Peer, error)
	Add(*Peer) error
	Remove(ID) error
	All() (*map[u.Key]*Peer, error)
}

type peerstore struct {
	sync.RWMutex
	peers ds.Datastore
}

// NewPeerstore creates a threadsafe collection of peers.
func NewPeerstore() Peerstore {
	return &peerstore{
		peers: ds.NewMapDatastore(),
	}
}

func (p *peerstore) Get(i ID) (*Peer, error) {
	p.RLock()
	defer p.RUnlock()

	val, err := p.peers.Get(ds.NewKey(string(i)))
	if err != nil {
		return nil, err
	}

	peer, ok := val.(*Peer)
	if !ok {
		return nil, errors.New("stored value was not a Peer")
	}
	return peer, nil
}

func (p *peerstore) Add(peer *Peer) error {
	p.Lock()
	defer p.Unlock()

	k := ds.NewKey(string(peer.ID))
	return p.peers.Put(k, peer)
}

func (p *peerstore) Remove(i ID) error {
	p.Lock()
	defer p.Unlock()

	k := ds.NewKey(string(i))
	return p.peers.Delete(k)
}

func (p *peerstore) All() (*map[u.Key]*Peer, error) {
	p.RLock()
	defer p.RUnlock()

	l, err := p.peers.KeyList()
	if err != nil {
		return nil, err
	}

	ps := &map[u.Key]*Peer{}
	for _, k := range l {
		val, err := p.peers.Get(k)
		if err != nil {
			continue
		}

		pval, ok := val.(*Peer)
		if ok {
			(*ps)[u.Key(k.String())] = pval
		}
	}
	return ps, nil
}