Index: third_party/sqlite/src/src/test_vfs.c |
diff --git a/third_party/sqlite/src/src/test_vfs.c b/third_party/sqlite/src/src/test_vfs.c |
index 64b3cb574b5eb81cb33c8a4125fc53a99426285d..7ee2a93453f56913b7911e706c325f56e17026fc 100644 |
--- a/third_party/sqlite/src/src/test_vfs.c |
+++ b/third_party/sqlite/src/src/test_vfs.c |
@@ -10,10 +10,6 @@ |
** |
****************************************************************************** |
** |
-*/ |
-#if SQLITE_TEST /* This file is used for testing only */ |
- |
-/* |
** This file contains the implementation of the Tcl [testvfs] command, |
** used to create SQLite VFS implementations with various properties and |
** instrumentation to support testing SQLite. |
@@ -28,9 +24,11 @@ |
** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname) |
** -iversion INTEGER (Value for sqlite3_vfs.iVersion) |
*/ |
+#if SQLITE_TEST /* This file is used for testing only */ |
#include "sqlite3.h" |
#include "sqliteInt.h" |
+#include <tcl.h> |
typedef struct Testvfs Testvfs; |
typedef struct TestvfsShm TestvfsShm; |
@@ -82,10 +80,9 @@ struct Testvfs { |
sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ |
Tcl_Interp *interp; /* Interpreter to run script in */ |
Tcl_Obj *pScript; /* Script to execute */ |
- int nScript; /* Number of elements in array apScript */ |
- Tcl_Obj **apScript; /* Array version of pScript */ |
TestvfsBuffer *pBuffer; /* List of shared buffers */ |
int isNoshm; |
+ int isFullshm; |
int mask; /* Mask controlling [script] and [ioerr] */ |
@@ -114,20 +111,26 @@ struct Testvfs { |
** + Simulating IO errors, and |
** + Invoking the Tcl callback script. |
*/ |
-#define TESTVFS_SHMOPEN_MASK 0x00000001 |
-#define TESTVFS_SHMLOCK_MASK 0x00000010 |
-#define TESTVFS_SHMMAP_MASK 0x00000020 |
-#define TESTVFS_SHMBARRIER_MASK 0x00000040 |
-#define TESTVFS_SHMCLOSE_MASK 0x00000080 |
- |
-#define TESTVFS_OPEN_MASK 0x00000100 |
-#define TESTVFS_SYNC_MASK 0x00000200 |
-#define TESTVFS_DELETE_MASK 0x00000400 |
-#define TESTVFS_CLOSE_MASK 0x00000800 |
-#define TESTVFS_WRITE_MASK 0x00001000 |
-#define TESTVFS_TRUNCATE_MASK 0x00002000 |
-#define TESTVFS_ACCESS_MASK 0x00004000 |
-#define TESTVFS_ALL_MASK 0x00007FFF |
+#define TESTVFS_SHMOPEN_MASK 0x00000001 |
+#define TESTVFS_SHMLOCK_MASK 0x00000010 |
+#define TESTVFS_SHMMAP_MASK 0x00000020 |
+#define TESTVFS_SHMBARRIER_MASK 0x00000040 |
+#define TESTVFS_SHMCLOSE_MASK 0x00000080 |
+ |
+#define TESTVFS_OPEN_MASK 0x00000100 |
+#define TESTVFS_SYNC_MASK 0x00000200 |
+#define TESTVFS_DELETE_MASK 0x00000400 |
+#define TESTVFS_CLOSE_MASK 0x00000800 |
+#define TESTVFS_WRITE_MASK 0x00001000 |
+#define TESTVFS_TRUNCATE_MASK 0x00002000 |
+#define TESTVFS_ACCESS_MASK 0x00004000 |
+#define TESTVFS_FULLPATHNAME_MASK 0x00008000 |
+#define TESTVFS_READ_MASK 0x00010000 |
+#define TESTVFS_UNLOCK_MASK 0x00020000 |
+#define TESTVFS_LOCK_MASK 0x00040000 |
+#define TESTVFS_CKLOCK_MASK 0x00080000 |
+ |
+#define TESTVFS_ALL_MASK 0x000FFFFF |
#define TESTVFS_MAX_PAGES 1024 |
@@ -190,8 +193,11 @@ static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **); |
static void tvfsShmBarrier(sqlite3_file*); |
static int tvfsShmUnmap(sqlite3_file*, int); |
+static int tvfsFetch(sqlite3_file*, sqlite3_int64, int, void**); |
+static int tvfsUnfetch(sqlite3_file*, sqlite3_int64, void*); |
+ |
static sqlite3_io_methods tvfs_io_methods = { |
- 2, /* iVersion */ |
+ 3, /* iVersion */ |
tvfsClose, /* xClose */ |
tvfsRead, /* xRead */ |
tvfsWrite, /* xWrite */ |
@@ -207,7 +213,9 @@ static sqlite3_io_methods tvfs_io_methods = { |
tvfsShmMap, /* xShmMap */ |
tvfsShmLock, /* xShmLock */ |
tvfsShmBarrier, /* xShmBarrier */ |
- tvfsShmUnmap /* xShmUnmap */ |
+ tvfsShmUnmap, /* xShmUnmap */ |
+ tvfsFetch, |
+ tvfsUnfetch |
}; |
static int tvfsResultCode(Testvfs *p, int *pRc){ |
@@ -266,51 +274,31 @@ static void tvfsExecTcl( |
const char *zMethod, |
Tcl_Obj *arg1, |
Tcl_Obj *arg2, |
- Tcl_Obj *arg3 |
+ Tcl_Obj *arg3, |
+ Tcl_Obj *arg4 |
){ |
int rc; /* Return code from Tcl_EvalObj() */ |
- int nArg; /* Elements in eval'd list */ |
- int nScript; |
- Tcl_Obj ** ap; |
- |
+ Tcl_Obj *pEval; |
assert( p->pScript ); |
- if( !p->apScript ){ |
- int nByte; |
- int i; |
- if( TCL_OK!=Tcl_ListObjGetElements(p->interp, p->pScript, &nScript, &ap) ){ |
- Tcl_BackgroundError(p->interp); |
- Tcl_ResetResult(p->interp); |
- return; |
- } |
- p->nScript = nScript; |
- nByte = (nScript+TESTVFS_MAX_ARGS)*sizeof(Tcl_Obj *); |
- p->apScript = (Tcl_Obj **)ckalloc(nByte); |
- memset(p->apScript, 0, nByte); |
- for(i=0; i<nScript; i++){ |
- p->apScript[i] = ap[i]; |
- } |
- } |
- |
- p->apScript[p->nScript] = Tcl_NewStringObj(zMethod, -1); |
- p->apScript[p->nScript+1] = arg1; |
- p->apScript[p->nScript+2] = arg2; |
- p->apScript[p->nScript+3] = arg3; |
+ assert( zMethod ); |
+ assert( p ); |
+ assert( arg2==0 || arg1!=0 ); |
+ assert( arg3==0 || arg2!=0 ); |
- for(nArg=p->nScript; p->apScript[nArg]; nArg++){ |
- Tcl_IncrRefCount(p->apScript[nArg]); |
- } |
+ pEval = Tcl_DuplicateObj(p->pScript); |
+ Tcl_IncrRefCount(p->pScript); |
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1)); |
+ if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1); |
+ if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2); |
+ if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3); |
+ if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4); |
- rc = Tcl_EvalObjv(p->interp, nArg, p->apScript, TCL_EVAL_GLOBAL); |
+ rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); |
if( rc!=TCL_OK ){ |
Tcl_BackgroundError(p->interp); |
Tcl_ResetResult(p->interp); |
} |
- |
- for(nArg=p->nScript; p->apScript[nArg]; nArg++){ |
- Tcl_DecrRefCount(p->apScript[nArg]); |
- p->apScript[nArg] = 0; |
- } |
} |
@@ -325,7 +313,7 @@ static int tvfsClose(sqlite3_file *pFile){ |
if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ |
tvfsExecTcl(p, "xClose", |
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 |
+ Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 |
); |
} |
@@ -351,8 +339,22 @@ static int tvfsRead( |
int iAmt, |
sqlite_int64 iOfst |
){ |
- TestvfsFd *p = tvfsGetFd(pFile); |
- return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); |
+ int rc = SQLITE_OK; |
+ TestvfsFd *pFd = tvfsGetFd(pFile); |
+ Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; |
+ if( p->pScript && p->mask&TESTVFS_READ_MASK ){ |
+ tvfsExecTcl(p, "xRead", |
+ Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 |
+ ); |
+ tvfsResultCode(p, &rc); |
+ } |
+ if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){ |
+ rc = SQLITE_IOERR; |
+ } |
+ if( rc==SQLITE_OK ){ |
+ rc = sqlite3OsRead(pFd->pReal, zBuf, iAmt, iOfst); |
+ } |
+ return rc; |
} |
/* |
@@ -370,7 +372,8 @@ static int tvfsWrite( |
if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ |
tvfsExecTcl(p, "xWrite", |
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 |
+ Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, |
+ Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt) |
); |
tvfsResultCode(p, &rc); |
} |
@@ -398,7 +401,7 @@ static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ |
if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ |
tvfsExecTcl(p, "xTruncate", |
- Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 |
+ Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 |
); |
tvfsResultCode(p, &rc); |
} |
@@ -439,7 +442,7 @@ static int tvfsSync(sqlite3_file *pFile, int flags){ |
tvfsExecTcl(p, "xSync", |
Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, |
- Tcl_NewStringObj(zFlags, -1) |
+ Tcl_NewStringObj(zFlags, -1), 0 |
); |
tvfsResultCode(p, &rc); |
} |
@@ -465,24 +468,46 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ |
** Lock an tvfs-file. |
*/ |
static int tvfsLock(sqlite3_file *pFile, int eLock){ |
- TestvfsFd *p = tvfsGetFd(pFile); |
- return sqlite3OsLock(p->pReal, eLock); |
+ TestvfsFd *pFd = tvfsGetFd(pFile); |
+ Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; |
+ if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){ |
+ char zLock[30]; |
+ sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock); |
+ tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1), |
+ Tcl_NewStringObj(zLock, -1), 0, 0); |
+ } |
+ return sqlite3OsLock(pFd->pReal, eLock); |
} |
/* |
** Unlock an tvfs-file. |
*/ |
static int tvfsUnlock(sqlite3_file *pFile, int eLock){ |
- TestvfsFd *p = tvfsGetFd(pFile); |
- return sqlite3OsUnlock(p->pReal, eLock); |
+ TestvfsFd *pFd = tvfsGetFd(pFile); |
+ Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; |
+ if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){ |
+ char zLock[30]; |
+ sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock); |
+ tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1), |
+ Tcl_NewStringObj(zLock, -1), 0, 0); |
+ } |
+ if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){ |
+ return SQLITE_IOERR_UNLOCK; |
+ } |
+ return sqlite3OsUnlock(pFd->pReal, eLock); |
} |
/* |
** Check if another file-handle holds a RESERVED lock on an tvfs-file. |
*/ |
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |
- TestvfsFd *p = tvfsGetFd(pFile); |
- return sqlite3OsCheckReservedLock(p->pReal, pResOut); |
+ TestvfsFd *pFd = tvfsGetFd(pFile); |
+ Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; |
+ if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){ |
+ tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1), |
+ 0, 0, 0); |
+ } |
+ return sqlite3OsCheckReservedLock(pFd->pReal, pResOut); |
} |
/* |
@@ -490,6 +515,27 @@ static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |
*/ |
static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ |
TestvfsFd *p = tvfsGetFd(pFile); |
+ if( op==SQLITE_FCNTL_PRAGMA ){ |
+ char **argv = (char**)pArg; |
+ if( sqlite3_stricmp(argv[1],"error")==0 ){ |
+ int rc = SQLITE_ERROR; |
+ if( argv[2] ){ |
+ const char *z = argv[2]; |
+ int x = atoi(z); |
+ if( x ){ |
+ rc = x; |
+ while( sqlite3Isdigit(z[0]) ){ z++; } |
+ while( sqlite3Isspace(z[0]) ){ z++; } |
+ } |
+ if( z[0] ) argv[0] = sqlite3_mprintf("%s", z); |
+ } |
+ return rc; |
+ } |
+ if( sqlite3_stricmp(argv[1], "filename")==0 ){ |
+ argv[0] = sqlite3_mprintf("%s", p->zFilename); |
+ return SQLITE_OK; |
+ } |
+ } |
return sqlite3OsFileControl(p->pReal, op, pArg); |
} |
@@ -545,7 +591,7 @@ static int tvfsOpen( |
/* Evaluate the Tcl script: |
** |
- ** SCRIPT xOpen FILENAME |
+ ** SCRIPT xOpen FILENAME KEY-VALUE-ARGS |
** |
** If the script returns an SQLite error code other than SQLITE_OK, an |
** error is returned to the caller. If it returns SQLITE_OK, the new |
@@ -554,7 +600,19 @@ static int tvfsOpen( |
*/ |
Tcl_ResetResult(p->interp); |
if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){ |
- tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); |
+ Tcl_Obj *pArg = Tcl_NewObj(); |
+ Tcl_IncrRefCount(pArg); |
+ if( flags&SQLITE_OPEN_MAIN_DB ){ |
+ const char *z = &zName[strlen(zName)+1]; |
+ while( *z ){ |
+ Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); |
+ z += strlen(z) + 1; |
+ Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); |
+ z += strlen(z) + 1; |
+ } |
+ } |
+ tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0); |
+ Tcl_DecrRefCount(pArg); |
if( tvfsResultCode(p, &rc) ){ |
if( rc!=SQLITE_OK ) return rc; |
}else{ |
@@ -586,7 +644,10 @@ static int tvfsOpen( |
pMethods = (sqlite3_io_methods *)ckalloc(nByte); |
memcpy(pMethods, &tvfs_io_methods, nByte); |
- pMethods->iVersion = pVfs->iVersion; |
+ pMethods->iVersion = pFd->pReal->pMethods->iVersion; |
+ if( pMethods->iVersion>pVfs->iVersion ){ |
+ pMethods->iVersion = pVfs->iVersion; |
+ } |
if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){ |
pMethods->xShmUnmap = 0; |
pMethods->xShmLock = 0; |
@@ -610,7 +671,7 @@ static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ |
tvfsExecTcl(p, "xDelete", |
- Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0 |
+ Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0 |
); |
tvfsResultCode(p, &rc); |
} |
@@ -638,7 +699,7 @@ static int tvfsAccess( |
if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; |
if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; |
tvfsExecTcl(p, "xAccess", |
- Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0 |
+ Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0 |
); |
if( tvfsResultCode(p, &rc) ){ |
if( rc!=SQLITE_OK ) return rc; |
@@ -663,6 +724,14 @@ static int tvfsFullPathname( |
int nOut, |
char *zOut |
){ |
+ Testvfs *p = (Testvfs *)pVfs->pAppData; |
+ if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ |
+ int rc; |
+ tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0); |
+ if( tvfsResultCode(p, &rc) ){ |
+ if( rc!=SQLITE_OK ) return rc; |
+ } |
+ } |
return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); |
} |
@@ -729,6 +798,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){ |
pFd = tvfsGetFd(pFile); |
p = (Testvfs *)pFd->pVfs->pAppData; |
+ assert( 0==p->isFullshm ); |
assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 ); |
/* Evaluate the Tcl script: |
@@ -737,7 +807,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){ |
*/ |
Tcl_ResetResult(p->interp); |
if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){ |
- tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); |
+ tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0); |
if( tvfsResultCode(p, &rc) ){ |
if( rc!=SQLITE_OK ) return rc; |
} |
@@ -753,7 +823,7 @@ static int tvfsShmOpen(sqlite3_file *pFile){ |
if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; |
} |
if( !pBuffer ){ |
- int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1; |
+ int nByte = sizeof(TestvfsBuffer) + (int)strlen(pFd->zFilename) + 1; |
pBuffer = (TestvfsBuffer *)ckalloc(nByte); |
memset(pBuffer, 0, nByte); |
pBuffer->zFile = (char *)&pBuffer[1]; |
@@ -789,6 +859,10 @@ static int tvfsShmMap( |
TestvfsFd *pFd = tvfsGetFd(pFile); |
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); |
+ if( p->isFullshm ){ |
+ return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp); |
+ } |
+ |
if( 0==pFd->pShm ){ |
rc = tvfsShmOpen(pFile); |
if( rc!=SQLITE_OK ){ |
@@ -803,7 +877,7 @@ static int tvfsShmMap( |
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); |
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite)); |
tvfsExecTcl(p, "xShmMap", |
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg |
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0 |
); |
tvfsResultCode(p, &rc); |
Tcl_DecrRefCount(pArg); |
@@ -833,15 +907,19 @@ static int tvfsShmLock( |
int nLock; |
char zLock[80]; |
+ if( p->isFullshm ){ |
+ return sqlite3OsShmLock(pFd->pReal, ofst, n, flags); |
+ } |
+ |
if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ |
sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); |
- nLock = strlen(zLock); |
+ nLock = (int)strlen(zLock); |
if( flags & SQLITE_SHM_LOCK ){ |
strcpy(&zLock[nLock], " lock"); |
}else{ |
strcpy(&zLock[nLock], " unlock"); |
} |
- nLock += strlen(&zLock[nLock]); |
+ nLock += (int)strlen(&zLock[nLock]); |
if( flags & SQLITE_SHM_SHARED ){ |
strcpy(&zLock[nLock], " shared"); |
}else{ |
@@ -849,7 +927,7 @@ static int tvfsShmLock( |
} |
tvfsExecTcl(p, "xShmLock", |
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, |
- Tcl_NewStringObj(zLock, -1) |
+ Tcl_NewStringObj(zLock, -1), 0 |
); |
tvfsResultCode(p, &rc); |
} |
@@ -888,9 +966,14 @@ static void tvfsShmBarrier(sqlite3_file *pFile){ |
TestvfsFd *pFd = tvfsGetFd(pFile); |
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); |
+ if( p->isFullshm ){ |
+ sqlite3OsShmBarrier(pFd->pReal); |
+ return; |
+ } |
+ |
if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ |
tvfsExecTcl(p, "xShmBarrier", |
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 |
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 |
); |
} |
} |
@@ -905,12 +988,16 @@ static int tvfsShmUnmap( |
TestvfsBuffer *pBuffer = pFd->pShm; |
TestvfsFd **ppFd; |
+ if( p->isFullshm ){ |
+ return sqlite3OsShmUnmap(pFd->pReal, deleteFlag); |
+ } |
+ |
if( !pBuffer ) return SQLITE_OK; |
assert( pFd->pShmId && pFd->pShm ); |
if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ |
tvfsExecTcl(p, "xShmUnmap", |
- Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 |
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 |
); |
tvfsResultCode(p, &rc); |
} |
@@ -935,6 +1022,21 @@ static int tvfsShmUnmap( |
return rc; |
} |
+static int tvfsFetch( |
+ sqlite3_file *pFile, |
+ sqlite3_int64 iOfst, |
+ int iAmt, |
+ void **pp |
+){ |
+ TestvfsFd *pFd = tvfsGetFd(pFile); |
+ return sqlite3OsFetch(pFd->pReal, iOfst, iAmt, pp); |
+} |
+ |
+static int tvfsUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *p){ |
+ TestvfsFd *pFd = tvfsGetFd(pFile); |
+ return sqlite3OsUnfetch(pFd->pReal, iOfst, p); |
+} |
+ |
static int testvfs_obj_cmd( |
ClientData cd, |
Tcl_Interp *interp, |
@@ -978,7 +1080,7 @@ static int testvfs_obj_cmd( |
switch( aSubcmd[i].eCmd ){ |
case CMD_SHM: { |
Tcl_Obj *pObj; |
- int i; |
+ int i, rc; |
TestvfsBuffer *pBuffer; |
char *zName; |
if( objc!=3 && objc!=4 ){ |
@@ -986,10 +1088,16 @@ static int testvfs_obj_cmd( |
return TCL_ERROR; |
} |
zName = ckalloc(p->pParent->mxPathname); |
- p->pParent->xFullPathname( |
+ rc = p->pParent->xFullPathname( |
p->pParent, Tcl_GetString(objv[2]), |
p->pParent->mxPathname, zName |
); |
+ if( rc!=SQLITE_OK ){ |
+ Tcl_AppendResult(interp, "failed to get full path: ", |
+ Tcl_GetString(objv[2]), 0); |
+ ckfree(zName); |
+ return TCL_ERROR; |
+ } |
for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ |
if( 0==strcmp(pBuffer->zFile, zName) ) break; |
} |
@@ -1023,23 +1131,32 @@ static int testvfs_obj_cmd( |
break; |
} |
+ /* TESTVFS filter METHOD-LIST |
+ ** |
+ ** Activate special processing for those methods contained in the list |
+ */ |
case CMD_FILTER: { |
static struct VfsMethod { |
char *zName; |
int mask; |
} vfsmethod [] = { |
- { "xShmOpen", TESTVFS_SHMOPEN_MASK }, |
- { "xShmLock", TESTVFS_SHMLOCK_MASK }, |
- { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, |
- { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, |
- { "xShmMap", TESTVFS_SHMMAP_MASK }, |
- { "xSync", TESTVFS_SYNC_MASK }, |
- { "xDelete", TESTVFS_DELETE_MASK }, |
- { "xWrite", TESTVFS_WRITE_MASK }, |
- { "xTruncate", TESTVFS_TRUNCATE_MASK }, |
- { "xOpen", TESTVFS_OPEN_MASK }, |
- { "xClose", TESTVFS_CLOSE_MASK }, |
- { "xAccess", TESTVFS_ACCESS_MASK }, |
+ { "xShmOpen", TESTVFS_SHMOPEN_MASK }, |
+ { "xShmLock", TESTVFS_SHMLOCK_MASK }, |
+ { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, |
+ { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, |
+ { "xShmMap", TESTVFS_SHMMAP_MASK }, |
+ { "xSync", TESTVFS_SYNC_MASK }, |
+ { "xDelete", TESTVFS_DELETE_MASK }, |
+ { "xWrite", TESTVFS_WRITE_MASK }, |
+ { "xRead", TESTVFS_READ_MASK }, |
+ { "xTruncate", TESTVFS_TRUNCATE_MASK }, |
+ { "xOpen", TESTVFS_OPEN_MASK }, |
+ { "xClose", TESTVFS_CLOSE_MASK }, |
+ { "xAccess", TESTVFS_ACCESS_MASK }, |
+ { "xFullPathname", TESTVFS_FULLPATHNAME_MASK }, |
+ { "xUnlock", TESTVFS_UNLOCK_MASK }, |
+ { "xLock", TESTVFS_LOCK_MASK }, |
+ { "xCheckReservedLock", TESTVFS_CKLOCK_MASK }, |
}; |
Tcl_Obj **apElem = 0; |
int nElem = 0; |
@@ -1071,14 +1188,17 @@ static int testvfs_obj_cmd( |
break; |
} |
+ /* |
+ ** TESTVFS script ?SCRIPT? |
+ ** |
+ ** Query or set the script to be run when filtered VFS events |
+ ** occur. |
+ */ |
case CMD_SCRIPT: { |
if( objc==3 ){ |
int nByte; |
if( p->pScript ){ |
Tcl_DecrRefCount(p->pScript); |
- ckfree((char *)p->apScript); |
- p->apScript = 0; |
- p->nScript = 0; |
p->pScript = 0; |
} |
Tcl_GetStringFromObj(objv[2], &nByte); |
@@ -1147,18 +1267,20 @@ static int testvfs_obj_cmd( |
int iValue; |
} aFlag[] = { |
{ "default", -1 }, |
- { "atomic", SQLITE_IOCAP_ATOMIC }, |
- { "atomic512", SQLITE_IOCAP_ATOMIC512 }, |
- { "atomic1k", SQLITE_IOCAP_ATOMIC1K }, |
- { "atomic2k", SQLITE_IOCAP_ATOMIC2K }, |
- { "atomic4k", SQLITE_IOCAP_ATOMIC4K }, |
- { "atomic8k", SQLITE_IOCAP_ATOMIC8K }, |
- { "atomic16k", SQLITE_IOCAP_ATOMIC16K }, |
- { "atomic32k", SQLITE_IOCAP_ATOMIC32K }, |
- { "atomic64k", SQLITE_IOCAP_ATOMIC64K }, |
- { "sequential", SQLITE_IOCAP_SEQUENTIAL }, |
- { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, |
+ { "atomic", SQLITE_IOCAP_ATOMIC }, |
+ { "atomic512", SQLITE_IOCAP_ATOMIC512 }, |
+ { "atomic1k", SQLITE_IOCAP_ATOMIC1K }, |
+ { "atomic2k", SQLITE_IOCAP_ATOMIC2K }, |
+ { "atomic4k", SQLITE_IOCAP_ATOMIC4K }, |
+ { "atomic8k", SQLITE_IOCAP_ATOMIC8K }, |
+ { "atomic16k", SQLITE_IOCAP_ATOMIC16K }, |
+ { "atomic32k", SQLITE_IOCAP_ATOMIC32K }, |
+ { "atomic64k", SQLITE_IOCAP_ATOMIC64K }, |
+ { "sequential", SQLITE_IOCAP_SEQUENTIAL }, |
+ { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, |
{ "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN }, |
+ { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE }, |
+ { "immutable", SQLITE_IOCAP_IMMUTABLE }, |
{ 0, 0 } |
}; |
Tcl_Obj *pRet; |
@@ -1192,7 +1314,7 @@ static int testvfs_obj_cmd( |
iNew |= aFlag[idx].iValue; |
} |
- p->iDevchar = iNew; |
+ p->iDevchar = iNew| 0x10000000; |
} |
pRet = Tcl_NewObj(); |
@@ -1232,7 +1354,6 @@ static void testvfs_obj_del(ClientData cd){ |
Testvfs *p = (Testvfs *)cd; |
if( p->pScript ) Tcl_DecrRefCount(p->pScript); |
sqlite3_vfs_unregister(p->pVfs); |
- ckfree((char *)p->apScript); |
ckfree((char *)p->pVfs); |
ckfree((char *)p); |
} |
@@ -1279,7 +1400,7 @@ static int testvfs_cmd( |
Tcl_Obj *CONST objv[] |
){ |
static sqlite3_vfs tvfs_vfs = { |
- 2, /* iVersion */ |
+ 3, /* iVersion */ |
0, /* szOsFile */ |
0, /* mxPathname */ |
0, /* pNext */ |
@@ -1305,6 +1426,9 @@ static int testvfs_cmd( |
tvfsCurrentTime, /* xCurrentTime */ |
0, /* xGetLastError */ |
0, /* xCurrentTimeInt64 */ |
+ 0, /* xSetSystemCall */ |
+ 0, /* xGetSystemCall */ |
+ 0, /* xNextSystemCall */ |
}; |
Testvfs *p; /* New object */ |
@@ -1314,10 +1438,11 @@ static int testvfs_cmd( |
int i; |
int isNoshm = 0; /* True if -noshm is passed */ |
+ int isFullshm = 0; /* True if -fullshm is passed */ |
int isDefault = 0; /* True if -default is passed */ |
int szOsFile = 0; /* Value passed to -szosfile */ |
int mxPathname = -1; /* Value passed to -mxpathname */ |
- int iVersion = 2; /* Value passed to -iversion */ |
+ int iVersion = 3; /* Value passed to -iversion */ |
if( objc<2 || 0!=(objc%2) ) goto bad_args; |
for(i=2; i<objc; i += 2){ |
@@ -1329,6 +1454,7 @@ static int testvfs_cmd( |
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){ |
return TCL_ERROR; |
} |
+ if( isNoshm ) isFullshm = 0; |
} |
else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ |
if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){ |
@@ -1350,6 +1476,12 @@ static int testvfs_cmd( |
return TCL_ERROR; |
} |
} |
+ else if( nSwitch>2 && 0==strncmp("-fullshm", zSwitch, nSwitch) ){ |
+ if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isFullshm) ){ |
+ return TCL_ERROR; |
+ } |
+ if( isFullshm ) isNoshm = 0; |
+ } |
else{ |
goto bad_args; |
} |
@@ -1360,7 +1492,7 @@ static int testvfs_cmd( |
} |
zVfs = Tcl_GetString(objv[1]); |
- nByte = sizeof(Testvfs) + strlen(zVfs)+1; |
+ nByte = sizeof(Testvfs) + (int)strlen(zVfs)+1; |
p = (Testvfs *)ckalloc(nByte); |
memset(p, 0, nByte); |
p->iDevchar = -1; |
@@ -1391,6 +1523,7 @@ static int testvfs_cmd( |
pVfs->szOsFile = szOsFile; |
p->pVfs = pVfs; |
p->isNoshm = isNoshm; |
+ p->isFullshm = isFullshm; |
p->mask = TESTVFS_ALL_MASK; |
sqlite3_vfs_register(pVfs, isDefault); |