centralized_server.go 1.83 KB
Newer Older
Brian Tiger Chow's avatar
Brian Tiger Chow committed
1 2 3
package mockrouting

import (
4
	"context"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
5 6
	"math/rand"
	"sync"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
7
	"time"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
8

9 10 11 12 13 14
	cid "github.com/ipfs/go-cid"
	ds "github.com/ipfs/go-datastore"
	dssync "github.com/ipfs/go-datastore/sync"
	peer "github.com/libp2p/go-libp2p-peer"
	pstore "github.com/libp2p/go-libp2p-peerstore"
	"github.com/libp2p/go-testutil"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
15 16 17 18
)

// server is the mockrouting.Client's private interface to the routing server
type server interface {
19 20
	Announce(pstore.PeerInfo, *cid.Cid) error
	Providers(*cid.Cid) []pstore.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
21 22 23 24 25 26

	Server
}

// s is an implementation of the private server interface
type s struct {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
27
	delayConf DelayConfig
Brian Tiger Chow's avatar
Brian Tiger Chow committed
28 29

	lock      sync.RWMutex
30
	providers map[string]map[peer.ID]providerRecord
Brian Tiger Chow's avatar
Brian Tiger Chow committed
31 32
}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
33
type providerRecord struct {
Jeromy's avatar
Jeromy committed
34
	Peer    pstore.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
35 36
	Created time.Time
}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
37

38
func (rs *s) Announce(p pstore.PeerInfo, c *cid.Cid) error {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
39 40 41
	rs.lock.Lock()
	defer rs.lock.Unlock()

42 43
	k := c.KeyString()

Brian Tiger Chow's avatar
Brian Tiger Chow committed
44 45
	_, ok := rs.providers[k]
	if !ok {
46
		rs.providers[k] = make(map[peer.ID]providerRecord)
Brian Tiger Chow's avatar
Brian Tiger Chow committed
47
	}
48
	rs.providers[k][p.ID] = providerRecord{
Brian Tiger Chow's avatar
Brian Tiger Chow committed
49 50
		Created: time.Now(),
		Peer:    p,
Brian Tiger Chow's avatar
Brian Tiger Chow committed
51 52 53 54
	}
	return nil
}

55
func (rs *s) Providers(c *cid.Cid) []pstore.PeerInfo {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
56
	rs.delayConf.Query.Wait() // before locking
Brian Tiger Chow's avatar
Brian Tiger Chow committed
57 58 59

	rs.lock.RLock()
	defer rs.lock.RUnlock()
60
	k := c.KeyString()
Brian Tiger Chow's avatar
Brian Tiger Chow committed
61

Jeromy's avatar
Jeromy committed
62
	var ret []pstore.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
63
	records, ok := rs.providers[k]
Brian Tiger Chow's avatar
Brian Tiger Chow committed
64 65 66
	if !ok {
		return ret
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
67
	for _, r := range records {
68
		if time.Since(r.Created) > rs.delayConf.ValueVisibility.Get() {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
69 70
			ret = append(ret, r.Peer)
		}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
71 72 73 74 75 76 77 78 79 80
	}

	for i := range ret {
		j := rand.Intn(i + 1)
		ret[i], ret[j] = ret[j], ret[i]
	}

	return ret
}

81
func (rs *s) Client(p testutil.Identity) Client {
Jeromy's avatar
Jeromy committed
82
	return rs.ClientWithDatastore(context.Background(), p, dssync.MutexWrap(ds.NewMapDatastore()))
Brian Tiger Chow's avatar
Brian Tiger Chow committed
83 84
}

85
func (rs *s) ClientWithDatastore(_ context.Context, p testutil.Identity, datastore ds.Datastore) Client {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
86 87
	return &client{
		peer:      p,
88
		datastore: datastore,
Brian Tiger Chow's avatar
Brian Tiger Chow committed
89 90 91
		server:    rs,
	}
}