210
210
static struct delta_index *
211
211
pack_delta_index(struct unpacked_index_entry **hash, unsigned int hsize,
212
unsigned int num_entries, const struct delta_index *old_index)
212
unsigned int num_entries, struct delta_index *old_index)
214
unsigned int i, j, hmask, memsize;
214
unsigned int i, j, hmask, memsize, to_copy, fit_in_old, copied_count;
215
215
struct unpacked_index_entry *entry;
216
216
struct delta_index *index;
217
struct index_entry *packed_entry, **packed_hash, *old_entry;
217
struct index_entry *packed_entry, **packed_hash, *old_entry, *copy_from;
218
218
struct index_entry null_entry = {0};
224
fprintf(stderr, "Packing %d entries into %d for total of %d entries"
226
num_entries - old_index->num_entries,
227
old_index->num_entries, num_entries,
228
old_index->hash_mask, hmask);
230
fprintf(stderr, "Packing %d entries into a new index\n",
233
/* First, see if we can squeeze the new items into the existing structure.
237
if (old_index && old_index->hash_mask == hmask) {
239
for (i = 0; i < hsize; ++i) {
241
for (entry = hash[i]; entry; entry = entry->next) {
242
if (packed_entry == NULL) {
243
/* Find the last open spot */
244
packed_entry = old_index->hash[i + 1];
246
while (packed_entry >= old_index->hash[i]
247
&& packed_entry->ptr == NULL) {
252
if (packed_entry >= old_index->hash[i+1]
253
|| packed_entry->ptr != NULL) {
254
/* There are no free spots here :( */
258
/* We found an empty spot to put this entry
259
* Copy it over, and remove it from the linked list, just in
260
* case we end up running out of room later.
262
*packed_entry++ = entry->entry;
263
assert(entry == hash[i]);
264
hash[i] = entry->next;
266
old_index->num_entries++;
275
fprintf(stderr, "Fit all %d entries into old index\n",
279
fprintf(stderr, "Fit only %d entries into old index,"
280
" reallocating\n", copied_count);
221
284
* Now create the packed index in array form
222
285
* rather than linked lists.
258
320
* old_index->hash_mask? Would it make any real difference?
260
322
j = i & old_index->hash_mask;
323
copy_from = old_index->hash[j];
261
325
for (old_entry = old_index->hash[j];
262
326
old_entry < old_index->hash[j + 1] && old_entry->ptr != NULL;
264
328
if ((old_entry->val & hmask) == i) {
265
*packed_entry++ = *old_entry;
331
/* We reached the end of a string of entries that should
332
* be copied. Copy the group, and then move the pointers.
335
memcpy(packed_entry, copy_from,
336
sizeof(*old_entry)*to_copy);
337
packed_entry += to_copy;
340
/* Don't copy *this* entry, and start the copy after this */
341
copy_from = old_entry + 1;
345
memcpy(packed_entry, copy_from,
346
sizeof(*old_entry)*to_copy);
347
packed_entry += to_copy;
269
351
for (entry = hash[i]; entry; entry = entry->next) {
270
352
*packed_entry++ = entry->entry;
294
376
struct delta_index *
295
create_index_from_old_and_hash(const struct delta_index *old,
296
struct unpacked_index_entry **hash,
298
unsigned int num_entries)
300
unsigned int i, memsize, total_num_entries, num_nulls;
301
struct unpacked_index_entry *entry;
302
struct delta_index *index;
303
struct index_entry *packed_entry, **packed_hash, null_entry = {0};
304
struct index_entry *copy_from_start, *copy_to_start, *old_entry;
305
size_t total_copy, to_copy;
306
unsigned int num_ops;
307
unsigned int bytes_copied;
310
* Now create the packed index in array form
311
* rather than linked lists.
313
total_num_entries = num_entries + old->num_entries;
314
memsize = sizeof(*index)
315
+ sizeof(*packed_hash) * (hsize+1)
316
+ sizeof(*packed_entry) * (total_num_entries + hsize * EXTRA_NULLS);
317
mem = malloc(memsize);
323
index->memsize = memsize;
324
index->hash_mask = hsize - 1;
325
index->num_entries = total_num_entries;
329
mem = packed_hash + (hsize+1);
335
copy_from_start = copy_to_start = NULL;
337
for (i = 0; i < hsize; i++) {
339
* Coalesce all entries belonging to one linked list
340
* into consecutive array entries.
341
* The entries in old all come before the entries in hash.
343
packed_hash[i] = packed_entry;
344
old_entry = old->hash[i+1];
345
/* Find how many NULL items are in this hash section */
348
while (old_entry >= old->hash[i] && old_entry->ptr == NULL) {
353
to_copy = (old_entry - old->hash[i]);
355
/* This next range can be copied wholesale. However, we will wait
356
* until we have to insert something from the new data before we
358
* So for now, just reserve space for the copy.
360
if (total_copy == 0) {
361
copy_from_start = old->hash[i];
362
copy_to_start = packed_entry;
364
packed_entry += to_copy;
365
total_copy += to_copy;
366
assert((packed_entry - copy_to_start) == total_copy);
367
assert((old_entry - copy_from_start) == total_copy);
369
for (entry = hash[i]; entry; entry = entry->next) {
370
/* We have an entry to insert, so flush the copy buffer */
371
if (total_copy > 0) {
372
assert(copy_to_start != NULL);
373
assert(copy_from_start != NULL);
374
memcpy(copy_to_start, copy_from_start,
375
total_copy * sizeof(struct index_entry));
376
bytes_copied += (total_copy * sizeof(struct index_entry));
378
copy_from_start = copy_to_start = NULL;
381
*packed_entry++ = entry->entry;
383
if (total_copy == 0) {
384
/* We inserted some entries, copy the null entries to the end */
385
for (; num_nulls > 0; --num_nulls) {
386
*packed_entry++ = null_entry;
389
/* We haven't done an insert yet, so just queue the null entries
392
total_copy += num_nulls;
393
packed_entry += num_nulls;
394
assert((packed_entry - copy_to_start) == total_copy);
395
assert((old->hash[i+1] - copy_from_start) == total_copy);
399
if (total_copy > 0) {
400
assert(copy_to_start != NULL);
401
assert(copy_from_start != NULL);
402
memcpy(copy_to_start, copy_from_start,
403
total_copy * sizeof(struct index_entry));
404
bytes_copied += (total_copy * sizeof(struct index_entry));
406
for (; num_nulls > 0; --num_nulls) {
407
*packed_entry++ = null_entry;
411
/* Sentinel value to indicate the length of the last hash bucket */
412
packed_hash[hsize] = packed_entry;
414
assert(packed_entry - (struct index_entry *)mem
415
== total_num_entries + hsize * EXTRA_NULLS);
416
index->last_entry = (packed_entry - 1);
422
377
create_delta_index(const struct source_info *src,
423
const struct delta_index *old)
378
struct delta_index *old)
425
380
unsigned int i, hsize, hmask, num_entries, prev_val, *hash_count;
426
381
unsigned int total_num_entries;