centralized_server.go 1.64 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 13 14

	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
)

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

	Server
}

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

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

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

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

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

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

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

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

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

	return ret
}

74
func (rs *s) Client(p peer.PeerInfo) Client {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
75 76 77
	return rs.ClientWithDatastore(p, ds.NewMapDatastore())
}

78
func (rs *s) ClientWithDatastore(p peer.PeerInfo, datastore ds.Datastore) Client {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
79 80 81 82 83 84
	return &client{
		peer:      p,
		datastore: ds.NewMapDatastore(),
		server:    rs,
	}
}