Fossil SCM

Getting in the changes reducing the leak on annotate.

viriketo 2011-09-13 16:43 UTC annotate_noleak merge
Commit 7870a89b103a37b0038436153b91d74f6c5000ed
1 file changed +71 -16
+71 -16
--- src/diff.c
+++ src/diff.c
@@ -619,10 +619,24 @@
619619
/**************************************************************************
620620
** The basic difference engine is above. What follows is the annotation
621621
** engine. Both are in the same file since they share many components.
622622
*/
623623
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
+
624638
/*
625639
** The status of an annotation operation is recorded by an instance
626640
** of the following structure.
627641
*/
628642
typedef struct Annotator Annotator;
@@ -630,18 +644,19 @@
630644
DContext c; /* The diff-engine context */
631645
struct AnnLine { /* Lines of the original files... */
632646
const char *z; /* The text of the line */
633647
short int n; /* Number of bytes (omitting trailing space and \n) */
634648
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 */
636650
} *aOrig;
637651
int nOrig; /* Number of elements in aOrig[] */
638652
int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
639653
int iLevel; /* Current level */
640654
int nVers; /* Number of versions analyzed */
641
- char **azVers; /* Names of versions analyzed */
655
+ struct Label **azVers; /* Names of versions analyzed */
642656
Blob toAnnotate;
657
+ struct Label *firstLabel;
643658
};
644659
645660
/*
646661
** Initialize the annotation process by specifying the file that is
647662
** to be annotated. The annotator takes control of the input Blob and
@@ -670,11 +685,11 @@
670685
** being annotated. Do another step of the annotation. Return true
671686
** if additional annotation is required. zPName is the tag to insert
672687
** on each line of the file being annotated that was contributed by
673688
** pParent. Memory to hold zPName is leaked.
674689
*/
675
-static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
690
+static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){
676691
int i, j;
677692
int lnTo;
678693
int iPrevLevel;
679694
int iThisLevel;
680695
@@ -698,13 +713,22 @@
698713
iThisLevel = p->iLevel;
699714
for(i=lnTo=0; i<p->c.nEdit; i+=3){
700715
struct AnnLine *x = &p->aOrig[lnTo];
701716
for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
702717
if( x->zSrc==0 || x->iLevel==iPrevLevel ){
703
- /* TODO: handle zPName so we can free labels
704
- * if they get totally unreferenced in the Annotator */
718
+ if (x->zSrc!=0)
719
+ {
720
+ if(--x->zSrc->nref == 0)
721
+ {
722
+ free(x->zSrc->str);
723
+ x->zSrc->prev->next = x->zSrc->next;
724
+ x->zSrc->next->prev = x->zSrc->prev;
725
+ free(x->zSrc);
726
+ }
727
+ }
705728
x->zSrc = zPName;
729
+ ++zPName->nref;
706730
x->iLevel = iThisLevel;
707731
}
708732
}
709733
lnTo += p->c.aEdit[i+2];
710734
}
@@ -739,20 +763,36 @@
739763
content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
740764
if( annotation_start(&x) ){
741765
fossil_fatal("binary file");
742766
}
743767
for(i=3; i<g.argc; i++){
768
+ struct Label *l;
744769
blob_zero(&b);
745770
content_get(name_to_rid(g.argv[i]), &b);
746
- if( annotation_step(&x, &b, g.argv[i-1]) ){
771
+ l = fossil_malloc(sizeof(*l));
772
+ l->str = g.argv[i-1];
773
+ l->nref = 0;
774
+ l->next = x.firstLabel;
775
+ if (x.firstLabel)
776
+ x.firstLabel->prev = l;
777
+ x.firstLabel = l;
778
+ if( annotation_step(&x, &b, l) ){
747779
fossil_fatal("binary file");
748780
}
749781
}
750782
for(i=0; i<x.nOrig; i++){
751
- const char *zSrc = x.aOrig[i].zSrc;
783
+ const char *zSrc = x.aOrig[i].zSrc->str;
752784
if( zSrc==0 ) zSrc = g.argv[g.argc-1];
753785
fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
786
+ }
787
+ while(x.firstLabel) {
788
+ struct Label *l;
789
+ l = x.firstLabel->next;
790
+ assert(x.firstLabel->nref > 0);
791
+ free(x.firstLabel->str);
792
+ free(x.firstLabel);
793
+ x.firstLabel = l;
754794
}
755795
}
756796
757797
/* Annotation flags */
758798
#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
@@ -770,11 +810,10 @@
770810
int iLimit, /* Limit the number of levels if greater than zero */
771811
int annFlags /* Flags to alter the annotation */
772812
){
773813
Blob step = empty_blob; /* Text of previous revision */
774814
int rid; /* Artifact ID of the file being annotated */
775
- char *zLabel; /* Label to apply to a line */
776815
Stmt q; /* Query returning all ancestor versions */
777816
778817
/* Initialize the annotation */
779818
rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
780819
if( rid==0 ){
@@ -808,23 +847,31 @@
808847
while( db_step(&q)==SQLITE_ROW ){
809848
int pid = db_column_int(&q, 0);
810849
const char *zUuid = db_column_text(&q, 1);
811850
const char *zDate = db_column_text(&q, 2);
812851
const char *zUser = db_column_text(&q, 3);
852
+ struct Label *l = fossil_malloc(sizeof(*l));
853
+ l->nref = 0;
854
+ l->next = p->firstLabel;
855
+ if (p->firstLabel)
856
+ p->firstLabel->prev = l;
813857
if( webLabel ){
814
- zLabel = mprintf(
858
+ l->str = mprintf(
815859
"<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
816860
g.zTop, zUuid, zUuid, zDate, zUser
817861
);
818862
}else{
819
- zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
863
+ l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
820864
}
865
+ p->firstLabel = l;
821866
p->nVers++;
822867
p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
823
- p->azVers[p->nVers-1] = zLabel;
868
+ p->azVers[p->nVers-1] = l;
824869
content_get(pid, &step);
825
- annotation_step(p, &step, zLabel);
870
+ annotation_step(p, &step, l);
871
+ if (l->nref == 0)
872
+ free(l->str);
826873
blob_reset(&step);
827874
}
828875
db_finalize(&q);
829876
free(p->c.aTo);
830877
}
@@ -860,20 +907,20 @@
860907
if( P("log") ){
861908
int i;
862909
@ <h2>Versions analyzed:</h2>
863910
@ <ol>
864911
for(i=0; i<ann.nVers; i++){
865
- @ <li><tt>%s(ann.azVers[i])</tt></li>
912
+ @ <li><tt>%s(ann.azVers[i]->str)</tt></li>
866913
}
867914
@ </ol>
868915
@ <hr>
869916
@ <h2>Annotation:</h2>
870917
}
871918
@ <pre>
872919
for(i=0; i<ann.nOrig; i++){
873920
((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
874
- @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
921
+ @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z)
875922
}
876923
@ </pre>
877924
style_footer();
878925
}
879926
@@ -930,17 +977,25 @@
930977
}
931978
if( fileVers ) annFlags |= ANN_FILE_VERS;
932979
annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
933980
if( showLog ){
934981
for(i=0; i<ann.nVers; i++){
935
- printf("version %3d: %s\n", i+1, ann.azVers[i]);
982
+ printf("version %3d: %s\n", i+1, ann.azVers[i]->str);
936983
}
937984
printf("---------------------------------------------------\n");
938985
}
939986
for(i=0; i<ann.nOrig; i++){
940987
fossil_print("%s: %.*s\n",
941
- ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
988
+ ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z);
942989
}
943990
free(ann.azVers);
944991
free(ann.aOrig);
945992
blob_reset(&ann.toAnnotate);
993
+ while(ann.firstLabel) {
994
+ struct Label *l;
995
+ l = ann.firstLabel->next;
996
+ assert(ann.firstLabel->nref > 0);
997
+ free(ann.firstLabel->str);
998
+ free(ann.firstLabel);
999
+ ann.firstLabel = l;
1000
+ }
9461001
}
9471002
--- src/diff.c
+++ src/diff.c
@@ -619,10 +619,24 @@
619 /**************************************************************************
620 ** The basic difference engine is above. What follows is the annotation
621 ** engine. Both are in the same file since they share many components.
622 */
623
 
 
 
 
 
 
 
 
 
 
 
 
 
 
624 /*
625 ** The status of an annotation operation is recorded by an instance
626 ** of the following structure.
627 */
628 typedef struct Annotator Annotator;
@@ -630,18 +644,19 @@
630 DContext c; /* The diff-engine context */
631 struct AnnLine { /* Lines of the original files... */
632 const char *z; /* The text of the line */
633 short int n; /* Number of bytes (omitting trailing space and \n) */
634 short int iLevel; /* Level at which tag was set */
635 const char *zSrc; /* Tag showing origin of this line */
636 } *aOrig;
637 int nOrig; /* Number of elements in aOrig[] */
638 int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
639 int iLevel; /* Current level */
640 int nVers; /* Number of versions analyzed */
641 char **azVers; /* Names of versions analyzed */
642 Blob toAnnotate;
 
643 };
644
645 /*
646 ** Initialize the annotation process by specifying the file that is
647 ** to be annotated. The annotator takes control of the input Blob and
@@ -670,11 +685,11 @@
670 ** being annotated. Do another step of the annotation. Return true
671 ** if additional annotation is required. zPName is the tag to insert
672 ** on each line of the file being annotated that was contributed by
673 ** pParent. Memory to hold zPName is leaked.
674 */
675 static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
676 int i, j;
677 int lnTo;
678 int iPrevLevel;
679 int iThisLevel;
680
@@ -698,13 +713,22 @@
698 iThisLevel = p->iLevel;
699 for(i=lnTo=0; i<p->c.nEdit; i+=3){
700 struct AnnLine *x = &p->aOrig[lnTo];
701 for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
702 if( x->zSrc==0 || x->iLevel==iPrevLevel ){
703 /* TODO: handle zPName so we can free labels
704 * if they get totally unreferenced in the Annotator */
 
 
 
 
 
 
 
 
705 x->zSrc = zPName;
 
706 x->iLevel = iThisLevel;
707 }
708 }
709 lnTo += p->c.aEdit[i+2];
710 }
@@ -739,20 +763,36 @@
739 content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
740 if( annotation_start(&x) ){
741 fossil_fatal("binary file");
742 }
743 for(i=3; i<g.argc; i++){
 
744 blob_zero(&b);
745 content_get(name_to_rid(g.argv[i]), &b);
746 if( annotation_step(&x, &b, g.argv[i-1]) ){
 
 
 
 
 
 
 
747 fossil_fatal("binary file");
748 }
749 }
750 for(i=0; i<x.nOrig; i++){
751 const char *zSrc = x.aOrig[i].zSrc;
752 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
753 fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
 
 
 
 
 
 
 
 
754 }
755 }
756
757 /* Annotation flags */
758 #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
@@ -770,11 +810,10 @@
770 int iLimit, /* Limit the number of levels if greater than zero */
771 int annFlags /* Flags to alter the annotation */
772 ){
773 Blob step = empty_blob; /* Text of previous revision */
774 int rid; /* Artifact ID of the file being annotated */
775 char *zLabel; /* Label to apply to a line */
776 Stmt q; /* Query returning all ancestor versions */
777
778 /* Initialize the annotation */
779 rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
780 if( rid==0 ){
@@ -808,23 +847,31 @@
808 while( db_step(&q)==SQLITE_ROW ){
809 int pid = db_column_int(&q, 0);
810 const char *zUuid = db_column_text(&q, 1);
811 const char *zDate = db_column_text(&q, 2);
812 const char *zUser = db_column_text(&q, 3);
 
 
 
 
 
813 if( webLabel ){
814 zLabel = mprintf(
815 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
816 g.zTop, zUuid, zUuid, zDate, zUser
817 );
818 }else{
819 zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
820 }
 
821 p->nVers++;
822 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
823 p->azVers[p->nVers-1] = zLabel;
824 content_get(pid, &step);
825 annotation_step(p, &step, zLabel);
 
 
826 blob_reset(&step);
827 }
828 db_finalize(&q);
829 free(p->c.aTo);
830 }
@@ -860,20 +907,20 @@
860 if( P("log") ){
861 int i;
862 @ <h2>Versions analyzed:</h2>
863 @ <ol>
864 for(i=0; i<ann.nVers; i++){
865 @ <li><tt>%s(ann.azVers[i])</tt></li>
866 }
867 @ </ol>
868 @ <hr>
869 @ <h2>Annotation:</h2>
870 }
871 @ <pre>
872 for(i=0; i<ann.nOrig; i++){
873 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
874 @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
875 }
876 @ </pre>
877 style_footer();
878 }
879
@@ -930,17 +977,25 @@
930 }
931 if( fileVers ) annFlags |= ANN_FILE_VERS;
932 annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
933 if( showLog ){
934 for(i=0; i<ann.nVers; i++){
935 printf("version %3d: %s\n", i+1, ann.azVers[i]);
936 }
937 printf("---------------------------------------------------\n");
938 }
939 for(i=0; i<ann.nOrig; i++){
940 fossil_print("%s: %.*s\n",
941 ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
942 }
943 free(ann.azVers);
944 free(ann.aOrig);
945 blob_reset(&ann.toAnnotate);
 
 
 
 
 
 
 
 
946 }
947
--- src/diff.c
+++ src/diff.c
@@ -619,10 +619,24 @@
619 /**************************************************************************
620 ** The basic difference engine is above. What follows is the annotation
621 ** engine. Both are in the same file since they share many components.
622 */
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
638 /*
639 ** The status of an annotation operation is recorded by an instance
640 ** of the following structure.
641 */
642 typedef struct Annotator Annotator;
@@ -630,18 +644,19 @@
644 DContext c; /* The diff-engine context */
645 struct AnnLine { /* Lines of the original files... */
646 const char *z; /* The text of the line */
647 short int n; /* Number of bytes (omitting trailing space and \n) */
648 short int iLevel; /* Level at which tag was set */
649 struct Label *zSrc; /* Tag showing origin of this line */
650 } *aOrig;
651 int nOrig; /* Number of elements in aOrig[] */
652 int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
653 int iLevel; /* Current level */
654 int nVers; /* Number of versions analyzed */
655 struct Label **azVers; /* Names of versions analyzed */
656 Blob toAnnotate;
657 struct Label *firstLabel;
658 };
659
660 /*
661 ** Initialize the annotation process by specifying the file that is
662 ** to be annotated. The annotator takes control of the input Blob and
@@ -670,11 +685,11 @@
685 ** being annotated. Do another step of the annotation. Return true
686 ** if additional annotation is required. zPName is the tag to insert
687 ** on each line of the file being annotated that was contributed by
688 ** pParent. Memory to hold zPName is leaked.
689 */
690 static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){
691 int i, j;
692 int lnTo;
693 int iPrevLevel;
694 int iThisLevel;
695
@@ -698,13 +713,22 @@
713 iThisLevel = p->iLevel;
714 for(i=lnTo=0; i<p->c.nEdit; i+=3){
715 struct AnnLine *x = &p->aOrig[lnTo];
716 for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
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 x->zSrc->prev->next = x->zSrc->next;
724 x->zSrc->next->prev = x->zSrc->prev;
725 free(x->zSrc);
726 }
727 }
728 x->zSrc = zPName;
729 ++zPName->nref;
730 x->iLevel = iThisLevel;
731 }
732 }
733 lnTo += p->c.aEdit[i+2];
734 }
@@ -739,20 +763,36 @@
763 content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
764 if( annotation_start(&x) ){
765 fossil_fatal("binary file");
766 }
767 for(i=3; i<g.argc; i++){
768 struct Label *l;
769 blob_zero(&b);
770 content_get(name_to_rid(g.argv[i]), &b);
771 l = fossil_malloc(sizeof(*l));
772 l->str = g.argv[i-1];
773 l->nref = 0;
774 l->next = x.firstLabel;
775 if (x.firstLabel)
776 x.firstLabel->prev = l;
777 x.firstLabel = l;
778 if( annotation_step(&x, &b, l) ){
779 fossil_fatal("binary file");
780 }
781 }
782 for(i=0; i<x.nOrig; i++){
783 const char *zSrc = x.aOrig[i].zSrc->str;
784 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
785 fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
786 }
787 while(x.firstLabel) {
788 struct Label *l;
789 l = x.firstLabel->next;
790 assert(x.firstLabel->nref > 0);
791 free(x.firstLabel->str);
792 free(x.firstLabel);
793 x.firstLabel = l;
794 }
795 }
796
797 /* Annotation flags */
798 #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
@@ -770,11 +810,10 @@
810 int iLimit, /* Limit the number of levels if greater than zero */
811 int annFlags /* Flags to alter the annotation */
812 ){
813 Blob step = empty_blob; /* Text of previous revision */
814 int rid; /* Artifact ID of the file being annotated */
 
815 Stmt q; /* Query returning all ancestor versions */
816
817 /* Initialize the annotation */
818 rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
819 if( rid==0 ){
@@ -808,23 +847,31 @@
847 while( db_step(&q)==SQLITE_ROW ){
848 int pid = db_column_int(&q, 0);
849 const char *zUuid = db_column_text(&q, 1);
850 const char *zDate = db_column_text(&q, 2);
851 const char *zUser = db_column_text(&q, 3);
852 struct Label *l = fossil_malloc(sizeof(*l));
853 l->nref = 0;
854 l->next = p->firstLabel;
855 if (p->firstLabel)
856 p->firstLabel->prev = l;
857 if( webLabel ){
858 l->str = mprintf(
859 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
860 g.zTop, zUuid, zUuid, zDate, zUser
861 );
862 }else{
863 l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
864 }
865 p->firstLabel = l;
866 p->nVers++;
867 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
868 p->azVers[p->nVers-1] = l;
869 content_get(pid, &step);
870 annotation_step(p, &step, l);
871 if (l->nref == 0)
872 free(l->str);
873 blob_reset(&step);
874 }
875 db_finalize(&q);
876 free(p->c.aTo);
877 }
@@ -860,20 +907,20 @@
907 if( P("log") ){
908 int i;
909 @ <h2>Versions analyzed:</h2>
910 @ <ol>
911 for(i=0; i<ann.nVers; i++){
912 @ <li><tt>%s(ann.azVers[i]->str)</tt></li>
913 }
914 @ </ol>
915 @ <hr>
916 @ <h2>Annotation:</h2>
917 }
918 @ <pre>
919 for(i=0; i<ann.nOrig; i++){
920 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
921 @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z)
922 }
923 @ </pre>
924 style_footer();
925 }
926
@@ -930,17 +977,25 @@
977 }
978 if( fileVers ) annFlags |= ANN_FILE_VERS;
979 annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
980 if( showLog ){
981 for(i=0; i<ann.nVers; i++){
982 printf("version %3d: %s\n", i+1, ann.azVers[i]->str);
983 }
984 printf("---------------------------------------------------\n");
985 }
986 for(i=0; i<ann.nOrig; i++){
987 fossil_print("%s: %.*s\n",
988 ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z);
989 }
990 free(ann.azVers);
991 free(ann.aOrig);
992 blob_reset(&ann.toAnnotate);
993 while(ann.firstLabel) {
994 struct Label *l;
995 l = ann.firstLabel->next;
996 assert(ann.firstLabel->nref > 0);
997 free(ann.firstLabel->str);
998 free(ann.firstLabel);
999 ann.firstLabel = l;
1000 }
1001 }
1002

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button