@@ -3,6 +3,7 @@ package main
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "log"
6
7
"strings"
7
8
"time"
8
9
@@ -66,9 +67,8 @@ func Fetch(c *cli.Context) error {
66
67
outfile = c .String ("output" )
67
68
}
68
69
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 })
72
72
}
73
73
74
74
var blockCount int
@@ -80,7 +80,7 @@ func Fetch(c *cli.Context) error {
80
80
fmt .Printf ("Received %d blocks...\n " , blockCount )
81
81
}
82
82
}
83
- bstore := & putCbBlockstore {parent : carStore , cb : putCb }
83
+ bstore := & putCbBlockstore {parentOpener : parentOpener , cb : putCb }
84
84
ret , err := setupRetriever (c , c .Duration ("timeout" ), bstore )
85
85
if err != nil {
86
86
return err
@@ -111,9 +111,7 @@ func Fetch(c *cli.Context) error {
111
111
humanize .IBytes (stats .Size ),
112
112
)
113
113
114
- carStore .Finalize ()
115
-
116
- return nil
114
+ return bstore .Finalize ()
117
115
}
118
116
119
117
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
158
156
var _ blockstore.Blockstore = (* putCbBlockstore )(nil )
159
157
160
158
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
162
166
cb func (putCount int )
163
167
}
164
168
165
169
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 )
167
175
}
168
176
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 )
170
182
}
171
183
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 )
173
189
}
174
190
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 )
176
196
}
177
197
func (pcb * putCbBlockstore ) Put (ctx context.Context , block blocks.Block ) error {
198
+ pbs , err := pcb .parentBlockstore ()
199
+ if err != nil {
200
+ return err
201
+ }
178
202
pcb .cb (1 )
179
- return pcb . parent .Put (ctx , block )
203
+ return pbs .Put (ctx , block )
180
204
}
181
205
func (pcb * putCbBlockstore ) PutMany (ctx context.Context , blocks []blocks.Block ) error {
206
+ pbs , err := pcb .parentBlockstore ()
207
+ if err != nil {
208
+ return err
209
+ }
182
210
pcb .cb (len (blocks ))
183
- return pcb . parent .PutMany (ctx , blocks )
211
+ return pbs .PutMany (ctx , blocks )
184
212
}
185
213
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 )
187
219
}
188
220
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
190
242
}
191
243
192
244
var _ retriever.RetrievalEventListener = (* progressPrinter )(nil )
0 commit comments