/ Check-in [25e72f81]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Modify the VFS in test_vfs.c to match the refactoring of the xShmXXX methods.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal-refactor
Files: files | file ages | folders
SHA1: 25e72f81561575051c63e9bf5d2c8e76f9fcf5c6
User & Date: dan 2010-05-13 06:19:37
Context
2010-05-13
07:08
Fix for a segfault that can follow a malloc failure. check-in: 3cab9022 user: dan tags: wal-refactor
06:19
Modify the VFS in test_vfs.c to match the refactoring of the xShmXXX methods. check-in: 25e72f81 user: dan tags: wal-refactor
2010-05-12
18:30
Fix for the test_devsym.c test module for the VFS-SHM refactoring. check-in: 49d62933 user: drh tags: wal-refactor
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test_vfs.c.

    12     12   **
    13     13   */
    14     14   #if SQLITE_TEST          /* This file is used for testing only */
    15     15   
    16     16   #include "sqlite3.h"
    17     17   #include "sqliteInt.h"
    18     18   
    19         -#if 0  /* FIX THIS LATER */
    20         -
    21     19   typedef struct Testvfs Testvfs;
    22     20   typedef struct TestvfsShm TestvfsShm;
    23     21   typedef struct TestvfsBuffer TestvfsBuffer;
    24         -typedef struct tvfs_file tvfs_file;
    25         -struct tvfs_file {
    26         -  sqlite3_file base;        /* Base class.  Must be first */
    27         -  sqlite3_vfs *pVfs;        /* the VFS */
    28         -  TestvfsShm *pShm;         /* Shared memory segment */
    29         -  const char *zFilename;    /* Filename */
    30         -  sqlite3_file *pReal;      /* The real, underlying file descriptor */
           22  +typedef struct TestvfsFile TestvfsFile;
           23  +
           24  +/*
           25  +** An open file handle.
           26  +*/
           27  +struct TestvfsFile {
           28  +  sqlite3_file base;              /* Base class.  Must be first */
           29  +  sqlite3_vfs *pVfs;              /* The VFS */
           30  +  const char *zFilename;          /* Filename as passed to xOpen() */
           31  +  sqlite3_file *pReal;            /* The real, underlying file descriptor */
           32  +  Tcl_Obj *pShmId;                /* Shared memory id for Tcl callbacks */
           33  +  TestvfsBuffer *pShm;            /* Shared memory buffer */
    31     34   };
    32     35   
    33     36   
    34     37   /*
    35     38   ** An instance of this structure is allocated for each VFS created. The
    36     39   ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
    37     40   ** is set to point to it.
................................................................................
    40     43     char *zName;                    /* Name of this VFS */
    41     44     sqlite3_vfs *pParent;           /* The VFS to use for file IO */
    42     45     sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
    43     46     Tcl_Interp *interp;             /* Interpreter to run script in */
    44     47     int nScript;                    /* Number of elements in array apScript */
    45     48     Tcl_Obj **apScript;             /* Script to execute */
    46     49     TestvfsBuffer *pBuffer;         /* List of shared buffers */
           50  +  int isNoshm;
    47     51   };
    48     52   
    49     53   /*
    50     54   ** A shared-memory buffer.
    51     55   */
    52     56   struct TestvfsBuffer {
    53     57     char *zFile;                    /* Associated file name */
    54     58     int n;                          /* Size of allocated buffer in bytes */
    55     59     u8 *a;                          /* Buffer allocated using ckalloc() */
    56     60     int nRef;                       /* Number of references to this object */
    57     61     TestvfsBuffer *pNext;           /* Next in linked list of all buffers */
    58     62   };
    59     63   
    60         -/*
    61         -** A shared-memory handle returned by tvfsShmOpen().
    62         -*/
    63         -struct TestvfsShm {
    64         -  Tcl_Obj *id;                    /* Name of this handle */
    65         -  TestvfsBuffer *pBuffer;         /* Underlying buffer */
    66         -};
    67         -
    68     64   
    69     65   #define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent)
    70     66   
    71     67   
    72     68   /*
    73         -** Method declarations for tvfs_file.
           69  +** Method declarations for TestvfsFile.
    74     70   */
    75     71   static int tvfsClose(sqlite3_file*);
    76     72   static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
    77     73   static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
    78     74   static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size);
    79     75   static int tvfsSync(sqlite3_file*, int flags);
    80     76   static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
