summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xdelta3/xdelta3-main.h200
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. */
2937static int 2934static int
2938main_getblk_func (xd3_stream *stream, 2935main_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. */
3011static int
3012main_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;