diff options
author | josh.macdonald <jmacd@users.noreply.github.com> | 2009-10-26 05:39:39 +0000 |
---|---|---|
committer | josh.macdonald <jmacd@users.noreply.github.com> | 2009-10-26 05:39:39 +0000 |
commit | ce816262e6dfa8cdea8849150a6dacab202989a5 (patch) | |
tree | d76309a9d6c68a48471a1d17aef5113ece29548f /xdelta3 | |
parent | d8237539476e01980ae977163cb078968bd071cc (diff) |
Fix xdelta3-main.h's lru[] implementation, new manual testing success.
Diffstat (limited to 'xdelta3')
-rw-r--r-- | xdelta3/xdelta3-main.h | 200 |
1 files changed, 124 insertions, 76 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index bfb9ba6..9a48af0 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -2824,7 +2824,6 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2824 | sfile->filename, source_size)); | 2824 | sfile->filename, source_size)); |
2825 | } | 2825 | } |
2826 | 2826 | ||
2827 | |||
2828 | source->name = sfile->filename; | 2827 | source->name = sfile->filename; |
2829 | source->ioh = sfile; | 2828 | source->ioh = sfile; |
2830 | source->curblkno = 0; | 2829 | source->curblkno = 0; |
@@ -2842,6 +2841,7 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2842 | 2841 | ||
2843 | lru_size = (option_srcwinsz + source->blksize - 1) / source->blksize; | 2842 | lru_size = (option_srcwinsz + source->blksize - 1) / source->blksize; |
2844 | lru_size = max(lru_size, 1U); | 2843 | lru_size = max(lru_size, 1U); |
2844 | IF_DEBUG1 (DP(RINT "[lru_size] == %d\n", lru_size)); | ||
2845 | option_srcwinsz = lru_size * source->blksize; | 2845 | option_srcwinsz = lru_size * source->blksize; |
2846 | 2846 | ||
2847 | if (option_verbose) | 2847 | if (option_verbose) |
@@ -2864,6 +2864,8 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2864 | sizebuf); | 2864 | sizebuf); |
2865 | } | 2865 | } |
2866 | 2866 | ||
2867 | XD3_ASSERT (lru == NULL); | ||
2868 | |||
2867 | if ((lru = (main_blklru*) | 2869 | if ((lru = (main_blklru*) |
2868 | main_malloc (sizeof (main_blklru) * lru_size)) == NULL) | 2870 | main_malloc (sizeof (main_blklru) * lru_size)) == NULL) |
2869 | { | 2871 | { |
@@ -2881,7 +2883,10 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd, | |||
2881 | goto error; | 2883 | goto error; |
2882 | } | 2884 | } |
2883 | 2885 | ||
2884 | main_blklru_list_push_back (& lru_free, & lru[i]); | 2886 | if (! do_not_lru) |
2887 | { | ||
2888 | main_blklru_list_push_back (& lru_free, & lru[i]); | ||
2889 | } | ||
2885 | } | 2890 | } |
2886 | 2891 | ||
2887 | if ((ret = main_getblk_func (stream, source, 0))) | 2892 | if ((ret = main_getblk_func (stream, source, 0))) |
@@ -2926,52 +2931,27 @@ main_get_winsize (main_file *ifile) { | |||
2926 | Source routines | 2931 | Source routines |
2927 | *******************************************************************/ | 2932 | *******************************************************************/ |
2928 | 2933 | ||
2929 | /* This is the callback for reading a block of source. This function | ||
2930 | * is blocking and it implements a small LRU. | ||
2931 | * | ||
2932 | * Note that it is possible for main_input() to handle getblk requests | ||
2933 | * in a non-blocking manner. If the callback is NULL then the caller | ||
2934 | * of xd3_*_input() must handle the XD3_GETSRCBLK return value and | ||
2935 | * fill the source in the same way. See xd3_getblk for details. To | ||
2936 | * see an example of non-blocking getblk, see xdelta-test.h. */ | ||
2937 | static int | 2934 | static int |
2938 | main_getblk_func (xd3_stream *stream, | 2935 | main_getblk_lru (xd3_source *source, xoff_t blkno, main_blklru** blrup, int *is_new) |
2939 | xd3_source *source, | ||
2940 | xoff_t blkno) | ||
2941 | { | 2936 | { |
2942 | int ret = 0; | 2937 | main_blklru *blru = NULL; |
2943 | xoff_t pos = blkno * source->blksize; | ||
2944 | main_file *sfile = (main_file*) source->ioh; | ||
2945 | main_blklru *blru = NULL; | ||
2946 | usize_t nread = 0; | ||
2947 | usize_t i; | 2938 | usize_t i; |
2948 | 2939 | ||
2949 | // TODO! The skip logic has to fill cache, duh! | 2940 | (*is_new) = 0; |
2950 | |||
2951 | if (allow_fake_source) | ||
2952 | { | ||
2953 | source->curblkno = blkno; | ||
2954 | source->onblk = 0; | ||
2955 | source->curblk = lru[0].blk; | ||
2956 | lru[0].size = 0; | ||
2957 | return 0; | ||
2958 | } | ||
2959 | 2941 | ||
2960 | if (do_not_lru) | 2942 | if (do_not_lru) |
2961 | { | 2943 | { |
2962 | /* Direct lookup assumes sequential scan w/o skipping blocks. */ | 2944 | /* Direct lookup assumes sequential scan w/o skipping blocks. */ |
2963 | int idx = blkno % lru_size; | 2945 | int idx = blkno % lru_size; |
2964 | if (lru[idx].blkno == blkno) | 2946 | blru = & lru[idx]; |
2947 | if (blru->blkno == blkno) | ||
2965 | { | 2948 | { |
2966 | source->curblkno = blkno; | 2949 | (*blrup) = blru; |
2967 | source->onblk = lru[idx].size; | ||
2968 | source->curblk = lru[idx].blk; | ||
2969 | lru_hits += 1; | ||
2970 | return 0; | 2950 | return 0; |
2971 | } | 2951 | } |
2972 | 2952 | ||
2973 | if (lru[idx].blkno != (xoff_t)-1 && | 2953 | if (blru->blkno != (xoff_t)-1 && |
2974 | lru[idx].blkno != (xoff_t)(blkno - lru_size)) | 2954 | blru->blkno != (xoff_t)(blkno - lru_size)) |
2975 | { | 2955 | { |
2976 | return XD3_TOOFARBACK; | 2956 | return XD3_TOOFARBACK; |
2977 | } | 2957 | } |
@@ -2981,40 +2961,89 @@ main_getblk_func (xd3_stream *stream, | |||
2981 | /* Sequential search through LRU. */ | 2961 | /* Sequential search through LRU. */ |
2982 | for (i = 0; i < lru_size; i += 1) | 2962 | for (i = 0; i < lru_size; i += 1) |
2983 | { | 2963 | { |
2984 | if (lru[i].blkno == blkno) | 2964 | blru = & lru[i]; |
2965 | if (blru->blkno == blkno) | ||
2985 | { | 2966 | { |
2986 | main_blklru_list_remove (& lru[i]); | 2967 | main_blklru_list_remove (blru); |
2987 | main_blklru_list_push_back (& lru_list, & lru[i]); | 2968 | main_blklru_list_push_back (& lru_list, blru); |
2988 | 2969 | (*blrup) = blru; | |
2989 | source->curblkno = blkno; | ||
2990 | source->onblk = lru[i].size; | ||
2991 | source->curblk = lru[i].blk; | ||
2992 | lru_hits += 1; | ||
2993 | return 0; | 2970 | return 0; |
2994 | } | 2971 | } |
2995 | } | 2972 | } |
2996 | } | 2973 | } |
2997 | 2974 | ||
2998 | if (! main_blklru_list_empty (& lru_free)) | 2975 | if (do_not_lru) |
2999 | { | 2976 | { |
3000 | blru = main_blklru_list_pop_front (& lru_free); | 2977 | int idx = blkno % lru_size; |
2978 | blru = & lru[idx]; | ||
3001 | } | 2979 | } |
3002 | else if (! main_blklru_list_empty (& lru_list)) | 2980 | else |
3003 | { | 2981 | { |
3004 | if (do_not_lru) { | 2982 | if (! main_blklru_list_empty (& lru_free)) |
3005 | blru = & lru[blkno % lru_size]; | 2983 | { |
3006 | main_blklru_list_remove(blru); | 2984 | blru = main_blklru_list_pop_front (& lru_free); |
3007 | } else { | 2985 | main_blklru_list_push_back (& lru_list, blru); |
3008 | blru = main_blklru_list_pop_front (& lru_list); | 2986 | } |
3009 | } | 2987 | else |
3010 | lru_misses += 1; | 2988 | { |
2989 | blru = main_blklru_list_pop_front (& lru_list); | ||
2990 | main_blklru_list_push_back (& lru_list, blru); | ||
2991 | } | ||
3011 | } | 2992 | } |
3012 | else | 2993 | |
2994 | lru_filled += 1; | ||
2995 | (*is_new) = 1; | ||
2996 | (*blrup) = blru; | ||
2997 | blru->blkno = blkno; | ||
2998 | IF_DEBUG1 (DP(RINT "new lru blkno == %"Q"u (lru_size=%u)\n", | ||
2999 | blru->blkno, lru_size)); | ||
3000 | return 0; | ||
3001 | } | ||
3002 | |||
3003 | /* This is the callback for reading a block of source. This function | ||
3004 | * is blocking and it implements a small LRU. | ||
3005 | * | ||
3006 | * Note that it is possible for main_input() to handle getblk requests | ||
3007 | * in a non-blocking manner. If the callback is NULL then the caller | ||
3008 | * of xd3_*_input() must handle the XD3_GETSRCBLK return value and | ||
3009 | * fill the source in the same way. See xd3_getblk for details. To | ||
3010 | * see an example of non-blocking getblk, see xdelta-test.h. */ | ||
3011 | static int | ||
3012 | main_getblk_func (xd3_stream *stream, | ||
3013 | xd3_source *source, | ||
3014 | xoff_t blkno) | ||
3015 | { | ||
3016 | int ret = 0; | ||
3017 | xoff_t pos = blkno * source->blksize; | ||
3018 | main_file *sfile = (main_file*) source->ioh; | ||
3019 | main_blklru *blru; | ||
3020 | int is_new; | ||
3021 | usize_t nread = 0; | ||
3022 | |||
3023 | if (allow_fake_source) | ||
3024 | { | ||
3025 | source->curblkno = blkno; | ||
3026 | source->onblk = 0; | ||
3027 | source->curblk = lru[0].blk; | ||
3028 | lru[0].size = 0; | ||
3029 | return 0; | ||
3030 | } | ||
3031 | |||
3032 | if ((ret = main_getblk_lru (source, blkno, & blru, & is_new))) | ||
3013 | { | 3033 | { |
3014 | XD3_ASSERT(0); | 3034 | return ret; |
3015 | } | 3035 | } |
3016 | 3036 | ||
3017 | lru_filled += 1; | 3037 | if (!is_new) |
3038 | { | ||
3039 | source->curblkno = blkno; | ||
3040 | source->onblk = blru->size; | ||
3041 | source->curblk = blru->blk; | ||
3042 | lru_hits++; | ||
3043 | return 0; | ||
3044 | } | ||
3045 | |||
3046 | lru_misses += 1; | ||
3018 | 3047 | ||
3019 | if (pos != sfile->source_position) | 3048 | if (pos != sfile->source_position) |
3020 | { | 3049 | { |
@@ -3026,35 +3055,51 @@ main_getblk_func (xd3_stream *stream, | |||
3026 | ret = main_file_seek (sfile, pos); | 3055 | ret = main_file_seek (sfile, pos); |
3027 | } | 3056 | } |
3028 | 3057 | ||
3029 | if (ret != 0 || sfile->seek_failed) | 3058 | if (sfile->seek_failed || ret != 0) |
3030 | { | 3059 | { |
3060 | if (!sfile->seek_failed && option_verbose) | ||
3061 | { | ||
3062 | XPR(NT "unseekable source: skipping past unused input\n"); | ||
3063 | } | ||
3064 | |||
3031 | sfile->seek_failed = 1; | 3065 | sfile->seek_failed = 1; |
3032 | 3066 | ||
3033 | /* For an unseekable file (or other seek error, does it | 3067 | /* For an unseekable file (or other seek error, does it |
3034 | * matter?) */ | 3068 | * matter?) */ |
3035 | if (sfile->source_position > pos) | 3069 | if (sfile->source_position > pos) |
3036 | { | 3070 | { |
3037 | /* Could assert !IS_ENCODE(), this shouldn't happen | 3071 | /* Could assert !IS_ENCODE(), this shouldn't happen |
3038 | * because of do_not_lru during encode. */ | 3072 | * because of do_not_lru during encode. */ |
3039 | IF_DEBUG1 (DP(RINT "cannot seek backwards\n")); | 3073 | IF_DEBUG1 (DP(RINT "[getblk] cannot seek backwards blkno %"Q"u (do_not_lru %d)\n", |
3074 | blkno, do_not_lru)); | ||
3040 | stream->msg = "non-seekable source: copy is too far back (try raising -B)"; | 3075 | stream->msg = "non-seekable source: copy is too far back (try raising -B)"; |
3041 | return XD3_TOOFARBACK; | 3076 | return XD3_TOOFARBACK; |
3042 | } | 3077 | } |
3043 | 3078 | ||
3044 | if (option_verbose && | 3079 | IF_DEBUG1 (DP(RINT "[getblk] skip %"Q"u starting at %"Q"u\n", |
3045 | sfile->source_position == 0 && | 3080 | pos - sfile->source_position, |
3046 | !sfile->seek_failed) | 3081 | sfile->source_position)); |
3047 | { | ||
3048 | XPR(NT "unseekable source: skipping past unused input\n"); | ||
3049 | } | ||
3050 | 3082 | ||
3051 | while (sfile->source_position < pos) | 3083 | while (sfile->source_position < pos) |
3052 | { | 3084 | { |
3085 | xoff_t skip_blkno; | ||
3086 | usize_t skip_offset; | ||
3087 | |||
3088 | xd3_blksize_div (sfile->source_position, source, &skip_blkno, &skip_offset); | ||
3089 | |||
3053 | /* Read past unused data */ | 3090 | /* Read past unused data */ |
3054 | XD3_ASSERT (pos - sfile->source_position >= source->blksize); | 3091 | XD3_ASSERT (pos - sfile->source_position >= source->blksize); |
3092 | XD3_ASSERT (skip_offset == 0); | ||
3093 | |||
3094 | if ((ret = main_getblk_lru (source, skip_blkno, & blru, & is_new))) | ||
3095 | { | ||
3096 | return ret; | ||
3097 | } | ||
3098 | |||
3099 | XD3_ASSERT (is_new); | ||
3055 | 3100 | ||
3056 | if ((ret = main_read_primary_input (sfile, | 3101 | if ((ret = main_read_primary_input (sfile, |
3057 | (uint8_t*) blru->blk, | 3102 | (uint8_t*) blru->blk, |
3058 | source->blksize, | 3103 | source->blksize, |
3059 | & nread, | 3104 | & nread, |
3060 | 1 /* source */))) | 3105 | 1 /* source */))) |
@@ -3062,20 +3107,19 @@ main_getblk_func (xd3_stream *stream, | |||
3062 | return ret; | 3107 | return ret; |
3063 | } | 3108 | } |
3064 | 3109 | ||
3065 | sfile->source_position += nread; | ||
3066 | |||
3067 | if (option_verbose > 1) | ||
3068 | { | ||
3069 | XPR(NT "skip 1 source block\n"); | ||
3070 | } | ||
3071 | |||
3072 | if (nread != source->blksize) | 3110 | if (nread != source->blksize) |
3073 | { | 3111 | { |
3074 | IF_DEBUG1 (DP(RINT "short skip block nread = %u\n", nread)); | 3112 | IF_DEBUG1 (DP(RINT "[getblk] short skip block nread = %u\n", nread)); |
3075 | stream->msg = "non-seekable input is short"; | 3113 | stream->msg = "non-seekable input is short"; |
3076 | return XD3_INVALID_INPUT; | 3114 | return XD3_INVALID_INPUT; |
3077 | } | 3115 | } |
3078 | 3116 | ||
3117 | sfile->source_position += nread; | ||
3118 | blru->size = nread; | ||
3119 | |||
3120 | IF_DEBUG1 (DP(RINT "[getblk] skip blkno %"Q"u {%"Q"u} size %u\n", | ||
3121 | skip_blkno, blru->blkno, blru->size)); | ||
3122 | |||
3079 | XD3_ASSERT (sfile->source_position <= pos); | 3123 | XD3_ASSERT (sfile->source_position <= pos); |
3080 | } | 3124 | } |
3081 | } | 3125 | } |
@@ -3083,6 +3127,11 @@ main_getblk_func (xd3_stream *stream, | |||
3083 | 3127 | ||
3084 | XD3_ASSERT (sfile->source_position == pos); | 3128 | XD3_ASSERT (sfile->source_position == pos); |
3085 | 3129 | ||
3130 | if ((ret = main_getblk_lru (source, blkno, & blru, & is_new))) | ||
3131 | { | ||
3132 | return ret; | ||
3133 | } | ||
3134 | |||
3086 | if ((ret = main_read_primary_input (sfile, | 3135 | if ((ret = main_read_primary_input (sfile, |
3087 | (uint8_t*) blru->blk, | 3136 | (uint8_t*) blru->blk, |
3088 | source->blksize, | 3137 | source->blksize, |
@@ -3112,13 +3161,12 @@ main_getblk_func (xd3_stream *stream, | |||
3112 | } | 3161 | } |
3113 | } | 3162 | } |
3114 | 3163 | ||
3115 | blru->blkno = blkno; | ||
3116 | source->curblk = blru->blk; | 3164 | source->curblk = blru->blk; |
3117 | source->curblkno = blkno; | 3165 | source->curblkno = blkno; |
3118 | source->onblk = nread; | 3166 | source->onblk = nread; |
3119 | blru->size = nread; | 3167 | blru->size = nread; |
3120 | 3168 | ||
3121 | IF_DEBUG1 (DP(RINT "[main_getblk] blkno %"Q"u onblk %u srcpos %"Q"u\n", | 3169 | IF_DEBUG1 (DP(RINT "[main_getblk] blkno %"Q"u onblk %u pos %"Q"u sfile->source_position %"Q"u\n", |
3122 | blkno, nread, pos, sfile->source_position)); | 3170 | blkno, nread, pos, sfile->source_position)); |
3123 | 3171 | ||
3124 | return 0; | 3172 | return 0; |