................................................................................
   131    127     tvfsShmClose                    /* xShmClose */
   132    128   };
   133    129   
   134    130   /*
   135    131   ** Close an tvfs-file.
   136    132   */
   137    133   static int tvfsClose(sqlite3_file *pFile){
   138         -  tvfs_file *p = (tvfs_file *)pFile;
          134  +  TestvfsFile *p = (TestvfsFile *)pFile;
          135  +  if( p->pShmId ){
          136  +    Tcl_DecrRefCount(p->pShmId);
          137  +    p->pShmId = 0;
          138  +  }
          139  +  if( pFile->pMethods ){
          140  +    ckfree((char *)pFile->pMethods);
          141  +  }
   139    142     return sqlite3OsClose(p->pReal);
   140    143   }
   141    144   
   142    145   /*
   143    146   ** Read data from an tvfs-file.
   144    147   */
   145    148   static int tvfsRead(
   146    149     sqlite3_file *pFile, 
   147    150     void *zBuf, 
   148    151     int iAmt, 
   149    152     sqlite_int64 iOfst
   150    153   ){
   151         -  tvfs_file *p = (tvfs_file *)pFile;
          154  +  TestvfsFile *p = (TestvfsFile *)pFile;
   152    155     return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
   153    156   }
   154    157   
   155    158   /*
   156    159   ** Write data to an tvfs-file.
   157    160   */
   158    161   static int tvfsWrite(
   159    162     sqlite3_file *pFile, 
   160    163     const void *zBuf, 
   161    164     int iAmt, 
   162    165     sqlite_int64 iOfst
   163    166   ){
   164         -  tvfs_file *p = (tvfs_file *)pFile;
          167  +  TestvfsFile *p = (TestvfsFile *)pFile;
   165    168     return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
   166    169   }
   167    170   
   168    171   /*
   169    172   ** Truncate an tvfs-file.
   170    173   */
   171    174   static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
   172         -  tvfs_file *p = (tvfs_file *)pFile;
          175  +  TestvfsFile *p = (TestvfsFile *)pFile;
   173    176     return sqlite3OsTruncate(p->pReal, size);
   174    177   }
   175    178   
   176    179   /*
   177    180   ** Sync an tvfs-file.
   178    181   */
   179    182   static int tvfsSync(sqlite3_file *pFile, int flags){
   180         -  tvfs_file *p = (tvfs_file *)pFile;
          183  +  TestvfsFile *p = (TestvfsFile *)pFile;
   181    184     return sqlite3OsSync(p->pReal, flags);
   182    185   }
   183    186   
   184    187   /*
   185    188   ** Return the current file-size of an tvfs-file.
   186    189   */
   187    190   static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
   188         -  tvfs_file *p = (tvfs_file *)pFile;
          191  +  TestvfsFile *p = (TestvfsFile *)pFile;
   189    192     return sqlite3OsFileSize(p->pReal, pSize);
   190    193   }
   191    194   
   192    195   /*
   193    196   ** Lock an tvfs-file.
   194    197   */
   195    198   static int tvfsLock(sqlite3_file *pFile, int eLock){
   196         -  tvfs_file *p = (tvfs_file *)pFile;
          199  +  TestvfsFile *p = (TestvfsFile *)pFile;
   197    200     return sqlite3OsLock(p->pReal, eLock);
   198    201   }
   199    202   
   200    203   /*
   201    204   ** Unlock an tvfs-file.
   202    205   */
   203    206   static int tvfsUnlock(sqlite3_file *pFile, int eLock){
   204         -  tvfs_file *p = (tvfs_file *)pFile;
          207  +  TestvfsFile *p = (TestvfsFile *)pFile;
   205    208     return sqlite3OsUnlock(p->pReal, eLock);
   206    209   }
   207    210   
   208    211   /*
   209    212   ** Check if another file-handle holds a RESERVED lock on an tvfs-file.
   210    213   */
   211    214   static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
   212         -  tvfs_file *p = (tvfs_file *)pFile;
          215  +  TestvfsFile *p = (TestvfsFile *)pFile;
   213    216     return sqlite3OsCheckReservedLock(p->pReal, pResOut);
   214    217   }
   215    218   
   216    219   /*
   217    220   ** File control method. For custom operations on an tvfs-file.
   218    221   */
   219    222   static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
   220         -  tvfs_file *p = (tvfs_file *)pFile;
          223  +  TestvfsFile *p = (TestvfsFile *)pFile;
   221    224     return sqlite3OsFileControl(p->pReal, op, pArg);
   222    225   }
   223    226   
   224    227   /*
   225    228   ** Return the sector-size in bytes for an tvfs-file.
   226    229   */
   227    230   static int tvfsSectorSize(sqlite3_file *pFile){
   228         -  tvfs_file *p = (tvfs_file *)pFile;
          231  +  TestvfsFile *p = (TestvfsFile *)pFile;
   229    232     return sqlite3OsSectorSize(p->pReal);
   230    233   }
   231    234   
   232    235   /*
   233    236   ** Return the device characteristic flags supported by an tvfs-file.
   234    237   */
   235    238   static int tvfsDeviceCharacteristics(sqlite3_file *pFile){
   236         -  tvfs_file *p = (tvfs_file *)pFile;
          239  +  TestvfsFile *p = (TestvfsFile *)pFile;
   237    240     return sqlite3OsDeviceCharacteristics(p->pReal);
   238    241   }
   239    242   
   240    243   /*
   241    244   ** Open an tvfs file handle.
   242    245   */
   243    246   static int tvfsOpen(
................................................................................
   244    247     sqlite3_vfs *pVfs,
   245    248     const char *zName,
   246    249     sqlite3_file *pFile,
   247    250     int flags,
   248    251     int *pOutFlags
   249    252   ){
   250    253     int rc;
   251         -  tvfs_file *p = (tvfs_file *)pFile;
          254  +  TestvfsFile *p = (TestvfsFile *)pFile;
   252    255     p->pShm = 0;
          256  +  p->pShmId = 0;
   253    257     p->zFilename = zName;
   254    258     p->pVfs = pVfs;
   255    259     p->pReal = (sqlite3_file *)&p[1];
   256    260     rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, p->pReal, flags, pOutFlags);
   257    261     if( p->pReal->pMethods ){
   258         -    pFile->pMethods = &tvfs_io_methods;
          262  +    sqlite3_io_methods *pMethods;
          263  +    pMethods = (sqlite3_io_methods *)ckalloc(sizeof(sqlite3_io_methods));
          264  +    memcpy(pMethods, &tvfs_io_methods, sizeof(sqlite3_io_methods));
          265  +    if( ((Testvfs *)pVfs->pAppData)->isNoshm ){
          266  +      pMethods->xShmOpen = 0;
          267  +      pMethods->xShmGet = 0;
          268  +      pMethods->xShmSize = 0;
          269  +      pMethods->xShmRelease = 0;
          270  +      pMethods->xShmClose = 0;
          271  +      pMethods->xShmLock = 0;
          272  +    }
          273  +    pFile->pMethods = pMethods;
   259    274     }
          275  +
   260    276     return rc;
   261    277   }
   262    278   
   263    279   /*
   264    280   ** Delete the file located at zPath. If the dirSync argument is true,
   265    281   ** ensure the file-system modifications are synced to disk before
   266    282   ** returning.
................................................................................
   347    363   /*
   348    364   ** Return the current time as a Julian Day number in *pTimeOut.
   349    365   */
   350    366   static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
   351    367     return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
   352    368   }
   353    369   
   354         -static void tvfsGrowBuffer(TestvfsShm *pShm, int reqSize, int *pNewSize){
   355         -  TestvfsBuffer *pBuffer = pShm->pBuffer;
          370  +static void tvfsGrowBuffer(TestvfsFile *pFd, int reqSize, int *pNewSize){
          371  +  TestvfsBuffer *pBuffer = pFd->pShm;
   356    372     if( reqSize>pBuffer->n ){
   357    373       pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, reqSize);
   358    374       memset(&pBuffer->a[pBuffer->n], 0x55, reqSize-pBuffer->n);
   359    375       pBuffer->n = reqSize;
   360    376     }
   361    377     *pNewSize = pBuffer->n;
   362    378   }
