From 4fa7d7c0df4a2815abb0fb613786a1dd7173269d Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 3 Apr 2011 02:41:00 +0000 Subject: [PATCH 1/6] Fix typos in comments. No changes to code. FossilOrigin-Name: 28c5f12e98655d5c6167b13e8a15085eca43dd5b --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btmutex.c | 2 +- src/btree.c | 2 +- src/btreeInt.h | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 927bd9ef71..13d580b533 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\s"tAttachMask"\sdatatype\sto\s"yDbMask". -D 2011-04-02T20:01:02.621 +C Fix\stypos\sin\scomments.\s\sNo\schanges\sto\scode. +D 2011-04-03T02:41:00.238 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,10 +120,10 @@ F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef -F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff -F src/btree.c 2b9c81ff64da339a67dda4f94c0d763627be0b67 +F src/btmutex.c 5ba4ca0216bd9406eccbf50aaf35fef6912c4e2c +F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 -F src/btreeInt.h 20f73dc93b1eeb83afd7259fbc6bd7dcf2df7fe4 +F src/btreeInt.h 29ab8a4172f12b04fac34c5a0b76d0df750ddc34 F src/build.c 3a8c6c4b1e16798755d46e699b7fcc12b9f27b2b F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3b91eaaa0b3c25022332ba3d1a5651848fc5d84c -R e5d6d2ab5437a135179f043b3faf09c4 +P 3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa +R 1103ef46d2beca5f9008b7e7268f91fc U drh -Z cdbe2872c525d3ae3a361db4be775f20 +Z 2ee794956e08f440e3a2557effd86b8a diff --git a/manifest.uuid b/manifest.uuid index 6c4bffcf25..eb10573089 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa \ No newline at end of file +28c5f12e98655d5c6167b13e8a15085eca43dd5b \ No newline at end of file diff --git a/src/btmutex.c b/src/btmutex.c index 201291a3e9..d772f4b50f 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -195,7 +195,7 @@ void sqlite3BtreeEnterAll(sqlite3 *db){ if( !p->locked ){ assert( p->wantToLock==1 ); while( p->pPrev ) p = p->pPrev; - /* Reason for ALWAYS: There must be at least on unlocked Btree in + /* Reason for ALWAYS: There must be at least one unlocked Btree in ** the chain. Otherwise the !p->locked test above would have failed */ while( p->locked && ALWAYS(p->pNext) ) p = p->pNext; for(pLater = p->pNext; pLater; pLater=pLater->pNext){ diff --git a/src/btree.c b/src/btree.c index 088c555fc6..d86b9edad1 100644 --- a/src/btree.c +++ b/src/btree.c @@ -7990,7 +7990,7 @@ int sqlite3BtreeIsInBackup(Btree *p){ ** ** Just before the shared-btree is closed, the function passed as the ** xFree argument when the memory allocation was made is invoked on the -** blob of allocated memory. This function should not call sqlite3_free() +** blob of allocated memory. The xFree function should not call sqlite3_free() ** on the memory, the btree layer does that. */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ diff --git a/src/btreeInt.h b/src/btreeInt.h index 0e71195b0a..a645f4fb97 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -336,7 +336,7 @@ struct BtLock { ** All fields in this structure are accessed under sqlite3.mutex. ** The pBt pointer itself may not be changed while there exists cursors ** in the referenced BtShared that point back to this Btree since those -** cursors have to do go through this Btree to find their BtShared and +** cursors have to go through this Btree to find their BtShared and ** they often do so without holding sqlite3.mutex. */ struct Btree { From dddd779b2bfc818bd2e5f46f01fafbcd89cc7955 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 3 Apr 2011 18:19:25 +0000 Subject: [PATCH 2/6] Make sure that the constant 1 is cast to yDbType before shifting to create an attached database mask. This check-in is a follow-up and fix to the [7aaf8772274422] change that increases the maximum number of attached databases from 30 to 62. FossilOrigin-Name: e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 24 ++++++++++++------------ src/vdbeaux.c | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 13d580b533..7659f6e29a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stypos\sin\scomments.\s\sNo\schanges\sto\scode. -D 2011-04-03T02:41:00.238 +C Make\ssure\sthat\sthe\sconstant\s1\sis\scast\sto\syDbType\sbefore\sshifting\sto\screate\nan\sattached\sdatabase\smask.\s\sThis\scheck-in\sis\sa\sfollow-up\sand\sfix\sto\sthe\n[7aaf8772274422]\schange\sthat\sincreases\sthe\smaximum\snumber\sof\sattached\sdatabases\nfrom\s30\sto\s62. +D 2011-04-03T18:19:25.822 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -235,11 +235,11 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c a45a6a0daf2161797d50b3b5b8a3e0e4debf2d2b +F src/vdbe.c d975adcef86051b6b51c5d2394dd2288e0b0ca81 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 8ee9302ecc1036509956df8aceea6b0b5e0e231c F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c 80ed78c8e1edf8918e0e404891d314aa01ccb095 +F src/vdbeaux.c ad921cf58e8c20e1c0a9ef0b7e0f557eabdc7d07 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 3d6f2e82358c0d8c0ca04e0da20b84fc65c3f7fa -R 1103ef46d2beca5f9008b7e7268f91fc +P 28c5f12e98655d5c6167b13e8a15085eca43dd5b +R 62a2deace5cc72cdc4511f7f5b5d9fa5 U drh -Z 2ee794956e08f440e3a2557effd86b8a +Z 905bef73ef8c243b27a93f7a5f38565e diff --git a/manifest.uuid b/manifest.uuid index eb10573089..b383b69990 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -28c5f12e98655d5c6167b13e8a15085eca43dd5b \ No newline at end of file +e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index ddf507ee9d..e6118a4cb5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2789,7 +2789,7 @@ case OP_Transaction: { Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ @@ -2845,7 +2845,7 @@ case OP_ReadCookie: { /* out2-prerelease */ assert( pOp->p3=0 && iDbnDb ); assert( db->aDb[iDb].pBt!=0 ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[iDb].pBt, iCookie, (u32 *)&iMeta); pOut->u.i = iMeta; @@ -2866,7 +2866,7 @@ case OP_SetCookie: { /* in3 */ Db *pDb; assert( pOp->p2p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); pIn3 = &aMem[pOp->p3]; @@ -2914,7 +2914,7 @@ case OP_VerifyCookie: { Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; if( pBt ){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta); @@ -3018,7 +3018,7 @@ case OP_OpenWrite: { p2 = pOp->p2; iDb = pOp->p3; assert( iDb>=0 && iDbnDb ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[iDb]; pX = pDb->pBt; assert( pX!=0 ); @@ -4513,7 +4513,7 @@ case OP_Destroy: { /* out2-prerelease */ }else{ iDb = pOp->p3; assert( iCnt==1 ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[iDb].pBt, pOp->p1, &iMoved); pOut->flags = MEM_Int; pOut->u.i = iMoved; @@ -4549,7 +4549,7 @@ case OP_Clear: { int nChange; nChange = 0; - assert( (p->btreeMask & (1<p2))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) ); @@ -4594,7 +4594,7 @@ case OP_CreateTable: { /* out2-prerelease */ pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pDb = &db->aDb[pOp->p1]; assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ @@ -4766,7 +4766,7 @@ case OP_IntegrityCk: { } aRoot[j] = 0; assert( pOp->p5nDb ); - assert( (p->btreeMask & (1<p5))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 ); z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot, (int)pnErr->u.i, &nErr); sqlite3DbFree(db, aRoot); @@ -5303,7 +5303,7 @@ case OP_JournalMode: { /* out2-prerelease */ ** No other mutexes are required by the ATTACH command so this is safe ** to do. */ - assert( (p->btreeMask & (1<p1))!=0 || p->aMutex.nMutex==0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 || p->aMutex.nMutex==0 ); if( p->aMutex.nMutex==0 ){ /* This occurs right after ATTACH. Get a mutex on the newly ATTACHed ** database. */ @@ -5408,7 +5408,7 @@ case OP_IncrVacuum: { /* jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); + assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ @@ -5457,7 +5457,7 @@ case OP_TableLock: { if( isWriteLock || 0==(db->flags&SQLITE_ReadUncommitted) ){ int p1 = pOp->p1; assert( p1>=0 && p1nDb ); - assert( (p->btreeMask & (1<btreeMask & (((yDbMask)1)<aDb[p1].pBt, pOp->p2, isWriteLock); if( (rc&0xFF)==SQLITE_LOCKED ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 16d234dd08..de02d021af 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -954,7 +954,7 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ yDbMask mask; assert( i>=0 && idb->nDb && ibtreeMask)*8 ); - mask = ((u32)1)<btreeMask & mask)==0 ){ p->btreeMask |= mask; sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); From bdaec52c6218c59e7f45d9894834843bb2c8aceb Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 00:14:43 +0000 Subject: [PATCH 3/6] Remove the BtreeMutexArray object - use the Vdbe.btreeMask field to accomplish the same result. Add a generation counter to btree mutexes in order to assert that mutexes are never temporarily dropped over a range of instructions in order to do deadlock avoidance in some subroutine. Lock all btrees in any Vdbe program that uses OP_ParseSchema. FossilOrigin-Name: d81708f7d1eee399bfe76f6b8dac950a85dc2582 --- manifest | 22 +++---- manifest.uuid | 2 +- src/btmutex.c | 137 ++++++++++++++--------------------------- src/btree.h | 20 +----- src/btreeInt.h | 3 +- src/vdbe.c | 81 +++++++++++++++--------- src/vdbeInt.h | 11 ++-- src/vdbeaux.c | 164 ++++++++++++++++++++++++++++++++++++------------- 8 files changed, 242 insertions(+), 198 deletions(-) diff --git a/manifest b/manifest index 7659f6e29a..54a041dd07 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthat\sthe\sconstant\s1\sis\scast\sto\syDbType\sbefore\sshifting\sto\screate\nan\sattached\sdatabase\smask.\s\sThis\scheck-in\sis\sa\sfollow-up\sand\sfix\sto\sthe\n[7aaf8772274422]\schange\sthat\sincreases\sthe\smaximum\snumber\sof\sattached\sdatabases\nfrom\s30\sto\s62. -D 2011-04-03T18:19:25.822 +C Remove\sthe\sBtreeMutexArray\sobject\s-\suse\sthe\sVdbe.btreeMask\sfield\sto\saccomplish\nthe\ssame\sresult.\s\sAdd\sa\sgeneration\scounter\sto\sbtree\smutexes\sin\sorder\sto\sassert\nthat\smutexes\sare\snever\stemporarily\sdropped\sover\sa\srange\sof\sinstructions\sin\sorder\nto\sdo\sdeadlock\savoidance\sin\ssome\ssubroutine.\s\sLock\sall\sbtrees\sin\sany\sVdbe\nprogram\sthat\suses\sOP_ParseSchema. +D 2011-04-04T00:14:43.936 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -120,10 +120,10 @@ F src/attach.c 438ea6f6b5d5961c1f49b737f2ce0f14ce7c6877 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 537f89c7ef5021cb580f31f782e556ffffcb2ed1 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef -F src/btmutex.c 5ba4ca0216bd9406eccbf50aaf35fef6912c4e2c +F src/btmutex.c 3e595ee1bb99e3a1f16824137b435ffc97c98e5f F src/btree.c 107723ed4f9bdb55213ba6164c30c49af75f4bf9 -F src/btree.h 8d36f774ec4b1d0027b8966f8c03d9a72a518c14 -F src/btreeInt.h 29ab8a4172f12b04fac34c5a0b76d0df750ddc34 +F src/btree.h a840a20c1969391f98ee06960d5ee2dc460186b3 +F src/btreeInt.h 6714ce2f5e879eb9a904a6a4575dc4faa4f29991 F src/build.c 3a8c6c4b1e16798755d46e699b7fcc12b9f27b2b F src/callback.c 5069f224882cbdccd559f591271d28d7f37745bc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac @@ -235,11 +235,11 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c d975adcef86051b6b51c5d2394dd2288e0b0ca81 +F src/vdbe.c e4d83957b4d102d542fb249bb46c7b55cbb67e4f F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 -F src/vdbeInt.h 8ee9302ecc1036509956df8aceea6b0b5e0e231c +F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c ad921cf58e8c20e1c0a9ef0b7e0f557eabdc7d07 +F src/vdbeaux.c 1a98cc953a316739c3e9a2930ae0eee517d37def F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 28c5f12e98655d5c6167b13e8a15085eca43dd5b -R 62a2deace5cc72cdc4511f7f5b5d9fa5 +P e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 +R 5eec5b6c06a45dcfcec6cc2765ee2ab8 U drh -Z 905bef73ef8c243b27a93f7a5f38565e +Z 9f8e37bd1010a379addad04d1c835970 diff --git a/manifest.uuid b/manifest.uuid index b383b69990..34a2869ab5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 \ No newline at end of file +d81708f7d1eee399bfe76f6b8dac950a85dc2582 \ No newline at end of file diff --git a/src/btmutex.c b/src/btmutex.c index d772f4b50f..42d0bdcbc7 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -39,15 +39,34 @@ static void lockBtreeMutex(Btree *p){ ** clear the p->locked boolean. */ static void unlockBtreeMutex(Btree *p){ + BtShared *pBt = p->pBt; assert( p->locked==1 ); - assert( sqlite3_mutex_held(p->pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); assert( sqlite3_mutex_held(p->db->mutex) ); - assert( p->db==p->pBt->db ); + assert( p->db==pBt->db ); - sqlite3_mutex_leave(p->pBt->mutex); + pBt->iMutexCounter++; + sqlite3_mutex_leave(pBt->mutex); p->locked = 0; } +#ifdef SQLITE_DEBUG +/* +** Return the number of times that the mutex has been exited for +** the given btree. +** +** This is a small circular counter that wraps around to zero on +** overflow. It is used only for sanity checking - to verify that +** mutexes are held continously by asserting that the value of +** this counter at the beginning of a region is the same as at +** the end. +*/ +u32 sqlite3BtreeMutexCounter(Btree *p){ + assert( p->locked==1 || p->sharable==0 ); + return p->pBt->iMutexCounter; +} +#endif + /* ** Enter a mutex on the given BTree object. ** @@ -92,6 +111,24 @@ void sqlite3BtreeEnter(Btree *p){ p->wantToLock++; if( p->locked ) return; + /* Increment the mutex counter on all locked btrees in the same + ** database connection. This simulates the unlocking that would + ** occur on a worst-case mutex dead-lock avoidance scenario. + */ +#ifdef SQLITE_DEBUG + { + int ii; + sqlite3 *db = p->db; + Btree *pOther; + for(ii=0; iinDb; ii++){ + if( ii==1 ) continue; + pOther = db->aDb[ii].pBt; + if( pOther==0 || pOther->sharable==0 || pOther->locked==0 ) continue; + pOther->pBt->iMutexCounter++; + } + } +#endif + /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock ** procedure that follows. Just be sure not to block. @@ -251,97 +288,17 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ } #endif /* NDEBUG */ +#else /* SQLITE_THREADSAFE>0 above. SQLITE_THREADSAFE==0 below */ /* -** Add a new Btree pointer to a BtreeMutexArray. -** if the pointer can possibly be shared with -** another database connection. +** The following are special cases for mutex enter routines for use +** in single threaded applications that use shared cache. Except for +** these two routines, all mutex operations are no-ops in that case and +** are null #defines in btree.h. ** -** The pointers are kept in sorted order by pBtree->pBt. That -** way when we go to enter all the mutexes, we can enter them -** in order without every having to backup and retry and without -** worrying about deadlock. -** -** The number of shared btrees will always be small (usually 0 or 1) -** so an insertion sort is an adequate algorithm here. +** If shared cache is disabled, then all btree mutex routines, including +** the ones below, are no-ops and are null #defines in btree.h. */ -void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ - int i, j; - BtShared *pBt; - if( pBtree==0 || pBtree->sharable==0 ) return; -#ifndef NDEBUG - { - for(i=0; inMutex; i++){ - assert( pArray->aBtree[i]!=pBtree ); - } - } -#endif - assert( pArray->nMutex>=0 ); - assert( pArray->nMutexaBtree)-1 ); - pBt = pBtree->pBt; - for(i=0; inMutex; i++){ - assert( pArray->aBtree[i]!=pBtree ); - if( pArray->aBtree[i]->pBt>pBt ){ - for(j=pArray->nMutex; j>i; j--){ - pArray->aBtree[j] = pArray->aBtree[j-1]; - } - pArray->aBtree[i] = pBtree; - pArray->nMutex++; - return; - } - } - pArray->aBtree[pArray->nMutex++] = pBtree; -} -/* -** Enter the mutex of every btree in the array. This routine is -** called at the beginning of sqlite3VdbeExec(). The mutexes are -** exited at the end of the same function. -*/ -void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){ - int i; - for(i=0; inMutex; i++){ - Btree *p = pArray->aBtree[i]; - /* Some basic sanity checking */ - assert( i==0 || pArray->aBtree[i-1]->pBtpBt ); - assert( !p->locked || p->wantToLock>0 ); - - /* We should already hold a lock on the database connection */ - assert( sqlite3_mutex_held(p->db->mutex) ); - - /* The Btree is sharable because only sharable Btrees are entered - ** into the array in the first place. */ - assert( p->sharable ); - - p->wantToLock++; - if( !p->locked ){ - lockBtreeMutex(p); - } - } -} - -/* -** Leave the mutex of every btree in the group. -*/ -void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ - int i; - for(i=0; inMutex; i++){ - Btree *p = pArray->aBtree[i]; - /* Some basic sanity checking */ - assert( i==0 || pArray->aBtree[i-1]->pBtpBt ); - assert( p->locked ); - assert( p->wantToLock>0 ); - - /* We should already hold a lock on the database connection */ - assert( sqlite3_mutex_held(p->db->mutex) ); - - p->wantToLock--; - if( p->wantToLock==0 ){ - unlockBtreeMutex(p); - } - } -} - -#else void sqlite3BtreeEnter(Btree *p){ p->pBt->db = p->db; } diff --git a/src/btree.h b/src/btree.h index 468723b33e..4fd4f67685 100644 --- a/src/btree.h +++ b/src/btree.h @@ -39,18 +39,6 @@ typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtShared BtShared; -typedef struct BtreeMutexArray BtreeMutexArray; - -/* -** This structure records all of the Btrees that need to hold -** a mutex before we enter sqlite3VdbeExec(). The Btrees are -** are placed in aBtree[] in order of aBtree[]->pBt. That way, -** we can always lock and unlock them all quickly. -*/ -struct BtreeMutexArray { - int nMutex; - Btree *aBtree[SQLITE_MAX_ATTACHED+1]; -}; int sqlite3BtreeOpen( @@ -228,23 +216,19 @@ void sqlite3BtreeCursorList(Btree*); void sqlite3BtreeEnterCursor(BtCursor*); void sqlite3BtreeLeaveCursor(BtCursor*); void sqlite3BtreeLeaveAll(sqlite3*); - void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*); - void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*); - void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); #ifndef NDEBUG /* These routines are used inside assert() statements only. */ int sqlite3BtreeHoldsMutex(Btree*); int sqlite3BtreeHoldsAllMutexes(sqlite3*); + u32 sqlite3BtreeMutexCounter(Btree*); #endif #else # define sqlite3BtreeLeave(X) +# define sqlite3BtreeMutexCounter(X) 0 # define sqlite3BtreeEnterCursor(X) # define sqlite3BtreeLeaveCursor(X) # define sqlite3BtreeLeaveAll(X) -# define sqlite3BtreeMutexArrayEnter(X) -# define sqlite3BtreeMutexArrayLeave(X) -# define sqlite3BtreeMutexArrayInsert(X,Y) # define sqlite3BtreeHoldsMutex(X) 1 # define sqlite3BtreeHoldsAllMutexes(X) 1 diff --git a/src/btreeInt.h b/src/btreeInt.h index a645f4fb97..2aee063d39 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -426,7 +426,7 @@ struct BtShared { u32 nPage; /* Number of pages in the database */ void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ - sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ + sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */ Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */ #ifndef SQLITE_OMIT_SHARED_CACHE int nRef; /* Number of references to this structure */ @@ -435,6 +435,7 @@ struct BtShared { Btree *pWriter; /* Btree with currently open write transaction */ u8 isExclusive; /* True if pWriter has an EXCLUSIVE lock on the db */ u8 isPending; /* If waiting for read-locks to clear */ + u16 iMutexCounter; /* The number of mutex_leave(mutex) calls */ #endif u8 *pTmpSpace; /* BtShared.pageSize bytes of space for tmp use */ }; diff --git a/src/vdbe.c b/src/vdbe.c index e6118a4cb5..eff4d86cf9 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -571,7 +571,7 @@ int sqlite3VdbeExec( /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ - sqlite3VdbeMutexArrayEnter(p); + sqlite3VdbeEnter(p); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ @@ -1394,6 +1394,7 @@ case OP_Function: { ctx.pColl = pOp[-1].p4.pColl; } (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + sqlite3VdbeMutexResync(p); if( db->mallocFailed ){ /* Even though a malloc() has failed, the implementation of the ** user function may have called an sqlite3_result_XXX() function @@ -1404,6 +1405,17 @@ case OP_Function: { goto no_mem; } + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ +#if 0 + if( p->expired ){ + rc = SQLITE_ABORT; + break; + } +#endif + /* If any auxiliary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ @@ -2650,6 +2662,7 @@ case OP_Savepoint: { if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetInternalSchema(db, 0); + sqlite3VdbeMutexResync(p); db->flags = (db->flags | SQLITE_InternChanges); } } @@ -2940,6 +2953,7 @@ case OP_VerifyCookie: { */ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){ sqlite3ResetInternalSchema(db, pOp->p1); + sqlite3VdbeMutexResync(p); } p->expired = 1; @@ -4622,29 +4636,22 @@ case OP_ParseSchema: { char *zSql; InitData initData; + /* Any prepared statement that invokes this opcode will hold mutexes + ** on every btree. This is a prerequisite for invoking + ** sqlite3InitCallback(). + */ +#ifdef SQLITE_DEBUG + for(iDb=0; iDbnDb; iDb++){ + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + } +#endif + assert( p->btreeMask == ~(yDbMask)0 ); + + iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); - - /* When this opcode is invoked, it is guaranteed that the b-tree mutex - ** is held and the schema is loaded for database iDb. However, at the - ** start of the sqlite3_exec() call below, SQLite will invoke - ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the iDb - ** mutex may be temporarily released to avoid deadlock. If this happens, - ** then some other thread may delete the in-memory schema of database iDb - ** before the SQL statement runs. The schema will not be reloaded because - ** the db->init.busy flag is set. This can result in a "no such table: - ** sqlite_master" or "malformed database schema" error being returned to - ** the user. - ** - ** To avoid this, obtain all mutexes and check that no other thread has - ** deleted the schema before calling sqlite3_exec(). If we find that the - ** another thread has deleted the schema, there is no need to update it. - ** The updated schema will be loaded from disk when it is next required. - */ - assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); - sqlite3BtreeEnterAll(db); - if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){ + /* Used to be a conditional */ { zMaster = SCHEMA_TABLE(iDb); initData.db = db; initData.iDb = pOp->p1; @@ -4665,7 +4672,6 @@ case OP_ParseSchema: { db->init.busy = 0; } } - sqlite3BtreeLeaveAll(db); if( rc==SQLITE_NOMEM ){ goto no_mem; } @@ -5190,11 +5196,25 @@ case OP_AggStep: { ctx.pColl = pOp[-1].p4.pColl; } (ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */ + sqlite3VdbeMutexResync(p); if( ctx.isError ){ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s)); rc = ctx.isError; } + + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ +#if 0 + if( p->expired ){ + rc = SQLITE_ABORT; + break; + } +#endif + sqlite3VdbeMemRelease(&ctx.s); + break; } @@ -5216,8 +5236,11 @@ case OP_AggFinal: { pMem = &aMem[pOp->p1]; assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); + sqlite3VdbeMutexResync(p); if( rc ){ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(pMem)); + }else if( p->expired ){ + rc = SQLITE_ABORT; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); @@ -5294,7 +5317,7 @@ case OP_JournalMode: { /* out2-prerelease */ /* This opcode is used in two places: PRAGMA journal_mode and ATTACH. ** In PRAGMA journal_mode, the sqlite3VdbeUsesBtree() routine is called - ** when the statment is prepared and so p->aMutex.nMutex>0. All mutexes + ** when the statement is prepared and so p->btreeMask!=0. All mutexes ** are already acquired. But when used in ATTACH, sqlite3VdbeUsesBtree() ** is not called when the statement is prepared because it requires the ** iDb index of the database as a parameter, and the database has not @@ -5303,12 +5326,11 @@ case OP_JournalMode: { /* out2-prerelease */ ** No other mutexes are required by the ATTACH command so this is safe ** to do. */ - assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 || p->aMutex.nMutex==0 ); - if( p->aMutex.nMutex==0 ){ + if( p->btreeMask==0 ){ /* This occurs right after ATTACH. Get a mutex on the newly ATTACHed ** database. */ sqlite3VdbeUsesBtree(p, pOp->p1); - sqlite3VdbeMutexArrayEnter(p); + sqlite3VdbeEnter(p); } pBt = db->aDb[pOp->p1].pBt; @@ -5946,13 +5968,16 @@ vdbe_error_halt: sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; - if( resetSchemaOnFault ) sqlite3ResetInternalSchema(db, 0); + if( resetSchemaOnFault ){ + sqlite3ResetInternalSchema(db, 0); + sqlite3VdbeMutexResync(p); + } /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeLeave(p); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 5b361b5055..15e4a812a7 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -303,9 +303,9 @@ struct Vdbe { u8 isPrepareV2; /* True if prepared with prepare_v2() */ int nChange; /* Number of db changes made since last reset */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ + u32 iMutexCounter; /* Mutex counter upon sqlite3VdbeEnter() */ int iStatement; /* Statement number (or 0 if has not opened stmt) */ int aCounter[3]; /* Counters used by sqlite3_stmt_status() */ - BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */ #ifndef SQLITE_OMIT_TRACE i64 startTime; /* Time when query started - used for profiling */ #endif @@ -387,6 +387,9 @@ int sqlite3VdbeCloseStatement(Vdbe *, int); void sqlite3VdbeFrameDelete(VdbeFrame*); int sqlite3VdbeFrameRestore(VdbeFrame *); void sqlite3VdbeMemStoreType(Mem *pMem); +void sqlite3VdbeEnter(Vdbe*); +void sqlite3VdbeLeave(Vdbe*); +void sqlite3VdbeMutexResync(Vdbe*); #ifdef SQLITE_DEBUG void sqlite3VdbeMemPrepareToChange(Vdbe*,Mem*); @@ -398,12 +401,6 @@ int sqlite3VdbeCheckFk(Vdbe *, int); # define sqlite3VdbeCheckFk(p,i) 0 #endif -#ifndef SQLITE_OMIT_SHARED_CACHE -void sqlite3VdbeMutexArrayEnter(Vdbe *p); -#else -# define sqlite3VdbeMutexArrayEnter(p) -#endif - int sqlite3VdbeMemTranslate(Mem*, u8); #ifdef SQLITE_DEBUG void sqlite3VdbePrintSql(Vdbe*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index de02d021af..6710b32ab0 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -157,6 +157,11 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; p->expired = 0; + if( op==OP_ParseSchema ){ + /* Any program that uses the OP_ParseSchema opcode needs to lock + ** all btrees. */ + p->btreeMask = ~(yDbMask)0; + } #ifdef SQLITE_DEBUG pOp->zComment = 0; if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]); @@ -457,7 +462,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){ assert( aOp && !p->db->mallocFailed ); /* Check that sqlite3VdbeUsesBtree() was not called on this VM */ - assert( p->aMutex.nMutex==0 ); + assert( p->btreeMask==0 ); resolveP2Values(p, pnMaxArg); *pnOp = p->nOp; @@ -945,22 +950,123 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. ** -** The prepared statement has to know in advance which Btree objects -** will be used so that it can acquire mutexes on them all in sorted -** order (via sqlite3VdbeMutexArrayEnter(). Mutexes are acquired -** in order (and released in reverse order) to avoid deadlocks. +** The prepared statements need to know in advance the complete set of +** attached databases that they will be using. A mask of these databases +** is maintained in p->btreeMask and is used for locking and other purposes. */ void sqlite3VdbeUsesBtree(Vdbe *p, int i){ - yDbMask mask; assert( i>=0 && idb->nDb && ibtreeMask)*8 ); - mask = ((yDbMask)1)<btreeMask & mask)==0 ){ - p->btreeMask |= mask; - sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt); - } + p->btreeMask |= ((yDbMask)1)<db; + Db *aDb = db->aDb; + int nDb = db->nDb; + for(i=0, mask=1; ibtreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ + cntSum += sqlite3BtreeMutexCounter(aDb[i].pBt); + } + } +#endif + return cntSum; +} +#endif + +/* +** If SQLite is compiled to support shared-cache mode and to be threadsafe, +** this routine obtains the mutex associated with each BtShared structure +** that may be accessed by the VM passed as an argument. In doing so it also +** sets the BtShared.db member of each of the BtShared structures, ensuring +** that the correct busy-handler callback is invoked if required. +** +** If SQLite is not threadsafe but does support shared-cache mode, then +** sqlite3BtreeEnter() is invoked to set the BtShared.db variables +** of all of BtShared structures accessible via the database handle +** associated with the VM. +** +** If SQLite is not threadsafe and does not support shared-cache mode, this +** function is a no-op. +** +** The p->btreeMask field is a bitmask of all btrees that the prepared +** statement p will ever use. Let N be the number of bits in p->btreeMask +** corresponding to btrees that use shared cache. Then the runtime of +** this routine is N*N. But as N is rarely more than 1, this should not +** be a problem. +*/ +void sqlite3VdbeEnter(Vdbe *p){ +#ifndef SQLITE_OMIT_SHARED_CACHE + int i; + yDbMask mask; + sqlite3 *db = p->db; + Db *aDb = db->aDb; + int nDb = db->nDb; + for(i=0, mask=1; ibtreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ + sqlite3BtreeEnter(aDb[i].pBt); + } + } + p->iMutexCounter = mutexCounterSum(p); +#endif +} + +/* +** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter(). +*/ +void sqlite3VdbeLeave(Vdbe *p){ +#ifndef SQLITE_OMIT_SHARED_CACHE + int i; + yDbMask mask; + sqlite3 *db = p->db; + Db *aDb = db->aDb; + int nDb = db->nDb; + + /* Assert that the all mutexes have been held continously since + ** the most recent sqlite3VdbeEnter() or sqlite3VdbeMutexResync(). + */ + assert( mutexCounterSum(p) == p->iMutexCounter ); + + for(i=0, mask=1; ibtreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){ + sqlite3BtreeLeave(aDb[i].pBt); + } + } +#endif +} + +/* +** Recompute the sum of the mutex counters on all btrees used by the +** prepared statement p. +** +** Call this routine while holding a sqlite3VdbeEnter() after doing something +** that might cause one or more of the individual mutexes held by the +** prepared statement to be released. Calling sqlite3BtreeEnter() on +** any BtShared mutex which is not used by the prepared statement is one +** way to cause one or more of the mutexes in the prepared statement +** to be temporarily released. The anti-deadlocking logic in +** sqlite3BtreeEnter() can cause mutexes to be released temporarily then +** reacquired. +** +** Calling this routine is an acknowledgement that some of the individual +** mutexes in the prepared statement might have been released and reacquired. +** So checks to verify that mutex-protected content did not change +** unexpectedly should accompany any call to this routine. +*/ +void sqlite3VdbeMutexResync(Vdbe *p){ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && defined(SQLITE_DEBUG) + p->iMutexCounter = mutexCounterSum(p); +#endif +} #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* @@ -1959,33 +2065,6 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ return rc; } -/* -** If SQLite is compiled to support shared-cache mode and to be threadsafe, -** this routine obtains the mutex associated with each BtShared structure -** that may be accessed by the VM passed as an argument. In doing so it -** sets the BtShared.db member of each of the BtShared structures, ensuring -** that the correct busy-handler callback is invoked if required. -** -** If SQLite is not threadsafe but does support shared-cache mode, then -** sqlite3BtreeEnterAll() is invoked to set the BtShared.db variables -** of all of BtShared structures accessible via the database handle -** associated with the VM. Of course only a subset of these structures -** will be accessed by the VM, and we could use Vdbe.btreeMask to figure -** that subset out, but there is no advantage to doing so. -** -** If SQLite is not threadsafe and does not support shared-cache mode, this -** function is a no-op. -*/ -#ifndef SQLITE_OMIT_SHARED_CACHE -void sqlite3VdbeMutexArrayEnter(Vdbe *p){ -#if SQLITE_THREADSAFE - sqlite3BtreeMutexArrayEnter(&p->aMutex); -#else - sqlite3BtreeEnterAll(p->db); -#endif -} -#endif - /* ** This function is called when a transaction opened by the database ** handle associated with the VM passed as an argument is about to be @@ -2058,7 +2137,7 @@ int sqlite3VdbeHalt(Vdbe *p){ int isSpecialError; /* Set to true if a 'special' error */ /* Lock all btrees used by the statement */ - sqlite3VdbeMutexArrayEnter(p); + sqlite3VdbeEnter(p); /* Check for one of the special errors */ mrc = p->rc & 0xff; @@ -2112,7 +2191,7 @@ int sqlite3VdbeHalt(Vdbe *p){ rc = sqlite3VdbeCheckFk(p, 1); if( rc!=SQLITE_OK ){ if( NEVER(p->readOnly) ){ - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeLeave(p); return SQLITE_ERROR; } rc = SQLITE_CONSTRAINT; @@ -2124,7 +2203,7 @@ int sqlite3VdbeHalt(Vdbe *p){ rc = vdbeCommit(db, p); } if( rc==SQLITE_BUSY && p->readOnly ){ - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; @@ -2196,7 +2275,8 @@ int sqlite3VdbeHalt(Vdbe *p){ } /* Release the locks */ - sqlite3BtreeMutexArrayLeave(&p->aMutex); + sqlite3VdbeMutexResync(p); + sqlite3VdbeLeave(p); } /* We have successfully halted and closed the VM. Record this fact. */ From dfdc48e157103b6ba04a28c5a0bf08b84090cb1a Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 03:27:16 +0000 Subject: [PATCH 4/6] Suppress unused parameter warnings in sqlite3VdbeEnter() and related routines. FossilOrigin-Name: f8e98ab3062a6e56924a86e8f3204c30d0f3d906 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 54a041dd07..0f239ebce6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sBtreeMutexArray\sobject\s-\suse\sthe\sVdbe.btreeMask\sfield\sto\saccomplish\nthe\ssame\sresult.\s\sAdd\sa\sgeneration\scounter\sto\sbtree\smutexes\sin\sorder\sto\sassert\nthat\smutexes\sare\snever\stemporarily\sdropped\sover\sa\srange\sof\sinstructions\sin\sorder\nto\sdo\sdeadlock\savoidance\sin\ssome\ssubroutine.\s\sLock\sall\sbtrees\sin\sany\sVdbe\nprogram\sthat\suses\sOP_ParseSchema. -D 2011-04-04T00:14:43.936 +C Suppress\sunused\sparameter\swarnings\sin\ssqlite3VdbeEnter()\sand\srelated\sroutines. +D 2011-04-04T03:27:16.245 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -239,7 +239,7 @@ F src/vdbe.c e4d83957b4d102d542fb249bb46c7b55cbb67e4f F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c -F src/vdbeaux.c 1a98cc953a316739c3e9a2930ae0eee517d37def +F src/vdbeaux.c 010e4e67a5a577451b0220ea8903c9e279a43248 F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P e2a09ea73c76a0bec1e09d1fc11092517e3ebdf9 -R 5eec5b6c06a45dcfcec6cc2765ee2ab8 +P d81708f7d1eee399bfe76f6b8dac950a85dc2582 +R a4fe05a3c45b7dfebc2c0e1b1ce8761a U drh -Z 9f8e37bd1010a379addad04d1c835970 +Z 802ab81287251956931cb7c1ec2989a0 diff --git a/manifest.uuid b/manifest.uuid index 34a2869ab5..dc9d29b53a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d81708f7d1eee399bfe76f6b8dac950a85dc2582 \ No newline at end of file +f8e98ab3062a6e56924a86e8f3204c30d0f3d906 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 6710b32ab0..b28bac4f36 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -978,6 +978,8 @@ static u32 mutexCounterSum(Vdbe *p){ cntSum += sqlite3BtreeMutexCounter(aDb[i].pBt); } } +#else + UNUSED_PARAMETER(p); #endif return cntSum; } @@ -1017,6 +1019,8 @@ void sqlite3VdbeEnter(Vdbe *p){ } } p->iMutexCounter = mutexCounterSum(p); +#else + UNUSED_PARAMETER(p); #endif } @@ -1041,6 +1045,8 @@ void sqlite3VdbeLeave(Vdbe *p){ sqlite3BtreeLeave(aDb[i].pBt); } } +#else + UNUSED_PARAMETER(p); #endif } @@ -1065,6 +1071,8 @@ void sqlite3VdbeLeave(Vdbe *p){ void sqlite3VdbeMutexResync(Vdbe *p){ #if !defined(SQLITE_OMIT_SHARED_CACHE) && defined(SQLITE_DEBUG) p->iMutexCounter = mutexCounterSum(p); +#else + UNUSED_PARAMETER(p); #endif } From 26ec621a9f60b69224122df4010c0e774bb75623 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 4 Apr 2011 07:05:38 +0000 Subject: [PATCH 5/6] Changes to oserror.test and syscall.test so that they work with the in-memory journal permutation test. FossilOrigin-Name: 4e996f36c73c5e768a954394fcbbf5e17576c807 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- test/oserror.test | 12 ++++++++---- test/syscall.test | 6 ++++-- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 0f239ebce6..66bd679080 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Suppress\sunused\sparameter\swarnings\sin\ssqlite3VdbeEnter()\sand\srelated\sroutines. -D 2011-04-04T03:27:16.245 +C Changes\sto\soserror.test\sand\ssyscall.test\sso\sthat\sthey\swork\swith\sthe\sin-memory\sjournal\spermutation\stest. +D 2011-04-04T07:05:38.773 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -594,7 +594,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347 F test/null.test a8b09b8ed87852742343b33441a9240022108993 F test/omitunique.test bbb2ec4345d9125d9ee21cd9488d97a163020d5f F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec -F test/oserror.test 0abf1b4a935aae329b95da27388d7ca61aaea6f0 +F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f @@ -677,7 +677,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3 -F test/syscall.test b967e1f5405bb1c9e2e223dbf7d7cd35220589a3 +F test/syscall.test 02e5359bf4f5e6f716696318fde4e0b5c2c70d21 F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f F test/table.test 04ba066432430657712d167ebf28080fe878d305 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P d81708f7d1eee399bfe76f6b8dac950a85dc2582 -R a4fe05a3c45b7dfebc2c0e1b1ce8761a -U drh -Z 802ab81287251956931cb7c1ec2989a0 +P f8e98ab3062a6e56924a86e8f3204c30d0f3d906 +R f1bbd3f7ef415e82a6c1a2591a207c23 +U dan +Z 67d15952b786647f2d72d97293a23816 diff --git a/manifest.uuid b/manifest.uuid index dc9d29b53a..62255888e6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f8e98ab3062a6e56924a86e8f3204c30d0f3d906 \ No newline at end of file +4e996f36c73c5e768a954394fcbbf5e17576c807 \ No newline at end of file diff --git a/test/oserror.test b/test/oserror.test index 82a5d5f6ff..2d3a24a8f5 100644 --- a/test/oserror.test +++ b/test/oserror.test @@ -100,13 +100,17 @@ do_test 2.1.1 { set ::log [list] file mkdir test.db-wal forcedelete test.db - sqlite3 dbh test.db - catchsql { SELECT * FROM sqlite_master } dbh + list [catch { + sqlite3 dbh test.db + execsql { SELECT * FROM sqlite_master } dbh + } msg] $msg } {1 {disk I/O error}} -do_re_test 2.1.2 { lindex $::log 0 } {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - } +do_re_test 2.1.2 { + lindex $::log 0 +} {^os_unix.c:\d+: \(\d+\) unlink\(.*test.db-wal\) - } do_test 2.1.3 { - dbh close + catch { dbh close } forcedelete test.db-wal } {} diff --git a/test/syscall.test b/test/syscall.test index 95921bd35e..6aca75ec39 100644 --- a/test/syscall.test +++ b/test/syscall.test @@ -221,8 +221,10 @@ foreach {nByte res} { } { do_test 7.$nByte { create_db_file $nByte - sqlite3 db test.db - catchsql { CREATE TABLE t1(a, b) } + list [catch { + sqlite3 db test.db + execsql { CREATE TABLE t1(a, b) } + } msg] $msg } $res catch { db close } } From 7b94e7f8382b0a29b12e3ee2427331d41a6a0061 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 4 Apr 2011 12:29:20 +0000 Subject: [PATCH 6/6] Move the expired-statement test for OP_Function until after all memory has been freed. The test is still commented out, however. FossilOrigin-Name: 425e3edb146c497817855dd741878709a25c8b98 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 20 +++++++++----------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index 66bd679080..65800fd981 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\soserror.test\sand\ssyscall.test\sso\sthat\sthey\swork\swith\sthe\sin-memory\sjournal\spermutation\stest. -D 2011-04-04T07:05:38.773 +C Move\sthe\sexpired-statement\stest\sfor\sOP_Function\suntil\safter\sall\smemory\shas\nbeen\sfreed.\s\sThe\stest\sis\sstill\scommented\sout,\showever. +D 2011-04-04T12:29:20.265 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -235,7 +235,7 @@ F src/update.c 81911be16ece3c3e7716aa18565b4814ec41f8b9 F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60 F src/util.c cd997077bad039efc0597eb027c929658f93c018 F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c e4d83957b4d102d542fb249bb46c7b55cbb67e4f +F src/vdbe.c 6488f759929602cbc3acea5e9c7c10e2d2cd00ed F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 7e2f028ecc1a9faa6f253e7aa8d89cae03662bae F src/vdbeapi.c a09ad9164cafc505250d5dd6b69660c960f1308c @@ -926,7 +926,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f8e98ab3062a6e56924a86e8f3204c30d0f3d906 -R f1bbd3f7ef415e82a6c1a2591a207c23 -U dan -Z 67d15952b786647f2d72d97293a23816 +P 4e996f36c73c5e768a954394fcbbf5e17576c807 +R 4c64876ffe2c0a670add1f1b62152ed8 +U drh +Z badc0ef9dd3fcc800ebaf4f50ec0d36c diff --git a/manifest.uuid b/manifest.uuid index 62255888e6..3a4413c91a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4e996f36c73c5e768a954394fcbbf5e17576c807 \ No newline at end of file +425e3edb146c497817855dd741878709a25c8b98 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index eff4d86cf9..4bfe518a9c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1405,17 +1405,6 @@ case OP_Function: { goto no_mem; } - /* The app-defined function has done something that as caused this - ** statement to expire. (Perhaps the function called sqlite3_exec() - ** with a CREATE TABLE statement.) - */ -#if 0 - if( p->expired ){ - rc = SQLITE_ABORT; - break; - } -#endif - /* If any auxiliary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ @@ -1437,6 +1426,15 @@ case OP_Function: { if( sqlite3VdbeMemTooBig(pOut) ){ goto too_big; } + +#if 0 + /* The app-defined function has done something that as caused this + ** statement to expire. (Perhaps the function called sqlite3_exec() + ** with a CREATE TABLE statement.) + */ + if( p->expired ) rc = SQLITE_ABORT; +#endif + REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); break;