/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/diff-delta.c

  • Committer: John Arbash Meinel
  • Date: 2011-04-20 14:27:19 UTC
  • mto: This revision was merged to the branch mainline in revision 5837.
  • Revision ID: john@arbash-meinel.com-20110420142719-advs1k5vztqzbrgv
Fix bug #767177. Be more agressive with file.close() calls.

Our test suite gets a number of thread leaks and failures because it happens to get async
SFTPFile.close() calls. (if an SFTPFile closes due to __del__ it is done as an async request,
while if you call SFTPFile.close() it is done as a synchronous request.)
We have a couple other cases, probably. Namely SFTPTransport.get() also does an async
prefetch of the content, so if you don't .read() you'll also leak threads that think they
are doing work that you want.

The biggest change here, though, is using a try/finally in a generator, which is not 
python2.4 compatible.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 * This code was greatly inspired by parts of LibXDiff from Davide Libenzi
5
5
 * http://www.xmailserver.org/xdiff-lib.html
6
6
 *
7
 
 * Rewritten for GIT by Nicolas Pitre <nico@cam.org>, (C) 2005-2007
 
7
 * Rewritten for GIT by Nicolas Pitre <nico@fluxnic.net>, (C) 2005-2007
8
8
 * Adapted for Bazaar by John Arbash Meinel <john@arbash-meinel.com> (C) 2009
9
9
 *
10
10
 * This program is free software; you can redistribute it and/or modify
280
280
        if (fit_in_old) {
281
281
            // fprintf(stderr, "Fit all %d entries into old index\n",
282
282
            //                 copied_count);
283
 
            /* No need to allocate a new buffer */
284
 
            return NULL;
 
283
            /*
 
284
             * No need to allocate a new buffer, but return old_index ptr so
 
285
             * callers can distinguish this from an OOM failure.
 
286
             */
 
287
            return old_index;
285
288
        } else {
286
289
            // fprintf(stderr, "Fit only %d entries into old index,"
287
290
            //                 " reallocating\n", copied_count);
370
373
}
371
374
 
372
375
 
373
 
struct delta_index *
 
376
delta_result
374
377
create_delta_index(const struct source_info *src,
375
 
                   struct delta_index *old)
 
378
                   struct delta_index *old,
 
379
                   struct delta_index **fresh)
376
380
{
377
381
    unsigned int i, hsize, hmask, num_entries, prev_val, *hash_count;
378
382
    unsigned int total_num_entries;
383
387
    unsigned long memsize;
384
388
 
385
389
    if (!src->buf || !src->size)
386
 
        return NULL;
 
390
        return DELTA_SOURCE_EMPTY;
387
391
    buffer = src->buf;
388
392
 
389
393
    /* Determine index hash size.  Note that indexing skips the
408
412
          sizeof(*entry) * total_num_entries;
409
413
    mem = malloc(memsize);
410
414
    if (!mem)
411
 
        return NULL;
 
415
        return DELTA_OUT_OF_MEMORY;
412
416
    hash = mem;
413
417
    mem = hash + hsize;
414
418
    entry = mem;
419
423
    hash_count = calloc(hsize, sizeof(*hash_count));
420
424
    if (!hash_count) {
421
425
        free(hash);
422
 
        return NULL;
 
426
        return DELTA_OUT_OF_MEMORY;
423
427
    }
424
428
 
425
429
    /* then populate the index for the new data */
450
454
    total_num_entries = limit_hash_buckets(hash, hash_count, hsize,
451
455
                                           total_num_entries);
452
456
    free(hash_count);
453
 
    if (old) {
454
 
        old->last_src = src;
455
 
    }
456
457
    index = pack_delta_index(hash, hsize, total_num_entries, old);
457
458
    free(hash);
 
459
    /* pack_delta_index only returns NULL on malloc failure */
458
460
    if (!index) {
459
 
        return NULL;
 
461
        return DELTA_OUT_OF_MEMORY;
460
462
    }
461
463
    index->last_src = src;
462
 
    return index;
 
464
    *fresh = index;
 
465
    return DELTA_OK;
463
466
}
464
467
 
465
468
/* Take some entries, and put them into a custom hash.
679
682
    }
680
683
}
681
684
 
682
 
struct delta_index *
 
685
delta_result
683
686
create_delta_index_from_delta(const struct source_info *src,
684
 
                              struct delta_index *old_index)
 
687
                              struct delta_index *old_index,
 
688
                              struct delta_index **fresh)
685
689
{
686
690
    unsigned int i, num_entries, max_num_entries, prev_val, num_inserted;
687
691
    unsigned int hash_offset;
690
694
    struct delta_index *new_index;
691
695
    struct index_entry *entry, *entries;
692
696
 
 
697
    if (!old_index)
 
698
        return DELTA_INDEX_NEEDED;
693
699
    if (!src->buf || !src->size)
694
 
        return NULL;
 
700
        return DELTA_SOURCE_EMPTY;
695
701
    buffer = src->buf;
696
702
    top = buffer + src->size;
697
703
 
707
713
    /* allocate an array to hold whatever entries we find */
708
714
    entries = malloc(sizeof(*entry) * max_num_entries);
709
715
    if (!entries) /* malloc failure */
