Index: src/test_vfs.c ================================================================== --- src/test_vfs.c +++ src/test_vfs.c @@ -14,22 +14,25 @@ #if SQLITE_TEST /* This file is used for testing only */ #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 */ }; /* ** An instance of this structure is allocated for each VFS created. The @@ -42,10 +45,11 @@ sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ Tcl_Interp *interp; /* Interpreter to run script in */ int nScript; /* Number of elements in array apScript */ Tcl_Obj **apScript; /* Script to execute */ TestvfsBuffer *pBuffer; /* List of shared buffers */ + int isNoshm; }; /* ** A shared-memory buffer. */ @@ -55,24 +59,16 @@ u8 *a; /* Buffer allocated using ckalloc() */ int nRef; /* Number of references to this object */ 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); static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size); @@ -133,11 +129,18 @@ /* ** 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); } /* ** Read data from an tvfs-file. @@ -146,11 +149,11 @@ sqlite3_file *pFile, void *zBuf, int iAmt, sqlite_int64 iOfst ){ - tvfs_file *p = (tvfs_file *)pFile; + TestvfsFile *p = (TestvfsFile *)pFile; return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); } /* ** Write data to an tvfs-file. @@ -159,83 +162,83 @@ sqlite3_file *pFile, const void *zBuf, 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); } /* ** Open an tvfs file handle. @@ -246,19 +249,32 @@ sqlite3_file *pFile, int flags, 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; } /* ** Delete the file located at zPath. If the dirSync argument is true, @@ -349,12 +365,12 @@ */ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 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); pBuffer->n = reqSize; } @@ -419,18 +435,19 @@ } 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: ** ** SCRIPT xShmOpen FILENAME ** @@ -445,101 +462,93 @@ pId = Tcl_NewStringObj("anon", -1); }else{ 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); return 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_READ: zLock = "READ"; break; case SQLITE_SHM_WRITE: zLock = "WRITE"; break; @@ -547,11 +556,11 @@ case SQLITE_SHM_RECOVER: zLock = "RECOVER"; break; case SQLITE_SHM_PENDING: zLock = "PENDING"; break; 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); if( rc==SQLITE_OK ){ *gotLock = desiredLock; @@ -559,25 +568,25 @@ return 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); pBuffer->nRef--; if( pBuffer->nRef==0 ){ @@ -585,12 +594,13 @@ for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext)); *pp = (*pp)->pNext; 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; } static int testvfs_obj_cmd( @@ -700,14 +710,13 @@ ClientData cd, Tcl_Interp *interp, 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 */ 0, /* pAppData */ tvfsOpen, /* xOpen */ @@ -777,18 +786,11 @@ pVfs->pAppData = (void *)p; pVfs->zName = p->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); return TCL_OK; @@ -795,13 +797,12 @@ bad_args: 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; } #endif