@@ -1899,24 +1899,21 @@ static char *cram_compress_by_method(cram_slice *s, char *in, size_t in_size,
18991899 return NULL ;
19001900}
19011901
1902-
19031902/*
1904- * Compresses a block using one of two different zlib strategies. If we only
1905- * want one choice set strat2 to be -1.
1906- *
1907- * The logic here is that sometimes Z_RLE does a better job than Z_FILTERED
1908- * or Z_DEFAULT_STRATEGY on quality data. If so, we'd rather use it as it is
1909- * significantly faster.
1910- *
1911- * Method and level -1 implies defaults, as specified in cram_fd.
1903+ * A copy of cram_compress_block2 with added recursion detection.
1904+ * This is only called for error handling where the auto-tuning has failed.
1905+ * The simplest way of doing this is recusion + an additional argument, but
1906+ * we didn't want to complicate the existing code hence this is static.
19121907 */
1913- int cram_compress_block2 (cram_fd * fd , cram_slice * s ,
1914- cram_block * b , cram_metrics * metrics ,
1915- int method , int level ) {
1908+ static int cram_compress_block3 (cram_fd * fd , cram_slice * s ,
1909+ cram_block * b , cram_metrics * metrics ,
1910+ int method , int level ,
1911+ int recurse ) {
19161912
19171913 if (!b )
19181914 return 0 ;
19191915
1916+ int orig_method = method ;
19201917 char * comp = NULL ;
19211918 size_t comp_size = 0 ;
19221919 int strat ;
@@ -2249,8 +2246,23 @@ int cram_compress_block2(cram_fd *fd, cram_slice *s,
22492246 b -> content_id , & comp_size , method ,
22502247 method == GZIP_1 ? 1 : level ,
22512248 strat );
2252- if (!comp )
2249+ if (!comp ) {
2250+ // Our cached best method failed, but maybe another works?
2251+ // Rerun with trial mode engaged again.
2252+ if (!recurse ) {
2253+ hts_log_warning ("Compressed block ID %d method %s failed, "
2254+ "redoing trial" , b -> content_id ,
2255+ cram_block_method2str (method ));
2256+ pthread_mutex_lock (& fd -> metrics_lock );
2257+ metrics -> trial = NTRIALS ;
2258+ metrics -> next_trial = TRIAL_SPAN ;
2259+ metrics -> revised_method = orig_method ;
2260+ pthread_mutex_unlock (& fd -> metrics_lock );
2261+ return cram_compress_block3 (fd , s , b , metrics , method ,
2262+ level , 1 );
2263+ }
22532264 return -1 ;
2265+ }
22542266
22552267 if (comp_size < b -> uncomp_size ) {
22562268 free (b -> data );
@@ -2290,6 +2302,19 @@ int cram_compress_block2(cram_fd *fd, cram_slice *s,
22902302
22912303 return 0 ;
22922304}
2305+
2306+ /*
2307+ * Compresses a block using a selection of compression codecs and options.
2308+ * The best is learnt and used for subsequent slices, periodically resampling.
2309+ *
2310+ * Method and level -1 implies defaults, as specified in cram_fd.
2311+ */
2312+ int cram_compress_block2 (cram_fd * fd , cram_slice * s ,
2313+ cram_block * b , cram_metrics * metrics ,
2314+ int method , int level ) {
2315+ return cram_compress_block3 (fd , s , b , metrics , method , level , 0 );
2316+ }
2317+
22932318int cram_compress_block (cram_fd * fd , cram_block * b , cram_metrics * metrics ,
22942319 int method , int level ) {
22952320 return cram_compress_block2 (fd , NULL , b , metrics , method , level );
0 commit comments