Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Update private branch to latest trunk. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | ttmrichter |
Files: | files | file ages | folders |
SHA1: | a87fbd331253c71da2f6980376960f6b |
User & Date: | michael 2010-07-07 07:44:27 |
Context
2010-07-09
| ||
16:23 |
Started the process of modifying the build system to permit more flexible and
reliable cross-platform support. Currently the build system is set up for
Linux (GCC or CLANG as the compiler) and for MinGW32 (GCC as the compiler).
Of these, only the Linux builds have been tested so far and confirmed to work
as expected. The way to use this new system is as follows:
make Builds the default platform and compiler (linux and gcc). PLATFORM=mingw32 make Builds the mingw32 build (untested!) using the default compiler (gcc). COMPILER=clang make Builds the default platform (linux) using the clang compiler. Other platform and compiler fragment files can be added in the ./make directory based on the models already there. check-in: d3252d74 user: michael tags: newbuild, ttmrichter | |
2010-07-07
| ||
07:44 | Update private branch to latest trunk. check-in: a87fbd33 user: michael tags: ttmrichter | |
2010-07-04
| ||
21:11 | Small performance tweaks for clone and rebuild. check-in: 710a8ba9 user: drh tags: trunk | |
2010-06-28
| ||
14:35 | Modified Makefile to support clang in private branch. check-in: 9c060263 user: michael tags: ttmrichter | |
Changes
Changes to src/content.c.
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
|
/* ** Mark artifact rid as being available now. Update the cache to ** show that everything that was formerly unavailable because rid ** was missing is now available. */ static void content_mark_available(int rid){ Bag pending; Stmt q; if( bag_find(&contentCache.available, rid) ) return; bag_init(&pending); bag_insert(&pending, rid); while( (rid = bag_first(&pending))!=0 ){ bag_remove(&pending, rid); bag_remove(&contentCache.missing, rid); bag_insert(&contentCache.available, rid); db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid); while( db_step(&q)==SQLITE_ROW ){ int nx = db_column_int(&q, 0); bag_insert(&pending, nx); } db_finalize(&q); } bag_clear(&pending); } /* ** Get the blob.content value for blob.rid=rid. Return 1 on success or ** 0 on failure. ................................................................................ /* ** When a record is converted from a phantom to a real record, ** if that record has other records that are derived by delta, ** then call manifest_crosslink() on those other records. */ void after_dephantomize(int rid, int linkFlag){ Stmt q; db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid); while( db_step(&q)==SQLITE_ROW ){ int tid = db_column_int(&q, 0); after_dephantomize(tid, 1); } db_finalize(&q); if( linkFlag ){ Blob content; content_get(rid, &content); manifest_crosslink(rid, &content); blob_reset(&content); } } |
|
|
>
|
>
>
>
>
>
>
>
>
|
>
>
|
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
/* ** Mark artifact rid as being available now. Update the cache to ** show that everything that was formerly unavailable because rid ** was missing is now available. */ static void content_mark_available(int rid){ Bag pending; static Stmt q; if( bag_find(&contentCache.available, rid) ) return; bag_init(&pending); bag_insert(&pending, rid); while( (rid = bag_first(&pending))!=0 ){ bag_remove(&pending, rid); bag_remove(&contentCache.missing, rid); bag_insert(&contentCache.available, rid); db_static_prepare(&q, "SELECT rid FROM delta WHERE srcid=:rid"); db_bind_int(&q, ":rid", rid); while( db_step(&q)==SQLITE_ROW ){ int nx = db_column_int(&q, 0); bag_insert(&pending, nx); } db_reset(&q); } bag_clear(&pending); } /* ** Get the blob.content value for blob.rid=rid. Return 1 on success or ** 0 on failure. ................................................................................ /* ** When a record is converted from a phantom to a real record, ** if that record has other records that are derived by delta, ** then call manifest_crosslink() on those other records. */ void after_dephantomize(int rid, int linkFlag){ Stmt q; int prevTid = 0; /* The prevTid variable is used to delay invoking this routine ** recursively, if possible, until after the query has finalized, ** in order to avoid having an excessive number of prepared statements. ** This is most effective in the common case where the query returns ** just one row. */ db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid); while( db_step(&q)==SQLITE_ROW ){ int tid = db_column_int(&q, 0); if( prevTid ) after_dephantomize(prevTid, 1); prevTid = tid; } db_finalize(&q); if( prevTid ) after_dephantomize(prevTid, 1); if( linkFlag ){ Blob content; content_get(rid, &content); manifest_crosslink(rid, &content); blob_reset(&content); } } |
Changes to src/db.c.
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
....
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
|
** With a value argument it changes the property for the current repository.
**
** The "unset" command clears a property setting.
**
**
** auto-captcha If enabled, the Login page provides a button to
** fill in the captcha password. Default: on
**
** autosync If enabled, automatically pull prior to commit
** or update and automatically push after commit or
** tag or branch creation. If the the value is "pullonly"
** then only pull operations occur automatically.
**
** binary-glob The VALUE is a comma-separated list of GLOB patterns
................................................................................
** web browser when given a URL as an argument.
** Defaults to "start" on windows, "open" on Mac,
** and "firefox" on Unix.
*/
void setting_cmd(void){
static const char *azName[] = {
"auto-captcha",
"autosync",
"binary-glob",
"clearsign",
"diff-command",
"dont-push",
"editor",
"gdiff-command",
|
>
>
>
>
|
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
....
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
|
** With a value argument it changes the property for the current repository. ** ** The "unset" command clears a property setting. ** ** ** auto-captcha If enabled, the Login page provides a button to ** fill in the captcha password. Default: on ** ** auto-shun If enabled, automatically pull the shunning list ** from a server to which the client autosyncs. ** ** autosync If enabled, automatically pull prior to commit ** or update and automatically push after commit or ** tag or branch creation. If the the value is "pullonly" ** then only pull operations occur automatically. ** ** binary-glob The VALUE is a comma-separated list of GLOB patterns ................................................................................ ** web browser when given a URL as an argument. ** Defaults to "start" on windows, "open" on Mac, ** and "firefox" on Unix. */ void setting_cmd(void){ static const char *azName[] = { "auto-captcha", "auto-shun", "autosync", "binary-glob", "clearsign", "diff-command", "dont-push", "editor", "gdiff-command", |
Changes to src/file.c.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
** * Does not contain any of these characters in the path: "\*[]?" ** * Does not end with "/". ** * Does not contain two or more "/" characters in a row. ** * Contains at least one character */ int file_is_simple_pathname(const char *z){ int i; if( *z=='/' || *z==0 ) return 0; if( *z=='.' ){ if( z[1]=='/' || z[1]==0 ) return 0; if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0; } for(i=0; z[i]; i++){ if( z[i]=='\\' || z[i]=='*' || z[i]=='[' || z[i]==']' || z[i]=='?' ){ return 0; } if( z[i]=='/' ){ if( z[i+1]=='/' ) return 0; if( z[i+1]=='.' ){ if( z[i+2]=='/' || z[i+2]==0 ) return 0; if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; } } } |
> | | | | | |
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
** * Does not contain any of these characters in the path: "\*[]?" ** * Does not end with "/". ** * Does not contain two or more "/" characters in a row. ** * Contains at least one character */ int file_is_simple_pathname(const char *z){ int i; char c = z[0]; if( c=='/' || c==0 ) return 0; if( c=='.' ){ if( z[1]=='/' || z[1]==0 ) return 0; if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0; } for(i=0; (c=z[i])!=0; i++){ if( c=='\\' || c=='*' || c=='[' || c==']' || c=='?' ){ return 0; } if( c=='/' ){ if( z[i+1]=='/' ) return 0; if( z[i+1]=='.' ){ if( z[i+2]=='/' || z[i+2]==0 ) return 0; if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; } } } |
Changes to src/rebuild.c.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 ... 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 ... 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
/* ** Rebuild cross-referencing information for the artifact ** rid with content pBase and all of its descendants. This ** routine clears the content buffer before returning. */ static void rebuild_step(int rid, int size, Blob *pBase){ Stmt q1; Bag children; Blob copy; Blob *pUse; int nChild, i, cid; /* Fix up the "blob.size" field if needed. */ if( size!=blob_size(pBase) ){ db_multi_exec( "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid ); } /* Find all children of artifact rid */ db_prepare(&q1, "SELECT rid FROM delta WHERE srcid=%d", rid); bag_init(&children); while( db_step(&q1)==SQLITE_ROW ){ int cid = db_column_int(&q1, 0); if( !bag_find(&bagDone, cid) ){ bag_insert(&children, cid); } } nChild = bag_count(&children); db_finalize(&q1); /* Crosslink the artifact */ if( nChild==0 ){ pUse = pBase; }else{ blob_copy(©, pBase); pUse = © ................................................................................ if (!g.fQuiet) { printf("0 (0%%)...\r"); fflush(stdout); } db_multi_exec(zSchemaUpdates); for(;;){ zTable = db_text(0, "SELECT name FROM sqlite_master" " WHERE type='table'" " AND name NOT IN ('blob','delta','rcvfrom','user'," "'config','shun','private','reportfmt'," "'concealed')" " AND name NOT GLOB 'sqlite_*'" ); if( zTable==0 ) break; ................................................................................ " WHERE rid IN (SELECT rid FROM shun JOIN blob USING(uuid))" ); db_multi_exec( "DELETE FROM config WHERE name IN ('remote-code', 'remote-maxid')" ); totalSize = db_int(0, "SELECT count(*) FROM blob"); db_prepare(&s, "SELECT rid, size FROM blob" " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" ); manifest_crosslink_begin(); while( db_step(&s)==SQLITE_ROW ){ int rid = db_column_int(&s, 0); int size = db_column_int(&s, 1); |
| | > | | | |
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 ... 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 ... 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
/* ** Rebuild cross-referencing information for the artifact ** rid with content pBase and all of its descendants. This ** routine clears the content buffer before returning. */ static void rebuild_step(int rid, int size, Blob *pBase){ static Stmt q1; Bag children; Blob copy; Blob *pUse; int nChild, i, cid; /* Fix up the "blob.size" field if needed. */ if( size!=blob_size(pBase) ){ db_multi_exec( "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid ); } /* Find all children of artifact rid */ db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid"); db_bind_int(&q1, ":rid", rid); bag_init(&children); while( db_step(&q1)==SQLITE_ROW ){ int cid = db_column_int(&q1, 0); if( !bag_find(&bagDone, cid) ){ bag_insert(&children, cid); } } nChild = bag_count(&children); db_reset(&q1); /* Crosslink the artifact */ if( nChild==0 ){ pUse = pBase; }else{ blob_copy(©, pBase); pUse = © ................................................................................ if (!g.fQuiet) { printf("0 (0%%)...\r"); fflush(stdout); } db_multi_exec(zSchemaUpdates); for(;;){ zTable = db_text(0, "SELECT name FROM sqlite_master /*scan*/" " WHERE type='table'" " AND name NOT IN ('blob','delta','rcvfrom','user'," "'config','shun','private','reportfmt'," "'concealed')" " AND name NOT GLOB 'sqlite_*'" ); if( zTable==0 ) break; ................................................................................ " WHERE rid IN (SELECT rid FROM shun JOIN blob USING(uuid))" ); db_multi_exec( "DELETE FROM config WHERE name IN ('remote-code', 'remote-maxid')" ); totalSize = db_int(0, "SELECT count(*) FROM blob"); db_prepare(&s, "SELECT rid, size FROM blob /*scan*/" " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)" " AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)" ); manifest_crosslink_begin(); while( db_step(&s)==SQLITE_ROW ){ int rid = db_column_int(&s, 0); int size = db_column_int(&s, 1); |
Changes to src/sqlite3.c.
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 ..... 12793 12794 12795 12796 12797 12798 12799 12800 12801 12802 12803 12804 12805 12806 12807 12808 ..... 15365 15366 15367 15368 15369 15370 15371 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 ..... 15522 15523 15524 15525 15526 15527 15528 15529 15530 15531 15532 15533 15534 15535 15536 ..... 25955 25956 25957 25958 25959 25960 25961 25962 25963 25964 25965 25966 25967 25968 ..... 27247 27248 27249 27250 27251 27252 27253 27254 27255 27256 27257 27258 27259 27260 ..... 27474 27475 27476 27477 27478 27479 27480 27481 27482 27483 27484 27485 27486 27487 27488 ..... 27615 27616 27617 27618 27619 27620 27621 27622 27623 27624 27625 27626 27627 27628 ..... 27664 27665 27666 27667 27668 27669 27670 27671 27672 27673 27674 27675 27676 27677 ..... 27684 27685 27686 27687 27688 27689 27690 27691 27692 27693 27694 27695 27696 27697 27698 ..... 30181 30182 30183 30184 30185 30186 30187 30188 30189 30190 30191 30192 30193 30194 ..... 30407 30408 30409 30410 30411 30412 30413 30414 30415 30416 30417 30418 30419 30420 ..... 33494 33495 33496 33497 33498 33499 33500 33501 33502 33503 33504 33505 33506 33507 33508 33509 33510 33511 33512 33513 33514 ..... 33774 33775 33776 33777 33778 33779 33780 33781 33782 33783 33784 33785 33786 33787 33788 ..... 35965 35966 35967 35968 35969 35970 35971 35972 35973 35974 35975 35976 35977 35978 35979 35980 35981 35982 35983 35984 35985 35986 35987 35988 35989 35990 35991 35992 35993 35994 35995 35996 35997 35998 35999 36000 36001 36002 36003 36004 36005 36006 36007 36008 36009 36010 36011 36012 36013 36014 36015 36016 ..... 36376 36377 36378 36379 36380 36381 36382 36383 36384 36385 36386 36387 36388 36389 36390 ..... 37754 37755 37756 37757 37758 37759 37760 37761 37762 37763 37764 37765 37766 37767 37768 ..... 38185 38186 38187 38188 38189 38190 38191 38192 38193 38194 38195 38196 38197 38198 38199 38200 38201 38202 38203 38204 38205 38206 38207 38208 38209 38210 38211 38212 38213 38214 38215 38216 38217 38218 38219 38220 38221 38222 ..... 38259 38260 38261 38262 38263 38264 38265 38266 38267 38268 38269 38270 38271 38272 38273 38274 38275 38276 ..... 38703 38704 38705 38706 38707 38708 38709 38710 38711 38712 38713 38714 38715 38716 38717 ..... 38837 38838 38839 38840 38841 38842 38843 38844 38845 38846 38847 38848 38849 38850 38851 ..... 38853 38854 38855 38856 38857 38858 38859 38860 38861 38862 38863 38864 38865 38866 38867 ..... 39187 39188 39189 39190 39191 39192 39193 39194 39195 39196 39197 39198 39199 39200 39201 39202 39203 39204 39205 39206 39207 39208 39209 39210 39211 39212 39213 39214 39215 ..... 39525 39526 39527 39528 39529 39530 39531 39532 39533 39534 39535 39536 39537 39538 39539 ..... 39582 39583 39584 39585 39586 39587 39588 39589 39590 39591 39592 39593 39594 39595 39596 39597 39598 39599 39600 39601 39602 39603 39604 39605 39606 ..... 39633 39634 39635 39636 39637 39638 39639 39640 39641 39642 39643 39644 39645 39646 39647 ..... 40180 40181 40182 40183 40184 40185 40186 40187 40188 40189 40190 40191 40192 40193 40194 40195 40196 40197 40198 40199 ..... 40420 40421 40422 40423 40424 40425 40426 40427 40428 40429 40430 40431 40432 40433 40434 ..... 40436 40437 40438 40439 40440 40441 40442 40443 40444 40445 40446 40447 40448 40449 40450 ..... 40548 40549 40550 40551 40552 40553 40554 40555 40556 40557 40558 40559 40560 40561 40562 40563 40564 ..... 40584 40585 40586 40587 40588 40589 40590 40591 40592 40593 40594 40595 40596 40597 40598 ..... 40611 40612 40613 40614 40615 40616 40617 40618 40619 40620 40621 40622 40623 40624 40625 40626 40627 ..... 40632 40633 40634 40635 40636 40637 40638 40639 40640 40641 40642 40643 40644 40645 40646 ..... 40652 40653 40654 40655 40656 40657 40658 40659 40660 40661 40662 40663 40664 40665 40666 ..... 40760 40761 40762 40763 40764 40765 40766 40767 40768 40769 40770 40771 40772 40773 40774 40775 ..... 40811 40812 40813 40814 40815 40816 40817 40818 40819 40820 40821 40822 40823 40824 40825 ..... 41028 41029 41030 41031 41032 41033 41034 41035 41036 41037 41038 41039 41040 41041 41042 41043 ..... 41139 41140 41141 41142 41143 41144 41145 41146 41147 41148 41149 41150 41151 41152 41153 41154 41155 41156 41157 41158 ..... 41331 41332 41333 41334 41335 41336 41337 41338 41339 41340 41341 41342 41343 41344 41345 ..... 41354 41355 41356 41357 41358 41359 41360 41361 41362 41363 41364 41365 41366 41367 41368 ..... 41667 41668 41669 41670 41671 41672 41673 41674 41675 41676 41677 41678 41679 41680 41681 ..... 42080 42081 42082 42083 42084 42085 42086 42087 42088 42089 42090 42091 42092 42093 42094 ..... 42174 42175 42176 42177 42178 42179 42180 42181 42182 42183 42184 42185 42186 42187 42188 ..... 44911 44912 44913 44914 44915 44916 44917 44918 44919 44920 44921 44922 44923 44924 44925 44926 44927 44928 44929 44930 44931 44932 44933 44934 ..... 45847 45848 45849 45850 45851 45852 45853 45854 45855 45856 45857 45858 45859 45860 45861 ..... 47570 47571 47572 47573 47574 47575 47576 47577 47578 47579 47580 47581 47582 47583 47584 ..... 51335 51336 51337 51338 51339 51340 51341 51342 51343 51344 51345 51346 51347 51348 51349 ..... 51827 51828 51829 51830 51831 51832 51833 51834 51835 51836 51837 51838 51839 51840 ..... 53949 53950 53951 53952 53953 53954 53955 53956 53957 53958 53959 53960 53961 53962 53963 ..... 62380 62381 62382 62383 62384 62385 62386 62387 62388 62389 62390 62391 62392 62393 62394 62395 62396 62397 62398 62399 62400 62401 ..... 63431 63432 63433 63434 63435 63436 63437 63438 63439 63440 63441 63442 63443 63444 ..... 63558 63559 63560 63561 63562 63563 63564 63565 63566 63567 63568 63569 63570 63571 ..... 64741 64742 64743 64744 64745 64746 64747 64748 64749 64750 64751 64752 64753 64754 64755 ..... 65021 65022 65023 65024 65025 65026 65027 65028 65029 65030 65031 65032 65033 65034 65035 ..... 65544 65545 65546 65547 65548 65549 65550 65551 65552 65553 65554 65555 65556 65557 ..... 75033 75034 75035 75036 75037 75038 75039 75040 75041 75042 75043 75044 75045 75046 ..... 80733 80734 80735 80736 80737 80738 80739 80740 80741 80742 80743 80744 80745 80746 80747 ..... 88380 88381 88382 88383 88384 88385 88386 88387 88388 88389 88390 88391 88392 88393 ..... 90365 90366 90367 90368 90369 90370 90371 90372 90373 90374 90375 90376 90377 90378 ..... 91175 91176 91177 91178 91179 91180 91181 91182 91183 91184 91185 91186 91187 91188 ..... 94753 94754 94755 94756 94757 94758 94759 94760 94761 94762 94763 94764 94765 94766 94767 ..... 96347 96348 96349 96350 96351 96352 96353 96354 96355 96356 96357 96358 96359 96360 96361 ...... 106032 106033 106034 106035 106036 106037 106038 106039 106040 106041 106042 106043 106044 106045 ...... 106057 106058 106059 106060 106061 106062 106063 106064 106065 106066 106067 106068 106069 106070 106071 |
** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.0" #define SQLITE_VERSION_NUMBER 3007000 #define SQLITE_SOURCE_ID "2010-06-26 20:25:31 f149b498b6ada3fc9f71ee104c351554c80c7f8a" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ................................................................................ ** sqlite3OsOpen() ** sqlite3OsRead() ** sqlite3OsWrite() ** sqlite3OsSync() ** sqlite3OsLock() ** */ #if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) #define DO_OS_MALLOC_TEST(x) if (!x || !sqlite3IsMemJournal(x)) { \ void *pTstAlloc = sqlite3Malloc(10); \ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ sqlite3_free(pTstAlloc); \ } #else #define DO_OS_MALLOC_TEST(x) #endif ................................................................................ /* ** Stub routines for all mutex methods. ** ** This routines provide no mutual exclusion or error checking. */ static int noopMutexInit(void){ return SQLITE_OK; } static int noopMutexEnd(void){ return SQLITE_OK; } static sqlite3_mutex *noopMutexAlloc(int id){ return (sqlite3_mutex*)8; } static void noopMutexFree(sqlite3_mutex *p){ return; } static void noopMutexEnter(sqlite3_mutex *p){ return; } static int noopMutexTry(sqlite3_mutex *p){ return SQLITE_OK; } static void noopMutexLeave(sqlite3_mutex *p){ return; } SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){ static const sqlite3_mutex_methods sMutex = { noopMutexInit, noopMutexEnd, noopMutexAlloc, noopMutexFree, ................................................................................ /* ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation ** is used regardless of the run-time threadsafety setting. */ #ifdef SQLITE_MUTEX_NOOP SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ return sqliteNoopMutex(); } #endif /* SQLITE_MUTEX_NOOP */ #endif /* SQLITE_MUTEX_OMIT */ /************** End of mutex_noop.c ******************************************/ /************** Begin file mutex_os2.c ***************************************/ /* ................................................................................ ** ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. */ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ unixEnterMutex(); unixLeaveMutex(); } /* ** This function is called to obtain a pointer to region iRegion of the ** shared-memory associated with the database file fd. Shared-memory regions ................................................................................ /* ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ sqlite3_int64 i; unixCurrentTimeInt64(0, &i); *prNow = i/86400000.0; return 0; } /* ** We added the xGetLastError() method with the intention of providing ................................................................................ if( lPath[len-1]!='/' ){ len = strlcat(lPath, "/", maxLen); } /* transform the db path to a unique cache name */ dbLen = (int)strlen(dbPath); for( i=0; i<dbLen && (i+len+7)<maxLen; i++){ char c = dbPath[i]; lPath[i+len] = (c=='/')?'_':c; } lPath[i+len]='\0'; strlcat(lPath, ":auto:", maxLen); OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid())); return SQLITE_OK; ................................................................................ #ifdef SQLITE_TEST /* simulate multiple hosts by creating unique hostid file paths */ SQLITE_API int sqlite3_hostid_num = 0; #endif #define PROXY_HOSTIDLEN 16 /* conch file host id length */ /* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN ** bytes of writable memory. */ static int proxyGetHostID(unsigned char *pHostID, int *pError){ struct timespec timeout = {1, 0}; /* 1 sec timeout */ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); ................................................................................ char buf[PROXY_MAXCONCHLEN]; char *cPath = pCtx->conchFilePath; size_t readLen = 0; size_t pathLen = 0; char errmsg[64] = ""; int fd = -1; int rc = -1; /* create a new path by replace the trailing '-conch' with '-break' */ pathLen = strlcpy(tPath, cPath, MAXPATHLEN); if( pathLen>MAXPATHLEN || pathLen<6 || (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ sprintf(errmsg, "path error (len %d)", (int)pathLen); goto end_breaklock; ................................................................................ } /* write it out to the temporary break file */ fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS); if( fd<0 ){ sprintf(errmsg, "create failed (%d)", errno); goto end_breaklock; } if( pwrite(fd, buf, readLen, 0) != readLen ){ sprintf(errmsg, "write failed (%d)", errno); goto end_breaklock; } if( rename(tPath, cPath) ){ sprintf(errmsg, "rename failed (%d)", errno); goto end_breaklock; } ................................................................................ } /* Check to see if another process is holding the dead-man switch. ** If not, truncate the file to zero length. */ if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); } if( rc==SQLITE_OK ){ winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); } if( rc ) goto shm_open_err; } ................................................................................ ** ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. */ static void winShmBarrier( sqlite3_file *fd /* Database holding the shared memory */ ){ /* MemoryBarrier(); // does not work -- do not know why not */ winShmEnterMutex(); winShmLeaveMutex(); } #else # define winShmOpen 0 ................................................................................ # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalClose(w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalRead(v,w,x,y,z) 0 # define sqlite3WalDbsize(y,z) # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWRiteTransaction(x) 0 # define sqlite3WalUndo(x,y,z) 0 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 # define sqlite3WalCheckpoint(u,v,w,x) 0 # define sqlite3WalCallback(z) 0 #else #define WAL_SAVEPOINT_NDATA 4 /* Connection to a write-ahead log (WAL) file. ** There is one object of this type for each pager. */ ................................................................................ typedef struct PagerSavepoint PagerSavepoint; struct PagerSavepoint { i64 iOffset; /* Starting offset in main journal */ i64 iHdrOffset; /* See above */ Bitvec *pInSavepoint; /* Set of pages in this savepoint */ Pgno nOrig; /* Original number of pages in file */ Pgno iSubRec; /* Index of first record in sub-journal */ u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ }; /* ** A open page cache is an instance of the following structure. ** ** errCode ** ................................................................................ } pPager->state = PAGER_SHARED; return rc; } /* ** Check if the *-wal file that corresponds to the database opened by pPager ** exists. Assuming no error occurs, set *pExists to 1 if the file exists, ** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return ** an SQLite error code. */ static int pagerHasWAL(Pager *pPager, int *pExists){ int rc; /* Return code */ char *zWal; /* Name of the WAL file */ assert( !pPager->tempFile ); zWal = sqlite3_mprintf("%s-wal", pPager->zFilename); if( !zWal ){ rc = SQLITE_NOMEM; }else{ rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists); sqlite3_free(zWal); } return rc; } /* ** Check if the *-wal file that corresponds to the database opened by pPager ** exists. If it does, open the pager in WAL mode. Otherwise, if no error ** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL. ** If an IO or OOM error occurs, return an SQLite error code. ** ** If the WAL file is opened, also open a snapshot (read transaction). ** ** The caller must hold a SHARED lock on the database file to call this ** function. Because an EXCLUSIVE lock on the db file is required to delete ** a WAL, this ensures there is no race condition between the xAccess() ** below and an xDelete() being executed by some other connection. */ static int pagerOpenWalIfPresent(Pager *pPager){ int rc = SQLITE_OK; if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ rc = pagerHasWAL(pPager, &isWal); if( rc==SQLITE_OK ){ if( isWal ){ pager_reset(pPager); rc = sqlite3PagerOpenWal(pPager, 0); if( rc==SQLITE_OK ){ rc = pagerBeginReadTransaction(pPager); } ................................................................................ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ int nPage; if( mxPage>0 ){ pPager->mxPgno = mxPage; } if( pPager->state!=PAGER_UNLOCK ){ sqlite3PagerPagecount(pPager, &nPage); assert( pPager->mxPgno>=nPage ); } return pPager->mxPgno; } /* ** The following set of routines are used to disable the simulated ** I/O error mechanism. These routines are used to avoid simulated ................................................................................ ** other bytes change randomly with each file change when ** a codec is in use. ** ** There is a vanishingly small chance that a change will not be ** detected. The chance of an undetected change is so small that ** it can be neglected. */ int nPage; char dbFileVers[sizeof(pPager->dbFileVers)]; sqlite3PagerPagecount(pPager, &nPage); if( pPager->errCode ){ rc = pPager->errCode; goto failed; } ................................................................................ } /* No need to open the journal file at this time. It will be ** opened before it is written to. If we defer opening the journal, ** we might save the work of creating a file if the transaction ** ends up being a no-op. */ }else if( isOpen(pPager->jfd) && pPager->journalOff==0 ){ /* This happens when the pager was in exclusive-access mode the last ** time a (read or write) transaction was successfully concluded ** by this connection. Instead of deleting the journal file it was ** kept open and either was truncated to 0 bytes or its header was ** overwritten with zeros. */ assert( pagerUseWal(pPager)==0 ); assert( pPager->nRec==0 ); assert( pPager->dbOrigSize==0 ); assert( pPager->pInJournal==0 ); rc = pager_open_journal(pPager); } PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); if( rc!=SQLITE_OK ){ assert( !pPager->dbModified ); /* Ignore any IO error that occurs within pager_end_transaction(). The ** purpose of this call is to reset the internal state of the pager ** sub-system. It doesn't matter if the journal-file is not properly ** finalized at this point (since it is not a valid journal file anyway). */ pager_end_transaction(pPager, 0); } return rc; } /* ** Mark a single data page as writeable. The page is written into the ** main journal or sub-journal as required. If the page is written into ** one of the journals, the corresponding bit is set in the ................................................................................ ** written to the transaction journal or the ckeckpoint journal ** or both. ** ** Higher level routines should have already started a transaction, ** which means they have acquired the necessary locks but the rollback ** journal might not yet be open. */ rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory); if( rc!=SQLITE_OK ){ return rc; } if( pPager->pInJournal==0 && pPager->journalMode!=PAGER_JOURNALMODE_OFF && !pagerUseWal(pPager) ){ assert( pPager->useJournal ); rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; ................................................................................ ** Otherwise, if the optimization is both enabled and applicable, ** then call pager_incr_changecounter() to update the change-counter ** in 'direct' mode. In this case the journal file will never be ** created for this transaction. */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE PgHdr *pPg; assert( isOpen(pPager->jfd) || pPager->journalMode==PAGER_JOURNALMODE_OFF ); if( !zMaster && isOpen(pPager->jfd) && pPager->journalOff==jrnlBufferSize(pPager) && pPager->dbSize>=pPager->dbFileSize && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) ){ /* Update the db file change counter via the direct-write method. The ** following call will modify the in-memory representation of page 1 ................................................................................ if( NEVER(pPager->errCode) ) return pPager->errCode; /* This function should not be called if the pager is not in at least ** PAGER_RESERVED state. **FIXME**: Make it so that this test always ** fails - make it so that we never reach this point if we do not hold ** all necessary locks. */ if( pPager->state<PAGER_RESERVED ) return SQLITE_ERROR; /* An optimization. If the database was not actually modified during ** this transaction, the pager is running in exclusive-mode and is ** using persistent journals, then this function is a no-op. ** ** The start of the journal file currently contains a single journal ** header with the nRec field set to 0. If such a journal is used as ................................................................................ ** to the database file. So there is no need to zero the journal ** header. Since the pager is in exclusive mode, there is no need ** to drop any locks either. */ if( pPager->dbModified==0 && pPager->exclusiveMode && pPager->journalMode==PAGER_JOURNALMODE_PERSIST ){ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); return SQLITE_OK; } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dbModified ); rc = pager_end_transaction(pPager, pPager->setMaster); return pager_error(pPager, rc); ................................................................................ return pPager->noSync; } #ifdef SQLITE_HAS_CODEC /* ** Set or retrieve the codec for this pager */ static void sqlite3PagerSetCodec( Pager *pPager, void *(*xCodec)(void*,void*,Pgno,int), void (*xCodecSizeChng)(void*,int,int), void (*xCodecFree)(void*), void *pCodec ){ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); pPager->xCodec = pPager->memDb ? 0 : xCodec; pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree; pPager->pCodec = pCodec; pagerReportSize(pPager); } static void *sqlite3PagerGetCodec(Pager *pPager){ return pPager->pCodec; } #endif #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Move the page pPg to location pgno in the file. ................................................................................ /* ** Return TRUE if the pager is in a state where it is OK to change the ** journalmode. Journalmode changes can only happen when the database ** is unmodified. */ SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ if( pPager->dbModified ) return 0; if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0; return 1; } /* ** Get/set the size-limit used for persistent journal files. ** ** Setting the size limit to -1 means no limit is enforced. ................................................................................ */ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ const sqlite3_io_methods *pMethods = pPager->fd->pMethods; return pMethods->iVersion>=2 && pMethods->xShmOpen!=0; } /* ** Open a connection to the write-ahead log file for pager pPager. If ** the log connection is already open, this function is a no-op. ** ** The caller must be holding a SHARED lock on the database file to call ** this function. */ SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){ int rc = SQLITE_OK; /* Return code */ assert( pPager->state>=PAGER_SHARED ); if( !pPager->pWal ){ if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), unlock the database file and ** return an error code. */ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, ................................................................................ ** it may need to be checkpointed before the connection can switch to ** rollback mode. Open it now so this can happen. */ if( !pPager->pWal ){ int logexists = 0; rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED); if( rc==SQLITE_OK ){ rc = pagerHasWAL(pPager, &logexists); } if( rc==SQLITE_OK && logexists ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zFilename, &pPager->pWal); } } ................................................................................ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ int rc = SQLITE_OK; /* Enlarge the pWal->apWiData[] array if required */ if( pWal->nWiData<=iPage ){ int nByte = sizeof(u32 *)*(iPage+1); volatile u32 **apNew; apNew = (volatile u32 **)sqlite3_realloc(pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; return SQLITE_NOMEM; } memset(&apNew[pWal->nWiData], 0, sizeof(u32 *)*(iPage+1-pWal->nWiData)); pWal->apWiData = apNew; pWal->nWiData = iPage+1; } /* Request a pointer to the required page from the VFS */ if( pWal->apWiData[iPage]==0 ){ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, ................................................................................ static int walLockShared(Wal *pWal, int lockIdx){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); ................................................................................ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, walLockName(lockIdx), n, rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) return rc; } static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, ................................................................................ ** ** At most only the hash table containing pWal->hdr.mxFrame needs to be ** updated. Any later hash tables will be automatically cleared when ** pWal->hdr.mxFrame advances to the point where those hash tables are ** actually needed. */ static void walCleanupHash(Wal *pWal){ volatile ht_slot *aHash; /* Pointer to hash table to clear */ volatile u32 *aPgno; /* Page number array for hash table */ u32 iZero; /* frame == (aHash[x]+iZero) */ int iLimit = 0; /* Zero values greater than this */ int nByte; /* Number of bytes to zero in aPgno[] */ int i; /* Used to iterate through aHash[] */ assert( pWal->writeLock ); testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 ); testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE ); ................................................................................ aHash[i] = 0; } } /* Zero the entries in the aPgno array that correspond to frames with ** frame numbers greater than pWal->hdr.mxFrame. */ nByte = ((char *)aHash - (char *)&aPgno[iLimit+1]); memset((void *)&aPgno[iLimit+1], 0, nByte); #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the every entry in the mapping region is still reachable ** via the hash table even after the cleanup. */ if( iLimit ){ ................................................................................ /* ** Set an entry in the wal-index that will map database page number ** pPage into WAL frame iFrame. */ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ int rc; /* Return code */ u32 iZero; /* One less than frame number of aPgno[1] */ volatile u32 *aPgno; /* Page number array */ volatile ht_slot *aHash; /* Hash table */ rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero); /* Assuming the wal-index file was successfully mapped, populate the ** page number array and hash table entry. */ if( rc==SQLITE_OK ){ ................................................................................ idx = iFrame - iZero; assert( idx <= HASHTABLE_NSLOT/2 + 1 ); /* If this is the first entry to be added to this hash-table, zero the ** entire hash table and aPgno[] array before proceding. */ if( idx==1 ){ int nByte = (u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]; memset((void*)&aPgno[1], 0, nByte); } /* If the entry in aPgno[] is already set, then the previous writer ** must have exited unexpectedly in the middle of a transaction (after ** writing one or more dirty pages to the WAL to free up memory). ** Remove the remnants of that writers uncommitted transaction from ................................................................................ } /* Write the aPgno[] array entry and the hash-table slot. */ for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ assert( nCollide++ < idx ); } aPgno[idx] = iPage; aHash[iKey] = idx; #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the number of entries in the hash table exactly equals ** the number of entries in the mapping region. */ { int i; /* Loop counter */ ................................................................................ if( (magic&0xFFFFFFFE)!=WAL_MAGIC || szPage&(szPage-1) || szPage>SQLITE_MAX_PAGE_SIZE || szPage<512 ){ goto finished; } pWal->hdr.bigEndCksum = (magic&0x00000001); pWal->szPage = szPage; pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); /* Verify that the WAL header checksum is correct */ walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum ); ................................................................................ rc = walIndexAppend(pWal, ++iFrame, pgno); if( rc!=SQLITE_OK ) break; /* If nTruncate is non-zero, this is a commit record. */ if( nTruncate ){ pWal->hdr.mxFrame = iFrame; pWal->hdr.nPage = nTruncate; pWal->hdr.szPage = szPage; aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; } } sqlite3_free(aFrame); } ................................................................................ ){ struct Sublist { int nList; /* Number of elements in aList */ ht_slot *aList; /* Pointer to sub-list content */ }; const int nList = *pnList; /* Size of input list */ int nMerge; /* Number of elements in list aMerge */ ht_slot *aMerge; /* List to be merged */ int iList; /* Index into input list */ int iSub = 0; /* Index into aSub array */ struct Sublist aSub[13]; /* Array of sub-lists */ memset(aSub, 0, sizeof(aSub)); assert( nList<=HASHTABLE_NPAGE && nList>0 ); assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) ); ................................................................................ rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero); if( rc==SQLITE_OK ){ int j; /* Counter variable */ int nEntry; /* Number of entries in this segment */ ht_slot *aIndex; /* Sorted index for this segment */ aPgno++; nEntry = ((i+1)==nSegment)?iLast-iZero:(u32 *)aHash-(u32 *)aPgno; aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero]; iZero++; for(j=0; j<nEntry; j++){ aIndex[j] = j; } walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); p->aSegment[i].iZero = iZero; p->aSegment[i].nEntry = nEntry; p->aSegment[i].aIndex = aIndex; p->aSegment[i].aPgno = (u32 *)aPgno; } ................................................................................ walIndexClose(pWal, isDelete); sqlite3OsClose(pWal->pWalFd); if( isDelete ){ sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0); } WALTRACE(("WAL%p: closed\n", pWal)); sqlite3_free(pWal->apWiData); sqlite3_free(pWal); } return rc; } /* ** Try to read the wal-index header. Return 0 on success and 1 if ................................................................................ ** If and only if the read is consistent and the header is different from ** pWal->hdr, then pWal->hdr is updated to the content of the new header ** and *pChanged is set to 1. ** ** If the checksum cannot be verified return non-zero. If the header ** is read successfully and the checksum verified, return zero. */ int walIndexTryHdr(Wal *pWal, int *pChanged){ u32 aCksum[2]; /* Checksum on the header content */ WalIndexHdr h1, h2; /* Two copies of the header content */ WalIndexHdr volatile *aHdr; /* Header in shared memory */ /* The first page of the wal-index must be mapped at this point. */ assert( pWal->nWiData>0 && pWal->apWiData[0] ); ................................................................................ if( pInfo->aReadMark[mxI]!=mxReadMark || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ walUnlockShared(pWal, WAL_READ_LOCK(mxI)); return WAL_RETRY; }else{ assert( mxReadMark<=pWal->hdr.mxFrame ); pWal->readLock = mxI; } } return rc; } /* ** Begin a read transaction on the database. ................................................................................ sqlite3Put4byte(&aWalHdr[8], szPage); sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); sqlite3Put4byte(&aWalHdr[24], aCksum[0]); sqlite3Put4byte(&aWalHdr[28], aCksum[1]); pWal->szPage = szPage; pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; pWal->hdr.aFrameCksum[0] = aCksum[0]; pWal->hdr.aFrameCksum[1] = aCksum[1]; rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); if( rc!=SQLITE_OK ){ ................................................................................ iFrame++; nLast--; rc = walIndexAppend(pWal, iFrame, pLast->pgno); } if( rc==SQLITE_OK ){ /* Update the private copy of the header. */ pWal->hdr.szPage = szPage; pWal->hdr.mxFrame = iFrame; if( isCommit ){ pWal->hdr.iChange++; pWal->hdr.nPage = nTruncate; } /* If this is a commit, update the wal-index header too. */ if( isCommit ){ ................................................................................ BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage /* Write the page pointer here */ ){ int rc; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno<=0 || pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = btreeGetPage(pBt, pgno, ppPage, 0); if( rc==SQLITE_OK ){ rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } } return rc; } /* ** Release a MemPage. This should be called once for each prior ** call to btreeGetPage. */ ................................................................................ /* Any read-only or read-write transaction implies a read-lock on ** page 1. So if some other shared-cache client already has a write-lock ** on page 1, the transaction cannot be opened. */ rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); if( SQLITE_OK!=rc ) goto trans_begun; pBt->initiallyEmpty = pBt->nPage==0; do { /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after ** reading page 1 it discovers that the page-size of the database ** file is not pBt->pageSize. In this case lockBtree() will update ** pBt->pageSize to the page-size of the file on disk. ................................................................................ assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( pCur->eState==CURSOR_INVALID ){ assert( pCur->apPage[pCur->iPage]->nCell==0 ); *pRes = 1; rc = SQLITE_OK; }else{ assert( pCur->apPage[pCur->iPage]->nCell>0 ); *pRes = 0; rc = moveToLeftmost(pCur); } } return rc; ................................................................................ assert( pBtree->inTrans==TRANS_NONE ); assert( iVersion==1 || iVersion==2 ); /* If setting the version fields to 1, do not automatically open the ** WAL connection, even if the version fields are currently set to 2. */ pBt->doNotUseWAL = (iVersion==1); rc = sqlite3BtreeBeginTrans(pBtree, 0); if( rc==SQLITE_OK ){ u8 *aData = pBt->pPage1->aData; if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ rc = sqlite3BtreeBeginTrans(pBtree, 2); if( rc==SQLITE_OK ){ ................................................................................ if( bCloseTrans ){ TESTONLY( int rc2 ); TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc); assert( rc2==SQLITE_OK ); } p->rc = rc; } if( p->pDestDb ){ sqlite3_mutex_leave(p->pDestDb->mutex); } sqlite3BtreeLeave(p->pSrc); sqlite3_mutex_leave(p->pSrcDb->mutex); ................................................................................ ** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as ** a new VDBE is created. So we are free to set addr to p->nOp-1 without ** having to double-check to make sure that the result is non-negative. But ** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to ** check the value of p->nOp-1 before continuing. */ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ static const VdbeOp dummy; assert( p->magic==VDBE_MAGIC_INIT ); if( addr<0 ){ #ifdef SQLITE_OMIT_TRACE if( p->nOp==0 ) return (VdbeOp*)&dummy; #endif addr = p->nOp - 1; } ................................................................................ BtCursor *pCrsr; int res; #endif /* local variables moved into u.bl */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); u.bl.pC = p->apCsr[pOp->p1]; assert( u.bl.pC!=0 ); if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res); u.bl.pC->atFirst = u.bl.res==0 ?1:0; u.bl.pC->deferredMoveto = 0; u.bl.pC->cacheStatus = CACHE_STALE; u.bl.pC->rowidIsValid = 0; }else{ u.bl.res = 1; } u.bl.pC->nullRow = (u8)u.bl.res; assert( pOp->p2>0 && pOp->p2<p->nOp ); if( u.bl.res ){ pc = pOp->p2 - 1; } break; ................................................................................ */ case OP_Checkpoint: { rc = sqlite3Checkpoint(db, pOp->p1); break; }; #endif /* Opcode: JournalMode P1 P2 P3 * P5 ** ** Change the journal mode of database P1 to P3. P3 must be one of the ** PAGER_JOURNALMODE_XXX values. If changing between the various rollback ** modes (delete, truncate, persist, off and memory), this is a simple ** operation. No IO is required. ** ................................................................................ pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = (char *)sqlite3JournalModename(u.cd.eNew); pOut->n = sqlite3Strlen30(pOut->z); pOut->enc = SQLITE_UTF8; sqlite3VdbeChangeEncoding(pOut, encoding); break; }; #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* Opcode: Vacuum * * * * * ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. ................................................................................ jrnlSync, /* xSync */ jrnlFileSize, /* xFileSize */ 0, /* xLock */ 0, /* xUnlock */ 0, /* xCheckReservedLock */ 0, /* xFileControl */ 0, /* xSectorSize */ 0 /* xDeviceCharacteristics */ }; /* ** Open a journal file. */ SQLITE_PRIVATE int sqlite3JournalOpen( sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ ................................................................................ memjrnlSync, /* xSync */ memjrnlFileSize, /* xFileSize */ 0, /* xLock */ 0, /* xUnlock */ 0, /* xCheckReservedLock */ 0, /* xFileControl */ 0, /* xSectorSize */ 0 /* xDeviceCharacteristics */ }; /* ** Open a journal file. */ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ MemJournal *p = (MemJournal *)pJfd; ................................................................................ if( zDb ){ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); }else if( zTab ){ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); }else{ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } pTopNC->nErr++; } /* If a column from a table in pSrcList is referenced, then record ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the ** column number is greater than the number of bits in the bitmask ................................................................................ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); goto exit_create_index; } pIndex->aiColumn[i] = j; /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of ** the way the "idxlist" non-terminal is constructed by the parser, ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl ** must exist or else there must have been an OOM error. But if there ................................................................................ } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pColumn->a[i].zName) ){ keyColumn = i; }else{ sqlite3ErrorMsg(pParse, "table %S has no column named %s", pTabList, 0, pColumn->a[i].zName); pParse->nErr++; goto insert_cleanup; } } } } /* If there is no IDLIST term but the table has an integer primary ................................................................................ Index *pIdx; for(pIdx=pTab->pIndex; pIdx && sqlite3StrICmp(pIdx->zName, zIndex); pIdx=pIdx->pNext ); if( !pIdx ){ sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0); return SQLITE_ERROR; } pFrom->pIndex = pIdx; } return SQLITE_OK; } ................................................................................ pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); if( pTrigger ) break; } if( !pTrigger ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); } goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger); drop_trigger_cleanup: sqlite3SrcListDelete(db, pName); } ................................................................................ } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pChanges->a[i].zName) ){ chngRowid = 1; pRowidExpr = pChanges->a[i].pExpr; }else{ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, ................................................................................ pIdx->aiColumn[n] = pTerm->u.leftColumn; pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); pIdx->azColl[n] = pColl->zName; n++; } } } assert( n==pLevel->plan.nEq ); /* Add additional columns needed to make the automatic index into ** a covering index */ for(i=0; i<mxBitCol; i++){ if( extraCols & (((Bitmask)1)<<i) ){ pIdx->aiColumn[n] = i; pIdx->azColl[n] = "BINARY"; ................................................................................ zEndAff = sqlite3DbStrDup(pParse->db, zStartAff); addrNxt = pLevel->addrNxt; /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ if( bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); } testcase( pRangeStart && pRangeStart->eOperator & WO_LE ); testcase( pRangeStart && pRangeStart->eOperator & WO_GE ); testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE ); testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE ); ................................................................................ return rc; } /* ** An sqlite3_exec() callback for fts3TableExists. */ static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){ *(int*)pArg = 1; return 1; } /* ** Determine if a table currently exists in the database. */ ................................................................................ if( *pRc ) return; zSql = sqlite3_mprintf( "SELECT 1 FROM %Q.sqlite_master WHERE name='%q%s'", zDb, zName, zSuffix ); rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0); sqlite3_free(zSql); *pResult = res & 0xff; if( rc!=SQLITE_ABORT ) *pRc = rc; } /* ** This function is the implementation of both the xConnect and xCreate ** methods of the FTS3 virtual table. ** |
| | > | > | > > > | | | > > > | | > > | > > > > | > > > > | > > > > | > | > > > > > | | > | > > > | > > > > | < > > > | | > > > > > > > > > | > | | < < < < < < < < < < < < | < < | | | | | | | | | > > > | < < < > | > > | | | | | < < < > > > > > > > > > > > | > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > | < | > > > > > | > < < > > | > > > > > | > > > > > > > | > > > | | > > > | |
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 ..... 12793 12794 12795 12796 12797 12798 12799 12800 12801 12802 12803 12804 12805 12806 12807 12808 12809 12810 ..... 15367 15368 15369 15370 15371 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 ..... 15530 15531 15532 15533 15534 15535 15536 15537 15538 15539 15540 15541 15542 15543 15544 ..... 25963 25964 25965 25966 25967 25968 25969 25970 25971 25972 25973 25974 25975 25976 25977 ..... 27256 27257 27258 27259 27260 27261 27262 27263 27264 27265 27266 27267 27268 27269 27270 ..... 27484 27485 27486 27487 27488 27489 27490 27491 27492 27493 27494 27495 27496 27497 27498 ..... 27625 27626 27627 27628 27629 27630 27631 27632 27633 27634 27635 27636 27637 27638 27639 27640 27641 ..... 27677 27678 27679 27680 27681 27682 27683 27684 27685 27686 27687 27688 27689 27690 27691 ..... 27698 27699 27700 27701 27702 27703 27704 27705 27706 27707 27708 27709 27710 27711 27712 ..... 30195 30196 30197 30198 30199 30200 30201 30202 30203 30204 30205 30206 30207 30208 30209 30210 30211 ..... 30424 30425 30426 30427 30428 30429 30430 30431 30432 30433 30434 30435 30436 30437 30438 ..... 33512 33513 33514 33515 33516 33517 33518 33519 33520 33521 33522 33523 33524 33525 33526 33527 33528 33529 33530 33531 33532 33533 ..... 33793 33794 33795 33796 33797 33798 33799 33800 33801 33802 33803 33804 33805 33806 33807 33808 33809 ..... 35986 35987 35988 35989 35990 35991 35992 35993 35994 35995 35996 35997 35998 35999 36000 36001 36002 36003 36004 36005 36006 36007 36008 36009 36010 36011 36012 36013 36014 36015 36016 36017 36018 36019 36020 36021 36022 36023 36024 36025 36026 36027 36028 36029 36030 36031 36032 36033 36034 36035 36036 36037 36038 36039 36040 36041 36042 36043 36044 36045 36046 36047 36048 36049 36050 36051 36052 36053 36054 36055 36056 36057 36058 36059 36060 36061 36062 36063 36064 ..... 36424 36425 36426 36427 36428 36429 36430 36431 36432 36433 36434 36435 36436 36437 36438 ..... 37802 37803 37804 37805 37806 37807 37808 37809 37810 37811 37812 37813 37814 37815 37816 ..... 38233 38234 38235 38236 38237 38238 38239 38240 38241 38242 38243 38244 38245 38246 38247 38248 38249 38250 38251 38252 38253 38254 38255 38256 38257 38258 38259 ..... 38296 38297 38298 38299 38300 38301 38302 38303 38304 38305 38306 38307 38308 38309 38310 ..... 38737 38738 38739 38740 38741 38742 38743 38744 38745 38746 38747 38748 38749 38750 38751 38752 38753 38754 ..... 38874 38875 38876 38877 38878 38879 38880 38881 38882 38883 38884 38885 38886 38887 38888 ..... 38890 38891 38892 38893 38894 38895 38896 38897 38898 38899 38900 38901 38902 38903 38904 ..... 39224 39225 39226 39227 39228 39229 39230 39231 39232 39233 39234 39235 39236 39237 39238 39239 39240 39241 39242 39243 39244 39245 39246 39247 39248 39249 39250 39251 39252 ..... 39562 39563 39564 39565 39566 39567 39568 39569 39570 39571 39572 39573 39574 39575 39576 ..... 39619 39620 39621 39622 39623 39624 39625 39626 39627 39628 39629 39630 39631 39632 39633 39634 39635 39636 39637 39638 39639 39640 39641 39642 39643 39644 39645 39646 39647 39648 39649 39650 39651 39652 39653 39654 39655 39656 ..... 39683 39684 39685 39686 39687 39688 39689 39690 39691 39692 39693 39694 39695 39696 39697 ..... 40230 40231 40232 40233 40234 40235 40236 40237 40238 40239 40240 40241 40242 40243 40244 40245 40246 40247 40248 40249 ..... 40470 40471 40472 40473 40474 40475 40476 40477 40478 40479 40480 40481 40482 40483 40484 ..... 40486 40487 40488 40489 40490 40491 40492 40493 40494 40495 40496 40497 40498 40499 40500 ..... 40598 40599 40600 40601 40602 40603 40604 40605 40606 40607 40608 40609 40610 40611 40612 40613 40614 ..... 40634 40635 40636 40637 40638 40639 40640 40641 40642 40643 40644 40645 40646 40647 40648 ..... 40661 40662 40663 40664 40665 40666 40667 40668 40669 40670 40671 40672 40673 40674 40675 40676 40677 ..... 40682 40683 40684 40685 40686 40687 40688 40689 40690 40691 40692 40693 40694 40695 40696 ..... 40702 40703 40704 40705 40706 40707 40708 40709 40710 40711 40712 40713 40714 40715 40716 ..... 40810 40811 40812 40813 40814 40815 40816 40817 40818 40819 40820 40821 40822 40823 40824 40825 ..... 40861 40862 40863 40864 40865 40866 40867 40868 40869 40870 40871 40872 40873 40874 40875 ..... 41078 41079 41080 41081 41082 41083 41084 41085 41086 41087 41088 41089 41090 41091 41092 41093 ..... 41189 41190 41191 41192 41193 41194 41195 41196 41197 41198 41199 41200 41201 41202 41203 41204 41205 41206 41207 41208 ..... 41381 41382 41383 41384 41385 41386 41387 41388 41389 41390 41391 41392 41393 41394 41395 ..... 41404 41405 41406 41407 41408 41409 41410 41411 41412 41413 41414 41415 41416 41417 41418 ..... 41717 41718 41719 41720 41721 41722 41723 41724 41725 41726 41727 41728 41729 41730 41731 ..... 42130 42131 42132 42133 42134 42135 42136 42137 42138 42139 42140 42141 42142 42143 42144 ..... 42224 42225 42226 42227 42228 42229 42230 42231 42232 42233 42234 42235 42236 42237 42238 ..... 44961 44962 44963 44964 44965 44966 44967 44968 44969 44970 44971 44972 44973 44974 44975 44976 44977 44978 44979 44980 44981 44982 44983 44984 44985 44986 44987 44988 ..... 45901 45902 45903 45904 45905 45906 45907 45908 45909 45910 45911 45912 45913 45914 45915 ..... 47624 47625 47626 47627 47628 47629 47630 47631 47632 47633 47634 47635 47636 47637 ..... 51388 51389 51390 51391 51392 51393 51394 51395 51396 51397 51398 51399 51400 51401 51402 ..... 51880 51881 51882 51883 51884 51885 51886 51887 51888 51889 51890 51891 51892 51893 51894 51895 51896 ..... 54005 54006 54007 54008 54009 54010 54011 54012 54013 54014 54015 54016 54017 54018 54019 54020 54021 ..... 62438 62439 62440 62441 62442 62443 62444 62445 62446 62447 62448 62449 62450 62451 62452 62453 62454 62455 62456 62457 62458 ..... 63488 63489 63490 63491 63492 63493 63494 63495 63496 63497 63498 63499 63500 63501 63502 ..... 63616 63617 63618 63619 63620 63621 63622 63623 63624 63625 63626 63627 63628 63629 63630 ..... 64800 64801 64802 64803 64804 64805 64806 64807 64808 64809 64810 64811 64812 64813 64814 64815 64816 64817 64818 64819 ..... 65085 65086 65087 65088 65089 65090 65091 65092 65093 65094 65095 65096 65097 65098 65099 65100 65101 65102 65103 65104 ..... 65613 65614 65615 65616 65617 65618 65619 65620 65621 65622 65623 65624 65625 65626 65627 ..... 75103 75104 75105 75106 75107 75108 75109 75110 75111 75112 75113 75114 75115 75116 75117 ..... 80804 80805 80806 80807 80808 80809 80810 80811 80812 80813 80814 80815 80816 80817 80818 ..... 88451 88452 88453 88454 88455 88456 88457 88458 88459 88460 88461 88462 88463 88464 88465 ..... 90437 90438 90439 90440 90441 90442 90443 90444 90445 90446 90447 90448 90449 90450 90451 ..... 91248 91249 91250 91251 91252 91253 91254 91255 91256 91257 91258 91259 91260 91261 91262 ..... 94827 94828 94829 94830 94831 94832 94833 94834 94835 94836 94837 94838 94839 94840 94841 ..... 96421 96422 96423 96424 96425 96426 96427 96428 96429 96430 96431 96432 96433 96434 96435 ...... 106106 106107 106108 106109 106110 106111 106112 106113 106114 106115 106116 106117 106118 106119 106120 106121 106122 ...... 106134 106135 106136 106137 106138 106139 106140 106141 106142 106143 106144 106145 106146 106147 106148 |
** ** See also: [sqlite3_libversion()], ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ #define SQLITE_VERSION "3.7.0" #define SQLITE_VERSION_NUMBER 3007000 #define SQLITE_SOURCE_ID "2010-07-03 13:59:01 3b20ad03be55613d922d81aec5313327bf4098b9" /* ** CAPI3REF: Run-Time Library Version Numbers ** KEYWORDS: sqlite3_version, sqlite3_sourceid ** ** These interfaces provide the same information as the [SQLITE_VERSION], ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros ................................................................................ ** sqlite3OsOpen() ** sqlite3OsRead() ** sqlite3OsWrite() ** sqlite3OsSync() ** sqlite3OsLock() ** */ #if defined(SQLITE_TEST) SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1; #define DO_OS_MALLOC_TEST(x) \ if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \ void *pTstAlloc = sqlite3Malloc(10); \ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ sqlite3_free(pTstAlloc); \ } #else #define DO_OS_MALLOC_TEST(x) #endif ................................................................................ /* ** Stub routines for all mutex methods. ** ** This routines provide no mutual exclusion or error checking. */ static int noopMutexInit(void){ return SQLITE_OK; } static int noopMutexEnd(void){ return SQLITE_OK; } static sqlite3_mutex *noopMutexAlloc(int id){ UNUSED_PARAMETER(id); return (sqlite3_mutex*)8; } static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } static int noopMutexTry(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return SQLITE_OK; } static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; } SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){ static const sqlite3_mutex_methods sMutex = { noopMutexInit, noopMutexEnd, noopMutexAlloc, noopMutexFree, ................................................................................ /* ** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation ** is used regardless of the run-time threadsafety setting. */ #ifdef SQLITE_MUTEX_NOOP SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){ return sqlite3NoopMutex(); } #endif /* SQLITE_MUTEX_NOOP */ #endif /* SQLITE_MUTEX_OMIT */ /************** End of mutex_noop.c ******************************************/ /************** Begin file mutex_os2.c ***************************************/ /* ................................................................................ ** ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. */ static void unixShmBarrier( sqlite3_file *fd /* Database file holding the shared memory */ ){ UNUSED_PARAMETER(fd); unixEnterMutex(); unixLeaveMutex(); } /* ** This function is called to obtain a pointer to region iRegion of the ** shared-memory associated with the database file fd. Shared-memory regions ................................................................................ /* ** Find the current time (in Universal Coordinated Time). Write the ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){ sqlite3_int64 i; UNUSED_PARAMETER(NotUsed); unixCurrentTimeInt64(0, &i); *prNow = i/86400000.0; return 0; } /* ** We added the xGetLastError() method with the intention of providing ................................................................................ if( lPath[len-1]!='/' ){ len = strlcat(lPath, "/", maxLen); } /* transform the db path to a unique cache name */ dbLen = (int)strlen(dbPath); for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){ char c = dbPath[i]; lPath[i+len] = (c=='/')?'_':c; } lPath[i+len]='\0'; strlcat(lPath, ":auto:", maxLen); OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid())); return SQLITE_OK; ................................................................................ #ifdef SQLITE_TEST /* simulate multiple hosts by creating unique hostid file paths */ SQLITE_API int sqlite3_hostid_num = 0; #endif #define PROXY_HOSTIDLEN 16 /* conch file host id length */ /* Not always defined in the headers as it ought to be */ extern int gethostuuid(uuid_t id, const struct timespec *wait); /* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN ** bytes of writable memory. */ static int proxyGetHostID(unsigned char *pHostID, int *pError){ struct timespec timeout = {1, 0}; /* 1 sec timeout */ assert(PROXY_HOSTIDLEN == sizeof(uuid_t)); ................................................................................ char buf[PROXY_MAXCONCHLEN]; char *cPath = pCtx->conchFilePath; size_t readLen = 0; size_t pathLen = 0; char errmsg[64] = ""; int fd = -1; int rc = -1; UNUSED_PARAMETER(myHostID); /* create a new path by replace the trailing '-conch' with '-break' */ pathLen = strlcpy(tPath, cPath, MAXPATHLEN); if( pathLen>MAXPATHLEN || pathLen<6 || (strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){ sprintf(errmsg, "path error (len %d)", (int)pathLen); goto end_breaklock; ................................................................................ } /* write it out to the temporary break file */ fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS); if( fd<0 ){ sprintf(errmsg, "create failed (%d)", errno); goto end_breaklock; } if( pwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){ sprintf(errmsg, "write failed (%d)", errno); goto end_breaklock; } if( rename(tPath, cPath) ){ sprintf(errmsg, "rename failed (%d)", errno); goto end_breaklock; } ................................................................................ } /* Check to see if another process is holding the dead-man switch. ** If not, truncate the file to zero length. */ if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); if( rc!=SQLITE_OK ){ rc = SQLITE_IOERR_SHMOPEN; } } if( rc==SQLITE_OK ){ winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); } if( rc ) goto shm_open_err; } ................................................................................ ** ** All loads and stores begun before the barrier must complete before ** any load or store begun after the barrier. */ static void winShmBarrier( sqlite3_file *fd /* Database holding the shared memory */ ){ UNUSED_PARAMETER(fd); /* MemoryBarrier(); // does not work -- do not know why not */ winShmEnterMutex(); winShmLeaveMutex(); } #else # define winShmOpen 0 ................................................................................ # define sqlite3WalOpen(x,y,z) 0 # define sqlite3WalClose(w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalRead(v,w,x,y,z) 0 # define sqlite3WalDbsize(y,z) # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWriteTransaction(x) 0 # define sqlite3WalUndo(x,y,z) 0 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 # define sqlite3WalCheckpoint(u,v,w,x) 0 # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 #else #define WAL_SAVEPOINT_NDATA 4 /* Connection to a write-ahead log (WAL) file. ** There is one object of this type for each pager. */ ................................................................................ typedef struct PagerSavepoint PagerSavepoint; struct PagerSavepoint { i64 iOffset; /* Starting offset in main journal */ i64 iHdrOffset; /* See above */ Bitvec *pInSavepoint; /* Set of pages in this savepoint */ Pgno nOrig; /* Original number of pages in file */ Pgno iSubRec; /* Index of first record in sub-journal */ #ifndef SQLITE_OMIT_WAL u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */ #endif }; /* ** A open page cache is an instance of the following structure. ** ** errCode ** ................................................................................ } pPager->state = PAGER_SHARED; return rc; } /* ** Check for the existence of or delete the *-wal file that corresponds to ** the database opened by pPager. ** ** When pExists!=NULL, set *pExists to 1 if the *-wal file exists, or 0 ** if the *-wal file does not exist. ** ** When pExists==NULL, delete the *-wal file if it exists, or the do ** nothing if the *-wal file does not exist. ** ** Return SQLITE_OK on success. If on an IO or OOM error occurs, return ** an SQLite error code. */ static int pagerCheckForOrDeleteWAL(Pager *pPager, int *pExists){ int rc; /* Return code */ char *zWal; /* Name of the WAL file */ assert( !pPager->tempFile ); zWal = sqlite3_mprintf("%s-wal", pPager->zFilename); if( !zWal ){ rc = SQLITE_NOMEM; }else{ if( pExists ){ rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists); }else{ rc = sqlite3OsDelete(pPager->pVfs, zWal, 0); } sqlite3_free(zWal); } return rc; } /* ** Check if the *-wal file that corresponds to the database opened by pPager ** exists if the database is not empy, or verify that the *-wal file does ** not exist (by deleting it) if the database file is empty. ** ** If the database is not empty and the *-wal file exists, open the pager ** in WAL mode. If the database is empty or if no *-wal file exists and ** if no error occurs, make sure Pager.journalMode is not set to ** PAGER_JOURNALMODE_WAL. ** ** Return SQLITE_OK or an error code. ** ** If the WAL file is opened, also open a snapshot (read transaction). ** ** The caller must hold a SHARED lock on the database file to call this ** function. Because an EXCLUSIVE lock on the db file is required to delete ** a WAL on a none-empty database, this ensures there is no race condition ** between the xAccess() below and an xDelete() being executed by some ** other connection. */ static int pagerOpenWalIfPresent(Pager *pPager){ int rc = SQLITE_OK; if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ int nPage; /* Size of the database file */ assert( pPager->state>=SHARED_LOCK ); rc = sqlite3PagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ rc = pagerCheckForOrDeleteWAL(pPager, 0); isWal = 0; }else{ rc = pagerCheckForOrDeleteWAL(pPager, &isWal); } if( rc==SQLITE_OK ){ if( isWal ){ pager_reset(pPager); rc = sqlite3PagerOpenWal(pPager, 0); if( rc==SQLITE_OK ){ rc = pagerBeginReadTransaction(pPager); } ................................................................................ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ int nPage; if( mxPage>0 ){ pPager->mxPgno = mxPage; } if( pPager->state!=PAGER_UNLOCK ){ sqlite3PagerPagecount(pPager, &nPage); assert( (int)pPager->mxPgno>=nPage ); } return pPager->mxPgno; } /* ** The following set of routines are used to disable the simulated ** I/O error mechanism. These routines are used to avoid simulated ................................................................................ ** other bytes change randomly with each file change when ** a codec is in use. ** ** There is a vanishingly small chance that a change will not be ** detected. The chance of an undetected change is so small that ** it can be neglected. */ int nPage = 0; char dbFileVers[sizeof(pPager->dbFileVers)]; sqlite3PagerPagecount(pPager, &nPage); if( pPager->errCode ){ rc = pPager->errCode; goto failed; } ................................................................................ } /* No need to open the journal file at this time. It will be ** opened before it is written to. If we defer opening the journal, ** we might save the work of creating a file if the transaction ** ends up being a no-op. */ if( rc!=SQLITE_OK ){ assert( !pPager->dbModified ); /* Ignore any IO error that occurs within pager_end_transaction(). The ** purpose of this call is to reset the internal state of the pager ** sub-system. It doesn't matter if the journal-file is not properly ** finalized at this point (since it is not a valid journal file anyway). */ pager_end_transaction(pPager, 0); } } PAGERTRACE(("TRANSACTION %d\n", PAGERID(pPager))); return rc; } /* ** Mark a single data page as writeable. The page is written into the ** main journal or sub-journal as required. If the page is written into ** one of the journals, the corresponding bit is set in the ................................................................................ ** written to the transaction journal or the ckeckpoint journal ** or both. ** ** Higher level routines should have already started a transaction, ** which means they have acquired the necessary locks but the rollback ** journal might not yet be open. */ assert( pPager->state>=RESERVED_LOCK ); if( pPager->pInJournal==0 && pPager->journalMode!=PAGER_JOURNALMODE_OFF && !pagerUseWal(pPager) ){ assert( pPager->useJournal ); rc = pager_open_journal(pPager); if( rc!=SQLITE_OK ) return rc; ................................................................................ ** Otherwise, if the optimization is both enabled and applicable, ** then call pager_incr_changecounter() to update the change-counter ** in 'direct' mode. In this case the journal file will never be ** created for this transaction. */ #ifdef SQLITE_ENABLE_ATOMIC_WRITE PgHdr *pPg; assert( isOpen(pPager->jfd) || pPager->journalMode==PAGER_JOURNALMODE_OFF || pPager->journalMode==PAGER_JOURNALMODE_WAL ); if( !zMaster && isOpen(pPager->jfd) && pPager->journalOff==jrnlBufferSize(pPager) && pPager->dbSize>=pPager->dbFileSize && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty) ){ /* Update the db file change counter via the direct-write method. The ** following call will modify the in-memory representation of page 1 ................................................................................ if( NEVER(pPager->errCode) ) return pPager->errCode; /* This function should not be called if the pager is not in at least ** PAGER_RESERVED state. **FIXME**: Make it so that this test always ** fails - make it so that we never reach this point if we do not hold ** all necessary locks. */ if( NEVER(pPager->state<PAGER_RESERVED) ) return SQLITE_ERROR; /* An optimization. If the database was not actually modified during ** this transaction, the pager is running in exclusive-mode and is ** using persistent journals, then this function is a no-op. ** ** The start of the journal file currently contains a single journal ** header with the nRec field set to 0. If such a journal is used as ................................................................................ ** to the database file. So there is no need to zero the journal ** header. Since the pager is in exclusive mode, there is no need ** to drop any locks either. */ if( pPager->dbModified==0 && pPager->exclusiveMode && pPager->journalMode==PAGER_JOURNALMODE_PERSIST ){ assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); return SQLITE_OK; } PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dbModified ); rc = pager_end_transaction(pPager, pPager->setMaster); return pager_error(pPager, rc); ................................................................................ return pPager->noSync; } #ifdef SQLITE_HAS_CODEC /* ** Set or retrieve the codec for this pager */ SQLITE_PRIVATE void sqlite3PagerSetCodec( Pager *pPager, void *(*xCodec)(void*,void*,Pgno,int), void (*xCodecSizeChng)(void*,int,int), void (*xCodecFree)(void*), void *pCodec ){ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); pPager->xCodec = pPager->memDb ? 0 : xCodec; pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree; pPager->pCodec = pCodec; pagerReportSize(pPager); } SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){ return pPager->pCodec; } #endif #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Move the page pPg to location pgno in the file. ................................................................................ /* ** Return TRUE if the pager is in a state where it is OK to change the ** journalmode. Journalmode changes can only happen when the database ** is unmodified. */ SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ if( pPager->dbModified ) return 0; if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; return 1; } /* ** Get/set the size-limit used for persistent journal files. ** ** Setting the size limit to -1 means no limit is enforced. ................................................................................ */ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ const sqlite3_io_methods *pMethods = pPager->fd->pMethods; return pMethods->iVersion>=2 && pMethods->xShmOpen!=0; } /* ** The caller must be holding a SHARED lock on the database file to call ** this function. ** ** If the pager passed as the first argument is open on a real database ** file (not a temp file or an in-memory database), and the WAL file ** is not already open, make an attempt to open it now. If successful, ** return SQLITE_OK. If an error occurs or the VFS used by the pager does ** not support the xShmXXX() methods, return an error code. *pisOpen is ** not modified in either case. ** ** If the pager is open on a temp-file (or in-memory database), or if ** the WAL file is already open, set *pisOpen to 1 and return SQLITE_OK ** without doing anything. */ SQLITE_PRIVATE int sqlite3PagerOpenWal( Pager *pPager, /* Pager object */ int *pisOpen /* OUT: Set to true if call is a no-op */ ){ int rc = SQLITE_OK; /* Return code */ assert( pPager->state>=PAGER_SHARED ); assert( (pisOpen==0 && !pPager->tempFile && !pPager->pWal) || *pisOpen==0 ); if( !pPager->tempFile && !pPager->pWal ){ if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; /* Open the connection to the log file. If this operation fails, ** (e.g. due to malloc() failure), unlock the database file and ** return an error code. */ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, ................................................................................ ** it may need to be checkpointed before the connection can switch to ** rollback mode. Open it now so this can happen. */ if( !pPager->pWal ){ int logexists = 0; rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED); if( rc==SQLITE_OK ){ rc = pagerCheckForOrDeleteWAL(pPager, &logexists); } if( rc==SQLITE_OK && logexists ){ rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zFilename, &pPager->pWal); } } ................................................................................ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ int rc = SQLITE_OK; /* Enlarge the pWal->apWiData[] array if required */ if( pWal->nWiData<=iPage ){ int nByte = sizeof(u32 *)*(iPage+1); volatile u32 **apNew; apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte); if( !apNew ){ *ppPage = 0; return SQLITE_NOMEM; } memset((void *)&apNew[pWal->nWiData], 0, sizeof(u32 *)*(iPage+1-pWal->nWiData)); pWal->apWiData = apNew; pWal->nWiData = iPage+1; } /* Request a pointer to the required page from the VFS */ if( pWal->apWiData[iPage]==0 ){ rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, ................................................................................ static int walLockShared(Wal *pWal, int lockIdx){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); ................................................................................ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ int rc; if( pWal->exclusiveMode ) return SQLITE_OK; rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, walLockName(lockIdx), n, rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) return rc; } static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); WALTRACE(("WAL%p: release EXCLUSIVE-%s cnt=%d\n", pWal, ................................................................................ ** ** At most only the hash table containing pWal->hdr.mxFrame needs to be ** updated. Any later hash tables will be automatically cleared when ** pWal->hdr.mxFrame advances to the point where those hash tables are ** actually needed. */ static void walCleanupHash(Wal *pWal){ volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */ volatile u32 *aPgno = 0; /* Page number array for hash table */ u32 iZero = 0; /* frame == (aHash[x]+iZero) */ int iLimit = 0; /* Zero values greater than this */ int nByte; /* Number of bytes to zero in aPgno[] */ int i; /* Used to iterate through aHash[] */ assert( pWal->writeLock ); testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 ); testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE ); ................................................................................ aHash[i] = 0; } } /* Zero the entries in the aPgno array that correspond to frames with ** frame numbers greater than pWal->hdr.mxFrame. */ nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]); memset((void *)&aPgno[iLimit+1], 0, nByte); #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the every entry in the mapping region is still reachable ** via the hash table even after the cleanup. */ if( iLimit ){ ................................................................................ /* ** Set an entry in the wal-index that will map database page number ** pPage into WAL frame iFrame. */ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ int rc; /* Return code */ u32 iZero = 0; /* One less than frame number of aPgno[1] */ volatile u32 *aPgno = 0; /* Page number array */ volatile ht_slot *aHash = 0; /* Hash table */ rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero); /* Assuming the wal-index file was successfully mapped, populate the ** page number array and hash table entry. */ if( rc==SQLITE_OK ){ ................................................................................ idx = iFrame - iZero; assert( idx <= HASHTABLE_NSLOT/2 + 1 ); /* If this is the first entry to be added to this hash-table, zero the ** entire hash table and aPgno[] array before proceding. */ if( idx==1 ){ int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]); memset((void*)&aPgno[1], 0, nByte); } /* If the entry in aPgno[] is already set, then the previous writer ** must have exited unexpectedly in the middle of a transaction (after ** writing one or more dirty pages to the WAL to free up memory). ** Remove the remnants of that writers uncommitted transaction from ................................................................................ } /* Write the aPgno[] array entry and the hash-table slot. */ for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ assert( nCollide++ < idx ); } aPgno[idx] = iPage; aHash[iKey] = (ht_slot)idx; #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the number of entries in the hash table exactly equals ** the number of entries in the mapping region. */ { int i; /* Loop counter */ ................................................................................ if( (magic&0xFFFFFFFE)!=WAL_MAGIC || szPage&(szPage-1) || szPage>SQLITE_MAX_PAGE_SIZE || szPage<512 ){ goto finished; } pWal->hdr.bigEndCksum = (u8)(magic&0x00000001); pWal->szPage = (u16)szPage; pWal->nCkpt = sqlite3Get4byte(&aBuf[12]); memcpy(&pWal->hdr.aSalt, &aBuf[16], 8); /* Verify that the WAL header checksum is correct */ walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum ); ................................................................................ rc = walIndexAppend(pWal, ++iFrame, pgno); if( rc!=SQLITE_OK ) break; /* If nTruncate is non-zero, this is a commit record. */ if( nTruncate ){ pWal->hdr.mxFrame = iFrame; pWal->hdr.nPage = nTruncate; pWal->hdr.szPage = (u16)szPage; aFrameCksum[0] = pWal->hdr.aFrameCksum[0]; aFrameCksum[1] = pWal->hdr.aFrameCksum[1]; } } sqlite3_free(aFrame); } ................................................................................ ){ struct Sublist { int nList; /* Number of elements in aList */ ht_slot *aList; /* Pointer to sub-list content */ }; const int nList = *pnList; /* Size of input list */ int nMerge = 0; /* Number of elements in list aMerge */ ht_slot *aMerge = 0; /* List to be merged */ int iList; /* Index into input list */ int iSub = 0; /* Index into aSub array */ struct Sublist aSub[13]; /* Array of sub-lists */ memset(aSub, 0, sizeof(aSub)); assert( nList<=HASHTABLE_NPAGE && nList>0 ); assert( HASHTABLE_NPAGE==(1<<(ArraySize(aSub)-1)) ); ................................................................................ rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero); if( rc==SQLITE_OK ){ int j; /* Counter variable */ int nEntry; /* Number of entries in this segment */ ht_slot *aIndex; /* Sorted index for this segment */ aPgno++; nEntry = (int)(((i+1)==nSegment)?(int)(iLast-iZero):(u32 *)aHash-(u32 *)aPgno); aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero]; iZero++; for(j=0; j<nEntry; j++){ aIndex[j] = (ht_slot)j; } walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry); p->aSegment[i].iZero = iZero; p->aSegment[i].nEntry = nEntry; p->aSegment[i].aIndex = aIndex; p->aSegment[i].aPgno = (u32 *)aPgno; } ................................................................................ walIndexClose(pWal, isDelete); sqlite3OsClose(pWal->pWalFd); if( isDelete ){ sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0); } WALTRACE(("WAL%p: closed\n", pWal)); sqlite3_free((void *)pWal->apWiData); sqlite3_free(pWal); } return rc; } /* ** Try to read the wal-index header. Return 0 on success and 1 if ................................................................................ ** If and only if the read is consistent and the header is different from ** pWal->hdr, then pWal->hdr is updated to the content of the new header ** and *pChanged is set to 1. ** ** If the checksum cannot be verified return non-zero. If the header ** is read successfully and the checksum verified, return zero. */ static int walIndexTryHdr(Wal *pWal, int *pChanged){ u32 aCksum[2]; /* Checksum on the header content */ WalIndexHdr h1, h2; /* Two copies of the header content */ WalIndexHdr volatile *aHdr; /* Header in shared memory */ /* The first page of the wal-index must be mapped at this point. */ assert( pWal->nWiData>0 && pWal->apWiData[0] ); ................................................................................ if( pInfo->aReadMark[mxI]!=mxReadMark || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){ walUnlockShared(pWal, WAL_READ_LOCK(mxI)); return WAL_RETRY; }else{ assert( mxReadMark<=pWal->hdr.mxFrame ); pWal->readLock = (i16)mxI; } } return rc; } /* ** Begin a read transaction on the database. ................................................................................ sqlite3Put4byte(&aWalHdr[8], szPage); sqlite3Put4byte(&aWalHdr[12], pWal->nCkpt); memcpy(&aWalHdr[16], pWal->hdr.aSalt, 8); walChecksumBytes(1, aWalHdr, WAL_HDRSIZE-2*4, 0, aCksum); sqlite3Put4byte(&aWalHdr[24], aCksum[0]); sqlite3Put4byte(&aWalHdr[28], aCksum[1]); pWal->szPage = (u16)szPage; pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN; pWal->hdr.aFrameCksum[0] = aCksum[0]; pWal->hdr.aFrameCksum[1] = aCksum[1]; rc = sqlite3OsWrite(pWal->pWalFd, aWalHdr, sizeof(aWalHdr), 0); WALTRACE(("WAL%p: wal-header write %s\n", pWal, rc ? "failed" : "ok")); if( rc!=SQLITE_OK ){ ................................................................................ iFrame++; nLast--; rc = walIndexAppend(pWal, iFrame, pLast->pgno); } if( rc==SQLITE_OK ){ /* Update the private copy of the header. */ pWal->hdr.szPage = (u16)szPage; pWal->hdr.mxFrame = iFrame; if( isCommit ){ pWal->hdr.iChange++; pWal->hdr.nPage = nTruncate; } /* If this is a commit, update the wal-index header too. */ if( isCommit ){ ................................................................................ BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ MemPage **ppPage /* Write the page pointer here */ ){ int rc; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeGetPage(pBt, pgno, ppPage, 0); if( rc==SQLITE_OK ){ rc = btreeInitPage(*ppPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); } } } testcase( pgno==0 ); assert( pgno!=0 || rc==SQLITE_CORRUPT ); return rc; } /* ** Release a MemPage. This should be called once for each prior ** call to btreeGetPage. */ ................................................................................ /* Any read-only or read-write transaction implies a read-lock on ** page 1. So if some other shared-cache client already has a write-lock ** on page 1, the transaction cannot be opened. */ rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK); if( SQLITE_OK!=rc ) goto trans_begun; pBt->initiallyEmpty = (u8)(pBt->nPage==0); do { /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after ** reading page 1 it discovers that the page-size of the database ** file is not pBt->pageSize. In this case lockBtree() will update ** pBt->pageSize to the page-size of the file on disk. ................................................................................ assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( pCur->eState==CURSOR_INVALID ){ assert( pCur->apPage[pCur->iPage]->nCell==0 ); *pRes = 1; }else{ assert( pCur->apPage[pCur->iPage]->nCell>0 ); *pRes = 0; rc = moveToLeftmost(pCur); } } return rc; ................................................................................ assert( pBtree->inTrans==TRANS_NONE ); assert( iVersion==1 || iVersion==2 ); /* If setting the version fields to 1, do not automatically open the ** WAL connection, even if the version fields are currently set to 2. */ pBt->doNotUseWAL = (u8)(iVersion==1); rc = sqlite3BtreeBeginTrans(pBtree, 0); if( rc==SQLITE_OK ){ u8 *aData = pBt->pPage1->aData; if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){ rc = sqlite3BtreeBeginTrans(pBtree, 2); if( rc==SQLITE_OK ){ ................................................................................ if( bCloseTrans ){ TESTONLY( int rc2 ); TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc); assert( rc2==SQLITE_OK ); } if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM; } p->rc = rc; } if( p->pDestDb ){ sqlite3_mutex_leave(p->pDestDb->mutex); } sqlite3BtreeLeave(p->pSrc); sqlite3_mutex_leave(p->pSrcDb->mutex); ................................................................................ ** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as ** a new VDBE is created. So we are free to set addr to p->nOp-1 without ** having to double-check to make sure that the result is non-negative. But ** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to ** check the value of p->nOp-1 before continuing. */ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ /* C89 specifies that the constant "dummy" will be initialized to all ** zeros, which is correct. MSVC generates a warning, nevertheless. */ static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */ assert( p->magic==VDBE_MAGIC_INIT ); if( addr<0 ){ #ifdef SQLITE_OMIT_TRACE if( p->nOp==0 ) return (VdbeOp*)&dummy; #endif addr = p->nOp - 1; } ................................................................................ BtCursor *pCrsr; int res; #endif /* local variables moved into u.bl */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); u.bl.pC = p->apCsr[pOp->p1]; assert( u.bl.pC!=0 ); u.bl.res = 1; if( (u.bl.pCrsr = u.bl.pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(u.bl.pCrsr, &u.bl.res); u.bl.pC->atFirst = u.bl.res==0 ?1:0; u.bl.pC->deferredMoveto = 0; u.bl.pC->cacheStatus = CACHE_STALE; u.bl.pC->rowidIsValid = 0; } u.bl.pC->nullRow = (u8)u.bl.res; assert( pOp->p2>0 && pOp->p2<p->nOp ); if( u.bl.res ){ pc = pOp->p2 - 1; } break; ................................................................................ */ case OP_Checkpoint: { rc = sqlite3Checkpoint(db, pOp->p1); break; }; #endif #ifndef SQLITE_OMIT_PRAGMA /* Opcode: JournalMode P1 P2 P3 * P5 ** ** Change the journal mode of database P1 to P3. P3 must be one of the ** PAGER_JOURNALMODE_XXX values. If changing between the various rollback ** modes (delete, truncate, persist, off and memory), this is a simple ** operation. No IO is required. ** ................................................................................ pOut->flags = MEM_Str|MEM_Static|MEM_Term; pOut->z = (char *)sqlite3JournalModename(u.cd.eNew); pOut->n = sqlite3Strlen30(pOut->z); pOut->enc = SQLITE_UTF8; sqlite3VdbeChangeEncoding(pOut, encoding); break; }; #endif /* SQLITE_OMIT_PRAGMA */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) /* Opcode: Vacuum * * * * * ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. ................................................................................ jrnlSync, /* xSync */ jrnlFileSize, /* xFileSize */ 0, /* xLock */ 0, /* xUnlock */ 0, /* xCheckReservedLock */ 0, /* xFileControl */ 0, /* xSectorSize */ 0, /* xDeviceCharacteristics */ 0, /* xShmOpen */ 0, /* xShmLock */ 0, /* xShmMap */ 0, /* xShmBarrier */ 0 /* xShmClose */ }; /* ** Open a journal file. */ SQLITE_PRIVATE int sqlite3JournalOpen( sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ ................................................................................ memjrnlSync, /* xSync */ memjrnlFileSize, /* xFileSize */ 0, /* xLock */ 0, /* xUnlock */ 0, /* xCheckReservedLock */ 0, /* xFileControl */ 0, /* xSectorSize */ 0, /* xDeviceCharacteristics */ 0, /* xShmOpen */ 0, /* xShmLock */ 0, /* xShmMap */ 0, /* xShmBarrier */ 0 /* xShmClose */ }; /* ** Open a journal file. */ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){ MemJournal *p = (MemJournal *)pJfd; ................................................................................ if( zDb ){ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); }else if( zTab ){ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); }else{ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } pParse->checkSchema = 1; pTopNC->nErr++; } /* If a column from a table in pSrcList is referenced, then record ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the ** column number is greater than the number of bits in the bitmask ................................................................................ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); pParse->checkSchema = 1; goto exit_create_index; } pIndex->aiColumn[i] = j; /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of ** the way the "idxlist" non-terminal is constructed by the parser, ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl ** must exist or else there must have been an OOM error. But if there ................................................................................ } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pColumn->a[i].zName) ){ keyColumn = i; }else{ sqlite3ErrorMsg(pParse, "table %S has no column named %s", pTabList, 0, pColumn->a[i].zName); pParse->checkSchema = 1; goto insert_cleanup; } } } } /* If there is no IDLIST term but the table has an integer primary ................................................................................ Index *pIdx; for(pIdx=pTab->pIndex; pIdx && sqlite3StrICmp(pIdx->zName, zIndex); pIdx=pIdx->pNext ); if( !pIdx ){ sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0); pParse->checkSchema = 1; return SQLITE_ERROR; } pFrom->pIndex = pIdx; } return SQLITE_OK; } ................................................................................ pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); if( pTrigger ) break; } if( !pTrigger ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); } pParse->checkSchema = 1; goto drop_trigger_cleanup; } sqlite3DropTriggerPtr(pParse, pTrigger); drop_trigger_cleanup: sqlite3SrcListDelete(db, pName); } ................................................................................ } if( j>=pTab->nCol ){ if( sqlite3IsRowid(pChanges->a[i].zName) ){ chngRowid = 1; pRowidExpr = pChanges->a[i].pExpr; }else{ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); pParse->checkSchema = 1; goto update_cleanup; } } #ifndef SQLITE_OMIT_AUTHORIZATION { int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, ................................................................................ pIdx->aiColumn[n] = pTerm->u.leftColumn; pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); pIdx->azColl[n] = pColl->zName; n++; } } } assert( (u32)n==pLevel->plan.nEq ); /* Add additional columns needed to make the automatic index into ** a covering index */ for(i=0; i<mxBitCol; i++){ if( extraCols & (((Bitmask)1)<<i) ){ pIdx->aiColumn[n] = i; pIdx->azColl[n] = "BINARY"; ................................................................................ zEndAff = sqlite3DbStrDup(pParse->db, zStartAff); addrNxt = pLevel->addrNxt; /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ if( nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); } testcase( pRangeStart && pRangeStart->eOperator & WO_LE ); testcase( pRangeStart && pRangeStart->eOperator & WO_GE ); testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE ); testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE ); ................................................................................ return rc; } /* ** An sqlite3_exec() callback for fts3TableExists. */ static int fts3TableExistsCallback(void *pArg, int n, char **pp1, char **pp2){ UNUSED_PARAMETER(n); UNUSED_PARAMETER(pp1); UNUSED_PARAMETER(pp2); *(int*)pArg = 1; return 1; } /* ** Determine if a table currently exists in the database. */ ................................................................................ if( *pRc ) return; zSql = sqlite3_mprintf( "SELECT 1 FROM %Q.sqlite_master WHERE name='%q%s'", zDb, zName, zSuffix ); rc = sqlite3_exec(db, zSql, fts3TableExistsCallback, &res, 0); sqlite3_free(zSql); *pResult = (u8)(res & 0xff); if( rc!=SQLITE_ABORT ) *pRc = rc; } /* ** This function is the implementation of both the xConnect and xCreate ** methods of the FTS3 virtual table. ** |
Changes to src/sqlite3.h.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.7.0"
#define SQLITE_VERSION_NUMBER 3007000
#define SQLITE_SOURCE_ID "2010-06-26 20:25:31 f149b498b6ada3fc9f71ee104c351554c80c7f8a"
/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
|
| |
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.7.0"
#define SQLITE_VERSION_NUMBER 3007000
#define SQLITE_SOURCE_ID "2010-07-03 13:59:01 3b20ad03be55613d922d81aec5313327bf4098b9"
/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
|
Changes to src/sync.c.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 .. 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 ... 104 105 106 107 108 109 110 111 112 113 114 115 116 117 ... 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 ... 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
** autosync. This will be a pull if the argument is true or a push ** if the argument is false. */ void autosync(int flags){ const char *zUrl; const char *zAutosync; const char *zPw; if( g.fNoSync ){ return; } zAutosync = db_get("autosync", 0); if( zAutosync ){ if( (flags & AUTOSYNC_PUSH)!=0 && memcmp(zAutosync,"pull",4)==0 ){ return; /* Do not auto-push when autosync=pullonly */ ................................................................................ if( zUrl==0 ){ return; /* No default server */ } zPw = db_get("last-sync-pw", 0); url_parse(zUrl); if( g.urlUser!=0 && g.urlPasswd==0 ){ g.urlPasswd = mprintf("%s", zPw); } printf("Autosync: %s\n", g.urlCanonical); url_enable_proxy("via proxy: "); client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, 0, 0); } /* ** This routine processes the command-line argument for push, pull, ** and sync. If a command-line argument is given, that is the URL ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ void process_sync_args(void){ const char *zUrl = 0; const char *zPw = 0; int urlOptional = find_option("autourl",0,0)!=0; g.dontKeepUrl = find_option("once",0,0)!=0; url_proxy_options(); db_find_and_open_repository(1); db_open_config(0); if( g.argc==2 ){ zUrl = db_get("last-sync-url", 0); zPw = db_get("last-sync-pw", 0); }else if( g.argc==3 ){ zUrl = g.argv[2]; } if( zUrl==0 ){ if( urlOptional ) exit(0); usage("URL"); } ................................................................................ } } user_select(); if( g.argc==2 ){ printf("Server: %s\n", g.urlCanonical); } url_enable_proxy("via proxy: "); } /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?options? ** ................................................................................ ** subsequent push, pull, and sync operations. However, the "--once" ** command-line option makes the URL a one-time-use URL that is not ** saved. ** ** See also: clone, push, sync, remote-url */ void pull_cmd(void){ process_sync_args(); client_sync(0,1,0,0,0); } /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ................................................................................ ** subsequent push, pull, and sync operations. However, the "--once" ** command-line option makes the URL a one-time-use URL that is not ** saved. ** ** See also: clone, push, pull, remote-url */ void sync_cmd(void){ process_sync_args(); client_sync(1,1,0,0,0); } /* ** COMMAND: remote-url ** ** Usage: %fossil remote-url ?URL|off? ** |
> > > > > > > > > > > | | > > > | | | | |
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 .. 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 ... 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 ... 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 ... 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
** autosync. This will be a pull if the argument is true or a push ** if the argument is false. */ void autosync(int flags){ const char *zUrl; const char *zAutosync; const char *zPw; int configSync = 0; /* configuration changes transferred */ if( g.fNoSync ){ return; } zAutosync = db_get("autosync", 0); if( zAutosync ){ if( (flags & AUTOSYNC_PUSH)!=0 && memcmp(zAutosync,"pull",4)==0 ){ return; /* Do not auto-push when autosync=pullonly */ ................................................................................ if( zUrl==0 ){ return; /* No default server */ } zPw = db_get("last-sync-pw", 0); url_parse(zUrl); if( g.urlUser!=0 && g.urlPasswd==0 ){ g.urlPasswd = mprintf("%s", zPw); } if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){ /* When doing an automatic pull, also automatically pull shuns from ** the server if pull_shuns is enabled. ** ** TODO: What happens if the shun list gets really big? ** Maybe the shunning list should only be pulled on every 10th ** autosync, or something? */ configSync = CONFIGSET_SHUN; } printf("Autosync: %s\n", g.urlCanonical); url_enable_proxy("via proxy: "); client_sync((flags & AUTOSYNC_PUSH)!=0, 1, 0, configSync, 0); } /* ** This routine processes the command-line argument for push, pull, ** and sync. If a command-line argument is given, that is the URL ** of a server to sync against. If no argument is given, use the ** most recently synced URL. Remember the current URL for next time. */ static int process_sync_args(void){ const char *zUrl = 0; const char *zPw = 0; int configSync = 0; int urlOptional = find_option("autourl",0,0)!=0; g.dontKeepUrl = find_option("once",0,0)!=0; url_proxy_options(); db_find_and_open_repository(1); db_open_config(0); if( g.argc==2 ){ zUrl = db_get("last-sync-url", 0); zPw = db_get("last-sync-pw", 0); if( db_get_boolean("auto-sync",1) ) configSync = CONFIGSET_SHUN; }else if( g.argc==3 ){ zUrl = g.argv[2]; } if( zUrl==0 ){ if( urlOptional ) exit(0); usage("URL"); } ................................................................................ } } user_select(); if( g.argc==2 ){ printf("Server: %s\n", g.urlCanonical); } url_enable_proxy("via proxy: "); return configSync; } /* ** COMMAND: pull ** ** Usage: %fossil pull ?URL? ?options? ** ................................................................................ ** subsequent push, pull, and sync operations. However, the "--once" ** command-line option makes the URL a one-time-use URL that is not ** saved. ** ** See also: clone, push, sync, remote-url */ void pull_cmd(void){ int syncFlags = process_sync_args(); client_sync(0,1,0,syncFlags,0); } /* ** COMMAND: push ** ** Usage: %fossil push ?URL? ?options? ** ................................................................................ ** subsequent push, pull, and sync operations. However, the "--once" ** command-line option makes the URL a one-time-use URL that is not ** saved. ** ** See also: clone, push, pull, remote-url */ void sync_cmd(void){ int syncFlags = process_sync_args(); client_sync(1,1,0,syncFlags,0); } /* ** COMMAND: remote-url ** ** Usage: %fossil remote-url ?URL|off? ** |