Fossil SCM

Change the content_deltify() routine so that looks an array of candidate source artifacts and picks the one that gives the best delta.

drh 2017-09-19 01:36 trunk
Commit a4047a91e3dbf58d53923e209a7a3e0ccb23245318219775668dd9368c9b8436
+1 -1
--- src/branch.c
+++ src/branch.c
@@ -157,11 +157,11 @@
157157
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
158158
if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
159159
fossil_fatal("%s", g.zErrMsg);
160160
}
161161
assert( blob_is_reset(&branch) );
162
- content_deltify(rootid, brid, 0);
162
+ content_deltify(rootid, &brid, 1, 0);
163163
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164164
fossil_print("New branch: %s\n", zUuid);
165165
if( g.argc==3 ){
166166
fossil_print(
167167
"\n"
168168
--- src/branch.c
+++ src/branch.c
@@ -157,11 +157,11 @@
157 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
158 if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
159 fossil_fatal("%s", g.zErrMsg);
160 }
161 assert( blob_is_reset(&branch) );
162 content_deltify(rootid, brid, 0);
163 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164 fossil_print("New branch: %s\n", zUuid);
165 if( g.argc==3 ){
166 fossil_print(
167 "\n"
168
--- src/branch.c
+++ src/branch.c
@@ -157,11 +157,11 @@
157 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
158 if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
159 fossil_fatal("%s", g.zErrMsg);
160 }
161 assert( blob_is_reset(&branch) );
162 content_deltify(rootid, &brid, 1, 0);
163 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", brid);
164 fossil_print("New branch: %s\n", zUuid);
165 if( g.argc==3 ){
166 fossil_print(
167 "\n"
168
+2 -2
--- src/checkin.c
+++ src/checkin.c
@@ -2398,11 +2398,11 @@
23982398
blob_reset(&fname);
23992399
}
24002400
nrid = content_put(&content);
24012401
blob_reset(&content);
24022402
if( rid>0 ){
2403
- content_deltify(rid, nrid, 0);
2403
+ content_deltify(rid, &nrid, 1, 0);
24042404
}
24052405
db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
24062406
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
24072407
}
24082408
db_finalize(&q);
@@ -2505,11 +2505,11 @@
25052505
if( manifest_crosslink(nvid, &manifest,
25062506
dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
25072507
fossil_fatal("%s", g.zErrMsg);
25082508
}
25092509
assert( blob_is_reset(&manifest) );
2510
- content_deltify(vid, nvid, 0);
2510
+ content_deltify(vid, &nvid, 1, 0);
25112511
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
25122512
25132513
db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
25142514
" WHERE id=-4");
25152515
while( db_step(&q)==SQLITE_ROW ){
25162516
--- src/checkin.c
+++ src/checkin.c
@@ -2398,11 +2398,11 @@
2398 blob_reset(&fname);
2399 }
2400 nrid = content_put(&content);
2401 blob_reset(&content);
2402 if( rid>0 ){
2403 content_deltify(rid, nrid, 0);
2404 }
2405 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
2406 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
2407 }
2408 db_finalize(&q);
@@ -2505,11 +2505,11 @@
2505 if( manifest_crosslink(nvid, &manifest,
2506 dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
2507 fossil_fatal("%s", g.zErrMsg);
2508 }
2509 assert( blob_is_reset(&manifest) );
2510 content_deltify(vid, nvid, 0);
2511 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
2512
2513 db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
2514 " WHERE id=-4");
2515 while( db_step(&q)==SQLITE_ROW ){
2516
--- src/checkin.c
+++ src/checkin.c
@@ -2398,11 +2398,11 @@
2398 blob_reset(&fname);
2399 }
2400 nrid = content_put(&content);
2401 blob_reset(&content);
2402 if( rid>0 ){
2403 content_deltify(rid, &nrid, 1, 0);
2404 }
2405 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
2406 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
2407 }
2408 db_finalize(&q);
@@ -2505,11 +2505,11 @@
2505 if( manifest_crosslink(nvid, &manifest,
2506 dryRunFlag ? MC_NONE : MC_PERMIT_HOOKS)==0 ){
2507 fossil_fatal("%s", g.zErrMsg);
2508 }
2509 assert( blob_is_reset(&manifest) );
2510 content_deltify(vid, &nvid, 1, 0);
2511 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nvid);
2512
2513 db_prepare(&q, "SELECT uuid,merge FROM vmerge JOIN blob ON merge=rid"
2514 " WHERE id=-4");
2515 while( db_step(&q)==SQLITE_ROW ){
2516
+86 -35
--- src/content.c
+++ src/content.c
@@ -772,89 +772,140 @@
772772
db_bind_int(&s1, ":rid", rid);
773773
db_exec(&s1);
774774
}
775775
776776
/*
777
-** Change the storage of rid so that it is a delta of srcid.
777
+** Try to change the storage of rid so that it is a delta from one
778
+** of the artifacts given in aSrc[0]..aSrc[nSrc-1]. The aSrc[*] that
779
+** gives the smallest delta is choosen.
778780
**
779781
** If rid is already a delta from some other place then no
780
-** conversion occurs and this is a no-op unless force==1.
782
+** conversion occurs and this is a no-op unless force==1. If force==1,
783
+** then nSrc must also be 1.
781784
**
782785
** Never generate a delta that carries a private artifact into a public
783786
** artifact. Otherwise, when we go to send the public artifact on a
784787
** sync operation, the other end of the sync will never be able to receive
785788
** the source of the delta. It is OK to delta private->private and
786789
** public->private and public->public. Just no private->public delta.
787790
**
788
-** If srcid is a delta that depends on rid, then srcid is
789
-** converted to undeltaed text.
791
+** If aSrc[bestSrc] is already a dleta that depends on rid, then it is
792
+** converted to undeltaed text before the aSrc[bestSrc]->rid delta is
793
+** created, in order to prevent a delta loop.
790794
**
791
-** If either rid or srcid contain less than 50 bytes, or if the
795
+** If either rid or aSrc[i] contain less than 50 bytes, or if the
792796
** resulting delta does not achieve a compression of at least 25%
793797
** the rid is left untouched.
794798
**
795799
** Return 1 if a delta is made and 0 if no delta occurs.
796800
*/
797
-int content_deltify(int rid, int srcid, int force){
801
+int content_deltify(int rid, int *aSrc, int nSrc, int force){
798802
int s;
799
- Blob data, src, delta;
800
- Stmt s1, s2;
801
- int rc = 0;
803
+ Blob data; /* Content of rid */
804
+ Blob src; /* Content of aSrc[i] */
805
+ Blob delta; /* Delta from aSrc[i] to rid */
806
+ Blob bestDelta; /* Best delta seen so far */
807
+ int bestSrc = 0; /* Which aSrc is the source of the best delta */
808
+ int rc = 0; /* Value to return */
809
+ int i; /* Loop variable for aSrc[] */
802810
803
- if( srcid==rid ) return 0;
811
+ /* If rid is already a child (a delta) of some other artifact, return
812
+ ** immediately if the force flags is false
813
+ */
804814
if( !force && findSrcid(rid)>0 ) return 0;
805
- if( content_is_private(srcid) && !content_is_private(rid) ){
806
- return 0;
807
- }
808
- s = srcid;
809
- while( (s = findSrcid(s))>0 ){
810
- if( s==rid ){
811
- content_undelta(srcid);
812
- break;
813
- }
814
- }
815
- content_get(srcid, &src);
816
- if( blob_size(&src)<50 ){
817
- blob_reset(&src);
818
- return 0;
819
- }
815
+
816
+ /* Get the complete content of the object to be delta-ed. If the size
817
+ ** is less than 50 bytes, then there really is no point in trying to do
818
+ ** a delta, so return immediately
819
+ */
820820
content_get(rid, &data);
821821
if( blob_size(&data)<50 ){
822
- blob_reset(&src);
822
+ /* Do not try to create a delta for objects smaller than 50 bytes */
823823
blob_reset(&data);
824824
return 0;
825825
}
826
- blob_delta_create(&src, &data, &delta);
827
- if( blob_size(&delta) <= blob_size(&data)*0.75 ){
826
+ blob_init(&bestDelta, 0, 0);
827
+
828
+ /* Loop over all candidate delta sources */
829
+ for(i=0; i<nSrc; i++){
830
+ int srcid = aSrc[i];
831
+ if( srcid==rid ) continue;
832
+ if( content_is_private(srcid) && !content_is_private(rid) ) continue;
833
+
834
+ /* Compute all ancestors of srcid and make sure rid is not one of them.
835
+ ** If rid is an ancestor of srcid, then making rid a decendent of srcid
836
+ ** would create a delta loop. */
837
+ s = srcid;
838
+ while( (s = findSrcid(s))>0 ){
839
+ if( s==rid ){
840
+ content_undelta(srcid);
841
+ break;
842
+ }
843
+ }
844
+ if( s!=0 ) continue;
845
+
846
+ content_get(srcid, &src);
847
+ if( blob_size(&src)<50 ){
848
+ /* The source is smaller then 50 bytes, so don't bother trying to use it*/
849
+ blob_reset(&src);
850
+ continue;
851
+ }
852
+ blob_delta_create(&src, &data, &delta);
853
+ if( blob_size(&delta) < blob_size(&data)*0.75
854
+ && (bestSrc<0 || blob_size(&delta)<blob_size(&bestDelta))
855
+ ){
856
+ /* This is the best delta seen so far. Remember it */
857
+ blob_reset(&bestDelta);
858
+ bestDelta = delta;
859
+ bestSrc = srcid;
860
+ }else{
861
+ /* This delta is not a candidate for becoming the new parent of rid */
862
+ blob_reset(&delta);
863
+ }
864
+ blob_reset(&src);
865
+ }
866
+
867
+ /* If there is a winning candidate for the new parent of rid, then
868
+ ** make that candidate the new parent now */
869
+ if( bestSrc>0 ){
870
+ Stmt s1, s2; /* Statements used to create the delta */
828871
blob_compress(&delta, &delta);
829872
db_prepare(&s1, "UPDATE blob SET content=:data WHERE rid=%d", rid);
830
- db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, srcid);
831
- db_bind_blob(&s1, ":data", &delta);
873
+ db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, bestSrc);
874
+ db_bind_blob(&s1, ":data", &bestDelta);
832875
db_begin_transaction();
833876
db_exec(&s1);
834877
db_exec(&s2);
835878
db_end_transaction(0);
836879
db_finalize(&s1);
837880
db_finalize(&s2);
838881
verify_before_commit(rid);
839882
rc = 1;
840883
}
841
- blob_reset(&src);
842884
blob_reset(&data);
843
- blob_reset(&delta);
885
+ blob_reset(&bestDelta);
844886
return rc;
845887
}
846888
847889
/*
848890
** COMMAND: test-content-deltify
849891
**
850
-** Convert the content at RID into a delta from SRCID.
892
+** Usage: %fossil RID SRCID SRCID ... [-force]
893
+**
894
+** Convert the content at RID into a delta one of the from SRCIDs.
851895
*/
852896
void test_content_deltify_cmd(void){
853
- if( g.argc!=5 ) usage("RID SRCID FORCE");
897
+ int nSrc;
898
+ int *aSrc;
899
+ int i;
900
+ int bForce = find_option("force",0,0)!=0;
901
+ if( g.argc<3 ) usage("[--force] RID SRCID SRCID...");
902
+ aSrc = fossil_malloc( (g.argc-2)*sizeof(aSrc[0]) );
903
+ nSrc = 0;
904
+ for(i=2; i<g.argc; i++) aSrc[nSrc++] = atoi(g.argv[i]);
854905
db_must_be_within_tree();
855
- content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
906
+ content_deltify(atoi(g.argv[2]), aSrc, nSrc, bForce);
856907
}
857908
858909
/*
859910
** Return true if Blob p looks like it might be a parsable control artifact.
860911
*/
861912
--- src/content.c
+++ src/content.c
@@ -772,89 +772,140 @@
772 db_bind_int(&s1, ":rid", rid);
773 db_exec(&s1);
774 }
775
776 /*
777 ** Change the storage of rid so that it is a delta of srcid.
 
 
778 **
779 ** If rid is already a delta from some other place then no
780 ** conversion occurs and this is a no-op unless force==1.
 
781 **
782 ** Never generate a delta that carries a private artifact into a public
783 ** artifact. Otherwise, when we go to send the public artifact on a
784 ** sync operation, the other end of the sync will never be able to receive
785 ** the source of the delta. It is OK to delta private->private and
786 ** public->private and public->public. Just no private->public delta.
787 **
788 ** If srcid is a delta that depends on rid, then srcid is
789 ** converted to undeltaed text.
 
790 **
791 ** If either rid or srcid contain less than 50 bytes, or if the
792 ** resulting delta does not achieve a compression of at least 25%
793 ** the rid is left untouched.
794 **
795 ** Return 1 if a delta is made and 0 if no delta occurs.
796 */
797 int content_deltify(int rid, int srcid, int force){
798 int s;
799 Blob data, src, delta;
800 Stmt s1, s2;
801 int rc = 0;
 
 
 
 
802
803 if( srcid==rid ) return 0;
 
 
804 if( !force && findSrcid(rid)>0 ) return 0;
805 if( content_is_private(srcid) && !content_is_private(rid) ){
806 return 0;
807 }
808 s = srcid;
809 while( (s = findSrcid(s))>0 ){
810 if( s==rid ){
811 content_undelta(srcid);
812 break;
813 }
814 }
815 content_get(srcid, &src);
816 if( blob_size(&src)<50 ){
817 blob_reset(&src);
818 return 0;
819 }
820 content_get(rid, &data);
821 if( blob_size(&data)<50 ){
822 blob_reset(&src);
823 blob_reset(&data);
824 return 0;
825 }
826 blob_delta_create(&src, &data, &delta);
827 if( blob_size(&delta) <= blob_size(&data)*0.75 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
828 blob_compress(&delta, &delta);
829 db_prepare(&s1, "UPDATE blob SET content=:data WHERE rid=%d", rid);
830 db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, srcid);
831 db_bind_blob(&s1, ":data", &delta);
832 db_begin_transaction();
833 db_exec(&s1);
834 db_exec(&s2);
835 db_end_transaction(0);
836 db_finalize(&s1);
837 db_finalize(&s2);
838 verify_before_commit(rid);
839 rc = 1;
840 }
841 blob_reset(&src);
842 blob_reset(&data);
843 blob_reset(&delta);
844 return rc;
845 }
846
847 /*
848 ** COMMAND: test-content-deltify
849 **
850 ** Convert the content at RID into a delta from SRCID.
 
 
851 */
852 void test_content_deltify_cmd(void){
853 if( g.argc!=5 ) usage("RID SRCID FORCE");
 
 
 
 
 
 
 
854 db_must_be_within_tree();
855 content_deltify(atoi(g.argv[2]), atoi(g.argv[3]), atoi(g.argv[4]));
856 }
857
858 /*
859 ** Return true if Blob p looks like it might be a parsable control artifact.
860 */
861
--- src/content.c
+++ src/content.c
@@ -772,89 +772,140 @@
772 db_bind_int(&s1, ":rid", rid);
773 db_exec(&s1);
774 }
775
776 /*
777 ** Try to change the storage of rid so that it is a delta from one
778 ** of the artifacts given in aSrc[0]..aSrc[nSrc-1]. The aSrc[*] that
779 ** gives the smallest delta is choosen.
780 **
781 ** If rid is already a delta from some other place then no
782 ** conversion occurs and this is a no-op unless force==1. If force==1,
783 ** then nSrc must also be 1.
784 **
785 ** Never generate a delta that carries a private artifact into a public
786 ** artifact. Otherwise, when we go to send the public artifact on a
787 ** sync operation, the other end of the sync will never be able to receive
788 ** the source of the delta. It is OK to delta private->private and
789 ** public->private and public->public. Just no private->public delta.
790 **
791 ** If aSrc[bestSrc] is already a dleta that depends on rid, then it is
792 ** converted to undeltaed text before the aSrc[bestSrc]->rid delta is
793 ** created, in order to prevent a delta loop.
794 **
795 ** If either rid or aSrc[i] contain less than 50 bytes, or if the
796 ** resulting delta does not achieve a compression of at least 25%
797 ** the rid is left untouched.
798 **
799 ** Return 1 if a delta is made and 0 if no delta occurs.
800 */
801 int content_deltify(int rid, int *aSrc, int nSrc, int force){
802 int s;
803 Blob data; /* Content of rid */
804 Blob src; /* Content of aSrc[i] */
805 Blob delta; /* Delta from aSrc[i] to rid */
806 Blob bestDelta; /* Best delta seen so far */
807 int bestSrc = 0; /* Which aSrc is the source of the best delta */
808 int rc = 0; /* Value to return */
809 int i; /* Loop variable for aSrc[] */
810
811 /* If rid is already a child (a delta) of some other artifact, return
812 ** immediately if the force flags is false
813 */
814 if( !force && findSrcid(rid)>0 ) return 0;
815
816 /* Get the complete content of the object to be delta-ed. If the size
817 ** is less than 50 bytes, then there really is no point in trying to do
818 ** a delta, so return immediately
819 */
 
 
 
 
 
 
 
 
 
 
820 content_get(rid, &data);
821 if( blob_size(&data)<50 ){
822 /* Do not try to create a delta for objects smaller than 50 bytes */
823 blob_reset(&data);
824 return 0;
825 }
826 blob_init(&bestDelta, 0, 0);
827
828 /* Loop over all candidate delta sources */
829 for(i=0; i<nSrc; i++){
830 int srcid = aSrc[i];
831 if( srcid==rid ) continue;
832 if( content_is_private(srcid) && !content_is_private(rid) ) continue;
833
834 /* Compute all ancestors of srcid and make sure rid is not one of them.
835 ** If rid is an ancestor of srcid, then making rid a decendent of srcid
836 ** would create a delta loop. */
837 s = srcid;
838 while( (s = findSrcid(s))>0 ){
839 if( s==rid ){
840 content_undelta(srcid);
841 break;
842 }
843 }
844 if( s!=0 ) continue;
845
846 content_get(srcid, &src);
847 if( blob_size(&src)<50 ){
848 /* The source is smaller then 50 bytes, so don't bother trying to use it*/
849 blob_reset(&src);
850 continue;
851 }
852 blob_delta_create(&src, &data, &delta);
853 if( blob_size(&delta) < blob_size(&data)*0.75
854 && (bestSrc<0 || blob_size(&delta)<blob_size(&bestDelta))
855 ){
856 /* This is the best delta seen so far. Remember it */
857 blob_reset(&bestDelta);
858 bestDelta = delta;
859 bestSrc = srcid;
860 }else{
861 /* This delta is not a candidate for becoming the new parent of rid */
862 blob_reset(&delta);
863 }
864 blob_reset(&src);
865 }
866
867 /* If there is a winning candidate for the new parent of rid, then
868 ** make that candidate the new parent now */
869 if( bestSrc>0 ){
870 Stmt s1, s2; /* Statements used to create the delta */
871 blob_compress(&delta, &delta);
872 db_prepare(&s1, "UPDATE blob SET content=:data WHERE rid=%d", rid);
873 db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, bestSrc);
874 db_bind_blob(&s1, ":data", &bestDelta);
875 db_begin_transaction();
876 db_exec(&s1);
877 db_exec(&s2);
878 db_end_transaction(0);
879 db_finalize(&s1);
880 db_finalize(&s2);
881 verify_before_commit(rid);
882 rc = 1;
883 }
 
