centralized_server.go 1.95 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

Jeromy's avatar
Jeromy committed
8
	ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore"
Jeromy's avatar
Jeromy committed
9
	dssync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/ipfs/go-datastore/sync"
10
	key "github.com/ipfs/go-ipfs/blocks/key"
11
	"github.com/ipfs/go-ipfs/util/testutil"
Jeromy's avatar
Jeromy committed
12
	peer "gx/ipfs/QmUBogf4nUefBjmYjn6jfsfPJRkmDGSeMhNj4usRKq69f4/go-libp2p/p2p/peer"
Jeromy's avatar
Jeromy committed
13
	context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
14 15 16 17
)

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

	Server
}

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

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

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

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

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

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

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

58
	var ret []peer.PeerInfo
Brian Tiger Chow's avatar
Brian Tiger Chow committed
59
	records, ok := rs.providers[k]
Brian Tiger Chow's avatar
Brian Tiger Chow committed
60 61 62
	if !ok {
		return ret
	}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
63 64 65 66
	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
67 68 69 70 71 72 73 74 75 76
	}

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

	return ret
}

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

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