Commit 2645e2bd authored by Kevin Atkinson's avatar Kevin Atkinson

Create a "write through" BlockService.

Create a block service where all writes are guaranteed to go though
to the blockstore.

License: MIT
Signed-off-by: default avatarKevin Atkinson <k@kevina.org>
parent 67829690
...@@ -37,6 +37,9 @@ type BlockService interface { ...@@ -37,6 +37,9 @@ type BlockService interface {
type blockService struct { type blockService struct {
blockstore blockstore.Blockstore blockstore blockstore.Blockstore
exchange exchange.Interface exchange exchange.Interface
// If checkFirst is true then first check that a block doesn't
// already exist to avoid republishing the block on the exchange.
checkFirst bool
} }
// NewBlockService creates a BlockService with given datastore instance. // NewBlockService creates a BlockService with given datastore instance.
...@@ -48,6 +51,21 @@ func New(bs blockstore.Blockstore, rem exchange.Interface) BlockService { ...@@ -48,6 +51,21 @@ func New(bs blockstore.Blockstore, rem exchange.Interface) BlockService {
return &blockService{ return &blockService{
blockstore: bs, blockstore: bs,
exchange: rem, exchange: rem,
checkFirst: true,
}
}
// NewWriteThrough ceates a BlockService that guarantees writes will go
// through to the blockstore and are not skipped by cache checks.
func NewWriteThrough(bs blockstore.Blockstore, rem exchange.Interface) BlockService {
if rem == nil {
log.Warning("blockservice running in local (offline) mode.")
}
return &blockService{
blockstore: bs,
exchange: rem,
checkFirst: false,
} }
} }
...@@ -62,12 +80,8 @@ func (bs *blockService) Exchange() exchange.Interface { ...@@ -62,12 +80,8 @@ func (bs *blockService) Exchange() exchange.Interface {
// AddBlock adds a particular block to the service, Putting it into the datastore. // AddBlock adds a particular block to the service, Putting it into the datastore.
// TODO pass a context into this if the remote.HasBlock is going to remain here. // TODO pass a context into this if the remote.HasBlock is going to remain here.
func (s *blockService) AddBlock(o blocks.Block) (*cid.Cid, error) { func (s *blockService) AddBlock(o blocks.Block) (*cid.Cid, error) {
// TODO: while this is a great optimization, we should think about the
// possibility of streaming writes directly to disk. If we can pass this object
// all the way down to the datastore without having to 'buffer' its data,
// we could implement a `WriteTo` method on it that could do a streaming write
// of the content, saving us (probably) considerable memory.
c := o.Cid() c := o.Cid()
if s.checkFirst {
has, err := s.blockstore.Has(c) has, err := s.blockstore.Has(c)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -76,8 +90,9 @@ func (s *blockService) AddBlock(o blocks.Block) (*cid.Cid, error) { ...@@ -76,8 +90,9 @@ func (s *blockService) AddBlock(o blocks.Block) (*cid.Cid, error) {
if has { if has {
return c, nil return c, nil
} }
}
err = s.blockstore.Put(o) err := s.blockstore.Put(o)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -91,18 +106,20 @@ func (s *blockService) AddBlock(o blocks.Block) (*cid.Cid, error) { ...@@ -91,18 +106,20 @@ func (s *blockService) AddBlock(o blocks.Block) (*cid.Cid, error) {
func (s *blockService) AddBlocks(bs []blocks.Block) ([]*cid.Cid, error) { func (s *blockService) AddBlocks(bs []blocks.Block) ([]*cid.Cid, error) {
var toput []blocks.Block var toput []blocks.Block
if s.checkFirst {
for _, b := range bs { for _, b := range bs {
has, err := s.blockstore.Has(b.Cid()) has, err := s.blockstore.Has(b.Cid())
if err != nil { if err != nil {
return nil, err return nil, err
} }
if has { if has {
continue continue
} }
toput = append(toput, b) toput = append(toput, b)
} }
} else {
toput = bs;
}
err := s.blockstore.PutMany(toput) err := s.blockstore.PutMany(toput)
if err != nil { if err != 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