summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xdelta3/xdelta3-blkcache.h216
-rw-r--r--xdelta3/xdelta3-main.h2
2 files changed, 101 insertions, 117 deletions
diff --git a/xdelta3/xdelta3-blkcache.h b/xdelta3/xdelta3-blkcache.h
index d01322e..6fbb8dd 100644
--- a/xdelta3/xdelta3-blkcache.h
+++ b/xdelta3/xdelta3-blkcache.h
@@ -18,6 +18,9 @@
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 19 */
20 20
21/* TODO: This code is heavily revised from 3.0z but still needs major
22 * refactoring. */
23
21typedef struct _main_blklru main_blklru; 24typedef struct _main_blklru main_blklru;
22typedef struct _main_blklru_list main_blklru_list; 25typedef struct _main_blklru_list main_blklru_list;
23 26
@@ -35,8 +38,9 @@ struct _main_blklru
35 main_blklru_list link; 38 main_blklru_list link;
36}; 39};
37 40
38#define MAX_LRU_SIZE 32U 41/* TODO: The value for MAX_LRU_SIZE has what significance? */
39#define XD3_MINSRCWINSZ XD3_ALLOCSIZE 42#define MAX_LRU_SIZE 32U /* must be a power of 2 */
43#define XD3_MINSRCWINSZ (XD3_ALLOCSIZE * MAX_LRU_SIZE)
40 44
41XD3_MAKELIST(main_blklru_list,main_blklru,link); 45XD3_MAKELIST(main_blklru_list,main_blklru,link);
42 46
@@ -62,13 +66,9 @@ static void main_lru_reset()
62 66
63static void main_lru_cleanup() 67static void main_lru_cleanup()
64{ 68{
65 int i; 69 if (lru != NULL)
66 /* TODO(jmacd): HERE YOU ARE
67 * Remove this loop, free only lru[0].blk.
68 */
69 for (i = 0; lru && i < lru_size; i += 1)
70 { 70 {
71 main_free (lru[i].blk); 71 main_free (lru[0].blk);
72 } 72 }
73 73
74 main_free (lru); 74 main_free (lru);
@@ -90,112 +90,108 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd,
90 usize_t i; 90 usize_t i;
91 usize_t blksize; 91 usize_t blksize;
92 xoff_t source_size = 0; 92 xoff_t source_size = 0;
93 main_blklru block0;
94 93
95 XD3_ASSERT (lru == NULL); 94 XD3_ASSERT (lru == NULL);
96 XD3_ASSERT (stream->src == NULL); 95 XD3_ASSERT (stream->src == NULL);
97 XD3_ASSERT (option_srcwinsz >= XD3_MINSRCWINSZ); 96 XD3_ASSERT (option_srcwinsz >= XD3_MINSRCWINSZ);
98 97
98 /* TODO: this code needs refactoring into FIFO, LRU, FAKE. Yuck!
99 * This is simplified from 3.0z which had issues with sizing the
100 * source buffer memory allocation and the source blocksize. */
101
102 /* LRU-specific */
99 main_blklru_list_init (& lru_list); 103 main_blklru_list_init (& lru_list);
100 main_blklru_list_init (& lru_free); 104 main_blklru_list_init (& lru_free);
101 105
102 if (allow_fake_source) 106 if (allow_fake_source)
103 { 107 {
108 /* TOOLS-specific (e.g., "printdelta"). Note: Check
109 * "allow_fake_source" mode looks broken now. */
104 sfile->mode = XO_READ; 110 sfile->mode = XO_READ;
105 sfile->realname = sfile->filename; 111 sfile->realname = sfile->filename;
106 sfile->nread = 0; 112 sfile->nread = 0;
107 } 113 }
108 else 114 else
109 { 115 {
116 /* Either a regular file (possibly compressed) or a FIFO
117 * (possibly compressed). */
110 if ((ret = main_file_open (sfile, sfile->filename, XO_READ))) 118 if ((ret = main_file_open (sfile, sfile->filename, XO_READ)))
111 { 119 {
112 return ret; 120 return ret;
113 } 121 }
114 122
115 /* Allow non-seekable sources from the start. If the file 123 /* If the file is regular we know it's size. If the file turns
116 * turns out to be externally compressed, size_known may change. */ 124 * out to be externally compressed, size_known may change. */
117 sfile->size_known = (main_file_stat (sfile, &source_size) == 0); 125 sfile->size_known = (main_file_stat (sfile, &source_size) == 0);
118 } 126 }
119 127
120 /* The API requires power-of-two blocksize, */ 128 /* Note: The API requires a power-of-two blocksize and srcwinsz
121 blksize = xd3_pow2_roundup (max (option_srcwinsz / MAX_LRU_SIZE, 129 * (-B). The logic here will use a single block if the entire file
122 XD3_MINSRCWINSZ)); 130 * is known to fit into srcwinsz. */
123 131 option_srcwinsz = xd3_pow2_roundup (option_srcwinsz);
124 /* TODO(jmacd): The organization of this code and the implementation 132
125 * of the LRU cache could be improved. This is too convoluted, the 133 /* Though called "lru", it is not LRU-specific. We always allocate
126 * code uses main_getblk_func() to read the first block, which may 134 * a maximum number of source block buffers. If the entire file
127 * trigger external-decompression, in large part so that the 135 * fits into srcwinsz, this buffer will stay as the only
128 * verbose-printing and counters maintained by getblk_func are 136 * (lru_size==1) source block. Otherwise, we know that at least
129 * consistent. There used to be additional optimizations going on 137 * option_srcwinsz bytes are available. Split the source window
130 * here: (1) if the source size is known we would like to lower 138 * into buffers. */
131 * option_srcwinsz, if possible, (2) avoid allocating more memory 139 if ((lru = (main_blklru*) main_malloc (MAX_LRU_SIZE *
132 * than needed, and (3) also want to use a single block when 140 sizeof (main_blklru))) == NULL)
133 * source_size < option_srcwinsz, this because compression is better
134 * for larger blocks (especially due to the blockwise-reverse
135 * insertion of checksums).
136 *
137 * (3) is no longer implemented. (2) is only implemented for files
138 * that are shorter than the default blocksize, and (1) is not
139 * implemented. These optimizations are not taken because the code
140 * is already too complicated.
141 *
142 * The ideal solution may be to allocate a block of memory equal to
143 * half of the option_srcwinsz. Read as much data as possible into
144 * that block. If the entire file fits, pass one block to the
145 * library for best compression. If not, copy the 50% block into
146 * smaller (option_srcwinsz / MAX_LRU_SIZE) blocks and proceed. Too
147 * much effort for too little payback. */
148
149 memset (&block0, 0, sizeof (block0));
150 block0.blkno = (xoff_t) -1;
151
152 /* TODO(jmacd): HERE YOU ARE
153 * Allocate only one block of option_srcwinsz.
154 */
155 /* Allocate the first block. Even if the size is known at this
156 * point, we do not lower it because decompression may happen. */
157 if ((block0.blk = (uint8_t*) main_malloc (blksize)) == NULL)
158 { 141 {
159 ret = ENOMEM; 142 ret = ENOMEM;
160 return ret; 143 return ret;
161 } 144 }
162 145
163 source->blksize = blksize; 146 memset (lru, 0, sizeof(lru[0]) * MAX_LRU_SIZE);
164 source->name = sfile->filename; 147
165 source->ioh = sfile; 148 /* Allocate the entire buffer. */
166 source->curblkno = (xoff_t) -1; 149 if ((lru[0].blk = (uint8_t*) main_malloc (option_srcwinsz)) == NULL)
167 source->curblk = NULL; 150 {
151 ret = ENOMEM;
152 return ret;
153 }
168 154
169 /* We have to read the first block into the cache now, because 155 /* Main calls main_getblk_func() once before xd3_set_source(). This
170 * size_known can still change (due to secondary decompression). 156 * is the point at which external decompression may begin. Set the
171 * Calls main_secondary_decompress_check() via 157 * system for a single block. */
172 * main_read_primary_input(). */
173 lru_size = 1; 158 lru_size = 1;
174 lru = &block0; 159 lru[0].blkno = -1;
160 blksize = option_srcwinsz;
175 XD3_ASSERT (main_blklru_list_empty (& lru_free)); 161 XD3_ASSERT (main_blklru_list_empty (& lru_free));
176 XD3_ASSERT (main_blklru_list_empty (& lru_list)); 162 XD3_ASSERT (main_blklru_list_empty (& lru_list));
177 main_blklru_list_push_back (& lru_free, & lru[0]);
178 /* This call is partly so that the diagnostics printed by
179 * this function appear to happen normally for the first read,
180 * which is special. */
181 ret = main_getblk_func (stream, source, 0);
182 main_blklru_list_remove (& lru[0]);
183 XD3_ASSERT (main_blklru_list_empty (& lru_free));
184 XD3_ASSERT (main_blklru_list_empty (& lru_list));
185 lru = NULL;
186 163
187 if (ret != 0) 164 /* TODO: Refactor. */
165 if (! do_src_fifo)
188 { 166 {
189 main_free (block0.blk); 167 main_blklru_list_push_back (& lru_free, & lru[0]);
168 }
169
170 /* Initialize xd3_source. */
171 source->blksize = blksize;
172 source->name = sfile->filename;
173 source->ioh = sfile;
174 source->curblkno = (xoff_t) -1;
175 source->curblk = NULL;
190 176
177 if ((ret = main_getblk_func (stream, source, 0)) != 0)
178 {
191 XPR(NT "error reading source: %s: %s\n", 179 XPR(NT "error reading source: %s: %s\n",
192 sfile->filename, 180 sfile->filename,
193 xd3_mainerror (ret)); 181 xd3_mainerror (ret));
194
195 return ret; 182 return ret;
196 } 183 }
197 184
198 source->onblk = block0.size; 185 /* TODO: Refactor */
186 if (!do_src_fifo)
187 {
188 XD3_ASSERT (!main_blklru_list_empty (& lru_list));
189 main_blklru_list_remove (& lru[0]);
190 }
191 XD3_ASSERT (main_blklru_list_empty (& lru_free));
192 XD3_ASSERT (main_blklru_list_empty (& lru_list));
193
194 source->onblk = lru[0].size; /* xd3 sets onblk */
199 195
200 /* If the file is smaller than a block, size is known. */ 196 /* If the file is smaller than a block, size is known. */
201 if (!sfile->size_known && source->onblk < blksize) 197 if (!sfile->size_known && source->onblk < blksize)
@@ -204,56 +200,44 @@ main_set_source (xd3_stream *stream, xd3_cmd cmd,
204 sfile->size_known = 1; 200 sfile->size_known = 1;
205 } 201 }
206 202
207 /* We update lru_size accordingly, and modify option_srcwinsz, which 203 /* If the size is not known or is greater than the buffer size, we
208 * will be passed via xd3_config. */ 204 * split the buffer across MAX_LRU_SIZE blocks (already allocated in
209 if (sfile->size_known && source_size <= option_srcwinsz) 205 * "lru"). */
206 if (!sfile->size_known || source_size > option_srcwinsz)
210 { 207 {
211 lru_size = (usize_t) ((source_size + blksize - 1) / blksize); 208 /* Modify block 0, change blocksize. */
212 } 209 lru_size = MAX_LRU_SIZE;
213 else 210 blksize = option_srcwinsz / MAX_LRU_SIZE; /* Power of 2 */
214 { 211 source->blksize = blksize;
215 lru_size = (option_srcwinsz + blksize - 1) / blksize; 212 source->onblk = blksize; /* xd3 sets onblk */
216 } 213 lru[0].size = blksize;
217 214
218 XD3_ASSERT (lru_size >= 1); 215 /* Setup rest of blocks. */
219 option_srcwinsz = lru_size * blksize; 216 for (i = 1; i < lru_size; i += 1)
220 217 {
221 if ((lru = (main_blklru*) main_malloc (lru_size * sizeof (main_blklru))) 218 lru[i].blk = lru[0].blk + (blksize * i);
222 == NULL) 219 lru[i].blkno = i;
223 { 220 lru[i].size = blksize;
224 ret = ENOMEM; 221 }
225 return ret;
226 } 222 }
227 223
228 lru[0].blk = block0.blk;
229 lru[0].blkno = 0;
230 lru[0].size = source->onblk;
231
232 if (! sfile->size_known) 224 if (! sfile->size_known)
233 { 225 {
226 /* If the size is not know, we must use FIFO discipline. */
234 do_src_fifo = 1; 227 do_src_fifo = 1;
235 } 228 }
236 else if (! do_src_fifo) 229 else if (! do_src_fifo)
237 { 230 {
238 main_blklru_list_push_back (& lru_list, & lru[0]); 231 /* TODO: Refactor.
239 } 232 * The encoder forces FIFO, otherwise initialize the LRU data structures */
240 233 for (i = 0; i < lru_size; ++i)
241 for (i = 1; i < lru_size; i += 1)
242 {
243 lru[i].blkno = (xoff_t) -1;
244
245 if ((lru[i].blk = (uint8_t*) main_malloc (source->blksize)) == NULL)
246 {
247 ret = ENOMEM;
248 return ret;
249 }
250
251 if (! do_src_fifo)
252 { 234 {
253 main_blklru_list_push_back (& lru_free, & lru[i]); 235 main_blklru_list_push_back (& lru_list, & lru[i]);
254 } 236 }
255 } 237 }
256 238
239 /* Call the appropriate set_source method, handle errors, print
240 * verbose message, etc. */
257 if (sfile->size_known) 241 if (sfile->size_known)
258 { 242 {
259 ret = xd3_set_source_and_size (stream, source, source_size); 243 ret = xd3_set_source_and_size (stream, source, source_size);
@@ -580,21 +564,21 @@ main_getblk_func (xd3_stream *stream,
580 { 564 {
581 if (blru->blkno != blkno) 565 if (blru->blkno != blkno)
582 { 566 {
583 XPR(NT "source block %"Q"u ejects %"Q"u (lru_hits=%u, " 567 XPR(NT "source block %"Q"u read %u ejects %"Q"u (lru_hits=%u, "
584 "lru_misses=%u, lru_filled=%u)\n", 568 "lru_misses=%u, lru_filled=%u)\n",
585 blkno, blru->blkno, lru_hits, lru_misses, lru_filled); 569 blkno, nread, blru->blkno, lru_hits, lru_misses, lru_filled);
586 } 570 }
587 else 571 else
588 { 572 {
589 XPR(NT "source block %"Q"u read (lru_hits=%u, " 573 XPR(NT "source block %"Q"u read %u (lru_hits=%u, "
590 "lru_misses=%u, lru_filled=%u)\n", 574 "lru_misses=%u, lru_filled=%u)\n",
591 blkno, lru_hits, lru_misses, lru_filled); 575 blkno, nread, lru_hits, lru_misses, lru_filled);
592 } 576 }
593 } 577 }
594 else 578 else
595 { 579 {
596 XPR(NT "source block %"Q"u read (lru_hits=%u, lru_misses=%u, " 580 XPR(NT "source block %"Q"u read %u (lru_hits=%u, lru_misses=%u, "
597 "lru_filled=%u)\n", blkno, lru_hits, lru_misses, lru_filled); 581 "lru_filled=%u)\n", blkno, nread, lru_hits, lru_misses, lru_filled);
598 } 582 }
599 } 583 }
600 584
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index e47d708..62018e0 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -3034,7 +3034,7 @@ main_input (xd3_cmd cmd,
3034 3034
3035#if XD3_ENCODER 3035#if XD3_ENCODER
3036 case CMD_ENCODE: 3036 case CMD_ENCODE:
3037 do_src_fifo = 1; 3037 do_src_fifo = 1;
3038 input_func = xd3_encode_input; 3038 input_func = xd3_encode_input;
3039 output_func = main_write_output; 3039 output_func = main_write_output;
3040 3040