@@ -73,6 +73,7 @@ static udpard_udpip_ep_t make_topic_ep(const uint32_t subject_id)
7373}
7474
7575static size_t smaller (const size_t a , const size_t b ) { return (a < b ) ? a : b ; }
76+ static size_t smaller3 (const size_t a , const size_t b , const size_t c ) { return smaller (smaller (a , b ), c ); }
7677static size_t larger (const size_t a , const size_t b ) { return (a > b ) ? a : b ; }
7778static uint32_t max_u32 (const uint32_t a , const uint32_t b ) { return (a > b ) ? a : b ; }
7879
@@ -775,15 +776,36 @@ static bool rx_fragment_tree_has_gap_in_range(udpard_tree_t* const root, const s
775776/// True if the specified fragment should be retained. Otherwise, it is redundant and should be discarded.
776777/// The complexity is O(log n + k), see rx_fragment_tree_has_gap_in_range() for details.
777778static bool rx_fragment_is_needed (udpard_tree_t * const root ,
778- const size_t fragment_offset ,
779- const size_t fragment_size ,
779+ const size_t frag_offset ,
780+ const size_t frag_size ,
780781 const size_t transfer_size ,
781782 const size_t extent )
782783{
783- const size_t size = smaller (transfer_size , extent );
784- const size_t left = fragment_offset ;
785- const size_t right = smaller (fragment_offset + fragment_size , size );
786- return (left < size ) && rx_fragment_tree_has_gap_in_range (root , left , right );
784+ const size_t end = smaller3 (frag_offset + frag_size , transfer_size , extent );
785+ return (frag_offset < extent ) && rx_fragment_tree_has_gap_in_range (root , frag_offset , end );
786+ }
787+
788+ /// Finds the number of contiguous payload bytes received from offset zero after accepting a new fragment.
789+ /// The transfer is considered fully received when covered_prefix >= min(extent, transfer_payload_size).
790+ /// This should be invoked after the fragment tree accepted a new fragment at frag_offset with frag_size.
791+ /// The complexity is linear in the number of contiguous fragments following old_prefix.
792+ static size_t rx_fragment_tree_update_covered_prefix (udpard_tree_t * const root ,
793+ const size_t old_prefix ,
794+ const size_t frag_offset ,
795+ const size_t frag_size )
796+ {
797+ const size_t end = frag_offset + frag_size ;
798+ if ((frag_offset > old_prefix ) || (end <= old_prefix )) {
799+ return old_prefix ; // The new fragment does not cross the frontier, so it cannot affect the prefix.
800+ }
801+ udpard_fragment_t * fr = (udpard_fragment_t * )cavl2_predecessor (root , & old_prefix , & rx_cavl_compare_fragment_offset );
802+ UDPARD_ASSERT (fr != NULL );
803+ size_t out = old_prefix ;
804+ while ((fr != NULL ) && (fr -> offset <= out )) {
805+ out = larger (out , fr -> offset + fr -> view .size );
806+ fr = (udpard_fragment_t * )cavl2_next_greater (& fr -> index_offset );
807+ }
808+ return out ;
787809}
788810
789811typedef enum
0 commit comments