Skip to content

Commit 4ac7fe6

Browse files
masihrvagg
authored andcommitted
Do not write CAR file when no candidates are found
Lazily instantiate the CARv2 ReadWrite blockstore, so that no `.car` file is created when no candidates are found from which to retrieve. Return any errors when finalizing the car blockstore. Fixes #32
1 parent 997860b commit 4ac7fe6

File tree

1 file changed

+68
-16
lines changed

1 file changed

+68
-16
lines changed

cmd/lassie/fetch.go

+68-16
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"log"
67
"strings"
78
"time"
89

@@ -66,9 +67,8 @@ func Fetch(c *cli.Context) error {
6667
outfile = c.String("output")
6768
}
6869

69-
carStore, err := carblockstore.OpenReadWrite(outfile, []cid.Cid{rootCid})
70-
if err != nil {
71-
return err
70+
var parentOpener = func() (*carblockstore.ReadWrite, error) {
71+
return carblockstore.OpenReadWrite(outfile, []cid.Cid{rootCid})
7272
}
7373

7474
var blockCount int
@@ -80,7 +80,7 @@ func Fetch(c *cli.Context) error {
8080
fmt.Printf("Received %d blocks...\n", blockCount)
8181
}
8282
}
83-
bstore := &putCbBlockstore{parent: carStore, cb: putCb}
83+
bstore := &putCbBlockstore{parentOpener: parentOpener, cb: putCb}
8484
ret, err := setupRetriever(c, c.Duration("timeout"), bstore)
8585
if err != nil {
8686
return err
@@ -111,9 +111,7 @@ func Fetch(c *cli.Context) error {
111111
humanize.IBytes(stats.Size),
112112
)
113113

114-
carStore.Finalize()
115-
116-
return nil
114+
return bstore.Finalize()
117115
}
118116

119117
func setupRetriever(c *cli.Context, timeout time.Duration, blockstore blockstore.Blockstore) (*retriever.Retriever, error) {
@@ -158,35 +156,89 @@ func setupRetriever(c *cli.Context, timeout time.Duration, blockstore blockstore
158156
var _ blockstore.Blockstore = (*putCbBlockstore)(nil)
159157

160158
type putCbBlockstore struct {
161-
parent blockstore.Blockstore
159+
// parentOpener lazily opens the parent blockstore upon first call to this blockstore.
160+
// This avoids blockstore instantiation until there is some interaction from the retriever.
161+
// In the case of CARv2 blockstores, this will avoid creation of empty .car files should
162+
// the retriever fail to find any candidates.
163+
parentOpener func() (*carblockstore.ReadWrite, error)
164+
// parent is lazily instantiated and should not be directly used; use parentBlockstore instead.
165+
parent *carblockstore.ReadWrite
162166
cb func(putCount int)
163167
}
164168

165169
func (pcb *putCbBlockstore) DeleteBlock(ctx context.Context, cid cid.Cid) error {
166-
return pcb.parent.DeleteBlock(ctx, cid)
170+
pbs, err := pcb.parentBlockstore()
171+
if err != nil {
172+
return err
173+
}
174+
return pbs.DeleteBlock(ctx, cid)
167175
}
168176
func (pcb *putCbBlockstore) Has(ctx context.Context, cid cid.Cid) (bool, error) {
169-
return pcb.parent.Has(ctx, cid)
177+
pbs, err := pcb.parentBlockstore()
178+
if err != nil {
179+
return false, err
180+
}
181+
return pbs.Has(ctx, cid)
170182
}
171183
func (pcb *putCbBlockstore) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) {
172-
return pcb.parent.Get(ctx, cid)
184+
pbs, err := pcb.parentBlockstore()
185+
if err != nil {
186+
return nil, err
187+
}
188+
return pbs.Get(ctx, cid)
173189
}
174190
func (pcb *putCbBlockstore) GetSize(ctx context.Context, cid cid.Cid) (int, error) {
175-
return pcb.parent.GetSize(ctx, cid)
191+
pbs, err := pcb.parentBlockstore()
192+
if err != nil {
193+
return 0, err
194+
}
195+
return pbs.GetSize(ctx, cid)
176196
}
177197
func (pcb *putCbBlockstore) Put(ctx context.Context, block blocks.Block) error {
198+
pbs, err := pcb.parentBlockstore()
199+
if err != nil {
200+
return err
201+
}
178202
pcb.cb(1)
179-
return pcb.parent.Put(ctx, block)
203+
return pbs.Put(ctx, block)
180204
}
181205
func (pcb *putCbBlockstore) PutMany(ctx context.Context, blocks []blocks.Block) error {
206+
pbs, err := pcb.parentBlockstore()
207+
if err != nil {
208+
return err
209+
}
182210
pcb.cb(len(blocks))
183-
return pcb.parent.PutMany(ctx, blocks)
211+
return pbs.PutMany(ctx, blocks)
184212
}
185213
func (pcb *putCbBlockstore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
186-
return pcb.parent.AllKeysChan(ctx)
214+
pbs, err := pcb.parentBlockstore()
215+
if err != nil {
216+
return nil, err
217+
}
218+
return pbs.AllKeysChan(ctx)
187219
}
188220
func (pcb *putCbBlockstore) HashOnRead(enabled bool) {
189-
pcb.parent.HashOnRead(enabled)
221+
if pbs, err := pcb.parentBlockstore(); err != nil {
222+
log.Printf("Failed to instantiate blockstore while setting HashOnRead: %v\n", err)
223+
} else {
224+
pbs.HashOnRead(enabled)
225+
}
226+
}
227+
func (pcb *putCbBlockstore) Finalize() error {
228+
if pbs, err := pcb.parentBlockstore(); err != nil {
229+
return err
230+
} else {
231+
return pbs.Finalize()
232+
}
233+
}
234+
func (pcb *putCbBlockstore) parentBlockstore() (*carblockstore.ReadWrite, error) {
235+
if pcb.parent == nil {
236+
var err error
237+
if pcb.parent, err = pcb.parentOpener(); err != nil {
238+
return nil, err
239+
}
240+
}
241+
return pcb.parent, nil
190242
}
191243

192244
var _ retriever.RetrievalEventListener = (*progressPrinter)(nil)

0 commit comments

Comments
 (0)