mirror of
https://github.com/ipfs/kubo.git
synced 2025-09-10 22:49:13 +08:00
fix: routing mock accuracy
routing interface doesn't wait for value to appear in network, but value doesn't appear in network until time as passed License: MIT Signed-off-by: Brian Tiger Chow <brian@perfmode.com>
This commit is contained in:
@ -104,7 +104,10 @@ func AddCatBytes(data []byte, conf Config) error {
|
|||||||
|
|
||||||
sessionGenerator := bitswap.NewSessionGenerator(
|
sessionGenerator := bitswap.NewSessionGenerator(
|
||||||
tn.VirtualNetwork(delay.Fixed(conf.NetworkLatency)), // TODO rename VirtualNetwork
|
tn.VirtualNetwork(delay.Fixed(conf.NetworkLatency)), // TODO rename VirtualNetwork
|
||||||
mockrouting.NewServerWithDelay(delay.Fixed(conf.RoutingLatency)),
|
mockrouting.NewServerWithDelay(mockrouting.DelayConfig{
|
||||||
|
Query: delay.Fixed(conf.RoutingLatency),
|
||||||
|
ValueVisibility: delay.Fixed(conf.RoutingLatency),
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
defer sessionGenerator.Close()
|
defer sessionGenerator.Close()
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ func (c *client) FindProvidersAsync(ctx context.Context, k u.Key, max int) <-cha
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Provide returns once the message is on the network. Value is not necessarily
|
||||||
|
// visible yet.
|
||||||
func (c *client) Provide(_ context.Context, key u.Key) error {
|
func (c *client) Provide(_ context.Context, key u.Key) error {
|
||||||
return c.server.Announce(c.peer, key)
|
return c.server.Announce(c.peer, key)
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,25 @@ type Client interface {
|
|||||||
|
|
||||||
// NewServer returns a mockrouting Server
|
// NewServer returns a mockrouting Server
|
||||||
func NewServer() Server {
|
func NewServer() Server {
|
||||||
return NewServerWithDelay(delay.Fixed(0))
|
return NewServerWithDelay(DelayConfig{
|
||||||
|
ValueVisibility: delay.Fixed(0),
|
||||||
|
Query: delay.Fixed(0),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServerWithDelay returns a mockrouting Server with a delay!
|
// NewServerWithDelay returns a mockrouting Server with a delay!
|
||||||
func NewServerWithDelay(d delay.D) Server {
|
func NewServerWithDelay(conf DelayConfig) Server {
|
||||||
return &s{
|
return &s{
|
||||||
providers: make(map[u.Key]peer.Map),
|
providers: make(map[u.Key]map[u.Key]providerRecord),
|
||||||
delay: d,
|
delayConf: conf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DelayConfig struct {
|
||||||
|
// ValueVisibility is the time it takes for a value to be visible in the network
|
||||||
|
// FIXME there _must_ be a better term for this
|
||||||
|
ValueVisibility delay.D
|
||||||
|
|
||||||
|
// Query is the time it takes to receive a response from a routing query
|
||||||
|
Query delay.D
|
||||||
|
}
|
||||||
|
@ -3,10 +3,12 @@ package mockrouting
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
|
||||||
"github.com/jbenet/go-ipfs/peer"
|
peer "github.com/jbenet/go-ipfs/peer"
|
||||||
u "github.com/jbenet/go-ipfs/util"
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
|
delay "github.com/jbenet/go-ipfs/util/delay"
|
||||||
testutil "github.com/jbenet/go-ipfs/util/testutil"
|
testutil "github.com/jbenet/go-ipfs/util/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -129,3 +131,36 @@ func TestCanceledContext(t *testing.T) {
|
|||||||
t.Fatal("Context cancel had no effect")
|
t.Fatal("Context cancel had no effect")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidAfter(t *testing.T) {
|
||||||
|
|
||||||
|
var p = testutil.NewPeerWithID(peer.ID([]byte("the peer id")))
|
||||||
|
var key = u.Key("mock key")
|
||||||
|
var ctx = context.Background()
|
||||||
|
conf := DelayConfig{
|
||||||
|
ValueVisibility: delay.Fixed(1 * time.Hour),
|
||||||
|
Query: delay.Fixed(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
rs := NewServerWithDelay(conf)
|
||||||
|
|
||||||
|
rs.Client(p).Provide(ctx, key)
|
||||||
|
|
||||||
|
var providers []peer.Peer
|
||||||
|
providers, err := rs.Client(p).FindProviders(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(providers) > 0 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.ValueVisibility.Set(0)
|
||||||
|
providers, err = rs.Client(p).FindProviders(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(providers) != 1 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,11 +3,11 @@ package mockrouting
|
|||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
|
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
|
||||||
peer "github.com/jbenet/go-ipfs/peer"
|
peer "github.com/jbenet/go-ipfs/peer"
|
||||||
u "github.com/jbenet/go-ipfs/util"
|
u "github.com/jbenet/go-ipfs/util"
|
||||||
delay "github.com/jbenet/go-ipfs/util/delay"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// server is the mockrouting.Client's private interface to the routing server
|
// server is the mockrouting.Client's private interface to the routing server
|
||||||
@ -20,39 +20,47 @@ type server interface {
|
|||||||
|
|
||||||
// s is an implementation of the private server interface
|
// s is an implementation of the private server interface
|
||||||
type s struct {
|
type s struct {
|
||||||
delay delay.D
|
delayConf DelayConfig
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
providers map[u.Key]peer.Map
|
providers map[u.Key]map[u.Key]providerRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
type providerRecord struct {
|
||||||
|
Peer peer.Peer
|
||||||
|
Created time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *s) Announce(p peer.Peer, k u.Key) error {
|
func (rs *s) Announce(p peer.Peer, k u.Key) error {
|
||||||
rs.delay.Wait() // before locking
|
|
||||||
|
|
||||||
rs.lock.Lock()
|
rs.lock.Lock()
|
||||||
defer rs.lock.Unlock()
|
defer rs.lock.Unlock()
|
||||||
|
|
||||||
_, ok := rs.providers[k]
|
_, ok := rs.providers[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
rs.providers[k] = make(peer.Map)
|
rs.providers[k] = make(map[u.Key]providerRecord)
|
||||||
|
}
|
||||||
|
rs.providers[k][p.Key()] = providerRecord{
|
||||||
|
Created: time.Now(),
|
||||||
|
Peer: p,
|
||||||
}
|
}
|
||||||
rs.providers[k][p.Key()] = p
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *s) Providers(k u.Key) []peer.Peer {
|
func (rs *s) Providers(k u.Key) []peer.Peer {
|
||||||
rs.delay.Wait() // before locking
|
rs.delayConf.Query.Wait() // before locking
|
||||||
|
|
||||||
rs.lock.RLock()
|
rs.lock.RLock()
|
||||||
defer rs.lock.RUnlock()
|
defer rs.lock.RUnlock()
|
||||||
|
|
||||||
var ret []peer.Peer
|
var ret []peer.Peer
|
||||||
peerset, ok := rs.providers[k]
|
records, ok := rs.providers[k]
|
||||||
if !ok {
|
if !ok {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
for _, peer := range peerset {
|
for _, r := range records {
|
||||||
ret = append(ret, peer)
|
if time.Now().Sub(r.Created) > rs.delayConf.ValueVisibility.Get() {
|
||||||
|
ret = append(ret, r.Peer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range ret {
|
for i := range ret {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
type D interface {
|
type D interface {
|
||||||
Set(time.Duration) time.Duration
|
Set(time.Duration) time.Duration
|
||||||
Wait()
|
Wait()
|
||||||
|
Get() time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixed returns a delay with fixed latency
|
// Fixed returns a delay with fixed latency
|
||||||
@ -37,3 +38,9 @@ func (d *delay) Wait() {
|
|||||||
defer d.l.RUnlock()
|
defer d.l.RUnlock()
|
||||||
time.Sleep(d.t)
|
time.Sleep(d.t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *delay) Get() time.Duration {
|
||||||
|
d.l.Lock()
|
||||||
|
defer d.l.Unlock()
|
||||||
|
return d.t
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user