package mockrouting import ( "math/rand" "sync" "time" ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore" dssync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore/sync" key "github.com/ipfs/go-ipfs/blocks/key" "github.com/ipfs/go-ipfs/thirdparty/testutil" peer "gx/ipfs/QmUBogf4nUefBjmYjn6jfsfPJRkmDGSeMhNj4usRKq69f4/go-libp2p/p2p/peer" context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" ) // server is the mockrouting.Client's private interface to the routing server type server interface { Announce(peer.PeerInfo, key.Key) error Providers(key.Key) []peer.PeerInfo Server } // s is an implementation of the private server interface type s struct { delayConf DelayConfig lock sync.RWMutex providers map[key.Key]map[peer.ID]providerRecord } type providerRecord struct { Peer peer.PeerInfo Created time.Time } func (rs *s) Announce(p peer.PeerInfo, k key.Key) error { rs.lock.Lock() defer rs.lock.Unlock() _, ok := rs.providers[k] if !ok { rs.providers[k] = make(map[peer.ID]providerRecord) } rs.providers[k][p.ID] = providerRecord{ Created: time.Now(), Peer: p, } return nil } func (rs *s) Providers(k key.Key) []peer.PeerInfo { rs.delayConf.Query.Wait() // before locking rs.lock.RLock() defer rs.lock.RUnlock() var ret []peer.PeerInfo records, ok := rs.providers[k] if !ok { return ret } for _, r := range records { if time.Now().Sub(r.Created) > rs.delayConf.ValueVisibility.Get() { ret = append(ret, r.Peer) } } for i := range ret { j := rand.Intn(i + 1) ret[i], ret[j] = ret[j], ret[i] } return ret } func (rs *s) Client(p testutil.Identity) Client { return rs.ClientWithDatastore(context.Background(), p, dssync.MutexWrap(ds.NewMapDatastore())) } func (rs *s) ClientWithDatastore(_ context.Context, p testutil.Identity, datastore ds.Datastore) Client { return &client{ peer: p, datastore: datastore, server: rs, } }