Index: third_party/sqlite/patches/0011-Allow-auto-vacuum-to-work-with-chunks.patch |
diff --git a/third_party/sqlite/patches/0011-Allow-auto-vacuum-to-work-with-chunks.patch b/third_party/sqlite/patches/0011-Allow-auto-vacuum-to-work-with-chunks.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..58294ad0b9d3dba9da4536354cda4beb918bc159 |
--- /dev/null |
+++ b/third_party/sqlite/patches/0011-Allow-auto-vacuum-to-work-with-chunks.patch |
@@ -0,0 +1,185 @@ |
+From d62ff0d64a8738fd8bb07b82bcebd65143a17045 Mon Sep 17 00:00:00 2001 |
+From: Scott Hess <shess@chromium.org> |
+Date: Thu, 2 Mar 2017 15:23:09 -0800 |
+Subject: [PATCH 11/11] Allow auto-vacuum to work with chunks. |
+ |
+SQLITE_FCNTL_CHUNK_SIZE can advise the VFS to resize files in quantum |
+amounts, to reduce fragmentation from tiny appends. This change allows |
+a new PRAGMA auto_vacuum_slack_pages to provide auto_vacuum with a hint |
+to only rearrange pages when an entire quantum can be released. |
+ |
+BUG=698010 |
+--- |
+ third_party/sqlite/src/src/btree.c | 56 ++++++++++++++++++++++++++++++++++- |
+ third_party/sqlite/src/src/btree.h | 2 ++ |
+ third_party/sqlite/src/src/btreeInt.h | 1 + |
+ third_party/sqlite/src/src/pragma.c | 21 +++++++++++++ |
+ third_party/sqlite/src/src/pragma.h | 8 +++++ |
+ 5 files changed, 87 insertions(+), 1 deletion(-) |
+ |
+diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c |
+index de553423b884..3335ced417ca 100644 |
+--- a/third_party/sqlite/src/src/btree.c |
++++ b/third_party/sqlite/src/src/btree.c |
+@@ -2812,6 +2812,46 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){ |
+ #endif |
+ } |
+ |
++/* |
++** Change the 'auto-vacuum-slack-pages' property of the database. If auto vacuum |
++** is enabled, this is the number of chunks of slack to allow before |
++** automatically running an incremental vacuum. |
++*/ |
++int sqlite3BtreeSetAutoVacuumSlackPages(Btree *p, int autoVacuumSlack){ |
++#ifdef SQLITE_OMIT_AUTOVACUUM |
++ return SQLITE_READONLY; |
++#else |
++ BtShared *pBt = p->pBt; |
++ int rc = SQLITE_OK; |
++ u8 avs = (u8)autoVacuumSlack; |
++ if( autoVacuumSlack>avs ){ |
++ avs = 0xFF; |
++ } |
++ |
++ sqlite3BtreeEnter(p); |
++ pBt->autoVacuumSlack = avs; |
++ sqlite3BtreeLeave(p); |
++ return rc; |
++#endif |
++} |
++ |
++/* |
++** Return the value of the 'auto-vacuum-slack-pages' property. |
++*/ |
++int sqlite3BtreeGetAutoVacuumSlackPages(Btree *p){ |
++#ifdef SQLITE_OMIT_AUTOVACUUM |
++ return 0; |
++#else |
++ int rc = 0; |
++ sqlite3BtreeEnter(p); |
++ if( p->pBt->autoVacuum!=0 ){ |
++ rc = p->pBt->autoVacuumSlack; |
++ } |
++ sqlite3BtreeLeave(p); |
++ return rc; |
++#endif |
++} |
++ |
+ |
+ /* |
+ ** Get a reference to pPage1 of the database file. This will |
+@@ -3653,13 +3693,27 @@ int sqlite3BtreeIncrVacuum(Btree *p){ |
+ */ |
+ static int autoVacuumCommit(BtShared *pBt){ |
+ int rc = SQLITE_OK; |
++ int bShouldVacuum = pBt->autoVacuum && !pBt->incrVacuum; |
+ Pager *pPager = pBt->pPager; |
+ VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); ) |
+ |
+ assert( sqlite3_mutex_held(pBt->mutex) ); |
+ invalidateAllOverflowCache(pBt); |
+ assert(pBt->autoVacuum); |
+- if( !pBt->incrVacuum ){ |
++ if( bShouldVacuum && pBt->autoVacuumSlack ){ |
++ Pgno nOrig; /* Database size before freeing */ |
++ Pgno nFree; /* Number of pages on the freelist initially */ |
++ |
++ nOrig = btreePagecount(pBt); |
++ nFree = get4byte(&pBt->pPage1->aData[36]); |
++ bShouldVacuum = |
++ (nOrig-nFree-1)/pBt->autoVacuumSlack < (nOrig-1)/pBt->autoVacuumSlack; |
++ /* TODO: When integrating this test with the following code, contrive to |
++ ** trim to the integral chunk boundary, rather than trimming the entire free |
++ ** list. |
++ */ |
++ } |
++ if( bShouldVacuum ){ |
+ Pgno nFin; /* Number of pages in database after autovacuuming */ |
+ Pgno nFree; /* Number of pages on the freelist initially */ |
+ Pgno iFree; /* The next page to be freed */ |
+diff --git a/third_party/sqlite/src/src/btree.h b/third_party/sqlite/src/src/btree.h |
+index ae57468e3fd5..e0da44957564 100644 |
+--- a/third_party/sqlite/src/src/btree.h |
++++ b/third_party/sqlite/src/src/btree.h |
+@@ -78,6 +78,8 @@ int sqlite3BtreeGetOptimalReserve(Btree*); |
+ int sqlite3BtreeGetReserveNoMutex(Btree *p); |
+ int sqlite3BtreeSetAutoVacuum(Btree *, int); |
+ int sqlite3BtreeGetAutoVacuum(Btree *); |
++int sqlite3BtreeSetAutoVacuumSlackPages(Btree *, int); |
++int sqlite3BtreeGetAutoVacuumSlackPages(Btree *); |
+ int sqlite3BtreeBeginTrans(Btree*,int); |
+ int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
+ int sqlite3BtreeCommitPhaseTwo(Btree*, int); |
+diff --git a/third_party/sqlite/src/src/btreeInt.h b/third_party/sqlite/src/src/btreeInt.h |
+index b01163c33f49..eb9d1b5ef58d 100644 |
+--- a/third_party/sqlite/src/src/btreeInt.h |
++++ b/third_party/sqlite/src/src/btreeInt.h |
+@@ -412,6 +412,7 @@ struct BtShared { |
+ u8 openFlags; /* Flags to sqlite3BtreeOpen() */ |
+ #ifndef SQLITE_OMIT_AUTOVACUUM |
+ u8 autoVacuum; /* True if auto-vacuum is enabled */ |
++ u8 autoVacuumSlack; /* Optional pages of slack for auto-vacuum */ |
+ u8 incrVacuum; /* True if incr-vacuum is enabled */ |
+ u8 bDoTruncate; /* True to truncate db on commit */ |
+ #endif |
+diff --git a/third_party/sqlite/src/src/pragma.c b/third_party/sqlite/src/src/pragma.c |
+index b1775a4082a3..1d5ebfca098d 100644 |
+--- a/third_party/sqlite/src/src/pragma.c |
++++ b/third_party/sqlite/src/src/pragma.c |
+@@ -736,6 +736,27 @@ void sqlite3Pragma( |
+ } |
+ #endif |
+ |
++ /* |
++ ** PRAGMA [schema.]auto_vacuum_slack_pages(N) |
++ ** |
++ ** Control chunk size of auto-vacuum. |
++ */ |
++#ifndef SQLITE_OMIT_AUTOVACUUM |
++ case PragTyp_AUTO_VACUUM_SLACK_PAGES: { |
++ Btree *pBt = pDb->pBt; |
++ assert( pBt!=0 ); |
++ if( !zRight ){ |
++ returnSingleInt(v, sqlite3BtreeGetAutoVacuumSlackPages(pBt)); |
++ }else{ |
++ int nPages = 8; |
++ if( sqlite3GetInt32(zRight, &nPages) ){ |
++ sqlite3BtreeSetAutoVacuumSlackPages(pBt, nPages); |
++ } |
++ } |
++ break; |
++ } |
++#endif |
++ |
+ #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
+ /* |
+ ** PRAGMA [schema.]cache_size |
+diff --git a/third_party/sqlite/src/src/pragma.h b/third_party/sqlite/src/src/pragma.h |
+index 5d8d0aa35b3f..e47f80fefac4 100644 |
+--- a/third_party/sqlite/src/src/pragma.h |
++++ b/third_party/sqlite/src/src/pragma.h |
+@@ -48,6 +48,7 @@ |
+ #define PragTyp_REKEY 40 |
+ #define PragTyp_LOCK_STATUS 41 |
+ #define PragTyp_PARSER_TRACE 42 |
++#define PragTyp_AUTO_VACUUM_SLACK_PAGES 43 |
+ |
+ /* Property flags associated with various pragma. */ |
+ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ |
+@@ -145,6 +146,13 @@ static const PragmaName aPragmaName[] = { |
+ /* ColNames: */ 0, 0, |
+ /* iArg: */ 0 }, |
+ #endif |
++#if !defined(SQLITE_OMIT_AUTOVACUUM) |
++ { /* zName: */ "auto_vacuum_slack_pages", |
++ /* ePragTyp: */ PragTyp_AUTO_VACUUM_SLACK_PAGES, |
++ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, |
++ /* ColNames: */ 0, 0, |
++ /* iArg: */ 0 }, |
++#endif |
+ #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
+ #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) |
+ {/* zName: */ "automatic_index", |
+-- |
+2.11.0 |
+ |