@@ -41,11 +41,19 @@ static int s_starts_upload_retry(struct aws_s3_client *client, struct aws_s3_req
4141 AWS_ZERO_STRUCT (client -> synced_data .upload_part_stats );
4242
4343 s_init_mock_s3_request_upload_part_timeout (mock_request , 0 , average_time_ns , average_time_ns );
44- for (size_t i = 0 ; i < 10 ; i ++ ) {
45- /* Mock a number of requests completed with the large time for the request */
44+ size_t init_count = client -> ideal_connection_count ;
45+ size_t p90_count = init_count / 10 + 1 ;
46+ for (size_t i = 0 ; i < init_count - p90_count ; i ++ ) {
47+ /* With 90% of the average request time. */
4648 aws_s3_client_update_upload_part_timeout (client , mock_request , AWS_ERROR_SUCCESS );
4749 }
4850
51+ uint64_t one_sec_time_ns = aws_timestamp_convert (1 , AWS_TIMESTAMP_SECS , AWS_TIMESTAMP_NANOS , NULL ); /* 1 Secs */
52+ s_init_mock_s3_request_upload_part_timeout (mock_request , 0 , one_sec_time_ns , one_sec_time_ns );
53+ for (size_t i = 0 ; i < p90_count ; i ++ ) {
54+ /* 10 percent of the request takes 1 sec */
55+ aws_s3_client_update_upload_part_timeout (client , mock_request , AWS_ERROR_SUCCESS );
56+ }
4957 /* Check that retry should be turned off */
5058 ASSERT_FALSE (client -> synced_data .upload_part_stats .stop_timeout );
5159 size_t current_timeout_ms = aws_atomic_load_int (& client -> upload_timeout_ms );
@@ -78,7 +86,7 @@ TEST_CASE(client_update_upload_part_timeout) {
7886 uint64_t average_time_ns = aws_timestamp_convert (
7987 250 , AWS_TIMESTAMP_MILLIS , AWS_TIMESTAMP_NANOS , NULL ); /* 0.25 Secs, close to average for upload a part */
8088
81- size_t init_count = 10 ;
89+ size_t init_count = client -> ideal_connection_count ;
8290 {
8391 /* 1. If the request time is larger than 5 secs, we don't do retry */
8492 AWS_ZERO_STRUCT (client -> synced_data .upload_part_stats );
@@ -91,10 +99,62 @@ TEST_CASE(client_update_upload_part_timeout) {
9199 aws_s3_client_update_upload_part_timeout (client , & mock_request , AWS_ERROR_SUCCESS );
92100 }
93101
94- /* Check that retry should be turned off */
95102 ASSERT_TRUE (client -> synced_data .upload_part_stats .stop_timeout );
96103 size_t current_timeout_ms = aws_atomic_load_int (& client -> upload_timeout_ms );
97104 ASSERT_UINT_EQUALS (0 , current_timeout_ms );
105+ /* clean up */
106+ if (client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 ) {
107+ aws_priority_queue_clean_up (& client -> synced_data .upload_part_stats .initial_request_time .p90_samples );
108+ client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 = false;
109+ }
110+ }
111+ {
112+ /* 2.1. Test that the P90 of the init samples are used correctly and at least 1 sec */
113+ AWS_ZERO_STRUCT (client -> synced_data .upload_part_stats );
114+ /* Hack around to set the ideal connection time for testing. */
115+ size_t test_init_connection = 1000 ;
116+ * (uint32_t * )(void * )& client -> ideal_connection_count = (uint32_t )test_init_connection ;
117+ for (size_t i = 0 ; i < test_init_connection ; i ++ ) {
118+ /* Mock a number of requests completed with the large time for the request */
119+ uint64_t time_ns = aws_timestamp_convert (i , AWS_TIMESTAMP_MILLIS , AWS_TIMESTAMP_NANOS , NULL );
120+ s_init_mock_s3_request_upload_part_timeout (& mock_request , 0 , time_ns , time_ns );
121+ aws_s3_client_update_upload_part_timeout (client , & mock_request , AWS_ERROR_SUCCESS );
122+ }
123+
124+ size_t current_timeout_ms = aws_atomic_load_int (& client -> upload_timeout_ms );
125+ /* the P90 of the results is 900, but it has to be at least 1000 */
126+ ASSERT_UINT_EQUALS (1000 , current_timeout_ms );
127+ /* clean up */
128+ if (client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 ) {
129+ aws_priority_queue_clean_up (& client -> synced_data .upload_part_stats .initial_request_time .p90_samples );
130+ client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 = false;
131+ }
132+ /* Change it back */
133+ * (uint32_t * )(void * )& client -> ideal_connection_count = (uint32_t )init_count ;
134+ }
135+ {
136+ /* 2.2. Test that the P90 of the init samples are used correctly */
137+ AWS_ZERO_STRUCT (client -> synced_data .upload_part_stats );
138+ /* Hack around to set the ideal connection time for testing. */
139+ size_t test_init_connection = 10000 ;
140+ * (uint32_t * )(void * )& client -> ideal_connection_count = (uint32_t )test_init_connection ;
141+ for (size_t i = 0 ; i < test_init_connection ; i ++ ) {
142+ /* Mock a number of requests completed with the large time for the request */
143+ uint64_t time_ns = aws_timestamp_convert (i , AWS_TIMESTAMP_MILLIS , AWS_TIMESTAMP_NANOS , NULL );
144+ s_init_mock_s3_request_upload_part_timeout (& mock_request , 0 , time_ns , time_ns );
145+ aws_s3_client_update_upload_part_timeout (client , & mock_request , AWS_ERROR_SUCCESS );
146+ }
147+
148+ size_t current_timeout_ms = aws_atomic_load_int (& client -> upload_timeout_ms );
149+ /* P90 is 9000 */
150+ ASSERT_UINT_EQUALS (9000 , current_timeout_ms );
151+ /* clean up */
152+ if (client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 ) {
153+ aws_priority_queue_clean_up (& client -> synced_data .upload_part_stats .initial_request_time .p90_samples );
154+ client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 = false;
155+ }
156+ /* Change it back */
157+ * (uint32_t * )(void * )& client -> ideal_connection_count = (uint32_t )init_count ;
98158 }
99159
100160 {
@@ -137,6 +197,11 @@ TEST_CASE(client_update_upload_part_timeout) {
137197 aws_timestamp_convert (average_time_ns , AWS_TIMESTAMP_NANOS , AWS_TIMESTAMP_MILLIS , NULL ) +
138198 g_expect_timeout_offset_ms ,
139199 current_timeout_ms );
200+ /* clean up */
201+ if (client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 ) {
202+ aws_priority_queue_clean_up (& client -> synced_data .upload_part_stats .initial_request_time .p90_samples );
203+ client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 = false;
204+ }
140205 }
141206
142207 {
@@ -162,6 +227,11 @@ TEST_CASE(client_update_upload_part_timeout) {
162227 current_timeout_ms = aws_atomic_load_int (& client -> upload_timeout_ms );
163228 /* 1.1 secs, still */
164229 ASSERT_UINT_EQUALS (1100 , current_timeout_ms );
230+ /* clean up */
231+ if (client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 ) {
232+ aws_priority_queue_clean_up (& client -> synced_data .upload_part_stats .initial_request_time .p90_samples );
233+ client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 = false;
234+ }
165235 }
166236
167237 {
@@ -224,6 +294,11 @@ TEST_CASE(client_update_upload_part_timeout) {
224294 current_timeout_ms = aws_atomic_load_int (& client -> upload_timeout_ms );
225295 ASSERT_UINT_EQUALS (3000 , current_timeout_ms );
226296 ASSERT_FALSE (client -> synced_data .upload_part_stats .stop_timeout );
297+ /* clean up */
298+ if (client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 ) {
299+ aws_priority_queue_clean_up (& client -> synced_data .upload_part_stats .initial_request_time .p90_samples );
300+ client -> synced_data .upload_part_stats .initial_request_time .collecting_p90 = false;
301+ }
227302 }
228303
229304 {
0 commit comments