| | @@ -363,11 +363,11 @@ |
| 363 | 363 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 364 | 364 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 365 | 365 | */ |
| 366 | 366 | #define SQLITE_VERSION "3.13.0" |
| 367 | 367 | #define SQLITE_VERSION_NUMBER 3013000 |
| 368 | | -#define SQLITE_SOURCE_ID "2016-05-09 19:03:42 14e53d0e2f62d82ae1d64a72fd9711548e3bf5ea" |
| 368 | +#define SQLITE_SOURCE_ID "2016-05-18 10:57:30 fc49f556e48970561d7ab6a2f24fdd7d9eb81ff2" |
| 369 | 369 | |
| 370 | 370 | /* |
| 371 | 371 | ** CAPI3REF: Run-Time Library Version Numbers |
| 372 | 372 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 373 | 373 | ** |
| | @@ -10917,11 +10917,11 @@ |
| 10917 | 10917 | ** |
| 10918 | 10918 | ** When doing coverage testing ALWAYS and NEVER are hard-coded to |
| 10919 | 10919 | ** be true and false so that the unreachable code they specify will |
| 10920 | 10920 | ** not be counted as untested code. |
| 10921 | 10921 | */ |
| 10922 | | -#if defined(SQLITE_COVERAGE_TEST) |
| 10922 | +#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) |
| 10923 | 10923 | # define ALWAYS(X) (1) |
| 10924 | 10924 | # define NEVER(X) (0) |
| 10925 | 10925 | #elif !defined(NDEBUG) |
| 10926 | 10926 | # define ALWAYS(X) ((X)?1:(assert(0),0)) |
| 10927 | 10927 | # define NEVER(X) ((X)?(assert(0),1):0) |
| | @@ -12954,11 +12954,11 @@ |
| 12954 | 12954 | */ |
| 12955 | 12955 | struct PgHdr { |
| 12956 | 12956 | sqlite3_pcache_page *pPage; /* Pcache object page handle */ |
| 12957 | 12957 | void *pData; /* Page data */ |
| 12958 | 12958 | void *pExtra; /* Extra content */ |
| 12959 | | - PgHdr *pDirty; /* Transient list of dirty pages */ |
| 12959 | + PgHdr *pDirty; /* Transient list of dirty sorted by pgno */ |
| 12960 | 12960 | Pager *pPager; /* The pager this page is part of */ |
| 12961 | 12961 | Pgno pgno; /* Page number for this page */ |
| 12962 | 12962 | #ifdef SQLITE_CHECK_PAGES |
| 12963 | 12963 | u32 pageHash; /* Hash of page content */ |
| 12964 | 12964 | #endif |
| | @@ -12979,15 +12979,14 @@ |
| 12979 | 12979 | #define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */ |
| 12980 | 12980 | #define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */ |
| 12981 | 12981 | #define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */ |
| 12982 | 12982 | #define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before |
| 12983 | 12983 | ** writing this page to the database */ |
| 12984 | | -#define PGHDR_NEED_READ 0x010 /* Content is unread */ |
| 12985 | | -#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ |
| 12986 | | -#define PGHDR_MMAP 0x040 /* This is an mmap page object */ |
| 12984 | +#define PGHDR_DONT_WRITE 0x010 /* Do not write content to disk */ |
| 12985 | +#define PGHDR_MMAP 0x020 /* This is an mmap page object */ |
| 12987 | 12986 | |
| 12988 | | -#define PGHDR_WAL_APPEND 0x080 /* Appended to wal file */ |
| 12987 | +#define PGHDR_WAL_APPEND 0x040 /* Appended to wal file */ |
| 12989 | 12988 | |
| 12990 | 12989 | /* Initialize and shutdown the page cache subsystem */ |
| 12991 | 12990 | SQLITE_PRIVATE int sqlite3PcacheInitialize(void); |
| 12992 | 12991 | SQLITE_PRIVATE void sqlite3PcacheShutdown(void); |
| 12993 | 12992 | |
| | @@ -13065,10 +13064,15 @@ |
| 13065 | 13064 | ** interface is only available if SQLITE_CHECK_PAGES is defined when the |
| 13066 | 13065 | ** library is built. |
| 13067 | 13066 | */ |
| 13068 | 13067 | SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); |
| 13069 | 13068 | #endif |
| 13069 | + |
| 13070 | +#if defined(SQLITE_DEBUG) |
| 13071 | +/* Check invariants on a PgHdr object */ |
| 13072 | +SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr*); |
| 13073 | +#endif |
| 13070 | 13074 | |
| 13071 | 13075 | /* Set and get the suggested cache-size for the specified pager-cache. |
| 13072 | 13076 | ** |
| 13073 | 13077 | ** If no global maximum is configured, then the system attempts to limit |
| 13074 | 13078 | ** the total number of pages cached by purgeable pager-caches to the sum |
| | @@ -43115,11 +43119,33 @@ |
| 43115 | 43119 | ** This file implements that page cache. |
| 43116 | 43120 | */ |
| 43117 | 43121 | /* #include "sqliteInt.h" */ |
| 43118 | 43122 | |
| 43119 | 43123 | /* |
| 43120 | | -** A complete page cache is an instance of this structure. |
| 43124 | +** A complete page cache is an instance of this structure. Every |
| 43125 | +** entry in the cache holds a single page of the database file. The |
| 43126 | +** btree layer only operates on the cached copy of the database pages. |
| 43127 | +** |
| 43128 | +** A page cache entry is "clean" if it exactly matches what is currently |
| 43129 | +** on disk. A page is "dirty" if it has been modified and needs to be |
| 43130 | +** persisted to disk. |
| 43131 | +** |
| 43132 | +** pDirty, pDirtyTail, pSynced: |
| 43133 | +** All dirty pages are linked into the doubly linked list using |
| 43134 | +** PgHdr.pDirtyNext and pDirtyPrev. The list is maintained in LRU order |
| 43135 | +** such that p was added to the list more recently than p->pDirtyNext. |
| 43136 | +** PCache.pDirty points to the first (newest) element in the list and |
| 43137 | +** pDirtyTail to the last (oldest). |
| 43138 | +** |
| 43139 | +** The PCache.pSynced variable is used to optimize searching for a dirty |
| 43140 | +** page to eject from the cache mid-transaction. It is better to eject |
| 43141 | +** a page that does not require a journal sync than one that does. |
| 43142 | +** Therefore, pSynced is maintained to that it *almost* always points |
| 43143 | +** to either the oldest page in the pDirty/pDirtyTail list that has a |
| 43144 | +** clear PGHDR_NEED_SYNC flag or to a page that is older than this one |
| 43145 | +** (so that the right page to eject can be found by following pDirtyPrev |
| 43146 | +** pointers). |
| 43121 | 43147 | */ |
| 43122 | 43148 | struct PCache { |
| 43123 | 43149 | PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ |
| 43124 | 43150 | PgHdr *pSynced; /* Last synced page in dirty page list */ |
| 43125 | 43151 | int nRefSum; /* Sum of ref counts over all pages */ |
| | @@ -43131,10 +43157,99 @@ |
| 43131 | 43157 | u8 eCreate; /* eCreate value for for xFetch() */ |
| 43132 | 43158 | int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ |
| 43133 | 43159 | void *pStress; /* Argument to xStress */ |
| 43134 | 43160 | sqlite3_pcache *pCache; /* Pluggable cache module */ |
| 43135 | 43161 | }; |
| 43162 | + |
| 43163 | +/********************************** Test and Debug Logic **********************/ |
| 43164 | +/* |
| 43165 | +** Debug tracing macros. Enable by by changing the "0" to "1" and |
| 43166 | +** recompiling. |
| 43167 | +** |
| 43168 | +** When sqlite3PcacheTrace is 1, single line trace messages are issued. |
| 43169 | +** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries |
| 43170 | +** is displayed for many operations, resulting in a lot of output. |
| 43171 | +*/ |
| 43172 | +#if defined(SQLITE_DEBUG) && 0 |
| 43173 | + int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */ |
| 43174 | + int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */ |
| 43175 | +# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;} |
| 43176 | + void pcacheDump(PCache *pCache){ |
| 43177 | + int N; |
| 43178 | + int i, j; |
| 43179 | + sqlite3_pcache_page *pLower; |
| 43180 | + PgHdr *pPg; |
| 43181 | + unsigned char *a; |
| 43182 | + |
| 43183 | + if( sqlite3PcacheTrace<2 ) return; |
| 43184 | + if( pCache->pCache==0 ) return; |
| 43185 | + N = sqlite3PcachePagecount(pCache); |
| 43186 | + if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; |
| 43187 | + for(i=1; i<=N; i++){ |
| 43188 | + pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); |
| 43189 | + if( pLower==0 ) continue; |
| 43190 | + pPg = (PgHdr*)pLower->pExtra; |
| 43191 | + printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags); |
| 43192 | + a = (unsigned char *)pLower->pBuf; |
| 43193 | + for(j=0; j<12; j++) printf("%02x", a[j]); |
| 43194 | + printf("\n"); |
| 43195 | + if( pPg->pPage==0 ){ |
| 43196 | + sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); |
| 43197 | + } |
| 43198 | + } |
| 43199 | + } |
| 43200 | + #else |
| 43201 | +# define pcacheTrace(X) |
| 43202 | +# define pcacheDump(X) |
| 43203 | +#endif |
| 43204 | + |
| 43205 | +/* |
| 43206 | +** Check invariants on a PgHdr entry. Return true if everything is OK. |
| 43207 | +** Return false if any invariant is violated. |
| 43208 | +** |
| 43209 | +** This routine is for use inside of assert() statements only. For |
| 43210 | +** example: |
| 43211 | +** |
| 43212 | +** assert( sqlite3PcachePageSanity(pPg) ); |
| 43213 | +*/ |
| 43214 | +#if SQLITE_DEBUG |
| 43215 | +SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){ |
| 43216 | + PCache *pCache; |
| 43217 | + assert( pPg!=0 ); |
| 43218 | + assert( pPg->pgno>0 ); /* Page number is 1 or more */ |
| 43219 | + pCache = pPg->pCache; |
| 43220 | + assert( pCache!=0 ); /* Every page has an associated PCache */ |
| 43221 | + if( pPg->flags & PGHDR_CLEAN ){ |
| 43222 | + assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */ |
| 43223 | + assert( pCache->pDirty!=pPg ); /* CLEAN pages not on dirty list */ |
| 43224 | + assert( pCache->pDirtyTail!=pPg ); |
| 43225 | + } |
| 43226 | + /* WRITEABLE pages must also be DIRTY */ |
| 43227 | + if( pPg->flags & PGHDR_WRITEABLE ){ |
| 43228 | + assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */ |
| 43229 | + } |
| 43230 | + /* NEED_SYNC can be set independently of WRITEABLE. This can happen, |
| 43231 | + ** for example, when using the sqlite3PagerDontWrite() optimization: |
| 43232 | + ** (1) Page X is journalled, and gets WRITEABLE and NEED_SEEK. |
| 43233 | + ** (2) Page X moved to freelist, WRITEABLE is cleared |
| 43234 | + ** (3) Page X reused, WRITEABLE is set again |
| 43235 | + ** If NEED_SYNC had been cleared in step 2, then it would not be reset |
| 43236 | + ** in step 3, and page might be written into the database without first |
| 43237 | + ** syncing the rollback journal, which might cause corruption on a power |
| 43238 | + ** loss. |
| 43239 | + ** |
| 43240 | + ** Another example is when the database page size is smaller than the |
| 43241 | + ** disk sector size. When any page of a sector is journalled, all pages |
| 43242 | + ** in that sector are marked NEED_SYNC even if they are still CLEAN, just |
| 43243 | + ** in case they are later modified, since all pages in the same sector |
| 43244 | + ** must be journalled and synced before any of those pages can be safely |
| 43245 | + ** written. |
| 43246 | + */ |
| 43247 | + return 1; |
| 43248 | +} |
| 43249 | +#endif /* SQLITE_DEBUG */ |
| 43250 | + |
| 43136 | 43251 | |
| 43137 | 43252 | /********************************** Linked List Management ********************/ |
| 43138 | 43253 | |
| 43139 | 43254 | /* Allowed values for second argument to pcacheManageDirtyList() */ |
| 43140 | 43255 | #define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */ |
| | @@ -43148,21 +43263,20 @@ |
| 43148 | 43263 | ** the dirty list. Doing both moves pPage to the front of the dirty list. |
| 43149 | 43264 | */ |
| 43150 | 43265 | static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){ |
| 43151 | 43266 | PCache *p = pPage->pCache; |
| 43152 | 43267 | |
| 43268 | + pcacheTrace(("%p.DIRTYLIST.%s %d\n", p, |
| 43269 | + addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT", |
| 43270 | + pPage->pgno)); |
| 43153 | 43271 | if( addRemove & PCACHE_DIRTYLIST_REMOVE ){ |
| 43154 | 43272 | assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); |
| 43155 | 43273 | assert( pPage->pDirtyPrev || pPage==p->pDirty ); |
| 43156 | 43274 | |
| 43157 | 43275 | /* Update the PCache1.pSynced variable if necessary. */ |
| 43158 | 43276 | if( p->pSynced==pPage ){ |
| 43159 | | - PgHdr *pSynced = pPage->pDirtyPrev; |
| 43160 | | - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ |
| 43161 | | - pSynced = pSynced->pDirtyPrev; |
| 43162 | | - } |
| 43163 | | - p->pSynced = pSynced; |
| 43277 | + p->pSynced = pPage->pDirtyPrev; |
| 43164 | 43278 | } |
| 43165 | 43279 | |
| 43166 | 43280 | if( pPage->pDirtyNext ){ |
| 43167 | 43281 | pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; |
| 43168 | 43282 | }else{ |
| | @@ -43170,14 +43284,19 @@ |
| 43170 | 43284 | p->pDirtyTail = pPage->pDirtyPrev; |
| 43171 | 43285 | } |
| 43172 | 43286 | if( pPage->pDirtyPrev ){ |
| 43173 | 43287 | pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; |
| 43174 | 43288 | }else{ |
| 43289 | + /* If there are now no dirty pages in the cache, set eCreate to 2. |
| 43290 | + ** This is an optimization that allows sqlite3PcacheFetch() to skip |
| 43291 | + ** searching for a dirty page to eject from the cache when it might |
| 43292 | + ** otherwise have to. */ |
| 43175 | 43293 | assert( pPage==p->pDirty ); |
| 43176 | 43294 | p->pDirty = pPage->pDirtyNext; |
| 43177 | | - if( p->pDirty==0 && p->bPurgeable ){ |
| 43178 | | - assert( p->eCreate==1 ); |
| 43295 | + assert( p->bPurgeable || p->eCreate==2 ); |
| 43296 | + if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/ |
| 43297 | + assert( p->bPurgeable==0 || p->eCreate==1 ); |
| 43179 | 43298 | p->eCreate = 2; |
| 43180 | 43299 | } |
| 43181 | 43300 | } |
| 43182 | 43301 | pPage->pDirtyNext = 0; |
| 43183 | 43302 | pPage->pDirtyPrev = 0; |
| | @@ -43195,23 +43314,34 @@ |
| 43195 | 43314 | assert( p->eCreate==2 ); |
| 43196 | 43315 | p->eCreate = 1; |
| 43197 | 43316 | } |
| 43198 | 43317 | } |
| 43199 | 43318 | p->pDirty = pPage; |
| 43200 | | - if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ |
| 43319 | + |
| 43320 | + /* If pSynced is NULL and this page has a clear NEED_SYNC flag, set |
| 43321 | + ** pSynced to point to it. Checking the NEED_SYNC flag is an |
| 43322 | + ** optimization, as if pSynced points to a page with the NEED_SYNC |
| 43323 | + ** flag set sqlite3PcacheFetchStress() searches through all newer |
| 43324 | + ** entries of the dirty-list for a page with NEED_SYNC clear anyway. */ |
| 43325 | + if( !p->pSynced |
| 43326 | + && 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/ |
| 43327 | + ){ |
| 43201 | 43328 | p->pSynced = pPage; |
| 43202 | 43329 | } |
| 43203 | 43330 | } |
| 43331 | + pcacheDump(p); |
| 43204 | 43332 | } |
| 43205 | 43333 | |
| 43206 | 43334 | /* |
| 43207 | 43335 | ** Wrapper around the pluggable caches xUnpin method. If the cache is |
| 43208 | 43336 | ** being used for an in-memory database, this function is a no-op. |
| 43209 | 43337 | */ |
| 43210 | 43338 | static void pcacheUnpin(PgHdr *p){ |
| 43211 | 43339 | if( p->pCache->bPurgeable ){ |
| 43340 | + pcacheTrace(("%p.UNPIN %d\n", p->pCache, p->pgno)); |
| 43212 | 43341 | sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0); |
| 43342 | + pcacheDump(p->pCache); |
| 43213 | 43343 | } |
| 43214 | 43344 | } |
| 43215 | 43345 | |
| 43216 | 43346 | /* |
| 43217 | 43347 | ** Compute the number of pages of cache requested. p->szCache is the |
| | @@ -43277,10 +43407,11 @@ |
| 43277 | 43407 | p->eCreate = 2; |
| 43278 | 43408 | p->xStress = xStress; |
| 43279 | 43409 | p->pStress = pStress; |
| 43280 | 43410 | p->szCache = 100; |
| 43281 | 43411 | p->szSpill = 1; |
| 43412 | + pcacheTrace(("%p.OPEN szPage %d bPurgeable %d\n",p,szPage,bPurgeable)); |
| 43282 | 43413 | return sqlite3PcacheSetPageSize(p, szPage); |
| 43283 | 43414 | } |
| 43284 | 43415 | |
| 43285 | 43416 | /* |
| 43286 | 43417 | ** Change the page size for PCache object. The caller must ensure that there |
| | @@ -43299,10 +43430,11 @@ |
| 43299 | 43430 | if( pCache->pCache ){ |
| 43300 | 43431 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| 43301 | 43432 | } |
| 43302 | 43433 | pCache->pCache = pNew; |
| 43303 | 43434 | pCache->szPage = szPage; |
| 43435 | + pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage)); |
| 43304 | 43436 | } |
| 43305 | 43437 | return SQLITE_OK; |
| 43306 | 43438 | } |
| 43307 | 43439 | |
| 43308 | 43440 | /* |
| | @@ -43333,15 +43465,17 @@ |
| 43333 | 43465 | PCache *pCache, /* Obtain the page from this cache */ |
| 43334 | 43466 | Pgno pgno, /* Page number to obtain */ |
| 43335 | 43467 | int createFlag /* If true, create page if it does not exist already */ |
| 43336 | 43468 | ){ |
| 43337 | 43469 | int eCreate; |
| 43470 | + sqlite3_pcache_page *pRes; |
| 43338 | 43471 | |
| 43339 | 43472 | assert( pCache!=0 ); |
| 43340 | 43473 | assert( pCache->pCache!=0 ); |
| 43341 | 43474 | assert( createFlag==3 || createFlag==0 ); |
| 43342 | 43475 | assert( pgno>0 ); |
| 43476 | + assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) ); |
| 43343 | 43477 | |
| 43344 | 43478 | /* eCreate defines what to do if the page does not exist. |
| 43345 | 43479 | ** 0 Do not allocate a new page. (createFlag==0) |
| 43346 | 43480 | ** 1 Allocate a new page if doing so is inexpensive. |
| 43347 | 43481 | ** (createFlag==1 AND bPurgeable AND pDirty) |
| | @@ -43350,11 +43484,14 @@ |
| 43350 | 43484 | */ |
| 43351 | 43485 | eCreate = createFlag & pCache->eCreate; |
| 43352 | 43486 | assert( eCreate==0 || eCreate==1 || eCreate==2 ); |
| 43353 | 43487 | assert( createFlag==0 || pCache->eCreate==eCreate ); |
| 43354 | 43488 | assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) ); |
| 43355 | | - return sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); |
| 43489 | + pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate); |
| 43490 | + pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno, |
| 43491 | + createFlag?" create":"",pRes)); |
| 43492 | + return pRes; |
| 43356 | 43493 | } |
| 43357 | 43494 | |
| 43358 | 43495 | /* |
| 43359 | 43496 | ** If the sqlite3PcacheFetch() routine is unable to allocate a new |
| 43360 | 43497 | ** page because no clean pages are available for reuse and the cache |
| | @@ -43377,11 +43514,15 @@ |
| 43377 | 43514 | if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){ |
| 43378 | 43515 | /* Find a dirty page to write-out and recycle. First try to find a |
| 43379 | 43516 | ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC |
| 43380 | 43517 | ** cleared), but if that is not possible settle for any other |
| 43381 | 43518 | ** unreferenced dirty page. |
| 43382 | | - */ |
| 43519 | + ** |
| 43520 | + ** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC |
| 43521 | + ** flag is currently referenced, then the following may leave pSynced |
| 43522 | + ** set incorrectly (pointing to other than the LRU page with NEED_SYNC |
| 43523 | + ** cleared). This is Ok, as pSynced is just an optimization. */ |
| 43383 | 43524 | for(pPg=pCache->pSynced; |
| 43384 | 43525 | pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); |
| 43385 | 43526 | pPg=pPg->pDirtyPrev |
| 43386 | 43527 | ); |
| 43387 | 43528 | pCache->pSynced = pPg; |
| | @@ -43395,11 +43536,13 @@ |
| 43395 | 43536 | "spill page %d making room for %d - cache used: %d/%d", |
| 43396 | 43537 | pPg->pgno, pgno, |
| 43397 | 43538 | sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), |
| 43398 | 43539 | numberOfCachePages(pCache)); |
| 43399 | 43540 | #endif |
| 43541 | + pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); |
| 43400 | 43542 | rc = pCache->xStress(pCache->pStress, pPg); |
| 43543 | + pcacheDump(pCache); |
| 43401 | 43544 | if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ |
| 43402 | 43545 | return rc; |
| 43403 | 43546 | } |
| 43404 | 43547 | } |
| 43405 | 43548 | } |
| | @@ -43455,10 +43598,11 @@ |
| 43455 | 43598 | if( !pPgHdr->pPage ){ |
| 43456 | 43599 | return pcacheFetchFinishWithInit(pCache, pgno, pPage); |
| 43457 | 43600 | } |
| 43458 | 43601 | pCache->nRefSum++; |
| 43459 | 43602 | pPgHdr->nRef++; |
| 43603 | + assert( sqlite3PcachePageSanity(pPgHdr) ); |
| 43460 | 43604 | return pPgHdr; |
| 43461 | 43605 | } |
| 43462 | 43606 | |
| 43463 | 43607 | /* |
| 43464 | 43608 | ** Decrement the reference count on a page. If the page is clean and the |
| | @@ -43468,12 +43612,15 @@ |
| 43468 | 43612 | assert( p->nRef>0 ); |
| 43469 | 43613 | p->pCache->nRefSum--; |
| 43470 | 43614 | if( (--p->nRef)==0 ){ |
| 43471 | 43615 | if( p->flags&PGHDR_CLEAN ){ |
| 43472 | 43616 | pcacheUnpin(p); |
| 43473 | | - }else if( p->pDirtyPrev!=0 ){ |
| 43474 | | - /* Move the page to the head of the dirty list. */ |
| 43617 | + }else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/ |
| 43618 | + /* Move the page to the head of the dirty list. If p->pDirtyPrev==0, |
| 43619 | + ** then page p is already at the head of the dirty list and the |
| 43620 | + ** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE |
| 43621 | + ** tag above. */ |
| 43475 | 43622 | pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); |
| 43476 | 43623 | } |
| 43477 | 43624 | } |
| 43478 | 43625 | } |
| 43479 | 43626 | |
| | @@ -43480,10 +43627,11 @@ |
| 43480 | 43627 | /* |
| 43481 | 43628 | ** Increase the reference count of a supplied page by 1. |
| 43482 | 43629 | */ |
| 43483 | 43630 | SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ |
| 43484 | 43631 | assert(p->nRef>0); |
| 43632 | + assert( sqlite3PcachePageSanity(p) ); |
| 43485 | 43633 | p->nRef++; |
| 43486 | 43634 | p->pCache->nRefSum++; |
| 43487 | 43635 | } |
| 43488 | 43636 | |
| 43489 | 43637 | /* |
| | @@ -43491,10 +43639,11 @@ |
| 43491 | 43639 | ** page. This function deletes that reference, so after it returns the |
| 43492 | 43640 | ** page pointed to by p is invalid. |
| 43493 | 43641 | */ |
| 43494 | 43642 | SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ |
| 43495 | 43643 | assert( p->nRef==1 ); |
| 43644 | + assert( sqlite3PcachePageSanity(p) ); |
| 43496 | 43645 | if( p->flags&PGHDR_DIRTY ){ |
| 43497 | 43646 | pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); |
| 43498 | 43647 | } |
| 43499 | 43648 | p->pCache->nRefSum--; |
| 43500 | 43649 | sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1); |
| | @@ -43504,30 +43653,36 @@ |
| 43504 | 43653 | ** Make sure the page is marked as dirty. If it isn't dirty already, |
| 43505 | 43654 | ** make it so. |
| 43506 | 43655 | */ |
| 43507 | 43656 | SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){ |
| 43508 | 43657 | assert( p->nRef>0 ); |
| 43509 | | - if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ |
| 43658 | + assert( sqlite3PcachePageSanity(p) ); |
| 43659 | + if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/ |
| 43510 | 43660 | p->flags &= ~PGHDR_DONT_WRITE; |
| 43511 | 43661 | if( p->flags & PGHDR_CLEAN ){ |
| 43512 | 43662 | p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN); |
| 43663 | + pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno)); |
| 43513 | 43664 | assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY ); |
| 43514 | 43665 | pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD); |
| 43515 | 43666 | } |
| 43667 | + assert( sqlite3PcachePageSanity(p) ); |
| 43516 | 43668 | } |
| 43517 | 43669 | } |
| 43518 | 43670 | |
| 43519 | 43671 | /* |
| 43520 | 43672 | ** Make sure the page is marked as clean. If it isn't clean already, |
| 43521 | 43673 | ** make it so. |
| 43522 | 43674 | */ |
| 43523 | 43675 | SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ |
| 43524 | | - if( (p->flags & PGHDR_DIRTY) ){ |
| 43676 | + assert( sqlite3PcachePageSanity(p) ); |
| 43677 | + if( ALWAYS((p->flags & PGHDR_DIRTY)!=0) ){ |
| 43525 | 43678 | assert( (p->flags & PGHDR_CLEAN)==0 ); |
| 43526 | 43679 | pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE); |
| 43527 | 43680 | p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE); |
| 43528 | 43681 | p->flags |= PGHDR_CLEAN; |
| 43682 | + pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno)); |
| 43683 | + assert( sqlite3PcachePageSanity(p) ); |
| 43529 | 43684 | if( p->nRef==0 ){ |
| 43530 | 43685 | pcacheUnpin(p); |
| 43531 | 43686 | } |
| 43532 | 43687 | } |
| 43533 | 43688 | } |
| | @@ -43535,10 +43690,11 @@ |
| 43535 | 43690 | /* |
| 43536 | 43691 | ** Make every page in the cache clean. |
| 43537 | 43692 | */ |
| 43538 | 43693 | SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){ |
| 43539 | 43694 | PgHdr *p; |
| 43695 | + pcacheTrace(("%p.CLEAN-ALL\n",pCache)); |
| 43540 | 43696 | while( (p = pCache->pDirty)!=0 ){ |
| 43541 | 43697 | sqlite3PcacheMakeClean(p); |
| 43542 | 43698 | } |
| 43543 | 43699 | } |
| 43544 | 43700 | |
| | @@ -43545,10 +43701,11 @@ |
| 43545 | 43701 | /* |
| 43546 | 43702 | ** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages. |
| 43547 | 43703 | */ |
| 43548 | 43704 | SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache *pCache){ |
| 43549 | 43705 | PgHdr *p; |
| 43706 | + pcacheTrace(("%p.CLEAR-WRITEABLE\n",pCache)); |
| 43550 | 43707 | for(p=pCache->pDirty; p; p=p->pDirtyNext){ |
| 43551 | 43708 | p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE); |
| 43552 | 43709 | } |
| 43553 | 43710 | pCache->pSynced = pCache->pDirtyTail; |
| 43554 | 43711 | } |
| | @@ -43569,10 +43726,12 @@ |
| 43569 | 43726 | */ |
| 43570 | 43727 | SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ |
| 43571 | 43728 | PCache *pCache = p->pCache; |
| 43572 | 43729 | assert( p->nRef>0 ); |
| 43573 | 43730 | assert( newPgno>0 ); |
| 43731 | + assert( sqlite3PcachePageSanity(p) ); |
| 43732 | + pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno)); |
| 43574 | 43733 | sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); |
| 43575 | 43734 | p->pgno = newPgno; |
| 43576 | 43735 | if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ |
| 43577 | 43736 | pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); |
| 43578 | 43737 | } |
| | @@ -43589,10 +43748,11 @@ |
| 43589 | 43748 | */ |
| 43590 | 43749 | SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){ |
| 43591 | 43750 | if( pCache->pCache ){ |
| 43592 | 43751 | PgHdr *p; |
| 43593 | 43752 | PgHdr *pNext; |
| 43753 | + pcacheTrace(("%p.TRUNCATE %d\n",pCache,pgno)); |
| 43594 | 43754 | for(p=pCache->pDirty; p; p=pNext){ |
| 43595 | 43755 | pNext = p->pDirtyNext; |
| 43596 | 43756 | /* This routine never gets call with a positive pgno except right |
| 43597 | 43757 | ** after sqlite3PcacheCleanAll(). So if there are dirty pages, |
| 43598 | 43758 | ** it must be that pgno==0. |
| | @@ -43619,10 +43779,11 @@ |
| 43619 | 43779 | /* |
| 43620 | 43780 | ** Close a cache. |
| 43621 | 43781 | */ |
| 43622 | 43782 | SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ |
| 43623 | 43783 | assert( pCache->pCache!=0 ); |
| 43784 | + pcacheTrace(("%p.CLOSE\n",pCache)); |
| 43624 | 43785 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| 43625 | 43786 | } |
| 43626 | 43787 | |
| 43627 | 43788 | /* |
| 43628 | 43789 | ** Discard the contents of the cache. |
| | @@ -47585,24 +47746,28 @@ |
| 47585 | 47746 | } |
| 47586 | 47747 | |
| 47587 | 47748 | static int pager_truncate(Pager *pPager, Pgno nPage); |
| 47588 | 47749 | |
| 47589 | 47750 | /* |
| 47590 | | -** The write transaction open on the pager passed as the only argument is |
| 47591 | | -** being committed. This function returns true if all dirty pages should |
| 47592 | | -** be flushed to disk, or false otherwise. Pages should be flushed to disk |
| 47593 | | -** unless one of the following is true: |
| 47594 | | -** |
| 47595 | | -** * The db is an in-memory database. |
| 47596 | | -** |
| 47597 | | -** * The db is a temporary database and the db file has not been opened. |
| 47598 | | -** |
| 47599 | | -** * The db is a temporary database and the cache contains less than |
| 47600 | | -** C/4 dirty pages, where C is the configured cache-size. |
| 47601 | | -*/ |
| 47602 | | -static int pagerFlushOnCommit(Pager *pPager){ |
| 47751 | +** The write transaction open on pPager is being committed (bCommit==1) |
| 47752 | +** or rolled back (bCommit==0). |
| 47753 | +** |
| 47754 | +** Return TRUE if and only if all dirty pages should be flushed to disk. |
| 47755 | +** |
| 47756 | +** Rules: |
| 47757 | +** |
| 47758 | +** * For non-TEMP databases, always sync to disk. This is necessary |
| 47759 | +** for transactions to be durable. |
| 47760 | +** |
| 47761 | +** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing |
| 47762 | +** file has been created already (via a spill on pagerStress()) and |
| 47763 | +** when the number of dirty pages in memory exceeds 25% of the total |
| 47764 | +** cache size. |
| 47765 | +*/ |
| 47766 | +static int pagerFlushOnCommit(Pager *pPager, int bCommit){ |
| 47603 | 47767 | if( pPager->tempFile==0 ) return 1; |
| 47768 | + if( !bCommit ) return 0; |
| 47604 | 47769 | if( !isOpen(pPager->fd) ) return 0; |
| 47605 | 47770 | return (sqlite3PCachePercentDirty(pPager->pPCache)>=25); |
| 47606 | 47771 | } |
| 47607 | 47772 | |
| 47608 | 47773 | /* |
| | @@ -47706,11 +47871,11 @@ |
| 47706 | 47871 | } |
| 47707 | 47872 | pPager->journalOff = 0; |
| 47708 | 47873 | }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST |
| 47709 | 47874 | || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL) |
| 47710 | 47875 | ){ |
| 47711 | | - rc = zeroJournalHdr(pPager, hasMaster); |
| 47876 | + rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile); |
| 47712 | 47877 | pPager->journalOff = 0; |
| 47713 | 47878 | }else{ |
| 47714 | 47879 | /* This branch may be executed with Pager.journalMode==MEMORY if |
| 47715 | 47880 | ** a hot-journal was just rolled back. In this case the journal |
| 47716 | 47881 | ** file should be closed and deleted. If this connection writes to |
| | @@ -47741,16 +47906,18 @@ |
| 47741 | 47906 | #endif |
| 47742 | 47907 | |
| 47743 | 47908 | sqlite3BitvecDestroy(pPager->pInJournal); |
| 47744 | 47909 | pPager->pInJournal = 0; |
| 47745 | 47910 | pPager->nRec = 0; |
| 47746 | | - if( MEMDB || pagerFlushOnCommit(pPager) ){ |
| 47747 | | - sqlite3PcacheCleanAll(pPager->pPCache); |
| 47748 | | - }else{ |
| 47749 | | - sqlite3PcacheClearWritable(pPager->pPCache); |
| 47911 | + if( rc==SQLITE_OK ){ |
| 47912 | + if( pagerFlushOnCommit(pPager, bCommit) ){ |
| 47913 | + sqlite3PcacheCleanAll(pPager->pPCache); |
| 47914 | + }else{ |
| 47915 | + sqlite3PcacheClearWritable(pPager->pPCache); |
| 47916 | + } |
| 47917 | + sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); |
| 47750 | 47918 | } |
| 47751 | | - sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize); |
| 47752 | 47919 | |
| 47753 | 47920 | if( pagerUseWal(pPager) ){ |
| 47754 | 47921 | /* Drop the WAL write-lock, if any. Also, if the connection was in |
| 47755 | 47922 | ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE |
| 47756 | 47923 | ** lock held on the database file. |
| | @@ -48080,11 +48247,10 @@ |
| 48080 | 48247 | pPager->doNotSpill |= SPILLFLAG_ROLLBACK; |
| 48081 | 48248 | rc = sqlite3PagerGet(pPager, pgno, &pPg, 1); |
| 48082 | 48249 | assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 ); |
| 48083 | 48250 | pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK; |
| 48084 | 48251 | if( rc!=SQLITE_OK ) return rc; |
| 48085 | | - pPg->flags &= ~PGHDR_NEED_READ; |
| 48086 | 48252 | sqlite3PcacheMakeDirty(pPg); |
| 48087 | 48253 | } |
| 48088 | 48254 | if( pPg ){ |
| 48089 | 48255 | /* No page should ever be explicitly rolled back that is in use, except |
| 48090 | 48256 | ** for page 1 which is held in use in order to keep the lock on the |
| | @@ -48094,37 +48260,14 @@ |
| 48094 | 48260 | */ |
| 48095 | 48261 | void *pData; |
| 48096 | 48262 | pData = pPg->pData; |
| 48097 | 48263 | memcpy(pData, (u8*)aData, pPager->pageSize); |
| 48098 | 48264 | pPager->xReiniter(pPg); |
| 48099 | | - if( isMainJrnl && (!isSavepnt || *pOffset<=pPager->journalHdr) ){ |
| 48100 | | - /* If the contents of this page were just restored from the main |
| 48101 | | - ** journal file, then its content must be as they were when the |
| 48102 | | - ** transaction was first opened. In this case we can mark the page |
| 48103 | | - ** as clean, since there will be no need to write it out to the |
| 48104 | | - ** database. |
| 48105 | | - ** |
| 48106 | | - ** There is one exception to this rule. If the page is being rolled |
| 48107 | | - ** back as part of a savepoint (or statement) rollback from an |
| 48108 | | - ** unsynced portion of the main journal file, then it is not safe |
| 48109 | | - ** to mark the page as clean. This is because marking the page as |
| 48110 | | - ** clean will clear the PGHDR_NEED_SYNC flag. Since the page is |
| 48111 | | - ** already in the journal file (recorded in Pager.pInJournal) and |
| 48112 | | - ** the PGHDR_NEED_SYNC flag is cleared, if the page is written to |
| 48113 | | - ** again within this transaction, it will be marked as dirty but |
| 48114 | | - ** the PGHDR_NEED_SYNC flag will not be set. It could then potentially |
| 48115 | | - ** be written out into the database file before its journal file |
| 48116 | | - ** segment is synced. If a crash occurs during or following this, |
| 48117 | | - ** database corruption may ensue. |
| 48118 | | - ** |
| 48119 | | - ** Update: Another exception is for temp files that are not |
| 48120 | | - ** in-memory databases. In this case the page may have been dirty |
| 48121 | | - ** at the start of the transaction. |
| 48122 | | - */ |
| 48123 | | - assert( !pagerUseWal(pPager) ); |
| 48124 | | - if( pPager->tempFile==0 ) sqlite3PcacheMakeClean(pPg); |
| 48125 | | - } |
| 48265 | + /* It used to be that sqlite3PcacheMakeClean(pPg) was called here. But |
| 48266 | + ** that call was dangerous and had no detectable benefit since the cache |
| 48267 | + ** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so |
| 48268 | + ** has been removed. */ |
| 48126 | 48269 | pager_set_pagehash(pPg); |
| 48127 | 48270 | |
| 48128 | 48271 | /* If this was page 1, then restore the value of Pager.dbFileVers. |
| 48129 | 48272 | ** Do this before any decoding. */ |
| 48130 | 48273 | if( pgno==1 ){ |
| | @@ -51731,10 +51874,11 @@ |
| 51731 | 51874 | if( !pPager->tempFile && (pPg->flags&PGHDR_DIRTY) && pPager->nSavepoint==0 ){ |
| 51732 | 51875 | PAGERTRACE(("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager))); |
| 51733 | 51876 | IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) |
| 51734 | 51877 | pPg->flags |= PGHDR_DONT_WRITE; |
| 51735 | 51878 | pPg->flags &= ~PGHDR_WRITEABLE; |
| 51879 | + testcase( pPg->flags & PGHDR_NEED_SYNC ); |
| 51736 | 51880 | pager_set_pagehash(pPg); |
| 51737 | 51881 | } |
| 51738 | 51882 | } |
| 51739 | 51883 | |
| 51740 | 51884 | /* |
| | @@ -51926,21 +52070,21 @@ |
| 51926 | 52070 | |
| 51927 | 52071 | /* If a prior error occurred, report that error again. */ |
| 51928 | 52072 | if( NEVER(pPager->errCode) ) return pPager->errCode; |
| 51929 | 52073 | |
| 51930 | 52074 | /* Provide the ability to easily simulate an I/O error during testing */ |
| 51931 | | - if( (rc = sqlite3FaultSim(400))!=SQLITE_OK ) return rc; |
| 52075 | + if( sqlite3FaultSim(400) ) return SQLITE_IOERR; |
| 51932 | 52076 | |
| 51933 | 52077 | PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", |
| 51934 | 52078 | pPager->zFilename, zMaster, pPager->dbSize)); |
| 51935 | 52079 | |
| 51936 | 52080 | /* If no database changes have been made, return early. */ |
| 51937 | 52081 | if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK; |
| 51938 | 52082 | |
| 51939 | 52083 | assert( MEMDB==0 || pPager->tempFile ); |
| 51940 | 52084 | assert( isOpen(pPager->fd) || pPager->tempFile ); |
| 51941 | | - if( 0==pagerFlushOnCommit(pPager) ){ |
| 52085 | + if( 0==pagerFlushOnCommit(pPager, 1) ){ |
| 51942 | 52086 | /* If this is an in-memory db, or no pages have been written to, or this |
| 51943 | 52087 | ** function has already been called, it is mostly a no-op. However, any |
| 51944 | 52088 | ** backup in progress needs to be restarted. */ |
| 51945 | 52089 | sqlite3BackupRestart(pPager->pBackup); |
| 51946 | 52090 | }else{ |
| | @@ -52561,10 +52705,11 @@ |
| 52561 | 52705 | assert( assert_pager_state(pPager) ); |
| 52562 | 52706 | |
| 52563 | 52707 | /* In order to be able to rollback, an in-memory database must journal |
| 52564 | 52708 | ** the page we are moving from. |
| 52565 | 52709 | */ |
| 52710 | + assert( pPager->tempFile || !MEMDB ); |
| 52566 | 52711 | if( pPager->tempFile ){ |
| 52567 | 52712 | rc = sqlite3PagerWrite(pPg); |
| 52568 | 52713 | if( rc ) return rc; |
| 52569 | 52714 | } |
| 52570 | 52715 | |
| | @@ -52635,12 +52780,11 @@ |
| 52635 | 52780 | |
| 52636 | 52781 | /* For an in-memory database, make sure the original page continues |
| 52637 | 52782 | ** to exist, in case the transaction needs to roll back. Use pPgOld |
| 52638 | 52783 | ** as the original page since it has already been allocated. |
| 52639 | 52784 | */ |
| 52640 | | - if( pPager->tempFile ){ |
| 52641 | | - assert( pPgOld ); |
| 52785 | + if( pPager->tempFile && pPgOld ){ |
| 52642 | 52786 | sqlite3PcacheMove(pPgOld, origPgno); |
| 52643 | 52787 | sqlite3PagerUnrefNotNull(pPgOld); |
| 52644 | 52788 | } |
| 52645 | 52789 | |
| 52646 | 52790 | if( needSyncPgno ){ |
| | @@ -59256,15 +59400,15 @@ |
| 59256 | 59400 | flagByte &= ~PTF_LEAF; |
| 59257 | 59401 | pPage->childPtrSize = 4-4*pPage->leaf; |
| 59258 | 59402 | pPage->xCellSize = cellSizePtr; |
| 59259 | 59403 | pBt = pPage->pBt; |
| 59260 | 59404 | if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ |
| 59261 | | - /* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior |
| 59262 | | - ** table b-tree page. */ |
| 59405 | + /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an |
| 59406 | + ** interior table b-tree page. */ |
| 59263 | 59407 | assert( (PTF_LEAFDATA|PTF_INTKEY)==5 ); |
| 59264 | | - /* EVIDENCE-OF: R-20501-61796 A value of 13 means the page is a leaf |
| 59265 | | - ** table b-tree page. */ |
| 59408 | + /* EVIDENCE-OF: R-26900-09176 A value of 13 (0x0d) means the page is a |
| 59409 | + ** leaf table b-tree page. */ |
| 59266 | 59410 | assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); |
| 59267 | 59411 | pPage->intKey = 1; |
| 59268 | 59412 | if( pPage->leaf ){ |
| 59269 | 59413 | pPage->intKeyLeaf = 1; |
| 59270 | 59414 | pPage->xParseCell = btreeParseCellPtr; |
| | @@ -59274,15 +59418,15 @@ |
| 59274 | 59418 | pPage->xParseCell = btreeParseCellPtrNoPayload; |
| 59275 | 59419 | } |
| 59276 | 59420 | pPage->maxLocal = pBt->maxLeaf; |
| 59277 | 59421 | pPage->minLocal = pBt->minLeaf; |
| 59278 | 59422 | }else if( flagByte==PTF_ZERODATA ){ |
| 59279 | | - /* EVIDENCE-OF: R-27225-53936 A value of 2 means the page is an interior |
| 59280 | | - ** index b-tree page. */ |
| 59423 | + /* EVIDENCE-OF: R-43316-37308 A value of 2 (0x02) means the page is an |
| 59424 | + ** interior index b-tree page. */ |
| 59281 | 59425 | assert( (PTF_ZERODATA)==2 ); |
| 59282 | | - /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf |
| 59283 | | - ** index b-tree page. */ |
| 59426 | + /* EVIDENCE-OF: R-59615-42828 A value of 10 (0x0a) means the page is a |
| 59427 | + ** leaf index b-tree page. */ |
| 59284 | 59428 | assert( (PTF_ZERODATA|PTF_LEAF)==10 ); |
| 59285 | 59429 | pPage->intKey = 0; |
| 59286 | 59430 | pPage->intKeyLeaf = 0; |
| 59287 | 59431 | pPage->xParseCell = btreeParseCellPtrIndex; |
| 59288 | 59432 | pPage->maxLocal = pBt->maxLocal; |
| | @@ -192850,11 +192994,11 @@ |
| 192850 | 192994 | int nArg, /* Number of args */ |
| 192851 | 192995 | sqlite3_value **apUnused /* Function arguments */ |
| 192852 | 192996 | ){ |
| 192853 | 192997 | assert( nArg==0 ); |
| 192854 | 192998 | UNUSED_PARAM2(nArg, apUnused); |
| 192855 | | - sqlite3_result_text(pCtx, "fts5: 2016-05-09 19:03:42 14e53d0e2f62d82ae1d64a72fd9711548e3bf5ea", -1, SQLITE_TRANSIENT); |
| 192999 | + sqlite3_result_text(pCtx, "fts5: 2016-05-18 10:57:30 fc49f556e48970561d7ab6a2f24fdd7d9eb81ff2", -1, SQLITE_TRANSIENT); |
| 192856 | 193000 | } |
| 192857 | 193001 | |
| 192858 | 193002 | static int fts5Init(sqlite3 *db){ |
| 192859 | 193003 | static const sqlite3_module fts5Mod = { |
| 192860 | 193004 | /* iVersion */ 2, |
| 192861 | 193005 | |