@@ -517,6 +517,144 @@ impl Storage {
517
517
self . metadata . piece_id ( task_id, number)
518
518
}
519
519
520
+ /// download_persistent_cache_piece_started updates the metadata of the persistent cache piece and writes
521
+ /// the data of piece to file when the persistent cache piece downloads started.
522
+ #[ instrument( skip_all) ]
523
+ pub async fn download_persistent_cache_piece_started (
524
+ & self ,
525
+ piece_id : & str ,
526
+ number : u32 ,
527
+ ) -> Result < metadata:: Piece > {
528
+ // Wait for the piece to be finished.
529
+ match self
530
+ . wait_for_persistent_cache_piece_finished ( piece_id)
531
+ . await
532
+ {
533
+ Ok ( piece) => Ok ( piece) ,
534
+ // If piece is not found or wait timeout, create piece metadata.
535
+ Err ( _) => self . metadata . download_piece_started ( piece_id, number) ,
536
+ }
537
+ }
538
+
539
+ /// download_persistent_cache_piece_from_parent_finished is used for downloading persistent cache piece from parent.
540
+ #[ instrument( skip_all) ]
541
+ pub async fn download_persistent_cache_piece_from_parent_finished <
542
+ R : AsyncRead + Unpin + ?Sized ,
543
+ > (
544
+ & self ,
545
+ piece_id : & str ,
546
+ task_id : & str ,
547
+ offset : u64 ,
548
+ expected_digest : & str ,
549
+ parent_id : & str ,
550
+ reader : & mut R ,
551
+ ) -> Result < metadata:: Piece > {
552
+ let response = self
553
+ . content
554
+ . write_piece_with_crc32_castagnoli ( task_id, offset, reader)
555
+ . await ?;
556
+
557
+ let length = response. length ;
558
+ let digest = Digest :: new ( Algorithm :: Crc32 , response. hash ) ;
559
+
560
+ // Check the digest of the piece.
561
+ if expected_digest != digest. to_string ( ) {
562
+ return Err ( Error :: DigestMismatch (
563
+ expected_digest. to_string ( ) ,
564
+ digest. to_string ( ) ,
565
+ ) ) ;
566
+ }
567
+
568
+ self . metadata . download_piece_finished (
569
+ piece_id,
570
+ offset,
571
+ length,
572
+ digest. to_string ( ) . as_str ( ) ,
573
+ Some ( parent_id. to_string ( ) ) ,
574
+ )
575
+ }
576
+
577
+ /// download_persistent_cache_piece_failed updates the metadata of the persistent cache piece when the persistent cache piece downloads failed.
578
+ #[ instrument( skip_all) ]
579
+ pub fn download_persistent_cache_piece_failed ( & self , piece_id : & str ) -> Result < ( ) > {
580
+ self . metadata . download_piece_failed ( piece_id)
581
+ }
582
+
583
+ /// upload_persistent_cache_piece updates the metadata of the piece and_then
584
+ /// returns the data of the piece.
585
+ #[ instrument( skip_all) ]
586
+ pub async fn upload_persistent_cache_piece (
587
+ & self ,
588
+ piece_id : & str ,
589
+ task_id : & str ,
590
+ range : Option < Range > ,
591
+ ) -> Result < impl AsyncRead > {
592
+ // Wait for the persistent cache piece to be finished.
593
+ self . wait_for_persistent_cache_piece_finished ( piece_id)
594
+ . await ?;
595
+
596
+ // Start uploading the persistent cache task.
597
+ self . metadata
598
+ . upload_persistent_cache_task_started ( task_id) ?;
599
+
600
+ // Get the persistent cache piece metadata and return the content of the persistent cache piece.
601
+ match self . metadata . get_piece ( piece_id) {
602
+ Ok ( Some ( piece) ) => {
603
+ match self
604
+ . content
605
+ . read_piece ( task_id, piece. offset , piece. length , range)
606
+ . await
607
+ {
608
+ Ok ( reader) => {
609
+ // Finish uploading the persistent cache task.
610
+ self . metadata
611
+ . upload_persistent_cache_task_finished ( task_id) ?;
612
+ Ok ( reader)
613
+ }
614
+ Err ( err) => {
615
+ // Failed uploading the persistent cache task.
616
+ self . metadata . upload_persistent_cache_task_failed ( task_id) ?;
617
+ Err ( err)
618
+ }
619
+ }
620
+ }
621
+ Ok ( None ) => {
622
+ // Failed uploading the persistent cache task.
623
+ self . metadata . upload_persistent_cache_task_failed ( task_id) ?;
624
+ Err ( Error :: PieceNotFound ( piece_id. to_string ( ) ) )
625
+ }
626
+ Err ( err) => {
627
+ // Failed uploading the persistent cache task.
628
+ self . metadata . upload_persistent_cache_task_failed ( task_id) ?;
629
+ Err ( err)
630
+ }
631
+ }
632
+ }
633
+
634
+ /// get_persistent_cache_piece returns the persistent cache piece metadata.
635
+ #[ instrument( skip_all) ]
636
+ pub fn get_persistent_cache_piece ( & self , piece_id : & str ) -> Result < Option < metadata:: Piece > > {
637
+ self . metadata . get_piece ( piece_id)
638
+ }
639
+
640
+ /// is_persistent_cache_piece_exists returns whether the persistent cache piece exists.
641
+ #[ instrument( skip_all) ]
642
+ pub fn is_persistent_cache_piece_exists ( & self , piece_id : & str ) -> Result < bool > {
643
+ self . metadata . is_piece_exists ( piece_id)
644
+ }
645
+
646
+ /// get_persistent_cache_pieces returns the persistent cache piece metadatas.
647
+ pub fn get_persistent_cache_pieces ( & self , task_id : & str ) -> Result < Vec < metadata:: Piece > > {
648
+ self . metadata . get_pieces ( task_id)
649
+ }
650
+
651
+ /// persistent_cache_piece_id returns the persistent cache piece id.
652
+ #[ inline]
653
+ #[ instrument( skip_all) ]
654
+ pub fn persistent_cache_piece_id ( & self , task_id : & str , number : u32 ) -> String {
655
+ self . metadata . piece_id ( task_id, number)
656
+ }
657
+
520
658
/// wait_for_piece_finished waits for the piece to be finished.
521
659
#[ instrument( skip_all) ]
522
660
async fn wait_for_piece_finished ( & self , piece_id : & str ) -> Result < metadata:: Piece > {
@@ -552,4 +690,43 @@ impl Storage {
552
690
}
553
691
}
554
692
}
693
+
694
+ /// wait_for_persistent_cache_piece_finished waits for the persistent cache piece to be finished.
695
+ #[ instrument( skip_all) ]
696
+ async fn wait_for_persistent_cache_piece_finished (
697
+ & self ,
698
+ piece_id : & str ,
699
+ ) -> Result < metadata:: Piece > {
700
+ // Initialize the timeout of piece.
701
+ let piece_timeout = tokio:: time:: sleep ( self . config . download . piece_timeout ) ;
702
+ tokio:: pin!( piece_timeout) ;
703
+
704
+ // Initialize the interval of piece.
705
+ let mut wait_for_piece_count = 0 ;
706
+ let mut interval = tokio:: time:: interval ( DEFAULT_WAIT_FOR_PIECE_FINISHED_INTERVAL ) ;
707
+ loop {
708
+ tokio:: select! {
709
+ _ = interval. tick( ) => {
710
+ let piece = self
711
+ . get_persistent_cache_piece( piece_id) ?
712
+ . ok_or_else( || Error :: PieceNotFound ( piece_id. to_string( ) ) ) ?;
713
+
714
+ // If the piece is finished, return.
715
+ if piece. is_finished( ) {
716
+ debug!( "wait piece finished success" ) ;
717
+ return Ok ( piece) ;
718
+ }
719
+
720
+ if wait_for_piece_count > 0 {
721
+ debug!( "wait piece finished" ) ;
722
+ }
723
+ wait_for_piece_count += 1 ;
724
+ }
725
+ _ = & mut piece_timeout => {
726
+ self . metadata. wait_for_piece_finished_failed( piece_id) . unwrap_or_else( |err| error!( "delete piece metadata failed: {}" , err) ) ;
727
+ return Err ( Error :: WaitForPieceFinishedTimeout ( piece_id. to_string( ) ) ) ;
728
+ }
729
+ }
730
+ }
731
+ }
555
732
}
0 commit comments