Fossil SCM

merge from trunk

wolfgang 2010-10-09 15:39 wolfgangHelpCmd merge
Commit e1d15514fba78718c82831236a01a513ecef459a
2 files changed +103 -11 +103 -11
+103 -11
--- src/manifest.c
+++ src/manifest.c
@@ -83,10 +83,22 @@
8383
char *zValue; /* Value of the field */
8484
} *aField; /* One for each J card */
8585
};
8686
#endif
8787
88
+/*
89
+** A cache of parsed manifests. This reduces the number of
90
+** calls to manifest_parse() when doing a rebuild.
91
+*/
92
+#define MX_MANIFEST_CACHE 4
93
+static struct {
94
+ int nxAge;
95
+ int aRid[MX_MANIFEST_CACHE];
96
+ int aAge[MX_MANIFEST_CACHE];
97
+ Manifest aLine[MX_MANIFEST_CACHE];
98
+} manifestCache;
99
+
88100
89101
/*
90102
** Clear the memory allocated in a manifest object
91103
*/
92104
void manifest_clear(Manifest *p){
@@ -97,10 +109,69 @@
97109
free(p->aTag);
98110
free(p->aField);
99111
memset(p, 0, sizeof(*p));
100112
}
101113
114
+/*
115
+** Add an element to the manifest cache using LRU replacement.
116
+*/
117
+void manifest_cache_insert(int rid, Manifest *p){
118
+ int i;
119
+ for(i=0; i<MX_MANIFEST_CACHE; i++){
120
+ if( manifestCache.aRid[i]==0 ) break;
121
+ }
122
+ if( i>=MX_MANIFEST_CACHE ){
123
+ int oldest = 0;
124
+ int oldestAge = manifestCache.aAge[0];
125
+ for(i=1; i<MX_MANIFEST_CACHE; i++){
126
+ if( manifestCache.aAge[i]<oldestAge ){
127
+ oldest = i;
128
+ oldestAge = manifestCache.aAge[i];
129
+ }
130
+ }
131
+ manifest_clear(&manifestCache.aLine[oldest]);
132
+ i = oldest;
133
+ }
134
+ manifestCache.aAge[i] = ++manifestCache.nxAge;
135
+ manifestCache.aRid[i] = rid;
136
+ manifestCache.aLine[i] = *p;
137
+}
138
+
139
+/*
140
+** Try to extract a line from the manifest cache. Return 1 if found.
141
+** Return 0 if not found.
142
+*/
143
+int manifest_cache_find(int rid, Manifest *p){
144
+ int i;
145
+ for(i=0; i<MX_MANIFEST_CACHE; i++){
146
+ if( manifestCache.aRid[i]==rid ){
147
+ *p = manifestCache.aLine[i];
148
+ manifestCache.aRid[i] = 0;
149
+ return 1;
150
+ }
151
+ }
152
+ return 0;
153
+}
154
+
155
+/*
156
+** Clear the manifest cache.
157
+*/
158
+void manifest_cache_clear(void){
159
+ int i;
160
+ for(i=0; i<MX_MANIFEST_CACHE; i++){
161
+ if( manifestCache.aRid[i]>0 ){
162
+ manifest_clear(&manifestCache.aLine[i]);
163
+ }
164
+ }
165
+ memset(&manifestCache, 0, sizeof(manifestCache));
166
+}
167
+
168
+#ifdef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
169
+# define md5sum_init(X)
170
+# define md5sum_step_text(X,Y)
171
+#endif
172
+
102173
/*
103174
** Parse a blob into a Manifest object. The Manifest object
104175
** takes over the input blob and will free it when the
105176
** Manifest object is freed. Zeros are inserted into the blob
106177
** as string terminators so that blob should not be used again.
@@ -569,20 +640,24 @@
569640
** This card is required for all control file types except for
570641
** Manifest. It is not required for manifest only for historical
571642
** compatibility reasons.
572643
*/
573644
case 'Z': {
645
+#ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
574646
int rc;
575647
Blob hash;
648
+#endif
576649
if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
577650
if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
578651
if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
579652
if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
653
+#ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
580654
md5sum_finish(&hash);
581655
rc = blob_compare(&hash, &a1);
582656
blob_reset(&hash);
583657
if( rc!=0 ) goto manifest_syntax_error;
658
+#endif
584659
seenZ = 1;
585660
break;
586661
}
587662
default: {
588663
goto manifest_syntax_error;
@@ -686,24 +761,31 @@
686761
}
687762
688763
/*
689764
** COMMAND: test-parse-manifest
690765
**
691
-** Usage: %fossil test-parse-manifest FILENAME
766
+** Usage: %fossil test-parse-manifest FILENAME ?N?
692767
**
693768
** Parse the manifest and discarded. Use for testing only.
694769
*/
695770
void manifest_test_parse_cmd(void){
696771
Manifest m;
697772
Blob b;
698
- if( g.argc!=3 ){
773
+ int i;
774
+ int n = 1;
775
+ if( g.argc!=3 && g.argc!=4 ){
699776
usage("FILENAME");
700777
}
701778
db_must_be_within_tree();
702779
blob_read_from_file(&b, g.argv[2]);
703
- manifest_parse(&m, &b);
704
- manifest_clear(&m);
780
+ if( g.argc>3 ) n = atoi(g.argv[3]);
781
+ for(i=0; i<n; i++){
782
+ Blob b2;
783
+ blob_copy(&b2, &b);
784
+ manifest_parse(&m, &b2);
785
+ manifest_clear(&m);
786
+ }
705787
}
706788
707789
/*
708790
** Translate a filename into a filename-id (fnid). Create a new fnid
709791
** if no previously exists.
@@ -810,25 +892,29 @@
810892
** Edited files have both mlink.pid!=0 and mlink.fid!=0
811893
*/
812894
static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
813895
Manifest other;
814896
Blob otherContent;
897
+ int otherRid;
815898
int i, j;
816899
817900
if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
818901
return;
819902
}
820903
assert( pParent==0 || pChild==0 );
821904
if( pParent==0 ){
822905
pParent = &other;
823
- content_get(pid, &otherContent);
906
+ otherRid = pid;
824907
}else{
825908
pChild = &other;
826
- content_get(cid, &otherContent);
909
+ otherRid = cid;
827910
}
828
- if( blob_size(&otherContent)==0 ) return;
829
- if( manifest_parse(&other, &otherContent)==0 ) return;
911
+ if( manifest_cache_find(otherRid, &other)==0 ){
912
+ content_get(otherRid, &otherContent);
913
+ if( blob_size(&otherContent)==0 ) return;
914
+ if( manifest_parse(&other, &otherContent)==0 ) return;
915
+ }
830916
content_deltify(pid, cid, 0);
831917
832918
/* Use the iRename fields to find the cross-linkage between
833919
** renamed files. */
834920
for(j=0; j<pChild->nFile; j++){
@@ -882,11 +968,11 @@
882968
}else{
883969
add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
884970
}
885971
j++;
886972
}
887
- manifest_clear(&other);
973
+ manifest_cache_insert(otherRid, &other);
888974
}
889975
890976
/*
891977
** True if manifest_crosslink_begin() has been called but
892978
** manifest_crosslink_end() is still pending.
@@ -1027,11 +1113,13 @@
10271113
int i;
10281114
Manifest m;
10291115
Stmt q;
10301116
int parentid = 0;
10311117
1032
- if( manifest_parse(&m, pContent)==0 ){
1118
+ if( manifest_cache_find(rid, &m) ){
1119
+ blob_reset(pContent);
1120
+ }else if( manifest_parse(&m, pContent)==0 ){
10331121
return 0;
10341122
}
10351123
if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){
10361124
manifest_clear(&m);
10371125
return 0;
@@ -1263,11 +1351,15 @@
12631351
);
12641352
free(zComment);
12651353
}
12661354
}
12671355
db_end_transaction(0);
1268
- manifest_clear(&m);
1356
+ if( m.type==CFTYPE_MANIFEST ){
1357
+ manifest_cache_insert(rid, &m);
1358
+ }else{
1359
+ manifest_clear(&m);
1360
+ }
12691361
return 1;
12701362
}
12711363
12721364
/*
12731365
** Given a checkin name, load and parse the manifest for that checkin.
12741366
--- src/manifest.c
+++ src/manifest.c
@@ -83,10 +83,22 @@
83 char *zValue; /* Value of the field */
84 } *aField; /* One for each J card */
85 };
86 #endif
87
 
 
 
 
 
 
 
 
 
 
 
 
88
89 /*
90 ** Clear the memory allocated in a manifest object
91 */
92 void manifest_clear(Manifest *p){
@@ -97,10 +109,69 @@
97 free(p->aTag);
98 free(p->aField);
99 memset(p, 0, sizeof(*p));
100 }
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102 /*
103 ** Parse a blob into a Manifest object. The Manifest object
104 ** takes over the input blob and will free it when the
105 ** Manifest object is freed. Zeros are inserted into the blob
106 ** as string terminators so that blob should not be used again.
@@ -569,20 +640,24 @@
569 ** This card is required for all control file types except for
570 ** Manifest. It is not required for manifest only for historical
571 ** compatibility reasons.
572 */
573 case 'Z': {
 
574 int rc;
575 Blob hash;
 
576 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
577 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
578 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
579 if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
 
580 md5sum_finish(&hash);
581 rc = blob_compare(&hash, &a1);
582 blob_reset(&hash);
583 if( rc!=0 ) goto manifest_syntax_error;
 
584 seenZ = 1;
585 break;
586 }
587 default: {
588 goto manifest_syntax_error;
@@ -686,24 +761,31 @@
686 }
687
688 /*
689 ** COMMAND: test-parse-manifest
690 **
691 ** Usage: %fossil test-parse-manifest FILENAME
692 **
693 ** Parse the manifest and discarded. Use for testing only.
694 */
695 void manifest_test_parse_cmd(void){
696 Manifest m;
697 Blob b;
698 if( g.argc!=3 ){
 
 
699 usage("FILENAME");
700 }
701 db_must_be_within_tree();
702 blob_read_from_file(&b, g.argv[2]);
703 manifest_parse(&m, &b);
704 manifest_clear(&m);
 
 
 
 
 
705 }
706
707 /*
708 ** Translate a filename into a filename-id (fnid). Create a new fnid
709 ** if no previously exists.
@@ -810,25 +892,29 @@
810 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
811 */
812 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
813 Manifest other;
814 Blob otherContent;
 