884 blob_reset(&data);
885 blob_reset(&bestDelta);
886 return rc;
887 }
888
889 /*
890 ** COMMAND: test-content-deltify
891 **
892 ** Usage: %fossil RID SRCID SRCID ... [-force]
893 **
894 ** Convert the content at RID into a delta one of the from SRCIDs.
895 */
896 void test_content_deltify_cmd(void){
897 int nSrc;
898 int *aSrc;
899 int i;
900 int bForce = find_option("force",0,0)!=0;
901 if( g.argc<3 ) usage("[--force] RID SRCID SRCID...");
902 aSrc = fossil_malloc( (g.argc-2)*sizeof(aSrc[0]) );
903 nSrc = 0;
904 for(i=2; i<g.argc; i++) aSrc[nSrc++] = atoi(g.argv[i]);
905 db_must_be_within_tree();
906 content_deltify(atoi(g.argv[2]), aSrc, nSrc, bForce);
907 }
908
909 /*
910 ** Return true if Blob p looks like it might be a parsable control artifact.
911 */
912
+1 -1
--- src/event.c
+++ src/event.c
@@ -332,11 +332,11 @@
332332
if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
333333
db_end_transaction(1);
334334
return 0;
335335
}
336336
assert( blob_is_reset(&event) );
337
- content_deltify(rid, nrid, 0);
337
+ content_deltify(rid, &nrid, 1, 0);
338338
db_end_transaction(0);
339339
return 1;
340340
}
341341
342342
/*
343343
--- src/event.c
+++ src/event.c
@@ -332,11 +332,11 @@
332 if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
333 db_end_transaction(1);
334 return 0;
335 }
336 assert( blob_is_reset(&event) );
337 content_deltify(rid, nrid, 0);
338 db_end_transaction(0);
339 return 1;
340 }
341
342 /*
343
--- src/event.c
+++ src/event.c
@@ -332,11 +332,11 @@
332 if( manifest_crosslink(nrid, &event, MC_NONE)==0 ){
333 db_end_transaction(1);
334 return 0;
335 }
336 assert( blob_is_reset(&event) );
337 content_deltify(rid, &nrid, 1, 0);
338 db_end_transaction(0);
339 return 1;
340 }
341
342 /*
343
--- src/json_branch.c
+++ src/json_branch.c
@@ -295,11 +295,11 @@
295295
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
296296
if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
297297
fossil_fatal("%s", g.zErrMsg);
298298
}
299299
assert( blob_is_reset(&branch) );
300
- content_deltify(rootid, brid, 0);
300
+ content_deltify(rootid, &brid, 1, 0);
301301
if( zNewRid ){
302302
*zNewRid = brid;
303303
}
304304
305305
/* Commit */
306306
--- src/json_branch.c
+++ src/json_branch.c
@@ -295,11 +295,11 @@
295 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
296 if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
297 fossil_fatal("%s", g.zErrMsg);
298 }
299 assert( blob_is_reset(&branch) );
300 content_deltify(rootid, brid, 0);
301 if( zNewRid ){
302 *zNewRid = brid;
303 }
304
305 /* Commit */
306
--- src/json_branch.c
+++ src/json_branch.c
@@ -295,11 +295,11 @@
295 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", brid);
296 if( manifest_crosslink(brid, &branch, MC_PERMIT_HOOKS)==0 ){
297 fossil_fatal("%s", g.zErrMsg);
298 }
299 assert( blob_is_reset(&branch) );
300 content_deltify(rootid, &brid, 1, 0);
301 if( zNewRid ){
302 *zNewRid = brid;
303 }
304
305 /* Commit */
306
+6 -6
--- src/manifest.c
+++ src/manifest.c
@@ -1246,11 +1246,11 @@
12461246
db_bind_int(&s1, ":mp", mperm);
12471247
db_bind_int(&s1, ":isaux", isPrimary==0);
12481248
db_exec(&s1);
12491249
}
12501250
if( pid && fid ){
1251
- content_deltify(pid, fid, 0);
1251
+ content_deltify(pid, &fid, 1, 0);
12521252
}
12531253
}
12541254
12551255
/*
12561256
** Do a binary search to find a file in the p->aFile[] array.
@@ -1435,13 +1435,13 @@
14351435
/* Try to make the parent manifest a delta from the child, if that
14361436
** is an appropriate thing to do. For a new baseline, make the
14371437
** previous baseline a delta from the current baseline.
14381438
*/
14391439
if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1440
- content_deltify(pmid, mid, 0);
1440
+ content_deltify(pmid, &mid, 1, 0);
14411441
}else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1442
- content_deltify(pParent->pBaseline->rid, mid, 0);
1442
+ content_deltify(pParent->pBaseline->rid, &mid, 1, 0);
14431443
}
14441444
14451445
/* Remember all children less than a few seconds younger than their parent,
14461446
** as we might want to fudge the times for those children.
14471447
*/
@@ -2059,11 +2059,11 @@
20592059
" WHERE tagid=%d AND mtime<%.17g"
20602060
" ORDER BY mtime DESC",
20612061
tagid, p->rDate
20622062
);
20632063
if( prior ){
2064
- content_deltify(prior, rid, 0);
2064
+ content_deltify(prior, &rid, 1, 0);
20652065
}
20662066
if( nWiki>0 ){
20672067
zComment = mprintf("Changes to wiki page [%h]", p->zWikiTitle);
20682068
}else{
20692069
zComment = mprintf("Deleted wiki page [%h]", p->zWikiTitle);
@@ -2106,11 +2106,11 @@
21062106
" WHERE tagid=%d AND mtime>=%.17g AND rid!=%d"
21072107
" ORDER BY mtime",
21082108
tagid, p->rDate, rid
21092109
);
21102110
if( prior ){
2111
- content_deltify(prior, rid, 0);
2111
+ content_deltify(prior, &rid, 1, 0);
21122112
if( !subsequent ){
21132113
db_multi_exec(
21142114
"DELETE FROM event"
21152115
" WHERE type='e'"
21162116
" AND tagid=%d"
@@ -2118,11 +2118,11 @@
21182118
tagid, tagid
21192119
);
21202120
}
21212121
}
21222122
if( subsequent ){
2123
- content_deltify(rid, subsequent, 0);
2123
+ content_deltify(rid, &subsequent, 1, 0);
21242124
}else{
21252125
search_doc_touch('e',rid,0);
21262126
db_multi_exec(
21272127
"REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
21282128
"VALUES('e',%.17g,%d,%d,%Q,%Q,"
21292129
--- src/manifest.c
+++ src/manifest.c
@@ -1246,11 +1246,11 @@
1246 db_bind_int(&s1, ":mp", mperm);
1247 db_bind_int(&s1, ":isaux", isPrimary==0);
1248 db_exec(&s1);
1249 }
1250 if( pid && fid ){
1251 content_deltify(pid, fid, 0);
1252 }
1253 }
1254
1255 /*
1256 ** Do a binary search to find a file in the p->aFile[] array.
@@ -1435,13 +1435,13 @@
1435 /* Try to make the parent manifest a delta from the child, if that
1436 ** is an appropriate thing to do. For a new baseline, make the
1437 ** previous baseline a delta from the current baseline.
1438 */
1439 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1440 content_deltify(pmid, mid, 0);
1441 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1442 content_deltify(pParent->pBaseline->rid, mid, 0);
1443 }
1444
1445 /* Remember all children less than a few seconds younger than their parent,
1446 ** as we might want to fudge the times for those children.
1447 */
@@ -2059,11 +2059,11 @@
2059 " WHERE tagid=%d AND mtime<%.17g"
2060 " ORDER BY mtime DESC",
2061 tagid, p->rDate
2062 );
2063 if( prior ){
2064 content_deltify(prior, rid, 0);
2065 }
2066 if( nWiki>0 ){
2067 zComment = mprintf("Changes to wiki page [%h]", p->zWikiTitle);
2068 }else{
2069 zComment = mprintf("Deleted wiki page [%h]", p->zWikiTitle);
@@ -2106,11 +2106,11 @@
2106 " WHERE tagid=%d AND mtime>=%.17g AND rid!=%d"
2107 " ORDER BY mtime",
2108 tagid, p->rDate, rid
2109 );
2110 if( prior ){
2111 content_deltify(prior, rid, 0);
2112 if( !subsequent ){
2113 db_multi_exec(
2114 "DELETE FROM event"
2115 " WHERE type='e'"
2116 " AND tagid=%d"
@@ -2118,11 +2118,11 @@
2118 tagid, tagid
2119 );
2120 }
2121 }
2122 if( subsequent ){
2123 content_deltify(rid, subsequent, 0);
2124 }else{
2125 search_doc_touch('e',rid,0);
2126 db_multi_exec(
2127 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
2128 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
2129
--- src/manifest.c
+++ src/manifest.c
@@ -1246,11 +1246,11 @@
1246 db_bind_int(&s1, ":mp", mperm);
1247 db_bind_int(&s1, ":isaux", isPrimary==0);
1248 db_exec(&s1);
1249 }
1250 if( pid && fid ){
1251 content_deltify(pid, &fid, 1, 0);
1252 }
1253 }
1254
1255 /*
1256 ** Do a binary search to find a file in the p->aFile[] array.
@@ -1435,13 +1435,13 @@
1435 /* Try to make the parent manifest a delta from the child, if that
1436 ** is an appropriate thing to do. For a new baseline, make the
1437 ** previous baseline a delta from the current baseline.
1438 */
1439 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1440 content_deltify(pmid, &mid, 1, 0);
1441 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1442 content_deltify(pParent->pBaseline->rid, &mid, 1, 0);
1443 }
1444
1445 /* Remember all children less than a few seconds younger than their parent,
1446 ** as we might want to fudge the times for those children.
1447 */
@@ -2059,11 +2059,11 @@
2059 " WHERE tagid=%d AND mtime<%.17g"
2060 " ORDER BY mtime DESC",
2061 tagid, p->rDate
2062 );
2063 if( prior ){
2064 content_deltify(prior, &rid, 1, 0);
2065 }
2066 if( nWiki>0 ){
2067 zComment = mprintf("Changes to wiki page [%h]", p->zWikiTitle);
2068 }else{
2069 zComment = mprintf("Deleted wiki page [%h]", p->zWikiTitle);
@@ -2106,11 +2106,11 @@
2106 " WHERE tagid=%d AND mtime>=%.17g AND rid!=%d"
2107 " ORDER BY mtime",
2108 tagid, p->rDate, rid
2109 );
2110 if( prior ){
2111 content_deltify(prior, &rid, 1, 0);
2112 if( !subsequent ){
2113 db_multi_exec(
2114 "DELETE FROM event"
2115 " WHERE type='e'"
2116 " AND tagid=%d"
@@ -2118,11 +2118,11 @@
2118 tagid, tagid
2119 );
2120 }
2121 }
2122 if( subsequent ){
2123 content_deltify(rid, &subsequent, 1, 0);
2124 }else{
2125 search_doc_touch('e',rid,0);
2126 db_multi_exec(
2127 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
2128 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
2129
+34 -15
--- src/rebuild.c
+++ src/rebuild.c
@@ -447,40 +447,57 @@
447447
fossil_print("\n");
448448
}
449449
return errCnt;
450450
}
451451
452
+/*
453
+** Number of neighbors to search
454
+*/
455
+#define N_NEIGHBOR 5
456
+
452457
/*
453458
** Attempt to convert more full-text blobs into delta-blobs for
454459
** storage efficiency.
455460
*/
456461
void extra_deltification(void){
457462
Stmt q;
458
- int topid, previd, rid;
463
+ int aPrev[N_NEIGHBOR];
464
+ int nPrev;
465
+ int rid;
459466
int prevfnid, fnid;
460467
db_begin_transaction();
468
+
469
+ /* Look for manifests that have not been deltaed and try to make them
470
+ ** children of one of the 5 chronologically subsequent check-ins
471
+ */
461472
db_prepare(&q,
462473
"SELECT rid FROM event, blob"
463474
" WHERE blob.rid=event.objid"
464475
" AND event.type='ci'"
465476
" AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
466477
" ORDER BY event.mtime DESC"
467478
);
468
- topid = previd = 0;
479
+ nPrev = 0;
469480
while( db_step(&q)==SQLITE_ROW ){
470481
rid = db_column_int(&q, 0);
471
- if( topid==0 ){
472
- topid = previd = rid;
482
+ if( nPrev>0 ){
483
+ content_deltify(rid, aPrev, nPrev, 0);
484
+ }
485
+ if( nPrev<N_NEIGHBOR ){
486
+ aPrev[nPrev++] = rid;
473487
}else{
474
- if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
475
- content_deltify(rid, topid, 0);
476
- }
477
- previd = rid;
488
+ int i;
489
+ for(i=0; i<N_NEIGHBOR-1; i++) aPrev[i] = aPrev[i+1];
490
+ aPrev[N_NEIGHBOR-1] = rid;
478491
}
479492
}
480493
db_finalize(&q);
481494
495
+ /* For individual files that have not been deltaed, try to find
496
+ ** a parent which is an undeltaed file with the same name in a
497
+ ** more recent branch.
498
+ */
482499
db_prepare(&q,
483500
"SELECT blob.rid, mlink.fnid FROM blob, mlink, plink"
484501
" WHERE NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
485502
" AND mlink.fid=blob.rid"
486503
" AND mlink.mid=plink.cid"
@@ -489,18 +506,20 @@
489506
);
490507
prevfnid = 0;
491508
while( db_step(&q)==SQLITE_ROW ){
492509
rid = db_column_int(&q, 0);
493510
fnid = db_column_int(&q, 1);
494
- if( prevfnid!=fnid ){
495
- prevfnid = fnid;
496
- topid = previd = rid;
511
+ if( fnid!=prevfnid ) nPrev = 0;
512
+ if( nPrev>0 ){
513
+ content_deltify(rid, aPrev, nPrev, 0);
514
+ }
515
+ if( nPrev<N_NEIGHBOR ){
516
+ aPrev[nPrev++] = rid;
497517
}else{
498
- if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
499
- content_deltify(rid, topid, 0);
500
- }
501
- previd = rid;
518
+ int i;
519
+ for(i=0; i<N_NEIGHBOR-1; i++) aPrev[i] = aPrev[i+1];
520
+ aPrev[N_NEIGHBOR-1] = rid;
502521
}
503522
}
504523
db_finalize(&q);
505524
506525
db_end_transaction(0);
507526
--- src/rebuild.c
+++ src/rebuild.c
@@ -447,40 +447,57 @@
447 fossil_print("\n");
448 }
449 return errCnt;
450 }
451
 
 
 
 
 
