5
5
6
6
use std:: { collections:: BTreeSet , fmt:: Debug , ops:: DerefMut , sync:: Arc } ;
7
7
8
- use anyhow:: { anyhow , bail, Result } ;
8
+ use anyhow:: { bail, Result } ;
9
9
use futures_lite:: future:: Boxed as BoxedFuture ;
10
10
use futures_util:: future:: BoxFuture ;
11
11
use iroh:: { endpoint:: Connecting , protocol:: ProtocolHandler , Endpoint , NodeAddr } ;
12
12
use iroh_base:: hash:: { BlobFormat , Hash } ;
13
13
use serde:: { Deserialize , Serialize } ;
14
- use tracing:: { debug, warn } ;
14
+ use tracing:: debug;
15
15
16
16
use crate :: {
17
- downloader:: { DownloadRequest , Downloader } ,
18
- get:: {
19
- db:: { DownloadProgress , GetState } ,
20
- Stats ,
21
- } ,
17
+ downloader:: Downloader ,
22
18
provider:: EventSender ,
23
19
store:: GcConfig ,
24
20
util:: {
25
21
local_pool:: { self , LocalPoolHandle } ,
26
- progress:: { AsyncChannelProgressSender , ProgressSender } ,
27
22
SetTagOption ,
28
23
} ,
29
- HashAndFormat ,
30
24
} ;
31
25
32
26
/// A callback that blobs can ask about a set of hashes that should not be garbage collected.
@@ -48,20 +42,22 @@ impl Default for GcState {
48
42
}
49
43
50
44
#[ derive( Debug ) ]
51
- struct BlobsInner < S > {
52
- rt : LocalPoolHandle ,
45
+ pub ( crate ) struct BlobsInner < S > {
46
+ pub ( crate ) rt : LocalPoolHandle ,
53
47
pub ( crate ) store : S ,
54
48
events : EventSender ,
55
- downloader : Downloader ,
56
- endpoint : Endpoint ,
49
+ pub ( crate ) downloader : Downloader ,
50
+ pub ( crate ) endpoint : Endpoint ,
57
51
gc_state : std:: sync:: Mutex < GcState > ,
58
52
#[ cfg( feature = "rpc" ) ]
59
- batches : tokio:: sync:: Mutex < BlobBatches > ,
53
+ pub ( crate ) batches : tokio:: sync:: Mutex < BlobBatches > ,
60
54
}
61
55
62
56
#[ derive( Debug , Clone ) ]
63
57
pub struct Blobs < S > {
64
- inner : Arc < BlobsInner < S > > ,
58
+ pub ( crate ) inner : Arc < BlobsInner < S > > ,
59
+ #[ cfg( feature = "rpc" ) ]
60
+ pub ( crate ) rpc_handler : Arc < std:: sync:: OnceLock < crate :: rpc:: RpcHandler > > ,
65
61
}
66
62
67
63
/// Keeps track of all the currently active batch operations of the blobs api.
@@ -79,7 +75,7 @@ pub(crate) struct BlobBatches {
79
75
#[ derive( Debug , Default ) ]
80
76
struct BlobBatch {
81
77
/// The tags in this batch.
82
- tags : std:: collections:: BTreeMap < HashAndFormat , Vec < crate :: TempTag > > ,
78
+ tags : std:: collections:: BTreeMap < iroh :: hash :: HashAndFormat , Vec < crate :: TempTag > > ,
83
79
}
84
80
85
81
#[ cfg( feature = "rpc" ) ]
@@ -98,7 +94,11 @@ impl BlobBatches {
98
94
}
99
95
100
96
/// Remove a tag from a batch.
101
- pub fn remove_one ( & mut self , batch : BatchId , content : & HashAndFormat ) -> Result < ( ) > {
97
+ pub fn remove_one (
98
+ & mut self ,
99
+ batch : BatchId ,
100
+ content : & iroh:: hash:: HashAndFormat ,
101
+ ) -> Result < ( ) > {
102
102
if let Some ( batch) = self . batches . get_mut ( & batch) {
103
103
if let Some ( tags) = batch. tags . get_mut ( content) {
104
104
tags. pop ( ) ;
@@ -191,6 +191,8 @@ impl<S: crate::store::Store> Blobs<S> {
191
191
batches : Default :: default ( ) ,
192
192
gc_state : Default :: default ( ) ,
193
193
} ) ,
194
+ #[ cfg( feature = "rpc" ) ]
195
+ rpc_handler : Default :: default ( ) ,
194
196
}
195
197
}
196
198
@@ -255,147 +257,6 @@ impl<S: crate::store::Store> Blobs<S> {
255
257
* state = GcState :: Started ( Some ( run) ) ;
256
258
Ok ( ( ) )
257
259
}
258
-
259
- #[ cfg( feature = "rpc" ) ]
260
- pub ( crate ) async fn batches ( & self ) -> tokio:: sync:: MutexGuard < ' _ , BlobBatches > {
261
- self . inner . batches . lock ( ) . await
262
- }
263
-
264
- pub ( crate ) async fn download (
265
- & self ,
266
- endpoint : Endpoint ,
267
- req : BlobDownloadRequest ,
268
- progress : AsyncChannelProgressSender < DownloadProgress > ,
269
- ) -> Result < ( ) > {
270
- let BlobDownloadRequest {
271
- hash,
272
- format,
273
- nodes,
274
- tag,
275
- mode,
276
- } = req;
277
- let hash_and_format = HashAndFormat { hash, format } ;
278
- let temp_tag = self . store ( ) . temp_tag ( hash_and_format) ;
279
- let stats = match mode {
280
- DownloadMode :: Queued => {
281
- self . download_queued ( endpoint, hash_and_format, nodes, progress. clone ( ) )
282
- . await ?
283
- }
284
- DownloadMode :: Direct => {
285
- self . download_direct_from_nodes ( endpoint, hash_and_format, nodes, progress. clone ( ) )
286
- . await ?
287
- }
288
- } ;
289
-
290
- progress. send ( DownloadProgress :: AllDone ( stats) ) . await . ok ( ) ;
291
- match tag {
292
- SetTagOption :: Named ( tag) => {
293
- self . store ( ) . set_tag ( tag, Some ( hash_and_format) ) . await ?;
294
- }
295
- SetTagOption :: Auto => {
296
- self . store ( ) . create_tag ( hash_and_format) . await ?;
297
- }
298
- }
299
- drop ( temp_tag) ;
300
-
301
- Ok ( ( ) )
302
- }
303
-
304
- async fn download_queued (
305
- & self ,
306
- endpoint : Endpoint ,
307
- hash_and_format : HashAndFormat ,
308
- nodes : Vec < NodeAddr > ,
309
- progress : AsyncChannelProgressSender < DownloadProgress > ,
310
- ) -> Result < Stats > {
311
- /// Name used for logging when new node addresses are added from gossip.
312
- const BLOB_DOWNLOAD_SOURCE_NAME : & str = "blob_download" ;
313
-
314
- let mut node_ids = Vec :: with_capacity ( nodes. len ( ) ) ;
315
- let mut any_added = false ;
316
- for node in nodes {
317
- node_ids. push ( node. node_id ) ;
318
- if !node. info . is_empty ( ) {
319
- endpoint. add_node_addr_with_source ( node, BLOB_DOWNLOAD_SOURCE_NAME ) ?;
320
- any_added = true ;
321
- }
322
- }
323
- let can_download = !node_ids. is_empty ( ) && ( any_added || endpoint. discovery ( ) . is_some ( ) ) ;
324
- anyhow:: ensure!( can_download, "no way to reach a node for download" ) ;
325
- let req = DownloadRequest :: new ( hash_and_format, node_ids) . progress_sender ( progress) ;
326
- let handle = self . downloader ( ) . queue ( req) . await ;
327
- let stats = handle. await ?;
328
- Ok ( stats)
329
- }
330
-
331
- #[ tracing:: instrument( "download_direct" , skip_all, fields( hash=%hash_and_format. hash. fmt_short( ) ) ) ]
332
- async fn download_direct_from_nodes (
333
- & self ,
334
- endpoint : Endpoint ,
335
- hash_and_format : HashAndFormat ,
336
- nodes : Vec < NodeAddr > ,
337
- progress : AsyncChannelProgressSender < DownloadProgress > ,
338
- ) -> Result < Stats > {
339
- let mut last_err = None ;
340
- let mut remaining_nodes = nodes. len ( ) ;
341
- let mut nodes_iter = nodes. into_iter ( ) ;
342
- ' outer: loop {
343
- match crate :: get:: db:: get_to_db_in_steps (
344
- self . store ( ) . clone ( ) ,
345
- hash_and_format,
346
- progress. clone ( ) ,
347
- )
348
- . await ?
349
- {
350
- GetState :: Complete ( stats) => return Ok ( stats) ,
351
- GetState :: NeedsConn ( needs_conn) => {
352
- let ( conn, node_id) = ' inner: loop {
353
- match nodes_iter. next ( ) {
354
- None => break ' outer,
355
- Some ( node) => {
356
- remaining_nodes -= 1 ;
357
- let node_id = node. node_id ;
358
- if node_id == endpoint. node_id ( ) {
359
- debug ! (
360
- ?remaining_nodes,
361
- "skip node {} (it is the node id of ourselves)" ,
362
- node_id. fmt_short( )
363
- ) ;
364
- continue ' inner;
365
- }
366
- match endpoint. connect ( node, crate :: protocol:: ALPN ) . await {
367
- Ok ( conn) => break ' inner ( conn, node_id) ,
368
- Err ( err) => {
369
- debug ! (
370
- ?remaining_nodes,
371
- "failed to connect to {}: {err}" ,
372
- node_id. fmt_short( )
373
- ) ;
374
- continue ' inner;
375
- }
376
- }
377
- }
378
- }
379
- } ;
380
- match needs_conn. proceed ( conn) . await {
381
- Ok ( stats) => return Ok ( stats) ,
382
- Err ( err) => {
383
- warn ! (
384
- ?remaining_nodes,
385
- "failed to download from {}: {err}" ,
386
- node_id. fmt_short( )
387
- ) ;
388
- last_err = Some ( err) ;
389
- }
390
- }
391
- }
392
- }
393
- }
394
- match last_err {
395
- Some ( err) => Err ( err. into ( ) ) ,
396
- None => Err ( anyhow ! ( "No nodes to download from provided" ) ) ,
397
- }
398
- }
399
260
}
400
261
401
262
impl < S : crate :: store:: Store > ProtocolHandler for Blobs < S > {
0 commit comments