710
 
        return NULL;
 
716
        return DELTA_OUT_OF_MEMORY;
711
717
 
712
718
    /* then populate the index for the new data */
713
719
    prev_val = ~0;
774
780
        }
775
781
    }
776
782
    if (data != top) {
777
 
        /* Something was wrong with this delta */
 
783
        /* The source_info data passed was corrupted or otherwise invalid */
778
784
        free(entries);
779
 
        return NULL;
 
785
        return DELTA_SOURCE_BAD;
780
786
    }
781
787
    if (num_entries == 0) {
782
788
        /** Nothing to index **/
783
789
        free(entries);
784
 
        return NULL;
 
790
        *fresh = old_index;
 
791
        return DELTA_OK;
785
792
    }
786
 
    assert(old_index != NULL);
787
793
    old_index->last_src = src;
788
794
    /* See if we can fill in these values into the holes in the array */
789
795
    entry = entries;
841
847
        new_index = create_index_from_old_and_new_entries(old_index,
842
848
            entry, num_entries);
843
849
    } else {
844
 
        new_index = NULL;
 
850
        new_index = old_index;
845
851
        // fprintf(stderr, "inserted %d without resizing\n", num_inserted);
846
852
    }
847
853
    free(entries);
848
 
    return new_index;
 
854
    /* create_index_from_old_and_new_entries returns NULL on malloc failure */
 
855
    if (!new_index)
 
856
        return DELTA_OUT_OF_MEMORY;
 
857
    *fresh = new_index;
 
858
    return DELTA_OK;
849
859
}
850
860
 
851
861
void free_delta_index(struct delta_index *index)
853
863
    free(index);
854
864
}
855
865
 
856
 
unsigned long sizeof_delta_index(struct delta_index *index)
 
866
unsigned long
 
867
sizeof_delta_index(struct delta_index *index)
857
868
{
858
869
    if (index)
859
870
        return index->memsize;
867
878
 */
868
879
#define MAX_OP_SIZE (5 + 5 + 1 + RABIN_WINDOW + 7)
869
880
 
870
 
void *
 
881
delta_result
871
882
create_delta(const struct delta_index *index,
872
883
             const void *trg_buf, unsigned long trg_size,
873
 
             unsigned long *delta_size, unsigned long max_size)
 
884
             unsigned long *delta_size, unsigned long max_size,
 
885
             void **delta_data)
874
886
{
875
 
    unsigned int i, outpos, outsize, moff, msize, val;
 
887
    unsigned int i, outpos, outsize, moff, val;
 
888
    int msize;
876
889
    const struct source_info *msource;
877
890
    int inscnt;
878
891
    const unsigned char *ref_data, *ref_top, *data, *top;
880
893
    unsigned long source_size;
881
894
 
882
895
    if (!trg_buf || !trg_size)
883
 
        return NULL;
 
896
        return DELTA_BUFFER_EMPTY;
884
897
    if (index == NULL)
885
 
        return NULL;
 
898
        return DELTA_INDEX_NEEDED;
886
899
 
887
900
    outpos = 0;
888
901
    outsize = 8192;
890
903
        outsize = max_size + MAX_OP_SIZE + 1;
891
904
    out = malloc(outsize);
892
905
    if (!out)
893
 
        return NULL;
 
906
        return DELTA_OUT_OF_MEMORY;
894
907
 
895
908
    source_size = index->last_src->size + index->last_src->agg_offset;
896
909
 
943
956
                 entry++) {
944
957
                const unsigned char *ref;
945
958
                const unsigned char *src;
946
 
                unsigned int ref_size;
 
959
                int ref_size;
947
960
                if (entry->val != val)
948
961
                    continue;
949
962
                ref = entry->ptr;
956
969
                 * match more bytes with this location that we have already
957
970
                 * matched.
958
971
                 */
959
 
                if (ref_size > top - src)
 
972
                if (ref_size > (top - src))
960
973
                    ref_size = top - src;
961
974
                if (ref_size <= msize)
962
975
                    break;
963
976
                /* See how many bytes actually match at this location. */
964
977
                while (ref_size-- && *src++ == *ref)
965
978
                    ref++;
966
 
                if (msize < ref - entry->ptr) {
 
979
                if (msize < (ref - entry->ptr)) {
967
980
                    /* this is our best match so far */
968
981
                    msize = ref - entry->ptr;
969
982
                    msource = entry->src;
1069
1082
            out = realloc(out, outsize);
1070
1083
            if (!out) {
1071
1084
                free(tmp);
1072
 
                return NULL;
 
1085
                return DELTA_OUT_OF_MEMORY;
1073
1086
            }
1074
1087
        }
1075
1088
    }
1079
1092
 
1080
1093
    if (max_size && outpos > max_size) {
1081
1094
        free(out);
1082
 
        return NULL;
 
1095
        return DELTA_SIZE_TOO_BIG;
1083
1096
    }
1084
1097
 
1085
1098
    *delta_size = outpos;
1086
 
    return out;
 
1099
    *delta_data = out;
 
1100
    return DELTA_OK;
1087
1101
}
1088
1102
 
1089
1103
/* vim: et ts=4 sw=4 sts=4