From: dan Date: Thu, 13 Jul 2017 21:06:51 +0000 (+0000) Subject: Make the freelist format a separate feature from the page-level locking. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e1e878687db2a654751c0a292d01e1325363588d;p=thirdparty%2Fsqlite.git Make the freelist format a separate feature from the page-level locking. Freelist format is now configure using "PRAGMA freelist_format". FossilOrigin-Name: dcc407972aa213d28f95cbaf4da5ab7d89ddbad2740f41cfb44b2c2ce20a3132 --- diff --git a/manifest b/manifest index 082a684481..c0d590d619 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sSQL\sfunction\susleep()\sto\stest\sprogram\stserver.c. -D 2017-07-11T18:38:26.799 +C Make\sthe\sfreelist\sformat\sa\sseparate\sfeature\sfrom\sthe\spage-level\slocking.\nFreelist\sformat\sis\snow\sconfigure\susing\s"PRAGMA\sfreelist_format". +D 2017-07-13T21:06:51.922 F Makefile.in 081e48dfe7f995d57ce1a88ddf4d2917b4349158648a6cd45b42beae30de3a12 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4ebb1d257cac7fb1bcb4ba59278416d410ff1c4bf59447a9c37a415f3516056a @@ -391,8 +391,8 @@ F src/auth.c 79f96c6f33bf0e5da8d1c282cee5ebb1852bb8a6ccca3e485d7c459b035d9c3c F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c 0e1bcecde07e3e022a1a1f16cdfa6817267c25eb4a48ea21fe9359b973837762 -F src/btree.h 3edc5329bc59534d2d15b4f069a9f54b779a7e51289e98fa481ae3c0e526a5ca +F src/btree.c 85cd6d97be767b660a030d841534b082d8e50df506c9eaaa0bcc0c5c15f77da9 +F src/btree.h d1f64c5683e9ade8afa968b49abeb108acd430fc33f2cae2a62a2cfc601087d8 F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610 F src/build.c 32107046e8cda19a917b4a397175c7eb5f2e234d19fae2fc6164859e4a3d4704 F src/callback.c 8e14b60d1ed1c87c02cb5f121ecda99224f2aea6524a77ee6f72c9b5c7110f84 @@ -441,8 +441,8 @@ F src/parse.y f732ca9ef4dbee9ba19d6d30d2d1f7ac0834d8642515dedbd8f6ebd16ab2a8e3 F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11 F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc -F src/pragma.c 3f9456edac7eaf171041d51510c5cc922c9b3bd56a713fb7ad6d5b85aa72f1f6 -F src/pragma.h 99d3df4a3d2f12c5227ad403f767334910e6356325b6d155a9a99b4037093460 +F src/pragma.c 09fe2d45a92a16d3dfcab3f18a4992b3bedaacdeed93704cc9dee4b8525717c8 +F src/pragma.h 10b1af34882f96d68b7d3bb07c00fda3283f270f83f58e1ebea6d3b694c95553 F src/prepare.c 4b84ae7458febe1df3e04ae62ba56abc851f771340e460d14426e6802c5615f4 F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 @@ -517,7 +517,7 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23 F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf -F src/vdbe.c e4493b09cc603a1b031c982785e94bbe637799c9e7fc974d37036c04ad2d79e0 +F src/vdbe.c 51a564ddea23a62589424c7d1755dfa245a4e3ffdc3630b1dac9939cecdbbcdd F src/vdbe.h dde459b1e8a02b8445ecfd5959f38cd5ebb6b0ad392d491d8b159ac8193d231a F src/vdbeInt.h 8dd7548d86a98b77b6ed910d8014d0e9e0666356b56f3d16ab7063aad4f102f5 F src/vdbeapi.c 899d8f021c89ab348708b3a9b00b855f5ecc3c0f949a75359a61a3c621021281 @@ -1573,7 +1573,7 @@ F tool/mkmsvcmin.tcl cbd93f1cfa3a0a9ae56fc958510aa3fc3ac65e29cb111716199e3d0e66e F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e -F tool/mkpragmatab.tcl aa94395a91b5bd47022b7db0c08126f047887e0d299cc19ec1c23a9e5b136961 +F tool/mkpragmatab.tcl 983057a16468b7e5f7c8a1a0f9ba515b4e188d04f326b781ea96c2cf814b3b9f F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb F tool/mksqlite3c.tcl 4b17864d0ae7664b2a82ac852afbe52e7d1db65c996b72941e149704b5e3cc15 @@ -1636,7 +1636,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b6157267f9d4ecdffbdf4b1e591b8d6baaaa964c418ec247a24ccb82146f9041 -R d431332999db79016ab1852b88d53c44 +P 8cbe8f2b2fe0a5a246401718da8db8d487ced232ada73b53bdc9f9608c47d50e +R e2a1314b3947fa4a991aa95e4137779f U dan -Z 974e699f24a083c2cc24ed8a142caee5 +Z 013d31178aa545fe252ff8393248759a diff --git a/manifest.uuid b/manifest.uuid index 9643b9844d..3a4b9e09fa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8cbe8f2b2fe0a5a246401718da8db8d487ced232ada73b53bdc9f9608c47d50e \ No newline at end of file +dcc407972aa213d28f95cbaf4da5ab7d89ddbad2740f41cfb44b2c2ce20a3132 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 6410f228df..7fdcba4a70 100644 --- a/src/btree.c +++ b/src/btree.c @@ -238,6 +238,15 @@ static int hasReadConflicts(Btree *pBtree, Pgno iRoot){ } #endif /* #ifdef SQLITE_DEBUG */ +#ifdef SQLITE_SERVER_EDITION +/* +** Return true if the b-tree uses free-list format 2. Or false otherwise. +*/ +static int btreeFreelistFormat2(BtShared *pBt){ + return (pBt->pPage1->aData[18] > 2); +} +#endif + /* ** Query to see if Btree handle p may obtain a lock of type eLock ** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return @@ -2927,6 +2936,15 @@ static int lockBtree(BtShared *pBt){ u32 pageSize; u32 usableSize; u8 *page1 = pPage1->aData; + u8 i18 = page1[18]; + u8 i19 = page1[19]; +#ifdef SQLITE_SERVER_EDITION + if( i18==i19 && i18>2 ){ + i18 -= 2; + i19 -= 2; + } +#endif + rc = SQLITE_NOTADB; /* EVIDENCE-OF: R-43737-39999 Every valid SQLite database file begins ** with the following 16 bytes (in hex): 53 51 4c 69 74 65 20 66 6f 72 6d @@ -2936,17 +2954,17 @@ static int lockBtree(BtShared *pBt){ } #ifdef SQLITE_OMIT_WAL - if( page1[18]>1 ){ + if( i18>1 ){ pBt->btsFlags |= BTS_READ_ONLY; } - if( page1[19]>1 ){ + if( i19>1 ){ goto page1_init_failed; } #else - if( page1[18]>2 ){ + if( i18>2 ){ pBt->btsFlags |= BTS_READ_ONLY; } - if( page1[19]>2 ){ + if( i19>2 ){ goto page1_init_failed; } @@ -2958,7 +2976,7 @@ static int lockBtree(BtShared *pBt){ ** may not be the latest version - there may be a newer one in the log ** file. */ - if( page1[19]==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){ + if( i19==2 && (pBt->btsFlags & BTS_NO_WAL)==0 ){ int isOpen = 0; rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen); if( rc!=SQLITE_OK ){ @@ -5900,7 +5918,7 @@ static int allocateBtreePage( MemPage *pPrevTrunk = 0; Pgno mxPage; /* Total size of the database file */ - if( sqlite3PagerIsServer(pBt->pPager) ){ + if( btreeFreelistFormat2(pBt) ){ return allocateServerPage(pBt, ppPage, pPgno, nearby, eMode); } @@ -6243,7 +6261,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ memset(pPage->aData, 0, pPage->pBt->pageSize); } - if( sqlite3PagerIsServer(pBt->pPager) ){ + if( btreeFreelistFormat2(pBt) ){ rc = freeServerPage2(pBt, pPage, iPage); goto freepage_out; } @@ -9816,7 +9834,7 @@ char *sqlite3BtreeIntegrityCheck( */ sCheck.zPfx = "Main freelist: "; #ifdef SQLITE_SERVER_EDITION - if( sqlite3PagerIsServer(pBt->pPager) ){ + if( btreeFreelistFormat2(pBt) ){ checkServerList(&sCheck); }else #endif @@ -10092,6 +10110,37 @@ void sqlite3BtreeIncrblobCursor(BtCursor *pCur){ } #endif +int btreeSetVersion(Btree *pBtree, int iVersion, int iFreelistFmt){ + BtShared *pBt = pBtree->pBt; + int rc = sqlite3BtreeBeginTrans(pBtree, 0); + if( rc==SQLITE_OK ){ + u8 iVal; + u8 *aData = pBt->pPage1->aData; + + assert( (iVersion==0 && (iFreelistFmt==1 || iFreelistFmt==2)) + || (iFreelistFmt==0 && (iVersion==1 || iVersion==2)) + ); + if( iVersion==0 ){ + iVal = ((aData[18] & 0x01) ? 1 : 2) + (u8)(iFreelistFmt==2 ? 2 : 0); + }else{ + iVal = (u8)iVersion + (u8)(aData[18]>2 ? 2 : 0); + } + + if( aData[18]!=iVal || aData[19]!=iVal ){ + rc = sqlite3BtreeBeginTrans(pBtree, 2); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ + aData[18] = iVal; + aData[19] = iVal; + } + } + } + } + + return rc; +} + /* ** Set both the "read version" (single byte at byte offset 18) and ** "write version" (single byte at byte offset 19) fields in the database @@ -10108,23 +10157,22 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){ */ pBt->btsFlags &= ~BTS_NO_WAL; if( iVersion==1 ) pBt->btsFlags |= BTS_NO_WAL; + rc = btreeSetVersion(pBtree, iVersion, 0); + pBt->btsFlags &= ~BTS_NO_WAL; + return rc; +} - 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 ){ - rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); - if( rc==SQLITE_OK ){ - aData[18] = (u8)iVersion; - aData[19] = (u8)iVersion; - } - } +int sqlite3BtreeFreelistFormat(Btree *p, int eParam, int *peFmt){ + int rc = SQLITE_OK; + sqlite3BtreeEnter(p); + if( eParam ){ + u8 *aData = p->pBt->pPage1->aData; + if( 0==get4byte(&aData[32]) ){ + rc = btreeSetVersion(p, 0, eParam); } } - - pBt->btsFlags &= ~BTS_NO_WAL; + *peFmt = (btreeFreelistFormat2(p->pBt) ? 2 : 1); + sqlite3BtreeLeave(p); return rc; } diff --git a/src/btree.h b/src/btree.h index b56eb85e68..4f9714c141 100644 --- a/src/btree.h +++ b/src/btree.h @@ -367,5 +367,8 @@ void sqlite3BtreeCursorList(Btree*); # define sqlite3SchemaMutexHeld(X,Y,Z) 1 #endif +#ifdef SQLITE_SERVER_EDITION +int sqlite3BtreeFreelistFormat(Btree *p, int eParam, int *peFmt); +#endif #endif /* SQLITE_BTREE_H */ diff --git a/src/pragma.c b/src/pragma.c index 7135f07553..fb6893de72 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -656,6 +656,33 @@ void sqlite3Pragma( break; } +#ifdef SQLITE_SERVER_EDITION + /* + ** PRAGMA [schema.]freelist_format + ** PRAGMA [schema.]freelist_format = (1|2) + */ + case PragTyp_FREELIST_FORMAT: { + sqlite3VdbeUsesBtree(v, iDb); + static const VdbeOpList freelist[] = { + { OP_Transaction, 0, 0, 0}, /* 0 */ + { OP_FreelistFmt, 0, 1, 0}, /* 1 */ + { OP_ResultRow, 1, 1, 0} /* 2 */ + }; + VdbeOp *aOp; + sqlite3VdbeVerifyNoMallocRequired(v, ArraySize(freelist)); + aOp = sqlite3VdbeAddOpList(v, ArraySize(freelist), freelist,0); + aOp[0].p1 = iDb; + aOp[1].p1 = iDb; + + if( zRight && (zRight[0]=='1' || zRight[0]=='2') && zRight[1]=='\0' ){ + aOp[0].p2 = 1; /* Open a write transaction */ + aOp[1].p3 = (int)(zRight[0] - '0'); + } + + break; + } +#endif + /* ** PRAGMA [schema.]journal_size_limit ** PRAGMA [schema.]journal_size_limit=N diff --git a/src/pragma.h b/src/pragma.h index 76e59cbc6b..a21b70aace 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -20,35 +20,36 @@ #define PragTyp_ENCODING 12 #define PragTyp_FOREIGN_KEY_CHECK 13 #define PragTyp_FOREIGN_KEY_LIST 14 -#define PragTyp_INCREMENTAL_VACUUM 15 -#define PragTyp_INDEX_INFO 16 -#define PragTyp_INDEX_LIST 17 -#define PragTyp_INTEGRITY_CHECK 18 -#define PragTyp_JOURNAL_MODE 19 -#define PragTyp_JOURNAL_SIZE_LIMIT 20 -#define PragTyp_LOCK_PROXY_FILE 21 -#define PragTyp_LOCKING_MODE 22 -#define PragTyp_PAGE_COUNT 23 -#define PragTyp_MMAP_SIZE 24 -#define PragTyp_OPTIMIZE 25 -#define PragTyp_PAGE_SIZE 26 -#define PragTyp_SECURE_DELETE 27 -#define PragTyp_SHRINK_MEMORY 28 -#define PragTyp_SOFT_HEAP_LIMIT 29 -#define PragTyp_SYNCHRONOUS 30 -#define PragTyp_TABLE_INFO 31 -#define PragTyp_TEMP_STORE 32 -#define PragTyp_TEMP_STORE_DIRECTORY 33 -#define PragTyp_THREADS 34 -#define PragTyp_WAL_AUTOCHECKPOINT 35 -#define PragTyp_WAL_CHECKPOINT 36 -#define PragTyp_ACTIVATE_EXTENSIONS 37 -#define PragTyp_HEXKEY 38 -#define PragTyp_KEY 39 -#define PragTyp_REKEY 40 -#define PragTyp_LOCK_STATUS 41 -#define PragTyp_PARSER_TRACE 42 -#define PragTyp_STATS 43 +#define PragTyp_FREELIST_FORMAT 15 +#define PragTyp_INCREMENTAL_VACUUM 16 +#define PragTyp_INDEX_INFO 17 +#define PragTyp_INDEX_LIST 18 +#define PragTyp_INTEGRITY_CHECK 19 +#define PragTyp_JOURNAL_MODE 20 +#define PragTyp_JOURNAL_SIZE_LIMIT 21 +#define PragTyp_LOCK_PROXY_FILE 22 +#define PragTyp_LOCKING_MODE 23 +#define PragTyp_PAGE_COUNT 24 +#define PragTyp_MMAP_SIZE 25 +#define PragTyp_OPTIMIZE 26 +#define PragTyp_PAGE_SIZE 27 +#define PragTyp_SECURE_DELETE 28 +#define PragTyp_SHRINK_MEMORY 29 +#define PragTyp_SOFT_HEAP_LIMIT 30 +#define PragTyp_SYNCHRONOUS 31 +#define PragTyp_TABLE_INFO 32 +#define PragTyp_TEMP_STORE 33 +#define PragTyp_TEMP_STORE_DIRECTORY 34 +#define PragTyp_THREADS 35 +#define PragTyp_WAL_AUTOCHECKPOINT 36 +#define PragTyp_WAL_CHECKPOINT 37 +#define PragTyp_ACTIVATE_EXTENSIONS 38 +#define PragTyp_HEXKEY 39 +#define PragTyp_KEY 40 +#define PragTyp_REKEY 41 +#define PragTyp_LOCK_STATUS 42 +#define PragTyp_PARSER_TRACE 43 +#define PragTyp_STATS 44 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -294,6 +295,13 @@ static const PragmaName aPragmaName[] = { /* ColNames: */ 0, 0, /* iArg: */ BTREE_FREE_PAGE_COUNT }, #endif +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && defined(SQLITE_SERVER_EDITION) + {/* zName: */ "freelist_format", + /* ePragTyp: */ PragTyp_FREELIST_FORMAT, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, + /* ColNames: */ 0, 0, + /* iArg: */ 0 }, +#endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "full_column_names", /* ePragTyp: */ PragTyp_FLAG, @@ -613,4 +621,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema }, #endif }; -/* Number of pragmas: 60 on by default, 74 total. */ +/* Number of pragmas: 60 on by default, 75 total. */ diff --git a/src/vdbe.c b/src/vdbe.c index 6242d6545d..8705ff0b53 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3377,6 +3377,33 @@ case OP_SetCookie: { break; } +#ifdef SQLITE_SERVER_EDITION +/* Opcode: FreelistFmt P1 P2 P3 * * +** +** Parameter P3 must be 0, 1 or 2. If it is not 0, attempt to set the +** freelist format of database P1 to format 1 or format 2. Before +** returning, store the final freelist format (either 1 or 2) of +** database P1 into register P2. +*/ +case OP_FreelistFmt: { /* out2 */ + Db *pDb; + int iVal; + + assert( pOp->p1>=0 && pOp->p1nDb ); + assert( DbMaskTest(p->btreeMask, pOp->p1) ); + assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); + + pOut = out2Prerelease(p, pOp); + rc = sqlite3BtreeFreelistFormat(pDb->pBt, pOp->p3, &iVal); + if( rc ) goto abort_due_to_error; + pOut->u.i = iVal; + + break; +} +#endif + /* Opcode: OpenRead P1 P2 P3 P4 P5 ** Synopsis: root=P2 iDb=P3 ** diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index c7001dc339..2ba65a8c90 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -364,6 +364,10 @@ set pragma_def { NAME: optimize FLAG: Result1 NeedSchema + + NAME: freelist_format + FLAG: NeedSchema Result0 SchemaReq + IF: !defined(SQLITE_OMIT_PAGER_PRAGMAS) && defined(SQLITE_SERVER_EDITION) } # Open the output file