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

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

8 9 10 11 12
	ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
	peer "github.com/ipfs/go-ipfs/p2p/peer"
	u "github.com/ipfs/go-ipfs/util"
	"github.com/ipfs/go-ipfs/util/testutil"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
13 14 15 16
)

// server is the mockrouting.Client's private interface to the routing server
type server interface {
17 18
	Announce(peer.PeerInfo, u.Key) error
	Providers(u.Key) []peer.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
19 20 21 22 23 24

	Server
}

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

	lock      sync.RWMutex
28
	providers map[u.Key]map[peer.ID]providerRecord
Brian Tiger Chow's avatar
Brian Tiger Chow committed
29 30
}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
31
type providerRecord struct {
32
	Peer    peer.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
33 34
	Created time.Time
}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
35

36
func (rs *s) Announce(p peer.PeerInfo, k u.Key) error {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
37 38 39 40 41
	rs.lock.Lock()
	defer rs.lock.Unlock()

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

51
func (rs *s) Providers(k u.Key) []peer.PeerInfo {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
52
	rs.delayConf.Query.Wait() // before locking
Brian Tiger Chow's avatar
Brian Tiger Chow committed
53 54 55 56

	rs.lock.RLock()
	defer rs.lock.RUnlock()

57
	var ret []peer.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
58
	records, ok := rs.providers[k]
Brian Tiger Chow's avatar
Brian Tiger Chow committed
59 60 61
	if !ok {
		return ret
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
62 63 64 65
	for _, r := range records {
		if time.Now().Sub(r.Created) > rs.delayConf.ValueVisibility.Get() {
			ret = append(ret, r.Peer)
		}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
66 67 68 69 70 71 72 73 74 75
	}

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

	return ret
}

76
func (rs *s) Client(p testutil.Identity) Client {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
77
	return rs.ClientWithDatastore(context.Background(), p, ds.NewMapDatastore())
Brian Tiger Chow's avatar
Brian Tiger Chow committed
78 79
}

80
func (rs *s) ClientWithDatastore(_ context.Context, p testutil.Identity, datastore ds.Datastore) Client {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
81 82 83 84 85 86
	return &client{
		peer:      p,
		datastore: ds.NewMapDatastore(),
		server:    rs,
	}
}