mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Add some assert() statements and fix small issues with code on this branch.
FossilOrigin-Name: bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\sa\sproblem\son\sthis\sbranch\scausing\scheckpoints\sthat\sdo\snot\sproceed\sbecause\sthey\scan't\sget\sthe\sCHECKPOINT\slock\sto\sreturn\sincorrect\soutput\svalues.
|
||||
D 2021-08-20T11:50:12.817
|
||||
C Add\ssome\sassert()\sstatements\sand\sfix\ssmall\sissues\swith\scode\son\sthis\sbranch.
|
||||
D 2021-08-20T16:19:19.544
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7
|
||||
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
|
||||
F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 42c64a0c198c0610a4f54158faff9ad8b0f3f390cb03c1a69692dc70f886b711
|
||||
F src/wal.c d47742fa0d58fa622416cfd105b4b309f39006f30d903e02db2f48236f3d83d7
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
|
||||
F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5
|
||||
@@ -1921,7 +1921,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 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f
|
||||
R 97abf4da384cedc02121f231f21869ab
|
||||
P 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa
|
||||
R eab33be79c818813f4366ae19768ee1d
|
||||
U dan
|
||||
Z 53bdf1f79fced94468e78efd135afd05
|
||||
Z 8887602c0a0185b63b60ad6538fd96e1
|
||||
|
@@ -1 +1 @@
|
||||
5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa
|
||||
bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45
|
110
src/wal.c
110
src/wal.c
@@ -528,10 +528,10 @@ struct Wal {
|
||||
u32 iReCksum; /* On commit, recalculate checksums from here */
|
||||
const char *zWalName; /* Name of WAL file */
|
||||
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
|
||||
#ifdef SQLITE_USE_SEH
|
||||
# ifdef SQLITE_DEBUG
|
||||
int nSehTry; /* Number of nested SEH_TRY{} blocks */
|
||||
# endif
|
||||
#ifdef SQLITE_USE_SEH
|
||||
u32 lockMask; /* Mask of locks held */
|
||||
void *pFree; /* Pointer to sqlite3_free() if exception thrown */
|
||||
#endif
|
||||
@@ -622,9 +622,12 @@ struct WalIterator {
|
||||
#include <Windows.h>
|
||||
|
||||
# define SEH_TRY __try { \
|
||||
assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++);
|
||||
assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \
|
||||
TESTONLY(pWal->nSehTry++);
|
||||
|
||||
# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \
|
||||
# define SEH_EXCEPT(X) \
|
||||
TESTONLY(pWal->nSehTry--); \
|
||||
assert( pWal->nSehTry==0 ); \
|
||||
} __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X }
|
||||
|
||||
# define SEH_INJECT_FAULT sehInjectFault(pWal)
|
||||
@@ -643,6 +646,12 @@ static int sehExceptionFilter(Wal *pWal, int eCode){
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
/*
|
||||
** If one is configured, invoke the xTestCallback callback with 650 as
|
||||
** the argument. If it returns true, throw the same exception that is
|
||||
** thrown by the system if the *-shm file mapping is accessed after it
|
||||
** has been invalidated.
|
||||
*/
|
||||
static void sehInjectFault(Wal *pWal){
|
||||
assert( pWal->nSehTry>0 );
|
||||
if( sqlite3FaultSim(650) ){
|
||||
@@ -650,13 +659,27 @@ static void sehInjectFault(Wal *pWal){
|
||||
}
|
||||
}
|
||||
|
||||
#define SEH_FREE_ON_ERROR(X) pWal->pFree = X
|
||||
/*
|
||||
** There are two ways to use this macro. To set a pointer to be freed
|
||||
** if an exception is thrown:
|
||||
**
|
||||
** SEH_FREE_ON_ERROR(0, pPtr);
|
||||
**
|
||||
** and to cancel the same:
|
||||
**
|
||||
** SEH_FREE_ON_ERROR(pPtr, 0);
|
||||
**
|
||||
** In the first case, there must not already be a pointer registered to
|
||||
** be freed. In the second case, pPtr must be the registered pointer.
|
||||
*/
|
||||
#define SEH_FREE_ON_ERROR(X,Y) \
|
||||
assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y
|
||||
|
||||
#else
|
||||
# define SEH_TRY
|
||||
# define SEH_EXCEPT(X)
|
||||
# define SEH_INJECT_FAULT
|
||||
# define SEH_FREE_ON_ERROR(X)
|
||||
# define SEH_TRY TESTONLY(pWal->nSehTry++);
|
||||
# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 );
|
||||
# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 );
|
||||
# define SEH_FREE_ON_ERROR(X,Y)
|
||||
#endif /* ifdef SQLITE_USE_SEH */
|
||||
|
||||
|
||||
@@ -1369,7 +1392,7 @@ static int walIndexRecover(Wal *pWal){
|
||||
/* Malloc a buffer to read frames into. */
|
||||
szFrame = szPage + WAL_FRAME_HDRSIZE;
|
||||
aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ);
|
||||
SEH_FREE_ON_ERROR(aFrame);
|
||||
SEH_FREE_ON_ERROR(0, aFrame);
|
||||
if( !aFrame ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto recovery_error;
|
||||
@@ -1447,8 +1470,8 @@ static int walIndexRecover(Wal *pWal){
|
||||
if( iFrame<=iLast ) break;
|
||||
}
|
||||
|
||||
SEH_FREE_ON_ERROR(aFrame, 0);
|
||||
sqlite3_free(aFrame);
|
||||
SEH_FREE_ON_ERROR(0);
|
||||
}
|
||||
|
||||
finished:
|
||||
@@ -1867,7 +1890,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
||||
memset(p, 0, nByte);
|
||||
p->nSegment = nSegment;
|
||||
aTmp = (ht_slot*)&(((u8*)p)[nByte]);
|
||||
SEH_FREE_ON_ERROR(p);
|
||||
SEH_FREE_ON_ERROR(0, p);
|
||||
|
||||
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
|
||||
WalHashLoc sLoc;
|
||||
@@ -1899,9 +1922,9 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
SEH_FREE_ON_ERROR(p, 0);
|
||||
walIteratorFree(p);
|
||||
p = 0;
|
||||
SEH_FREE_ON_ERROR(0);
|
||||
}
|
||||
*pp = p;
|
||||
return rc;
|
||||
@@ -2266,10 +2289,7 @@ static int walCheckpoint(
|
||||
}
|
||||
|
||||
walcheckpoint_out:
|
||||
#ifdef SQLITE_USE_SEH
|
||||
assert( pWal->pFree==(void*)pIter );
|
||||
pWal->pFree = 0;
|
||||
#endif
|
||||
SEH_FREE_ON_ERROR(pIter, 0);
|
||||
walIteratorFree(pIter);
|
||||
return rc;
|
||||
}
|
||||
@@ -2306,9 +2326,7 @@ int sqlite3WalClose(
|
||||
if( pWal ){
|
||||
int isDelete = 0; /* True to unlink wal and wal-index files */
|
||||
|
||||
#ifdef SQLITE_USE_SEH
|
||||
assert( pWal->lockMask==0 );
|
||||
#endif
|
||||
assert( walAssertLockmask(pWal) );
|
||||
|
||||
/* If an EXCLUSIVE lock can be obtained on the database file (using the
|
||||
** ordinary, rollback-mode locking methods, this guarantees that the
|
||||
@@ -3020,6 +3038,13 @@ static int walHandleException(Wal *pWal){
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Assert that the Wal.lockMask mask, which indicates the locks held
|
||||
** by the connenction, is consistent with the Wal.readLock, Wal.writeLock
|
||||
** and Wal.ckptLock variables. To be used as:
|
||||
**
|
||||
** assert( walAssertLockmask(pWal) );
|
||||
*/
|
||||
static int walAssertLockmask(Wal *pWal){
|
||||
if( pWal->exclusiveMode==0 ){
|
||||
static const int S = 1;
|
||||
@@ -3134,18 +3159,8 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
/*
|
||||
** Begin a read transaction on the database.
|
||||
**
|
||||
** This routine used to be called sqlite3OpenSnapshot() and with good reason:
|
||||
** it takes a snapshot of the state of the WAL and wal-index for the current
|
||||
** instant in time. The current thread will continue to use this snapshot.
|
||||
** Other threads might append new content to the WAL and wal-index but
|
||||
** that extra content is ignored by the current thread.
|
||||
**
|
||||
** If the database contents have changes since the previous read
|
||||
** transaction, then *pChanged is set to 1 before returning. The
|
||||
** Pager layer will use this to know that its cache is stale and
|
||||
** needs to be flushed.
|
||||
** This function does the work of sqlite3WalBeginReadTransaction() (see
|
||||
** below). That function simply calls this one inside an SEH_TRY{...} block.
|
||||
*/
|
||||
static int walBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
int rc; /* Return code */
|
||||
@@ -3157,6 +3172,7 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
#endif
|
||||
|
||||
assert( pWal->ckptLock==0 );
|
||||
assert( pWal->nSehTry>0 );
|
||||
|
||||
#ifdef SQLITE_ENABLE_SNAPSHOT
|
||||
if( pSnapshot ){
|
||||
@@ -3251,6 +3267,20 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Begin a read transaction on the database.
|
||||
**
|
||||
** This routine used to be called sqlite3OpenSnapshot() and with good reason:
|
||||
** it takes a snapshot of the state of the WAL and wal-index for the current
|
||||
** instant in time. The current thread will continue to use this snapshot.
|
||||
** Other threads might append new content to the WAL and wal-index but
|
||||
** that extra content is ignored by the current thread.
|
||||
**
|
||||
** If the database contents have changes since the previous read
|
||||
** transaction, then *pChanged is set to 1 before returning. The
|
||||
** Pager layer will use this to know that its cache is stale and
|
||||
** needs to be flushed.
|
||||
*/
|
||||
int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
||||
int rc;
|
||||
SEH_TRY {
|
||||
@@ -3380,6 +3410,17 @@ static int walFindFrame(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Search the wal file for page pgno. If found, set *piRead to the frame that
|
||||
** contains the page. Otherwise, if pgno is not in the wal file, set *piRead
|
||||
** to zero.
|
||||
**
|
||||
** Return SQLITE_OK if successful, or an error code if an error occurs. If an
|
||||
** error does occur, the final value of *piRead is undefined.
|
||||
**
|
||||
** The difference between this function and walFindFrame() is that this
|
||||
** function wraps walFindFrame() in an SEH_TRY{...} block.
|
||||
*/
|
||||
int sqlite3WalFindFrame(
|
||||
Wal *pWal, /* WAL handle */
|
||||
Pgno pgno, /* Database page number to read data for */
|
||||
@@ -4002,6 +4043,13 @@ static int walFrames(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write a set of frames to the log. The caller must hold the write-lock
|
||||
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
|
||||
**
|
||||
** The difference between this function and walFrames() is that this
|
||||
** function wraps walFrames() in an SEH_TRY{...} block.
|
||||
*/
|
||||
int sqlite3WalFrames(
|
||||
Wal *pWal, /* Wal handle to write to */
|
||||
int szPage, /* Database page-size in bytes */
|
||||
|
Reference in New Issue
Block a user