815 int i, j;
816
817 if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
818 return;
819 }
820 assert( pParent==0 || pChild==0 );
821 if( pParent==0 ){
822 pParent = &other;
823 content_get(pid, &otherContent);
824 }else{
825 pChild = &other;
826 content_get(cid, &otherContent);
827 }
828 if( blob_size(&otherContent)==0 ) return;
829 if( manifest_parse(&other, &otherContent)==0 ) return;
 
 
 
830 content_deltify(pid, cid, 0);
831
832 /* Use the iRename fields to find the cross-linkage between
833 ** renamed files. */
834 for(j=0; j<pChild->nFile; j++){
@@ -882,11 +968,11 @@
882 }else{
883 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
884 }
885 j++;
886 }
887 manifest_clear(&other);
888 }
889
890 /*
891 ** True if manifest_crosslink_begin() has been called but
892 ** manifest_crosslink_end() is still pending.
@@ -1027,11 +1113,13 @@
1027 int i;
1028 Manifest m;
1029 Stmt q;
1030 int parentid = 0;
1031
1032 if( manifest_parse(&m, pContent)==0 ){
 
 
1033 return 0;
1034 }
1035 if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){
1036 manifest_clear(&m);
1037 return 0;
@@ -1263,11 +1351,15 @@
1263 );
1264 free(zComment);
1265 }
1266 }
1267 db_end_transaction(0);
1268 manifest_clear(&m);
 
 
 
 
1269 return 1;
1270 }
1271
1272 /*
1273 ** Given a checkin name, load and parse the manifest for that checkin.
1274
--- src/manifest.c
+++ src/manifest.c
@@ -83,10 +83,22 @@
83 char *zValue; /* Value of the field */
84 } *aField; /* One for each J card */
85 };
86 #endif
87
88 /*
89 ** A cache of parsed manifests. This reduces the number of
90 ** calls to manifest_parse() when doing a rebuild.
91 */
92 #define MX_MANIFEST_CACHE 4
93 static struct {
94 int nxAge;
95 int aRid[MX_MANIFEST_CACHE];
96 int aAge[MX_MANIFEST_CACHE];
97 Manifest aLine[MX_MANIFEST_CACHE];
98 } manifestCache;
99
100
101 /*
102 ** Clear the memory allocated in a manifest object
103 */
104 void manifest_clear(Manifest *p){
@@ -97,10 +109,69 @@
109 free(p->aTag);
110 free(p->aField);
111 memset(p, 0, sizeof(*p));
112 }
113
114 /*
115 ** Add an element to the manifest cache using LRU replacement.
116 */
117 void manifest_cache_insert(int rid, Manifest *p){
118 int i;
119 for(i=0; i<MX_MANIFEST_CACHE; i++){
120 if( manifestCache.aRid[i]==0 ) break;
121 }
122 if( i>=MX_MANIFEST_CACHE ){
123 int oldest = 0;
124 int oldestAge = manifestCache.aAge[0];
125 for(i=1; i<MX_MANIFEST_CACHE; i++){
126 if( manifestCache.aAge[i]<oldestAge ){
127 oldest = i;
128 oldestAge = manifestCache.aAge[i];
129 }
130 }
131 manifest_clear(&manifestCache.aLine[oldest]);
132 i = oldest;
133 }
134 manifestCache.aAge[i] = ++manifestCache.nxAge;
135 manifestCache.aRid[i] = rid;
136 manifestCache.aLine[i] = *p;
137 }
138
139 /*
140 ** Try to extract a line from the manifest cache. Return 1 if found.
141 ** Return 0 if not found.
142 */
143 int manifest_cache_find(int rid, Manifest *p){
144 int i;
145 for(i=0; i<MX_MANIFEST_CACHE; i++){
146 if( manifestCache.aRid[i]==rid ){
147 *p = manifestCache.aLine[i];
148 manifestCache.aRid[i] = 0;
149 return 1;
150 }
151 }
152 return 0;
153 }
154
155 /*
156 ** Clear the manifest cache.
157 */
158 void manifest_cache_clear(void){
159 int i;
160 for(i=0; i<MX_MANIFEST_CACHE; i++){
161 if( manifestCache.aRid[i]>0 ){
162 manifest_clear(&manifestCache.aLine[i]);
163 }
164 }
165 memset(&manifestCache, 0, sizeof(manifestCache));
166 }
167
168 #ifdef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
169 # define md5sum_init(X)
170 # define md5sum_step_text(X,Y)
171 #endif
172
173 /*
174 ** Parse a blob into a Manifest object. The Manifest object
175 ** takes over the input blob and will free it when the
176 ** Manifest object is freed. Zeros are inserted into the blob
177 ** as string terminators so that blob should not be used again.
@@ -569,20 +640,24 @@
640 ** This card is required for all control file types except for
641 ** Manifest. It is not required for manifest only for historical
642 ** compatibility reasons.
643 */
644 case 'Z': {
645 #ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
646 int rc;
647 Blob hash;
648 #endif
649 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
650 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
651 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
652 if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
653 #ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
654 md5sum_finish(&hash);
655 rc = blob_compare(&hash, &a1);
656 blob_reset(&hash);
657 if( rc!=0 ) goto manifest_syntax_error;
658 #endif
659 seenZ = 1;
660 break;
661 }
662 default: {
663 goto manifest_syntax_error;
@@ -686,24 +761,31 @@
761 }
762
763 /*
764 ** COMMAND: test-parse-manifest
765 **
766 ** Usage: %fossil test-parse-manifest FILENAME ?N?
767 **
768 ** Parse the manifest and discarded. Use for testing only.
769 */
770 void manifest_test_parse_cmd(void){
771 Manifest m;
772 Blob b;
773 int i;
774 int n = 1;
775 if( g.argc!=3 && g.argc!=4 ){
776 usage("FILENAME");
777 }
778 db_must_be_within_tree();
779 blob_read_from_file(&b, g.argv[2]);
780 if( g.argc>3 ) n = atoi(g.argv[3]);
781 for(i=0; i<n; i++){
782 Blob b2;
783 blob_copy(&b2, &b);
784 manifest_parse(&m, &b2);
785 manifest_clear(&m);
786 }
787 }
788
789 /*
790 ** Translate a filename into a filename-id (fnid). Create a new fnid
791 ** if no previously exists.
@@ -810,25 +892,29 @@
892 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
893 */
894 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
895 Manifest other;
896 Blob otherContent;
897 int otherRid;
898 int i, j;
899
900 if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
901 return;
902 }
903 assert( pParent==0 || pChild==0 );
904 if( pParent==0 ){
905 pParent = &other;
906 otherRid = pid;
907 }else{
908 pChild = &other;
909 otherRid = cid;
910 }
911 if( manifest_cache_find(otherRid, &other)==0 ){
912 content_get(otherRid, &otherContent);
913 if( blob_size(&otherContent)==0 ) return;
914 if( manifest_parse(&other, &otherContent)==0 ) return;
915 }
916 content_deltify(pid, cid, 0);
917
918 /* Use the iRename fields to find the cross-linkage between
919 ** renamed files. */
920 for(j=0; j<pChild->nFile; j++){
@@ -882,11 +968,11 @@
968 }else{
969 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
970 }
971 j++;
972 }
973 manifest_cache_insert(otherRid, &other);
974 }
975
976 /*
977 ** True if manifest_crosslink_begin() has been called but
978 ** manifest_crosslink_end() is still pending.
@@ -1027,11 +1113,13 @@
1113 int i;
1114 Manifest m;
1115 Stmt q;
1116 int parentid = 0;
1117
1118 if( manifest_cache_find(rid, &m) ){
1119 blob_reset(pContent);
1120 }else if( manifest_parse(&m, pContent)==0 ){
1121 return 0;
1122 }
1123 if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){
1124 manifest_clear(&m);
1125 return 0;
@@ -1263,11 +1351,15 @@
1351 );
1352 free(zComment);
1353 }
1354 }
1355 db_end_transaction(0);
1356 if( m.type==CFTYPE_MANIFEST ){
1357 manifest_cache_insert(rid, &m);
1358 }else{
1359 manifest_clear(&m);
1360 }
1361 return 1;
1362 }
1363
1364 /*
1365 ** Given a checkin name, load and parse the manifest for that checkin.
1366
+103 -11
--- src/manifest.c
+++ src/manifest.c
@@ -83,10 +83,22 @@
8383
char *zValue; /* Value of the field */
8484
} *aField; /* One for each J card */
8585
};
8686
#endif
8787
88
+/*
89
+** A cache of parsed manifests. This reduces the number of
90
+** calls to manifest_parse() when doing a rebuild.
91
+*/
92
+#define MX_MANIFEST_CACHE 4
93
+static struct {
94
+ int nxAge;
95
+ int aRid[MX_MANIFEST_CACHE];
96
+ int aAge[MX_MANIFEST_CACHE];
97
+ Manifest aLine[MX_MANIFEST_CACHE];
98
+} manifestCache;
99
+
88100
89101
/*
90102
** Clear the memory allocated in a manifest object
91103
*/
92104
void manifest_clear(Manifest *p){
@@ -97,10 +109,69 @@
97109
free(p->aTag);
98110
free(p->aField);
99111
memset(p, 0, sizeof(*p));
100112
}
101113
114
+/*
115
+** Add an element to the manifest cache using LRU replacement.
116
+*/
117
+void manifest_cache_insert(int rid, Manifest *p){
118
+ int i;
119
+ for(i=0; i<MX_MANIFEST_CACHE; i++){
120
+ if( manifestCache.aRid[i]==0 ) break;
121
+ }
122
+ if( i>=MX_MANIFEST_CACHE ){
123
+ int oldest = 0;
124
+ int oldestAge = manifestCache.aAge[0];
125
+ for(i=1; i<MX_MANIFEST_CACHE; i++){
126
+ if( manifestCache.aAge[i]<oldestAge ){
127
+ oldest = i;
128
+ oldestAge = manifestCache.aAge[i];
129
+ }
130
+ }
131
+ manifest_clear(&manifestCache.aLine[oldest]);
132
+ i = oldest;
133
+ }
134
+ manifestCache.aAge[i] = ++manifestCache.nxAge;
135
+ manifestCache.aRid[i] = rid;
136
+ manifestCache.aLine[i] = *p;
137
+}
138
+
139
+/*
140
+** Try to extract a line from the manifest cache. Return 1 if found.
141
+** Return 0 if not found.
142
+*/
143
+int manifest_cache_find(int rid, Manifest *p){
144
+ int i;
145
+ for(i=0; i<MX_MANIFEST_CACHE; i++){
146
+ if( manifestCache.aRid[i]==rid ){
147
+ *p = manifestCache.aLine[i];
148
+ manifestCache.aRid[i] = 0;
149
+ return 1;
150
+ }
151
+ }
152
+ return 0;
153
+}
154
+
155
+/*
156
+** Clear the manifest cache.
157
+*/
158
+void manifest_cache_clear(void){
159
+ int i;
160
+ for(i=0; i<MX_MANIFEST_CACHE; i++){
161
+ if( manifestCache.aRid[i]>0 ){
162
+ manifest_clear(&manifestCache.aLine[i]);
163
+ }
164
+ }
165
+ memset(&manifestCache, 0, sizeof(manifestCache));
166
+}
167
+
168
+#ifdef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
169
+# define md5sum_init(X)
170
+# define md5sum_step_text(X,Y)
171
+#endif
172
+
102173
/*
103174
** Parse a blob into a Manifest object. The Manifest object
104175
** takes over the input blob and will free it when the
105176
** Manifest object is freed. Zeros are inserted into the blob
106177
** as string terminators so that blob should not be used again.
@@ -569,20 +640,24 @@
569640
** This card is required for all control file types except for
570641
** Manifest. It is not required for manifest only for historical
571642
** compatibility reasons.
572643
*/
573644
case 'Z': {
645
+#ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
574646
int rc;
575647
Blob hash;
648
+#endif
576649
if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
577650
if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
578651
if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
579652
if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
653
+#ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
580654
md5sum_finish(&hash);
581655
rc = blob_compare(&hash, &a1);
582656
blob_reset(&hash);
583657
if( rc!=0 ) goto manifest_syntax_error;
658
+#endif
584659
seenZ = 1;
585660
break;
586661
}
587662
default: {
588663
goto manifest_syntax_error;
@@ -686,24 +761,31 @@
686761
}
687762
688763
/*
689764
** COMMAND: test-parse-manifest
690765
**
691
-** Usage: %fossil test-parse-manifest FILENAME
766
+** Usage: %fossil test-parse-manifest FILENAME ?N?
692767
**
693768
** Parse the manifest and discarded. Use for testing only.
694769
*/
695770
void manifest_test_parse_cmd(void){
696771
Manifest m;
697772
Blob b;
698
- if( g.argc!=3 ){
773
+ int i;
774
+ int n = 1;
775
+ if( g.argc!=3 && g.argc!=4 ){
699776
usage("FILENAME");
700777
}
701778
db_must_be_within_tree();
702779
blob_read_from_file(&b, g.argv[2]);
703
- manifest_parse(&m, &b);
704
- manifest_clear(&m);
780
+ if( g.argc>3 ) n = atoi(g.argv[3]);
781
+ for(i=0; i<n; i++){
782
+ Blob b2;
783
+ blob_copy(&b2, &b);
784
+ manifest_parse(&m, &b2);
785
+ manifest_clear(&m);
786
+ }
705787
}
706788
707789
/*
708790
** Translate a filename into a filename-id (fnid). Create a new fnid
709791
** if no previously exists.
@@ -810,25 +892,29 @@
810892
** Edited files have both mlink.pid!=0 and mlink.fid!=0
811893
*/
812894
static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
813895
Manifest other;
814896
Blob otherContent;
897
+ int otherRid;
815898
int i, j;
816899
817900
if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
818901
return;
819902
}
820903
assert( pParent==0 || pChild==0 );
821904
if( pParent==0 ){
822905
pParent = &other;
823
- content_get(pid, &otherContent);
906
+ otherRid = pid;
824907
}else{
825908
pChild = &other;
826
- content_get(cid, &otherContent);
909
+ otherRid = cid;
827910
}
828
- if( blob_size(&otherContent)==0 ) return;
829
- if( manifest_parse(&other, &otherContent)==0 ) return;
911
+ if( manifest_cache_find(otherRid, &other)==0 ){
912
+ content_get(otherRid, &otherContent);
913
+ if( blob_size(&otherContent)==0 ) return;
914
+ if( manifest_parse(&other, &otherContent)==0 ) return;
915
+ }
830916
content_deltify(pid, cid, 0);
831917
832918
/* Use the iRename fields to find the cross-linkage between
833919
** renamed files. */
834920
for(j=0; j<pChild->nFile; j++){
@@ -882,11 +968,11 @@
882968
}else{
883969
add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
884970
}
885971
j++;
886972
}
887
- manifest_clear(&other);
973
+ manifest_cache_insert(otherRid, &other);
888974
}
889975
890976
/*
891977
** True if manifest_crosslink_begin() has been called but
892978
** manifest_crosslink_end() is still pending.
@@ -1027,11 +1113,13 @@
10271113
int i;
10281114
Manifest m;
10291115
Stmt q;
10301116
int parentid = 0;
10311117
1032
- if( manifest_parse(&m, pContent)==0 ){
1118
+ if( manifest_cache_find(rid, &m) ){
1119
+ blob_reset(pContent);
1120
+ }else if( manifest_parse(&m, pContent)==0 ){
10331121
return 0;
10341122
}
10351123
if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){
10361124
manifest_clear(&m);
10371125
return 0;
@@ -1263,11 +1351,15 @@
12631351
);
12641352
free(zComment);
12651353
}
12661354
}
12671355
db_end_transaction(0);
1268
- manifest_clear(&m);
1356
+ if( m.type==CFTYPE_MANIFEST ){
1357
+ manifest_cache_insert(rid, &m);
1358
+ }else{
1359
+ manifest_clear(&m);
1360
+ }
12691361
return 1;
12701362
}
12711363
12721364
/*
12731365
** Given a checkin name, load and parse the manifest for that checkin.
12741366
--- src/manifest.c
+++ src/manifest.c
@@ -83,10 +83,22 @@
83 char *zValue; /* Value of the field */
84 } *aField; /* One for each J card */
85 };
86 #endif
87
 
 
 
 
 
 
 
 
 
 
 
 
88
89 /*
90 ** Clear the memory allocated in a manifest object
91 */
92 void manifest_clear(Manifest *p){
@@ -97,10 +109,69 @@
97 free(p->aTag);
98 free(p->aField);
99 memset(p, 0, sizeof(*p));
100 }
101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102 /*
103 ** Parse a blob into a Manifest object. The Manifest object
104 ** takes over the input blob and will free it when the
105 ** Manifest object is freed. Zeros are inserted into the blob
106 ** as string terminators so that blob should not be used again.
@@ -569,20 +640,24 @@
569 ** This card is required for all control file types except for
570 ** Manifest. It is not required for manifest only for historical
571 ** compatibility reasons.
572 */
573 case 'Z': {
 
574 int rc;
575 Blob hash;
 
576 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
577 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
578 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
579 if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
 
580 md5sum_finish(&hash);
581 rc = blob_compare(&hash, &a1);
582 blob_reset(&hash);
583 if( rc!=0 ) goto manifest_syntax_error;
 
584 seenZ = 1;
585 break;
586 }
587 default: {
588 goto manifest_syntax_error;
@@ -686,24 +761,31 @@
686 }
687
688 /*
689 ** COMMAND: test-parse-manifest
690 **
691 ** Usage: %fossil test-parse-manifest FILENAME
692 **
693 ** Parse the manifest and discarded. Use for testing only.
694 */
695 void manifest_test_parse_cmd(void){
696 Manifest m;
697 Blob b;
698 if( g.argc!=3 ){
 
 
699 usage("FILENAME");
700 }
701 db_must_be_within_tree();
702 blob_read_from_file(&b, g.argv[2]);
703 manifest_parse(&m, &b);
704 manifest_clear(&m);
 
 
 
 
 
705 }
706
707 /*
708 ** Translate a filename into a filename-id (fnid). Create a new fnid
709 ** if no previously exists.
@@ -810,25 +892,29 @@
810 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
811 */
812 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
813 Manifest other;
814 Blob otherContent;
 