................................................................................
   417    433   
   418    434     return 0;
   419    435   }
   420    436   
   421    437   static int tvfsShmOpen(
   422    438     sqlite3_file *pFileDes
   423    439   ){
   424         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
          440  +  Testvfs *p;
   425    441     int rc = SQLITE_OK;             /* Return code */
   426    442     Tcl_Obj *pId = 0;               /* Id for this connection */
   427    443     TestvfsBuffer *pBuffer;         /* Buffer to open connection to */
   428         -  TestvfsShm *pShm;               /* New shm handle */
   429         -  tvfs_file *pFd;                 /* The file descriptor */
          444  +  TestvfsFile *pFd;               /* The testvfs file structure */
   430    445   
   431         -  pFd = (tvfs_file*)pFileDes;
          446  +  pFd = (TestvfsFile*)pFileDes;
          447  +  p = (Testvfs *)pFd->pVfs->pAppData;
          448  +  assert( pFd->pShmId==0 && pFd->pShm==0 );
   432    449   
   433    450     /* Evaluate the Tcl script: 
   434    451     **
   435    452     **   SCRIPT xShmOpen FILENAME
   436    453     **
   437    454     ** If the script returns an SQLite error code other than SQLITE_OK, an
   438    455     ** error is returned to the caller. If it returns SQLITE_OK, the new
................................................................................
   443    460     if( tvfsResultCode(p, &rc) ){
   444    461       if( rc!=SQLITE_OK ) return rc;
   445    462       pId = Tcl_NewStringObj("anon", -1);
   446    463     }else{
   447    464       pId = Tcl_GetObjResult(p->interp);
   448    465     }
   449    466     Tcl_IncrRefCount(pId);
   450         -
   451         -  /* Allocate the TestvfsShm handle. */
   452         -  pShm = (TestvfsShm *)ckalloc(sizeof(TestvfsShm));
   453         -  memset(pShm, 0, sizeof(TestvfsShm));
   454         -  pShm->id = pId;
          467  +  pFd->pShmId = pId;
   455    468   
   456    469     /* Search for a TestvfsBuffer. Create a new one if required. */
   457    470     for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
   458         -    if( 0==strcmp(zName, pBuffer->zFile) ) break;
          471  +    if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break;
   459    472     }
   460    473     if( !pBuffer ){
   461         -    int nByte = sizeof(TestvfsBuffer) + strlen(zName) + 1;
          474  +    int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1;
   462    475       pBuffer = (TestvfsBuffer *)ckalloc(nByte);
   463    476       memset(pBuffer, 0, nByte);
   464    477       pBuffer->zFile = (char *)&pBuffer[1];
   465         -    strcpy(pBuffer->zFile, zName);
          478  +    strcpy(pBuffer->zFile, pFd->zFilename);
   466    479       pBuffer->pNext = p->pBuffer;
   467    480       p->pBuffer = pBuffer;
   468    481     }
   469    482   
   470    483     /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
   471    484     pBuffer->nRef++;
   472         -  pShm->pBuffer = pBuffer;
   473         -  *pp = (sqlite3_shm *)pShm;
          485  +  pFd->pShm = pBuffer;
   474    486     return SQLITE_OK;
   475    487   }
   476    488   
   477    489   static int tvfsShmSize(
   478         -  sqlite3_vfs *pVfs,
   479         -  sqlite3_shm *pShmHandle,
          490  +  sqlite3_file *pFile,
   480    491     int reqSize,
   481    492     int *pNewSize
   482    493   ){
   483    494     int rc = SQLITE_OK;
   484         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   485         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          495  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          496  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   486    497   
   487    498     tvfsExecTcl(p, "xShmSize", 
   488         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          499  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   489    500     );
   490    501     tvfsResultCode(p, &rc);
   491    502     if( rc==SQLITE_OK ){
   492         -    tvfsGrowBuffer(pShm, reqSize, pNewSize);
          503  +    tvfsGrowBuffer(pFd, reqSize, pNewSize);
   493    504     }
   494    505     return rc;
   495    506   }
   496    507   
   497    508   static int tvfsShmGet(
   498         -  sqlite3_vfs *pVfs,
   499         -  sqlite3_shm *pShmHandle, 
          509  +  sqlite3_file *pFile, 
   500    510     int reqMapSize, 
   501    511     int *pMapSize, 
   502    512     void **pp
   503    513   ){
   504    514     int rc = SQLITE_OK;
   505         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   506         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          515  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          516  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   507    517   
   508    518     tvfsExecTcl(p, "xShmGet", 
   509         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          519  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   510    520     );
   511    521     tvfsResultCode(p, &rc);
   512    522     if( rc==SQLITE_OK ){
   513         -    tvfsGrowBuffer(pShm, reqMapSize, pMapSize);
   514         -    *pp = pShm->pBuffer->a;
          523  +    tvfsGrowBuffer(pFd, reqMapSize, pMapSize);
          524  +    *pp = pFd->pShm->a;
   515    525     }
   516    526     return rc;
   517    527   }
   518    528   
   519         -static int tvfsShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pShmHandle){
          529  +static int tvfsShmRelease(sqlite3_file *pFile){
   520    530     int rc = SQLITE_OK;
   521         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   522         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          531  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          532  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   523    533   
   524    534     tvfsExecTcl(p, "xShmRelease", 
   525         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          535  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   526    536     );
   527    537     tvfsResultCode(p, &rc);
   528    538   
   529    539     return rc;
   530    540   }
   531    541   
   532    542   static int tvfsShmLock(
   533         -  sqlite3_vfs *pVfs,
   534         -  sqlite3_shm *pShmHandle,
          543  +  sqlite3_file *pFile,
   535    544     int desiredLock,
   536    545     int *gotLock
   537    546   ){
   538    547     int rc = SQLITE_OK;
   539         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   540         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          548  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          549  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   541    550     char *zLock = "";
   542    551   
   543    552     switch( desiredLock ){
   544    553       case SQLITE_SHM_READ:         zLock = "READ";       break;
   545    554       case SQLITE_SHM_WRITE:        zLock = "WRITE";      break;
   546    555       case SQLITE_SHM_CHECKPOINT:   zLock = "CHECKPOINT"; break;
   547    556       case SQLITE_SHM_RECOVER:      zLock = "RECOVER";    break;
   548    557       case SQLITE_SHM_PENDING:      zLock = "PENDING";    break;
   549    558       case SQLITE_SHM_UNLOCK:       zLock = "UNLOCK";     break;
   550    559     }
   551    560     tvfsExecTcl(p, "xShmLock", 
   552         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id,
          561  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
   553    562         Tcl_NewStringObj(zLock, -1)
   554    563     );
   555    564     tvfsResultCode(p, &rc);
   556    565     if( rc==SQLITE_OK ){
   557    566       *gotLock = desiredLock;
   558    567     }
   559    568   
   560    569     return rc;
   561    570   }
   562    571   
   563    572   static int tvfsShmClose(
   564         -  sqlite3_vfs *pVfs, 
   565         -  sqlite3_shm *pShmHandle, 
          573  +  sqlite3_file *pFile,
   566    574     int deleteFlag
   567    575   ){
   568    576     int rc = SQLITE_OK;
   569         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   570         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
   571         -  TestvfsBuffer *pBuffer = pShm->pBuffer;
          577  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          578  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
          579  +  TestvfsBuffer *pBuffer = pFd->pShm;
   572    580   
          581  +  assert( pFd->pShmId && pFd->pShm );
   573    582   #if 0
   574    583     assert( (deleteFlag!=0)==(pBuffer->nRef==1) );
   575    584   #endif
   576    585   
   577    586     tvfsExecTcl(p, "xShmClose", 
   578         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          587  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   579    588     );
   580    589     tvfsResultCode(p, &rc);
   581    590   
   582    591     pBuffer->nRef--;
   583    592     if( pBuffer->nRef==0 ){
   584    593       TestvfsBuffer **pp;
   585    594       for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext));
   586    595       *pp = (*pp)->pNext;
   587    596       ckfree((char *)pBuffer->a);
   588    597       ckfree((char *)pBuffer);
   589    598     }
   590         -  Tcl_DecrRefCount(pShm->id);
   591         -  ckfree((char *)pShm);
          599  +  Tcl_DecrRefCount(pFd->pShmId);
          600  +  pFd->pShmId = 0;
          601  +  pFd->pShm = 0;
   592    602   
   593    603     return rc;
   594    604   }
   595    605   
   596    606   static int testvfs_obj_cmd(
   597    607     ClientData cd,
   598    608     Tcl_Interp *interp,
................................................................................
   698    708   */
   699    709   static int testvfs_cmd(
   700    710     ClientData cd,
   701    711     Tcl_Interp *interp,
   702    712     int objc,
   703    713     Tcl_Obj *CONST objv[]
   704    714   ){
   705         -
   706    715     static sqlite3_vfs tvfs_vfs = {
   707    716       2,                            /* iVersion */
   708         -    sizeof(tvfs_file),            /* szOsFile */
          717  +    sizeof(TestvfsFile),            /* szOsFile */
   709    718       0,                            /* mxPathname */
   710    719       0,                            /* pNext */
   711    720       0,                            /* zName */
   712    721       0,                            /* pAppData */
   713    722       tvfsOpen,                     /* xOpen */
   714    723       tvfsDelete,                   /* xDelete */
   715    724       tvfsAccess,                   /* xAccess */
................................................................................
   775    784     pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs));
   776    785     memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs));
   777    786     pVfs->pAppData = (void *)p;
   778    787     pVfs->zName = p->zName;
   779    788     pVfs->mxPathname = p->pParent->mxPathname;
   780    789     pVfs->szOsFile += p->pParent->szOsFile;
   781    790     p->pVfs = pVfs;
   782         -  if( isNoshm ){
   783         -    pVfs->xShmOpen = 0;
   784         -    pVfs->xShmGet = 0;
   785         -    pVfs->xShmSize = 0;
   786         -    pVfs->xShmRelease = 0;
   787         -    pVfs->xShmClose = 0;
   788         -    pVfs->xShmLock = 0;
   789         -  }
          791  +  p->isNoshm = isNoshm;
   790    792   
   791    793     Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
   792    794     sqlite3_vfs_register(pVfs, 0);
   793    795   
   794    796     return TCL_OK;
   795    797   
   796    798    bad_args:
   797    799     Tcl_WrongNumArgs(interp, 1, objv, "?-noshm? VFSNAME SCRIPT");
   798    800     return TCL_ERROR;
   799    801   }
   800         -#endif /* 0 */
   801    802   
   802    803   int Sqlitetestvfs_Init(Tcl_Interp *interp){
   803         -  /* Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); */
          804  +  Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
   804    805     return TCL_OK;
   805    806   }
   806    807   
   807    808   #endif