Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch annotate_noleak Excluding Merge-Ins
This is equivalent to a diff from 0cf5416002 to 4860d9f234
2011-10-14
| ||
16:11 | Merging the annotate_noleak changes, about removing an important memory leak in the annotate operation. It also fixes some blob behaviour in blob.c and content.c. Update: Removed from trunk. Replaced by the must simpler fix at [9929bab702f99839ee] check-in: 409f370a6d user: viriketo tags: declined | |
2011-09-13
| ||
17:18 | The Label list was not properly freed in some cases; looking at the annotate of 'win/Makefile.msc' was triggering the case. Closed-Leaf check-in: 4860d9f234 user: viriketo tags: annotate_noleak | |
16:43 | Getting in the changes reducing the leak on annotate. In the fossil mailing list, I received only opinions in favour of getting mallocs and frees properly paired, so I think noone will refuse the change. check-in: 7870a89b10 user: viriketo tags: annotate_noleak | |
2011-09-06
| ||
13:23 | Close A and LI tags when displaying new and deleted files in timeline. check-in: 8d703ff956 user: dmitry tags: trunk | |
07:33 | Two fixes about localtime: • The ci_edit page tells the user that it asks UTC time • The object_description gives links to localtime (if it's set in the config). Otherwise the links were not pointing at the concerning checkin. Leaf check-in: 1765c18d94 user: viriketo tags: localtime_fixes | |
2011-09-04
| ||
20:43 | Updating from trunk to get the latest code. check-in: 73b6ff4966 user: viriketo tags: annotate_noleak | |
01:28 | Update the built-in SQLite to the latest 3.7.8-alpha version that contains the improved merge-sort logic. check-in: 0cf5416002 user: drh tags: trunk | |
2011-09-02
| ||
16:19 | Do a better job of merging branches that contain lots of file renames. check-in: 0b93b0f958 user: drh tags: trunk | |
Changes to src/blob.c.
892 892 ** 893 893 ** pOut must be either uninitialized or the same as pIn. 894 894 */ 895 895 int blob_uncompress(Blob *pIn, Blob *pOut){ 896 896 unsigned int nOut; 897 897 unsigned char *inBuf; 898 898 unsigned int nIn = blob_size(pIn); 899 - Blob temp; 899 + Blob temp = empty_blob; 900 900 int rc; 901 901 unsigned long int nOut2; 902 902 if( nIn<=4 ){ 903 903 return 0; 904 904 } 905 905 inBuf = (unsigned char*)blob_buffer(pIn); 906 906 nOut = (inBuf[0]<<24) + (inBuf[1]<<16) + (inBuf[2]<<8) + inBuf[3];
Changes to src/content.c.
93 93 contentCache.nAlloc*sizeof(contentCache.a[0])); 94 94 } 95 95 p = &contentCache.a[contentCache.n++]; 96 96 p->rid = rid; 97 97 p->age = contentCache.nextAge++; 98 98 contentCache.szTotal += blob_size(pBlob); 99 99 p->content = *pBlob; 100 - blob_zero(pBlob); 100 + *pBlob = empty_blob; 101 101 bag_insert(&contentCache.inCache, rid); 102 102 } 103 103 104 104 /* 105 105 ** Clear the content cache. 106 106 */ 107 107 void content_clear_cache(void){ ................................................................................ 257 257 if( nextRid==0 ){ 258 258 rc = content_of_blob(rid, pBlob); 259 259 }else{ 260 260 int n = 1; 261 261 int nAlloc = 10; 262 262 int *a = 0; 263 263 int mx; 264 - Blob delta, next; 264 + Blob delta = empty_blob, next = empty_blob; 265 265 266 266 a = fossil_malloc( sizeof(a[0])*nAlloc ); 267 267 a[0] = rid; 268 268 a[1] = nextRid; 269 269 n = 1; 270 270 while( !bag_find(&contentCache.inCache, nextRid) 271 271 && (nextRid = findSrcid(nextRid))>0 ){
Changes to src/db.c.
209 209 ** Prepare a Stmt. Assume that the Stmt is previously uninitialized. 210 210 ** If the input string contains multiple SQL statements, only the first 211 211 ** one is processed. All statements beyond the first are silently ignored. 212 212 */ 213 213 int db_vprepare(Stmt *pStmt, int errOk, const char *zFormat, va_list ap){ 214 214 int rc; 215 215 char *zSql; 216 - blob_zero(&pStmt->sql); 216 + pStmt->sql = empty_blob; 217 217 blob_vappendf(&pStmt->sql, zFormat, ap); 218 218 va_end(ap); 219 219 zSql = blob_str(&pStmt->sql); 220 220 nPrepare++; 221 221 rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt->pStmt, 0); 222 222 if( rc!=0 && !errOk ){ 223 223 db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
Changes to src/deltacmd.c.
75 75 ** 76 76 ** It works ok for pTarget and pOriginal to be the same blob. 77 77 ** 78 78 ** Return the length of the target. Return -1 if there is an error. 79 79 */ 80 80 int blob_delta_apply(Blob *pOriginal, Blob *pDelta, Blob *pTarget){ 81 81 int len, n; 82 - Blob out; 82 + Blob out = empty_blob; 83 83 84 84 n = delta_output_size(blob_buffer(pDelta), blob_size(pDelta)); 85 85 blob_zero(&out); 86 86 if( n<0 ) return -1; 87 87 blob_resize(&out, n); 88 88 len = delta_apply( 89 89 blob_buffer(pOriginal), blob_size(pOriginal),
Changes to src/diff.c.
617 617 } 618 618 619 619 /************************************************************************** 620 620 ** The basic difference engine is above. What follows is the annotation 621 621 ** engine. Both are in the same file since they share many components. 622 622 */ 623 623 624 +/* 625 +** Linked list of strings, labels used in the annotator code. 626 +** The elements of the list and the pointed string (str) 627 +** will be freed once they become totally unreferenced 628 +** (nref == 0). 629 +*/ 630 +struct Label 631 +{ 632 + struct Label *prev; /* previous element */ 633 + struct Label *next; /* next element */ 634 + char *str; /* The label string */ 635 + int nref; /* Number of references to the string */ 636 +}; 637 + 624 638 /* 625 639 ** The status of an annotation operation is recorded by an instance 626 640 ** of the following structure. 627 641 */ 628 642 typedef struct Annotator Annotator; 629 643 struct Annotator { 630 644 DContext c; /* The diff-engine context */ 631 645 struct AnnLine { /* Lines of the original files... */ 632 646 const char *z; /* The text of the line */ 633 647 short int n; /* Number of bytes (omitting trailing space and \n) */ 634 648 short int iLevel; /* Level at which tag was set */ 635 - const char *zSrc; /* Tag showing origin of this line */ 649 + struct Label *zSrc; /* Tag showing origin of this line */ 636 650 } *aOrig; 637 651 int nOrig; /* Number of elements in aOrig[] */ 638 652 int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ 639 653 int iLevel; /* Current level */ 640 654 int nVers; /* Number of versions analyzed */ 641 - char **azVers; /* Names of versions analyzed */ 655 + struct Label **azVers; /* Names of versions analyzed */ 656 + Blob toAnnotate; 657 + struct Label *firstLabel; 642 658 }; 643 659 644 660 /* 645 661 ** Initialize the annotation process by specifying the file that is 646 662 ** to be annotated. The annotator takes control of the input Blob and 647 663 ** will release it when it is finished with it. 648 664 */ 649 -static int annotation_start(Annotator *p, Blob *pInput){ 665 +static int annotation_start(Annotator *p){ 650 666 int i; 651 667 652 - memset(p, 0, sizeof(*p)); 653 - p->c.aTo = break_into_lines(blob_str(pInput), blob_size(pInput),&p->c.nTo,1); 668 + p->c.aTo = break_into_lines(blob_str(&p->toAnnotate), 669 + blob_size(&p->toAnnotate),&p->c.nTo,1); 654 670 if( p->c.aTo==0 ){ 655 671 return 1; 656 672 } 657 673 p->aOrig = fossil_malloc( sizeof(p->aOrig[0])*p->c.nTo ); 658 674 for(i=0; i<p->c.nTo; i++){ 659 675 p->aOrig[i].z = p->c.aTo[i].z; 660 676 p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK; ................................................................................ 667 683 /* 668 684 ** The input pParent is the next most recent ancestor of the file 669 685 ** being annotated. Do another step of the annotation. Return true 670 686 ** if additional annotation is required. zPName is the tag to insert 671 687 ** on each line of the file being annotated that was contributed by 672 688 ** pParent. Memory to hold zPName is leaked. 673 689 */ 674 -static int annotation_step(Annotator *p, Blob *pParent, char *zPName){ 690 +static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){ 675 691 int i, j; 676 692 int lnTo; 677 693 int iPrevLevel; 678 694 int iThisLevel; 679 695 680 696 /* Prepare the parent file to be diffed */ 681 697 p->c.aFrom = break_into_lines(blob_str(pParent), blob_size(pParent), 682 698 &p->c.nFrom, 1); 683 699 if( p->c.aFrom==0 ){ 700 + free(p->c.aFrom); 684 701 return 1; 685 702 } 686 703 687 704 /* Compute the differences going from pParent to the file being 688 705 ** annotated. */ 689 706 diff_all(&p->c); 690 707 ................................................................................ 694 711 iPrevLevel = p->iLevel; 695 712 p->iLevel++; 696 713 iThisLevel = p->iLevel; 697 714 for(i=lnTo=0; i<p->c.nEdit; i+=3){ 698 715 struct AnnLine *x = &p->aOrig[lnTo]; 699 716 for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){ 700 717 if( x->zSrc==0 || x->iLevel==iPrevLevel ){ 718 + if (x->zSrc!=0) 719 + { 720 + if(--x->zSrc->nref == 0) 721 + { 722 + free(x->zSrc->str); 723 + if (x->zSrc->prev) 724 + x->zSrc->prev->next = x->zSrc->next; 725 + if (x->zSrc->next) 726 + x->zSrc->next->prev = x->zSrc->prev; 727 + free(x->zSrc); 728 + } 729 + } 701 730 x->zSrc = zPName; 731 + ++zPName->nref; 702 732 x->iLevel = iThisLevel; 703 733 } 704 734 } 705 735 lnTo += p->c.aEdit[i+2]; 706 736 } 707 737 708 738 /* Clear out the diff results */ ................................................................................ 709 739 free(p->c.aEdit); 710 740 p->c.aEdit = 0; 711 741 p->c.nEdit = 0; 712 742 p->c.nEditAlloc = 0; 713 743 714 744 /* Clear out the from file */ 715 745 free(p->c.aFrom); 716 - blob_zero(pParent); 746 + blob_reset(pParent); 717 747 718 748 /* Return no errors */ 719 749 return 0; 720 750 } 721 751 722 752 723 753 /* 724 754 ** COMMAND: test-annotate-step 725 755 */ 726 756 void test_annotate_step_cmd(void){ 727 - Blob orig, b; 757 + Blob b = empty_blob; 728 758 Annotator x; 729 759 int i; 730 760 731 761 if( g.argc<4 ) usage("RID1 RID2 ..."); 732 762 db_must_be_within_tree(); 733 - blob_zero(&b); 734 - content_get(name_to_rid(g.argv[2]), &orig); 735 - if( annotation_start(&x, &orig) ){ 763 + memset(&x, 0, sizeof(x)); 764 + x.toAnnotate = empty_blob; 765 + content_get(name_to_rid(g.argv[2]), &x.toAnnotate); 766 + if( annotation_start(&x) ){ 736 767 fossil_fatal("binary file"); 737 768 } 738 769 for(i=3; i<g.argc; i++){ 770 + struct Label *l; 739 771 blob_zero(&b); 740 772 content_get(name_to_rid(g.argv[i]), &b); 741 - if( annotation_step(&x, &b, g.argv[i-1]) ){ 773 + l = fossil_malloc(sizeof(*l)); 774 + l->str = g.argv[i-1]; 775 + l->nref = 0; 776 + l->next = x.firstLabel; 777 + if (x.firstLabel) 778 + x.firstLabel->prev = l; 779 + x.firstLabel = l; 780 + if( annotation_step(&x, &b, l) ){ 742 781 fossil_fatal("binary file"); 743 782 } 744 783 } 745 784 for(i=0; i<x.nOrig; i++){ 746 - const char *zSrc = x.aOrig[i].zSrc; 785 + const char *zSrc = x.aOrig[i].zSrc->str; 747 786 if( zSrc==0 ) zSrc = g.argv[g.argc-1]; 748 787 fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); 788 + } 789 + while(x.firstLabel) { 790 + struct Label *l; 791 + l = x.firstLabel->next; 792 + assert(x.firstLabel->nref > 0); 793 + free(x.firstLabel->str); 794 + free(x.firstLabel); 795 + x.firstLabel = l; 749 796 } 750 797 } 751 798 752 799 /* Annotation flags */ 753 800 #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */ 754 801 755 802 /* ................................................................................ 761 808 Annotator *p, /* The annotator */ 762 809 int fnid, /* The name of the file to be annotated */ 763 810 int mid, /* Use the version of the file in this check-in */ 764 811 int webLabel, /* Use web-style annotations if true */ 765 812 int iLimit, /* Limit the number of levels if greater than zero */ 766 813 int annFlags /* Flags to alter the annotation */ 767 814 ){ 768 - Blob toAnnotate; /* Text of the final (mid) version of the file */ 769 - Blob step; /* Text of previous revision */ 815 + Blob step = empty_blob; /* Text of previous revision */ 770 816 int rid; /* Artifact ID of the file being annotated */ 771 - char *zLabel; /* Label to apply to a line */ 772 817 Stmt q; /* Query returning all ancestor versions */ 773 818 774 819 /* Initialize the annotation */ 775 820 rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid); 776 821 if( rid==0 ){ 777 822 fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid); 778 823 } 779 - if( !content_get(rid, &toAnnotate) ){ 824 + memset(p, 0, sizeof(*p)); 825 + p->toAnnotate = empty_blob; 826 + if( !content_get(rid, &p->toAnnotate) ){ 780 827 fossil_panic("unable to retrieve content of artifact #%d", rid); 781 828 } 782 829 db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); 783 830 if( iLimit<=0 ) iLimit = 1000000000; 784 831 compute_direct_ancestors(mid, iLimit); 785 - annotation_start(p, &toAnnotate); 832 + annotation_start(p); 786 833 787 834 db_prepare(&q, 788 835 "SELECT mlink.fid," 789 836 " (SELECT uuid FROM blob WHERE rid=mlink.%s)," 790 837 " date(event.mtime), " 791 838 " coalesce(event.euser,event.user) " 792 839 " FROM ancestor, mlink, event" ................................................................................ 800 847 iLimit>0 ? iLimit : 10000000 801 848 ); 802 849 while( db_step(&q)==SQLITE_ROW ){ 803 850 int pid = db_column_int(&q, 0); 804 851 const char *zUuid = db_column_text(&q, 1); 805 852 const char *zDate = db_column_text(&q, 2); 806 853 const char *zUser = db_column_text(&q, 3); 854 + struct Label *l = fossil_malloc(sizeof(*l)); 855 + l->nref = 0; 856 + l->next = p->firstLabel; 857 + l->prev = 0; 858 + if (p->firstLabel) 859 + p->firstLabel->prev = l; 807 860 if( webLabel ){ 808 - zLabel = mprintf( 861 + l->str = mprintf( 809 862 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s", 810 863 g.zTop, zUuid, zUuid, zDate, zUser 811 864 ); 812 865 }else{ 813 - zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser); 866 + l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser); 814 867 } 868 + p->firstLabel = l; 815 869 p->nVers++; 816 870 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) ); 817 - p->azVers[p->nVers-1] = zLabel; 871 + p->azVers[p->nVers-1] = l; 818 872 content_get(pid, &step); 819 - annotation_step(p, &step, zLabel); 873 + annotation_step(p, &step, l); 874 + if (l->nref == 0) 875 + { 876 + free(l->str); 877 + p->firstLabel = l->next; 878 + if (l->next) 879 + l->next->prev = 0; 880 + free(l); 881 + } 820 882 blob_reset(&step); 821 883 } 822 884 db_finalize(&q); 885 + free(p->c.aTo); 823 886 } 824 887 825 888 /* 826 889 ** WEBPAGE: annotate 827 890 ** 828 891 ** Query parameters: 829 892 ** ................................................................................ 851 914 if( P("filevers") ) annFlags |= ANN_FILE_VERS; 852 915 annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags); 853 916 if( P("log") ){ 854 917 int i; 855 918 @ <h2>Versions analyzed:</h2> 856 919 @ <ol> 857 920 for(i=0; i<ann.nVers; i++){ 858 - @ <li><tt>%s(ann.azVers[i])</tt></li> 921 + @ <li><tt>%s(ann.azVers[i]->str)</tt></li> 859 922 } 860 923 @ </ol> 861 924 @ <hr> 862 925 @ <h2>Annotation:</h2> 863 926 } 864 927 @ <pre> 865 928 for(i=0; i<ann.nOrig; i++){ 866 929 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0; 867 - @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z) 930 + @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z) 868 931 } 869 932 @ </pre> 870 933 style_footer(); 934 + 935 + free(ann.azVers); 936 + free(ann.aOrig); 937 + blob_reset(&ann.toAnnotate); 938 + while(ann.firstLabel) { 939 + struct Label *l; 940 + l = ann.firstLabel->next; 941 + assert(ann.firstLabel->nref > 0); 942 + free(ann.firstLabel->str); 943 + free(ann.firstLabel); 944 + ann.firstLabel = l; 945 + } 871 946 } 872 947 873 948 /* 874 949 ** COMMAND: annotate 875 950 ** 876 951 ** %fossil annotate FILENAME 877 952 ** ................................................................................ 883 958 ** --log List all versions analyzed 884 959 ** --filevers Show file version numbers rather than check-in versions 885 960 */ 886 961 void annotate_cmd(void){ 887 962 int fnid; /* Filename ID */ 888 963 int fid; /* File instance ID */ 889 964 int mid; /* Manifest where file was checked in */ 890 - Blob treename; /* FILENAME translated to canonical form */ 965 + Blob treename = empty_blob; /* FILENAME translated to canonical form */ 891 966 char *zFilename; /* Cannonical filename */ 892 967 Annotator ann; /* The annotation of the file */ 893 968 int i; /* Loop counter */ 894 969 const char *zLimit; /* The value to the --limit option */ 895 970 int iLimit; /* How far back in time to look */ 896 971 int showLog; /* True to show the log */ 897 972 int fileVers; /* Show file version instead of check-in versions */ ................................................................................ 912 987 if( fnid==0 ){ 913 988 fossil_fatal("no such file: %s", zFilename); 914 989 } 915 990 fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); 916 991 if( fid==0 ){ 917 992 fossil_fatal("not part of current checkout: %s", zFilename); 918 993 } 994 + blob_reset(&treename); 919 995 mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); 920 996 if( mid==0 ){ 921 997 fossil_panic("unable to find manifest"); 922 998 } 923 999 if( fileVers ) annFlags |= ANN_FILE_VERS; 924 1000 annotate_file(&ann, fnid, mid, 0, iLimit, annFlags); 925 1001 if( showLog ){ 926 1002 for(i=0; i<ann.nVers; i++){ 927 - printf("version %3d: %s\n", i+1, ann.azVers[i]); 1003 + printf("version %3d: %s\n", i+1, ann.azVers[i]->str); 928 1004 } 929 1005 printf("---------------------------------------------------\n"); 930 1006 } 931 1007 for(i=0; i<ann.nOrig; i++){ 932 1008 fossil_print("%s: %.*s\n", 933 - ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); 1009 + ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z); 1010 + } 1011 + free(ann.azVers); 1012 + free(ann.aOrig); 1013 + blob_reset(&ann.toAnnotate); 1014 + while(ann.firstLabel) { 1015 + struct Label *l; 1016 + l = ann.firstLabel->next; 1017 + assert(ann.firstLabel->nref > 0); 1018 + free(ann.firstLabel->str); 1019 + free(ann.firstLabel); 1020 + ann.firstLabel = l; 934 1021 } 935 1022 }
Changes to src/file.c.
699 699 ** message and quit if the errFatal flag is true. If errFatal is 700 700 ** false, then simply return 0. 701 701 ** 702 702 ** The root of the tree is defined by the g.zLocalRoot variable. 703 703 */ 704 704 int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ 705 705 int n; 706 - Blob full; 706 + Blob full = empty_blob; 707 707 int nFull; 708 708 char *zFull; 709 709 710 710 blob_zero(pOut); 711 711 db_must_be_within_tree(); 712 712 file_canonical_name(zOrigName, &full); 713 713 n = strlen(g.zLocalRoot);