1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Experimental change to the xShmXXX parts of the VFS interface.

FossilOrigin-Name: ca68472db01c14a899892007d1cbaff5e86ae193
This commit is contained in:
dan
2010-06-11 19:04:21 +00:00
parent 0b9b4301b8
commit 13a3cb82ce
12 changed files with 428 additions and 395 deletions

View File

@@ -75,10 +75,14 @@ struct Testvfs {
#define TESTVFS_SHMLOCK_MASK 0x00000010
#define TESTVFS_SHMBARRIER_MASK 0x00000020
#define TESTVFS_SHMCLOSE_MASK 0x00000040
#define TESTVFS_SHMPAGE_MASK 0x00000080
#define TESTVFS_OPEN_MASK 0x00000080
#define TESTVFS_SYNC_MASK 0x00000100
#define TESTVFS_ALL_MASK 0x000001FF
#define TESTVFS_OPEN_MASK 0x00000100
#define TESTVFS_SYNC_MASK 0x00000200
#define TESTVFS_ALL_MASK 0x000003FF
#define TESTVFS_MAX_PAGES 256
/*
** A shared-memory buffer. There is one of these objects for each shared
@@ -87,8 +91,8 @@ struct Testvfs {
*/
struct TestvfsBuffer {
char *zFile; /* Associated file name */
int n; /* Size of allocated buffer in bytes */
u8 *a; /* Buffer allocated using ckalloc() */
int pgsz; /* Page size */
u8 *aPage[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */
TestvfsFile *pFile; /* List of open handles */
TestvfsBuffer *pNext; /* Next in linked list of all buffers */
};
@@ -139,6 +143,7 @@ static int tvfsShmRelease(sqlite3_file*);
static int tvfsShmLock(sqlite3_file*, int , int, int);
static void tvfsShmBarrier(sqlite3_file*);
static int tvfsShmClose(sqlite3_file*, int);
static int tvfsShmPage(sqlite3_file*,int,int,int, void volatile **);
static sqlite3_io_methods tvfs_io_methods = {
2, /* iVersion */
@@ -160,7 +165,8 @@ static sqlite3_io_methods tvfs_io_methods = {
tvfsShmRelease, /* xShmRelease */
tvfsShmLock, /* xShmLock */
tvfsShmBarrier, /* xShmBarrier */
tvfsShmClose /* xShmClose */
tvfsShmClose, /* xShmClose */
tvfsShmPage /* xShmPage */
};
static int tvfsResultCode(Testvfs *p, int *pRc){
@@ -547,16 +553,6 @@ static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
}
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;
}
*pNewSize = pBuffer->n;
}
static int tvfsInjectIoerr(Testvfs *p){
int ret = 0;
if( p->ioerr ){
@@ -624,66 +620,66 @@ static int tvfsShmSize(
int reqSize,
int *pNewSize
){
int rc = SQLITE_OK;
TestvfsFile *pFd = (TestvfsFile *)pFile;
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
if( p->pScript && p->mask&TESTVFS_SHMSIZE_MASK ){
tvfsExecTcl(p, "xShmSize",
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
);
tvfsResultCode(p, &rc);
}
if( rc==SQLITE_OK && p->mask&TESTVFS_SHMSIZE_MASK && tvfsInjectIoerr(p) ){
rc = SQLITE_IOERR;
}
if( rc==SQLITE_OK ){
tvfsGrowBuffer(pFd, reqSize, pNewSize);
}
return rc;
assert(0);
return SQLITE_OK;
}
static int tvfsShmGet(
sqlite3_file *pFile,
int reqMapSize,
int *pMapSize,
volatile void **pp
){
assert(0);
return SQLITE_OK;
}
static int tvfsShmRelease(sqlite3_file *pFile){
assert(0);
return SQLITE_OK;
}
static void tvfsAllocPage(TestvfsBuffer *p, int iPage, int pgsz){
assert( iPage<TESTVFS_MAX_PAGES );
if( p->aPage[iPage]==0 ){
p->aPage[iPage] = ckalloc(pgsz);
memset(p->aPage[iPage], 0, pgsz);
p->pgsz = pgsz;
}
}
static int tvfsShmPage(
sqlite3_file *pFile, /* Handle open on database file */
int iPage, /* Page to retrieve */
int pgsz, /* Size of pages */
int isWrite, /* True to extend file if necessary */
void volatile **pp /* OUT: Mapped memory */
){
int rc = SQLITE_OK;
TestvfsFile *pFd = (TestvfsFile *)pFile;
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
if( p->pScript && p->mask&TESTVFS_SHMGET_MASK ){
tvfsExecTcl(p, "xShmGet",
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
Tcl_NewIntObj(reqMapSize)
if( p->pScript && p->mask&TESTVFS_SHMPAGE_MASK ){
Tcl_Obj *pArg = Tcl_NewObj();
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
tvfsExecTcl(p, "xShmPage",
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg
);
tvfsResultCode(p, &rc);
}
if( rc==SQLITE_OK && p->mask&TESTVFS_SHMGET_MASK && tvfsInjectIoerr(p) ){
if( rc==SQLITE_OK && p->mask&TESTVFS_SHMPAGE_MASK && tvfsInjectIoerr(p) ){
rc = SQLITE_IOERR;
}
*pMapSize = pFd->pShm->n;
*pp = pFd->pShm->a;
return rc;
}
static int tvfsShmRelease(sqlite3_file *pFile){
int rc = SQLITE_OK;
TestvfsFile *pFd = (TestvfsFile *)pFile;
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
if( p->pScript && p->mask&TESTVFS_SHMRELEASE_MASK ){
tvfsExecTcl(p, "xShmRelease",
Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
);
tvfsResultCode(p, &rc);
if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){
tvfsAllocPage(pFd->pShm, iPage, pgsz);
}
*pp = (void volatile *)pFd->pShm->aPage[iPage];
return rc;
}
static int tvfsShmLock(
sqlite3_file *pFile,
int ofst,
@@ -782,10 +778,13 @@ static int tvfsShmClose(
*ppFd = pFd->pNext;
if( pBuffer->pFile==0 ){
int i;
TestvfsBuffer **pp;
for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext));
*pp = (*pp)->pNext;
ckfree((char *)pBuffer->a);
for(i=0; pBuffer->aPage[i]; i++){
ckfree((char *)pBuffer->aPage[i]);
}
ckfree((char *)pBuffer);
}
pFd->pShm = 0;
@@ -821,6 +820,8 @@ static int testvfs_obj_cmd(
switch( (enum DB_enum)i ){
case CMD_SHM: {
Tcl_Obj *pObj;
int i;
TestvfsBuffer *pBuffer;
char *zName;
if( objc!=3 && objc!=4 ){
@@ -838,11 +839,22 @@ static int testvfs_obj_cmd(
if( objc==4 ){
int n;
u8 *a = Tcl_GetByteArrayFromObj(objv[3], &n);
pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, n);
pBuffer->n = n;
memcpy(pBuffer->a, a, n);
assert( pBuffer->pgsz==0 || pBuffer->pgsz==32768 );
for(i=0; i*32768<n; i++){
int nByte = 32768;
tvfsAllocPage(pBuffer, i, 32768);
if( n-i*32768<32768 ){
nByte = n;
}
memcpy(pBuffer->aPage[i], &a[i*32768], nByte);
}
}
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBuffer->a, pBuffer->n));
pObj = Tcl_NewObj();
for(i=0; pBuffer->aPage[i]; i++){
Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], 32768));
}
Tcl_SetObjResult(interp, pObj);
break;
}