Unverified Commit 19ff6794 authored by Steven Allen's avatar Steven Allen Committed by GitHub

Merge pull request #6 from ipfs/feat/avoid-alloc-sess

Avoid allocating a session unless we need it
parents 142905b4 8819f05e
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"sync"
blocks "github.com/ipfs/go-block-format" blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
...@@ -116,8 +117,9 @@ func NewSession(ctx context.Context, bs BlockService) *Session { ...@@ -116,8 +117,9 @@ func NewSession(ctx context.Context, bs BlockService) *Session {
if sessEx, ok := exch.(exchange.SessionExchange); ok { if sessEx, ok := exch.(exchange.SessionExchange); ok {
ses := sessEx.NewSession(ctx) ses := sessEx.NewSession(ctx)
return &Session{ return &Session{
ses: ses, ses: ses,
bs: bs.Blockstore(), sessEx: sessEx,
bs: bs.Blockstore(),
} }
} }
return &Session{ return &Session{
...@@ -199,15 +201,19 @@ func (s *blockService) AddBlocks(bs []blocks.Block) error { ...@@ -199,15 +201,19 @@ func (s *blockService) AddBlocks(bs []blocks.Block) error {
func (s *blockService) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) { func (s *blockService) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) {
log.Debugf("BlockService GetBlock: '%s'", c) log.Debugf("BlockService GetBlock: '%s'", c)
var f exchange.Fetcher var f func() exchange.Fetcher
if s.exchange != nil { if s.exchange != nil {
f = s.exchange f = s.getExchange
} }
return getBlock(ctx, c, s.blockstore, f) // hash security return getBlock(ctx, c, s.blockstore, f) // hash security
} }
func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) (blocks.Block, error) { func (s *blockService) getExchange() exchange.Fetcher {
return s.exchange
}
func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, fget func() exchange.Fetcher) (blocks.Block, error) {
err := verifcid.ValidateCid(c) // hash security err := verifcid.ValidateCid(c) // hash security
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -218,7 +224,9 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchan ...@@ -218,7 +224,9 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchan
return block, nil return block, nil
} }
if err == blockstore.ErrNotFound && f != nil { if err == blockstore.ErrNotFound && fget != nil {
f := fget() // Don't load the exchange until we have to
// TODO be careful checking ErrNotFound. If the underlying // TODO be careful checking ErrNotFound. If the underlying
// implementation changes, this will break. // implementation changes, this will break.
log.Debug("Blockservice: Searching bitswap") log.Debug("Blockservice: Searching bitswap")
...@@ -245,10 +253,10 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchan ...@@ -245,10 +253,10 @@ func getBlock(ctx context.Context, c cid.Cid, bs blockstore.Blockstore, f exchan
// the returned channel. // the returned channel.
// NB: No guarantees are made about order. // NB: No guarantees are made about order.
func (s *blockService) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block { func (s *blockService) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
return getBlocks(ctx, ks, s.blockstore, s.exchange) // hash security return getBlocks(ctx, ks, s.blockstore, s.getExchange) // hash security
} }
func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) <-chan blocks.Block { func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, fget func() exchange.Fetcher) <-chan blocks.Block {
out := make(chan blocks.Block) out := make(chan blocks.Block)
go func() { go func() {
...@@ -284,6 +292,7 @@ func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, f ex ...@@ -284,6 +292,7 @@ func getBlocks(ctx context.Context, ks []cid.Cid, bs blockstore.Blockstore, f ex
return return
} }
f := fget() // don't load exchange unless we have to
rblocks, err := f.GetBlocks(ctx, misses) rblocks, err := f.GetBlocks(ctx, misses)
if err != nil { if err != nil {
log.Debugf("Error with GetBlocks: %s", err) log.Debugf("Error with GetBlocks: %s", err)
...@@ -318,18 +327,31 @@ func (s *blockService) Close() error { ...@@ -318,18 +327,31 @@ func (s *blockService) Close() error {
// Session is a helper type to provide higher level access to bitswap sessions // Session is a helper type to provide higher level access to bitswap sessions
type Session struct { type Session struct {
bs blockstore.Blockstore bs blockstore.Blockstore
ses exchange.Fetcher ses exchange.Fetcher
sessEx exchange.SessionExchange
sessCtx context.Context
lk sync.Mutex
}
func (s *Session) getSession() exchange.Fetcher {
s.lk.Lock()
defer s.lk.Unlock()
if s.ses == nil {
s.ses = s.sessEx.NewSession(s.sessCtx)
}
return s.ses
} }
// GetBlock gets a block in the context of a request session // GetBlock gets a block in the context of a request session
func (s *Session) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) { func (s *Session) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) {
return getBlock(ctx, c, s.bs, s.ses) // hash security return getBlock(ctx, c, s.bs, s.getSession) // hash security
} }
// GetBlocks gets blocks in the context of a request session // GetBlocks gets blocks in the context of a request session
func (s *Session) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block { func (s *Session) GetBlocks(ctx context.Context, ks []cid.Cid) <-chan blocks.Block {
return getBlocks(ctx, ks, s.bs, s.ses) // hash security return getBlocks(ctx, ks, s.bs, s.getSession) // hash security
} }
var _ BlockGetter = (*Session)(nil) var _ BlockGetter = (*Session)(nil)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment