提交 1e007791 作者: Brian Tiger Chow

refactor(peer) impl peerstore with map

License: MIT
Signed-off-by: 's avatarBrian Tiger Chow <brian@perfmode.com>
上级 3f63e50c
package peer package peer
import ( import (
"errors"
"sync" "sync"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
) )
// Peerstore provides a threadsafe collection for peers. // Peerstore provides a threadsafe collection for peers.
...@@ -19,34 +16,26 @@ type Peerstore interface { ...@@ -19,34 +16,26 @@ type Peerstore interface {
type peerstore struct { type peerstore struct {
sync.RWMutex sync.RWMutex
peers ds.Datastore data map[string]Peer // key is string(ID)
} }
// NewPeerstore creates a threadsafe collection of peers. // NewPeerstore creates a threadsafe collection of peers.
func NewPeerstore() Peerstore { func NewPeerstore() Peerstore {
return &peerstore{ return &peerstore{
peers: ds.NewMapDatastore(), data: make(map[string]Peer),
} }
} }
func (p *peerstore) Get(i ID) (Peer, error) { func (ps *peerstore) Get(i ID) (Peer, error) {
p.Lock() ps.Lock()
defer p.Unlock() defer ps.Unlock()
if i == nil { if i == nil {
panic("wat") panic("wat")
} }
k := u.Key(i).DsKey() p, ok := ps.data[i.String()]
val, err := p.peers.Get(k) if !ok { // not found, construct it ourselves, add it to datastore, and return.
switch err {
// some other datastore error
default:
return nil, err
// not found, construct it ourselves, add it to datastore, and return.
case ds.ErrNotFound:
// TODO(brian) kinda dangerous, no? If ID is invalid and doesn't // TODO(brian) kinda dangerous, no? If ID is invalid and doesn't
// correspond to an actual valid peer ID, this peerstore will return an // correspond to an actual valid peer ID, this peerstore will return an
...@@ -57,84 +46,46 @@ func (p *peerstore) Get(i ID) (Peer, error) { ...@@ -57,84 +46,46 @@ func (p *peerstore) Get(i ID) (Peer, error) {
// //
// Potential bad case: Suppose values arrive from untrusted providers // Potential bad case: Suppose values arrive from untrusted providers
// in the DHT. // in the DHT.
p = &peer{id: i}
peer := &peer{id: i} ps.data[i.String()] = p
if err := p.peers.Put(k, peer); err != nil { }
return nil, err
}
return peer, nil
// no error, got it back fine // no error, got it back fine
case nil: return p, nil
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) (Peer, error) { func (p *peerstore) Add(peer Peer) (Peer, error) {
p.Lock() p.Lock()
defer p.Unlock() defer p.Unlock()
k := peer.Key().DsKey() existing, ok := p.data[peer.Key().String()]
val, err := p.peers.Get(k) if !ok { // not found? just add and return.
switch err { p.data[peer.Key().String()] = peer
// some other datastore error return peer, nil
default: }
return nil, err // already here.
if peer == existing {
// not found? just add and return. return peer, nil
case ds.ErrNotFound:
err := p.peers.Put(k, peer)
return peer, err
// no error, already here.
case nil:
peer2, ok := val.(Peer)
if !ok {
return nil, errors.New("stored value was not a Peer")
}
if peer == peer2 {
return peer, nil
}
// must do some merging.
peer2.Update(peer)
return peer2, nil
} }
existing.Update(peer) // must do some merging.
return existing, nil
} }
func (p *peerstore) Delete(i ID) error { func (p *peerstore) Delete(i ID) error {
p.Lock() p.Lock()
defer p.Unlock() defer p.Unlock()
k := u.Key(i).DsKey() delete(p.data, i.String())
return p.peers.Delete(k) return nil
} }
func (p *peerstore) All() (*Map, error) { func (p *peerstore) All() (*Map, error) {
p.RLock() p.Lock()
defer p.RUnlock() defer p.Unlock()
l, err := p.peers.KeyList()
if err != nil {
return nil, err
}
ps := &Map{} ps := Map{}
for _, k := range l { for k, v := range p.data {
val, err := p.peers.Get(k) ps[u.Key(k)] = v
if err != nil {
continue
}
pval, ok := val.(*peer)
if ok {
(*ps)[pval.Key()] = pval
}
} }
return ps, nil return &ps, nil
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论