#include "sqlite3.h"
#include "sqliteInt.h"
-#if 0 /* FIX THIS LATER */
-
typedef struct Testvfs Testvfs;
typedef struct TestvfsShm TestvfsShm;
typedef struct TestvfsBuffer TestvfsBuffer;
-typedef struct tvfs_file tvfs_file;
-struct tvfs_file {
- sqlite3_file base; /* Base class. Must be first */
- sqlite3_vfs *pVfs; /* the VFS */
- TestvfsShm *pShm; /* Shared memory segment */
- const char *zFilename; /* Filename */
- sqlite3_file *pReal; /* The real, underlying file descriptor */
+typedef struct TestvfsFile TestvfsFile;
+
+/*
+** An open file handle.
+*/
+struct TestvfsFile {
+ sqlite3_file base; /* Base class. Must be first */
+ sqlite3_vfs *pVfs; /* The VFS */
+ const char *zFilename; /* Filename as passed to xOpen() */
+ sqlite3_file *pReal; /* The real, underlying file descriptor */
+ Tcl_Obj *pShmId; /* Shared memory id for Tcl callbacks */
+ TestvfsBuffer *pShm; /* Shared memory buffer */
};
int nScript; /* Number of elements in array apScript */
Tcl_Obj **apScript; /* Script to execute */
TestvfsBuffer *pBuffer; /* List of shared buffers */
+ int isNoshm;
};
/*
TestvfsBuffer *pNext; /* Next in linked list of all buffers */
};
-/*
-** A shared-memory handle returned by tvfsShmOpen().
-*/
-struct TestvfsShm {
- Tcl_Obj *id; /* Name of this handle */
- TestvfsBuffer *pBuffer; /* Underlying buffer */
-};
-
#define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent)
/*
-** Method declarations for tvfs_file.
+** Method declarations for TestvfsFile.
*/
static int tvfsClose(sqlite3_file*);
static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
** Close an tvfs-file.
*/
static int tvfsClose(sqlite3_file *pFile){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
+ if( p->pShmId ){
+ Tcl_DecrRefCount(p->pShmId);
+ p->pShmId = 0;
+ }
+ if( pFile->pMethods ){
+ ckfree((char *)pFile->pMethods);
+ }
return sqlite3OsClose(p->pReal);
}
int iAmt,
sqlite_int64 iOfst
){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
}
int iAmt,
sqlite_int64 iOfst
){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
}
** Truncate an tvfs-file.
*/
static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsTruncate(p->pReal, size);
}
** Sync an tvfs-file.
*/
static int tvfsSync(sqlite3_file *pFile, int flags){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsSync(p->pReal, flags);
}
** Return the current file-size of an tvfs-file.
*/
static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsFileSize(p->pReal, pSize);
}
** Lock an tvfs-file.
*/
static int tvfsLock(sqlite3_file *pFile, int eLock){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsLock(p->pReal, eLock);
}
** Unlock an tvfs-file.
*/
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsUnlock(p->pReal, eLock);
}
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
*/
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsCheckReservedLock(p->pReal, pResOut);
}
** File control method. For custom operations on an tvfs-file.
*/
static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsFileControl(p->pReal, op, pArg);
}
** Return the sector-size in bytes for an tvfs-file.
*/
static int tvfsSectorSize(sqlite3_file *pFile){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsSectorSize(p->pReal);
}
** Return the device characteristic flags supported by an tvfs-file.
*/
static int tvfsDeviceCharacteristics(sqlite3_file *pFile){
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
return sqlite3OsDeviceCharacteristics(p->pReal);
}
int *pOutFlags
){
int rc;
- tvfs_file *p = (tvfs_file *)pFile;
+ TestvfsFile *p = (TestvfsFile *)pFile;
p->pShm = 0;
+ p->pShmId = 0;
p->zFilename = zName;
p->pVfs = pVfs;
p->pReal = (sqlite3_file *)&p[1];
rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, p->pReal, flags, pOutFlags);
if( p->pReal->pMethods ){
- pFile->pMethods = &tvfs_io_methods;
+ sqlite3_io_methods *pMethods;
+ pMethods = (sqlite3_io_methods *)ckalloc(sizeof(sqlite3_io_methods));
+ memcpy(pMethods, &tvfs_io_methods, sizeof(sqlite3_io_methods));
+ if( ((Testvfs *)pVfs->pAppData)->isNoshm ){
+ pMethods->xShmOpen = 0;
+ pMethods->xShmGet = 0;
+ pMethods->xShmSize = 0;
+ pMethods->xShmRelease = 0;
+ pMethods->xShmClose = 0;
+ pMethods->xShmLock = 0;
+ }
+ pFile->pMethods = pMethods;
}
+
return rc;
}
return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
}
-static void tvfsGrowBuffer(TestvfsShm *pShm, int reqSize, int *pNewSize){
- TestvfsBuffer *pBuffer = pShm->pBuffer;
+static void tvfsGrowBuffer(TestvfsFile *pFd, int reqSize, int *pNewSize){
+ TestvfsBuffer *pBuffer = pFd->pShm;
if( reqSize>pBuffer->n ){
pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, reqSize);
memset(&pBuffer->a[pBuffer->n], 0x55, reqSize-pBuffer->n);
static int tvfsShmOpen(
sqlite3_file *pFileDes
){
- Testvfs *p = (Testvfs *)(pVfs->pAppData);
+ Testvfs *p;
int rc = SQLITE_OK; /* Return code */
Tcl_Obj *pId = 0; /* Id for this connection */
TestvfsBuffer *pBuffer; /* Buffer to open connection to */
- TestvfsShm *pShm; /* New shm handle */
- tvfs_file *pFd; /* The file descriptor */
+ TestvfsFile *pFd; /* The testvfs file structure */
- pFd = (tvfs_file*)pFileDes;
+ pFd = (TestvfsFile*)pFileDes;
+ p = (Testvfs *)pFd->pVfs->pAppData;
+ assert( pFd->pShmId==0 && pFd->pShm==0 );
/* Evaluate the Tcl script:
**
pId = Tcl_GetObjResult(p->interp);
}
Tcl_IncrRefCount(pId);
-
- /* Allocate the TestvfsShm handle. */
- pShm = (TestvfsShm *)ckalloc(sizeof(TestvfsShm));
- memset(pShm, 0, sizeof(TestvfsShm));
- pShm->id = pId;
+ pFd->pShmId = pId;
/* Search for a TestvfsBuffer. Create a new one if required. */
for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
- if( 0==strcmp(zName, pBuffer->zFile) ) break;
+ if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break;
}
if( !pBuffer ){
- int nByte = sizeof(TestvfsBuffer) + strlen(zName) + 1;
+ int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1;
pBuffer = (TestvfsBuffer *)ckalloc(nByte);
memset(pBuffer, 0, nByte);
pBuffer->zFile = (char *)&pBuffer[1];
- strcpy(pBuffer->zFile, zName);
+ strcpy(pBuffer->zFile, pFd->zFilename);
pBuffer->pNext = p->pBuffer;
p->pBuffer = pBuffer;
}
/* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
pBuffer->nRef++;
- pShm->pBuffer = pBuffer;
- *pp = (sqlite3_shm *)pShm;
+ pFd->pShm = pBuffer;
return SQLITE_OK;
}
static int tvfsShmSize(
- sqlite3_vfs *pVfs,
- sqlite3_shm *pShmHandle,
+ sqlite3_file *pFile,
int reqSize,
int *pNewSize
){
int rc = SQLITE_OK;
- Testvfs *p = (Testvfs *)(pVfs->pAppData);
- TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
+ TestvfsFile *pFd = (TestvfsFile *)pFile;
+ Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
tvfsExecTcl(p, "xShmSize",
- Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
);
tvfsResultCode(p, &rc);
if( rc==SQLITE_OK ){
- tvfsGrowBuffer(pShm, reqSize, pNewSize);
+ tvfsGrowBuffer(pFd, reqSize, pNewSize);
}
return rc;
}
static int tvfsShmGet(
- sqlite3_vfs *pVfs,
- sqlite3_shm *pShmHandle,
+ sqlite3_file *pFile,
int reqMapSize,
int *pMapSize,
void **pp
){
int rc = SQLITE_OK;
- Testvfs *p = (Testvfs *)(pVfs->pAppData);
- TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
+ TestvfsFile *pFd = (TestvfsFile *)pFile;
+ Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
tvfsExecTcl(p, "xShmGet",
- Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
);
tvfsResultCode(p, &rc);
if( rc==SQLITE_OK ){
- tvfsGrowBuffer(pShm, reqMapSize, pMapSize);
- *pp = pShm->pBuffer->a;
+ tvfsGrowBuffer(pFd, reqMapSize, pMapSize);
+ *pp = pFd->pShm->a;
}
return rc;
}
-static int tvfsShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pShmHandle){
+static int tvfsShmRelease(sqlite3_file *pFile){
int rc = SQLITE_OK;
- Testvfs *p = (Testvfs *)(pVfs->pAppData);
- TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
+ TestvfsFile *pFd = (TestvfsFile *)pFile;
+ Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
tvfsExecTcl(p, "xShmRelease",
- Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
);
tvfsResultCode(p, &rc);
}
static int tvfsShmLock(
- sqlite3_vfs *pVfs,
- sqlite3_shm *pShmHandle,
+ sqlite3_file *pFile,
int desiredLock,
int *gotLock
){
int rc = SQLITE_OK;
- Testvfs *p = (Testvfs *)(pVfs->pAppData);
- TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
+ TestvfsFile *pFd = (TestvfsFile *)pFile;
+ Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
char *zLock = "";
switch( desiredLock ){
case SQLITE_SHM_UNLOCK: zLock = "UNLOCK"; break;
}
tvfsExecTcl(p, "xShmLock",
- Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id,
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
Tcl_NewStringObj(zLock, -1)
);
tvfsResultCode(p, &rc);
}
static int tvfsShmClose(
- sqlite3_vfs *pVfs,
- sqlite3_shm *pShmHandle,
+ sqlite3_file *pFile,
int deleteFlag
){
int rc = SQLITE_OK;
- Testvfs *p = (Testvfs *)(pVfs->pAppData);
- TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
- TestvfsBuffer *pBuffer = pShm->pBuffer;
+ TestvfsFile *pFd = (TestvfsFile *)pFile;
+ Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
+ TestvfsBuffer *pBuffer = pFd->pShm;
+ assert( pFd->pShmId && pFd->pShm );
#if 0
assert( (deleteFlag!=0)==(pBuffer->nRef==1) );
#endif
tvfsExecTcl(p, "xShmClose",
- Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
+ Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
);
tvfsResultCode(p, &rc);
ckfree((char *)pBuffer->a);
ckfree((char *)pBuffer);
}
- Tcl_DecrRefCount(pShm->id);
- ckfree((char *)pShm);
+ Tcl_DecrRefCount(pFd->pShmId);
+ pFd->pShmId = 0;
+ pFd->pShm = 0;
return rc;
}
int objc,
Tcl_Obj *CONST objv[]
){
-
static sqlite3_vfs tvfs_vfs = {
2, /* iVersion */
- sizeof(tvfs_file), /* szOsFile */
+ sizeof(TestvfsFile), /* szOsFile */
0, /* mxPathname */
0, /* pNext */
0, /* zName */
pVfs->mxPathname = p->pParent->mxPathname;
pVfs->szOsFile += p->pParent->szOsFile;
p->pVfs = pVfs;
- if( isNoshm ){
- pVfs->xShmOpen = 0;
- pVfs->xShmGet = 0;
- pVfs->xShmSize = 0;
- pVfs->xShmRelease = 0;
- pVfs->xShmClose = 0;
- pVfs->xShmLock = 0;
- }
+ p->isNoshm = isNoshm;
Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
sqlite3_vfs_register(pVfs, 0);
Tcl_WrongNumArgs(interp, 1, objv, "?-noshm? VFSNAME SCRIPT");
return TCL_ERROR;
}
-#endif /* 0 */
int Sqlitetestvfs_Init(Tcl_Interp *interp){
- /* Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); */
+ Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
return TCL_OK;
}