diff options
Diffstat (limited to 'xdelta3/xdelta3-main.h')
-rw-r--r-- | xdelta3/xdelta3-main.h | 255 |
1 files changed, 151 insertions, 104 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index 7fa0901..b33b26a 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -339,7 +339,7 @@ static usize_t lru_size = 0; | |||
339 | static main_blklru *lru = NULL; /* array of lru_size elts */ | 339 | static main_blklru *lru = NULL; /* array of lru_size elts */ |
340 | static main_blklru_list lru_list; | 340 | static main_blklru_list lru_list; |
341 | static main_blklru_list lru_free; | 341 | static main_blklru_list lru_free; |
342 | static int do_not_lru = 0; /* set to avoid lru */ | 342 | static int do_src_fifo = 0; /* set to avoid lru */ |
343 | 343 | ||
344 | static int lru_hits = 0; | 344 | static int lru_hits = 0; |
345 | static int lru_misses = 0; | 345 | static int lru_misses = 0; |
@@ -452,7 +452,7 @@ reset_defaults(void) | |||
452 | main_bsize = 0; | 452 | main_bsize = 0; |
453 | lru_size = 0; | 453 | lru_size = 0; |
454 | lru = NULL; | 454 | lru = NULL; |
455 | do_not_lru = 0; | 455 | do_src_fifo = 0; |
456 | lru_hits = 0; | 456 | lru_hits = 0; |
457 | lru_misses = 0; | 457 | lru_misses = 0; |
458 | lru_filled = 0; | 458 | lru_filled = 0; |
@@ -1032,7 +1032,7 @@ main_file_read (main_file *ifile, | |||
1032 | } | 1032 | } |
1033 | else | 1033 | else |
1034 | { | 1034 | { |
1035 | if (option_verbose > 3) { XPR(NT "read %s: %u bytes\n", | 1035 | if (option_verbose > 4) { XPR(NT "read %s: %u bytes\n", |
1036 | ifile->filename, (*nread)); } | 1036 | ifile->filename, (*nread)); } |
1037 | ifile->nread += (*nread); | 1037 | ifile->nread += (*nread); |
1038 | } | 1038 | } |
@@ -1923,7 +1923,8 @@ main_merge_output (xd3_stream *stream, main_file *ofile) | |||
1923 | (stream->dec_win_ind & VCD_ADLER32) != 0) | 1923 | (stream->dec_win_ind & VCD_ADLER32) != 0) |
1924 | { | 1924 | { |
1925 | recode_stream->flags |= XD3_ADLER32_RECODE; | 1925 | recode_stream->flags |= XD3_ADLER32_RECODE; |
1926 | recode_stream->recode_adler32 = stream->whole_target.wininfo[window_num].adler32; | 1926 | recode_stream->recode_adler32 = |
1927 | stream->whole_target.wininfo[window_num].adler32; | ||
1927 | } | 1928 | } |
1928 | 1929 | ||
1929 | window_num++; | 1930 | window_num++; |
@@ -2880,11 +2881,18 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2880 | * size_known can still change (due to secondary | 2881 | * size_known can still change (due to secondary |
2881 | * decompression). Calls main_decompress_input_check() via | 2882 | * decompression). Calls main_decompress_input_check() via |
2882 | * main_read_primary_input(). */ | 2883 | * main_read_primary_input(). */ |
2884 | /* TODO(jmacd): This is a huge hack! Fix me. */ | ||
2883 | lru_size = 1; | 2885 | lru_size = 1; |
2884 | lru = &block0; | 2886 | lru = &block0; |
2887 | XD3_ASSERT (main_blklru_list_empty (& lru_free)); | ||
2888 | XD3_ASSERT (main_blklru_list_empty (& lru_list)); | ||
2885 | main_blklru_list_push_back (& lru_free, & lru[0]); | 2889 | main_blklru_list_push_back (& lru_free, & lru[0]); |
2886 | ret = main_getblk_func (stream, source, 0); | 2890 | ret = main_getblk_func (stream, source, 0); |
2887 | main_blklru_list_remove (& lru[0]); | 2891 | main_blklru_list_remove (& lru[0]); |
2892 | /* TODO(jmacd): In particular, not sure if these assertions | ||
2893 | * are valid when ret != 0. */ | ||
2894 | XD3_ASSERT (main_blklru_list_empty (& lru_free)); | ||
2895 | XD3_ASSERT (main_blklru_list_empty (& lru_list)); | ||
2888 | lru = NULL; | 2896 | lru = NULL; |
2889 | 2897 | ||
2890 | if (ret != 0) | 2898 | if (ret != 0) |
@@ -2923,7 +2931,8 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2923 | 2931 | ||
2924 | XD3_ASSERT (lru_size >= 1); | 2932 | XD3_ASSERT (lru_size >= 1); |
2925 | 2933 | ||
2926 | if ((lru = (main_blklru*) main_malloc (lru_size * sizeof (main_blklru))) == NULL) | 2934 | if ((lru = (main_blklru*) main_malloc (lru_size * sizeof (main_blklru))) |
2935 | == NULL) | ||
2927 | { | 2936 | { |
2928 | ret = ENOMEM; | 2937 | ret = ENOMEM; |
2929 | return ret; | 2938 | return ret; |
@@ -2935,9 +2944,9 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2935 | 2944 | ||
2936 | if (! sfile->size_known) | 2945 | if (! sfile->size_known) |
2937 | { | 2946 | { |
2938 | do_not_lru = 1; | 2947 | do_src_fifo = 1; |
2939 | } | 2948 | } |
2940 | else if (! do_not_lru) | 2949 | else if (! do_src_fifo) |
2941 | { | 2950 | { |
2942 | main_blklru_list_push_back (& lru_list, & lru[0]); | 2951 | main_blklru_list_push_back (& lru_list, & lru[0]); |
2943 | } | 2952 | } |
@@ -2952,7 +2961,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2952 | return ret; | 2961 | return ret; |
2953 | } | 2962 | } |
2954 | 2963 | ||
2955 | if (do_not_lru == 0) | 2964 | if (! do_src_fifo) |
2956 | { | 2965 | { |
2957 | main_blklru_list_push_back (& lru_free, & lru[i]); | 2966 | main_blklru_list_push_back (& lru_free, & lru[i]); |
2958 | } | 2967 | } |
@@ -3008,7 +3017,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
3008 | main_format_bcnt (blksize, blkszbuf), | 3017 | main_format_bcnt (blksize, blkszbuf), |
3009 | main_format_bcnt (option_srcwinsz, winszbuf), | 3018 | main_format_bcnt (option_srcwinsz, winszbuf), |
3010 | nbufs, | 3019 | nbufs, |
3011 | do_not_lru ? " (FIFO)" : ""); | 3020 | do_src_fifo ? " (FIFO)" : ""); |
3012 | } | 3021 | } |
3013 | 3022 | ||
3014 | return 0; | 3023 | return 0; |
@@ -3042,14 +3051,15 @@ main_get_winsize (main_file *ifile) { | |||
3042 | *******************************************************************/ | 3051 | *******************************************************************/ |
3043 | 3052 | ||
3044 | static int | 3053 | static int |
3045 | main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_new) | 3054 | main_getblk_lru (xd3_source *source, xoff_t blkno, |
3055 | main_blklru** blrup, int *is_new) | ||
3046 | { | 3056 | { |
3047 | main_blklru *blru = NULL; | 3057 | main_blklru *blru = NULL; |
3048 | usize_t i; | 3058 | usize_t i; |
3049 | 3059 | ||
3050 | (*is_new) = 0; | 3060 | (*is_new) = 0; |
3051 | 3061 | ||
3052 | if (do_not_lru) | 3062 | if (do_src_fifo) |
3053 | { | 3063 | { |
3054 | /* Direct lookup assumes sequential scan w/o skipping blocks. */ | 3064 | /* Direct lookup assumes sequential scan w/o skipping blocks. */ |
3055 | int idx = blkno % lru_size; | 3065 | int idx = blkno % lru_size; |
@@ -3082,7 +3092,7 @@ main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_ | |||
3082 | } | 3092 | } |
3083 | } | 3093 | } |
3084 | 3094 | ||
3085 | if (do_not_lru) | 3095 | if (do_src_fifo) |
3086 | { | 3096 | { |
3087 | int idx = blkno % lru_size; | 3097 | int idx = blkno % lru_size; |
3088 | blru = & lru[idx]; | 3098 | blru = & lru[idx]; |
@@ -3096,6 +3106,7 @@ main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_ | |||
3096 | } | 3106 | } |
3097 | else | 3107 | else |
3098 | { | 3108 | { |
3109 | XD3_ASSERT (! main_blklru_list_empty (& lru_list)); | ||
3099 | blru = main_blklru_list_pop_front (& lru_list); | 3110 | blru = main_blklru_list_pop_front (& lru_list); |
3100 | main_blklru_list_push_back (& lru_list, blru); | 3111 | main_blklru_list_push_back (& lru_list, blru); |
3101 | } | 3112 | } |
@@ -3108,6 +3119,110 @@ main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_ | |||
3108 | return 0; | 3119 | return 0; |
3109 | } | 3120 | } |
3110 | 3121 | ||
3122 | static int | ||
3123 | main_read_seek_source (xd3_stream *stream, | ||
3124 | xd3_source *source, | ||
3125 | xoff_t blkno) { | ||
3126 | xoff_t pos = blkno * source->blksize; | ||
3127 | main_file *sfile = (main_file*) source->ioh; | ||
3128 | main_blklru *blru; | ||
3129 | int is_new; | ||
3130 | usize_t nread = 0; | ||
3131 | int ret = 0; | ||
3132 | |||
3133 | if (!sfile->seek_failed) | ||
3134 | { | ||
3135 | ret = main_file_seek (sfile, pos); | ||
3136 | |||
3137 | if (ret == 0) | ||
3138 | { | ||
3139 | sfile->source_position = pos; | ||
3140 | } | ||
3141 | } | ||
3142 | |||
3143 | /* There's a chance here, that an genuine lseek error will cause | ||
3144 | * xdelta3 to shift into non-seekable mode, entering a degraded | ||
3145 | * condition. */ | ||
3146 | if (sfile->seek_failed || ret != 0) | ||
3147 | { | ||
3148 | /* For an unseekable file (or other seek error, does it | ||
3149 | * matter?) */ | ||
3150 | if (sfile->source_position > pos) | ||
3151 | { | ||
3152 | /* Could assert !IS_ENCODE(), this shouldn't happen | ||
3153 | * because of do_src_fifo during encode. */ | ||
3154 | if (option_verbose) | ||
3155 | { | ||
3156 | XPR(NT "source can't seek backwards; requested block offset " | ||
3157 | "%"Q"u source position is %"Q"u\n", | ||
3158 | pos, sfile->source_position); | ||
3159 | } | ||
3160 | |||
3161 | sfile->seek_failed = 1; | ||
3162 | stream->msg = "non-seekable source: " | ||
3163 | "copy is too far back (try raising -B)"; | ||
3164 | return XD3_TOOFARBACK; | ||
3165 | } | ||
3166 | |||
3167 | if (option_verbose > 2 || (option_verbose > 1 && !sfile->seek_failed)) | ||
3168 | { | ||
3169 | XPR(NT "non-seekable source skipping %"Q"u bytes @ %"Q"u\n", | ||
3170 | pos - sfile->source_position, | ||
3171 | sfile->source_position); | ||
3172 | } | ||
3173 | |||
3174 | sfile->seek_failed = 1; | ||
3175 | |||
3176 | while (sfile->source_position < pos) | ||
3177 | { | ||
3178 | xoff_t skip_blkno; | ||
3179 | usize_t skip_offset; | ||
3180 | |||
3181 | xd3_blksize_div (sfile->source_position, source, | ||
3182 | &skip_blkno, &skip_offset); | ||
3183 | |||
3184 | /* Read past unused data */ | ||
3185 | XD3_ASSERT (pos - sfile->source_position >= source->blksize); | ||
3186 | XD3_ASSERT (skip_offset == 0); | ||
3187 | |||
3188 | if ((ret = main_getblk_lru (source, skip_blkno, | ||
3189 | & blru, & is_new))) | ||
3190 | { | ||
3191 | return ret; | ||
3192 | } | ||
3193 | |||
3194 | XD3_ASSERT (is_new); | ||
3195 | |||
3196 | if ((ret = main_read_primary_input (sfile, | ||
3197 | (uint8_t*) blru->blk, | ||
3198 | source->blksize, | ||
3199 | & nread, | ||
3200 | 1 /* source */))) | ||
3201 | { | ||
3202 | return ret; | ||
3203 | } | ||
3204 | |||
3205 | if (nread != source->blksize) | ||
3206 | { | ||
3207 | IF_DEBUG1 (DP(RINT "[getblk] short skip block nread = %u\n", | ||
3208 | nread)); | ||
3209 | stream->msg = "non-seekable input is short"; | ||
3210 | return XD3_INVALID_INPUT; | ||
3211 | } | ||
3212 | |||
3213 | sfile->source_position += nread; | ||
3214 | blru->size = nread; | ||
3215 | |||
3216 | IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u {%"Q"u} size %u\n", | ||
3217 | skip_blkno, blru->blkno, blru->size)); | ||
3218 | |||
3219 | XD3_ASSERT (sfile->source_position <= pos); | ||
3220 | } | ||
3221 | } | ||
3222 | |||
3223 | return 0; | ||
3224 | } | ||
3225 | |||
3111 | /* This is the callback for reading a block of source. This function | 3226 | /* This is the callback for reading a block of source. This function |
3112 | * is blocking and it implements a small LRU. | 3227 | * is blocking and it implements a small LRU. |
3113 | * | 3228 | * |
@@ -3126,6 +3241,7 @@ main_getblk_func (xd3_stream *stream, | |||
3126 | main_file *sfile = (main_file*) source->ioh; | 3241 | main_file *sfile = (main_file*) source->ioh; |
3127 | main_blklru *blru; | 3242 | main_blklru *blru; |
3128 | int is_new; | 3243 | int is_new; |
3244 | int did_seek = 0; | ||
3129 | usize_t nread = 0; | 3245 | usize_t nread = 0; |
3130 | 3246 | ||
3131 | if (allow_fake_source) | 3247 | if (allow_fake_source) |
@@ -3158,97 +3274,20 @@ main_getblk_func (xd3_stream *stream, | |||
3158 | /* Only try to seek when the position is wrong. This means the | 3274 | /* Only try to seek when the position is wrong. This means the |
3159 | * decoder will fail when the source buffer is too small, but | 3275 | * decoder will fail when the source buffer is too small, but |
3160 | * only when the input is non-seekable. */ | 3276 | * only when the input is non-seekable. */ |
3161 | if (!sfile->seek_failed) | 3277 | if ((ret = main_read_seek_source (stream, source, blkno))) |
3162 | { | 3278 | { |
3163 | ret = main_file_seek (sfile, pos); | 3279 | return ret; |
3164 | |||
3165 | if (ret == 0) | ||
3166 | { | ||
3167 | sfile->source_position = pos; | ||
3168 | } | ||
3169 | } | 3280 | } |
3170 | 3281 | ||
3171 | /* There's a chance here, that an genuine lseek error will cause | 3282 | /* Indicates that another call to main_getblk_lru() may be |
3172 | * xdelta3 to shift into non-seekable mode, entering a degraded | 3283 | * needed */ |
3173 | * condition. */ | 3284 | did_seek = 1; |
3174 | if (sfile->seek_failed || ret != 0) | ||
3175 | { | ||
3176 | /* For an unseekable file (or other seek error, does it | ||
3177 | * matter?) */ | ||
3178 | if (sfile->source_position > pos) | ||
3179 | { | ||
3180 | /* Could assert !IS_ENCODE(), this shouldn't happen | ||
3181 | * because of do_not_lru during encode. */ | ||
3182 | if (option_verbose) | ||
3183 | { | ||
3184 | XPR(NT "source can't seek backwards; requested block offset " | ||
3185 | "%"Q"u source position is %"Q"u\n", | ||
3186 | pos, sfile->source_position); | ||
3187 | } | ||
3188 | |||
3189 | sfile->seek_failed = 1; | ||
3190 | stream->msg = "non-seekable source: " | ||
3191 | "copy is too far back (try raising -B)"; | ||
3192 | return XD3_TOOFARBACK; | ||
3193 | } | ||
3194 | |||
3195 | if (option_verbose > 2 || (option_verbose > 1 && !sfile->seek_failed)) | ||
3196 | { | ||
3197 | XPR(NT "non-seekable source skipping %"Q"u bytes @ %"Q"u\n", | ||
3198 | pos - sfile->source_position, | ||
3199 | sfile->source_position); | ||
3200 | } | ||
3201 | |||
3202 | sfile->seek_failed = 1; | ||
3203 | |||
3204 | while (sfile->source_position < pos) | ||
3205 | { | ||
3206 | xoff_t skip_blkno; | ||
3207 | usize_t skip_offset; | ||
3208 | |||
3209 | xd3_blksize_div (sfile->source_position, source, &skip_blkno, &skip_offset); | ||
3210 | |||
3211 | /* Read past unused data */ | ||
3212 | XD3_ASSERT (pos - sfile->source_position >= source->blksize); | ||
3213 | XD3_ASSERT (skip_offset == 0); | ||
3214 | |||
3215 | if ((ret = main_getblk_lru (source, skip_blkno, & blru, & is_new))) | ||
3216 | { | ||
3217 | return ret; | ||
3218 | } | ||
3219 | |||
3220 | XD3_ASSERT (is_new); | ||
3221 | |||
3222 | if ((ret = main_read_primary_input (sfile, | ||
3223 | (uint8_t*) blru->blk, | ||
3224 | source->blksize, | ||
3225 | & nread, | ||
3226 | 1 /* source */))) | ||
3227 | { | ||
3228 | return ret; | ||
3229 | } | ||
3230 | |||
3231 | if (nread != source->blksize) | ||
3232 | { | ||
3233 | IF_DEBUG1 (DP(RINT "[getblk] short skip block nread = %u\n", nread)); | ||
3234 | stream->msg = "non-seekable input is short"; | ||
3235 | return XD3_INVALID_INPUT; | ||
3236 | } | ||
3237 | |||
3238 | sfile->source_position += nread; | ||
3239 | blru->size = nread; | ||
3240 | |||
3241 | IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u {%"Q"u} size %u\n", | ||
3242 | skip_blkno, blru->blkno, blru->size)); | ||
3243 | |||
3244 | XD3_ASSERT (sfile->source_position <= pos); | ||
3245 | } | ||
3246 | } | ||
3247 | } | 3285 | } |
3248 | 3286 | ||
3249 | XD3_ASSERT (sfile->source_position == pos); | 3287 | XD3_ASSERT (sfile->source_position == pos); |
3250 | 3288 | ||
3251 | if ((ret = main_getblk_lru (source, blkno, & blru, & is_new))) | 3289 | if (did_seek && |
3290 | (ret = main_getblk_lru (source, blkno, & blru, & is_new))) | ||
3252 | { | 3291 | { |
3253 | return ret; | 3292 | return ret; |
3254 | } | 3293 | } |
@@ -3265,15 +3304,22 @@ main_getblk_func (xd3_stream *stream, | |||
3265 | /* Save the last block read, used to handle non-seekable files. */ | 3304 | /* Save the last block read, used to handle non-seekable files. */ |
3266 | sfile->source_position = pos + nread; | 3305 | sfile->source_position = pos + nread; |
3267 | 3306 | ||
3268 | main_blklru_list_push_back (& lru_list, blru); | ||
3269 | |||
3270 | if (option_verbose > 3) | 3307 | if (option_verbose > 3) |
3271 | { | 3308 | { |
3272 | if (blru->blkno != (xoff_t)-1) | 3309 | if (blru->blkno != (xoff_t)-1) |
3273 | { | 3310 | { |
3274 | XPR(NT "source block %"Q"u ejects %"Q"u (lru_hits=%u, " | 3311 | if (blru->blkno != blkno) |
3275 | "lru_misses=%u, lru_filled=%u)\n", | 3312 | { |
3276 | blkno, blru->blkno, lru_hits, lru_misses, lru_filled); | 3313 | XPR(NT "source block %"Q"u ejects %"Q"u (lru_hits=%u, " |
3314 | "lru_misses=%u, lru_filled=%u)\n", | ||
3315 | blkno, blru->blkno, lru_hits, lru_misses, lru_filled); | ||
3316 | } | ||
3317 | else | ||
3318 | { | ||
3319 | XPR(NT "source block %"Q"u read (lru_hits=%u, " | ||
3320 | "lru_misses=%u, lru_filled=%u)\n", | ||
3321 | blkno, lru_hits, lru_misses, lru_filled); | ||
3322 | } | ||
3277 | } | 3323 | } |
3278 | else | 3324 | else |
3279 | { | 3325 | { |
@@ -3287,7 +3333,8 @@ main_getblk_func (xd3_stream *stream, | |||
3287 | source->onblk = nread; | 3333 | source->onblk = nread; |
3288 | blru->size = nread; | 3334 | blru->size = nread; |
3289 | 3335 | ||
3290 | IF_DEBUG1 (DP(RINT "[main_getblk] blkno %"Q"u onblk %u pos %"Q"u srcpos %"Q"u\n", | 3336 | IF_DEBUG1 (DP(RINT "[main_getblk] blkno %"Q"u onblk %u pos %"Q"u " |
3337 | "srcpos %"Q"u\n", | ||
3291 | blkno, nread, pos, sfile->source_position)); | 3338 | blkno, nread, pos, sfile->source_position)); |
3292 | 3339 | ||
3293 | return 0; | 3340 | return 0; |
@@ -3331,7 +3378,7 @@ main_input (xd3_cmd cmd, | |||
3331 | config.iopt_size = option_iopt_size; | 3378 | config.iopt_size = option_iopt_size; |
3332 | config.sprevsz = option_sprevsz; | 3379 | config.sprevsz = option_sprevsz; |
3333 | 3380 | ||
3334 | do_not_lru = 0; | 3381 | do_src_fifo = 0; |
3335 | 3382 | ||
3336 | start_time = get_millisecs_now (); | 3383 | start_time = get_millisecs_now (); |
3337 | 3384 | ||
@@ -3371,7 +3418,7 @@ main_input (xd3_cmd cmd, | |||
3371 | 3418 | ||
3372 | #if XD3_ENCODER | 3419 | #if XD3_ENCODER |
3373 | case CMD_ENCODE: | 3420 | case CMD_ENCODE: |
3374 | do_not_lru = 1; | 3421 | do_src_fifo = 1; |
3375 | input_func = xd3_encode_input; | 3422 | input_func = xd3_encode_input; |
3376 | output_func = main_write_output; | 3423 | output_func = main_write_output; |
3377 | 3424 | ||