815 int i, j;
816
817 if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
818 return;
819 }
820 assert( pParent==0 || pChild==0 );
821 if( pParent==0 ){
822 pParent = &other;
823 content_get(pid, &otherContent);
824 }else{
825 pChild = &other;
826 content_get(cid, &otherContent);
827 }
828 if( blob_size(&otherContent)==0 ) return;
829 if( manifest_parse(&other, &otherContent)==0 ) return;
 
 
 
830 content_deltify(pid, cid, 0);
831
832 /* Use the iRename fields to find the cross-linkage between
833 ** renamed files. */
834 for(j=0; j<pChild->nFile; j++){
@@ -882,11 +968,11 @@
882 }else{
883 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
884 }
885 j++;
886 }
887 manifest_clear(&other);
888 }
889
890 /*
891 ** True if manifest_crosslink_begin() has been called but
892 ** manifest_crosslink_end() is still pending.
@@ -1027,11 +1113,13 @@
1027 int i;
1028 Manifest m;
1029 Stmt q;
1030 int parentid = 0;
1031
1032 if( manifest_parse(&m, pContent)==0 ){
 
 
1033 return 0;
1034 }
1035 if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){
1036 manifest_clear(&m);
1037 return 0;
@@ -1263,11 +1351,15 @@
1263 );
1264 free(zComment);
1265 }
1266 }
1267 db_end_transaction(0);
1268 manifest_clear(&m);
 
 
 
 
1269 return 1;
1270 }
1271
1272 /*
1273 ** Given a checkin name, load and parse the manifest for that checkin.
1274
--- src/manifest.c
+++ src/manifest.c
@@ -83,10 +83,22 @@
83 char *zValue; /* Value of the field */
84 } *aField; /* One for each J card */
85 };
86 #endif
87
88 /*
89 ** A cache of parsed manifests. This reduces the number of
90 ** calls to manifest_parse() when doing a rebuild.
91 */
92 #define MX_MANIFEST_CACHE 4
93 static struct {
94 int nxAge;
95 int aRid[MX_MANIFEST_CACHE];
96 int aAge[MX_MANIFEST_CACHE];
97 Manifest aLine[MX_MANIFEST_CACHE];
98 } manifestCache;
99
100
101 /*
102 ** Clear the memory allocated in a manifest object
103 */
104 void manifest_clear(Manifest *p){
@@ -97,10 +109,69 @@
109 free(p->aTag);
110 free(p->aField);
111 memset(p, 0, sizeof(*p));
112 }
113
114 /*
115 ** Add an element to the manifest cache using LRU replacement.
116 */
117 void manifest_cache_insert(int rid, Manifest *p){
118 int i;
119 for(i=0; i<MX_MANIFEST_CACHE; i++){
120 if( manifestCache.aRid[i]==0 ) break;
121 }
122 if( i>=MX_MANIFEST_CACHE ){
123 int oldest = 0;
124 int oldestAge = manifestCache.aAge[0];
125 for(i=1; i<MX_MANIFEST_CACHE; i++){
126 if( manifestCache.aAge[i]<oldestAge ){
127 oldest = i;
128 oldestAge = manifestCache.aAge[i];
129 }
130 }
131 manifest_clear(&manifestCache.aLine[oldest]);
132 i = oldest;
133 }
134 manifestCache.aAge[i] = ++manifestCache.nxAge;
135 manifestCache.aRid[i] = rid;
136 manifestCache.aLine[i] = *p;
137 }
138
139 /*
140 ** Try to extract a line from the manifest cache. Return 1 if found.
141 ** Return 0 if not found.
142 */
143 int manifest_cache_find(int rid, Manifest *p){
144 int i;
145 for(i=0; i<MX_MANIFEST_CACHE; i++){
146 if( manifestCache.aRid[i]==rid ){
147 *p = manifestCache.aLine[i];
148 manifestCache.aRid[i] = 0;
149 return 1;
150 }
151 }
152 return 0;
153 }
154
155 /*
156 ** Clear the manifest cache.
157 */
158 void manifest_cache_clear(void){
159 int i;
160 for(i=0; i<MX_MANIFEST_CACHE; i++){
161 if( manifestCache.aRid[i]>0 ){
162 manifest_clear(&manifestCache.aLine[i]);
163 }
164 }
165 memset(&manifestCache, 0, sizeof(manifestCache));
166 }
167
168 #ifdef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
169 # define md5sum_init(X)
170 # define md5sum_step_text(X,Y)
171 #endif
172
173 /*
174 ** Parse a blob into a Manifest object. The Manifest object
175 ** takes over the input blob and will free it when the
176 ** Manifest object is freed. Zeros are inserted into the blob
177 ** as string terminators so that blob should not be used again.
@@ -569,20 +640,24 @@
640 ** This card is required for all control file types except for
641 ** Manifest. It is not required for manifest only for historical
642 ** compatibility reasons.
643 */
644 case 'Z': {
645 #ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
646 int rc;
647 Blob hash;
648 #endif
649 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
650 if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error;
651 if( blob_size(&a1)!=32 ) goto manifest_syntax_error;
652 if( !validate16(blob_buffer(&a1), 32) ) goto manifest_syntax_error;
653 #ifndef FOSSIL_DONT_VERIFY_MANIFEST_MD5SUM
654 md5sum_finish(&hash);
655 rc = blob_compare(&hash, &a1);
656 blob_reset(&hash);
657 if( rc!=0 ) goto manifest_syntax_error;
658 #endif
659 seenZ = 1;
660 break;
661 }
662 default: {
663 goto manifest_syntax_error;
@@ -686,24 +761,31 @@
761 }
762
763 /*
764 ** COMMAND: test-parse-manifest
765 **
766 ** Usage: %fossil test-parse-manifest FILENAME ?N?
767 **
768 ** Parse the manifest and discarded. Use for testing only.
769 */
770 void manifest_test_parse_cmd(void){
771 Manifest m;
772 Blob b;
773 int i;
774 int n = 1;
775 if( g.argc!=3 && g.argc!=4 ){
776 usage("FILENAME");
777 }
778 db_must_be_within_tree();
779 blob_read_from_file(&b, g.argv[2]);
780 if( g.argc>3 ) n = atoi(g.argv[3]);
781 for(i=0; i<n; i++){
782 Blob b2;
783 blob_copy(&b2, &b);
784 manifest_parse(&m, &b2);
785 manifest_clear(&m);
786 }
787 }
788
789 /*
790 ** Translate a filename into a filename-id (fnid). Create a new fnid
791 ** if no previously exists.
@@ -810,25 +892,29 @@
892 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
893 */
894 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
895 Manifest other;
896 Blob otherContent;
897 int otherRid;
898 int i, j;
899
900 if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", cid) ){
901 return;
902 }
903 assert( pParent==0 || pChild==0 );
904 if( pParent==0 ){
905 pParent = &other;
906 otherRid = pid;
907 }else{
908 pChild = &other;
909 otherRid = cid;
910 }
911 if( manifest_cache_find(otherRid, &other)==0 ){
912 content_get(otherRid, &otherContent);
913 if( blob_size(&otherContent)==0 ) return;
914 if( manifest_parse(&other, &otherContent)==0 ) return;
915 }
916 content_deltify(pid, cid, 0);
917
918 /* Use the iRename fields to find the cross-linkage between
919 ** renamed files. */
920 for(j=0; j<pChild->nFile; j++){
@@ -882,11 +968,11 @@
968 }else{
969 add_one_mlink(cid, 0, pChild->aFile[j].zUuid, pChild->aFile[j].zName,0);
970 }
971 j++;
972 }
973 manifest_cache_insert(otherRid, &other);
974 }
975
976 /*
977 ** True if manifest_crosslink_begin() has been called but
978 ** manifest_crosslink_end() is still pending.
@@ -1027,11 +1113,13 @@
1113 int i;
1114 Manifest m;
1115 Stmt q;
1116 int parentid = 0;
1117
1118 if( manifest_cache_find(rid, &m) ){
1119 blob_reset(pContent);
1120 }else if( manifest_parse(&m, pContent)==0 ){
1121 return 0;
1122 }
1123 if( g.xlinkClusterOnly && m.type!=CFTYPE_CLUSTER ){
1124 manifest_clear(&m);
1125 return 0;
@@ -1263,11 +1351,15 @@
1351 );
1352 free(zComment);
1353 }
1354 }
1355 db_end_transaction(0);
1356 if( m.type==CFTYPE_MANIFEST ){
1357 manifest_cache_insert(rid, &m);
1358 }else{
1359 manifest_clear(&m);
1360 }
1361 return 1;
1362 }
1363
1364 /*
1365 ** Given a checkin name, load and parse the manifest for that checkin.
1366

Keyboard Shortcuts

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