Index: third_party/sqlite/amalgamation/sqlite3.c |
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c |
index 9c66c16c9e47cab0198735fcac01648a2c6be556..f82ed1cb45dc0527bb0595a1b448ae7c1aec780e 100644 |
--- a/third_party/sqlite/amalgamation/sqlite3.c |
+++ b/third_party/sqlite/amalgamation/sqlite3.c |
@@ -126259,3 +126259,94 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule( |
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ |
/************** End of fts3_icu.c ********************************************/ |
+ |
+/* Touch the bigs of pCache which will be processed by |
+** pcache1TruncateUnsafe(), pcache1FreePage(), and pcache1Free() |
+** during sqlite3_close(). *pnTouched will have the number of bytes |
+** represented by the pages touched added to it. */ |
+SQLITE_PRIVATE void pcache1VisitUnsafe(PCache1 *pCache, |
+ unsigned int *pnTouched){ |
+ unsigned int iHash; |
+ |
+ assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); |
+ |
+ for(iHash=0; iHash<pCache->nHash; iHash++){ |
+ PgHdr1 *pp = pCache->apHash[iHash]; |
+ PgHdr1 *lp = pp; |
+ unsigned int s = 0; |
+ while (pp) { |
+ /* Crash if a loop is detected. */ |
+ /* NOTE(shess): Touches the PgHdr1 structure as a side effect. |
+ ** If this check is removed, revise the code to match ordering |
+ ** in pcache1TruncateUnsafe(). Yes, I realize this is |
+ ** probably reordered to heck and back. |
+ */ |
+ if (lp == pp->pNext) { |
+ int *zero = NULL; |
+ *zero = 42; |
+ } |
+ |
+ /* Touch the data area, in case it's on a prior VM page. */ |
+ *pnTouched += sqlite3MallocSize(PGHDR1_TO_PAGE(pp)); |
+ |
+ pp = pp->pNext; |
+ |
+ /* Bump the loop-detection pointer forward every time s is an |
+ ** even power of 2. */ |
+ s++; |
+ if (!(s & (s-1))) { |
+ lp = pp; |
+ } |
+ } |
+ } |
+} |
+ |
+/* TODO(shess): Debugging code for http://crbug.com/95527 . |
+** Touch the entire page cache for the given db. The idea is that if |
+** paging activity is causing the slowdown, the shutdown monitor will |
+** see things happening here, rather than in sqlite3_close(). |
+*/ |
+int sqlite3_95527(sqlite3 *db, unsigned int *pnTouched){ |
+ unsigned int iDb; |
+ |
+ /* This code assumes that pcache1 is the pager cache implementation. */ |
+ if (sqlite3GlobalConfig.pcache.xTruncate != pcache1Truncate) { |
+ return SQLITE_OK; |
+ } |
+ |
+ /* This setup is like sqlite3_close(). */ |
+ if( !db ){ |
+ return SQLITE_OK; |
+ } |
+ if( !sqlite3SafetyCheckSickOrOk(db) ){ |
+ return SQLITE_MISUSE_BKPT; |
+ } |
+ sqlite3_mutex_enter(db->mutex); |
+ |
+ /* A sqlite3* connection may refer to multiple underlying database |
+ files. Usually these will be 'main' and 'temp', with 'temp' having |
+ no btree or pager. */ |
+ for(iDb=0; iDb<db->nDb; iDb++){ |
+ Btree *b; |
+ Pager *p; |
+ PCache1 *pCache; |
+ struct Db *pDb = &db->aDb[iDb]; |
+ if (!pDb) continue; |
+ |
+ b = pDb->pBt; |
+ if (!b) continue; |
+ |
+ p = sqlite3BtreePager(b); |
+ if (!p) continue; |
+ |
+ pCache = (PCache1*)p->pPCache->pCache; |
+ if (!pCache) continue; |
+ |
+ pcache1EnterMutex(pCache->pGroup); |
+ pcache1VisitUnsafe(pCache, pnTouched); |
+ pcache1LeaveMutex(pCache->pGroup); |
+ } |
+ |
+ sqlite3_mutex_leave(db->mutex); |
+ return SQLITE_OK; |
+} |