Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-dms3
Commits
63f72a51
Commit
63f72a51
authored
Sep 02, 2015
by
Jeromy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove context from HasBlock, use bitswap process instead
License: MIT Signed-off-by:
Jeromy
<
jeromyj@gmail.com
>
parent
47b85c7b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
14 additions
and
399 deletions
+14
-399
blockservice/blockservice.go
blockservice/blockservice.go
+2
-2
blockservice/worker/bench/main.go
blockservice/worker/bench/main.go
+0
-91
blockservice/worker/bench_worker_test.go
blockservice/worker/bench_worker_test.go
+0
-42
blockservice/worker/worker.go
blockservice/worker/worker.go
+0
-184
blockservice/worker/worker_test.go
blockservice/worker/worker_test.go
+0
-63
exchange/bitswap/bitswap.go
exchange/bitswap/bitswap.go
+4
-6
exchange/bitswap/bitswap_test.go
exchange/bitswap/bitswap_test.go
+4
-7
exchange/interface.go
exchange/interface.go
+1
-1
exchange/offline/offline.go
exchange/offline/offline.go
+1
-1
exchange/offline/offline_test.go
exchange/offline/offline_test.go
+2
-2
No files found.
blockservice/blockservice.go
View file @
63f72a51
...
...
@@ -47,7 +47,7 @@ func (s *BlockService) AddBlock(b *blocks.Block) (key.Key, error) {
if
err
!=
nil
{
return
k
,
err
}
if
err
:=
s
.
Exchange
.
HasBlock
(
context
.
TODO
(),
b
);
err
!=
nil
{
if
err
:=
s
.
Exchange
.
HasBlock
(
b
);
err
!=
nil
{
return
""
,
errors
.
New
(
"blockservice is closed"
)
}
return
k
,
nil
...
...
@@ -61,7 +61,7 @@ func (s *BlockService) AddBlocks(bs []*blocks.Block) ([]key.Key, error) {
var
ks
[]
key
.
Key
for
_
,
b
:=
range
bs
{
if
err
:=
s
.
Exchange
.
HasBlock
(
context
.
TODO
(),
b
);
err
!=
nil
{
if
err
:=
s
.
Exchange
.
HasBlock
(
b
);
err
!=
nil
{
return
nil
,
errors
.
New
(
"blockservice is closed"
)
}
ks
=
append
(
ks
,
b
.
Key
())
...
...
blockservice/worker/bench/main.go
deleted
100644 → 0
View file @
47b85c7b
/*
Benchmark github.com/ipfs/go-ipfs/blockservice/worker.
Loop over a range of workers and buffer sizes and measure the time it
per block-transfer operation for each value. Run with:
$ go run "${GOPATH}/src/github.com/ipfs/go-ipfs/blockservice/worker/bench/main.go"
*/
package
main
import
(
"log"
"math"
"testing"
"time"
ds
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
ds_sync
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
blocks
"github.com/ipfs/go-ipfs/blocks"
blockstore
"github.com/ipfs/go-ipfs/blocks/blockstore"
worker
"github.com/ipfs/go-ipfs/blockservice/worker"
"github.com/ipfs/go-ipfs/exchange/offline"
"github.com/ipfs/go-ipfs/thirdparty/delay"
"github.com/ipfs/go-ipfs/util/datastore2"
)
const
kEstRoutingDelay
=
time
.
Second
const
kBlocksPerOp
=
100
func
main
()
{
var
bestConfig
worker
.
Config
var
quickestNsPerOp
int64
=
math
.
MaxInt64
for
NumWorkers
:=
1
;
NumWorkers
<
10
;
NumWorkers
++
{
for
ClientBufferSize
:=
0
;
ClientBufferSize
<
10
;
ClientBufferSize
++
{
for
WorkerBufferSize
:=
0
;
WorkerBufferSize
<
10
;
WorkerBufferSize
++
{
c
:=
worker
.
Config
{
NumWorkers
:
NumWorkers
,
ClientBufferSize
:
ClientBufferSize
,
WorkerBufferSize
:
WorkerBufferSize
,
}
result
:=
testing
.
Benchmark
(
BenchmarkWithConfig
(
c
))
if
result
.
NsPerOp
()
<
quickestNsPerOp
{
bestConfig
=
c
quickestNsPerOp
=
result
.
NsPerOp
()
}
log
.
Printf
(
"benched %+v
\t
result: %+v"
,
c
,
result
)
}
}
}
log
.
Println
(
bestConfig
)
}
func
BenchmarkWithConfig
(
c
worker
.
Config
)
func
(
b
*
testing
.
B
)
{
return
func
(
b
*
testing
.
B
)
{
routingDelay
:=
delay
.
Fixed
(
0
)
// during setup
dstore
:=
ds_sync
.
MutexWrap
(
datastore2
.
WithDelay
(
ds
.
NewMapDatastore
(),
routingDelay
))
bstore
:=
blockstore
.
NewBlockstore
(
dstore
)
var
testdata
[]
*
blocks
.
Block
var
i
int64
for
i
=
0
;
i
<
kBlocksPerOp
;
i
++
{
testdata
=
append
(
testdata
,
blocks
.
NewBlock
([]
byte
(
string
(
i
))))
}
b
.
ResetTimer
()
b
.
SetBytes
(
kBlocksPerOp
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
b
.
StopTimer
()
w
:=
worker
.
NewWorker
(
offline
.
Exchange
(
bstore
),
c
)
b
.
StartTimer
()
prev
:=
routingDelay
.
Set
(
kEstRoutingDelay
)
// during measured section
for
_
,
block
:=
range
testdata
{
if
err
:=
w
.
HasBlock
(
block
);
err
!=
nil
{
b
.
Fatal
(
err
)
}
}
routingDelay
.
Set
(
prev
)
// to hasten the unmeasured close period
b
.
StopTimer
()
w
.
Close
()
b
.
StartTimer
()
}
}
}
blockservice/worker/bench_worker_test.go
deleted
100644 → 0
View file @
47b85c7b
package
worker
import
(
"testing"
ds
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
dssync
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
blocks
"github.com/ipfs/go-ipfs/blocks"
blockstore
"github.com/ipfs/go-ipfs/blocks/blockstore"
"github.com/ipfs/go-ipfs/exchange/offline"
)
func
BenchmarkHandle10KBlocks
(
b
*
testing
.
B
)
{
bstore
:=
blockstore
.
NewBlockstore
(
dssync
.
MutexWrap
(
ds
.
NewMapDatastore
()))
var
testdata
[]
*
blocks
.
Block
for
i
:=
0
;
i
<
10000
;
i
++
{
testdata
=
append
(
testdata
,
blocks
.
NewBlock
([]
byte
(
string
(
i
))))
}
b
.
ResetTimer
()
b
.
SetBytes
(
10000
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
b
.
StopTimer
()
w
:=
NewWorker
(
offline
.
Exchange
(
bstore
),
Config
{
NumWorkers
:
1
,
ClientBufferSize
:
0
,
WorkerBufferSize
:
0
,
})
b
.
StartTimer
()
for
_
,
block
:=
range
testdata
{
if
err
:=
w
.
HasBlock
(
block
);
err
!=
nil
{
b
.
Fatal
(
err
)
}
}
b
.
StopTimer
()
w
.
Close
()
b
.
StartTimer
()
}
}
blockservice/worker/worker.go
deleted
100644 → 0
View file @
47b85c7b
// TODO FIXME name me
package
worker
import
(
"container/list"
"errors"
"time"
process
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
procctx
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
ratelimit
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/ratelimit"
blocks
"github.com/ipfs/go-ipfs/blocks"
key
"github.com/ipfs/go-ipfs/blocks/key"
exchange
"github.com/ipfs/go-ipfs/exchange"
logging
"github.com/ipfs/go-ipfs/vendor/go-log-v1.0.0"
)
var
log
=
logging
.
Logger
(
"blockservice"
)
var
DefaultConfig
=
Config
{
NumWorkers
:
1
,
ClientBufferSize
:
0
,
WorkerBufferSize
:
0
,
}
type
Config
struct
{
// NumWorkers sets the number of background workers that provide blocks to
// the exchange.
NumWorkers
int
// ClientBufferSize allows clients of HasBlock to send up to
// |ClientBufferSize| blocks without blocking.
ClientBufferSize
int
// WorkerBufferSize can be used in conjunction with NumWorkers to reduce
// communication-coordination within the worker.
WorkerBufferSize
int
}
// TODO FIXME name me
type
Worker
struct
{
// added accepts blocks from client
added
chan
*
blocks
.
Block
exchange
exchange
.
Interface
// workQueue is owned by the client worker
// process manages life-cycle
process
process
.
Process
}
func
NewWorker
(
e
exchange
.
Interface
,
c
Config
)
*
Worker
{
if
c
.
NumWorkers
<
1
{
c
.
NumWorkers
=
1
// provide a sane default
}
w
:=
&
Worker
{
exchange
:
e
,
added
:
make
(
chan
*
blocks
.
Block
,
c
.
ClientBufferSize
),
process
:
process
.
WithParent
(
process
.
Background
()),
// internal management
}
w
.
start
(
c
)
return
w
}
func
(
w
*
Worker
)
HasBlock
(
b
*
blocks
.
Block
)
error
{
select
{
case
<-
w
.
process
.
Closed
()
:
return
errors
.
New
(
"blockservice worker is closed"
)
case
w
.
added
<-
b
:
return
nil
}
}
func
(
w
*
Worker
)
Close
()
error
{
log
.
Debug
(
"blockservice provide worker is shutting down..."
)
return
w
.
process
.
Close
()
}
func
(
w
*
Worker
)
start
(
c
Config
)
{
workerChan
:=
make
(
chan
*
blocks
.
Block
,
c
.
WorkerBufferSize
)
// clientWorker handles incoming blocks from |w.added| and sends to
// |workerChan|. This will never block the client.
w
.
process
.
Go
(
func
(
proc
process
.
Process
)
{
defer
close
(
workerChan
)
var
workQueue
BlockList
debugInfo
:=
time
.
NewTicker
(
5
*
time
.
Second
)
defer
debugInfo
.
Stop
()
for
{
// take advantage of the fact that sending on nil channel always
// blocks so that a message is only sent if a block exists
sendToWorker
:=
workerChan
nextBlock
:=
workQueue
.
Pop
()
if
nextBlock
==
nil
{
sendToWorker
=
nil
}
select
{
// if worker is ready and there's a block to process, send the
// block
case
sendToWorker
<-
nextBlock
:
case
<-
debugInfo
.
C
:
if
workQueue
.
Len
()
>
0
{
log
.
Debugf
(
"%d blocks in blockservice provide queue..."
,
workQueue
.
Len
())
}
case
block
:=
<-
w
.
added
:
if
nextBlock
!=
nil
{
workQueue
.
Push
(
nextBlock
)
// missed the chance to send it
}
// if the client sends another block, add it to the queue.
workQueue
.
Push
(
block
)
case
<-
proc
.
Closing
()
:
return
}
}
})
// reads from |workerChan| until w.process closes
limiter
:=
ratelimit
.
NewRateLimiter
(
w
.
process
,
c
.
NumWorkers
)
limiter
.
Go
(
func
(
proc
process
.
Process
)
{
ctx
:=
procctx
.
OnClosingContext
(
proc
)
// shut down in-progress HasBlock when time to die
for
{
select
{
case
<-
proc
.
Closing
()
:
return
case
block
,
ok
:=
<-
workerChan
:
if
!
ok
{
return
}
limiter
.
LimitedGo
(
func
(
proc
process
.
Process
)
{
if
err
:=
w
.
exchange
.
HasBlock
(
ctx
,
block
);
err
!=
nil
{
log
.
Infof
(
"blockservice worker error: %s"
,
err
)
}
})
}
}
})
}
type
BlockList
struct
{
list
list
.
List
uniques
map
[
key
.
Key
]
*
list
.
Element
}
func
(
s
*
BlockList
)
PushFront
(
b
*
blocks
.
Block
)
{
if
s
.
uniques
==
nil
{
s
.
uniques
=
make
(
map
[
key
.
Key
]
*
list
.
Element
)
}
_
,
ok
:=
s
.
uniques
[
b
.
Key
()]
if
!
ok
{
e
:=
s
.
list
.
PushFront
(
b
)
s
.
uniques
[
b
.
Key
()]
=
e
}
}
func
(
s
*
BlockList
)
Push
(
b
*
blocks
.
Block
)
{
if
s
.
uniques
==
nil
{
s
.
uniques
=
make
(
map
[
key
.
Key
]
*
list
.
Element
)
}
_
,
ok
:=
s
.
uniques
[
b
.
Key
()]
if
!
ok
{
e
:=
s
.
list
.
PushBack
(
b
)
s
.
uniques
[
b
.
Key
()]
=
e
}
}
func
(
s
*
BlockList
)
Pop
()
*
blocks
.
Block
{
if
s
.
list
.
Len
()
==
0
{
return
nil
}
e
:=
s
.
list
.
Front
()
s
.
list
.
Remove
(
e
)
b
:=
e
.
Value
.
(
*
blocks
.
Block
)
delete
(
s
.
uniques
,
b
.
Key
())
return
b
}
func
(
s
*
BlockList
)
Len
()
int
{
return
s
.
list
.
Len
()
}
blockservice/worker/worker_test.go
deleted
100644 → 0
View file @
47b85c7b
package
worker
import
(
blocks
"github.com/ipfs/go-ipfs/blocks"
"testing"
)
func
TestStartClose
(
t
*
testing
.
T
)
{
numRuns
:=
50
if
testing
.
Short
()
{
numRuns
=
5
}
for
i
:=
0
;
i
<
numRuns
;
i
++
{
w
:=
NewWorker
(
nil
,
DefaultConfig
)
w
.
Close
()
}
}
func
TestQueueDeduplication
(
t
*
testing
.
T
)
{
numUniqBlocks
:=
5
// arbitrary
var
firstBatch
[]
*
blocks
.
Block
for
i
:=
0
;
i
<
numUniqBlocks
;
i
++
{
firstBatch
=
append
(
firstBatch
,
blockFromInt
(
i
))
}
// to get different pointer values and prevent the implementation from
// cheating. The impl must check equality using Key.
var
secondBatch
[]
*
blocks
.
Block
for
i
:=
0
;
i
<
numUniqBlocks
;
i
++
{
secondBatch
=
append
(
secondBatch
,
blockFromInt
(
i
))
}
var
workQueue
BlockList
for
_
,
b
:=
range
append
(
firstBatch
,
secondBatch
...
)
{
workQueue
.
Push
(
b
)
}
for
i
:=
0
;
i
<
numUniqBlocks
;
i
++
{
b
:=
workQueue
.
Pop
()
if
b
.
Key
()
!=
firstBatch
[
i
]
.
Key
()
{
t
.
Fatal
(
"list is not FIFO"
)
}
}
if
b
:=
workQueue
.
Pop
();
b
!=
nil
{
t
.
Fatal
(
"the workQueue did not de-duplicate the blocks"
)
}
}
func
TestPushPopPushPop
(
t
*
testing
.
T
)
{
var
workQueue
BlockList
orig
:=
blockFromInt
(
1
)
dup
:=
blockFromInt
(
1
)
workQueue
.
PushFront
(
orig
)
workQueue
.
Pop
()
workQueue
.
Push
(
dup
)
if
workQueue
.
Len
()
!=
1
{
t
.
Fatal
(
"the block list's internal state is corrupt"
)
}
}
func
blockFromInt
(
i
int
)
*
blocks
.
Block
{
return
blocks
.
NewBlock
([]
byte
(
string
(
i
)))
}
exchange/bitswap/bitswap.go
View file @
63f72a51
...
...
@@ -228,7 +228,7 @@ func (bs *Bitswap) CancelWants(ks []key.Key) {
// HasBlock announces the existance of a block to this bitswap service. The
// service will potentially notify its peers.
func
(
bs
*
Bitswap
)
HasBlock
(
ctx
context
.
Context
,
blk
*
blocks
.
Block
)
error
{
func
(
bs
*
Bitswap
)
HasBlock
(
blk
*
blocks
.
Block
)
error
{
select
{
case
<-
bs
.
process
.
Closing
()
:
return
errors
.
New
(
"bitswap is closed"
)
...
...
@@ -246,8 +246,8 @@ func (bs *Bitswap) HasBlock(ctx context.Context, blk *blocks.Block) error {
select
{
case
bs
.
newBlocks
<-
blk
:
// send block off to be reprovided
case
<-
ctx
.
Done
()
:
return
ctx
.
Err
()
case
<-
bs
.
process
.
Closing
()
:
return
bs
.
process
.
Close
()
}
return
nil
}
...
...
@@ -328,9 +328,7 @@ func (bs *Bitswap) ReceiveMessage(ctx context.Context, p peer.ID, incoming bsmsg
log
.
Event
(
ctx
,
"Bitswap.GetBlockRequest.End"
,
&
k
)
log
.
Debugf
(
"got block %s from %s"
,
b
,
p
)
hasBlockCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
hasBlockTimeout
)
defer
cancel
()
if
err
:=
bs
.
HasBlock
(
hasBlockCtx
,
b
);
err
!=
nil
{
if
err
:=
bs
.
HasBlock
(
b
);
err
!=
nil
{
log
.
Warningf
(
"ReceiveMessage HasBlock error: %s"
,
err
)
}
}(
block
)
...
...
exchange/bitswap/bitswap_test.go
View file @
63f72a51
...
...
@@ -70,7 +70,7 @@ func TestGetBlockFromPeerAfterPeerAnnounces(t *testing.T) {
hasBlock
:=
peers
[
0
]
defer
hasBlock
.
Exchange
.
Close
()
if
err
:=
hasBlock
.
Exchange
.
HasBlock
(
context
.
Background
(),
block
);
err
!=
nil
{
if
err
:=
hasBlock
.
Exchange
.
HasBlock
(
block
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -162,7 +162,7 @@ func PerformDistributionTest(t *testing.T, numInstances, numBlocks int) {
first
:=
instances
[
0
]
for
_
,
b
:=
range
blocks
{
blkeys
=
append
(
blkeys
,
b
.
Key
())
first
.
Exchange
.
HasBlock
(
ctx
,
b
)
first
.
Exchange
.
HasBlock
(
b
)
}
t
.
Log
(
"Distribute!"
)
...
...
@@ -224,7 +224,6 @@ func TestSendToWantingPeer(t *testing.T) {
t
.
Logf
(
"Session %v
\n
"
,
peerA
.
Peer
)
t
.
Logf
(
"Session %v
\n
"
,
peerB
.
Peer
)
timeout
:=
time
.
Second
waitTime
:=
time
.
Second
*
5
alpha
:=
bg
.
Next
()
...
...
@@ -237,9 +236,7 @@ func TestSendToWantingPeer(t *testing.T) {
}
// peerB announces to the network that he has block alpha
ctx
,
cancel
=
context
.
WithTimeout
(
context
.
Background
(),
timeout
)
defer
cancel
()
err
=
peerB
.
Exchange
.
HasBlock
(
ctx
,
alpha
)
err
=
peerB
.
Exchange
.
HasBlock
(
alpha
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -266,7 +263,7 @@ func TestBasicBitswap(t *testing.T) {
instances
:=
sg
.
Instances
(
2
)
blocks
:=
bg
.
Blocks
(
1
)
err
:=
instances
[
0
]
.
Exchange
.
HasBlock
(
context
.
Background
(),
blocks
[
0
])
err
:=
instances
[
0
]
.
Exchange
.
HasBlock
(
blocks
[
0
])
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
exchange/interface.go
View file @
63f72a51
...
...
@@ -19,7 +19,7 @@ type Interface interface {
// TODO Should callers be concerned with whether the block was made
// available on the network?
HasBlock
(
context
.
Context
,
*
blocks
.
Block
)
error
HasBlock
(
*
blocks
.
Block
)
error
io
.
Closer
}
exchange/offline/offline.go
View file @
63f72a51
...
...
@@ -28,7 +28,7 @@ func (e *offlineExchange) GetBlock(_ context.Context, k key.Key) (*blocks.Block,
}
// HasBlock always returns nil.
func
(
e
*
offlineExchange
)
HasBlock
(
_
context
.
Context
,
b
*
blocks
.
Block
)
error
{
func
(
e
*
offlineExchange
)
HasBlock
(
b
*
blocks
.
Block
)
error
{
return
e
.
bs
.
Put
(
b
)
}
...
...
exchange/offline/offline_test.go
View file @
63f72a51
...
...
@@ -26,7 +26,7 @@ func TestHasBlockReturnsNil(t *testing.T) {
ex
:=
Exchange
(
store
)
block
:=
blocks
.
NewBlock
([]
byte
(
"data"
))
err
:=
ex
.
HasBlock
(
context
.
Background
(),
block
)
err
:=
ex
.
HasBlock
(
block
)
if
err
!=
nil
{
t
.
Fail
()
}
...
...
@@ -44,7 +44,7 @@ func TestGetBlocks(t *testing.T) {
expected
:=
g
.
Blocks
(
2
)
for
_
,
b
:=
range
expected
{
if
err
:=
ex
.
HasBlock
(
context
.
Background
(),
b
);
err
!=
nil
{
if
err
:=
ex
.
HasBlock
(
b
);
err
!=
nil
{
t
.
Fail
()
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment