Fossil SCM

Implementation of a linked list to solve the memory leak described in a TODO in [e2ebb1f5cae8]

viriketo 2011-09-04 22:14 UTC label_linkedlist
Commit ef8266b710505ed189f1d016aff319fabcbd8acf
1 file changed +64 -16
+64 -16
--- src/diff.c
+++ src/diff.c
@@ -624,24 +624,32 @@
624624
/*
625625
** The status of an annotation operation is recorded by an instance
626626
** of the following structure.
627627
*/
628628
typedef struct Annotator Annotator;
629
+struct Label
630
+{
631
+ struct Label *prev;
632
+ struct Label *next;
633
+ char *str;
634
+ int nref;
635
+};
629636
struct Annotator {
630637
DContext c; /* The diff-engine context */
631638
struct AnnLine { /* Lines of the original files... */
632639
const char *z; /* The text of the line */
633640
short int n; /* Number of bytes (omitting trailing space and \n) */
634641
short int iLevel; /* Level at which tag was set */
635
- const char *zSrc; /* Tag showing origin of this line */
642
+ struct Label *zSrc; /* Tag showing origin of this line */
636643
} *aOrig;
637644
int nOrig; /* Number of elements in aOrig[] */
638645
int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
639646
int iLevel; /* Current level */
640647
int nVers; /* Number of versions analyzed */
641
- char **azVers; /* Names of versions analyzed */
648
+ struct Label **azVers; /* Names of versions analyzed */
642649
Blob toAnnotate;
650
+ struct Label *firstLabel;
643651
};
644652
645653
/*
646654
** Initialize the annotation process by specifying the file that is
647655
** to be annotated. The annotator takes control of the input Blob and
@@ -670,11 +678,11 @@
670678
** being annotated. Do another step of the annotation. Return true
671679
** if additional annotation is required. zPName is the tag to insert
672680
** on each line of the file being annotated that was contributed by
673681
** pParent. Memory to hold zPName is leaked.
674682
*/
675
-static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
683
+static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){
676684
int i, j;
677685
int lnTo;
678686
int iPrevLevel;
679687
int iThisLevel;
680688
@@ -698,13 +706,22 @@
698706
iThisLevel = p->iLevel;
699707
for(i=lnTo=0; i<p->c.nEdit; i+=3){
700708
struct AnnLine *x = &p->aOrig[lnTo];
701709
for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
702710
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 */
711
+ if (x->zSrc!=0)
712
+ {
713
+ if(--x->zSrc->nref == 0)
714
+ {
715
+ free(x->zSrc->str);
716
+ x->zSrc->prev->next = x->zSrc->next;
717
+ x->zSrc->next->prev = x->zSrc->prev;
718
+ free(x->zSrc);
719
+ }
720
+ }
705721
x->zSrc = zPName;
722
+ ++zPName->nref;
706723
x->iLevel = iThisLevel;
707724
}
708725
}
709726
lnTo += p->c.aEdit[i+2];
710727
}
@@ -739,20 +756,36 @@
739756
content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
740757
if( annotation_start(&x) ){
741758
fossil_fatal("binary file");
742759
}
743760
for(i=3; i<g.argc; i++){
761
+ struct Label *l;
744762
blob_zero(&b);
745763
content_get(name_to_rid(g.argv[i]), &b);
746
- if( annotation_step(&x, &b, g.argv[i-1]) ){
764
+ l = fossil_malloc(sizeof(*l));
765
+ l->str = g.argv[i-1];
766
+ l->nref = 0;
767
+ l->next = x.firstLabel;
768
+ if (x.firstLabel)
769
+ x.firstLabel->prev = l;
770
+ x.firstLabel = l;
771
+ if( annotation_step(&x, &b, l) ){
747772
fossil_fatal("binary file");
748773
}
749774
}
750775
for(i=0; i<x.nOrig; i++){
751
- const char *zSrc = x.aOrig[i].zSrc;
776
+ const char *zSrc = x.aOrig[i].zSrc->str;
752777
if( zSrc==0 ) zSrc = g.argv[g.argc-1];
753778
fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
779
+ }
780
+ while(x.firstLabel) {
781
+ struct Label *l;
782
+ l = x.firstLabel->next;
783
+ assert(x.firstLabel->nref > 0);
784
+ free(x.firstLabel->str);
785
+ free(x.firstLabel);
786
+ x.firstLabel = l;
754787
}
755788
}
756789
757790
/* Annotation flags */
758791
#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
@@ -770,11 +803,10 @@
770803
int iLimit, /* Limit the number of levels if greater than zero */
771804
int annFlags /* Flags to alter the annotation */
772805
){
773806
Blob step = empty_blob; /* Text of previous revision */
774807
int rid; /* Artifact ID of the file being annotated */
775
- char *zLabel; /* Label to apply to a line */
776808
Stmt q; /* Query returning all ancestor versions */
777809
778810
/* Initialize the annotation */
779811
rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
780812
if( rid==0 ){
@@ -808,23 +840,31 @@
808840
while( db_step(&q)==SQLITE_ROW ){
809841
int pid = db_column_int(&q, 0);
810842
const char *zUuid = db_column_text(&q, 1);
811843
const char *zDate = db_column_text(&q, 2);
812844
const char *zUser = db_column_text(&q, 3);
845
+ struct Label *l = fossil_malloc(sizeof(*l));
846
+ l->nref = 0;
847
+ l->next = p->firstLabel;
848
+ if (p->firstLabel)
849
+ p->firstLabel->prev = l;
813850
if( webLabel ){
814
- zLabel = mprintf(
851
+ l->str = mprintf(
815852
"<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
816853
g.zTop, zUuid, zUuid, zDate, zUser
817854
);
818855
}else{
819
- zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
856
+ l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
820857
}
858
+ p->firstLabel = l;
821859
p->nVers++;
822860
p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
823
- p->azVers[p->nVers-1] = zLabel;
861
+ p->azVers[p->nVers-1] = l;
824862
content_get(pid, &step);
825
- annotation_step(p, &step, zLabel);
863
+ annotation_step(p, &step, l);
864
+ if (l->nref == 0)
865
+ free(l->str);
826866
blob_reset(&step);
827867
}
828868
db_finalize(&q);
829869
free(p->c.aTo);
830870
}
@@ -860,20 +900,20 @@
860900
if( P("log") ){
861901
int i;
862902
@ <h2>Versions analyzed:</h2>
863903
@ <ol>
864904
for(i=0; i<ann.nVers; i++){
865
- @ <li><tt>%s(ann.azVers[i])</tt></li>
905
+ @ <li><tt>%s(ann.azVers[i]->str)</tt></li>
866906
}
867907
@ </ol>
868908
@ <hr>
869909
@ <h2>Annotation:</h2>
870910
}
871911
@ <pre>
872912
for(i=0; i<ann.nOrig; i++){
873913
((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
874
- @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
914
+ @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z)
875915
}
876916
@ </pre>
877917
style_footer();
878918
}
879919
@@ -930,17 +970,25 @@
930970
}
931971
if( fileVers ) annFlags |= ANN_FILE_VERS;
932972
annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
933973
if( showLog ){
934974
for(i=0; i<ann.nVers; i++){
935
- printf("version %3d: %s\n", i+1, ann.azVers[i]);
975
+ printf("version %3d: %s\n", i+1, ann.azVers[i]->str);
936976
}
937977
printf("---------------------------------------------------\n");
938978
}
939979
for(i=0; i<ann.nOrig; i++){
940980
fossil_print("%s: %.*s\n",
941
- ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
981
+ ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z);
942982
}
943983
free(ann.azVers);
944984
free(ann.aOrig);
945985
blob_reset(&ann.toAnnotate);
986
+ while(ann.firstLabel) {
987
+ struct Label *l;
988
+ l = ann.firstLabel->next;
989
+ assert(ann.firstLabel->nref > 0);
990
+ free(ann.firstLabel->str);
991
+ free(ann.firstLabel);
992
+ ann.firstLabel = l;
993
+ }
946994
}
947995
--- src/diff.c
+++ src/diff.c
@@ -624,24 +624,32 @@
624 /*
625 ** The status of an annotation operation is recorded by an instance
626 ** of the following structure.
627 */
628 typedef struct Annotator Annotator;
 
 
 
 
 
 
 
629 struct Annotator {
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 +678,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 +706,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 +756,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 +803,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 +840,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 +900,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 +970,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
@@ -624,24 +624,32 @@
624 /*
625 ** The status of an annotation operation is recorded by an instance
626 ** of the following structure.
627 */
628 typedef struct Annotator Annotator;
629 struct Label
630 {
631 struct Label *prev;
632 struct Label *next;
633 char *str;
634 int nref;
635 };
636 struct Annotator {
637 DContext c; /* The diff-engine context */
638 struct AnnLine { /* Lines of the original files... */
639 const char *z; /* The text of the line */
640 short int n; /* Number of bytes (omitting trailing space and \n) */
641 short int iLevel; /* Level at which tag was set */
642 struct Label *zSrc; /* Tag showing origin of this line */
643 } *aOrig;
644 int nOrig; /* Number of elements in aOrig[] */
645 int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */
646 int iLevel; /* Current level */
647 int nVers; /* Number of versions analyzed */
648 struct Label **azVers; /* Names of versions analyzed */
649 Blob toAnnotate;
650 struct Label *firstLabel;
651 };
652
653 /*
654 ** Initialize the annotation process by specifying the file that is
655 ** to be annotated. The annotator takes control of the input Blob and
@@ -670,11 +678,11 @@
678 ** being annotated. Do another step of the annotation. Return true
679 ** if additional annotation is required. zPName is the tag to insert
680 ** on each line of the file being annotated that was contributed by
681 ** pParent. Memory to hold zPName is leaked.
682 */
683 static int annotation_step(Annotator *p, Blob *pParent, struct Label *zPName){
684 int i, j;
685 int lnTo;
686 int iPrevLevel;
687 int iThisLevel;
688
@@ -698,13 +706,22 @@
706 iThisLevel = p->iLevel;
707 for(i=lnTo=0; i<p->c.nEdit; i+=3){
708 struct AnnLine *x = &p->aOrig[lnTo];
709 for(j=0; j<p->c.aEdit[i]; j++, lnTo++, x++){
710 if( x->zSrc==0 || x->iLevel==iPrevLevel ){
711 if (x->zSrc!=0)
712 {
713 if(--x->zSrc->nref == 0)
714 {
715 free(x->zSrc->str);
716 x->zSrc->prev->next = x->zSrc->next;
717 x->zSrc->next->prev = x->zSrc->prev;
718 free(x->zSrc);
719 }
720 }
721 x->zSrc = zPName;
722 ++zPName->nref;
723 x->iLevel = iThisLevel;
724 }
725 }
726 lnTo += p->c.aEdit[i+2];
727 }
@@ -739,20 +756,36 @@
756 content_get(name_to_rid(g.argv[2]), &x.toAnnotate);
757 if( annotation_start(&x) ){
758 fossil_fatal("binary file");
759 }
760 for(i=3; i<g.argc; i++){
761 struct Label *l;
762 blob_zero(&b);
763 content_get(name_to_rid(g.argv[i]), &b);
764 l = fossil_malloc(sizeof(*l));
765 l->str = g.argv[i-1];
766 l->nref = 0;
767 l->next = x.firstLabel;
768 if (x.firstLabel)
769 x.firstLabel->prev = l;
770 x.firstLabel = l;
771 if( annotation_step(&x, &b, l) ){
772 fossil_fatal("binary file");
773 }
774 }
775 for(i=0; i<x.nOrig; i++){
776 const char *zSrc = x.aOrig[i].zSrc->str;
777 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
778 fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
779 }
780 while(x.firstLabel) {
781 struct Label *l;
782 l = x.firstLabel->next;
783 assert(x.firstLabel->nref > 0);
784 free(x.firstLabel->str);
785 free(x.firstLabel);
786 x.firstLabel = l;
787 }
788 }
789
790 /* Annotation flags */
791 #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
@@ -770,11 +803,10 @@
803 int iLimit, /* Limit the number of levels if greater than zero */
804 int annFlags /* Flags to alter the annotation */
805 ){
806 Blob step = empty_blob; /* Text of previous revision */
807 int rid; /* Artifact ID of the file being annotated */
 
808 Stmt q; /* Query returning all ancestor versions */
809
810 /* Initialize the annotation */
811 rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
812 if( rid==0 ){
@@ -808,23 +840,31 @@
840 while( db_step(&q)==SQLITE_ROW ){
841 int pid = db_column_int(&q, 0);
842 const char *zUuid = db_column_text(&q, 1);
843 const char *zDate = db_column_text(&q, 2);
844 const char *zUser = db_column_text(&q, 3);
845 struct Label *l = fossil_malloc(sizeof(*l));
846 l->nref = 0;
847 l->next = p->firstLabel;
848 if (p->firstLabel)
849 p->firstLabel->prev = l;
850 if( webLabel ){
851 l->str = mprintf(
852 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s",
853 g.zTop, zUuid, zUuid, zDate, zUser
854 );
855 }else{
856 l->str = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
857 }
858 p->firstLabel = l;
859 p->nVers++;
860 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
861 p->azVers[p->nVers-1] = l;
862 content_get(pid, &step);
863 annotation_step(p, &step, l);
864 if (l->nref == 0)
865 free(l->str);
866 blob_reset(&step);
867 }
868 db_finalize(&q);
869 free(p->c.aTo);
870 }
@@ -860,20 +900,20 @@
900 if( P("log") ){
901 int i;
902 @ <h2>Versions analyzed:</h2>
903 @ <ol>
904 for(i=0; i<ann.nVers; i++){
905 @ <li><tt>%s(ann.azVers[i]->str)</tt></li>
906 }
907 @ </ol>
908 @ <hr>
909 @ <h2>Annotation:</h2>
910 }
911 @ <pre>
912 for(i=0; i<ann.nOrig; i++){
913 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
914 @ %s(ann.aOrig[i].zSrc->str): %h(ann.aOrig[i].z)
915 }
916 @ </pre>
917 style_footer();
918 }
919
@@ -930,17 +970,25 @@
970 }
971 if( fileVers ) annFlags |= ANN_FILE_VERS;
972 annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
973 if( showLog ){
974 for(i=0; i<ann.nVers; i++){
975 printf("version %3d: %s\n", i+1, ann.azVers[i]->str);
976 }
977 printf("---------------------------------------------------\n");
978 }
979 for(i=0; i<ann.nOrig; i++){
980 fossil_print("%s: %.*s\n",
981 ann.aOrig[i].zSrc->str, ann.aOrig[i].n, ann.aOrig[i].z);
982 }
983 free(ann.azVers);
984 free(ann.aOrig);
985 blob_reset(&ann.toAnnotate);
986 while(ann.firstLabel) {
987 struct Label *l;
988 l = ann.firstLabel->next;
989 assert(ann.firstLabel->nref > 0);
990 free(ann.firstLabel->str);
991 free(ann.firstLabel);
992 ann.firstLabel = l;
993 }
994 }
995

Keyboard Shortcuts

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