452 /*
453 ** Attempt to convert more full-text blobs into delta-blobs for
454 ** storage efficiency.
455 */
456 void extra_deltification(void){
457 Stmt q;
458 int topid, previd, rid;
 
 
459 int prevfnid, fnid;
460 db_begin_transaction();
 
 
 
 
461 db_prepare(&q,
462 "SELECT rid FROM event, blob"
463 " WHERE blob.rid=event.objid"
464 " AND event.type='ci'"
465 " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
466 " ORDER BY event.mtime DESC"
467 );
468 topid = previd = 0;
469 while( db_step(&q)==SQLITE_ROW ){
470 rid = db_column_int(&q, 0);
471 if( topid==0 ){
472 topid = previd = rid;
 
 
 
473 }else{
474 if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
475 content_deltify(rid, topid, 0);
476 }
477 previd = rid;
478 }
479 }
480 db_finalize(&q);
481
 
 
 
 
482 db_prepare(&q,
483 "SELECT blob.rid, mlink.fnid FROM blob, mlink, plink"
484 " WHERE NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
485 " AND mlink.fid=blob.rid"
486 " AND mlink.mid=plink.cid"
@@ -489,18 +506,20 @@
489 );
490 prevfnid = 0;
491 while( db_step(&q)==SQLITE_ROW ){
492 rid = db_column_int(&q, 0);
493 fnid = db_column_int(&q, 1);
494 if( prevfnid!=fnid ){
495 prevfnid = fnid;
496 topid = previd = rid;
 
 
 
497 }else{
498 if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
499 content_deltify(rid, topid, 0);
500 }
501 previd = rid;
502 }
503 }
504 db_finalize(&q);
505
506 db_end_transaction(0);
507
--- src/rebuild.c
+++ src/rebuild.c
@@ -447,40 +447,57 @@
447 fossil_print("\n");
448 }
449 return errCnt;
450 }
451
452 /*
453 ** Number of neighbors to search
454 */
455 #define N_NEIGHBOR 5
456
457 /*
458 ** Attempt to convert more full-text blobs into delta-blobs for
459 ** storage efficiency.
460 */
461 void extra_deltification(void){
462 Stmt q;
463 int aPrev[N_NEIGHBOR];
464 int nPrev;
465 int rid;
466 int prevfnid, fnid;
467 db_begin_transaction();
468
469 /* Look for manifests that have not been deltaed and try to make them
470 ** children of one of the 5 chronologically subsequent check-ins
471 */
472 db_prepare(&q,
473 "SELECT rid FROM event, blob"
474 " WHERE blob.rid=event.objid"
475 " AND event.type='ci'"
476 " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
477 " ORDER BY event.mtime DESC"
478 );
479 nPrev = 0;
480 while( db_step(&q)==SQLITE_ROW ){
481 rid = db_column_int(&q, 0);
482 if( nPrev>0 ){
483 content_deltify(rid, aPrev, nPrev, 0);
484 }
485 if( nPrev<N_NEIGHBOR ){
486 aPrev[nPrev++] = rid;
487 }else{
488 int i;
489 for(i=0; i<N_NEIGHBOR-1; i++) aPrev[i] = aPrev[i+1];
490 aPrev[N_NEIGHBOR-1] = rid;
 
491 }
492 }
493 db_finalize(&q);
494
495 /* For individual files that have not been deltaed, try to find
496 ** a parent which is an undeltaed file with the same name in a
497 ** more recent branch.
498 */
499 db_prepare(&q,
500 "SELECT blob.rid, mlink.fnid FROM blob, mlink, plink"
501 " WHERE NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
502 " AND mlink.fid=blob.rid"
503 " AND mlink.mid=plink.cid"
@@ -489,18 +506,20 @@
506 );
507 prevfnid = 0;
508 while( db_step(&q)==SQLITE_ROW ){
509 rid = db_column_int(&q, 0);
510 fnid = db_column_int(&q, 1);
511 if( fnid!=prevfnid ) nPrev = 0;
512 if( nPrev>0 ){
513 content_deltify(rid, aPrev, nPrev, 0);
514 }
515 if( nPrev<N_NEIGHBOR ){
516 aPrev[nPrev++] = rid;
517 }else{
518 int i;
519 for(i=0; i<N_NEIGHBOR-1; i++) aPrev[i] = aPrev[i+1];
520 aPrev[N_NEIGHBOR-1] = rid;
 
521 }
522 }
523 db_finalize(&q);
524
525 db_end_transaction(0);
526
+1 -1
--- src/wiki.c
+++ src/wiki.c
@@ -410,11 +410,11 @@
410410
*/
411411
static void wiki_put(Blob *pWiki, int parent, int needMod){
412412
int nrid;
413413
if( !needMod ){
414414
nrid = content_put_ex(pWiki, 0, 0, 0, 0);
415
- if( parent) content_deltify(parent, nrid, 0);
415
+ if( parent) content_deltify(parent, &nrid, 1, 0);
416416
}else{
417417
nrid = content_put_ex(pWiki, 0, 0, 0, 1);
418418
moderation_table_create();
419419
db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
420420
}
421421
--- src/wiki.c
+++ src/wiki.c
@@ -410,11 +410,11 @@
410 */
411 static void wiki_put(Blob *pWiki, int parent, int needMod){
412 int nrid;
413 if( !needMod ){
414 nrid = content_put_ex(pWiki, 0, 0, 0, 0);
415 if( parent) content_deltify(parent, nrid, 0);
416 }else{
417 nrid = content_put_ex(pWiki, 0, 0, 0, 1);
418 moderation_table_create();
419 db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
420 }
421
--- src/wiki.c
+++ src/wiki.c
@@ -410,11 +410,11 @@
410 */
411 static void wiki_put(Blob *pWiki, int parent, int needMod){
412 int nrid;
413 if( !needMod ){
414 nrid = content_put_ex(pWiki, 0, 0, 0, 0);
415 if( parent) content_deltify(parent, &nrid, 1, 0);
416 }else{
417 nrid = content_put_ex(pWiki, 0, 0, 0, 1);
418 moderation_table_create();
419 db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
420 }
421

Keyboard Shortcuts

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