/ Check-in [4b69f2cd]
Login

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

Overview
Comment:Pull in all the latest changes from the trunk. Update the win32 SHM methods to work with the new interface design.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal-win32
Files: files | file ages | folders
SHA1: 4b69f2cd315b6b66d10e5190d235114788853258
User & Date: drh 2010-05-14 16:34:35
Original Comment: Pull in all the latest changes from the trunk. Update the win32 SHM methods to work with the new interface design.
Context
2010-05-19
23:41
Merge WIN32 WAL support into trunk. Still some issues with locking to resolve. check-in: 43377663 user: shaneh tags: trunk
2010-05-14
16:34
Pull in all the latest changes from the trunk. Update the win32 SHM methods to work with the new interface design. Closed-Leaf check-in: 4b69f2cd user: drh tags: wal-win32
14:52
Simplifications to the SHM implementation in os_unix.c, taking advantage of the removal of the LinuxThreads mess. check-in: d1debe5d user: drh tags: trunk
2010-05-12
17:14
Updates to WAL support in os_win.c: pulled in latest changes from src/os_unix.c; updated tracing; misc. improvements. check-in: 76504726 user: shaneh tags: wal-win32
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to doc/vfs-shm.txt.

    74     74   
    75     75   The SQLite core will obey the next set of rules.  These rules are
    76     76   assertions on the behavior of the SQLite core which might be verified
    77     77   during testing using an instrumented lock manager.
    78     78   
    79     79   (5)  No part of the wal-index will be read without holding either some
    80     80        kind of SHM lock or an EXCLUSIVE lock on the original database.
           81  +     The original database is the file named in the 2nd parameter to
           82  +     the xShmOpen method.
           83  +
    81     84   (6)  A holder of a READ_FULL will never read any page of the database
    82     85        file that is contained anywhere in the wal-index.
           86  +
    83     87   (7)  No part of the wal-index other than the header will be written nor
    84         -     will the size of the wal-index grow without holding a WRITE.
           88  +     will the size of the wal-index grow without holding a WRITE or
           89  +     an EXCLUSIVE on the original database file.
           90  +
    85     91   (8)  The wal-index header will not be written without holding one of
    86         -     WRITE, CHECKPOINT, or RECOVER.
    87         -(9)  A CHECKPOINT or RECOVER must be held in order to reset the last valid
    88         -     frame counter in the header of the wal-index back to zero.
           92  +     WRITE, CHECKPOINT, or RECOVER on the wal-index or an EXCLUSIVE on
           93  +     the original database files.
           94  +
           95  +(9)  A CHECKPOINT or RECOVER must be held on the wal-index, or an
           96  +     EXCLUSIVE on the original database file, in order to reset the 
           97  +     last valid frame counter in the header of the wal-index back to zero.
           98  +
    89     99   (10) A WRITE can only increase the last valid frame pointer in the header.
    90    100   
    91    101   The SQLite core will only ever send requests for UNLOCK, READ, WRITE,
    92    102   CHECKPOINT, or RECOVER to the lock manager.   The SQLite core will never
    93    103   request a READ_FULL or PENDING lock though the lock manager may deliver
    94    104   those locking states in response to READ and CHECKPOINT requests,
    95    105   respectively, if and only if the requested READ or CHECKPOINT cannot

Changes to src/expr.c.

  2349   2349         assert( z[n]=='\'' );
  2350   2350         zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
  2351   2351         sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
  2352   2352         break;
  2353   2353       }
  2354   2354   #endif
  2355   2355       case TK_VARIABLE: {
  2356         -      VdbeOp *pOp;
  2357   2356         assert( !ExprHasProperty(pExpr, EP_IntValue) );
  2358   2357         assert( pExpr->u.zToken!=0 );
  2359   2358         assert( pExpr->u.zToken[0]!=0 );
  2360         -      if( pExpr->u.zToken[1]==0
  2361         -         && (pOp = sqlite3VdbeGetOp(v, -1))->opcode==OP_Variable
  2362         -         && pOp->p1+pOp->p3==pExpr->iColumn
  2363         -         && pOp->p2+pOp->p3==target
  2364         -         && pOp->p4.z==0
  2365         -      ){
  2366         -        /* If the previous instruction was a copy of the previous unnamed
  2367         -        ** parameter into the previous register, then simply increment the
  2368         -        ** repeat count on the prior instruction rather than making a new
  2369         -        ** instruction.
  2370         -        */
  2371         -        pOp->p3++;
  2372         -      }else{
  2373         -        sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iColumn, target, 1);
  2374         -        if( pExpr->u.zToken[1]!=0 ){
  2375         -          sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0);
  2376         -        }
         2359  +      sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
         2360  +      if( pExpr->u.zToken[1]!=0 ){
         2361  +        sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0);
  2377   2362         }
  2378   2363         break;
  2379   2364       }
  2380   2365       case TK_REGISTER: {
  2381   2366         inReg = pExpr->iTable;
  2382   2367         break;
  2383   2368       }

Changes to src/mutex_unix.c.

    20     20   ** Note that this implementation requires a version of pthreads that
    21     21   ** supports recursive mutexes.
    22     22   */
    23     23   #ifdef SQLITE_MUTEX_PTHREADS
    24     24   
    25     25   #include <pthread.h>
    26     26   
           27  +/*
           28  +** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
           29  +** are necessary under two condidtions:  (1) Debug builds and (2) using
           30  +** home-grown mutexes.  Encapsulate these conditions into a single #define.
           31  +*/
           32  +#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
           33  +# define SQLITE_MUTEX_NREF 1
           34  +#else
           35  +# define SQLITE_MUTEX_NREF 0
           36  +#endif
    27     37   
    28     38   /*
    29     39   ** Each recursive mutex is an instance of the following structure.
    30     40   */
    31     41   struct sqlite3_mutex {
    32     42     pthread_mutex_t mutex;     /* Mutex controlling the lock */
           43  +#if SQLITE_MUTEX_NREF
    33     44     int id;                    /* Mutex type */
    34         -  int nRef;                  /* Number of entrances */
    35         -  pthread_t owner;           /* Thread that is within this mutex */
    36         -#ifdef SQLITE_DEBUG
           45  +  volatile int nRef;         /* Number of entrances */
           46  +  volatile pthread_t owner;  /* Thread that is within this mutex */
    37     47     int trace;                 /* True to trace changes */
    38     48   #endif
    39     49   };
    40         -#ifdef SQLITE_DEBUG
           50  +#if SQLITE_MUTEX_NREF
    41     51   #define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
    42     52   #else
    43         -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0 }
           53  +#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
    44     54   #endif
    45     55   
    46     56   /*
    47     57   ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
    48     58   ** intended for use only inside assert() statements.  On some platforms,
    49     59   ** there might be race conditions that can cause these routines to
    50     60   ** deliver incorrect results.  In particular, if pthread_equal() is
................................................................................
   138    148           /* Use a recursive mutex if it is available */
   139    149           pthread_mutexattr_t recursiveAttr;
   140    150           pthread_mutexattr_init(&recursiveAttr);
   141    151           pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
   142    152           pthread_mutex_init(&p->mutex, &recursiveAttr);
   143    153           pthread_mutexattr_destroy(&recursiveAttr);
   144    154   #endif
          155  +#if SQLITE_MUTEX_NREF
   145    156           p->id = iType;
          157  +#endif
   146    158         }
   147    159         break;
   148    160       }
   149    161       case SQLITE_MUTEX_FAST: {
   150    162         p = sqlite3MallocZero( sizeof(*p) );
   151    163         if( p ){
          164  +#if SQLITE_MUTEX_NREF
   152    165           p->id = iType;
          166  +#endif
   153    167           pthread_mutex_init(&p->mutex, 0);
   154    168         }
   155    169         break;
   156    170       }
   157    171       default: {
   158    172         assert( iType-2 >= 0 );
   159    173         assert( iType-2 < ArraySize(staticMutexes) );
   160    174         p = &staticMutexes[iType-2];
          175  +#if SQLITE_MUTEX_NREF
   161    176         p->id = iType;
          177  +#endif
   162    178         break;
   163    179       }
   164    180     }
   165    181     return p;
   166    182   }
   167    183   
   168    184   
................................................................................
   214    230         p->nRef = 1;
   215    231       }
   216    232     }
   217    233   #else
   218    234     /* Use the built-in recursive mutexes if they are available.
   219    235     */
   220    236     pthread_mutex_lock(&p->mutex);
          237  +#if SQLITE_MUTEX_NREF
   221    238     p->owner = pthread_self();
   222    239     p->nRef++;
          240  +#endif
   223    241   #endif
   224    242   
   225    243   #ifdef SQLITE_DEBUG
   226    244     if( p->trace ){
   227    245       printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
   228    246     }
   229    247   #endif
................................................................................
   257    275         rc = SQLITE_BUSY;
   258    276       }
   259    277     }
   260    278   #else
   261    279     /* Use the built-in recursive mutexes if they are available.
   262    280     */
   263    281     if( pthread_mutex_trylock(&p->mutex)==0 ){
          282  +#if SQLITE_MUTEX_NREF
   264    283       p->owner = pthread_self();
   265    284       p->nRef++;
          285  +#endif
   266    286       rc = SQLITE_OK;
   267    287     }else{
   268    288       rc = SQLITE_BUSY;
   269    289     }
   270    290   #endif
   271    291   
   272    292   #ifdef SQLITE_DEBUG
................................................................................
   281    301   ** The sqlite3_mutex_leave() routine exits a mutex that was
   282    302   ** previously entered by the same thread.  The behavior
   283    303   ** is undefined if the mutex is not currently entered or
   284    304   ** is not currently allocated.  SQLite will never do either.
   285    305   */
   286    306   static void pthreadMutexLeave(sqlite3_mutex *p){
   287    307     assert( pthreadMutexHeld(p) );
          308  +#if SQLITE_MUTEX_NREF
   288    309     p->nRef--;
          310  +#endif
   289    311     assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
   290    312   
   291    313   #ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
   292    314     if( p->nRef==0 ){
   293    315       pthread_mutex_unlock(&p->mutex);
   294    316     }
   295    317   #else

Changes to src/mutex_w32.c.

    21     21   
    22     22   /*
    23     23   ** Each recursive mutex is an instance of the following structure.
    24     24   */
    25     25   struct sqlite3_mutex {
    26     26     CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
    27     27     int id;                    /* Mutex type */
    28         -  int nRef;                  /* Number of enterances */
    29         -  DWORD owner;               /* Thread holding this mutex */
    30     28   #ifdef SQLITE_DEBUG
           29  +  volatile int nRef;         /* Number of enterances */
           30  +  volatile DWORD owner;      /* Thread holding this mutex */
    31     31     int trace;                 /* True to trace changes */
    32     32   #endif
    33     33   };
    34     34   #define SQLITE_W32_MUTEX_INITIALIZER { 0 }
    35     35   #ifdef SQLITE_DEBUG
    36     36   #define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
    37     37   #else
    38         -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0 }
           38  +#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 }
    39     39   #endif
    40     40   
    41     41   /*
    42     42   ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
    43     43   ** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
    44     44   **
    45     45   ** Here is an interesting observation:  Win95, Win98, and WinME lack
................................................................................
   187    187     sqlite3_mutex *p;
   188    188   
   189    189     switch( iType ){
   190    190       case SQLITE_MUTEX_FAST:
   191    191       case SQLITE_MUTEX_RECURSIVE: {
   192    192         p = sqlite3MallocZero( sizeof(*p) );
   193    193         if( p ){  
          194  +#ifdef SQLITE_DEBUG
   194    195           p->id = iType;
          196  +#endif
   195    197           InitializeCriticalSection(&p->mutex);
   196    198         }
   197    199         break;
   198    200       }
   199    201       default: {
   200    202         assert( winMutex_isInit==1 );
   201    203         assert( iType-2 >= 0 );
   202    204         assert( iType-2 < ArraySize(winMutex_staticMutexes) );
   203    205         p = &winMutex_staticMutexes[iType-2];
          206  +#ifdef SQLITE_DEBUG
   204    207         p->id = iType;
          208  +#endif
   205    209         break;
   206    210       }
   207    211     }
   208    212     return p;
   209    213   }
   210    214   
   211    215   
................................................................................
   230    234   ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
   231    235   ** be entered multiple times by the same thread.  In such cases the,
   232    236   ** mutex must be exited an equal number of times before another thread
   233    237   ** can enter.  If the same thread tries to enter any other kind of mutex
   234    238   ** more than once, the behavior is undefined.
   235    239   */
   236    240   static void winMutexEnter(sqlite3_mutex *p){
          241  +#ifdef SQLITE_DEBUG
   237    242     DWORD tid = GetCurrentThreadId(); 
   238    243     assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
          244  +#endif
   239    245     EnterCriticalSection(&p->mutex);
          246  +#ifdef SQLITE_DEBUG
   240    247     p->owner = tid; 
   241    248     p->nRef++;
   242         -#ifdef SQLITE_DEBUG
   243    249     if( p->trace ){
   244    250       printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
   245    251     }
   246    252   #endif
   247    253   }
   248    254   static int winMutexTry(sqlite3_mutex *p){
   249    255   #ifndef NDEBUG
................................................................................
   284    290   ** previously entered by the same thread.  The behavior
   285    291   ** is undefined if the mutex is not currently entered or
   286    292   ** is not currently allocated.  SQLite will never do either.
   287    293   */
   288    294   static void winMutexLeave(sqlite3_mutex *p){
   289    295   #ifndef NDEBUG
   290    296     DWORD tid = GetCurrentThreadId();
   291         -#endif
   292    297     assert( p->nRef>0 );
   293    298     assert( p->owner==tid );
   294    299     p->nRef--;
   295    300     assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
          301  +#endif
   296    302     LeaveCriticalSection(&p->mutex);
   297    303   #ifdef SQLITE_DEBUG
   298    304     if( p->trace ){
   299    305       printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
   300    306     }
   301    307   #endif
   302    308   }

Changes to src/os.c.

    94     94   int sqlite3OsSectorSize(sqlite3_file *id){
    95     95     int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
    96     96     return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
    97     97   }
    98     98   int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
    99     99     return id->pMethods->xDeviceCharacteristics(id);
   100    100   }
          101  +int sqlite3OsShmOpen(sqlite3_file *id){
          102  +  return id->pMethods->xShmOpen(id);
          103  +}
          104  +int sqlite3OsShmSize(sqlite3_file *id, int reqSize, int *pNewSize){
          105  +  return id->pMethods->xShmSize(id, reqSize, pNewSize);
          106  +}
          107  +int sqlite3OsShmGet(sqlite3_file *id, int reqSize, int *pSize, void **pp){
          108  +  return id->pMethods->xShmGet(id, reqSize, pSize, pp);
          109  +}
          110  +int sqlite3OsShmRelease(sqlite3_file *id){
          111  +  return id->pMethods->xShmRelease(id);
          112  +}
          113  +int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){
          114  +  return id->pMethods->xShmLock(id, desiredLock, pGotLock);
          115  +}
          116  +int sqlite3OsShmClose(sqlite3_file *id, int deleteFlag){
          117  +  return id->pMethods->xShmClose(id, deleteFlag);
          118  +}
   101    119   
   102    120   /*
   103    121   ** The next group of routines are convenience wrappers around the
   104    122   ** VFS methods.
   105    123   */
   106    124   int sqlite3OsOpen(
   107    125     sqlite3_vfs *pVfs, 

Changes to src/os.h.

   239    239   int sqlite3OsLock(sqlite3_file*, int);
   240    240   int sqlite3OsUnlock(sqlite3_file*, int);
   241    241   int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
   242    242   int sqlite3OsFileControl(sqlite3_file*,int,void*);
   243    243   #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
   244    244   int sqlite3OsSectorSize(sqlite3_file *id);
   245    245   int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
          246  +int sqlite3OsShmOpen(sqlite3_file *id);
          247  +int sqlite3OsShmSize(sqlite3_file *id, int, int*);
          248  +int sqlite3OsShmGet(sqlite3_file *id, int, int*, void**);
          249  +int sqlite3OsShmRelease(sqlite3_file *id);
          250  +int sqlite3OsShmLock(sqlite3_file *id, int, int*);
          251  +int sqlite3OsShmClose(sqlite3_file *id, int);
   246    252   
   247    253   /* 
   248    254   ** Functions for accessing sqlite3_vfs methods 
   249    255   */
   250    256   int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
   251    257   int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
   252    258   int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);

Changes to src/os_common.h.

    27     27   */
    28     28   #ifdef MEMORY_DEBUG
    29     29   # error "The MEMORY_DEBUG macro is obsolete.  Use SQLITE_DEBUG instead."
    30     30   #endif
    31     31   
    32     32   #ifdef SQLITE_DEBUG
    33     33   int sqlite3OSTrace = 0;
    34         -#define OSTRACE1(X)         if( sqlite3OSTrace ) sqlite3DebugPrintf(X)
    35         -#define OSTRACE2(X,Y)       if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y)
    36         -#define OSTRACE3(X,Y,Z)     if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z)
    37         -#define OSTRACE4(X,Y,Z,A)   if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A)
    38         -#define OSTRACE5(X,Y,Z,A,B) if( sqlite3OSTrace ) sqlite3DebugPrintf(X,Y,Z,A,B)
    39         -#define OSTRACE6(X,Y,Z,A,B,C) \
    40         -    if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
    41         -#define OSTRACE7(X,Y,Z,A,B,C,D) \
    42         -    if(sqlite3OSTrace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
    43     34   #define OSTRACE(X)          if( sqlite3OSTrace ) sqlite3DebugPrintf X
    44     35   #else
    45         -#define OSTRACE1(X)
    46         -#define OSTRACE2(X,Y)
    47         -#define OSTRACE3(X,Y,Z)
    48         -#define OSTRACE4(X,Y,Z,A)
    49         -#define OSTRACE5(X,Y,Z,A,B)
    50         -#define OSTRACE6(X,Y,Z,A,B,C)
    51         -#define OSTRACE7(X,Y,Z,A,B,C,D)
    52     36   #define OSTRACE(X)
    53     37   #endif
    54     38   
    55     39   /*
    56     40   ** Macros for performance tracing.  Normally turned off.  Only works
    57     41   ** on i486 hardware.
    58     42   */

Changes to src/os_os2.c.

    77     77   /*
    78     78   ** Close a file.
    79     79   */
    80     80   static int os2Close( sqlite3_file *id ){
    81     81     APIRET rc = NO_ERROR;
    82     82     os2File *pFile;
    83     83     if( id && (pFile = (os2File*)id) != 0 ){
    84         -    OSTRACE2( "CLOSE %d\n", pFile->h );
           84  +    OSTRACE(( "CLOSE %d\n", pFile->h ));
    85     85       rc = DosClose( pFile->h );
    86     86       pFile->locktype = NO_LOCK;
    87     87       if( pFile->pathToDel != NULL ){
    88     88         rc = DosForceDelete( (PSZ)pFile->pathToDel );
    89     89         free( pFile->pathToDel );
    90     90         pFile->pathToDel = NULL;
    91     91       }
................................................................................
   108    108     sqlite3_int64 offset            /* Begin reading at this offset */
   109    109   ){
   110    110     ULONG fileLocation = 0L;
   111    111     ULONG got;
   112    112     os2File *pFile = (os2File*)id;
   113    113     assert( id!=0 );
   114    114     SimulateIOError( return SQLITE_IOERR_READ );
   115         -  OSTRACE3( "READ %d lock=%d\n", pFile->h, pFile->locktype );
          115  +  OSTRACE(( "READ %d lock=%d\n", pFile->h, pFile->locktype ));
   116    116     if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
   117    117       return SQLITE_IOERR;
   118    118     }
   119    119     if( DosRead( pFile->h, pBuf, amt, &got ) != NO_ERROR ){
   120    120       return SQLITE_IOERR_READ;
   121    121     }
   122    122     if( got == (ULONG)amt )
................................................................................
   141    141     ULONG fileLocation = 0L;
   142    142     APIRET rc = NO_ERROR;
   143    143     ULONG wrote;
   144    144     os2File *pFile = (os2File*)id;
   145    145     assert( id!=0 );
   146    146     SimulateIOError( return SQLITE_IOERR_WRITE );
   147    147     SimulateDiskfullError( return SQLITE_FULL );
   148         -  OSTRACE3( "WRITE %d lock=%d\n", pFile->h, pFile->locktype );
          148  +  OSTRACE(( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ));
   149    149     if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){
   150    150       return SQLITE_IOERR;
   151    151     }
   152    152     assert( amt>0 );
   153    153     while( amt > 0 &&
   154    154            ( rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote ) ) == NO_ERROR &&
   155    155            wrote > 0
................................................................................
   163    163   
   164    164   /*
   165    165   ** Truncate an open file to a specified size
   166    166   */
   167    167   static int os2Truncate( sqlite3_file *id, i64 nByte ){
   168    168     APIRET rc = NO_ERROR;
   169    169     os2File *pFile = (os2File*)id;
   170         -  OSTRACE3( "TRUNCATE %d %lld\n", pFile->h, nByte );
          170  +  OSTRACE(( "TRUNCATE %d %lld\n", pFile->h, nByte ));
   171    171     SimulateIOError( return SQLITE_IOERR_TRUNCATE );
   172    172     rc = DosSetFileSize( pFile->h, nByte );
   173    173     return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
   174    174   }
   175    175   
   176    176   #ifdef SQLITE_TEST
   177    177   /*
................................................................................
   183    183   #endif
   184    184   
   185    185   /*
   186    186   ** Make sure all writes to a particular file are committed to disk.
   187    187   */
   188    188   static int os2Sync( sqlite3_file *id, int flags ){
   189    189     os2File *pFile = (os2File*)id;
   190         -  OSTRACE3( "SYNC %d lock=%d\n", pFile->h, pFile->locktype );
          190  +  OSTRACE(( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ));
   191    191   #ifdef SQLITE_TEST
   192    192     if( flags & SQLITE_SYNC_FULL){
   193    193       sqlite3_fullsync_count++;
   194    194     }
   195    195     sqlite3_sync_count++;
   196    196   #endif
   197    197     /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
................................................................................
   233    233     memset(&LockArea, 0, sizeof(LockArea));
   234    234     memset(&UnlockArea, 0, sizeof(UnlockArea));
   235    235     LockArea.lOffset = SHARED_FIRST;
   236    236     LockArea.lRange = SHARED_SIZE;
   237    237     UnlockArea.lOffset = 0L;
   238    238     UnlockArea.lRange = 0L;
   239    239     res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
   240         -  OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res );
          240  +  OSTRACE(( "GETREADLOCK %d res=%d\n", pFile->h, res ));
   241    241     return res;
   242    242   }
   243    243   
   244    244   /*
   245    245   ** Undo a readlock
   246    246   */
   247    247   static int unlockReadLock( os2File *id ){
................................................................................
   251    251     memset(&LockArea, 0, sizeof(LockArea));
   252    252     memset(&UnlockArea, 0, sizeof(UnlockArea));
   253    253     LockArea.lOffset = 0L;
   254    254     LockArea.lRange = 0L;
   255    255     UnlockArea.lOffset = SHARED_FIRST;
   256    256     UnlockArea.lRange = SHARED_SIZE;
   257    257     res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 1L );
   258         -  OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res );
          258  +  OSTRACE(( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ));
   259    259     return res;
   260    260   }
   261    261   
   262    262   /*
   263    263   ** Lock the file with the lock specified by parameter locktype - one
   264    264   ** of the following:
   265    265   **
................................................................................
   292    292     int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
   293    293     FILELOCK  LockArea,
   294    294               UnlockArea;
   295    295     os2File *pFile = (os2File*)id;
   296    296     memset(&LockArea, 0, sizeof(LockArea));
   297    297     memset(&UnlockArea, 0, sizeof(UnlockArea));
   298    298     assert( pFile!=0 );
   299         -  OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype );
          299  +  OSTRACE(( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ));
   300    300   
   301    301     /* If there is already a lock of this type or more restrictive on the
   302    302     ** os2File, do nothing. Don't use the end_lock: exit path, as
   303    303     ** sqlite3_mutex_enter() hasn't been called yet.
   304    304     */
   305    305     if( pFile->locktype>=locktype ){
   306         -    OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype );
          306  +    OSTRACE(( "LOCK %d %d ok (already held)\n", pFile->h, locktype ));
   307    307       return SQLITE_OK;
   308    308     }
   309    309   
   310    310     /* Make sure the locking sequence is correct
   311    311     */
   312    312     assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
   313    313     assert( locktype!=PENDING_LOCK );
................................................................................
   326    326       UnlockArea.lOffset = 0L;
   327    327       UnlockArea.lRange = 0L;
   328    328   
   329    329       /* wait longer than LOCK_TIMEOUT here not to have to try multiple times */
   330    330       res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 100L, 0L );
   331    331       if( res == NO_ERROR ){
   332    332         gotPendingLock = 1;
   333         -      OSTRACE3( "LOCK %d pending lock boolean set.  res=%d\n", pFile->h, res );
          333  +      OSTRACE(( "LOCK %d pending lock boolean set.  res=%d\n", pFile->h, res ));
   334    334       }
   335    335     }
   336    336   
   337    337     /* Acquire a shared lock
   338    338     */
   339    339     if( locktype==SHARED_LOCK && res == NO_ERROR ){
   340    340       assert( pFile->locktype==NO_LOCK );
   341    341       res = getReadLock(pFile);
   342    342       if( res == NO_ERROR ){
   343    343         newLocktype = SHARED_LOCK;
   344    344       }
   345         -    OSTRACE3( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res );
          345  +    OSTRACE(( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ));
   346    346     }
   347    347   
   348    348     /* Acquire a RESERVED lock
   349    349     */
   350    350     if( locktype==RESERVED_LOCK && res == NO_ERROR ){
   351    351       assert( pFile->locktype==SHARED_LOCK );
   352    352       LockArea.lOffset = RESERVED_BYTE;
................................................................................
   353    353       LockArea.lRange = 1L;
   354    354       UnlockArea.lOffset = 0L;
   355    355       UnlockArea.lRange = 0L;
   356    356       res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   357    357       if( res == NO_ERROR ){
   358    358         newLocktype = RESERVED_LOCK;
   359    359       }
   360         -    OSTRACE3( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res );
          360  +    OSTRACE(( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ));
   361    361     }
   362    362   
   363    363     /* Acquire a PENDING lock
   364    364     */
   365    365     if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
   366    366       newLocktype = PENDING_LOCK;
   367    367       gotPendingLock = 0;
   368         -    OSTRACE2( "LOCK %d acquire pending lock. pending lock boolean unset.\n", pFile->h );
          368  +    OSTRACE(( "LOCK %d acquire pending lock. pending lock boolean unset.\n",
          369  +               pFile->h ));
   369    370     }
   370    371   
   371    372     /* Acquire an EXCLUSIVE lock
   372    373     */
   373    374     if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){
   374    375       assert( pFile->locktype>=SHARED_LOCK );
   375    376       res = unlockReadLock(pFile);
   376         -    OSTRACE2( "unreadlock = %d\n", res );
          377  +    OSTRACE(( "unreadlock = %d\n", res ));
   377    378       LockArea.lOffset = SHARED_FIRST;
   378    379       LockArea.lRange = SHARED_SIZE;
   379    380       UnlockArea.lOffset = 0L;
   380    381       UnlockArea.lRange = 0L;
   381    382       res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   382    383       if( res == NO_ERROR ){
   383    384         newLocktype = EXCLUSIVE_LOCK;
   384    385       }else{
   385         -      OSTRACE2( "OS/2 error-code = %d\n", res );
          386  +      OSTRACE(( "OS/2 error-code = %d\n", res ));
   386    387         getReadLock(pFile);
   387    388       }
   388         -    OSTRACE3( "LOCK %d acquire exclusive lock.  res=%d\n", pFile->h, res );
          389  +    OSTRACE(( "LOCK %d acquire exclusive lock.  res=%d\n", pFile->h, res ));
   389    390     }
   390    391   
   391    392     /* If we are holding a PENDING lock that ought to be released, then
   392    393     ** release it now.
   393    394     */
   394    395     if( gotPendingLock && locktype==SHARED_LOCK ){
   395    396       int r;
   396    397       LockArea.lOffset = 0L;
   397    398       LockArea.lRange = 0L;
   398    399       UnlockArea.lOffset = PENDING_BYTE;
   399    400       UnlockArea.lRange = 1L;
   400    401       r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   401         -    OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r );
          402  +    OSTRACE(( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ));
   402    403     }
   403    404   
   404    405     /* Update the state of the lock has held in the file descriptor then
   405    406     ** return the appropriate result code.
   406    407     */
   407    408     if( res == NO_ERROR ){
   408    409       rc = SQLITE_OK;
   409    410     }else{
   410         -    OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
   411         -              locktype, newLocktype );
          411  +    OSTRACE(( "LOCK FAILED %d trying for %d but got %d\n", pFile->h,
          412  +              locktype, newLocktype ));
   412    413       rc = SQLITE_BUSY;
   413    414     }
   414    415     pFile->locktype = newLocktype;
   415         -  OSTRACE3( "LOCK %d now %d\n", pFile->h, pFile->locktype );
          416  +  OSTRACE(( "LOCK %d now %d\n", pFile->h, pFile->locktype ));
   416    417     return rc;
   417    418   }
   418    419   
   419    420   /*
   420    421   ** This routine checks if there is a RESERVED lock held on the specified
   421    422   ** file by this or any other process. If such a lock is held, return
   422    423   ** non-zero, otherwise zero.
................................................................................
   423    424   */
   424    425   static int os2CheckReservedLock( sqlite3_file *id, int *pOut ){
   425    426     int r = 0;
   426    427     os2File *pFile = (os2File*)id;
   427    428     assert( pFile!=0 );
   428    429     if( pFile->locktype>=RESERVED_LOCK ){
   429    430       r = 1;
   430         -    OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, r );
          431  +    OSTRACE(( "TEST WR-LOCK %d %d (local)\n", pFile->h, r ));
   431    432     }else{
   432    433       FILELOCK  LockArea,
   433    434                 UnlockArea;
   434    435       APIRET rc = NO_ERROR;
   435    436       memset(&LockArea, 0, sizeof(LockArea));
   436    437       memset(&UnlockArea, 0, sizeof(UnlockArea));
   437    438       LockArea.lOffset = RESERVED_BYTE;
   438    439       LockArea.lRange = 1L;
   439    440       UnlockArea.lOffset = 0L;
   440    441       UnlockArea.lRange = 0L;
   441    442       rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   442         -    OSTRACE3( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc );
          443  +    OSTRACE(( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ));
   443    444       if( rc == NO_ERROR ){
   444    445         APIRET rcu = NO_ERROR; /* return code for unlocking */
   445    446         LockArea.lOffset = 0L;
   446    447         LockArea.lRange = 0L;
   447    448         UnlockArea.lOffset = RESERVED_BYTE;
   448    449         UnlockArea.lRange = 1L;
   449    450         rcu = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   450         -      OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu );
          451  +      OSTRACE(( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, rcu ));
   451    452       }
   452    453       r = !(rc == NO_ERROR);
   453         -    OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r );
          454  +    OSTRACE(( "TEST WR-LOCK %d %d (remote)\n", pFile->h, r ));
   454    455     }
   455    456     *pOut = r;
   456    457     return SQLITE_OK;
   457    458   }
   458    459   
   459    460   /*
   460    461   ** Lower the locking level on file descriptor id to locktype.  locktype
................................................................................
   474    475     APIRET res = NO_ERROR;
   475    476     FILELOCK  LockArea,
   476    477               UnlockArea;
   477    478     memset(&LockArea, 0, sizeof(LockArea));
   478    479     memset(&UnlockArea, 0, sizeof(UnlockArea));
   479    480     assert( pFile!=0 );
   480    481     assert( locktype<=SHARED_LOCK );
   481         -  OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype );
          482  +  OSTRACE(( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ));
   482    483     type = pFile->locktype;
   483    484     if( type>=EXCLUSIVE_LOCK ){
   484    485       LockArea.lOffset = 0L;
   485    486       LockArea.lRange = 0L;
   486    487       UnlockArea.lOffset = SHARED_FIRST;
   487    488       UnlockArea.lRange = SHARED_SIZE;
   488    489       res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   489         -    OSTRACE3( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res );
          490  +    OSTRACE(( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ));
   490    491       if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){
   491    492         /* This should never happen.  We should always be able to
   492    493         ** reacquire the read lock */
   493         -      OSTRACE3( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype );
          494  +      OSTRACE(( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ));
   494    495         rc = SQLITE_IOERR_UNLOCK;
   495    496       }
   496    497     }
   497    498     if( type>=RESERVED_LOCK ){
   498    499       LockArea.lOffset = 0L;
   499    500       LockArea.lRange = 0L;
   500    501       UnlockArea.lOffset = RESERVED_BYTE;
   501    502       UnlockArea.lRange = 1L;
   502    503       res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   503         -    OSTRACE3( "UNLOCK %d reserved res=%d\n", pFile->h, res );
          504  +    OSTRACE(( "UNLOCK %d reserved res=%d\n", pFile->h, res ));
   504    505     }
   505    506     if( locktype==NO_LOCK && type>=SHARED_LOCK ){
   506    507       res = unlockReadLock(pFile);
   507         -    OSTRACE5( "UNLOCK %d is %d want %d res=%d\n", pFile->h, type, locktype, res );
          508  +    OSTRACE(( "UNLOCK %d is %d want %d res=%d\n",
          509  +              pFile->h, type, locktype, res ));
   508    510     }
   509    511     if( type>=PENDING_LOCK ){
   510    512       LockArea.lOffset = 0L;
   511    513       LockArea.lRange = 0L;
   512    514       UnlockArea.lOffset = PENDING_BYTE;
   513    515       UnlockArea.lRange = 1L;
   514    516       res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, LOCK_TIMEOUT, 0L );
   515         -    OSTRACE3( "UNLOCK %d pending res=%d\n", pFile->h, res );
          517  +    OSTRACE(( "UNLOCK %d pending res=%d\n", pFile->h, res ));
   516    518     }
   517    519     pFile->locktype = locktype;
   518         -  OSTRACE3( "UNLOCK %d now %d\n", pFile->h, pFile->locktype );
          520  +  OSTRACE(( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ));
   519    521     return rc;
   520    522   }
   521    523   
   522    524   /*
   523    525   ** Control and query of the open file handle.
   524    526   */
   525    527   static int os2FileControl(sqlite3_file *id, int op, void *pArg){
   526    528     switch( op ){
   527    529       case SQLITE_FCNTL_LOCKSTATE: {
   528    530         *(int*)pArg = ((os2File*)id)->locktype;
   529         -      OSTRACE3( "FCNTL_LOCKSTATE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype );
          531  +      OSTRACE(( "FCNTL_LOCKSTATE %d lock=%d\n",
          532  +                ((os2File*)id)->h, ((os2File*)id)->locktype ));
   530    533         return SQLITE_OK;
   531    534       }
   532    535     }
   533    536     return SQLITE_ERROR;
   534    537   }
   535    538   
   536    539   /*
................................................................................
   709    712     }
   710    713     j = sqlite3Strlen30( zBuf );
   711    714     sqlite3_randomness( 20, &zBuf[j] );
   712    715     for( i = 0; i < 20; i++, j++ ){
   713    716       zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
   714    717     }
   715    718     zBuf[j] = 0;
   716         -  OSTRACE2( "TEMP FILENAME: %s\n", zBuf );
          719  +  OSTRACE(( "TEMP FILENAME: %s\n", zBuf ));
   717    720     return SQLITE_OK;
   718    721   }
   719    722   
   720    723   
   721    724   /*
   722    725   ** Turn a relative pathname into a full pathname.  Write the full
   723    726   ** pathname into zFull[].  zFull[] will be at least pVfs->mxPathname
................................................................................
   772    775       }
   773    776       zName = zTmpname;
   774    777     }
   775    778   
   776    779   
   777    780     memset( pFile, 0, sizeof(*pFile) );
   778    781   
   779         -  OSTRACE2( "OPEN want %d\n", flags );
          782  +  OSTRACE( "OPEN want %d\n", flags ));
   780    783   
   781    784     if( flags & SQLITE_OPEN_READWRITE ){
   782    785       ulOpenMode |= OPEN_ACCESS_READWRITE;
   783         -    OSTRACE1( "OPEN read/write\n" );
          786  +    OSTRACE(( "OPEN read/write\n" ));
   784    787     }else{
   785    788       ulOpenMode |= OPEN_ACCESS_READONLY;
   786         -    OSTRACE1( "OPEN read only\n" );
          789  +    OSTRACE(( "OPEN read only\n" ));
   787    790     }
   788    791   
   789    792     if( flags & SQLITE_OPEN_CREATE ){
   790    793       ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
   791         -    OSTRACE1( "OPEN open new/create\n" );
          794  +    OSTRACE(( "OPEN open new/create\n" ));
   792    795     }else{
   793    796       ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
   794         -    OSTRACE1( "OPEN open existing\n" );
          797  +    OSTRACE(( "OPEN open existing\n" ));
   795    798     }
   796    799   
   797    800     if( flags & SQLITE_OPEN_MAIN_DB ){
   798    801       ulOpenMode |= OPEN_SHARE_DENYNONE;
   799         -    OSTRACE1( "OPEN share read/write\n" );
          802  +    OSTRACE(( "OPEN share read/write\n" ));
   800    803     }else{
   801    804       ulOpenMode |= OPEN_SHARE_DENYWRITE;
   802         -    OSTRACE1( "OPEN share read only\n" );
          805  +    OSTRACE(( "OPEN share read only\n" ));
   803    806     }
   804    807   
   805    808     if( flags & SQLITE_OPEN_DELETEONCLOSE ){
   806    809       char pathUtf8[CCHMAXPATH];
   807    810   #ifdef NDEBUG /* when debugging we want to make sure it is deleted */
   808    811       ulFileAttribute = FILE_HIDDEN;
   809    812   #endif
   810    813       os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
   811    814       pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
   812         -    OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
          815  +    OSTRACE(( "OPEN hidden/delete on close file attributes\n" ));
   813    816     }else{
   814    817       pFile->pathToDel = NULL;
   815         -    OSTRACE1( "OPEN normal file attribute\n" );
          818  +    OSTRACE(( "OPEN normal file attribute\n" ));
   816    819     }
   817    820   
   818    821     /* always open in random access mode for possibly better speed */
   819    822     ulOpenMode |= OPEN_FLAGS_RANDOM;
   820    823     ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR;
   821    824     ulOpenMode |= OPEN_FLAGS_NOINHERIT;
   822    825   
................................................................................
   827    830                   0L,
   828    831                   ulFileAttribute,
   829    832                   ulOpenFlags,
   830    833                   ulOpenMode,
   831    834                   (PEAOP2)NULL );
   832    835     free( zNameCp );
   833    836     if( rc != NO_ERROR ){
   834         -    OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
   835         -              rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode );
          837  +    OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
          838  +              rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ));
   836    839       if( pFile->pathToDel )
   837    840         free( pFile->pathToDel );
   838    841       pFile->pathToDel = NULL;
   839    842       if( flags & SQLITE_OPEN_READWRITE ){
   840         -      OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) );
          843  +      OSTRACE(( "OPEN %d Invalid handle\n",
          844  +                ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ));
   841    845         return os2Open( pVfs, zName, id,
   842    846                         ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
   843    847                         pOutFlags );
   844    848       }else{
   845    849         return SQLITE_CANTOPEN;
   846    850       }
   847    851     }
................................................................................
   849    853     if( pOutFlags ){
   850    854       *pOutFlags = flags & SQLITE_OPEN_READWRITE ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
   851    855     }
   852    856   
   853    857     pFile->pMethod = &os2IoMethod;
   854    858     pFile->h = h;
   855    859     OpenCounter(+1);
   856         -  OSTRACE3( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags );
          860  +  OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
   857    861     return SQLITE_OK;
   858    862   }
   859    863   
   860    864   /*
   861    865   ** Delete the named file.
   862    866   */
   863    867   static int os2Delete(
................................................................................
   866    870     int syncDir                            /* Not used on os2 */
   867    871   ){
   868    872     APIRET rc = NO_ERROR;
   869    873     char *zFilenameCp = convertUtf8PathToCp( zFilename );
   870    874     SimulateIOError( return SQLITE_IOERR_DELETE );
   871    875     rc = DosDelete( (PSZ)zFilenameCp );
   872    876     free( zFilenameCp );
   873         -  OSTRACE2( "DELETE \"%s\"\n", zFilename );
          877  +  OSTRACE(( "DELETE \"%s\"\n", zFilename ));
   874    878     return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_DELETE;
   875    879   }
   876    880   
   877    881   /*
   878    882   ** Check the existance and status of a file.
   879    883   */
   880    884   static int os2Access(
................................................................................
   887    891     APIRET rc = NO_ERROR;
   888    892     char *zFilenameCp = convertUtf8PathToCp( zFilename );
   889    893   
   890    894     memset( &fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo) );
   891    895     rc = DosQueryPathInfo( (PSZ)zFilenameCp, FIL_STANDARD,
   892    896                            &fsts3ConfigInfo, sizeof(FILESTATUS3) );
   893    897     free( zFilenameCp );
   894         -  OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
   895         -            fsts3ConfigInfo.attrFile, flags, rc );
          898  +  OSTRACE(( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n",
          899  +            fsts3ConfigInfo.attrFile, flags, rc ));
   896    900     switch( flags ){
   897    901       case SQLITE_ACCESS_READ:
   898    902       case SQLITE_ACCESS_EXISTS:
   899    903         rc = (rc == NO_ERROR);
   900         -      OSTRACE3( "ACCESS %s access of read and exists  rc=%d\n", zFilename, rc );
          904  +      OSTRACE(( "ACCESS %s access of read and exists  rc=%d\n", zFilename, rc));
   901    905         break;
   902    906       case SQLITE_ACCESS_READWRITE:
   903    907         rc = (rc == NO_ERROR) && ( (fsts3ConfigInfo.attrFile & FILE_READONLY) == 0 );
   904         -      OSTRACE3( "ACCESS %s access of read/write  rc=%d\n", zFilename, rc );
          908  +      OSTRACE(( "ACCESS %s access of read/write  rc=%d\n", zFilename, rc ));
   905    909         break;
   906    910       default:
   907    911         assert( !"Invalid flags argument" );
   908    912     }
   909    913     *pOut = rc;
   910    914     return SQLITE_OK;
   911    915   }

Changes to src/os_unix.c.

   171    171   
   172    172   /*
   173    173   ** Only set the lastErrno if the error code is a real error and not 
   174    174   ** a normal expected return code of SQLITE_BUSY or SQLITE_OK
   175    175   */
   176    176   #define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
   177    177   
          178  +/* Forward references */
          179  +typedef struct unixShm unixShm;               /* Connection shared memory */
          180  +typedef struct unixShmNode unixShmNode;       /* Shared memory instance */
          181  +typedef struct unixInodeInfo unixInodeInfo;   /* An i-node */
          182  +typedef struct UnixUnusedFd UnixUnusedFd;     /* An unused file descriptor */
   178    183   
   179    184   /*
   180    185   ** Sometimes, after a file handle is closed by SQLite, the file descriptor
   181    186   ** cannot be closed immediately. In these cases, instances of the following
   182    187   ** structure are used to store the file descriptor while waiting for an
   183    188   ** opportunity to either close or reuse it.
   184    189   */
   185         -typedef struct UnixUnusedFd UnixUnusedFd;
   186    190   struct UnixUnusedFd {
   187    191     int fd;                   /* File descriptor to close */
   188    192     int flags;                /* Flags this file descriptor was opened with */
   189    193     UnixUnusedFd *pNext;      /* Next unused file descriptor on same file */
   190    194   };
   191    195   
   192    196   /*
   193    197   ** The unixFile structure is subclass of sqlite3_file specific to the unix
   194    198   ** VFS implementations.
   195    199   */
   196    200   typedef struct unixFile unixFile;
   197    201   struct unixFile {
   198    202     sqlite3_io_methods const *pMethod;  /* Always the first entry */
   199         -  struct unixOpenCnt *pOpen;       /* Info about all open fd's on this inode */
   200         -  struct unixLockInfo *pLock;      /* Info about locks on this inode */
   201         -  int h;                           /* The file descriptor */
   202         -  int dirfd;                       /* File descriptor for the directory */
   203         -  unsigned char locktype;          /* The type of lock held on this fd */
   204         -  int lastErrno;                   /* The unix errno from the last I/O error */
   205         -  void *lockingContext;            /* Locking style specific state */
   206         -  UnixUnusedFd *pUnused;           /* Pre-allocated UnixUnusedFd */
   207         -  int fileFlags;                   /* Miscellanous flags */
          203  +  unixInodeInfo *pInode;              /* Info about locks on this inode */
          204  +  int h;                              /* The file descriptor */
          205  +  int dirfd;                          /* File descriptor for the directory */
          206  +  unsigned char eFileLock;            /* The type of lock held on this fd */
          207  +  int lastErrno;                      /* The unix errno from last I/O error */
          208  +  void *lockingContext;               /* Locking style specific state */
          209  +  UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
          210  +  int fileFlags;                      /* Miscellanous flags */
          211  +  const char *zPath;                  /* Name of the file */
          212  +  unixShm *pShm;                      /* Shared memory segment information */
   208    213   #if SQLITE_ENABLE_LOCKING_STYLE
   209         -  int openFlags;                   /* The flags specified at open() */
          214  +  int openFlags;                      /* The flags specified at open() */
   210    215   #endif
   211    216   #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
   212         -  unsigned fsFlags;                 /* cached details from statfs() */
   213         -#endif
   214         -#if SQLITE_THREADSAFE && defined(__linux__)
   215         -  pthread_t tid;                   /* The thread that "owns" this unixFile */
          217  +  unsigned fsFlags;                   /* cached details from statfs() */
   216    218   #endif
   217    219   #if OS_VXWORKS
   218         -  int isDelete;                    /* Delete on close if true */
   219         -  struct vxworksFileId *pId;       /* Unique file ID */
          220  +  int isDelete;                       /* Delete on close if true */
          221  +  struct vxworksFileId *pId;          /* Unique file ID */
   220    222   #endif
   221    223   #ifndef NDEBUG
   222    224     /* The next group of variables are used to track whether or not the
   223    225     ** transaction counter in bytes 24-27 of database files are updated
   224    226     ** whenever any part of the database changes.  An assertion fault will
   225    227     ** occur if a file is updated without also updating the transaction
   226    228     ** counter.  This test is made to avoid new problems similar to the
................................................................................
   284    286   #else
   285    287   #define threadid 0
   286    288   #endif
   287    289   
   288    290   
   289    291   /*
   290    292   ** Helper functions to obtain and relinquish the global mutex. The
   291         -** global mutex is used to protect the unixOpenCnt, unixLockInfo and
          293  +** global mutex is used to protect the unixInodeInfo and
   292    294   ** vxworksFileId objects used by this file, all of which may be 
   293    295   ** shared by multiple threads.
   294    296   **
   295    297   ** Function unixMutexHeld() is used to assert() that the global mutex 
   296    298   ** is held when required. This function is only used as part of assert() 
   297    299   ** statements. e.g.
   298    300   **
................................................................................
   315    317   
   316    318   #ifdef SQLITE_DEBUG
   317    319   /*
   318    320   ** Helper function for printing out trace information from debugging
   319    321   ** binaries. This returns the string represetation of the supplied
   320    322   ** integer lock-type.
   321    323   */
   322         -static const char *locktypeName(int locktype){
   323         -  switch( locktype ){
          324  +static const char *azFileLock(int eFileLock){
          325  +  switch( eFileLock ){
   324    326       case NO_LOCK: return "NONE";
   325    327       case SHARED_LOCK: return "SHARED";
   326    328       case RESERVED_LOCK: return "RESERVED";
   327    329       case PENDING_LOCK: return "PENDING";
   328    330       case EXCLUSIVE_LOCK: return "EXCLUSIVE";
   329    331     }
   330    332     return "ERROR";
................................................................................
   653    655   ** POSIX lock if the internal lock structure transitions between
   654    656   ** a locked and an unlocked state.
   655    657   **
   656    658   ** But wait:  there are yet more problems with POSIX advisory locks.
   657    659   **
   658    660   ** If you close a file descriptor that points to a file that has locks,
   659    661   ** all locks on that file that are owned by the current process are
   660         -** released.  To work around this problem, each unixFile structure contains
   661         -** a pointer to an unixOpenCnt structure.  There is one unixOpenCnt structure
   662         -** per open inode, which means that multiple unixFile can point to a single
   663         -** unixOpenCnt.  When an attempt is made to close an unixFile, if there are
          662  +** released.  To work around this problem, each unixInodeInfo object
          663  +** maintains a count of the number of pending locks on tha inode.
          664  +** When an attempt is made to close an unixFile, if there are
   664    665   ** other unixFile open on the same inode that are holding locks, the call
   665    666   ** to close() the file descriptor is deferred until all of the locks clear.
   666         -** The unixOpenCnt structure keeps a list of file descriptors that need to
          667  +** The unixInodeInfo structure keeps a list of file descriptors that need to
   667    668   ** be closed and that list is walked (and cleared) when the last lock
   668    669   ** clears.
   669    670   **
   670    671   ** Yet another problem:  LinuxThreads do not play well with posix locks.
   671    672   **
   672    673   ** Many older versions of linux use the LinuxThreads library which is
   673    674   ** not posix compliant.  Under LinuxThreads, a lock created by thread
................................................................................
   674    675   ** A cannot be modified or overridden by a different thread B.
   675    676   ** Only thread A can modify the lock.  Locking behavior is correct
   676    677   ** if the appliation uses the newer Native Posix Thread Library (NPTL)
   677    678   ** on linux - with NPTL a lock created by thread A can override locks
   678    679   ** in thread B.  But there is no way to know at compile-time which
   679    680   ** threading library is being used.  So there is no way to know at
   680    681   ** compile-time whether or not thread A can override locks on thread B.
   681         -** We have to do a run-time check to discover the behavior of the
          682  +** One has to do a run-time check to discover the behavior of the
   682    683   ** current process.
   683    684   **
   684         -** On systems where thread A is unable to modify locks created by
   685         -** thread B, we have to keep track of which thread created each
   686         -** lock.  Hence there is an extra field in the key to the unixLockInfo
   687         -** structure to record this information.  And on those systems it
   688         -** is illegal to begin a transaction in one thread and finish it
   689         -** in another.  For this latter restriction, there is no work-around.
   690         -** It is a limitation of LinuxThreads.
          685  +** SQLite used to support LinuxThreads.  But support for LinuxThreads
          686  +** was dropped beginning with version 3.7.0.  SQLite will still work with
          687  +** LinuxThreads provided that (1) there is no more than one connection 
          688  +** per database file in the same process and (2) database connections
          689  +** do not move across threads.
   691    690   */
   692    691   
   693         -/*
   694         -** Set or check the unixFile.tid field.  This field is set when an unixFile
   695         -** is first opened.  All subsequent uses of the unixFile verify that the
   696         -** same thread is operating on the unixFile.  Some operating systems do
   697         -** not allow locks to be overridden by other threads and that restriction
   698         -** means that sqlite3* database handles cannot be moved from one thread
   699         -** to another while locks are held.
   700         -**
   701         -** Version 3.3.1 (2006-01-15):  unixFile can be moved from one thread to
   702         -** another as long as we are running on a system that supports threads
   703         -** overriding each others locks (which is now the most common behavior)
   704         -** or if no locks are held.  But the unixFile.pLock field needs to be
   705         -** recomputed because its key includes the thread-id.  See the 
   706         -** transferOwnership() function below for additional information
   707         -*/
   708         -#if SQLITE_THREADSAFE && defined(__linux__)
   709         -# define SET_THREADID(X)   (X)->tid = pthread_self()
   710         -# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
   711         -                            !pthread_equal((X)->tid, pthread_self()))
   712         -#else
   713         -# define SET_THREADID(X)
   714         -# define CHECK_THREADID(X) 0
   715         -#endif
   716         -
   717    692   /*
   718    693   ** An instance of the following structure serves as the key used
   719         -** to locate a particular unixOpenCnt structure given its inode.  This
   720         -** is the same as the unixLockKey except that the thread ID is omitted.
          694  +** to locate a particular unixInodeInfo object.
   721    695   */
   722    696   struct unixFileId {
   723    697     dev_t dev;                  /* Device number */
   724    698   #if OS_VXWORKS
   725    699     struct vxworksFileId *pId;  /* Unique file ID for vxworks. */
   726    700   #else
   727    701     ino_t ino;                  /* Inode number */
   728    702   #endif
   729    703   };
   730    704   
   731         -/*
   732         -** An instance of the following structure serves as the key used
   733         -** to locate a particular unixLockInfo structure given its inode.
   734         -**
   735         -** If threads cannot override each others locks (LinuxThreads), then we
   736         -** set the unixLockKey.tid field to the thread ID.  If threads can override
   737         -** each others locks (Posix and NPTL) then tid is always set to zero.
   738         -** tid is omitted if we compile without threading support or on an OS
   739         -** other than linux.
   740         -*/
   741         -struct unixLockKey {
   742         -  struct unixFileId fid;  /* Unique identifier for the file */
   743         -#if SQLITE_THREADSAFE && defined(__linux__)
   744         -  pthread_t tid;  /* Thread ID of lock owner. Zero if not using LinuxThreads */
   745         -#endif
   746         -};
   747         -
   748    705   /*
   749    706   ** An instance of the following structure is allocated for each open
   750    707   ** inode.  Or, on LinuxThreads, there is one of these structures for
   751    708   ** each inode opened by each thread.
   752    709   **
   753    710   ** A single inode can have multiple file descriptors, so each unixFile
   754    711   ** structure contains a pointer to an instance of this object and this
   755    712   ** object keeps a count of the number of unixFile pointing to it.
   756    713   */
   757         -struct unixLockInfo {
   758         -  struct unixLockKey lockKey;     /* The lookup key */
   759         -  int cnt;                        /* Number of SHARED locks held */
   760         -  int locktype;                   /* One of SHARED_LOCK, RESERVED_LOCK etc. */
          714  +struct unixInodeInfo {
          715  +  struct unixFileId fileId;       /* The lookup key */
          716  +  int nShared;                    /* Number of SHARED locks held */
          717  +  int eFileLock;                  /* One of SHARED_LOCK, RESERVED_LOCK etc. */
   761    718     int nRef;                       /* Number of pointers to this structure */
          719  +  unixShmNode *pShmNode;          /* Shared memory associated with this inode */
          720  +  int nLock;                      /* Number of outstanding file locks */
          721  +  UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
          722  +  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
          723  +  unixInodeInfo *pPrev;           /*    .... doubly linked */
   762    724   #if defined(SQLITE_ENABLE_LOCKING_STYLE)
   763    725     unsigned long long sharedByte;  /* for AFP simulated shared lock */
   764    726   #endif
   765         -  struct unixLockInfo *pNext;     /* List of all unixLockInfo objects */
   766         -  struct unixLockInfo *pPrev;     /*    .... doubly linked */
   767         -};
   768         -
   769         -/*
   770         -** An instance of the following structure is allocated for each open
   771         -** inode.  This structure keeps track of the number of locks on that
   772         -** inode.  If a close is attempted against an inode that is holding
   773         -** locks, the close is deferred until all locks clear by adding the
   774         -** file descriptor to be closed to the pending list.
   775         -**
   776         -** TODO:  Consider changing this so that there is only a single file
   777         -** descriptor for each open file, even when it is opened multiple times.
   778         -** The close() system call would only occur when the last database
   779         -** using the file closes.
   780         -*/
   781         -struct unixOpenCnt {
   782         -  struct unixFileId fileId;   /* The lookup key */
   783         -  int nRef;                   /* Number of pointers to this structure */
   784         -  int nLock;                  /* Number of outstanding locks */
   785         -  UnixUnusedFd *pUnused;      /* Unused file descriptors to close */
   786    727   #if OS_VXWORKS
   787         -  sem_t *pSem;                     /* Named POSIX semaphore */
   788         -  char aSemName[MAX_PATHNAME+2];   /* Name of that semaphore */
          728  +  sem_t *pSem;                    /* Named POSIX semaphore */
          729  +  char aSemName[MAX_PATHNAME+2];  /* Name of that semaphore */
   789    730   #endif
   790         -  struct unixOpenCnt *pNext, *pPrev;   /* List of all unixOpenCnt objects */
   791    731   };
   792    732   
   793    733   /*
   794         -** Lists of all unixLockInfo and unixOpenCnt objects.  These used to be hash
   795         -** tables.  But the number of objects is rarely more than a dozen and
   796         -** never exceeds a few thousand.  And lookup is not on a critical
   797         -** path so a simple linked list will suffice.
   798         -*/
   799         -static struct unixLockInfo *lockList = 0;
   800         -static struct unixOpenCnt *openList = 0;
   801         -
   802         -/*
   803         -** This variable remembers whether or not threads can override each others
   804         -** locks.
   805         -**
   806         -**    0:  No.  Threads cannot override each others locks.  (LinuxThreads)
   807         -**    1:  Yes.  Threads can override each others locks.  (Posix & NLPT)
   808         -**   -1:  We don't know yet.
   809         -**
   810         -** On some systems, we know at compile-time if threads can override each
   811         -** others locks.  On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro
   812         -** will be set appropriately.  On other systems, we have to check at
   813         -** runtime.  On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is
   814         -** undefined.
   815         -**
   816         -** This variable normally has file scope only.  But during testing, we make
   817         -** it a global so that the test code can change its value in order to verify
   818         -** that the right stuff happens in either case.
   819         -*/
   820         -#if SQLITE_THREADSAFE && defined(__linux__)
   821         -#  ifndef SQLITE_THREAD_OVERRIDE_LOCK
   822         -#    define SQLITE_THREAD_OVERRIDE_LOCK -1
   823         -#  endif
   824         -#  ifdef SQLITE_TEST
   825         -int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
   826         -#  else
   827         -static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
   828         -#  endif
   829         -#endif
   830         -
   831         -/*
   832         -** This structure holds information passed into individual test
   833         -** threads by the testThreadLockingBehavior() routine.
   834         -*/
   835         -struct threadTestData {
   836         -  int fd;                /* File to be locked */
   837         -  struct flock lock;     /* The locking operation */
   838         -  int result;            /* Result of the locking operation */
   839         -};
   840         -
   841         -#if SQLITE_THREADSAFE && defined(__linux__)
   842         -/*
   843         -** This function is used as the main routine for a thread launched by
   844         -** testThreadLockingBehavior(). It tests whether the shared-lock obtained
   845         -** by the main thread in testThreadLockingBehavior() conflicts with a
   846         -** hypothetical write-lock obtained by this thread on the same file.
   847         -**
   848         -** The write-lock is not actually acquired, as this is not possible if 
   849         -** the file is open in read-only mode (see ticket #3472).
   850         -*/ 
   851         -static void *threadLockingTest(void *pArg){
   852         -  struct threadTestData *pData = (struct threadTestData*)pArg;
   853         -  pData->result = fcntl(pData->fd, F_GETLK, &pData->lock);
   854         -  return pArg;
   855         -}
   856         -#endif /* SQLITE_THREADSAFE && defined(__linux__) */
   857         -
   858         -
   859         -#if SQLITE_THREADSAFE && defined(__linux__)
   860         -/*
   861         -** This procedure attempts to determine whether or not threads
   862         -** can override each others locks then sets the 
   863         -** threadsOverrideEachOthersLocks variable appropriately.
   864         -*/
   865         -static void testThreadLockingBehavior(int fd_orig){
   866         -  int fd;
   867         -  int rc;
   868         -  struct threadTestData d;
   869         -  struct flock l;
   870         -  pthread_t t;
   871         -
   872         -  fd = dup(fd_orig);
   873         -  if( fd<0 ) return;
   874         -  memset(&l, 0, sizeof(l));
   875         -  l.l_type = F_RDLCK;
   876         -  l.l_len = 1;
   877         -  l.l_start = 0;
   878         -  l.l_whence = SEEK_SET;
   879         -  rc = fcntl(fd_orig, F_SETLK, &l);
   880         -  if( rc!=0 ) return;
   881         -  memset(&d, 0, sizeof(d));
   882         -  d.fd = fd;
   883         -  d.lock = l;
   884         -  d.lock.l_type = F_WRLCK;
   885         -  if( pthread_create(&t, 0, threadLockingTest, &d)==0 ){
   886         -    pthread_join(t, 0);
   887         -  }
   888         -  close(fd);
   889         -  if( d.result!=0 ) return;
   890         -  threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);
   891         -}
   892         -#endif /* SQLITE_THREADSAFE && defined(__linux__) */
   893         -
   894         -/*
   895         -** Release a unixLockInfo structure previously allocated by findLockInfo().
          734  +** A lists of all unixInodeInfo objects.
          735  +*/
          736  +static unixInodeInfo *inodeList = 0;
          737  +
          738  +/*
          739  +** Release a unixInodeInfo structure previously allocated by findInodeInfo().
   896    740   **
   897    741   ** The mutex entered using the unixEnterMutex() function must be held
   898    742   ** when this function is called.
   899    743   */
   900         -static void releaseLockInfo(struct unixLockInfo *pLock){
          744  +static void releaseInodeInfo(unixInodeInfo *pInode){
   901    745     assert( unixMutexHeld() );
   902         -  if( pLock ){
   903         -    pLock->nRef--;
   904         -    if( pLock->nRef==0 ){
   905         -      if( pLock->pPrev ){
   906         -        assert( pLock->pPrev->pNext==pLock );
   907         -        pLock->pPrev->pNext = pLock->pNext;
          746  +  if( pInode ){
          747  +    pInode->nRef--;
          748  +    if( pInode->nRef==0 ){
          749  +      assert( pInode->pShmNode==0 );
          750  +      if( pInode->pPrev ){
          751  +        assert( pInode->pPrev->pNext==pInode );
          752  +        pInode->pPrev->pNext = pInode->pNext;
   908    753         }else{
   909         -        assert( lockList==pLock );
   910         -        lockList = pLock->pNext;
   911         -      }
   912         -      if( pLock->pNext ){
   913         -        assert( pLock->pNext->pPrev==pLock );
   914         -        pLock->pNext->pPrev = pLock->pPrev;
   915         -      }
   916         -      sqlite3_free(pLock);
   917         -    }
   918         -  }
   919         -}
   920         -
   921         -/*
   922         -** Release a unixOpenCnt structure previously allocated by findLockInfo().
   923         -**
   924         -** The mutex entered using the unixEnterMutex() function must be held
   925         -** when this function is called.
   926         -*/
   927         -static void releaseOpenCnt(struct unixOpenCnt *pOpen){
   928         -  assert( unixMutexHeld() );
   929         -  if( pOpen ){
   930         -    pOpen->nRef--;
   931         -    if( pOpen->nRef==0 ){
   932         -      if( pOpen->pPrev ){
   933         -        assert( pOpen->pPrev->pNext==pOpen );
   934         -        pOpen->pPrev->pNext = pOpen->pNext;
   935         -      }else{
   936         -        assert( openList==pOpen );
   937         -        openList = pOpen->pNext;
   938         -      }
   939         -      if( pOpen->pNext ){
   940         -        assert( pOpen->pNext->pPrev==pOpen );
   941         -        pOpen->pNext->pPrev = pOpen->pPrev;
   942         -      }
   943         -#if SQLITE_THREADSAFE && defined(__linux__)
   944         -      assert( !pOpen->pUnused || threadsOverrideEachOthersLocks==0 );
   945         -#endif
   946         -
   947         -      /* If pOpen->pUnused is not null, then memory and file-descriptors
   948         -      ** are leaked.
   949         -      **
   950         -      ** This will only happen if, under Linuxthreads, the user has opened
   951         -      ** a transaction in one thread, then attempts to close the database
   952         -      ** handle from another thread (without first unlocking the db file).
   953         -      ** This is a misuse.  */
   954         -      sqlite3_free(pOpen);
   955         -    }
   956         -  }
   957         -}
   958         -
   959         -/*
   960         -** Given a file descriptor, locate unixLockInfo and unixOpenCnt structures that
   961         -** describes that file descriptor.  Create new ones if necessary.  The
   962         -** return values might be uninitialized if an error occurs.
          754  +        assert( inodeList==pInode );
          755  +        inodeList = pInode->pNext;
          756  +      }
          757  +      if( pInode->pNext ){
          758  +        assert( pInode->pNext->pPrev==pInode );
          759  +        pInode->pNext->pPrev = pInode->pPrev;
          760  +      }
          761  +      sqlite3_free(pInode);
          762  +    }
          763  +  }
          764  +}
          765  +
          766  +/*
          767  +** Given a file descriptor, locate the unixInodeInfo object that
          768  +** describes that file descriptor.  Create a new one if necessary.  The
          769  +** return value might be uninitialized if an error occurs.
   963    770   **
   964    771   ** The mutex entered using the unixEnterMutex() function must be held
   965    772   ** when this function is called.
   966    773   **
   967    774   ** Return an appropriate error code.
   968    775   */
   969         -static int findLockInfo(
          776  +static int findInodeInfo(
   970    777     unixFile *pFile,               /* Unix file with file desc used in the key */
   971         -  struct unixLockInfo **ppLock,  /* Return the unixLockInfo structure here */
   972         -  struct unixOpenCnt **ppOpen    /* Return the unixOpenCnt structure here */
          778  +  unixInodeInfo **ppInode        /* Return the unixInodeInfo object here */
   973    779   ){
   974    780     int rc;                        /* System call return code */
   975    781     int fd;                        /* The file descriptor for pFile */
   976         -  struct unixLockKey lockKey;    /* Lookup key for the unixLockInfo structure */
   977         -  struct unixFileId fileId;      /* Lookup key for the unixOpenCnt struct */
          782  +  struct unixFileId fileId;      /* Lookup key for the unixInodeInfo */
   978    783     struct stat statbuf;           /* Low-level file information */
   979         -  struct unixLockInfo *pLock = 0;/* Candidate unixLockInfo object */
   980         -  struct unixOpenCnt *pOpen;     /* Candidate unixOpenCnt object */
          784  +  unixInodeInfo *pInode = 0;     /* Candidate unixInodeInfo object */
   981    785   
   982    786     assert( unixMutexHeld() );
   983    787   
   984    788     /* Get low-level information about the file that we can used to
   985    789     ** create a unique name for the file.
   986    790     */
   987    791     fd = pFile->h;
................................................................................
  1015    819       if( rc!=0 ){
  1016    820         pFile->lastErrno = errno;
  1017    821         return SQLITE_IOERR;
  1018    822       }
  1019    823     }
  1020    824   #endif
  1021    825   
  1022         -  memset(&lockKey, 0, sizeof(lockKey));
  1023         -  lockKey.fid.dev = statbuf.st_dev;
          826  +  memset(&fileId, 0, sizeof(fileId));
          827  +  fileId.dev = statbuf.st_dev;
  1024    828   #if OS_VXWORKS
  1025         -  lockKey.fid.pId = pFile->pId;
  1026         -#else
  1027         -  lockKey.fid.ino = statbuf.st_ino;
  1028         -#endif
  1029         -#if SQLITE_THREADSAFE && defined(__linux__)
  1030         -  if( threadsOverrideEachOthersLocks<0 ){
  1031         -    testThreadLockingBehavior(fd);
  1032         -  }
  1033         -  lockKey.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
  1034         -#endif
  1035         -  fileId = lockKey.fid;
  1036         -  if( ppLock!=0 ){
  1037         -    pLock = lockList;
  1038         -    while( pLock && memcmp(&lockKey, &pLock->lockKey, sizeof(lockKey)) ){
  1039         -      pLock = pLock->pNext;
  1040         -    }
  1041         -    if( pLock==0 ){
  1042         -      pLock = sqlite3_malloc( sizeof(*pLock) );
  1043         -      if( pLock==0 ){
  1044         -        rc = SQLITE_NOMEM;
  1045         -        goto exit_findlockinfo;
  1046         -      }
  1047         -      memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey));
  1048         -      pLock->nRef = 1;
  1049         -      pLock->cnt = 0;
  1050         -      pLock->locktype = 0;
  1051         -#if defined(SQLITE_ENABLE_LOCKING_STYLE)
  1052         -      pLock->sharedByte = 0;
  1053         -#endif
  1054         -      pLock->pNext = lockList;
  1055         -      pLock->pPrev = 0;
  1056         -      if( lockList ) lockList->pPrev = pLock;
  1057         -      lockList = pLock;
  1058         -    }else{
  1059         -      pLock->nRef++;
  1060         -    }
  1061         -    *ppLock = pLock;
  1062         -  }
  1063         -  if( ppOpen!=0 ){
  1064         -    pOpen = openList;
  1065         -    while( pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)) ){
  1066         -      pOpen = pOpen->pNext;
  1067         -    }
  1068         -    if( pOpen==0 ){
  1069         -      pOpen = sqlite3_malloc( sizeof(*pOpen) );
  1070         -      if( pOpen==0 ){
  1071         -        releaseLockInfo(pLock);
  1072         -        rc = SQLITE_NOMEM;
  1073         -        goto exit_findlockinfo;
  1074         -      }
  1075         -      memset(pOpen, 0, sizeof(*pOpen));
  1076         -      pOpen->fileId = fileId;
  1077         -      pOpen->nRef = 1;
  1078         -      pOpen->pNext = openList;
  1079         -      if( openList ) openList->pPrev = pOpen;
  1080         -      openList = pOpen;
  1081         -    }else{
  1082         -      pOpen->nRef++;
  1083         -    }
  1084         -    *ppOpen = pOpen;
  1085         -  }
  1086         -
  1087         -exit_findlockinfo:
  1088         -  return rc;
  1089         -}
  1090         -
  1091         -/*
  1092         -** If we are currently in a different thread than the thread that the
  1093         -** unixFile argument belongs to, then transfer ownership of the unixFile
  1094         -** over to the current thread.
  1095         -**
  1096         -** A unixFile is only owned by a thread on systems that use LinuxThreads.
  1097         -**
  1098         -** Ownership transfer is only allowed if the unixFile is currently unlocked.
  1099         -** If the unixFile is locked and an ownership is wrong, then return
  1100         -** SQLITE_MISUSE.  SQLITE_OK is returned if everything works.
  1101         -*/
  1102         -#if SQLITE_THREADSAFE && defined(__linux__)
  1103         -static int transferOwnership(unixFile *pFile){
  1104         -  int rc;
  1105         -  pthread_t hSelf;
  1106         -  if( threadsOverrideEachOthersLocks ){
  1107         -    /* Ownership transfers not needed on this system */
  1108         -    return SQLITE_OK;
  1109         -  }
  1110         -  hSelf = pthread_self();
  1111         -  if( pthread_equal(pFile->tid, hSelf) ){
  1112         -    /* We are still in the same thread */
  1113         -    OSTRACE1("No-transfer, same thread\n");
  1114         -    return SQLITE_OK;
  1115         -  }
  1116         -  if( pFile->locktype!=NO_LOCK ){
  1117         -    /* We cannot change ownership while we are holding a lock! */
  1118         -    return SQLITE_MISUSE_BKPT;
  1119         -  }
  1120         -  OSTRACE4("Transfer ownership of %d from %d to %d\n",
  1121         -            pFile->h, pFile->tid, hSelf);
  1122         -  pFile->tid = hSelf;
  1123         -  if (pFile->pLock != NULL) {
  1124         -    releaseLockInfo(pFile->pLock);
  1125         -    rc = findLockInfo(pFile, &pFile->pLock, 0);
  1126         -    OSTRACE5("LOCK    %d is now %s(%s,%d)\n", pFile->h,
  1127         -           locktypeName(pFile->locktype),
  1128         -           locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
  1129         -    return rc;
  1130         -  } else {
  1131         -    return SQLITE_OK;
  1132         -  }
  1133         -}
  1134         -#else  /* if not SQLITE_THREADSAFE */
  1135         -  /* On single-threaded builds, ownership transfer is a no-op */
  1136         -# define transferOwnership(X) SQLITE_OK
  1137         -#endif /* SQLITE_THREADSAFE */
          829  +  fileId.pId = pFile->pId;
          830  +#else
          831  +  fileId.ino = statbuf.st_ino;
          832  +#endif
          833  +  pInode = inodeList;
          834  +  while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
          835  +    pInode = pInode->pNext;
          836  +  }
          837  +  if( pInode==0 ){
          838  +    pInode = sqlite3_malloc( sizeof(*pInode) );
          839  +    if( pInode==0 ){
          840  +      return SQLITE_NOMEM;
          841  +    }
          842  +    memset(pInode, 0, sizeof(*pInode));
          843  +    memcpy(&pInode->fileId, &fileId, sizeof(fileId));
          844  +    pInode->nRef = 1;
          845  +    pInode->pNext = inodeList;
          846  +    pInode->pPrev = 0;
          847  +    if( inodeList ) inodeList->pPrev = pInode;
          848  +    inodeList = pInode;
          849  +  }else{
          850  +    pInode->nRef++;
          851  +  }
          852  +  *ppInode = pInode;
          853  +  return SQLITE_OK;
          854  +}
  1138    855   
  1139    856   
  1140    857   /*
  1141    858   ** This routine checks if there is a RESERVED lock held on the specified
  1142    859   ** file by this or any other process. If such a lock is held, set *pResOut
  1143    860   ** to a non-zero value otherwise *pResOut is set to zero.  The return value
  1144    861   ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
................................................................................
  1147    864     int rc = SQLITE_OK;
  1148    865     int reserved = 0;
  1149    866     unixFile *pFile = (unixFile*)id;
  1150    867   
  1151    868     SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  1152    869   
  1153    870     assert( pFile );
  1154         -  unixEnterMutex(); /* Because pFile->pLock is shared across threads */
          871  +  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
  1155    872   
  1156    873     /* Check if a thread in this process holds such a lock */
  1157         -  if( pFile->pLock->locktype>SHARED_LOCK ){
          874  +  if( pFile->pInode->eFileLock>SHARED_LOCK ){
  1158    875       reserved = 1;
  1159    876     }
  1160    877   
  1161    878     /* Otherwise see if some other process holds it.
  1162    879     */
  1163    880   #ifndef __DJGPP__
  1164    881     if( !reserved ){
................................................................................
  1174    891       } else if( lock.l_type!=F_UNLCK ){
  1175    892         reserved = 1;
  1176    893       }
  1177    894     }
  1178    895   #endif
  1179    896     
  1180    897     unixLeaveMutex();
  1181         -  OSTRACE4("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved);
          898  +  OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
  1182    899   
  1183    900     *pResOut = reserved;
  1184    901     return rc;
  1185    902   }
  1186    903   
  1187    904   /*
  1188         -** Lock the file with the lock specified by parameter locktype - one
          905  +** Lock the file with the lock specified by parameter eFileLock - one
  1189    906   ** of the following:
  1190    907   **
  1191    908   **     (1) SHARED_LOCK
  1192    909   **     (2) RESERVED_LOCK
  1193    910   **     (3) PENDING_LOCK
  1194    911   **     (4) EXCLUSIVE_LOCK
  1195    912   **
................................................................................
  1204    921   **    SHARED -> (PENDING) -> EXCLUSIVE
  1205    922   **    RESERVED -> (PENDING) -> EXCLUSIVE
  1206    923   **    PENDING -> EXCLUSIVE
  1207    924   **
  1208    925   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  1209    926   ** routine to lower a locking level.
  1210    927   */
  1211         -static int unixLock(sqlite3_file *id, int locktype){
          928  +static int unixLock(sqlite3_file *id, int eFileLock){
  1212    929     /* The following describes the implementation of the various locks and
  1213    930     ** lock transitions in terms of the POSIX advisory shared and exclusive
  1214    931     ** lock primitives (called read-locks and write-locks below, to avoid
  1215    932     ** confusion with SQLite lock names). The algorithms are complicated
  1216    933     ** slightly in order to be compatible with windows systems simultaneously
  1217    934     ** accessing the same database file, in case that is ever required.
  1218    935     **
................................................................................
  1245    962     ** The reason a single byte cannot be used instead of the 'shared byte
  1246    963     ** range' is that some versions of windows do not support read-locks. By
  1247    964     ** locking a random byte from a range, concurrent SHARED locks may exist
  1248    965     ** even if the locking primitive used is always a write-lock.
  1249    966     */
  1250    967     int rc = SQLITE_OK;
  1251    968     unixFile *pFile = (unixFile*)id;
  1252         -  struct unixLockInfo *pLock = pFile->pLock;
          969  +  unixInodeInfo *pInode = pFile->pInode;
  1253    970     struct flock lock;
  1254    971     int s = 0;
  1255    972     int tErrno = 0;
  1256    973   
  1257    974     assert( pFile );
  1258         -  OSTRACE7("LOCK    %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
  1259         -      locktypeName(locktype), locktypeName(pFile->locktype),
  1260         -      locktypeName(pLock->locktype), pLock->cnt , getpid());
          975  +  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
          976  +      azFileLock(eFileLock), azFileLock(pFile->eFileLock),
          977  +      azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
  1261    978   
  1262    979     /* If there is already a lock of this type or more restrictive on the
  1263    980     ** unixFile, do nothing. Don't use the end_lock: exit path, as
  1264    981     ** unixEnterMutex() hasn't been called yet.
  1265    982     */
  1266         -  if( pFile->locktype>=locktype ){
  1267         -    OSTRACE3("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
  1268         -            locktypeName(locktype));
          983  +  if( pFile->eFileLock>=eFileLock ){
          984  +    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
          985  +            azFileLock(eFileLock)));
  1269    986       return SQLITE_OK;
  1270    987     }
  1271    988   
  1272    989     /* Make sure the locking sequence is correct.
  1273    990     **  (1) We never move from unlocked to anything higher than shared lock.
  1274    991     **  (2) SQLite never explicitly requests a pendig lock.
  1275    992     **  (3) A shared lock is always held when a reserve lock is requested.
  1276    993     */
  1277         -  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  1278         -  assert( locktype!=PENDING_LOCK );
  1279         -  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
          994  +  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
          995  +  assert( eFileLock!=PENDING_LOCK );
          996  +  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
  1280    997   
  1281         -  /* This mutex is needed because pFile->pLock is shared across threads
          998  +  /* This mutex is needed because pFile->pInode is shared across threads
  1282    999     */
  1283   1000     unixEnterMutex();
  1284         -
  1285         -  /* Make sure the current thread owns the pFile.
  1286         -  */
  1287         -  rc = transferOwnership(pFile);
  1288         -  if( rc!=SQLITE_OK ){
  1289         -    unixLeaveMutex();
  1290         -    return rc;
  1291         -  }
  1292         -  pLock = pFile->pLock;
         1001  +  pInode = pFile->pInode;
  1293   1002   
  1294   1003     /* If some thread using this PID has a lock via a different unixFile*
  1295   1004     ** handle that precludes the requested lock, return BUSY.
  1296   1005     */
  1297         -  if( (pFile->locktype!=pLock->locktype && 
  1298         -          (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK))
         1006  +  if( (pFile->eFileLock!=pInode->eFileLock && 
         1007  +          (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
  1299   1008     ){
  1300   1009       rc = SQLITE_BUSY;
  1301   1010       goto end_lock;
  1302   1011     }
  1303   1012   
  1304   1013     /* If a SHARED lock is requested, and some thread using this PID already
  1305   1014     ** has a SHARED or RESERVED lock, then increment reference counts and
  1306   1015     ** return SQLITE_OK.
  1307   1016     */
  1308         -  if( locktype==SHARED_LOCK && 
  1309         -      (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
  1310         -    assert( locktype==SHARED_LOCK );
  1311         -    assert( pFile->locktype==0 );
  1312         -    assert( pLock->cnt>0 );
  1313         -    pFile->locktype = SHARED_LOCK;
  1314         -    pLock->cnt++;
  1315         -    pFile->pOpen->nLock++;
         1017  +  if( eFileLock==SHARED_LOCK && 
         1018  +      (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
         1019  +    assert( eFileLock==SHARED_LOCK );
         1020  +    assert( pFile->eFileLock==0 );
         1021  +    assert( pInode->nShared>0 );
         1022  +    pFile->eFileLock = SHARED_LOCK;
         1023  +    pInode->nShared++;
         1024  +    pInode->nLock++;
  1316   1025       goto end_lock;
  1317   1026     }
  1318   1027   
  1319   1028   
  1320   1029     /* A PENDING lock is needed before acquiring a SHARED lock and before
  1321   1030     ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  1322   1031     ** be released.
  1323   1032     */
  1324   1033     lock.l_len = 1L;
  1325   1034     lock.l_whence = SEEK_SET;
  1326         -  if( locktype==SHARED_LOCK 
  1327         -      || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
         1035  +  if( eFileLock==SHARED_LOCK 
         1036  +      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
  1328   1037     ){
  1329         -    lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK);
         1038  +    lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
  1330   1039       lock.l_start = PENDING_BYTE;
  1331   1040       s = fcntl(pFile->h, F_SETLK, &lock);
  1332   1041       if( s==(-1) ){
  1333   1042         tErrno = errno;
  1334   1043         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1335   1044         if( IS_LOCK_ERROR(rc) ){
  1336   1045           pFile->lastErrno = tErrno;
................................................................................
  1339   1048       }
  1340   1049     }
  1341   1050   
  1342   1051   
  1343   1052     /* If control gets to this point, then actually go ahead and make
  1344   1053     ** operating system calls for the specified lock.
  1345   1054     */
  1346         -  if( locktype==SHARED_LOCK ){
  1347         -    assert( pLock->cnt==0 );
  1348         -    assert( pLock->locktype==0 );
         1055  +  if( eFileLock==SHARED_LOCK ){
         1056  +    assert( pInode->nShared==0 );
         1057  +    assert( pInode->eFileLock==0 );
  1349   1058   
  1350   1059       /* Now get the read-lock */
  1351   1060       lock.l_start = SHARED_FIRST;
  1352   1061       lock.l_len = SHARED_SIZE;
  1353   1062       if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
  1354   1063         tErrno = errno;
  1355   1064       }
................................................................................
  1370   1079       }
  1371   1080       if( s==(-1) ){
  1372   1081         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1373   1082         if( IS_LOCK_ERROR(rc) ){
  1374   1083           pFile->lastErrno = tErrno;
  1375   1084         }
  1376   1085       }else{
  1377         -      pFile->locktype = SHARED_LOCK;
  1378         -      pFile->pOpen->nLock++;
  1379         -      pLock->cnt = 1;
         1086  +      pFile->eFileLock = SHARED_LOCK;
         1087  +      pInode->nLock++;
         1088  +      pInode->nShared = 1;
  1380   1089       }
  1381         -  }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){
         1090  +  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
  1382   1091       /* We are trying for an exclusive lock but another thread in this
  1383   1092       ** same process is still holding a shared lock. */
  1384   1093       rc = SQLITE_BUSY;
  1385   1094     }else{
  1386   1095       /* The request was for a RESERVED or EXCLUSIVE lock.  It is
  1387   1096       ** assumed that there is a SHARED or greater lock on the file
  1388   1097       ** already.
  1389   1098       */
  1390         -    assert( 0!=pFile->locktype );
         1099  +    assert( 0!=pFile->eFileLock );
  1391   1100       lock.l_type = F_WRLCK;
  1392         -    switch( locktype ){
         1101  +    switch( eFileLock ){
  1393   1102         case RESERVED_LOCK:
  1394   1103           lock.l_start = RESERVED_BYTE;
  1395   1104           break;
  1396   1105         case EXCLUSIVE_LOCK:
  1397   1106           lock.l_start = SHARED_FIRST;
  1398   1107           lock.l_len = SHARED_SIZE;
  1399   1108           break;
................................................................................
  1414   1123   #ifndef NDEBUG
  1415   1124     /* Set up the transaction-counter change checking flags when
  1416   1125     ** transitioning from a SHARED to a RESERVED lock.  The change
  1417   1126     ** from SHARED to RESERVED marks the beginning of a normal
  1418   1127     ** write operation (not a hot journal rollback).
  1419   1128     */
  1420   1129     if( rc==SQLITE_OK
  1421         -   && pFile->locktype<=SHARED_LOCK
  1422         -   && locktype==RESERVED_LOCK
         1130  +   && pFile->eFileLock<=SHARED_LOCK
         1131  +   && eFileLock==RESERVED_LOCK
  1423   1132     ){
  1424   1133       pFile->transCntrChng = 0;
  1425   1134       pFile->dbUpdate = 0;
  1426   1135       pFile->inNormalWrite = 1;
  1427   1136     }
  1428   1137   #endif
  1429   1138   
  1430   1139   
  1431   1140     if( rc==SQLITE_OK ){
  1432         -    pFile->locktype = locktype;
  1433         -    pLock->locktype = locktype;
  1434         -  }else if( locktype==EXCLUSIVE_LOCK ){
  1435         -    pFile->locktype = PENDING_LOCK;
  1436         -    pLock->locktype = PENDING_LOCK;
         1141  +    pFile->eFileLock = eFileLock;
         1142  +    pInode->eFileLock = eFileLock;
         1143  +  }else if( eFileLock==EXCLUSIVE_LOCK ){
         1144  +    pFile->eFileLock = PENDING_LOCK;
         1145  +    pInode->eFileLock = PENDING_LOCK;
  1437   1146     }
  1438   1147   
  1439   1148   end_lock:
  1440   1149     unixLeaveMutex();
  1441         -  OSTRACE4("LOCK    %d %s %s (unix)\n", pFile->h, locktypeName(locktype), 
  1442         -      rc==SQLITE_OK ? "ok" : "failed");
         1150  +  OSTRACE(("LOCK    %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock), 
         1151  +      rc==SQLITE_OK ? "ok" : "failed"));
  1443   1152     return rc;
  1444   1153   }
  1445   1154   
  1446   1155   /*
  1447         -** Close all file descriptors accumuated in the unixOpenCnt->pUnused list.
         1156  +** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
  1448   1157   ** If all such file descriptors are closed without error, the list is
  1449   1158   ** cleared and SQLITE_OK returned.
  1450   1159   **
  1451   1160   ** Otherwise, if an error occurs, then successfully closed file descriptor
  1452   1161   ** entries are removed from the list, and SQLITE_IOERR_CLOSE returned. 
  1453   1162   ** not deleted and SQLITE_IOERR_CLOSE returned.
  1454   1163   */ 
  1455   1164   static int closePendingFds(unixFile *pFile){
  1456   1165     int rc = SQLITE_OK;
  1457         -  struct unixOpenCnt *pOpen = pFile->pOpen;
         1166  +  unixInodeInfo *pInode = pFile->pInode;
  1458   1167     UnixUnusedFd *pError = 0;
  1459   1168     UnixUnusedFd *p;
  1460   1169     UnixUnusedFd *pNext;
  1461         -  for(p=pOpen->pUnused; p; p=pNext){
         1170  +  for(p=pInode->pUnused; p; p=pNext){
  1462   1171       pNext = p->pNext;
  1463   1172       if( close(p->fd) ){
  1464   1173         pFile->lastErrno = errno;
  1465   1174         rc = SQLITE_IOERR_CLOSE;
  1466   1175         p->pNext = pError;
  1467   1176         pError = p;
  1468   1177       }else{
  1469   1178         sqlite3_free(p);
  1470   1179       }
  1471   1180     }
  1472         -  pOpen->pUnused = pError;
         1181  +  pInode->pUnused = pError;
  1473   1182     return rc;
  1474   1183   }
  1475   1184   
  1476   1185   /*
  1477   1186   ** Add the file descriptor used by file handle pFile to the corresponding
  1478   1187   ** pUnused list.
  1479   1188   */
  1480   1189   static void setPendingFd(unixFile *pFile){
  1481         -  struct unixOpenCnt *pOpen = pFile->pOpen;
         1190  +  unixInodeInfo *pInode = pFile->pInode;
  1482   1191     UnixUnusedFd *p = pFile->pUnused;
  1483         -  p->pNext = pOpen->pUnused;
  1484         -  pOpen->pUnused = p;
         1192  +  p->pNext = pInode->pUnused;
         1193  +  pInode->pUnused = p;
  1485   1194     pFile->h = -1;
  1486   1195     pFile->pUnused = 0;
  1487   1196   }
  1488   1197   
  1489   1198   /*
  1490         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         1199  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  1491   1200   ** must be either NO_LOCK or SHARED_LOCK.
  1492   1201   **
  1493   1202   ** If the locking level of the file descriptor is already at or below
  1494   1203   ** the requested locking level, this routine is a no-op.
  1495   1204   ** 
  1496   1205   ** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
  1497   1206   ** the byte range is divided into 2 parts and the first part is unlocked then
  1498   1207   ** set to a read lock, then the other part is simply unlocked.  This works 
  1499   1208   ** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to 
  1500   1209   ** remove the write lock on a region when a read lock is set.
  1501   1210   */
  1502         -static int _posixUnlock(sqlite3_file *id, int locktype, int handleNFSUnlock){
         1211  +static int _posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
  1503   1212     unixFile *pFile = (unixFile*)id;
  1504         -  struct unixLockInfo *pLock;
         1213  +  unixInodeInfo *pInode;
  1505   1214     struct flock lock;
  1506   1215     int rc = SQLITE_OK;
  1507   1216     int h;
  1508   1217     int tErrno;                      /* Error code from system call errors */
  1509   1218   
  1510   1219     assert( pFile );
  1511         -  OSTRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, locktype,
  1512         -      pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
         1220  +  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
         1221  +      pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
         1222  +      getpid()));
  1513   1223   
  1514         -  assert( locktype<=SHARED_LOCK );
  1515         -  if( pFile->locktype<=locktype ){
         1224  +  assert( eFileLock<=SHARED_LOCK );
         1225  +  if( pFile->eFileLock<=eFileLock ){
  1516   1226       return SQLITE_OK;
  1517   1227     }
  1518         -  if( CHECK_THREADID(pFile) ){
  1519         -    return SQLITE_MISUSE_BKPT;
  1520         -  }
  1521   1228     unixEnterMutex();
  1522   1229     h = pFile->h;
  1523         -  pLock = pFile->pLock;
  1524         -  assert( pLock->cnt!=0 );
  1525         -  if( pFile->locktype>SHARED_LOCK ){
  1526         -    assert( pLock->locktype==pFile->locktype );
         1230  +  pInode = pFile->pInode;
         1231  +  assert( pInode->nShared!=0 );
         1232  +  if( pFile->eFileLock>SHARED_LOCK ){
         1233  +    assert( pInode->eFileLock==pFile->eFileLock );
  1527   1234       SimulateIOErrorBenign(1);
  1528   1235       SimulateIOError( h=(-1) )
  1529   1236       SimulateIOErrorBenign(0);
  1530   1237   
  1531   1238   #ifndef NDEBUG
  1532   1239       /* When reducing a lock such that other processes can start
  1533   1240       ** reading the database file again, make sure that the
................................................................................
  1550   1257       ** the lock in 2 blocks, so that part of the range will be covered by a 
  1551   1258       ** write lock until the rest is covered by a read lock:
  1552   1259       **  1:   [WWWWW]
  1553   1260       **  2:   [....W]
  1554   1261       **  3:   [RRRRW]
  1555   1262       **  4:   [RRRR.]
  1556   1263       */
  1557         -    if( locktype==SHARED_LOCK ){
         1264  +    if( eFileLock==SHARED_LOCK ){
  1558   1265         if( handleNFSUnlock ){
  1559   1266           off_t divSize = SHARED_SIZE - 1;
  1560   1267           
  1561   1268           lock.l_type = F_UNLCK;
  1562   1269           lock.l_whence = SEEK_SET;
  1563   1270           lock.l_start = SHARED_FIRST;
  1564   1271           lock.l_len = divSize;
................................................................................
  1610   1317         }
  1611   1318       }
  1612   1319       lock.l_type = F_UNLCK;
  1613   1320       lock.l_whence = SEEK_SET;
  1614   1321       lock.l_start = PENDING_BYTE;
  1615   1322       lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
  1616   1323       if( fcntl(h, F_SETLK, &lock)!=(-1) ){
  1617         -      pLock->locktype = SHARED_LOCK;
         1324  +      pInode->eFileLock = SHARED_LOCK;
  1618   1325       }else{
  1619   1326         tErrno = errno;
  1620   1327         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1621   1328         if( IS_LOCK_ERROR(rc) ){
  1622   1329           pFile->lastErrno = tErrno;
  1623   1330         }
  1624   1331         goto end_unlock;
  1625   1332       }
  1626   1333     }
  1627         -  if( locktype==NO_LOCK ){
  1628         -    struct unixOpenCnt *pOpen;
  1629         -
         1334  +  if( eFileLock==NO_LOCK ){
  1630   1335       /* Decrement the shared lock counter.  Release the lock using an
  1631   1336       ** OS call only when all threads in this same process have released
  1632   1337       ** the lock.
  1633   1338       */
  1634         -    pLock->cnt--;
  1635         -    if( pLock->cnt==0 ){
         1339  +    pInode->nShared--;
         1340  +    if( pInode->nShared==0 ){
  1636   1341         lock.l_type = F_UNLCK;
  1637   1342         lock.l_whence = SEEK_SET;
  1638   1343         lock.l_start = lock.l_len = 0L;
  1639   1344         SimulateIOErrorBenign(1);
  1640   1345         SimulateIOError( h=(-1) )
  1641   1346         SimulateIOErrorBenign(0);
  1642   1347         if( fcntl(h, F_SETLK, &lock)!=(-1) ){
  1643         -        pLock->locktype = NO_LOCK;
         1348  +        pInode->eFileLock = NO_LOCK;
  1644   1349         }else{
  1645   1350           tErrno = errno;
  1646   1351           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1647   1352           if( IS_LOCK_ERROR(rc) ){
  1648   1353             pFile->lastErrno = tErrno;
  1649   1354           }
  1650         -        pLock->locktype = NO_LOCK;
  1651         -        pFile->locktype = NO_LOCK;
         1355  +        pInode->eFileLock = NO_LOCK;
         1356  +        pFile->eFileLock = NO_LOCK;
  1652   1357         }
  1653   1358       }
  1654   1359   
  1655   1360       /* Decrement the count of locks against this same file.  When the
  1656   1361       ** count reaches zero, close any other file descriptors whose close
  1657   1362       ** was deferred because of outstanding locks.
  1658   1363       */
  1659         -    pOpen = pFile->pOpen;
  1660         -    pOpen->nLock--;
  1661         -    assert( pOpen->nLock>=0 );
  1662         -    if( pOpen->nLock==0 ){
         1364  +    pInode->nLock--;
         1365  +    assert( pInode->nLock>=0 );
         1366  +    if( pInode->nLock==0 ){
  1663   1367         int rc2 = closePendingFds(pFile);
  1664   1368         if( rc==SQLITE_OK ){
  1665   1369           rc = rc2;
  1666   1370         }
  1667   1371       }
  1668   1372     }
  1669   1373   	
  1670   1374   end_unlock:
  1671   1375     unixLeaveMutex();
  1672         -  if( rc==SQLITE_OK ) pFile->locktype = locktype;
         1376  +  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
  1673   1377     return rc;
  1674   1378   }
  1675   1379   
  1676   1380   /*
  1677         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         1381  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  1678   1382   ** must be either NO_LOCK or SHARED_LOCK.
  1679   1383   **
  1680   1384   ** If the locking level of the file descriptor is already at or below
  1681   1385   ** the requested locking level, this routine is a no-op.
  1682   1386   */
  1683         -static int unixUnlock(sqlite3_file *id, int locktype){
  1684         -  return _posixUnlock(id, locktype, 0);
         1387  +static int unixUnlock(sqlite3_file *id, int eFileLock){
         1388  +  return _posixUnlock(id, eFileLock, 0);
  1685   1389   }
  1686   1390   
  1687   1391   /*
  1688   1392   ** This function performs the parts of the "close file" operation 
  1689   1393   ** common to all locking schemes. It closes the directory and file
  1690   1394   ** handles, if they are valid, and sets all fields of the unixFile
  1691   1395   ** structure to 0.
................................................................................
  1718   1422         if( pFile->isDelete ){
  1719   1423           unlink(pFile->pId->zCanonicalName);
  1720   1424         }
  1721   1425         vxworksReleaseFileId(pFile->pId);
  1722   1426         pFile->pId = 0;
  1723   1427       }
  1724   1428   #endif
  1725         -    OSTRACE2("CLOSE   %-3d\n", pFile->h);
         1429  +    OSTRACE(("CLOSE   %-3d\n", pFile->h);
  1726   1430       OpenCounter(-1);
  1727   1431       sqlite3_free(pFile->pUnused);
  1728         -    memset(pFile, 0, sizeof(unixFile));
         1432  +    memset(pFile, 0, sizeof(unixFile)));
  1729   1433     }
  1730   1434     return SQLITE_OK;
  1731   1435   }
  1732   1436   
  1733   1437   /*
  1734   1438   ** Close a file.
  1735   1439   */
  1736   1440   static int unixClose(sqlite3_file *id){
  1737   1441     int rc = SQLITE_OK;
  1738   1442     if( id ){
  1739   1443       unixFile *pFile = (unixFile *)id;
  1740   1444       unixUnlock(id, NO_LOCK);
  1741   1445       unixEnterMutex();
  1742         -    if( pFile->pOpen && pFile->pOpen->nLock ){
         1446  +    if( pFile->pInode && pFile->pInode->nLock ){
  1743   1447         /* If there are outstanding locks, do not actually close the file just
  1744   1448         ** yet because that would clear those locks.  Instead, add the file
  1745         -      ** descriptor to pOpen->pUnused list.  It will be automatically closed 
         1449  +      ** descriptor to pInode->pUnused list.  It will be automatically closed 
  1746   1450         ** when the last lock is cleared.
  1747   1451         */
  1748   1452         setPendingFd(pFile);
  1749   1453       }
  1750         -    releaseLockInfo(pFile->pLock);
  1751         -    releaseOpenCnt(pFile->pOpen);
         1454  +    releaseInodeInfo(pFile->pInode);
  1752   1455       rc = closeUnixFile(id);
  1753   1456       unixLeaveMutex();
  1754   1457     }
  1755   1458     return rc;
  1756   1459   }
  1757   1460   
  1758   1461   /************** End of the posix advisory lock implementation *****************
................................................................................
  1843   1546     unixFile *pFile = (unixFile*)id;
  1844   1547   
  1845   1548     SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  1846   1549     
  1847   1550     assert( pFile );
  1848   1551   
  1849   1552     /* Check if a thread in this process holds such a lock */
  1850         -  if( pFile->locktype>SHARED_LOCK ){
         1553  +  if( pFile->eFileLock>SHARED_LOCK ){
  1851   1554       /* Either this connection or some other connection in the same process
  1852   1555       ** holds a lock on the file.  No need to check further. */
  1853   1556       reserved = 1;
  1854   1557     }else{
  1855   1558       /* The lock is held if and only if the lockfile exists */
  1856   1559       const char *zLockFile = (const char*)pFile->lockingContext;
  1857   1560       reserved = access(zLockFile, 0)==0;
  1858   1561     }
  1859         -  OSTRACE4("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved);
         1562  +  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
  1860   1563     *pResOut = reserved;
  1861   1564     return rc;
  1862   1565   }
  1863   1566   
  1864   1567   /*
  1865         -** Lock the file with the lock specified by parameter locktype - one
         1568  +** Lock the file with the lock specified by parameter eFileLock - one
  1866   1569   ** of the following:
  1867   1570   **
  1868   1571   **     (1) SHARED_LOCK
  1869   1572   **     (2) RESERVED_LOCK
  1870   1573   **     (3) PENDING_LOCK
  1871   1574   **     (4) EXCLUSIVE_LOCK
  1872   1575   **
................................................................................
  1884   1587   **
  1885   1588   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  1886   1589   ** routine to lower a locking level.
  1887   1590   **
  1888   1591   ** With dotfile locking, we really only support state (4): EXCLUSIVE.
  1889   1592   ** But we track the other locking levels internally.
  1890   1593   */
  1891         -static int dotlockLock(sqlite3_file *id, int locktype) {
         1594  +static int dotlockLock(sqlite3_file *id, int eFileLock) {
  1892   1595     unixFile *pFile = (unixFile*)id;
  1893   1596     int fd;
  1894   1597     char *zLockFile = (char *)pFile->lockingContext;
  1895   1598     int rc = SQLITE_OK;
  1896   1599   
  1897   1600   
  1898   1601     /* If we have any lock, then the lock file already exists.  All we have
  1899   1602     ** to do is adjust our internal record of the lock level.
  1900   1603     */
  1901         -  if( pFile->locktype > NO_LOCK ){
  1902         -    pFile->locktype = locktype;
         1604  +  if( pFile->eFileLock > NO_LOCK ){
         1605  +    pFile->eFileLock = eFileLock;
  1903   1606   #if !OS_VXWORKS
  1904   1607       /* Always update the timestamp on the old file */
  1905   1608       utimes(zLockFile, NULL);
  1906   1609   #endif
  1907   1610       return SQLITE_OK;
  1908   1611     }
  1909   1612     
................................................................................
  1924   1627     } 
  1925   1628     if( close(fd) ){
  1926   1629       pFile->lastErrno = errno;
  1927   1630       rc = SQLITE_IOERR_CLOSE;
  1928   1631     }
  1929   1632     
  1930   1633     /* got it, set the type and return ok */
  1931         -  pFile->locktype = locktype;
         1634  +  pFile->eFileLock = eFileLock;
  1932   1635     return rc;
  1933   1636   }
  1934   1637   
  1935   1638   /*
  1936         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         1639  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  1937   1640   ** must be either NO_LOCK or SHARED_LOCK.
  1938   1641   **
  1939   1642   ** If the locking level of the file descriptor is already at or below
  1940   1643   ** the requested locking level, this routine is a no-op.
  1941   1644   **
  1942   1645   ** When the locking level reaches NO_LOCK, delete the lock file.
  1943   1646   */
  1944         -static int dotlockUnlock(sqlite3_file *id, int locktype) {
         1647  +static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
  1945   1648     unixFile *pFile = (unixFile*)id;
  1946   1649     char *zLockFile = (char *)pFile->lockingContext;
  1947   1650   
  1948   1651     assert( pFile );
  1949         -  OSTRACE5("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, locktype,
  1950         -	   pFile->locktype, getpid());
  1951         -  assert( locktype<=SHARED_LOCK );
         1652  +  OSTRACE(("UNLOCK  %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
         1653  +	   pFile->eFileLock, getpid()));
         1654  +  assert( eFileLock<=SHARED_LOCK );
  1952   1655     
  1953   1656     /* no-op if possible */
  1954         -  if( pFile->locktype==locktype ){
         1657  +  if( pFile->eFileLock==eFileLock ){
  1955   1658       return SQLITE_OK;
  1956   1659     }
  1957   1660   
  1958   1661     /* To downgrade to shared, simply update our internal notion of the
  1959   1662     ** lock state.  No need to mess with the file on disk.
  1960   1663     */
  1961         -  if( locktype==SHARED_LOCK ){
  1962         -    pFile->locktype = SHARED_LOCK;
         1664  +  if( eFileLock==SHARED_LOCK ){
         1665  +    pFile->eFileLock = SHARED_LOCK;
  1963   1666       return SQLITE_OK;
  1964   1667     }
  1965   1668     
  1966   1669     /* To fully unlock the database, delete the lock file */
  1967         -  assert( locktype==NO_LOCK );
         1670  +  assert( eFileLock==NO_LOCK );
  1968   1671     if( unlink(zLockFile) ){
  1969   1672       int rc = 0;
  1970   1673       int tErrno = errno;
  1971   1674       if( ENOENT != tErrno ){
  1972   1675         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1973   1676       }
  1974   1677       if( IS_LOCK_ERROR(rc) ){
  1975   1678         pFile->lastErrno = tErrno;
  1976   1679       }
  1977   1680       return rc; 
  1978   1681     }
  1979         -  pFile->locktype = NO_LOCK;
         1682  +  pFile->eFileLock = NO_LOCK;
  1980   1683     return SQLITE_OK;
  1981   1684   }
  1982   1685   
  1983   1686   /*
  1984   1687   ** Close a file.  Make sure the lock has been released before closing.
  1985   1688   */
  1986   1689   static int dotlockClose(sqlite3_file *id) {
................................................................................
  2025   1728     unixFile *pFile = (unixFile*)id;
  2026   1729     
  2027   1730     SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  2028   1731     
  2029   1732     assert( pFile );
  2030   1733     
  2031   1734     /* Check if a thread in this process holds such a lock */
  2032         -  if( pFile->locktype>SHARED_LOCK ){
         1735  +  if( pFile->eFileLock>SHARED_LOCK ){
  2033   1736       reserved = 1;
  2034   1737     }
  2035   1738     
  2036   1739     /* Otherwise see if some other process holds it. */
  2037   1740     if( !reserved ){
  2038   1741       /* attempt to get the lock */
  2039   1742       int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);
................................................................................
  2056   1759         lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK); 
  2057   1760         if( IS_LOCK_ERROR(lrc) ){
  2058   1761           pFile->lastErrno = tErrno;
  2059   1762           rc = lrc;
  2060   1763         }
  2061   1764       }
  2062   1765     }
  2063         -  OSTRACE4("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved);
         1766  +  OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
  2064   1767   
  2065   1768   #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
  2066   1769     if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
  2067   1770       rc = SQLITE_OK;
  2068   1771       reserved=1;
  2069   1772     }
  2070   1773   #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
  2071   1774     *pResOut = reserved;
  2072   1775     return rc;
  2073   1776   }
  2074   1777   
  2075   1778   /*
  2076         -** Lock the file with the lock specified by parameter locktype - one
         1779  +** Lock the file with the lock specified by parameter eFileLock - one
  2077   1780   ** of the following:
  2078   1781   **
  2079   1782   **     (1) SHARED_LOCK
  2080   1783   **     (2) RESERVED_LOCK
  2081   1784   **     (3) PENDING_LOCK
  2082   1785   **     (4) EXCLUSIVE_LOCK
  2083   1786   **
................................................................................
  2097   1800   ** lock states in the sqlite3_file structure, but all locks SHARED or
  2098   1801   ** above are really EXCLUSIVE locks and exclude all other processes from
  2099   1802   ** access the file.
  2100   1803   **
  2101   1804   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  2102   1805   ** routine to lower a locking level.
  2103   1806   */
  2104         -static int flockLock(sqlite3_file *id, int locktype) {
         1807  +static int flockLock(sqlite3_file *id, int eFileLock) {
  2105   1808     int rc = SQLITE_OK;
  2106   1809     unixFile *pFile = (unixFile*)id;
  2107   1810   
  2108   1811     assert( pFile );
  2109   1812   
  2110   1813     /* if we already have a lock, it is exclusive.  
  2111   1814     ** Just adjust level and punt on outta here. */
  2112         -  if (pFile->locktype > NO_LOCK) {
  2113         -    pFile->locktype = locktype;
         1815  +  if (pFile->eFileLock > NO_LOCK) {
         1816  +    pFile->eFileLock = eFileLock;
  2114   1817       return SQLITE_OK;
  2115   1818     }
  2116   1819     
  2117   1820     /* grab an exclusive lock */
  2118   1821     
  2119   1822     if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
  2120   1823       int tErrno = errno;
................................................................................
  2121   1824       /* didn't get, must be busy */
  2122   1825       rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  2123   1826       if( IS_LOCK_ERROR(rc) ){
  2124   1827         pFile->lastErrno = tErrno;
  2125   1828       }
  2126   1829     } else {
  2127   1830       /* got it, set the type and return ok */
  2128         -    pFile->locktype = locktype;
         1831  +    pFile->eFileLock = eFileLock;
  2129   1832     }
  2130         -  OSTRACE4("LOCK    %d %s %s (flock)\n", pFile->h, locktypeName(locktype), 
  2131         -           rc==SQLITE_OK ? "ok" : "failed");
         1833  +  OSTRACE(("LOCK    %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock), 
         1834  +           rc==SQLITE_OK ? "ok" : "failed"));
  2132   1835   #ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
  2133   1836     if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
  2134   1837       rc = SQLITE_BUSY;
  2135   1838     }
  2136   1839   #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
  2137   1840     return rc;
  2138   1841   }
  2139   1842   
  2140   1843   
  2141   1844   /*
  2142         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         1845  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  2143   1846   ** must be either NO_LOCK or SHARED_LOCK.
  2144   1847   **
  2145   1848   ** If the locking level of the file descriptor is already at or below
  2146   1849   ** the requested locking level, this routine is a no-op.
  2147   1850   */
  2148         -static int flockUnlock(sqlite3_file *id, int locktype) {
         1851  +static int flockUnlock(sqlite3_file *id, int eFileLock) {
  2149   1852     unixFile *pFile = (unixFile*)id;
  2150   1853     
  2151   1854     assert( pFile );
  2152         -  OSTRACE5("UNLOCK  %d %d was %d pid=%d (flock)\n", pFile->h, locktype,
  2153         -           pFile->locktype, getpid());
  2154         -  assert( locktype<=SHARED_LOCK );
         1855  +  OSTRACE(("UNLOCK  %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
         1856  +           pFile->eFileLock, getpid()));
         1857  +  assert( eFileLock<=SHARED_LOCK );
  2155   1858     
  2156   1859     /* no-op if possible */
  2157         -  if( pFile->locktype==locktype ){
         1860  +  if( pFile->eFileLock==eFileLock ){
  2158   1861       return SQLITE_OK;
  2159   1862     }
  2160   1863     
  2161   1864     /* shared can just be set because we always have an exclusive */
  2162         -  if (locktype==SHARED_LOCK) {
  2163         -    pFile->locktype = locktype;
         1865  +  if (eFileLock==SHARED_LOCK) {
         1866  +    pFile->eFileLock = eFileLock;
  2164   1867       return SQLITE_OK;
  2165   1868     }
  2166   1869     
  2167   1870     /* no, really, unlock. */
  2168   1871     int rc = flock(pFile->h, LOCK_UN);
  2169   1872     if (rc) {
  2170   1873       int r, tErrno = errno;
................................................................................
  2176   1879       if( (r & SQLITE_IOERR) == SQLITE_IOERR ){
  2177   1880         r = SQLITE_BUSY;
  2178   1881       }
  2179   1882   #endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
  2180   1883       
  2181   1884       return r;
  2182   1885     } else {
  2183         -    pFile->locktype = NO_LOCK;
         1886  +    pFile->eFileLock = NO_LOCK;
  2184   1887       return SQLITE_OK;
  2185   1888     }
  2186   1889   }
  2187   1890   
  2188   1891   /*
  2189   1892   ** Close a file.
  2190   1893   */
................................................................................
  2224   1927     unixFile *pFile = (unixFile*)id;
  2225   1928   
  2226   1929     SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  2227   1930     
  2228   1931     assert( pFile );
  2229   1932   
  2230   1933     /* Check if a thread in this process holds such a lock */
  2231         -  if( pFile->locktype>SHARED_LOCK ){
         1934  +  if( pFile->eFileLock>SHARED_LOCK ){
  2232   1935       reserved = 1;
  2233   1936     }
  2234   1937     
  2235   1938     /* Otherwise see if some other process holds it. */
  2236   1939     if( !reserved ){
  2237         -    sem_t *pSem = pFile->pOpen->pSem;
         1940  +    sem_t *pSem = pFile->pInode->pSem;
  2238   1941       struct stat statBuf;
  2239   1942   
  2240   1943       if( sem_trywait(pSem)==-1 ){
  2241   1944         int tErrno = errno;
  2242   1945         if( EAGAIN != tErrno ){
  2243   1946           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
  2244   1947           pFile->lastErrno = tErrno;
  2245   1948         } else {
  2246   1949           /* someone else has the lock when we are in NO_LOCK */
  2247         -        reserved = (pFile->locktype < SHARED_LOCK);
         1950  +        reserved = (pFile->eFileLock < SHARED_LOCK);
  2248   1951         }
  2249   1952       }else{
  2250   1953         /* we could have it if we want it */
  2251   1954         sem_post(pSem);
  2252   1955       }
  2253   1956     }
  2254         -  OSTRACE4("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved);
         1957  +  OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
  2255   1958   
  2256   1959     *pResOut = reserved;
  2257   1960     return rc;
  2258   1961   }
  2259   1962   
  2260   1963   /*
  2261         -** Lock the file with the lock specified by parameter locktype - one
         1964  +** Lock the file with the lock specified by parameter eFileLock - one
  2262   1965   ** of the following:
  2263   1966   **
  2264   1967   **     (1) SHARED_LOCK
  2265   1968   **     (2) RESERVED_LOCK
  2266   1969   **     (3) PENDING_LOCK
  2267   1970   **     (4) EXCLUSIVE_LOCK
  2268   1971   **
................................................................................
  2282   1985   ** lock states in the sqlite3_file structure, but all locks SHARED or
  2283   1986   ** above are really EXCLUSIVE locks and exclude all other processes from
  2284   1987   ** access the file.
  2285   1988   **
  2286   1989   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  2287   1990   ** routine to lower a locking level.
  2288   1991   */
  2289         -static int semLock(sqlite3_file *id, int locktype) {
         1992  +static int semLock(sqlite3_file *id, int eFileLock) {
  2290   1993     unixFile *pFile = (unixFile*)id;
  2291   1994     int fd;
  2292         -  sem_t *pSem = pFile->pOpen->pSem;
         1995  +  sem_t *pSem = pFile->pInode->pSem;
  2293   1996     int rc = SQLITE_OK;
  2294   1997   
  2295   1998     /* if we already have a lock, it is exclusive.  
  2296   1999     ** Just adjust level and punt on outta here. */
  2297         -  if (pFile->locktype > NO_LOCK) {
  2298         -    pFile->locktype = locktype;
         2000  +  if (pFile->eFileLock > NO_LOCK) {
         2001  +    pFile->eFileLock = eFileLock;
  2299   2002       rc = SQLITE_OK;
  2300   2003       goto sem_end_lock;
  2301   2004     }
  2302   2005     
  2303   2006     /* lock semaphore now but bail out when already locked. */
  2304   2007     if( sem_trywait(pSem)==-1 ){
  2305   2008       rc = SQLITE_BUSY;
  2306   2009       goto sem_end_lock;
  2307   2010     }
  2308   2011   
  2309   2012     /* got it, set the type and return ok */
  2310         -  pFile->locktype = locktype;
         2013  +  pFile->eFileLock = eFileLock;
  2311   2014   
  2312   2015    sem_end_lock:
  2313   2016     return rc;
  2314   2017   }
  2315   2018   
  2316   2019   /*
  2317         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         2020  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  2318   2021   ** must be either NO_LOCK or SHARED_LOCK.
  2319   2022   **
  2320   2023   ** If the locking level of the file descriptor is already at or below
  2321   2024   ** the requested locking level, this routine is a no-op.
  2322   2025   */
  2323         -static int semUnlock(sqlite3_file *id, int locktype) {
         2026  +static int semUnlock(sqlite3_file *id, int eFileLock) {
  2324   2027     unixFile *pFile = (unixFile*)id;
  2325         -  sem_t *pSem = pFile->pOpen->pSem;
         2028  +  sem_t *pSem = pFile->pInode->pSem;
  2326   2029   
  2327   2030     assert( pFile );
  2328   2031     assert( pSem );
  2329         -  OSTRACE5("UNLOCK  %d %d was %d pid=%d (sem)\n", pFile->h, locktype,
  2330         -	   pFile->locktype, getpid());
  2331         -  assert( locktype<=SHARED_LOCK );
         2032  +  OSTRACE(("UNLOCK  %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
         2033  +	   pFile->eFileLock, getpid()));
         2034  +  assert( eFileLock<=SHARED_LOCK );
  2332   2035     
  2333   2036     /* no-op if possible */
  2334         -  if( pFile->locktype==locktype ){
         2037  +  if( pFile->eFileLock==eFileLock ){
  2335   2038       return SQLITE_OK;
  2336   2039     }
  2337   2040     
  2338   2041     /* shared can just be set because we always have an exclusive */
  2339         -  if (locktype==SHARED_LOCK) {
  2340         -    pFile->locktype = locktype;
         2042  +  if (eFileLock==SHARED_LOCK) {
         2043  +    pFile->eFileLock = eFileLock;
  2341   2044       return SQLITE_OK;
  2342   2045     }
  2343   2046     
  2344   2047     /* no, really unlock. */
  2345   2048     if ( sem_post(pSem)==-1 ) {
  2346   2049       int rc, tErrno = errno;
  2347   2050       rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  2348   2051       if( IS_LOCK_ERROR(rc) ){
  2349   2052         pFile->lastErrno = tErrno;
  2350   2053       }
  2351   2054       return rc; 
  2352   2055     }
  2353         -  pFile->locktype = NO_LOCK;
         2056  +  pFile->eFileLock = NO_LOCK;
  2354   2057     return SQLITE_OK;
  2355   2058   }
  2356   2059   
  2357   2060   /*
  2358   2061    ** Close a file.
  2359   2062    */
  2360   2063   static int semClose(sqlite3_file *id) {
  2361   2064     if( id ){
  2362   2065       unixFile *pFile = (unixFile*)id;
  2363   2066       semUnlock(id, NO_LOCK);
  2364   2067       assert( pFile );
  2365   2068       unixEnterMutex();
  2366         -    releaseLockInfo(pFile->pLock);
  2367         -    releaseOpenCnt(pFile->pOpen);
         2069  +    releaseLockInfo(pFile->pInode);
  2368   2070       unixLeaveMutex();
  2369   2071       closeUnixFile(id);
  2370   2072     }
  2371   2073     return SQLITE_OK;
  2372   2074   }
  2373   2075   
  2374   2076   #endif /* OS_VXWORKS */
................................................................................
  2429   2131     
  2430   2132     pb.unLockFlag = setLockFlag ? 0 : 1;
  2431   2133     pb.startEndFlag = 0;
  2432   2134     pb.offset = offset;
  2433   2135     pb.length = length; 
  2434   2136     pb.fd = pFile->h;
  2435   2137     
  2436         -  OSTRACE6("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", 
         2138  +  OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n", 
  2437   2139       (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
  2438         -    offset, length);
         2140  +    offset, length));
  2439   2141     err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
  2440   2142     if ( err==-1 ) {
  2441   2143       int rc;
  2442   2144       int tErrno = errno;
  2443         -    OSTRACE4("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
  2444         -             path, tErrno, strerror(tErrno));
         2145  +    OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
         2146  +             path, tErrno, strerror(tErrno)));
  2445   2147   #ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
  2446   2148       rc = SQLITE_BUSY;
  2447   2149   #else
  2448   2150       rc = sqliteErrorFromPosixError(tErrno,
  2449   2151                       setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
  2450   2152   #endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
  2451   2153       if( IS_LOCK_ERROR(rc) ){
................................................................................
  2472   2174     
  2473   2175     assert( pFile );
  2474   2176     afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
  2475   2177     if( context->reserved ){
  2476   2178       *pResOut = 1;
  2477   2179       return SQLITE_OK;
  2478   2180     }
  2479         -  unixEnterMutex(); /* Because pFile->pLock is shared across threads */
         2181  +  unixEnterMutex(); /* Because pFile->pInode is shared across threads */
  2480   2182     
  2481   2183     /* Check if a thread in this process holds such a lock */
  2482         -  if( pFile->pLock->locktype>SHARED_LOCK ){
         2184  +  if( pFile->pInode->eFileLock>SHARED_LOCK ){
  2483   2185       reserved = 1;
  2484   2186     }
  2485   2187     
  2486   2188     /* Otherwise see if some other process holds it.
  2487   2189      */
  2488   2190     if( !reserved ){
  2489   2191       /* lock the RESERVED byte */
................................................................................
  2498   2200       }
  2499   2201       if( IS_LOCK_ERROR(lrc) ){
  2500   2202         rc=lrc;
  2501   2203       }
  2502   2204     }
  2503   2205     
  2504   2206     unixLeaveMutex();
  2505         -  OSTRACE4("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved);
         2207  +  OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
  2506   2208     
  2507   2209     *pResOut = reserved;
  2508   2210     return rc;
  2509   2211   }
  2510   2212   
  2511   2213   /*
  2512         -** Lock the file with the lock specified by parameter locktype - one
         2214  +** Lock the file with the lock specified by parameter eFileLock - one
  2513   2215   ** of the following:
  2514   2216   **
  2515   2217   **     (1) SHARED_LOCK
  2516   2218   **     (2) RESERVED_LOCK
  2517   2219   **     (3) PENDING_LOCK
  2518   2220   **     (4) EXCLUSIVE_LOCK
  2519   2221   **
................................................................................
  2528   2230   **    SHARED -> (PENDING) -> EXCLUSIVE
  2529   2231   **    RESERVED -> (PENDING) -> EXCLUSIVE
  2530   2232   **    PENDING -> EXCLUSIVE
  2531   2233   **
  2532   2234   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  2533   2235   ** routine to lower a locking level.
  2534   2236   */
  2535         -static int afpLock(sqlite3_file *id, int locktype){
         2237  +static int afpLock(sqlite3_file *id, int eFileLock){
  2536   2238     int rc = SQLITE_OK;
  2537   2239     unixFile *pFile = (unixFile*)id;
  2538         -  struct unixLockInfo *pLock = pFile->pLock;
         2240  +  unixInodeInfo *pInode = pFile->pInode;
  2539   2241     afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
  2540   2242     
  2541   2243     assert( pFile );
  2542         -  OSTRACE7("LOCK    %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
  2543         -           locktypeName(locktype), locktypeName(pFile->locktype),
  2544         -           locktypeName(pLock->locktype), pLock->cnt , getpid());
         2244  +  OSTRACE(("LOCK    %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
         2245  +           azFileLock(eFileLock), azFileLock(pFile->eFileLock),
         2246  +           azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
  2545   2247   
  2546   2248     /* If there is already a lock of this type or more restrictive on the
  2547   2249     ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
  2548   2250     ** unixEnterMutex() hasn't been called yet.
  2549   2251     */
  2550         -  if( pFile->locktype>=locktype ){
  2551         -    OSTRACE3("LOCK    %d %s ok (already held) (afp)\n", pFile->h,
  2552         -           locktypeName(locktype));
         2252  +  if( pFile->eFileLock>=eFileLock ){
         2253  +    OSTRACE(("LOCK    %d %s ok (already held) (afp)\n", pFile->h,
         2254  +           azFileLock(eFileLock)));
  2553   2255       return SQLITE_OK;
  2554   2256     }
  2555   2257   
  2556   2258     /* Make sure the locking sequence is correct
  2557   2259     **  (1) We never move from unlocked to anything higher than shared lock.
  2558   2260     **  (2) SQLite never explicitly requests a pendig lock.
  2559   2261     **  (3) A shared lock is always held when a reserve lock is requested.
  2560   2262     */
  2561         -  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
  2562         -  assert( locktype!=PENDING_LOCK );
  2563         -  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
         2263  +  assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
         2264  +  assert( eFileLock!=PENDING_LOCK );
         2265  +  assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
  2564   2266     
  2565         -  /* This mutex is needed because pFile->pLock is shared across threads
         2267  +  /* This mutex is needed because pFile->pInode is shared across threads
  2566   2268     */
  2567   2269     unixEnterMutex();
  2568         -
  2569         -  /* Make sure the current thread owns the pFile.
  2570         -  */
  2571         -  rc = transferOwnership(pFile);
  2572         -  if( rc!=SQLITE_OK ){
  2573         -    unixLeaveMutex();
  2574         -    return rc;
  2575         -  }
  2576         -  pLock = pFile->pLock;
         2270  +  pInode = pFile->pInode;
  2577   2271   
  2578   2272     /* If some thread using this PID has a lock via a different unixFile*
  2579   2273     ** handle that precludes the requested lock, return BUSY.
  2580   2274     */
  2581         -  if( (pFile->locktype!=pLock->locktype && 
  2582         -       (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK))
         2275  +  if( (pFile->eFileLock!=pInode->eFileLock && 
         2276  +       (pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
  2583   2277        ){
  2584   2278       rc = SQLITE_BUSY;
  2585   2279       goto afp_end_lock;
  2586   2280     }
  2587   2281     
  2588   2282     /* If a SHARED lock is requested, and some thread using this PID already
  2589   2283     ** has a SHARED or RESERVED lock, then increment reference counts and
  2590   2284     ** return SQLITE_OK.
  2591   2285     */
  2592         -  if( locktype==SHARED_LOCK && 
  2593         -     (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){
  2594         -    assert( locktype==SHARED_LOCK );
  2595         -    assert( pFile->locktype==0 );
  2596         -    assert( pLock->cnt>0 );
  2597         -    pFile->locktype = SHARED_LOCK;
  2598         -    pLock->cnt++;
  2599         -    pFile->pOpen->nLock++;
         2286  +  if( eFileLock==SHARED_LOCK && 
         2287  +     (pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
         2288  +    assert( eFileLock==SHARED_LOCK );
         2289  +    assert( pFile->eFileLock==0 );
         2290  +    assert( pInode->nShared>0 );
         2291  +    pFile->eFileLock = SHARED_LOCK;
         2292  +    pInode->nShared++;
         2293  +    pInode->nLock++;
  2600   2294       goto afp_end_lock;
  2601   2295     }
  2602   2296       
  2603   2297     /* A PENDING lock is needed before acquiring a SHARED lock and before
  2604   2298     ** acquiring an EXCLUSIVE lock.  For the SHARED lock, the PENDING will
  2605   2299     ** be released.
  2606   2300     */
  2607         -  if( locktype==SHARED_LOCK 
  2608         -      || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
         2301  +  if( eFileLock==SHARED_LOCK 
         2302  +      || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
  2609   2303     ){
  2610   2304       int failed;
  2611   2305       failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
  2612   2306       if (failed) {
  2613   2307         rc = failed;
  2614   2308         goto afp_end_lock;
  2615   2309       }
  2616   2310     }
  2617   2311     
  2618   2312     /* If control gets to this point, then actually go ahead and make
  2619   2313     ** operating system calls for the specified lock.
  2620   2314     */
  2621         -  if( locktype==SHARED_LOCK ){
         2315  +  if( eFileLock==SHARED_LOCK ){
  2622   2316       int lrc1, lrc2, lrc1Errno;
  2623   2317       long lk, mask;
  2624   2318       
  2625         -    assert( pLock->cnt==0 );
  2626         -    assert( pLock->locktype==0 );
         2319  +    assert( pInode->nShared==0 );
         2320  +    assert( pInode->eFileLock==0 );
  2627   2321           
  2628   2322       mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
  2629   2323       /* Now get the read-lock SHARED_LOCK */
  2630   2324       /* note that the quality of the randomness doesn't matter that much */
  2631   2325       lk = random(); 
  2632         -    pLock->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
         2326  +    pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
  2633   2327       lrc1 = afpSetLock(context->dbPath, pFile, 
  2634         -          SHARED_FIRST+pLock->sharedByte, 1, 1);
         2328  +          SHARED_FIRST+pInode->sharedByte, 1, 1);
  2635   2329       if( IS_LOCK_ERROR(lrc1) ){
  2636   2330         lrc1Errno = pFile->lastErrno;
  2637   2331       }
  2638   2332       /* Drop the temporary PENDING lock */
  2639   2333       lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
  2640   2334       
  2641   2335       if( IS_LOCK_ERROR(lrc1) ) {
................................................................................
  2644   2338         goto afp_end_lock;
  2645   2339       } else if( IS_LOCK_ERROR(lrc2) ){
  2646   2340         rc = lrc2;
  2647   2341         goto afp_end_lock;
  2648   2342       } else if( lrc1 != SQLITE_OK ) {
  2649   2343         rc = lrc1;
  2650   2344       } else {
  2651         -      pFile->locktype = SHARED_LOCK;
  2652         -      pFile->pOpen->nLock++;
  2653         -      pLock->cnt = 1;
         2345  +      pFile->eFileLock = SHARED_LOCK;
         2346  +      pInode->nLock++;
         2347  +      pInode->nShared = 1;
  2654   2348       }
  2655         -  }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){
         2349  +  }else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
  2656   2350       /* We are trying for an exclusive lock but another thread in this
  2657   2351        ** same process is still holding a shared lock. */
  2658   2352       rc = SQLITE_BUSY;
  2659   2353     }else{
  2660   2354       /* The request was for a RESERVED or EXCLUSIVE lock.  It is
  2661   2355       ** assumed that there is a SHARED or greater lock on the file
  2662   2356       ** already.
  2663   2357       */
  2664   2358       int failed = 0;
  2665         -    assert( 0!=pFile->locktype );
  2666         -    if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
         2359  +    assert( 0!=pFile->eFileLock );
         2360  +    if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
  2667   2361           /* Acquire a RESERVED lock */
  2668   2362           failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
  2669   2363         if( !failed ){
  2670   2364           context->reserved = 1;
  2671   2365         }
  2672   2366       }
  2673         -    if (!failed && locktype == EXCLUSIVE_LOCK) {
         2367  +    if (!failed && eFileLock == EXCLUSIVE_LOCK) {
  2674   2368         /* Acquire an EXCLUSIVE lock */
  2675   2369           
  2676   2370         /* Remove the shared lock before trying the range.  we'll need to 
  2677   2371         ** reestablish the shared lock if we can't get the  afpUnlock
  2678   2372         */
  2679   2373         if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
  2680         -                         pLock->sharedByte, 1, 0)) ){
         2374  +                         pInode->sharedByte, 1, 0)) ){
  2681   2375           int failed2 = SQLITE_OK;
  2682   2376           /* now attemmpt to get the exclusive lock range */
  2683   2377           failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, 
  2684   2378                                  SHARED_SIZE, 1);
  2685   2379           if( failed && (failed2 = afpSetLock(context->dbPath, pFile, 
  2686         -                       SHARED_FIRST + pLock->sharedByte, 1, 1)) ){
         2380  +                       SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
  2687   2381             /* Can't reestablish the shared lock.  Sqlite can't deal, this is
  2688   2382             ** a critical I/O error
  2689   2383             */
  2690   2384             rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : 
  2691   2385                  SQLITE_IOERR_LOCK;
  2692   2386             goto afp_end_lock;
  2693   2387           } 
................................................................................
  2697   2391       }
  2698   2392       if( failed ){
  2699   2393         rc = failed;
  2700   2394       }
  2701   2395     }
  2702   2396     
  2703   2397     if( rc==SQLITE_OK ){
  2704         -    pFile->locktype = locktype;
  2705         -    pLock->locktype = locktype;
  2706         -  }else if( locktype==EXCLUSIVE_LOCK ){
  2707         -    pFile->locktype = PENDING_LOCK;
  2708         -    pLock->locktype = PENDING_LOCK;
         2398  +    pFile->eFileLock = eFileLock;
         2399  +    pInode->eFileLock = eFileLock;
         2400  +  }else if( eFileLock==EXCLUSIVE_LOCK ){
         2401  +    pFile->eFileLock = PENDING_LOCK;
         2402  +    pInode->eFileLock = PENDING_LOCK;
  2709   2403     }
  2710   2404     
  2711   2405   afp_end_lock:
  2712   2406     unixLeaveMutex();
  2713         -  OSTRACE4("LOCK    %d %s %s (afp)\n", pFile->h, locktypeName(locktype), 
  2714         -         rc==SQLITE_OK ? "ok" : "failed");
         2407  +  OSTRACE(("LOCK    %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock), 
         2408  +         rc==SQLITE_OK ? "ok" : "failed"));
  2715   2409     return rc;
  2716   2410   }
  2717   2411   
  2718   2412   /*
  2719         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         2413  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  2720   2414   ** must be either NO_LOCK or SHARED_LOCK.
  2721   2415   **
  2722   2416   ** If the locking level of the file descriptor is already at or below
  2723   2417   ** the requested locking level, this routine is a no-op.
  2724   2418   */
  2725         -static int afpUnlock(sqlite3_file *id, int locktype) {
         2419  +static int afpUnlock(sqlite3_file *id, int eFileLock) {
  2726   2420     int rc = SQLITE_OK;
  2727   2421     unixFile *pFile = (unixFile*)id;
  2728         -  struct unixLockInfo *pLock;
         2422  +  unixInodeInfo *pInode;
  2729   2423     afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
  2730   2424     int skipShared = 0;
  2731   2425   #ifdef SQLITE_TEST
  2732   2426     int h = pFile->h;
  2733   2427   #endif
  2734   2428   
  2735   2429     assert( pFile );
  2736         -  OSTRACE7("UNLOCK  %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, locktype,
  2737         -           pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid());
         2430  +  OSTRACE(("UNLOCK  %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
         2431  +           pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
         2432  +           getpid()));
  2738   2433   
  2739         -  assert( locktype<=SHARED_LOCK );
  2740         -  if( pFile->locktype<=locktype ){
         2434  +  assert( eFileLock<=SHARED_LOCK );
         2435  +  if( pFile->eFileLock<=eFileLock ){
  2741   2436       return SQLITE_OK;
  2742   2437     }
  2743         -  if( CHECK_THREADID(pFile) ){
  2744         -    return SQLITE_MISUSE_BKPT;
  2745         -  }
  2746   2438     unixEnterMutex();
  2747         -  pLock = pFile->pLock;
  2748         -  assert( pLock->cnt!=0 );
  2749         -  if( pFile->locktype>SHARED_LOCK ){
  2750         -    assert( pLock->locktype==pFile->locktype );
         2439  +  pInode = pFile->pInode;
         2440  +  assert( pInode->nShared!=0 );
         2441  +  if( pFile->eFileLock>SHARED_LOCK ){
         2442  +    assert( pInode->eFileLock==pFile->eFileLock );
  2751   2443       SimulateIOErrorBenign(1);
  2752   2444       SimulateIOError( h=(-1) )
  2753   2445       SimulateIOErrorBenign(0);
  2754   2446       
  2755   2447   #ifndef NDEBUG
  2756   2448       /* When reducing a lock such that other processes can start
  2757   2449       ** reading the database file again, make sure that the
................................................................................
  2763   2455       */
  2764   2456       assert( pFile->inNormalWrite==0
  2765   2457              || pFile->dbUpdate==0
  2766   2458              || pFile->transCntrChng==1 );
  2767   2459       pFile->inNormalWrite = 0;
  2768   2460   #endif
  2769   2461       
  2770         -    if( pFile->locktype==EXCLUSIVE_LOCK ){
         2462  +    if( pFile->eFileLock==EXCLUSIVE_LOCK ){
  2771   2463         rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
  2772         -      if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1) ){
         2464  +      if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
  2773   2465           /* only re-establish the shared lock if necessary */
  2774         -        int sharedLockByte = SHARED_FIRST+pLock->sharedByte;
         2466  +        int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
  2775   2467           rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
  2776   2468         } else {
  2777   2469           skipShared = 1;
  2778   2470         }
  2779   2471       }
  2780         -    if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){
         2472  +    if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
  2781   2473         rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
  2782   2474       } 
  2783         -    if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){
         2475  +    if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
  2784   2476         rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
  2785   2477         if( !rc ){ 
  2786   2478           context->reserved = 0; 
  2787   2479         }
  2788   2480       }
  2789         -    if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1)){
  2790         -      pLock->locktype = SHARED_LOCK;
         2481  +    if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
         2482  +      pInode->eFileLock = SHARED_LOCK;
  2791   2483       }
  2792   2484     }
  2793         -  if( rc==SQLITE_OK && locktype==NO_LOCK ){
         2485  +  if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
  2794   2486   
  2795   2487       /* Decrement the shared lock counter.  Release the lock using an
  2796   2488       ** OS call only when all threads in this same process have released
  2797   2489       ** the lock.
  2798   2490       */
  2799         -    unsigned long long sharedLockByte = SHARED_FIRST+pLock->sharedByte;
  2800         -    pLock->cnt--;
  2801         -    if( pLock->cnt==0 ){
         2491  +    unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
         2492  +    pInode->nShared--;
         2493  +    if( pInode->nShared==0 ){
  2802   2494         SimulateIOErrorBenign(1);
  2803   2495         SimulateIOError( h=(-1) )
  2804   2496         SimulateIOErrorBenign(0);
  2805   2497         if( !skipShared ){
  2806   2498           rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
  2807   2499         }
  2808   2500         if( !rc ){
  2809         -        pLock->locktype = NO_LOCK;
  2810         -        pFile->locktype = NO_LOCK;
         2501  +        pInode->eFileLock = NO_LOCK;
         2502  +        pFile->eFileLock = NO_LOCK;
  2811   2503         }
  2812   2504       }
  2813   2505       if( rc==SQLITE_OK ){
  2814         -      struct unixOpenCnt *pOpen = pFile->pOpen;
  2815         -        
  2816         -      pOpen->nLock--;
  2817         -      assert( pOpen->nLock>=0 );
  2818         -      if( pOpen->nLock==0 ){
         2506  +      pInode->nLock--;
         2507  +      assert( pInode->nLock>=0 );
         2508  +      if( pInode->nLock==0 ){
  2819   2509           rc = closePendingFds(pFile);
  2820   2510         }
  2821   2511       }
  2822   2512     }
  2823   2513     
  2824   2514     unixLeaveMutex();
  2825         -  if( rc==SQLITE_OK ) pFile->locktype = locktype;
         2515  +  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
  2826   2516     return rc;
  2827   2517   }
  2828   2518   
  2829   2519   /*
  2830   2520   ** Close a file & cleanup AFP specific locking context 
  2831   2521   */
  2832   2522   static int afpClose(sqlite3_file *id) {
  2833   2523     int rc = SQLITE_OK;
  2834   2524     if( id ){
  2835   2525       unixFile *pFile = (unixFile*)id;
  2836   2526       afpUnlock(id, NO_LOCK);
  2837   2527       unixEnterMutex();
  2838         -    if( pFile->pOpen && pFile->pOpen->nLock ){
         2528  +    if( pFile->pInode && pFile->pInode->nLock ){
  2839   2529         /* If there are outstanding locks, do not actually close the file just
  2840   2530         ** yet because that would clear those locks.  Instead, add the file
  2841         -      ** descriptor to pOpen->aPending.  It will be automatically closed when
         2531  +      ** descriptor to pInode->aPending.  It will be automatically closed when
  2842   2532         ** the last lock is cleared.
  2843   2533         */
  2844   2534         setPendingFd(pFile);
  2845   2535       }
  2846         -    releaseLockInfo(pFile->pLock);
  2847         -    releaseOpenCnt(pFile->pOpen);
         2536  +    releaseLockInfo(pFile->pInode);
  2848   2537       sqlite3_free(pFile->lockingContext);
  2849   2538       rc = closeUnixFile(id);
  2850   2539       unixLeaveMutex();
  2851   2540     }
  2852   2541     return rc;
  2853   2542   }
  2854   2543   
................................................................................
  2863   2552   ******************************************************************************/
  2864   2553   
  2865   2554   /******************************************************************************
  2866   2555   *************************** Begin NFS Locking ********************************/
  2867   2556   
  2868   2557   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  2869   2558   /*
  2870         - ** Lower the locking level on file descriptor pFile to locktype.  locktype
         2559  + ** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  2871   2560    ** must be either NO_LOCK or SHARED_LOCK.
  2872   2561    **
  2873   2562    ** If the locking level of the file descriptor is already at or below
  2874   2563    ** the requested locking level, this routine is a no-op.
  2875   2564    */
  2876         -static int nfsUnlock(sqlite3_file *id, int locktype){
  2877         -  return _posixUnlock(id, locktype, 1);
         2565  +static int nfsUnlock(sqlite3_file *id, int eFileLock){
         2566  +  return _posixUnlock(id, eFileLock, 1);
  2878   2567   }
  2879   2568   
  2880   2569   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  2881   2570   /*
  2882   2571   ** The code above is the NFS lock implementation.  The code is specific
  2883   2572   ** to MacOSX and does not work on other unix platforms.  No alternative
  2884   2573   ** is available.  
................................................................................
  2934   2623     }
  2935   2624     got = read(id->h, pBuf, cnt);
  2936   2625   #endif
  2937   2626     TIMER_END;
  2938   2627     if( got<0 ){
  2939   2628       ((unixFile*)id)->lastErrno = errno;
  2940   2629     }
  2941         -  OSTRACE5("READ    %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
         2630  +  OSTRACE(("READ    %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
  2942   2631     return got;
  2943   2632   }
  2944   2633   
  2945   2634   /*
  2946   2635   ** Read data from a file into a buffer.  Return SQLITE_OK if all
  2947   2636   ** bytes were read successfully and SQLITE_IOERR if anything goes
  2948   2637   ** wrong.
................................................................................
  3010   2699     got = write(id->h, pBuf, cnt);
  3011   2700   #endif
  3012   2701     TIMER_END;
  3013   2702     if( got<0 ){
  3014   2703       ((unixFile*)id)->lastErrno = errno;
  3015   2704     }
  3016   2705   
  3017         -  OSTRACE5("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
         2706  +  OSTRACE(("WRITE   %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED));
  3018   2707     return got;
  3019   2708   }
  3020   2709   
  3021   2710   
  3022   2711   /*
  3023   2712   ** Write data from a buffer into a file.  Return SQLITE_OK on success
  3024   2713   ** or some other error code on failure.
................................................................................
  3236   2925   
  3237   2926     /* Unix cannot, but some systems may return SQLITE_FULL from here. This
  3238   2927     ** line is to test that doing so does not cause any problems.
  3239   2928     */
  3240   2929     SimulateDiskfullError( return SQLITE_FULL );
  3241   2930   
  3242   2931     assert( pFile );
  3243         -  OSTRACE2("SYNC    %-3d\n", pFile->h);
         2932  +  OSTRACE(("SYNC    %-3d\n", pFile->h));
  3244   2933     rc = full_fsync(pFile->h, isFullsync, isDataOnly);
  3245   2934     SimulateIOError( rc=1 );
  3246   2935     if( rc ){
  3247   2936       pFile->lastErrno = errno;
  3248   2937       return SQLITE_IOERR_FSYNC;
  3249   2938     }
  3250   2939     if( pFile->dirfd>=0 ){
  3251   2940       int err;
  3252         -    OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
  3253         -            HAVE_FULLFSYNC, isFullsync);
         2941  +    OSTRACE(("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
         2942  +            HAVE_FULLFSYNC, isFullsync));
  3254   2943   #ifndef SQLITE_DISABLE_DIRSYNC
  3255   2944       /* The directory sync is only attempted if full_fsync is
  3256   2945       ** turned off or unavailable.  If a full_fsync occurred above,
  3257   2946       ** then the directory sync is superfluous.
  3258   2947       */
  3259   2948       if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
  3260   2949          /*
................................................................................
  3318   3007     SimulateIOError( rc=1 );
  3319   3008     if( rc!=0 ){
  3320   3009       ((unixFile*)id)->lastErrno = errno;
  3321   3010       return SQLITE_IOERR_FSTAT;
  3322   3011     }
  3323   3012     *pSize = buf.st_size;
  3324   3013   
  3325         -  /* When opening a zero-size database, the findLockInfo() procedure
         3014  +  /* When opening a zero-size database, the findInodeInfo() procedure
  3326   3015     ** writes a single byte into that file in order to work around a bug
  3327   3016     ** in the OS-X msdos filesystem.  In order to avoid problems with upper
  3328   3017     ** layers, we need to report this file size as zero even though it is
  3329   3018     ** really 1.   Ticket #3260.
  3330   3019     */
  3331   3020     if( *pSize==1 ) *pSize = 0;
  3332   3021   
................................................................................
  3345   3034   
  3346   3035   /*
  3347   3036   ** Information and control of an open file handle.
  3348   3037   */
  3349   3038   static int unixFileControl(sqlite3_file *id, int op, void *pArg){
  3350   3039     switch( op ){
  3351   3040       case SQLITE_FCNTL_LOCKSTATE: {
  3352         -      *(int*)pArg = ((unixFile*)id)->locktype;
         3041  +      *(int*)pArg = ((unixFile*)id)->eFileLock;
  3353   3042         return SQLITE_OK;
  3354   3043       }
  3355   3044       case SQLITE_LAST_ERRNO: {
  3356   3045         *(int*)pArg = ((unixFile*)id)->lastErrno;
  3357   3046         return SQLITE_OK;
  3358   3047       }
  3359   3048   #ifndef NDEBUG
................................................................................
  3396   3085   ** Return the device characteristics for the file. This is always 0 for unix.
  3397   3086   */
  3398   3087   static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
  3399   3088     UNUSED_PARAMETER(NotUsed);
  3400   3089     return 0;
  3401   3090   }
  3402   3091   
         3092  +#ifndef SQLITE_OMIT_WAL
         3093  +
         3094  +
         3095  +/*
         3096  +** Object used to represent an shared memory buffer.  
         3097  +**
         3098  +** When multiple threads all reference the same wal-index, each thread
         3099  +** has its own unixShm object, but they all point to a single instance
         3100  +** of this unixShmNode object.  In other words, each wal-index is opened
         3101  +** only once per process.
         3102  +**
         3103  +** Each unixShmNode object is connected to a single unixInodeInfo object.
         3104  +** We could coalesce this object into unixInodeInfo, but that would mean
         3105  +** every open file that does not use shared memory (in other words, most
         3106  +** open files) would have to carry around this extra information.  So
         3107  +** the unixInodeInfo object contains a pointer to this unixShmNode object
         3108  +** and the unixShmNode object is created only when needed.
         3109  +**
         3110  +** unixMutexHeld() must be true when creating or destroying
         3111  +** this object or while reading or writing the following fields:
         3112  +**
         3113  +**      nRef
         3114  +**
         3115  +** The following fields are read-only after the object is created:
         3116  +** 
         3117  +**      fid
         3118  +**      zFilename
         3119  +**
         3120  +** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
         3121  +** unixMutexHeld() is true when reading or writing any other field
         3122  +** in this structure.
         3123  +**
         3124  +** To avoid deadlocks, mutex and mutexBuf are always released in the
         3125  +** reverse order that they are acquired.  mutexBuf is always acquired
         3126  +** first and released last.  This invariant is check by asserting
         3127  +** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
         3128  +** released.
         3129  +*/
         3130  +struct unixShmNode {
         3131  +  unixInodeInfo *pInode;     /* unixInodeInfo that owns this SHM node */
         3132  +  sqlite3_mutex *mutex;      /* Mutex to access this object */
         3133  +  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
         3134  +  char *zFilename;           /* Name of the mmapped file */
         3135  +  int h;                     /* Open file descriptor */
         3136  +  int szMap;                 /* Size of the mapping into memory */
         3137  +  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
         3138  +  int nRef;                  /* Number of unixShm objects pointing to this */
         3139  +  unixShm *pFirst;           /* All unixShm objects pointing to this */
         3140  +#ifdef SQLITE_DEBUG
         3141  +  u8 exclMask;               /* Mask of exclusive locks held */
         3142  +  u8 sharedMask;             /* Mask of shared locks held */
         3143  +  u8 nextShmId;              /* Next available unixShm.id value */
         3144  +#endif
         3145  +};
         3146  +
         3147  +/*
         3148  +** Structure used internally by this VFS to record the state of an
         3149  +** open shared memory connection.
         3150  +**
         3151  +** The following fields are initialized when this object is created and
         3152  +** are read-only thereafter:
         3153  +**
         3154  +**    unixShm.pFile
         3155  +**    unixShm.id
         3156  +**
         3157  +** All other fields are read/write.  The unixShm.pFile->mutex must be held
         3158  +** while accessing any read/write fields.
         3159  +*/
         3160  +struct unixShm {
         3161  +  unixShmNode *pShmNode;     /* The underlying unixShmNode object */
         3162  +  unixShm *pNext;            /* Next unixShm with the same unixShmNode */
         3163  +  u8 lockState;              /* Current lock state */
         3164  +  u8 hasMutex;               /* True if holding the unixShmNode mutex */
         3165  +  u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
         3166  +  u8 sharedMask;             /* Mask of shared locks held */
         3167  +  u8 exclMask;               /* Mask of exclusive locks held */
         3168  +#ifdef SQLITE_DEBUG
         3169  +  u8 id;                     /* Id of this connection within its unixShmNode */
         3170  +#endif
         3171  +};
         3172  +
         3173  +/*
         3174  +** Size increment by which shared memory grows
         3175  +*/
         3176  +#define SQLITE_UNIX_SHM_INCR  4096
         3177  +
         3178  +/*
         3179  +** Constants used for locking
         3180  +*/
         3181  +#define UNIX_SHM_BASE      32        /* Byte offset of the first lock byte */
         3182  +#define UNIX_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
         3183  +#define UNIX_SHM_A         0x10      /* Mask for region locks... */
         3184  +#define UNIX_SHM_B         0x20
         3185  +#define UNIX_SHM_C         0x40
         3186  +#define UNIX_SHM_D         0x80
         3187  +
         3188  +#ifdef SQLITE_DEBUG
         3189  +/*
         3190  +** Return a pointer to a nul-terminated string in static memory that
         3191  +** describes a locking mask.  The string is of the form "MSABCD" with
         3192  +** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
         3193  +** and "A" through "D" for the region locks.  If a lock is held, the
         3194  +** letter is shown.  If the lock is not held, the letter is converted
         3195  +** to ".".
         3196  +**
         3197  +** This routine is for debugging purposes only and does not appear
         3198  +** in a production build.
         3199  +*/
         3200  +static const char *unixShmLockString(u8 mask){
         3201  +  static char zBuf[48];
         3202  +  static int iBuf = 0;
         3203  +  char *z;
         3204  +
         3205  +  z = &zBuf[iBuf];
         3206  +  iBuf += 8;
         3207  +  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
         3208  +
         3209  +  z[0] = (mask & UNIX_SHM_DMS)   ? 'S' : '.';
         3210  +  z[1] = (mask & UNIX_SHM_A)     ? 'A' : '.';
         3211  +  z[2] = (mask & UNIX_SHM_B)     ? 'B' : '.';
         3212  +  z[3] = (mask & UNIX_SHM_C)     ? 'C' : '.';
         3213  +  z[4] = (mask & UNIX_SHM_D)     ? 'D' : '.';
         3214  +  z[5] = 0;
         3215  +  return z;
         3216  +}
         3217  +#endif /* SQLITE_DEBUG */
         3218  +
         3219  +/*
         3220  +** Apply posix advisory locks for all bytes identified in lockMask.
         3221  +**
         3222  +** lockMask might contain multiple bits but all bits are guaranteed
         3223  +** to be contiguous.
         3224  +**
         3225  +** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
         3226  +** otherwise.
         3227  +*/
         3228  +static int unixShmSystemLock(
         3229  +  unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
         3230  +  int lockType,          /* F_UNLCK, F_RDLCK, or F_WRLCK */
         3231  +  u8 lockMask            /* Which bytes to lock or unlock */
         3232  +){
         3233  +  struct flock f;       /* The posix advisory locking structure */
         3234  +  int lockOp;           /* The opcode for fcntl() */
         3235  +  int i;                /* Offset into the locking byte range */
         3236  +  int rc;               /* Result code form fcntl() */
         3237  +  u8 mask;              /* Mask of bits in lockMask */
         3238  +
         3239  +  /* Access to the unixShmNode object is serialized by the caller */
         3240  +  assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
         3241  +
         3242  +  /* Initialize the locking parameters */
         3243  +  memset(&f, 0, sizeof(f));
         3244  +  f.l_type = lockType;
         3245  +  f.l_whence = SEEK_SET;
         3246  +  if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){
         3247  +    lockOp = F_SETLKW;
         3248  +    OSTRACE(("SHM-LOCK requesting blocking lock\n"));
         3249  +  }else{
         3250  +    lockOp = F_SETLK;
         3251  +  }
         3252  +
         3253  +  /* Find the first bit in lockMask that is set */
         3254  +  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
         3255  +  assert( mask!=0 );
         3256  +  f.l_start = i+UNIX_SHM_BASE;
         3257  +  f.l_len = 1;
         3258  +
         3259  +  /* Extend the locking range for each additional bit that is set */
         3260  +  mask <<= 1;
         3261  +  while( mask!=0 && (lockMask & mask)!=0 ){
         3262  +    f.l_len++;
         3263  +    mask <<= 1;
         3264  +  }
         3265  +
         3266  +  /* Verify that all bits set in lockMask are contiguous */
         3267  +  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
         3268  +
         3269  +  /* Acquire the system-level lock */
         3270  +  rc = fcntl(pShmNode->h, lockOp, &f);
         3271  +  rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
         3272  +
         3273  +  /* Update the global lock state and do debug tracing */
         3274  +#ifdef SQLITE_DEBUG
         3275  +  OSTRACE(("SHM-LOCK "));
         3276  +  if( rc==SQLITE_OK ){
         3277  +    if( lockType==F_UNLCK ){
         3278  +      OSTRACE(("unlock ok"));
         3279  +      pShmNode->exclMask &= ~lockMask;
         3280  +      pShmNode->sharedMask &= ~lockMask;
         3281  +    }else if( lockType==F_RDLCK ){
         3282  +      OSTRACE(("read-lock ok"));
         3283  +      pShmNode->exclMask &= ~lockMask;
         3284  +      pShmNode->sharedMask |= lockMask;
         3285  +    }else{
         3286  +      assert( lockType==F_WRLCK );
         3287  +      OSTRACE(("write-lock ok"));
         3288  +      pShmNode->exclMask |= lockMask;
         3289  +      pShmNode->sharedMask &= ~lockMask;
         3290  +    }
         3291  +  }else{
         3292  +    if( lockType==F_UNLCK ){
         3293  +      OSTRACE(("unlock failed"));
         3294  +    }else if( lockType==F_RDLCK ){
         3295  +      OSTRACE(("read-lock failed"));
         3296  +    }else{
         3297  +      assert( lockType==F_WRLCK );
         3298  +      OSTRACE(("write-lock failed"));
         3299  +    }
         3300  +  }
         3301  +  OSTRACE((" - change requested %s - afterwards %s:%s\n",
         3302  +           unixShmLockString(lockMask),
         3303  +           unixShmLockString(pShmNode->sharedMask),
         3304  +           unixShmLockString(pShmNode->exclMask)));
         3305  +#endif
         3306  +
         3307  +  return rc;        
         3308  +}
         3309  +
         3310  +/*
         3311  +** For connection p, unlock all of the locks identified by the unlockMask
         3312  +** parameter.
         3313  +*/
         3314  +static int unixShmUnlock(
         3315  +  unixShmNode *pShmNode,   /* The underlying shared-memory file */
         3316  +  unixShm *p,              /* The connection to be unlocked */
         3317  +  u8 unlockMask            /* Mask of locks to be unlocked */
         3318  +){
         3319  +  int rc;      /* Result code */
         3320  +  unixShm *pX; /* For looping over all sibling connections */
         3321  +  u8 allMask;  /* Union of locks held by connections other than "p" */
         3322  +
         3323  +  /* Access to the unixShmNode object is serialized by the caller */
         3324  +  assert( sqlite3_mutex_held(pShmNode->mutex) );
         3325  +
         3326  +  /* Compute locks held by sibling connections */
         3327  +  allMask = 0;
         3328  +  for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
         3329  +    if( pX==p ) continue;
         3330  +    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
         3331  +    allMask |= pX->sharedMask;
         3332  +  }
         3333  +
         3334  +  /* Unlock the system-level locks */
         3335  +  if( (unlockMask & allMask)!=unlockMask ){
         3336  +    rc = unixShmSystemLock(pShmNode, F_UNLCK, unlockMask & ~allMask);
         3337  +  }else{
         3338  +    rc = SQLITE_OK;
         3339  +  }
         3340  +
         3341  +  /* Undo the local locks */
         3342  +  if( rc==SQLITE_OK ){
         3343  +    p->exclMask &= ~unlockMask;
         3344  +    p->sharedMask &= ~unlockMask;
         3345  +  } 
         3346  +  return rc;
         3347  +}
         3348  +
         3349  +/*
         3350  +** Get reader locks for connection p on all locks in the readMask parameter.
         3351  +*/
         3352  +static int unixShmSharedLock(
         3353  +  unixShmNode *pShmNode,   /* The underlying shared-memory file */
         3354  +  unixShm *p,              /* The connection to get the shared locks */
         3355  +  u8 readMask              /* Mask of shared locks to be acquired */
         3356  +){
         3357  +  int rc;        /* Result code */
         3358  +  unixShm *pX;   /* For looping over all sibling connections */
         3359  +  u8 allShared;  /* Union of locks held by connections other than "p" */
         3360  +
         3361  +  /* Access to the unixShmNode object is serialized by the caller */
         3362  +  assert( sqlite3_mutex_held(pShmNode->mutex) );
         3363  +
         3364  +  /* Find out which shared locks are already held by sibling connections.
         3365  +  ** If any sibling already holds an exclusive lock, go ahead and return
         3366  +  ** SQLITE_BUSY.
         3367  +  */
         3368  +  allShared = 0;
         3369  +  for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
         3370  +    if( pX==p ) continue;
         3371  +    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
         3372  +    allShared |= pX->sharedMask;
         3373  +  }
         3374  +
         3375  +  /* Get shared locks at the system level, if necessary */
         3376  +  if( (~allShared) & readMask ){
         3377  +    rc = unixShmSystemLock(pShmNode, F_RDLCK, readMask);
         3378  +  }else{
         3379  +    rc = SQLITE_OK;
         3380  +  }
         3381  +
         3382  +  /* Get the local shared locks */
         3383  +  if( rc==SQLITE_OK ){
         3384  +    p->sharedMask |= readMask;
         3385  +  }
         3386  +  return rc;
         3387  +}
         3388  +
         3389  +/*
         3390  +** For connection p, get an exclusive lock on all locks identified in
         3391  +** the writeMask parameter.
         3392  +*/
         3393  +static int unixShmExclusiveLock(
         3394  +  unixShmNode *pShmNode,    /* The underlying shared-memory file */
         3395  +  unixShm *p,               /* The connection to get the exclusive locks */
         3396  +  u8 writeMask              /* Mask of exclusive locks to be acquired */
         3397  +){
         3398  +  int rc;        /* Result code */
         3399  +  unixShm *pX;   /* For looping over all sibling connections */
         3400  +
         3401  +  /* Access to the unixShmNode object is serialized by the caller */
         3402  +  assert( sqlite3_mutex_held(pShmNode->mutex) );
         3403  +
         3404  +  /* Make sure no sibling connections hold locks that will block this
         3405  +  ** lock.  If any do, return SQLITE_BUSY right away.
         3406  +  */
         3407  +  for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
         3408  +    if( pX==p ) continue;
         3409  +    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
         3410  +    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
         3411  +  }
         3412  +
         3413  +  /* Get the exclusive locks at the system level.  Then if successful
         3414  +  ** also mark the local connection as being locked.
         3415  +  */
         3416  +  rc = unixShmSystemLock(pShmNode, F_WRLCK, writeMask);
         3417  +  if( rc==SQLITE_OK ){
         3418  +    p->sharedMask &= ~writeMask;
         3419  +    p->exclMask |= writeMask;
         3420  +  }
         3421  +  return rc;
         3422  +}
         3423  +
         3424  +/*
         3425  +** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
         3426  +**
         3427  +** This is not a VFS shared-memory method; it is a utility function called
         3428  +** by VFS shared-memory methods.
         3429  +*/
         3430  +static void unixShmPurge(unixFile *pFd){
         3431  +  unixShmNode *p = pFd->pInode->pShmNode;
         3432  +  assert( unixMutexHeld() );
         3433  +  if( p && p->nRef==0 ){
         3434  +    assert( p->pInode==pFd->pInode );
         3435  +    if( p->mutex ) sqlite3_mutex_free(p->mutex);
         3436  +    if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
         3437  +    if( p->h>=0 ) close(p->h);
         3438  +    p->pInode->pShmNode = 0;
         3439  +    sqlite3_free(p);
         3440  +  }
         3441  +}
         3442  +
         3443  +/*
         3444  +** Open a shared-memory area.  This particular implementation uses
         3445  +** mmapped files.
         3446  +**
         3447  +** zName is a filename used to identify the shared-memory area.  The
         3448  +** implementation does not (and perhaps should not) use this name
         3449  +** directly, but rather use it as a template for finding an appropriate
         3450  +** name for the shared-memory storage.  In this implementation, the
         3451  +** string "-index" is appended to zName and used as the name of the
         3452  +** mmapped file.
         3453  +**
         3454  +** When opening a new shared-memory file, if no other instances of that
         3455  +** file are currently open, in this process or in other processes, then
         3456  +** the file must be truncated to zero length or have its header cleared.
         3457  +*/
         3458  +static int unixShmOpen(
         3459  +  sqlite3_file *fd      /* The file descriptor of the associated database */
         3460  +){
         3461  +  struct unixShm *p = 0;             /* The connection to be opened */
         3462  +  struct unixShmNode *pShmNode = 0;  /* The underlying mmapped file */
         3463  +  int rc;                            /* Result code */
         3464  +  struct unixFile *pDbFd;            /* Underlying database file */
         3465  +  int nPath;                         /* Size of pDbFd->zPath in bytes */
         3466  +
         3467  +  /* Allocate space for the new sqlite3_shm object.
         3468  +  */
         3469  +  p = sqlite3_malloc( sizeof(*p) );
         3470  +  if( p==0 ) return SQLITE_NOMEM;
         3471  +  memset(p, 0, sizeof(*p));
         3472  +  pDbFd = (struct unixFile*)fd;
         3473  +  assert( pDbFd->pShm==0 );
         3474  +
         3475  +  /* Check to see if a unixShmNode object already exists.  Reuse an existing
         3476  +  ** one if present.  Create a new one if necessary.
         3477  +  */
         3478  +  unixEnterMutex();
         3479  +  pShmNode = pDbFd->pInode->pShmNode;
         3480  +  if( pShmNode==0 ){
         3481  +    nPath = strlen(pDbFd->zPath);
         3482  +    pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nPath + 15 );
         3483  +    if( pShmNode==0 ){
         3484  +      rc = SQLITE_NOMEM;
         3485  +      goto shm_open_err;
         3486  +    }
         3487  +    memset(pShmNode, 0, sizeof(*pShmNode));
         3488  +    pShmNode->zFilename = (char*)&pShmNode[1];
         3489  +    sqlite3_snprintf(nPath+15, pShmNode->zFilename,
         3490  +                     "%s-wal-index", pDbFd->zPath);
         3491  +    pShmNode->h = -1;
         3492  +    pDbFd->pInode->pShmNode = pShmNode;
         3493  +    pShmNode->pInode = pDbFd->pInode;
         3494  +    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
         3495  +    if( pShmNode->mutex==0 ){
         3496  +      rc = SQLITE_NOMEM;
         3497  +      goto shm_open_err;
         3498  +    }
         3499  +    pShmNode->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
         3500  +    if( pShmNode->mutexBuf==0 ){
         3501  +      rc = SQLITE_NOMEM;
         3502  +      goto shm_open_err;
         3503  +    }
         3504  +
         3505  +    pShmNode->h = open(pShmNode->zFilename, O_RDWR|O_CREAT, 0664);
         3506  +    if( pShmNode->h<0 ){
         3507  +      rc = SQLITE_CANTOPEN_BKPT;
         3508  +      goto shm_open_err;
         3509  +    }
         3510  +
         3511  +    /* Check to see if another process is holding the dead-man switch.
         3512  +    ** If not, truncate the file to zero length. 
         3513  +    */
         3514  +    rc = SQLITE_OK;
         3515  +    if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
         3516  +      if( ftruncate(pShmNode->h, 0) ){
         3517  +        rc = SQLITE_IOERR;
         3518  +      }
         3519  +    }
         3520  +    if( rc==SQLITE_OK ){
         3521  +      rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS);
         3522  +    }
         3523  +    if( rc ) goto shm_open_err;
         3524  +  }
         3525  +
         3526  +  /* Make the new connection a child of the unixShmNode */
         3527  +  p->pShmNode = pShmNode;
         3528  +  p->pNext = pShmNode->pFirst;
         3529  +#ifdef SQLITE_DEBUG
         3530  +  p->id = pShmNode->nextShmId++;
         3531  +#endif
         3532  +  pShmNode->pFirst = p;
         3533  +  pShmNode->nRef++;
         3534  +  pDbFd->pShm = p;
         3535  +  unixLeaveMutex();
         3536  +  return SQLITE_OK;
         3537  +
         3538  +  /* Jump here on any error */
         3539  +shm_open_err:
         3540  +  unixShmPurge(pDbFd);       /* This call frees pShmNode if required */
         3541  +  sqlite3_free(p);
         3542  +  unixLeaveMutex();
         3543  +  return rc;
         3544  +}
         3545  +
         3546  +/*
         3547  +** Close a connection to shared-memory.  Delete the underlying 
         3548  +** storage if deleteFlag is true.
         3549  +*/
         3550  +static int unixShmClose(
         3551  +  sqlite3_file *fd,          /* The underlying database file */
         3552  +  int deleteFlag             /* Delete shared-memory if true */
         3553  +){
         3554  +  unixShm *p;            /* The connection to be closed */
         3555  +  unixShmNode *pShmNode; /* The underlying shared-memory file */
         3556  +  unixShm **pp;          /* For looping over sibling connections */
         3557  +  unixFile *pDbFd;       /* The underlying database file */
         3558  +
         3559  +  pDbFd = (unixFile*)fd;
         3560  +  p = pDbFd->pShm;
         3561  +  if( p==0 ) return SQLITE_OK;
         3562  +  pShmNode = p->pShmNode;
         3563  +
         3564  +  assert( pShmNode==pDbFd->pInode->pShmNode );
         3565  +  assert( pShmNode->pInode==pDbFd->pInode );
         3566  +
         3567  +  /* Verify that the connection being closed holds no locks */
         3568  +  assert( p->exclMask==0 );
         3569  +  assert( p->sharedMask==0 );
         3570  +
         3571  +  /* Remove connection p from the set of connections associated
         3572  +  ** with pShmNode */
         3573  +  sqlite3_mutex_enter(pShmNode->mutex);
         3574  +  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
         3575  +  *pp = p->pNext;
         3576  +
         3577  +  /* Free the connection p */
         3578  +  sqlite3_free(p);
         3579  +  pDbFd->pShm = 0;
         3580  +  sqlite3_mutex_leave(pShmNode->mutex);
         3581  +
         3582  +  /* If pShmNode->nRef has reached 0, then close the underlying
         3583  +  ** shared-memory file, too */
         3584  +  unixEnterMutex();
         3585  +  assert( pShmNode->nRef>0 );
         3586  +  pShmNode->nRef--;
         3587  +  if( pShmNode->nRef==0 ){
         3588  +    if( deleteFlag ) unlink(pShmNode->zFilename);
         3589  +    unixShmPurge(pDbFd);
         3590  +  }
         3591  +  unixLeaveMutex();
         3592  +
         3593  +  return SQLITE_OK;
         3594  +}
         3595  +
         3596  +/*
         3597  +** Query and/or changes the size of the underlying storage for
         3598  +** a shared-memory segment.  The reqSize parameter is the new size
         3599  +** of the underlying storage, or -1 to do just a query.  The size
         3600  +** of the underlying storage (after resizing if resizing occurs) is
         3601  +** written into pNewSize.
         3602  +**
         3603  +** This routine does not (necessarily) change the size of the mapping 
         3604  +** of the underlying storage into memory.  Use xShmGet() to change
         3605  +** the mapping size.
         3606  +**
         3607  +** The reqSize parameter is the minimum size requested.  The implementation
         3608  +** is free to expand the storage to some larger amount if it chooses.
         3609  +*/
         3610  +static int unixShmSize(
         3611  +  sqlite3_file *fd,         /* The open database file holding SHM */
         3612  +  int reqSize,              /* Requested size.  -1 for query only */
         3613  +  int *pNewSize             /* Write new size here */
         3614  +){
         3615  +  unixFile *pDbFd = (unixFile*)fd;
         3616  +  unixShm *p = pDbFd->pShm;
         3617  +  unixShmNode *pShmNode = p->pShmNode;
         3618  +  int rc = SQLITE_OK;
         3619  +  struct stat sStat;
         3620  +
         3621  +  assert( pShmNode==pDbFd->pInode->pShmNode );
         3622  +  assert( pShmNode->pInode==pDbFd->pInode );
         3623  +
         3624  +  /* On a query, this loop runs once.  When reqSize>=0, the loop potentially
         3625  +  ** runs twice, except if the actual size is already greater than or equal
         3626  +  ** to the requested size, reqSize is set to -1 on the first iteration and
         3627  +  ** the loop only runs once.
         3628  +  */
         3629  +  while( 1 ){
         3630  +    if( fstat(pShmNode->h, &sStat)==0 ){
         3631  +      *pNewSize = (int)sStat.st_size;
         3632  +      if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break;
         3633  +    }else{
         3634  +      *pNewSize = 0;
         3635  +      rc = SQLITE_IOERR;
         3636  +      break;
         3637  +    }
         3638  +    if( reqSize<0 ) break;
         3639  +    reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
         3640  +    reqSize *= SQLITE_UNIX_SHM_INCR;
         3641  +    rc = ftruncate(pShmNode->h, reqSize);
         3642  +    reqSize = -1;
         3643  +  }
         3644  +  return rc;
         3645  +}
         3646  +
         3647  +
         3648  +/*
         3649  +** Map the shared storage into memory.  The minimum size of the
         3650  +** mapping should be reqMapSize if reqMapSize is positive.  If
         3651  +** reqMapSize is zero or negative, the implementation can choose
         3652  +** whatever mapping size is convenient.
         3653  +**
         3654  +** *ppBuf is made to point to the memory which is a mapping of the
         3655  +** underlying storage.  A mutex is acquired to prevent other threads
         3656  +** from running while *ppBuf is in use in order to prevent other threads
         3657  +** remapping *ppBuf out from under this thread.  The unixShmRelease()
         3658  +** call will release the mutex.  However, if the lock state is CHECKPOINT,
         3659  +** the mutex is not acquired because CHECKPOINT will never remap the
         3660  +** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
         3661  +** the mutex if and when it promotes to RECOVER.
         3662  +**
         3663  +** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
         3664  +** being remapped also prevents more than one thread from being in
         3665  +** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
         3666  +** To prevent RECOVER from losing its lock while remapping, the
         3667  +** mutex is not released by unixShmRelease() when in RECOVER.
         3668  +**
         3669  +** *pNewMapSize is set to the size of the mapping.
         3670  +**
         3671  +** *ppBuf and *pNewMapSize might be NULL and zero if no space has
         3672  +** yet been allocated to the underlying storage.
         3673  +*/
         3674  +static int unixShmGet(
         3675  +  sqlite3_file *fd,        /* Database file holding shared memory */
         3676  +  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
         3677  +  int *pNewMapSize,        /* Write new size of mapping here */
         3678  +  void **ppBuf             /* Write mapping buffer origin here */
         3679  +){
         3680  +  unixFile *pDbFd = (unixFile*)fd;
         3681  +  unixShm *p = pDbFd->pShm;
         3682  +  unixShmNode *pShmNode = p->pShmNode;
         3683  +  int rc = SQLITE_OK;
         3684  +
         3685  +  assert( pShmNode==pDbFd->pInode->pShmNode );
         3686  +  assert( pShmNode->pInode==pDbFd->pInode );
         3687  +
         3688  +  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
         3689  +    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
         3690  +    sqlite3_mutex_enter(pShmNode->mutexBuf);
         3691  +    p->hasMutexBuf = 1;
         3692  +  }
         3693  +  sqlite3_mutex_enter(pShmNode->mutex);
         3694  +  if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
         3695  +    int actualSize;
         3696  +    if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK
         3697  +     && reqMapSize<actualSize
         3698  +    ){
         3699  +      reqMapSize = actualSize;
         3700  +    }
         3701  +    if( pShmNode->pMMapBuf ){
         3702  +      munmap(pShmNode->pMMapBuf, pShmNode->szMap);
         3703  +    }
         3704  +    pShmNode->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
         3705  +                           pShmNode->h, 0);
         3706  +    pShmNode->szMap = pShmNode->pMMapBuf ? reqMapSize : 0;
         3707  +  }
         3708  +  *pNewMapSize = pShmNode->szMap;
         3709  +  *ppBuf = pShmNode->pMMapBuf;
         3710  +  sqlite3_mutex_leave(pShmNode->mutex);
         3711  +  return rc;
         3712  +}
         3713  +
         3714  +/*
         3715  +** Release the lock held on the shared memory segment to that other
         3716  +** threads are free to resize it if necessary.
         3717  +**
         3718  +** If the lock is not currently held, this routine is a harmless no-op.
         3719  +**
         3720  +** If the shared-memory object is in lock state RECOVER, then we do not
         3721  +** really want to release the lock, so in that case too, this routine
         3722  +** is a no-op.
         3723  +*/
         3724  +static int unixShmRelease(sqlite3_file *fd){
         3725  +  unixFile *pDbFd = (unixFile*)fd;
         3726  +  unixShm *p = pDbFd->pShm;
         3727  +
         3728  +  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
         3729  +    assert( sqlite3_mutex_notheld(p->pShmNode->mutex) );
         3730  +    sqlite3_mutex_leave(p->pShmNode->mutexBuf);
         3731  +    p->hasMutexBuf = 0;
         3732  +  }
         3733  +  return SQLITE_OK;
         3734  +}
         3735  +
         3736  +/*
         3737  +** Symbolic names for LOCK states used for debugging.
         3738  +*/
         3739  +#ifdef SQLITE_DEBUG
         3740  +static const char *azLkName[] = {
         3741  +  "UNLOCK",
         3742  +  "READ",
         3743  +  "READ_FULL",
         3744  +  "WRITE",
         3745  +  "PENDING",
         3746  +  "CHECKPOINT",
         3747  +  "RECOVER"
         3748  +};
         3749  +#endif
         3750  +
         3751  +
         3752  +/*
         3753  +** Change the lock state for a shared-memory segment.
         3754  +*/
         3755  +static int unixShmLock(
         3756  +  sqlite3_file *fd,          /* Database file holding the shared memory */
         3757  +  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
         3758  +  int *pGotLock              /* The lock you actually got */
         3759  +){
         3760  +  unixFile *pDbFd = (unixFile*)fd;
         3761  +  unixShm *p = pDbFd->pShm;
         3762  +  unixShmNode *pShmNode = p->pShmNode;
         3763  +  int rc = SQLITE_PROTOCOL;
         3764  +
         3765  +  assert( pShmNode==pDbFd->pInode->pShmNode );
         3766  +  assert( pShmNode->pInode==pDbFd->pInode );
         3767  +
         3768  +  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
         3769  +  ** directly requested; they are side effects from requesting
         3770  +  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
         3771  +  */
         3772  +  assert( desiredLock==SQLITE_SHM_UNLOCK
         3773  +       || desiredLock==SQLITE_SHM_READ
         3774  +       || desiredLock==SQLITE_SHM_WRITE
         3775  +       || desiredLock==SQLITE_SHM_CHECKPOINT
         3776  +       || desiredLock==SQLITE_SHM_RECOVER );
         3777  +
         3778  +  /* Return directly if this is just a lock state query, or if
         3779  +  ** the connection is already in the desired locking state.
         3780  +  */
         3781  +  if( desiredLock==p->lockState
         3782  +   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
         3783  +  ){
         3784  +    OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n",
         3785  +             p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState]));
         3786  +    if( pGotLock ) *pGotLock = p->lockState;
         3787  +    return SQLITE_OK;
         3788  +  }
         3789  +
         3790  +  OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
         3791  +            p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
         3792  +  
         3793  +  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
         3794  +    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
         3795  +    sqlite3_mutex_enter(pShmNode->mutexBuf);
         3796  +    p->hasMutexBuf = 1;
         3797  +  }
         3798  +  sqlite3_mutex_enter(pShmNode->mutex);
         3799  +  switch( desiredLock ){
         3800  +    case SQLITE_SHM_UNLOCK: {
         3801  +      assert( p->lockState!=SQLITE_SHM_RECOVER );
         3802  +      unixShmUnlock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
         3803  +      rc = SQLITE_OK;
         3804  +      p->lockState = SQLITE_SHM_UNLOCK;
         3805  +      break;
         3806  +    }
         3807  +    case SQLITE_SHM_READ: {
         3808  +      if( p->lockState==SQLITE_SHM_UNLOCK ){
         3809  +        int nAttempt;
         3810  +        rc = SQLITE_BUSY;
         3811  +        assert( p->lockState==SQLITE_SHM_UNLOCK );
         3812  +        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
         3813  +          rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A|UNIX_SHM_B);
         3814  +          if( rc==SQLITE_BUSY ){
         3815  +            rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_D);
         3816  +            if( rc==SQLITE_OK ){
         3817  +              p->lockState = SQLITE_SHM_READ_FULL;
         3818  +            }
         3819  +          }else{
         3820  +            unixShmUnlock(pShmNode, p, UNIX_SHM_B);
         3821  +            p->lockState = SQLITE_SHM_READ;
         3822  +          }
         3823  +        }
         3824  +      }else{
         3825  +       assert( p->lockState==SQLITE_SHM_WRITE
         3826  +               || p->lockState==SQLITE_SHM_RECOVER );
         3827  +        rc = unixShmSharedLock(pShmNode, p, UNIX_SHM_A);
         3828  +        unixShmUnlock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
         3829  +        p->lockState = SQLITE_SHM_READ;
         3830  +      }
         3831  +      break;
         3832  +    }
         3833  +    case SQLITE_SHM_WRITE: {
         3834  +      assert( p->lockState==SQLITE_SHM_READ 
         3835  +              || p->lockState==SQLITE_SHM_READ_FULL );
         3836  +      rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C|UNIX_SHM_D);
         3837  +      if( rc==SQLITE_OK ){
         3838  +        p->lockState = SQLITE_SHM_WRITE;
         3839  +      }
         3840  +      break;
         3841  +    }
         3842  +    case SQLITE_SHM_CHECKPOINT: {
         3843  +      assert( p->lockState==SQLITE_SHM_UNLOCK
         3844  +           || p->lockState==SQLITE_SHM_PENDING
         3845  +      );
         3846  +      if( p->lockState==SQLITE_SHM_UNLOCK ){
         3847  +        rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_B|UNIX_SHM_C);
         3848  +        if( rc==SQLITE_OK ){
         3849  +          p->lockState = SQLITE_SHM_PENDING;
         3850  +        }
         3851  +      }
         3852  +      if( p->lockState==SQLITE_SHM_PENDING ){
         3853  +        rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_A);
         3854  +        if( rc==SQLITE_OK ){
         3855  +          p->lockState = SQLITE_SHM_CHECKPOINT;
         3856  +        }
         3857  +      }
         3858  +      break;
         3859  +    }
         3860  +    default: {
         3861  +      assert( desiredLock==SQLITE_SHM_RECOVER );
         3862  +      assert( p->lockState==SQLITE_SHM_READ
         3863  +           || p->lockState==SQLITE_SHM_READ_FULL
         3864  +      );
         3865  +      assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
         3866  +      rc = unixShmExclusiveLock(pShmNode, p, UNIX_SHM_C);
         3867  +      if( rc==SQLITE_OK ){
         3868  +        p->lockState = SQLITE_SHM_RECOVER;
         3869  +      }
         3870  +      break;
         3871  +    }
         3872  +  }
         3873  +  sqlite3_mutex_leave(pShmNode->mutex);
         3874  +  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
         3875  +           p->id, getpid(), azLkName[p->lockState]));
         3876  +  if( pGotLock ) *pGotLock = p->lockState;
         3877  +  return rc;
         3878  +}
         3879  +
         3880  +#else
         3881  +# define unixShmOpen    0
         3882  +# define unixShmSize    0
         3883  +# define unixShmGet     0
         3884  +# define unixShmRelease 0
         3885  +# define unixShmLock    0
         3886  +# define unixShmClose   0
         3887  +#endif /* #ifndef SQLITE_OMIT_WAL */
         3888  +
  3403   3889   /*
  3404   3890   ** Here ends the implementation of all sqlite3_file methods.
  3405   3891   **
  3406   3892   ********************** End sqlite3_file Methods *******************************
  3407   3893   ******************************************************************************/
  3408   3894   
  3409   3895   /*
................................................................................
  3436   3922   **
  3437   3923   **   *  A constant sqlite3_io_methods object call METHOD that has locking
  3438   3924   **      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
  3439   3925   **
  3440   3926   **   *  An I/O method finder function called FINDER that returns a pointer
  3441   3927   **      to the METHOD object in the previous bullet.
  3442   3928   */
  3443         -#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK)               \
         3929  +#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK)      \
  3444   3930   static const sqlite3_io_methods METHOD = {                                   \
  3445         -   1,                          /* iVersion */                                \
         3931  +   VERSION,                    /* iVersion */                                \
  3446   3932      CLOSE,                      /* xClose */                                  \
  3447   3933      unixRead,                   /* xRead */                                   \
  3448   3934      unixWrite,                  /* xWrite */                                  \
  3449   3935      unixTruncate,               /* xTruncate */                               \
  3450   3936      unixSync,                   /* xSync */                                   \
  3451   3937      unixFileSize,               /* xFileSize */                               \
  3452   3938      LOCK,                       /* xLock */                                   \
  3453   3939      UNLOCK,                     /* xUnlock */                                 \
  3454   3940      CKLOCK,                     /* xCheckReservedLock */                      \
  3455   3941      unixFileControl,            /* xFileControl */                            \
  3456   3942      unixSectorSize,             /* xSectorSize */                             \
  3457         -   unixDeviceCharacteristics   /* xDeviceCapabilities */                     \
         3943  +   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
         3944  +   unixShmOpen,                /* xShmOpen */                                \
         3945  +   unixShmSize,                /* xShmSize */                                \
         3946  +   unixShmGet,                 /* xShmGet */                                 \
         3947  +   unixShmRelease,             /* xShmRelease */                             \
         3948  +   unixShmLock,                /* xShmLock */                                \
         3949  +   unixShmClose                /* xShmClose */                               \
  3458   3950   };                                                                           \
  3459   3951   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  3460   3952     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  3461   3953     return &METHOD;                                                            \
  3462   3954   }                                                                            \
  3463   3955   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  3464   3956       = FINDER##Impl;
................................................................................
  3467   3959   ** Here are all of the sqlite3_io_methods objects for each of the
  3468   3960   ** locking strategies.  Functions that return pointers to these methods
  3469   3961   ** are also created.
  3470   3962   */
  3471   3963   IOMETHODS(
  3472   3964     posixIoFinder,            /* Finder function name */
  3473   3965     posixIoMethods,           /* sqlite3_io_methods object name */
         3966  +  2,                        /* ShmOpen is enabled */
  3474   3967     unixClose,                /* xClose method */
  3475   3968     unixLock,                 /* xLock method */
  3476   3969     unixUnlock,               /* xUnlock method */
  3477   3970     unixCheckReservedLock     /* xCheckReservedLock method */
  3478   3971   )
  3479   3972   IOMETHODS(
  3480   3973     nolockIoFinder,           /* Finder function name */
  3481   3974     nolockIoMethods,          /* sqlite3_io_methods object name */
         3975  +  1,                        /* ShmOpen is disabled */
  3482   3976     nolockClose,              /* xClose method */
  3483   3977     nolockLock,               /* xLock method */
  3484   3978     nolockUnlock,             /* xUnlock method */
  3485   3979     nolockCheckReservedLock   /* xCheckReservedLock method */
  3486   3980   )
  3487   3981   IOMETHODS(
  3488   3982     dotlockIoFinder,          /* Finder function name */
  3489   3983     dotlockIoMethods,         /* sqlite3_io_methods object name */
         3984  +  1,                        /* ShmOpen is disabled */
  3490   3985     dotlockClose,             /* xClose method */
  3491   3986     dotlockLock,              /* xLock method */
  3492   3987     dotlockUnlock,            /* xUnlock method */
  3493   3988     dotlockCheckReservedLock  /* xCheckReservedLock method */
  3494   3989   )
  3495   3990   
  3496   3991   #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
  3497   3992   IOMETHODS(
  3498   3993     flockIoFinder,            /* Finder function name */
  3499   3994     flockIoMethods,           /* sqlite3_io_methods object name */
         3995  +  1,                        /* ShmOpen is disabled */
  3500   3996     flockClose,               /* xClose method */
  3501   3997     flockLock,                /* xLock method */
  3502   3998     flockUnlock,              /* xUnlock method */
  3503   3999     flockCheckReservedLock    /* xCheckReservedLock method */
  3504   4000   )
  3505   4001   #endif
  3506   4002   
  3507   4003   #if OS_VXWORKS
  3508   4004   IOMETHODS(
  3509   4005     semIoFinder,              /* Finder function name */
  3510   4006     semIoMethods,             /* sqlite3_io_methods object name */
         4007  +  1,                        /* ShmOpen is disabled */
  3511   4008     semClose,                 /* xClose method */
  3512   4009     semLock,                  /* xLock method */
  3513   4010     semUnlock,                /* xUnlock method */
  3514   4011     semCheckReservedLock      /* xCheckReservedLock method */
  3515   4012   )
  3516   4013   #endif
  3517   4014   
  3518   4015   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  3519   4016   IOMETHODS(
  3520   4017     afpIoFinder,              /* Finder function name */
  3521   4018     afpIoMethods,             /* sqlite3_io_methods object name */
         4019  +  1,                        /* ShmOpen is disabled */
  3522   4020     afpClose,                 /* xClose method */
  3523   4021     afpLock,                  /* xLock method */
  3524   4022     afpUnlock,                /* xUnlock method */
  3525   4023     afpCheckReservedLock      /* xCheckReservedLock method */
  3526   4024   )
  3527   4025   #endif
  3528   4026   
................................................................................
  3539   4037   static int proxyClose(sqlite3_file*);
  3540   4038   static int proxyLock(sqlite3_file*, int);
  3541   4039   static int proxyUnlock(sqlite3_file*, int);
  3542   4040   static int proxyCheckReservedLock(sqlite3_file*, int*);
  3543   4041   IOMETHODS(
  3544   4042     proxyIoFinder,            /* Finder function name */
  3545   4043     proxyIoMethods,           /* sqlite3_io_methods object name */
         4044  +  1,                        /* ShmOpen is disabled */
  3546   4045     proxyClose,               /* xClose method */
  3547   4046     proxyLock,                /* xLock method */
  3548   4047     proxyUnlock,              /* xUnlock method */
  3549   4048     proxyCheckReservedLock    /* xCheckReservedLock method */
  3550   4049   )
  3551   4050   #endif
  3552   4051   
  3553   4052   /* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
  3554   4053   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  3555   4054   IOMETHODS(
  3556   4055     nfsIoFinder,               /* Finder function name */
  3557   4056     nfsIoMethods,              /* sqlite3_io_methods object name */
         4057  +  1,                         /* ShmOpen is disabled */
  3558   4058     unixClose,                 /* xClose method */
  3559   4059     unixLock,                  /* xLock method */
  3560   4060     nfsUnlock,                 /* xUnlock method */
  3561   4061     unixCheckReservedLock      /* xCheckReservedLock method */
  3562   4062   )
  3563   4063   #endif
  3564   4064   
................................................................................
  3691   4191     int noLock,             /* Omit locking if true */
  3692   4192     int isDelete            /* Delete on close if true */
  3693   4193   ){
  3694   4194     const sqlite3_io_methods *pLockingStyle;
  3695   4195     unixFile *pNew = (unixFile *)pId;
  3696   4196     int rc = SQLITE_OK;
  3697   4197   
  3698         -  assert( pNew->pLock==NULL );
  3699         -  assert( pNew->pOpen==NULL );
         4198  +  assert( pNew->pInode==NULL );
  3700   4199   
  3701   4200     /* Parameter isDelete is only used on vxworks. Express this explicitly 
  3702   4201     ** here to prevent compiler warnings about unused parameters.
  3703   4202     */
  3704   4203     UNUSED_PARAMETER(isDelete);
  3705   4204   
  3706         -  OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
         4205  +  OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  3707   4206     pNew->h = h;
  3708   4207     pNew->dirfd = dirfd;
  3709         -  SET_THREADID(pNew);
  3710   4208     pNew->fileFlags = 0;
         4209  +  assert( zFilename==0 || zFilename[0]=='/' );  /* Never a relative pathname */
         4210  +  pNew->zPath = zFilename;
  3711   4211   
  3712   4212   #if OS_VXWORKS
  3713   4213     pNew->pId = vxworksFindFileId(zFilename);
  3714   4214     if( pNew->pId==0 ){
  3715   4215       noLock = 1;
  3716   4216       rc = SQLITE_NOMEM;
  3717   4217     }
................................................................................
  3731   4231   
  3732   4232     if( pLockingStyle == &posixIoMethods
  3733   4233   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  3734   4234       || pLockingStyle == &nfsIoMethods
  3735   4235   #endif
  3736   4236     ){
  3737   4237       unixEnterMutex();
  3738         -    rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
         4238  +    rc = findInodeInfo(pNew, &pNew->pInode);
  3739   4239       if( rc!=SQLITE_OK ){
  3740         -      /* If an error occured in findLockInfo(), close the file descriptor
  3741         -      ** immediately, before releasing the mutex. findLockInfo() may fail
         4240  +      /* If an error occured in findInodeInfo(), close the file descriptor
         4241  +      ** immediately, before releasing the mutex. findInodeInfo() may fail
  3742   4242         ** in two scenarios:
  3743   4243         **
  3744   4244         **   (a) A call to fstat() failed.
  3745   4245         **   (b) A malloc failed.
  3746   4246         **
  3747   4247         ** Scenario (b) may only occur if the process is holding no other
  3748   4248         ** file descriptors open on the same file. If there were other file
  3749   4249         ** descriptors on this file, then no malloc would be required by
  3750         -      ** findLockInfo(). If this is the case, it is quite safe to close
         4250  +      ** findInodeInfo(). If this is the case, it is quite safe to close
  3751   4251         ** handle h - as it is guaranteed that no posix locks will be released
  3752   4252         ** by doing so.
  3753   4253         **
  3754   4254         ** If scenario (a) caused the error then things are not so safe. The
  3755   4255         ** implicit assumption here is that if fstat() fails, things are in
  3756   4256         ** such bad shape that dropping a lock or two doesn't matter much.
  3757   4257         */
................................................................................
  3774   4274         /* NB: zFilename exists and remains valid until the file is closed
  3775   4275         ** according to requirement F11141.  So we do not need to make a
  3776   4276         ** copy of the filename. */
  3777   4277         pCtx->dbPath = zFilename;
  3778   4278         pCtx->reserved = 0;
  3779   4279         srandomdev();
  3780   4280         unixEnterMutex();
  3781         -      rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
         4281  +      rc = findInodeInfo(pNew, &pNew->pInode);
  3782   4282         if( rc!=SQLITE_OK ){
  3783   4283           sqlite3_free(pNew->lockingContext);
  3784   4284           close(h);
  3785   4285           h = -1;
  3786   4286         }
  3787   4287         unixLeaveMutex();        
  3788   4288       }
................................................................................
  3807   4307   
  3808   4308   #if OS_VXWORKS
  3809   4309     else if( pLockingStyle == &semIoMethods ){
  3810   4310       /* Named semaphore locking uses the file path so it needs to be
  3811   4311       ** included in the semLockingContext
  3812   4312       */
  3813   4313       unixEnterMutex();
  3814         -    rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
  3815         -    if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
  3816         -      char *zSemName = pNew->pOpen->aSemName;
         4314  +    rc = findInodeInfo(pNew, &pNew->pInode);
         4315  +    if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
         4316  +      char *zSemName = pNew->pInode->aSemName;
  3817   4317         int n;
  3818   4318         sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
  3819   4319                          pNew->pId->zCanonicalName);
  3820   4320         for( n=1; zSemName[n]; n++ )
  3821   4321           if( zSemName[n]=='/' ) zSemName[n] = '_';
  3822         -      pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
  3823         -      if( pNew->pOpen->pSem == SEM_FAILED ){
         4322  +      pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
         4323  +      if( pNew->pInode->pSem == SEM_FAILED ){
  3824   4324           rc = SQLITE_NOMEM;
  3825         -        pNew->pOpen->aSemName[0] = '\0';
         4325  +        pNew->pInode->aSemName[0] = '\0';
  3826   4326         }
  3827   4327       }
  3828   4328       unixLeaveMutex();
  3829   4329     }
  3830   4330   #endif
  3831   4331     
  3832   4332     pNew->lastErrno = 0;
................................................................................
  3869   4369     if( ii>0 ){
  3870   4370       zDirname[ii] = '\0';
  3871   4371       fd = open(zDirname, O_RDONLY|O_BINARY, 0);
  3872   4372       if( fd>=0 ){
  3873   4373   #ifdef FD_CLOEXEC
  3874   4374         fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
  3875   4375   #endif
  3876         -      OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
         4376  +      OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
  3877   4377       }
  3878   4378     }
  3879   4379     *pFd = fd;
  3880   4380     return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN_BKPT);
  3881   4381   }
  3882   4382   
  3883   4383   /*
................................................................................
  3982   4482     ** For this reason, if an error occurs in the stat() call here, it is
  3983   4483     ** ignored and -1 is returned. The caller will try to open a new file
  3984   4484     ** descriptor on the same path, fail, and return an error to SQLite.
  3985   4485     **
  3986   4486     ** Even if a subsequent open() call does succeed, the consequences of
  3987   4487     ** not searching for a resusable file descriptor are not dire.  */
  3988   4488     if( 0==stat(zPath, &sStat) ){
  3989         -    struct unixOpenCnt *pOpen;
         4489  +    unixInodeInfo *pInode;
  3990   4490   
  3991   4491       unixEnterMutex();
  3992         -    pOpen = openList;
  3993         -    while( pOpen && (pOpen->fileId.dev!=sStat.st_dev
  3994         -                     || pOpen->fileId.ino!=sStat.st_ino) ){
  3995         -       pOpen = pOpen->pNext;
         4492  +    pInode = inodeList;
         4493  +    while( pInode && (pInode->fileId.dev!=sStat.st_dev
         4494  +                     || pInode->fileId.ino!=sStat.st_ino) ){
         4495  +       pInode = pInode->pNext;
  3996   4496       }
  3997         -    if( pOpen ){
         4497  +    if( pInode ){
  3998   4498         UnixUnusedFd **pp;
  3999         -      for(pp=&pOpen->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
         4499  +      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
  4000   4500         pUnused = *pp;
  4001   4501         if( pUnused ){
  4002   4502           *pp = pUnused->pNext;
  4003   4503         }
  4004   4504       }
  4005   4505       unixLeaveMutex();
  4006   4506     }
................................................................................
  4126   4626     if( isCreate )    openFlags |= O_CREAT;
  4127   4627     if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
  4128   4628     openFlags |= (O_LARGEFILE|O_BINARY);
  4129   4629   
  4130   4630     if( fd<0 ){
  4131   4631       mode_t openMode = (isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
  4132   4632       fd = open(zName, openFlags, openMode);
  4133         -    OSTRACE4("OPENX   %-3d %s 0%o\n", fd, zName, openFlags);
         4633  +    OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
  4134   4634       if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
  4135   4635         /* Failed to open the file for read/write access. Try read-only. */
  4136   4636         flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
  4137   4637         openFlags &= ~(O_RDWR|O_CREAT);
  4138   4638         flags |= SQLITE_OPEN_READONLY;
  4139   4639         openFlags |= O_RDONLY;
  4140   4640         fd = open(zName, openFlags, openMode);
................................................................................
  4571   5071   static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
  4572   5072     UNUSED_PARAMETER(NotUsed);
  4573   5073     UNUSED_PARAMETER(NotUsed2);
  4574   5074     UNUSED_PARAMETER(NotUsed3);
  4575   5075     return 0;
  4576   5076   }
  4577   5077   
  4578         -#ifndef SQLITE_OMIT_WAL
  4579         -
  4580         -/* Forward reference */
  4581         -typedef struct unixShm unixShm;
  4582         -typedef struct unixShmFile unixShmFile;
  4583         -
  4584         -/*
  4585         -** Object used to represent a single file opened and mmapped to provide
  4586         -** shared memory.  When multiple threads all reference the same
  4587         -** log-summary, each thread has its own unixFile object, but they all
  4588         -** point to a single instance of this object.  In other words, each
  4589         -** log-summary is opened only once per process.
  4590         -**
  4591         -** unixMutexHeld() must be true when creating or destroying
  4592         -** this object or while reading or writing the following fields:
  4593         -**
  4594         -**      nRef
  4595         -**      pNext 
  4596         -**
  4597         -** The following fields are read-only after the object is created:
  4598         -** 
  4599         -**      fid
  4600         -**      zFilename
  4601         -**
  4602         -** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and
  4603         -** unixMutexHeld() is true when reading or writing any other field
  4604         -** in this structure.
  4605         -**
  4606         -** To avoid deadlocks, mutex and mutexBuf are always released in the
  4607         -** reverse order that they are acquired.  mutexBuf is always acquired
  4608         -** first and released last.  This invariant is check by asserting
  4609         -** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
  4610         -** released.
  4611         -*/
  4612         -struct unixShmFile {
  4613         -  struct unixFileId fid;     /* Unique file identifier */
  4614         -  sqlite3_mutex *mutex;      /* Mutex to access this object */
  4615         -  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
  4616         -  char *zFilename;           /* Name of the file */
  4617         -  int h;                     /* Open file descriptor */
  4618         -  int szMap;                 /* Size of the mapping of file into memory */
  4619         -  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
  4620         -  int nRef;                  /* Number of unixShm objects pointing to this */
  4621         -  unixShm *pFirst;           /* All unixShm objects pointing to this */
  4622         -  unixShmFile *pNext;        /* Next in list of all unixShmFile objects */
  4623         -#ifdef SQLITE_DEBUG
  4624         -  u8 exclMask;               /* Mask of exclusive locks held */
  4625         -  u8 sharedMask;             /* Mask of shared locks held */
  4626         -  u8 nextShmId;              /* Next available unixShm.id value */
  4627         -#endif
  4628         -};
  4629         -
  4630         -/*
  4631         -** A global array of all unixShmFile objects.
  4632         -**
  4633         -** The unixMutexHeld() must be true while reading or writing this list.
  4634         -*/
  4635         -static unixShmFile *unixShmFileList = 0;
  4636         -
  4637         -/*
  4638         -** Structure used internally by this VFS to record the state of an
  4639         -** open shared memory connection.
  4640         -**
  4641         -** unixShm.pFile->mutex must be held while reading or writing the
  4642         -** unixShm.pNext and unixShm.locks[] elements.
  4643         -**
  4644         -** The unixShm.pFile element is initialized when the object is created
  4645         -** and is read-only thereafter.
  4646         -*/
  4647         -struct unixShm {
  4648         -  unixShmFile *pFile;        /* The underlying unixShmFile object */
  4649         -  unixShm *pNext;            /* Next unixShm with the same unixShmFile */
  4650         -  u8 lockState;              /* Current lock state */
  4651         -  u8 hasMutex;               /* True if holding the unixShmFile mutex */
  4652         -  u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
  4653         -  u8 sharedMask;             /* Mask of shared locks held */
  4654         -  u8 exclMask;               /* Mask of exclusive locks held */
  4655         -#ifdef SQLITE_DEBUG
  4656         -  u8 id;                     /* Id of this connection with its unixShmFile */
  4657         -#endif
  4658         -};
  4659         -
  4660         -/*
  4661         -** Size increment by which shared memory grows
  4662         -*/
  4663         -#define SQLITE_UNIX_SHM_INCR  4096
  4664         -
  4665         -/*
  4666         -** Constants used for locking
  4667         -*/
  4668         -#define UNIX_SHM_BASE      32        /* Byte offset of the first lock byte */
  4669         -#define UNIX_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
  4670         -#define UNIX_SHM_A         0x10      /* Mask for region locks... */
  4671         -#define UNIX_SHM_B         0x20
  4672         -#define UNIX_SHM_C         0x40
  4673         -#define UNIX_SHM_D         0x80
  4674         -
  4675         -#ifdef SQLITE_DEBUG
  4676         -/*
  4677         -** Return a pointer to a nul-terminated string in static memory that
  4678         -** describes a locking mask.  The string is of the form "MSABCD" with
  4679         -** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
  4680         -** and "A" through "D" for the region locks.  If a lock is held, the
  4681         -** letter is shown.  If the lock is not held, the letter is converted
  4682         -** to ".".
  4683         -**
  4684         -** This routine is for debugging purposes only and does not appear
  4685         -** in a production build.
  4686         -*/
  4687         -static const char *unixShmLockString(u8 mask){
  4688         -  static char zBuf[48];
  4689         -  static int iBuf = 0;
  4690         -  char *z;
  4691         -
  4692         -  z = &zBuf[iBuf];
  4693         -  iBuf += 8;
  4694         -  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
  4695         -
  4696         -  z[0] = (mask & UNIX_SHM_DMS)   ? 'S' : '.';
  4697         -  z[1] = (mask & UNIX_SHM_A)     ? 'A' : '.';
  4698         -  z[2] = (mask & UNIX_SHM_B)     ? 'B' : '.';
  4699         -  z[3] = (mask & UNIX_SHM_C)     ? 'C' : '.';
  4700         -  z[4] = (mask & UNIX_SHM_D)     ? 'D' : '.';
  4701         -  z[5] = 0;
  4702         -  return z;
  4703         -}
  4704         -#endif /* SQLITE_DEBUG */
  4705         -
  4706         -/*
  4707         -** Apply posix advisory locks for all bytes identified in lockMask.
  4708         -**
  4709         -** lockMask might contain multiple bits but all bits are guaranteed
  4710         -** to be contiguous.
  4711         -**
  4712         -** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
  4713         -** otherwise.
  4714         -*/
  4715         -static int unixShmSystemLock(
  4716         -  unixShmFile *pFile,   /* Apply locks to this open shared-memory segment */
  4717         -  int lockType,         /* F_UNLCK, F_RDLCK, or F_WRLCK */
  4718         -  u8 lockMask           /* Which bytes to lock or unlock */
  4719         -){
  4720         -  struct flock f;       /* The posix advisory locking structure */
  4721         -  int lockOp;           /* The opcode for fcntl() */
  4722         -  int i;                /* Offset into the locking byte range */
  4723         -  int rc;               /* Result code form fcntl() */
  4724         -  u8 mask;              /* Mask of bits in lockMask */
  4725         -
  4726         -  /* Access to the unixShmFile object is serialized by the caller */
  4727         -  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
  4728         -
  4729         -  /* Initialize the locking parameters */
  4730         -  memset(&f, 0, sizeof(f));
  4731         -  f.l_type = lockType;
  4732         -  f.l_whence = SEEK_SET;
  4733         -  if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){
  4734         -    lockOp = F_SETLKW;
  4735         -    OSTRACE(("SHM-LOCK requesting blocking lock\n"));
  4736         -  }else{
  4737         -    lockOp = F_SETLK;
  4738         -  }
  4739         -
  4740         -  /* Find the first bit in lockMask that is set */
  4741         -  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
  4742         -  assert( mask!=0 );
  4743         -  f.l_start = i+UNIX_SHM_BASE;
  4744         -  f.l_len = 1;
  4745         -
  4746         -  /* Extend the locking range for each additional bit that is set */
  4747         -  mask <<= 1;
  4748         -  while( mask!=0 && (lockMask & mask)!=0 ){
  4749         -    f.l_len++;
  4750         -    mask <<= 1;
  4751         -  }
  4752         -
  4753         -  /* Verify that all bits set in lockMask are contiguous */
  4754         -  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
  4755         -
  4756         -  /* Acquire the system-level lock */
  4757         -  rc = fcntl(pFile->h, lockOp, &f);
  4758         -  rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
  4759         -
  4760         -  /* Update the global lock state and do debug tracing */
  4761         -#ifdef SQLITE_DEBUG
  4762         -  OSTRACE(("SHM-LOCK "));
  4763         -  if( rc==SQLITE_OK ){
  4764         -    if( lockType==F_UNLCK ){
  4765         -      OSTRACE(("unlock ok"));
  4766         -      pFile->exclMask &= ~lockMask;
  4767         -      pFile->sharedMask &= ~lockMask;
  4768         -    }else if( lockType==F_RDLCK ){
  4769         -      OSTRACE(("read-lock ok"));
  4770         -      pFile->exclMask &= ~lockMask;
  4771         -      pFile->sharedMask |= lockMask;
  4772         -    }else{
  4773         -      assert( lockType==F_WRLCK );
  4774         -      OSTRACE(("write-lock ok"));
  4775         -      pFile->exclMask |= lockMask;
  4776         -      pFile->sharedMask &= ~lockMask;
  4777         -    }
  4778         -  }else{
  4779         -    if( lockType==F_UNLCK ){
  4780         -      OSTRACE(("unlock failed"));
  4781         -    }else if( lockType==F_RDLCK ){
  4782         -      OSTRACE(("read-lock failed"));
  4783         -    }else{
  4784         -      assert( lockType==F_WRLCK );
  4785         -      OSTRACE(("write-lock failed"));
  4786         -    }
  4787         -  }
  4788         -  OSTRACE((" - change requested %s - afterwards %s:%s\n",
  4789         -           unixShmLockString(lockMask),
  4790         -           unixShmLockString(pFile->sharedMask),
  4791         -           unixShmLockString(pFile->exclMask)));
  4792         -#endif
  4793         -
  4794         -  return rc;        
  4795         -}
  4796         -
  4797         -/*
  4798         -** For connection p, unlock all of the locks identified by the unlockMask
  4799         -** parameter.
  4800         -*/
  4801         -static int unixShmUnlock(
  4802         -  unixShmFile *pFile,   /* The underlying shared-memory file */
  4803         -  unixShm *p,           /* The connection to be unlocked */
  4804         -  u8 unlockMask         /* Mask of locks to be unlocked */
  4805         -){
  4806         -  int rc;      /* Result code */
  4807         -  unixShm *pX; /* For looping over all sibling connections */
  4808         -  u8 allMask;  /* Union of locks held by connections other than "p" */
  4809         -
  4810         -  /* Access to the unixShmFile object is serialized by the caller */
  4811         -  assert( sqlite3_mutex_held(pFile->mutex) );
  4812         -
  4813         -  /* Compute locks held by sibling connections */
  4814         -  allMask = 0;
  4815         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4816         -    if( pX==p ) continue;
  4817         -    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
  4818         -    allMask |= pX->sharedMask;
  4819         -  }
  4820         -
  4821         -  /* Unlock the system-level locks */
  4822         -  if( (unlockMask & allMask)!=unlockMask ){
  4823         -    rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask);
  4824         -  }else{
  4825         -    rc = SQLITE_OK;
  4826         -  }
  4827         -
  4828         -  /* Undo the local locks */
  4829         -  if( rc==SQLITE_OK ){
  4830         -    p->exclMask &= ~unlockMask;
  4831         -    p->sharedMask &= ~unlockMask;
  4832         -  } 
  4833         -  return rc;
  4834         -}
  4835         -
  4836         -/*
  4837         -** Get reader locks for connection p on all locks in the readMask parameter.
  4838         -*/
  4839         -static int unixShmSharedLock(
  4840         -  unixShmFile *pFile,   /* The underlying shared-memory file */
  4841         -  unixShm *p,           /* The connection to get the shared locks */
  4842         -  u8 readMask           /* Mask of shared locks to be acquired */
  4843         -){
  4844         -  int rc;        /* Result code */
  4845         -  unixShm *pX;   /* For looping over all sibling connections */
  4846         -  u8 allShared;  /* Union of locks held by connections other than "p" */
  4847         -
  4848         -  /* Access to the unixShmFile object is serialized by the caller */
  4849         -  assert( sqlite3_mutex_held(pFile->mutex) );
  4850         -
  4851         -  /* Find out which shared locks are already held by sibling connections.
  4852         -  ** If any sibling already holds an exclusive lock, go ahead and return
  4853         -  ** SQLITE_BUSY.
  4854         -  */
  4855         -  allShared = 0;
  4856         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4857         -    if( pX==p ) continue;
  4858         -    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
  4859         -    allShared |= pX->sharedMask;
  4860         -  }
  4861         -
  4862         -  /* Get shared locks at the system level, if necessary */
  4863         -  if( (~allShared) & readMask ){
  4864         -    rc = unixShmSystemLock(pFile, F_RDLCK, readMask);
  4865         -  }else{
  4866         -    rc = SQLITE_OK;
  4867         -  }
  4868         -
  4869         -  /* Get the local shared locks */
  4870         -  if( rc==SQLITE_OK ){
  4871         -    p->sharedMask |= readMask;
  4872         -  }
  4873         -  return rc;
  4874         -}
  4875         -
  4876         -/*
  4877         -** For connection p, get an exclusive lock on all locks identified in
  4878         -** the writeMask parameter.
  4879         -*/
  4880         -static int unixShmExclusiveLock(
  4881         -  unixShmFile *pFile,    /* The underlying shared-memory file */
  4882         -  unixShm *p,            /* The connection to get the exclusive locks */
  4883         -  u8 writeMask           /* Mask of exclusive locks to be acquired */
  4884         -){
  4885         -  int rc;        /* Result code */
  4886         -  unixShm *pX;   /* For looping over all sibling connections */
  4887         -
  4888         -  /* Access to the unixShmFile object is serialized by the caller */
  4889         -  assert( sqlite3_mutex_held(pFile->mutex) );
  4890         -
  4891         -  /* Make sure no sibling connections hold locks that will block this
  4892         -  ** lock.  If any do, return SQLITE_BUSY right away.
  4893         -  */
  4894         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4895         -    if( pX==p ) continue;
  4896         -    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
  4897         -    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
  4898         -  }
  4899         -
  4900         -  /* Get the exclusive locks at the system level.  Then if successful
  4901         -  ** also mark the local connection as being locked.
  4902         -  */
  4903         -  rc = unixShmSystemLock(pFile, F_WRLCK, writeMask);
  4904         -  if( rc==SQLITE_OK ){
  4905         -    p->sharedMask &= ~writeMask;
  4906         -    p->exclMask |= writeMask;
  4907         -  }
  4908         -  return rc;
  4909         -}
  4910         -
  4911         -/*
  4912         -** Purge the unixShmFileList list of all entries with unixShmFile.nRef==0.
  4913         -**
  4914         -** This is not a VFS shared-memory method; it is a utility function called
  4915         -** by VFS shared-memory methods.
  4916         -*/
  4917         -static void unixShmPurge(void){
  4918         -  unixShmFile **pp;
  4919         -  unixShmFile *p;
  4920         -  assert( unixMutexHeld() );
  4921         -  pp = &unixShmFileList;
  4922         -  while( (p = *pp)!=0 ){
  4923         -    if( p->nRef==0 ){
  4924         -      if( p->mutex ) sqlite3_mutex_free(p->mutex);
  4925         -      if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
  4926         -      if( p->h>=0 ) close(p->h);
  4927         -      *pp = p->pNext;
  4928         -      sqlite3_free(p);
  4929         -    }else{
  4930         -      pp = &p->pNext;
  4931         -    }
  4932         -  }
  4933         -}
  4934         -
  4935         -/*
  4936         -** Open a shared-memory area.  This particular implementation uses
  4937         -** mmapped files.
  4938         -**
  4939         -** zName is a filename used to identify the shared-memory area.  The
  4940         -** implementation does not (and perhaps should not) use this name
  4941         -** directly, but rather use it as a template for finding an appropriate
  4942         -** name for the shared-memory storage.  In this implementation, the
  4943         -** string "-index" is appended to zName and used as the name of the
  4944         -** mmapped file.
  4945         -**
  4946         -** When opening a new shared-memory file, if no other instances of that
  4947         -** file are currently open, in this process or in other processes, then
  4948         -** the file must be truncated to zero length or have its header cleared.
  4949         -*/
  4950         -static int unixShmOpen(
  4951         -  sqlite3_vfs *pVfs,    /* The VFS */
  4952         -  const char *zName,    /* Name of the corresponding database file */
  4953         -  sqlite3_shm **pShm    /* Write the unixShm object created here */
  4954         -){
  4955         -  struct unixShm *p = 0;             /* The connection to be opened */
  4956         -  struct unixShmFile *pFile = 0;     /* The underlying mmapped file */
  4957         -  int rc;                            /* Result code */
  4958         -  struct unixFileId fid;             /* Unix file identifier */
  4959         -  struct unixShmFile *pNew;          /* Newly allocated pFile */
  4960         -  struct stat sStat;                 /* Result from stat() an fstat() */
  4961         -  int nName;                         /* Size of zName in bytes */
  4962         -
  4963         -  /* Allocate space for the new sqlite3_shm object.  Also speculatively
  4964         -  ** allocate space for a new unixShmFile and filename.
  4965         -  */
  4966         -  p = sqlite3_malloc( sizeof(*p) );
  4967         -  if( p==0 ) return SQLITE_NOMEM;
  4968         -  memset(p, 0, sizeof(*p));
  4969         -  nName = strlen(zName);
  4970         -  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 15 );
  4971         -  if( pNew==0 ){
  4972         -    sqlite3_free(p);
  4973         -    return SQLITE_NOMEM;
  4974         -  }
  4975         -  memset(pNew, 0, sizeof(*pNew));
  4976         -  pNew->zFilename = (char*)&pNew[1];
  4977         -  sqlite3_snprintf(nName+11, pNew->zFilename, "%s-wal-index", zName);
  4978         -
  4979         -  /* Look to see if there is an existing unixShmFile that can be used.
  4980         -  ** If no matching unixShmFile currently exists, create a new one.
  4981         -  */
  4982         -  unixEnterMutex();
  4983         -  rc = stat(pNew->zFilename, &sStat);
  4984         -  if( rc==0 ){
  4985         -    memset(&fid, 0, sizeof(fid));
  4986         -    fid.dev = sStat.st_dev;
  4987         -    fid.ino = sStat.st_ino;
  4988         -    for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){
  4989         -      if( memcmp(&pFile->fid, &fid, sizeof(fid))==0 ) break;
  4990         -    }
  4991         -  }
  4992         -  if( pFile ){
  4993         -    sqlite3_free(pNew);
  4994         -  }else{
  4995         -    pFile = pNew;
  4996         -    pNew = 0;
  4997         -    pFile->h = -1;
  4998         -    pFile->pNext = unixShmFileList;
  4999         -    unixShmFileList = pFile;
  5000         -
  5001         -    pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  5002         -    if( pFile->mutex==0 ){
  5003         -      rc = SQLITE_NOMEM;
  5004         -      goto shm_open_err;
  5005         -    }
  5006         -    pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  5007         -    if( pFile->mutexBuf==0 ){
  5008         -      rc = SQLITE_NOMEM;
  5009         -      goto shm_open_err;
  5010         -    }
  5011         -
  5012         -    pFile->h = open(pFile->zFilename, O_RDWR|O_CREAT, 0664);
  5013         -    if( pFile->h<0 ){
  5014         -      rc = SQLITE_CANTOPEN_BKPT;
  5015         -      goto shm_open_err;
  5016         -    }
  5017         -
  5018         -    rc = fstat(pFile->h, &sStat);
  5019         -    if( rc ){
  5020         -      rc = SQLITE_CANTOPEN_BKPT;
  5021         -      goto shm_open_err;
  5022         -    }
  5023         -    pFile->fid.dev = sStat.st_dev;
  5024         -    pFile->fid.ino = sStat.st_ino;
  5025         -
  5026         -    /* Check to see if another process is holding the dead-man switch.
  5027         -    ** If not, truncate the file to zero length. 
  5028         -    */
  5029         -    if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
  5030         -      if( ftruncate(pFile->h, 0) ){
  5031         -        rc = SQLITE_IOERR;
  5032         -      }
  5033         -    }
  5034         -    if( rc==SQLITE_OK ){
  5035         -      rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS);
  5036         -    }
  5037         -    if( rc ) goto shm_open_err;
  5038         -  }
  5039         -
  5040         -  /* Make the new connection a child of the unixShmFile */
  5041         -  p->pFile = pFile;
  5042         -  p->pNext = pFile->pFirst;
  5043         -#ifdef SQLITE_DEBUG
  5044         -  p->id = pFile->nextShmId++;
  5045         -#endif
  5046         -  pFile->pFirst = p;
  5047         -  pFile->nRef++;
  5048         -  *pShm = (sqlite3_shm*)p;
  5049         -  unixLeaveMutex();
  5050         -  return SQLITE_OK;
  5051         -
  5052         -  /* Jump here on any error */
  5053         -shm_open_err:
  5054         -  unixShmPurge();                 /* This call frees pFile if required */
  5055         -  sqlite3_free(p);
  5056         -  sqlite3_free(pNew);
  5057         -  *pShm = 0;
  5058         -  unixLeaveMutex();
  5059         -  return rc;
  5060         -}
  5061         -
  5062         -/*
  5063         -** Close a connection to shared-memory.  Delete the underlying 
  5064         -** storage if deleteFlag is true.
  5065         -*/
  5066         -static int unixShmClose(
  5067         -  sqlite3_vfs *pVfs,         /* The VFS */
  5068         -  sqlite3_shm *pSharedMem,   /* The shared-memory to be closed */
  5069         -  int deleteFlag             /* Delete after closing if true */
  5070         -){
  5071         -  unixShm *p;            /* The connection to be closed */
  5072         -  unixShmFile *pFile;    /* The underlying shared-memory file */
  5073         -  unixShm **pp;          /* For looping over sibling connections */
  5074         -
  5075         -  UNUSED_PARAMETER(pVfs);
  5076         -  if( pSharedMem==0 ) return SQLITE_OK;
  5077         -  p = (struct unixShm*)pSharedMem;
  5078         -  pFile = p->pFile;
  5079         -
  5080         -  /* Verify that the connection being closed holds no locks */
  5081         -  assert( p->exclMask==0 );
  5082         -  assert( p->sharedMask==0 );
  5083         -
  5084         -  /* Remove connection p from the set of connections associated with pFile */
  5085         -  sqlite3_mutex_enter(pFile->mutex);
  5086         -  for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
  5087         -  *pp = p->pNext;
  5088         -
  5089         -  /* Free the connection p */
  5090         -  sqlite3_free(p);
  5091         -  sqlite3_mutex_leave(pFile->mutex);
  5092         -
  5093         -  /* If pFile->nRef has reached 0, then close the underlying
  5094         -  ** shared-memory file, too */
  5095         -  unixEnterMutex();
  5096         -  assert( pFile->nRef>0 );
  5097         -  pFile->nRef--;
  5098         -  if( pFile->nRef==0 ){
  5099         -    if( deleteFlag ) unlink(pFile->zFilename);
  5100         -    unixShmPurge();
  5101         -  }
  5102         -  unixLeaveMutex();
  5103         -
  5104         -  return SQLITE_OK;
  5105         -}
  5106         -
  5107         -/*
  5108         -** Query and/or changes the size of the underlying storage for
  5109         -** a shared-memory segment.  The reqSize parameter is the new size
  5110         -** of the underlying storage, or -1 to do just a query.  The size
  5111         -** of the underlying storage (after resizing if resizing occurs) is
  5112         -** written into pNewSize.
  5113         -**
  5114         -** This routine does not (necessarily) change the size of the mapping 
  5115         -** of the underlying storage into memory.  Use xShmGet() to change
  5116         -** the mapping size.
  5117         -**
  5118         -** The reqSize parameter is the minimum size requested.  The implementation
  5119         -** is free to expand the storage to some larger amount if it chooses.
  5120         -*/
  5121         -static int unixShmSize(
  5122         -  sqlite3_vfs *pVfs,        /* The VFS */
  5123         -  sqlite3_shm *pSharedMem,  /* Pointer returned by unixShmOpen() */
  5124         -  int reqSize,              /* Requested size.  -1 for query only */
  5125         -  int *pNewSize             /* Write new size here */
  5126         -){
  5127         -  unixShm *p = (unixShm*)pSharedMem;
  5128         -  unixShmFile *pFile = p->pFile;
  5129         -  int rc = SQLITE_OK;
  5130         -  struct stat sStat;
  5131         -
  5132         -  UNUSED_PARAMETER(pVfs);
  5133         -
  5134         -  if( reqSize>=0 ){
  5135         -    reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
  5136         -    reqSize *= SQLITE_UNIX_SHM_INCR;
  5137         -    rc = ftruncate(pFile->h, reqSize);
  5138         -  }
  5139         -  if( fstat(pFile->h, &sStat)==0 ){
  5140         -    *pNewSize = (int)sStat.st_size;
  5141         -  }else{
  5142         -    *pNewSize = 0;
  5143         -    rc = SQLITE_IOERR;
  5144         -  }
  5145         -  return rc;
  5146         -}
  5147         -
  5148         -
  5149         -/*
  5150         -** Map the shared storage into memory.  The minimum size of the
  5151         -** mapping should be reqMapSize if reqMapSize is positive.  If
  5152         -** reqMapSize is zero or negative, the implementation can choose
  5153         -** whatever mapping size is convenient.
  5154         -**
  5155         -** *ppBuf is made to point to the memory which is a mapping of the
  5156         -** underlying storage.  A mutex is acquired to prevent other threads
  5157         -** from running while *ppBuf is in use in order to prevent other threads
  5158         -** remapping *ppBuf out from under this thread.  The unixShmRelease()
  5159         -** call will release the mutex.  However, if the lock state is CHECKPOINT,
  5160         -** the mutex is not acquired because CHECKPOINT will never remap the
  5161         -** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
  5162         -** the mutex if and when it promotes to RECOVER.
  5163         -**
  5164         -** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
  5165         -** being remapped also prevents more than one thread from being in
  5166         -** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
  5167         -** To prevent RECOVER from losing its lock while remapping, the
  5168         -** mutex is not released by unixShmRelease() when in RECOVER.
  5169         -**
  5170         -** *pNewMapSize is set to the size of the mapping.
  5171         -**
  5172         -** *ppBuf and *pNewMapSize might be NULL and zero if no space has
  5173         -** yet been allocated to the underlying storage.
  5174         -*/
  5175         -static int unixShmGet(
  5176         -  sqlite3_vfs *pVfs,       /* The VFS */
  5177         -  sqlite3_shm *pSharedMem, /* Pointer returned by unixShmOpen() */
  5178         -  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  5179         -  int *pNewMapSize,        /* Write new size of mapping here */
  5180         -  void **ppBuf             /* Write mapping buffer origin here */
  5181         -){
  5182         -  unixShm *p = (unixShm*)pSharedMem;
  5183         -  unixShmFile *pFile = p->pFile;
  5184         -  int rc = SQLITE_OK;
  5185         -
  5186         -  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
  5187         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  5188         -    sqlite3_mutex_enter(pFile->mutexBuf);
  5189         -    p->hasMutexBuf = 1;
  5190         -  }
  5191         -  sqlite3_mutex_enter(pFile->mutex);
  5192         -  if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
  5193         -    int actualSize;
  5194         -    if( unixShmSize(pVfs, pSharedMem, -1, &actualSize)==SQLITE_OK
  5195         -     && reqMapSize<actualSize
  5196         -    ){
  5197         -      reqMapSize = actualSize;
  5198         -    }
  5199         -    if( pFile->pMMapBuf ){
  5200         -      munmap(pFile->pMMapBuf, pFile->szMap);
  5201         -    }
  5202         -    pFile->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
  5203         -                           pFile->h, 0);
  5204         -    pFile->szMap = pFile->pMMapBuf ? reqMapSize : 0;
  5205         -  }
  5206         -  *pNewMapSize = pFile->szMap;
  5207         -  *ppBuf = pFile->pMMapBuf;
  5208         -  sqlite3_mutex_leave(pFile->mutex);
  5209         -  return rc;
  5210         -}
  5211         -
  5212         -/*
  5213         -** Release the lock held on the shared memory segment to that other
  5214         -** threads are free to resize it if necessary.
  5215         -**
  5216         -** If the lock is not currently held, this routine is a harmless no-op.
  5217         -**
  5218         -** If the shared-memory object is in lock state RECOVER, then we do not
  5219         -** really want to release the lock, so in that case too, this routine
  5220         -** is a no-op.
  5221         -*/
  5222         -static int unixShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pSharedMem){
  5223         -  unixShm *p = (unixShm*)pSharedMem;
  5224         -  UNUSED_PARAMETER(pVfs);
  5225         -  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
  5226         -    assert( sqlite3_mutex_notheld(p->pFile->mutex) );
  5227         -    sqlite3_mutex_leave(p->pFile->mutexBuf);
  5228         -    p->hasMutexBuf = 0;
  5229         -  }
  5230         -  return SQLITE_OK;
  5231         -}
  5232         -
  5233         -/*
  5234         -** Symbolic names for LOCK states used for debugging.
  5235         -*/
  5236         -#ifdef SQLITE_DEBUG
  5237         -static const char *azLkName[] = {
  5238         -  "UNLOCK",
  5239         -  "READ",
  5240         -  "READ_FULL",
  5241         -  "WRITE",
  5242         -  "PENDING",
  5243         -  "CHECKPOINT",
  5244         -  "RECOVER"
  5245         -};
  5246         -#endif
  5247         -
  5248         -
  5249         -/*
  5250         -** Change the lock state for a shared-memory segment.
  5251         -*/
  5252         -static int unixShmLock(
  5253         -  sqlite3_vfs *pVfs,         /* The VFS */
  5254         -  sqlite3_shm *pSharedMem,   /* Pointer from unixShmOpen() */
  5255         -  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
  5256         -  int *pGotLock              /* The lock you actually got */
  5257         -){
  5258         -  unixShm *p = (unixShm*)pSharedMem;
  5259         -  unixShmFile *pFile = p->pFile;
  5260         -  int rc = SQLITE_PROTOCOL;
  5261         -
  5262         -  UNUSED_PARAMETER(pVfs);
  5263         -
  5264         -  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
  5265         -  ** directly requested; they are side effects from requesting
  5266         -  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
  5267         -  */
  5268         -  assert( desiredLock==SQLITE_SHM_UNLOCK
  5269         -       || desiredLock==SQLITE_SHM_READ
  5270         -       || desiredLock==SQLITE_SHM_WRITE
  5271         -       || desiredLock==SQLITE_SHM_CHECKPOINT
  5272         -       || desiredLock==SQLITE_SHM_RECOVER );
  5273         -
  5274         -  /* Return directly if this is just a lock state query, or if
  5275         -  ** the connection is already in the desired locking state.
  5276         -  */
  5277         -  if( desiredLock==p->lockState
  5278         -   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
  5279         -  ){
  5280         -    OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n",
  5281         -             p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState]));
  5282         -    if( pGotLock ) *pGotLock = p->lockState;
  5283         -    return SQLITE_OK;
  5284         -  }
  5285         -
  5286         -  OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
  5287         -            p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
  5288         -  
  5289         -  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
  5290         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  5291         -    sqlite3_mutex_enter(pFile->mutexBuf);
  5292         -    p->hasMutexBuf = 1;
  5293         -  }
  5294         -  sqlite3_mutex_enter(pFile->mutex);
  5295         -  switch( desiredLock ){
  5296         -    case SQLITE_SHM_UNLOCK: {
  5297         -      assert( p->lockState!=SQLITE_SHM_RECOVER );
  5298         -      unixShmUnlock(pFile, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
  5299         -      rc = SQLITE_OK;
  5300         -      p->lockState = SQLITE_SHM_UNLOCK;
  5301         -      break;
  5302         -    }
  5303         -    case SQLITE_SHM_READ: {
  5304         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  5305         -        int nAttempt;
  5306         -        rc = SQLITE_BUSY;
  5307         -        assert( p->lockState==SQLITE_SHM_UNLOCK );
  5308         -        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
  5309         -          rc = unixShmSharedLock(pFile, p, UNIX_SHM_A|UNIX_SHM_B);
  5310         -          if( rc==SQLITE_BUSY ){
  5311         -            rc = unixShmSharedLock(pFile, p, UNIX_SHM_D);
  5312         -            if( rc==SQLITE_OK ){
  5313         -              p->lockState = SQLITE_SHM_READ_FULL;
  5314         -            }
  5315         -          }else{
  5316         -            unixShmUnlock(pFile, p, UNIX_SHM_B);
  5317         -            p->lockState = SQLITE_SHM_READ;
  5318         -          }
  5319         -        }
  5320         -      }else{
  5321         -       assert( p->lockState==SQLITE_SHM_WRITE
  5322         -               || p->lockState==SQLITE_SHM_RECOVER );
  5323         -        rc = unixShmSharedLock(pFile, p, UNIX_SHM_A);
  5324         -        unixShmUnlock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
  5325         -        p->lockState = SQLITE_SHM_READ;
  5326         -      }
  5327         -      break;
  5328         -    }
  5329         -    case SQLITE_SHM_WRITE: {
  5330         -      assert( p->lockState==SQLITE_SHM_READ 
  5331         -              || p->lockState==SQLITE_SHM_READ_FULL );
  5332         -      rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
  5333         -      if( rc==SQLITE_OK ){
  5334         -        p->lockState = SQLITE_SHM_WRITE;
  5335         -      }
  5336         -      break;
  5337         -    }
  5338         -    case SQLITE_SHM_CHECKPOINT: {
  5339         -      assert( p->lockState==SQLITE_SHM_UNLOCK
  5340         -           || p->lockState==SQLITE_SHM_PENDING
  5341         -      );
  5342         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  5343         -        rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_B|UNIX_SHM_C);
  5344         -        if( rc==SQLITE_OK ){
  5345         -          p->lockState = SQLITE_SHM_PENDING;
  5346         -        }
  5347         -      }
  5348         -      if( p->lockState==SQLITE_SHM_PENDING ){
  5349         -        rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_A);
  5350         -        if( rc==SQLITE_OK ){
  5351         -          p->lockState = SQLITE_SHM_CHECKPOINT;
  5352         -        }
  5353         -      }
  5354         -      break;
  5355         -    }
  5356         -    default: {
  5357         -      assert( desiredLock==SQLITE_SHM_RECOVER );
  5358         -      assert( p->lockState==SQLITE_SHM_READ
  5359         -           || p->lockState==SQLITE_SHM_READ_FULL
  5360         -      );
  5361         -      assert( sqlite3_mutex_held(pFile->mutexBuf) );
  5362         -      rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C);
  5363         -      if( rc==SQLITE_OK ){
  5364         -        p->lockState = SQLITE_SHM_RECOVER;
  5365         -      }
  5366         -      break;
  5367         -    }
  5368         -  }
  5369         -  sqlite3_mutex_leave(pFile->mutex);
  5370         -  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
  5371         -           p->id, getpid(), azLkName[p->lockState]));
  5372         -  if( pGotLock ) *pGotLock = p->lockState;
  5373         -  return rc;
  5374         -}
  5375         -
  5376         -#else
  5377         -# define unixShmOpen    0
  5378         -# define unixShmSize    0
  5379         -# define unixShmGet     0
  5380         -# define unixShmRelease 0
  5381         -# define unixShmLock    0
  5382         -# define unixShmClose   0
  5383         -#endif /* #ifndef SQLITE_OMIT_WAL */
  5384   5078   
  5385   5079   /*
  5386   5080   ************************ End of sqlite3_vfs methods ***************************
  5387   5081   ******************************************************************************/
  5388   5082   
  5389   5083   /******************************************************************************
  5390   5084   ************************** Begin Proxy Locking ********************************
................................................................................
  5568   5262   
  5569   5263   #ifdef LOCKPROXYDIR
  5570   5264     len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
  5571   5265   #else
  5572   5266   # ifdef _CS_DARWIN_USER_TEMP_DIR
  5573   5267     {
  5574   5268       if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
  5575         -      OSTRACE4("GETLOCKPATH  failed %s errno=%d pid=%d\n",
  5576         -               lPath, errno, getpid());
         5269  +      OSTRACE(("GETLOCKPATH  failed %s errno=%d pid=%d\n",
         5270  +               lPath, errno, getpid()));
  5577   5271         return SQLITE_IOERR_LOCK;
  5578   5272       }
  5579   5273       len = strlcat(lPath, "sqliteplocks", maxLen);    
  5580   5274     }
  5581   5275   # else
  5582   5276     len = strlcpy(lPath, "/tmp/", maxLen);
  5583   5277   # endif
................................................................................
  5591   5285     dbLen = (int)strlen(dbPath);
  5592   5286     for( i=0; i<dbLen && (i+len+7)<maxLen; i++){
  5593   5287       char c = dbPath[i];
  5594   5288       lPath[i+len] = (c=='/')?'_':c;
  5595   5289     }
  5596   5290     lPath[i+len]='\0';
  5597   5291     strlcat(lPath, ":auto:", maxLen);
  5598         -  OSTRACE3("GETLOCKPATH  proxy lock path=%s pid=%d\n", lPath, getpid());
         5292  +  OSTRACE(("GETLOCKPATH  proxy lock path=%s pid=%d\n", lPath, getpid()));
  5599   5293     return SQLITE_OK;
  5600   5294   }
  5601   5295   
  5602   5296   /* 
  5603   5297    ** Creates the lock file and any missing directories in lockPath
  5604   5298    */
  5605   5299   static int proxyCreateLockPath(const char *lockPath){
................................................................................
  5616   5310         /* only mkdir if leaf dir != "." or "/" or ".." */
  5617   5311         if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/') 
  5618   5312            || (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
  5619   5313           buf[i]='\0';
  5620   5314           if( mkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
  5621   5315             int err=errno;
  5622   5316             if( err!=EEXIST ) {
  5623         -            OSTRACE5("CREATELOCKPATH  FAILED creating %s, "
         5317  +            OSTRACE(("CREATELOCKPATH  FAILED creating %s, "
  5624   5318                        "'%s' proxy lock path=%s pid=%d\n",
  5625         -                     buf, strerror(err), lockPath, getpid());
         5319  +                     buf, strerror(err), lockPath, getpid()));
  5626   5320               return err;
  5627   5321             }
  5628   5322           }
  5629   5323         }
  5630   5324         start=i+1;
  5631   5325       }
  5632   5326       buf[i] = lockPath[i];
  5633   5327     }
  5634         -  OSTRACE3("CREATELOCKPATH  proxy lock path=%s pid=%d\n", lockPath, getpid());
         5328  +  OSTRACE(("CREATELOCKPATH  proxy lock path=%s pid=%d\n", lockPath, getpid()));
  5635   5329     return 0;
  5636   5330   }
  5637   5331   
  5638   5332   /*
  5639   5333   ** Create a new VFS file descriptor (stored in memory obtained from
  5640   5334   ** sqlite3_malloc) and open the file named "path" in the file descriptor.
  5641   5335   **
................................................................................
  5919   5613       int rc = SQLITE_OK;
  5920   5614       int createConch = 0;
  5921   5615       int hostIdMatch = 0;
  5922   5616       int readLen = 0;
  5923   5617       int tryOldLockPath = 0;
  5924   5618       int forceNewLockPath = 0;
  5925   5619       
  5926         -    OSTRACE4("TAKECONCH  %d for %s pid=%d\n", conchFile->h,
  5927         -             (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid());
         5620  +    OSTRACE(("TAKECONCH  %d for %s pid=%d\n", conchFile->h,
         5621  +             (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
  5928   5622   
  5929   5623       rc = proxyGetHostID(myHostID, &pError);
  5930   5624       if( (rc&0xff)==SQLITE_IOERR ){
  5931   5625         pFile->lastErrno = pError;
  5932   5626         goto end_takeconch;
  5933   5627       }
  5934   5628       rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
................................................................................
  6000   5694         
  6001   5695         /* update conch with host and path (this will fail if other process
  6002   5696         ** has a shared lock already), if the host id matches, use the big
  6003   5697         ** stick.
  6004   5698         */
  6005   5699         futimes(conchFile->h, NULL);
  6006   5700         if( hostIdMatch && !createConch ){
  6007         -        if( conchFile->pLock && conchFile->pLock->cnt>1 ){
         5701  +        if( conchFile->pInode && conchFile->pInode->nShared>1 ){
  6008   5702             /* We are trying for an exclusive lock but another thread in this
  6009   5703              ** same process is still holding a shared lock. */
  6010   5704             rc = SQLITE_BUSY;
  6011   5705           } else {          
  6012   5706             rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
  6013   5707           }
  6014   5708         }else{
................................................................................
  6056   5750   #endif
  6057   5751             }
  6058   5752           }
  6059   5753         }
  6060   5754         conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
  6061   5755         
  6062   5756       end_takeconch:
  6063         -      OSTRACE2("TRANSPROXY: CLOSE  %d\n", pFile->h);
         5757  +      OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
  6064   5758         if( rc==SQLITE_OK && pFile->openFlags ){
  6065   5759           if( pFile->h>=0 ){
  6066   5760   #ifdef STRICT_CLOSE_ERROR
  6067   5761             if( close(pFile->h) ){
  6068   5762               pFile->lastErrno = errno;
  6069   5763               return SQLITE_IOERR_CLOSE;
  6070   5764             }
................................................................................
  6071   5765   #else
  6072   5766             close(pFile->h); /* silently leak fd if fail */
  6073   5767   #endif
  6074   5768           }
  6075   5769           pFile->h = -1;
  6076   5770           int fd = open(pCtx->dbPath, pFile->openFlags,
  6077   5771                         SQLITE_DEFAULT_FILE_PERMISSIONS);
  6078         -        OSTRACE2("TRANSPROXY: OPEN  %d\n", fd);
         5772  +        OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
  6079   5773           if( fd>=0 ){
  6080   5774             pFile->h = fd;
  6081   5775           }else{
  6082   5776             rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
  6083   5777              during locking */
  6084   5778           }
  6085   5779         }
................................................................................
  6113   5807             afpLockingContext *afpCtx;
  6114   5808             afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
  6115   5809             afpCtx->dbPath = pCtx->lockProxyPath;
  6116   5810           }
  6117   5811         } else {
  6118   5812           conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
  6119   5813         }
  6120         -      OSTRACE3("TAKECONCH  %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
         5814  +      OSTRACE(("TAKECONCH  %d %s\n", conchFile->h,
         5815  +               rc==SQLITE_OK?"ok":"failed"));
  6121   5816         return rc;
  6122         -    } while (1); /* in case we need to retry the :auto: lock file - we should never get here except via the 'continue' call. */
         5817  +    } while (1); /* in case we need to retry the :auto: lock file - 
         5818  +                 ** we should never get here except via the 'continue' call. */
  6123   5819     }
  6124   5820   }
  6125   5821   
  6126   5822   /*
  6127   5823   ** If pFile holds a lock on a conch file, then release that lock.
  6128   5824   */
  6129   5825   static int proxyReleaseConch(unixFile *pFile){
  6130   5826     int rc = SQLITE_OK;         /* Subroutine return code */
  6131   5827     proxyLockingContext *pCtx;  /* The locking context for the proxy lock */
  6132   5828     unixFile *conchFile;        /* Name of the conch file */
  6133   5829   
  6134   5830     pCtx = (proxyLockingContext *)pFile->lockingContext;
  6135   5831     conchFile = pCtx->conchFile;
  6136         -  OSTRACE4("RELEASECONCH  %d for %s pid=%d\n", conchFile->h,
         5832  +  OSTRACE(("RELEASECONCH  %d for %s pid=%d\n", conchFile->h,
  6137   5833              (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), 
  6138         -           getpid());
         5834  +           getpid()));
  6139   5835     if( pCtx->conchHeld>0 ){
  6140   5836       rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
  6141   5837     }
  6142   5838     pCtx->conchHeld = 0;
  6143         -  OSTRACE3("RELEASECONCH  %d %s\n", conchFile->h,
  6144         -           (rc==SQLITE_OK ? "ok" : "failed"));
         5839  +  OSTRACE(("RELEASECONCH  %d %s\n", conchFile->h,
         5840  +           (rc==SQLITE_OK ? "ok" : "failed")));
  6145   5841     return rc;
  6146   5842   }
  6147   5843   
  6148   5844   /*
  6149   5845   ** Given the name of a database file, compute the name of its conch file.
  6150   5846   ** Store the conch filename in memory obtained from sqlite3_malloc().
  6151   5847   ** Make *pConchPath point to the new name.  Return SQLITE_OK on success
................................................................................
  6194   5890   ** the local lock file path 
  6195   5891   */
  6196   5892   static int switchLockProxyPath(unixFile *pFile, const char *path) {
  6197   5893     proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
  6198   5894     char *oldPath = pCtx->lockProxyPath;
  6199   5895     int rc = SQLITE_OK;
  6200   5896   
  6201         -  if( pFile->locktype!=NO_LOCK ){
         5897  +  if( pFile->eFileLock!=NO_LOCK ){
  6202   5898       return SQLITE_BUSY;
  6203   5899     }  
  6204   5900   
  6205   5901     /* nothing to do if the path is NULL, :auto: or matches the existing path */
  6206   5902     if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
  6207   5903       (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
  6208   5904       return SQLITE_OK;
................................................................................
  6261   5957   */
  6262   5958   static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
  6263   5959     proxyLockingContext *pCtx;
  6264   5960     char dbPath[MAXPATHLEN+1];       /* Name of the database file */
  6265   5961     char *lockPath=NULL;
  6266   5962     int rc = SQLITE_OK;
  6267   5963     
  6268         -  if( pFile->locktype!=NO_LOCK ){
         5964  +  if( pFile->eFileLock!=NO_LOCK ){
  6269   5965       return SQLITE_BUSY;
  6270   5966     }
  6271   5967     proxyGetDbPathForUnixFile(pFile, dbPath);
  6272   5968     if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
  6273   5969       lockPath=NULL;
  6274   5970     }else{
  6275   5971       lockPath=(char *)path;
  6276   5972     }
  6277   5973     
  6278         -  OSTRACE4("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
  6279         -           (lockPath ? lockPath : ":auto:"), getpid());
         5974  +  OSTRACE(("TRANSPROXY  %d for %s pid=%d\n", pFile->h,
         5975  +           (lockPath ? lockPath : ":auto:"), getpid()));
  6280   5976   
  6281   5977     pCtx = sqlite3_malloc( sizeof(*pCtx) );
  6282   5978     if( pCtx==0 ){
  6283   5979       return SQLITE_NOMEM;
  6284   5980     }
  6285   5981     memset(pCtx, 0, sizeof(*pCtx));
  6286   5982   
................................................................................
  6332   6028         pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
  6333   6029         sqlite3_free(pCtx->conchFile);
  6334   6030       }
  6335   6031       sqlite3_free(pCtx->lockProxyPath);
  6336   6032       sqlite3_free(pCtx->conchFilePath); 
  6337   6033       sqlite3_free(pCtx);
  6338   6034     }
  6339         -  OSTRACE3("TRANSPROXY  %d %s\n", pFile->h,
  6340         -           (rc==SQLITE_OK ? "ok" : "failed"));
         6035  +  OSTRACE(("TRANSPROXY  %d %s\n", pFile->h,
         6036  +           (rc==SQLITE_OK ? "ok" : "failed")));
  6341   6037     return rc;
  6342   6038   }
  6343   6039   
  6344   6040   
  6345   6041   /*
  6346   6042   ** This routine handles sqlite3_file_control() calls that are specific
  6347   6043   ** to proxy locking.
................................................................................
  6428   6124         pResOut=0;
  6429   6125       }
  6430   6126     }
  6431   6127     return rc;
  6432   6128   }
  6433   6129   
  6434   6130   /*
  6435         -** Lock the file with the lock specified by parameter locktype - one
         6131  +** Lock the file with the lock specified by parameter eFileLock - one
  6436   6132   ** of the following:
  6437   6133   **
  6438   6134   **     (1) SHARED_LOCK
  6439   6135   **     (2) RESERVED_LOCK
  6440   6136   **     (3) PENDING_LOCK
  6441   6137   **     (4) EXCLUSIVE_LOCK
  6442   6138   **
................................................................................
  6451   6147   **    SHARED -> (PENDING) -> EXCLUSIVE
  6452   6148   **    RESERVED -> (PENDING) -> EXCLUSIVE
  6453   6149   **    PENDING -> EXCLUSIVE
  6454   6150   **
  6455   6151   ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
  6456   6152   ** routine to lower a locking level.
  6457   6153   */
  6458         -static int proxyLock(sqlite3_file *id, int locktype) {
         6154  +static int proxyLock(sqlite3_file *id, int eFileLock) {
  6459   6155     unixFile *pFile = (unixFile*)id;
  6460   6156     int rc = proxyTakeConch(pFile);
  6461   6157     if( rc==SQLITE_OK ){
  6462   6158       proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
  6463   6159       if( pCtx->conchHeld>0 ){
  6464   6160         unixFile *proxy = pCtx->lockProxy;
  6465         -      rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype);
  6466         -      pFile->locktype = proxy->locktype;
         6161  +      rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
         6162  +      pFile->eFileLock = proxy->eFileLock;
  6467   6163       }else{
  6468   6164         /* conchHeld < 0 is lockless */
  6469   6165       }
  6470   6166     }
  6471   6167     return rc;
  6472   6168   }
  6473   6169   
  6474   6170   
  6475   6171   /*
  6476         -** Lower the locking level on file descriptor pFile to locktype.  locktype
         6172  +** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
  6477   6173   ** must be either NO_LOCK or SHARED_LOCK.
  6478   6174   **
  6479   6175   ** If the locking level of the file descriptor is already at or below
  6480   6176   ** the requested locking level, this routine is a no-op.
  6481   6177   */
  6482         -static int proxyUnlock(sqlite3_file *id, int locktype) {
         6178  +static int proxyUnlock(sqlite3_file *id, int eFileLock) {
  6483   6179     unixFile *pFile = (unixFile*)id;
  6484   6180     int rc = proxyTakeConch(pFile);
  6485   6181     if( rc==SQLITE_OK ){
  6486   6182       proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
  6487   6183       if( pCtx->conchHeld>0 ){
  6488   6184         unixFile *proxy = pCtx->lockProxy;
  6489         -      rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype);
  6490         -      pFile->locktype = proxy->locktype;
         6185  +      rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
         6186  +      pFile->eFileLock = proxy->eFileLock;
  6491   6187       }else{
  6492   6188         /* conchHeld < 0 is lockless */
  6493   6189       }
  6494   6190     }
  6495   6191     return rc;
  6496   6192   }
  6497   6193   
................................................................................
  6596   6292       unixDlError,          /* xDlError */                    \
  6597   6293       unixDlSym,            /* xDlSym */                      \
  6598   6294       unixDlClose,          /* xDlClose */                    \
  6599   6295       unixRandomness,       /* xRandomness */                 \
  6600   6296       unixSleep,            /* xSleep */                      \
  6601   6297       unixCurrentTime,      /* xCurrentTime */                \
  6602   6298       unixGetLastError,     /* xGetLastError */               \
  6603         -    unixShmOpen,          /* xShmOpen */                    \
  6604         -    unixShmSize,          /* xShmSize */                    \
  6605         -    unixShmGet,           /* xShmGet */                     \
  6606         -    unixShmRelease,       /* xShmRelease */                 \
  6607         -    unixShmLock,          /* xShmLock */                    \
  6608         -    unixShmClose,         /* xShmClose */                   \
  6609   6299       0,                    /* xRename */                     \
  6610   6300       unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
  6611   6301     }
  6612   6302   
  6613   6303     /*
  6614   6304     ** All default VFSes for unix are contained in the following array.
  6615   6305     **

Changes to src/os_win.c.

    72     72   ** reduced API.
    73     73   */
    74     74   #if SQLITE_OS_WINCE
    75     75   # define AreFileApisANSI() 1
    76     76   # define FormatMessageW(a,b,c,d,e,f,g) 0
    77     77   #endif
    78     78   
           79  +/* Forward references */
           80  +typedef struct winShm winShm;           /* A connection to shared-memory */
           81  +typedef struct winShmNode winShmNode;   /* A region of shared-memory */
           82  +
    79     83   /*
    80     84   ** WinCE lacks native support for file locking so we have to fake it
    81     85   ** with some code of our own.
    82     86   */
    83     87   #if SQLITE_OS_WINCE
    84     88   typedef struct winceLock {
    85     89     int nReaders;       /* Number of reader locks obtained */
................................................................................
    91     95   
    92     96   /*
    93     97   ** The winFile structure is a subclass of sqlite3_file* specific to the win32
    94     98   ** portability layer.
    95     99   */
    96    100   typedef struct winFile winFile;
    97    101   struct winFile {
    98         -  const sqlite3_io_methods *pMethod;/* Must be first */
          102  +  const sqlite3_io_methods *pMethod; /*** Must be first ***/
          103  +  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
    99    104     HANDLE h;               /* Handle for accessing the file */
   100    105     unsigned char locktype; /* Type of lock currently held on this file */
   101    106     short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
   102    107     DWORD lastErrno;        /* The Windows errno from the last I/O error */
   103    108     DWORD sectorSize;       /* Sector size of the device file is on */
          109  +  winShm *pShm;           /* Instance of shared memory on this file */
          110  +  const char *zPath;      /* Full pathname of this file */
   104    111   #if SQLITE_OS_WINCE
   105    112     WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */
   106    113     HANDLE hMutex;          /* Mutex used to control access to shared lock */  
   107    114     HANDLE hShared;         /* Shared memory segment used for locking */
   108    115     winceLock local;        /* Locks obtained by this instance of winFile */
   109    116     winceLock *shared;      /* Global shared lock memory for the file  */
   110    117   #endif
................................................................................
   625    632   */
   626    633   #define MX_CLOSE_ATTEMPT 3
   627    634   static int winClose(sqlite3_file *id){
   628    635     int rc, cnt = 0;
   629    636     winFile *pFile = (winFile*)id;
   630    637   
   631    638     assert( id!=0 );
          639  +  assert( pFile->pShm==0 );
          640  +  OSTRACE(("CLOSE %d\n", pFile->h));
   632    641     do{
   633    642       rc = CloseHandle(pFile->h);
   634    643     }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
   635    644   #if SQLITE_OS_WINCE
   636    645   #define WINCE_DELETION_ATTEMPTS 3
   637    646     winceDestroyLock(pFile);
   638    647     if( pFile->zDeleteOnClose ){
................................................................................
   675    684     DWORD rc;
   676    685     winFile *pFile = (winFile*)id;
   677    686     DWORD error;
   678    687     DWORD got;
   679    688   
   680    689     assert( id!=0 );
   681    690     SimulateIOError(return SQLITE_IOERR_READ);
   682         -  OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype);
          691  +  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
   683    692     rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
   684    693     if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
   685    694       pFile->lastErrno = error;
   686    695       return SQLITE_FULL;
   687    696     }
   688    697     if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){
   689    698       pFile->lastErrno = GetLastError();
................................................................................
   714    723     winFile *pFile = (winFile*)id;
   715    724     DWORD error;
   716    725     DWORD wrote = 0;
   717    726   
   718    727     assert( id!=0 );
   719    728     SimulateIOError(return SQLITE_IOERR_WRITE);
   720    729     SimulateDiskfullError(return SQLITE_FULL);
   721         -  OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype);
          730  +  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
   722    731     rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
   723    732     if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
   724    733       pFile->lastErrno = error;
   725    734       return SQLITE_FULL;
   726    735     }
   727    736     assert( amt>0 );
   728    737     while(
................................................................................
   748    757     LONG lowerBits = (LONG)(nByte & 0xffffffff);
   749    758     DWORD dwRet;
   750    759     winFile *pFile = (winFile*)id;
   751    760     DWORD error;
   752    761     int rc = SQLITE_OK;
   753    762   
   754    763     assert( id!=0 );
          764  +  OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
   755    765     SimulateIOError(return SQLITE_IOERR_TRUNCATE);
   756    766     dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
   757    767     if( dwRet==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
   758    768       pFile->lastErrno = error;
   759    769       rc = SQLITE_IOERR_TRUNCATE;
   760    770     /* SetEndOfFile will fail if nByte is negative */
   761    771     }else if( !SetEndOfFile(pFile->h) ){
................................................................................
   779    789   ** Make sure all writes to a particular file are committed to disk.
   780    790   */
   781    791   static int winSync(sqlite3_file *id, int flags){
   782    792   #ifndef SQLITE_NO_SYNC
   783    793     winFile *pFile = (winFile*)id;
   784    794   
   785    795     assert( id!=0 );
   786         -  OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype);
          796  +  OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
   787    797   #else
   788    798     UNUSED_PARAMETER(id);
   789    799   #endif
   790    800   #ifndef SQLITE_TEST
   791    801     UNUSED_PARAMETER(flags);
   792    802   #else
   793    803     if( flags & SQLITE_SYNC_FULL ){
................................................................................
   951    961            && (pFile->locktype==RESERVED_LOCK))
   952    962     ){
   953    963       int cnt = 3;
   954    964       while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
   955    965         /* Try 3 times to get the pending lock.  The pending lock might be
   956    966         ** held by another reader process who will release it momentarily.
   957    967         */
   958         -      OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
          968  +      OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
   959    969         Sleep(1);
   960    970       }
   961    971       gotPendingLock = res;
   962    972       if( !res ){
   963    973         error = GetLastError();
   964    974       }
   965    975     }
................................................................................
   996   1006     }
   997   1007   
   998   1008     /* Acquire an EXCLUSIVE lock
   999   1009     */
  1000   1010     if( locktype==EXCLUSIVE_LOCK && res ){
  1001   1011       assert( pFile->locktype>=SHARED_LOCK );
  1002   1012       res = unlockReadLock(pFile);
  1003         -    OSTRACE2("unreadlock = %d\n", res);
         1013  +    OSTRACE(("unreadlock = %d\n", res));
  1004   1014       res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  1005   1015       if( res ){
  1006   1016         newLocktype = EXCLUSIVE_LOCK;
  1007   1017       }else{
  1008   1018         error = GetLastError();
  1009         -      OSTRACE2("error-code = %d\n", error);
         1019  +      OSTRACE(("error-code = %d\n", error));
  1010   1020         getReadLock(pFile);
  1011   1021       }
  1012   1022     }
  1013   1023   
  1014   1024     /* If we are holding a PENDING lock that ought to be released, then
  1015   1025     ** release it now.
  1016   1026     */
................................................................................
  1020   1030   
  1021   1031     /* Update the state of the lock has held in the file descriptor then
  1022   1032     ** return the appropriate result code.
  1023   1033     */
  1024   1034     if( res ){
  1025   1035       rc = SQLITE_OK;
  1026   1036     }else{
  1027         -    OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
  1028         -           locktype, newLocktype);
         1037  +    OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
         1038  +           locktype, newLocktype));
  1029   1039       pFile->lastErrno = error;
  1030   1040       rc = SQLITE_BUSY;
  1031   1041     }
  1032   1042     pFile->locktype = (u8)newLocktype;
  1033   1043     return rc;
  1034   1044   }
  1035   1045   
................................................................................
  1041   1051   static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
  1042   1052     int rc;
  1043   1053     winFile *pFile = (winFile*)id;
  1044   1054   
  1045   1055     assert( id!=0 );
  1046   1056     if( pFile->locktype>=RESERVED_LOCK ){
  1047   1057       rc = 1;
  1048         -    OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
         1058  +    OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
  1049   1059     }else{
  1050   1060       rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
  1051   1061       if( rc ){
  1052   1062         UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
  1053   1063       }
  1054   1064       rc = !rc;
  1055         -    OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
         1065  +    OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
  1056   1066     }
  1057   1067     *pResOut = rc;
  1058   1068     return SQLITE_OK;
  1059   1069   }
  1060   1070   
  1061   1071   /*
  1062   1072   ** Lower the locking level on file descriptor id to locktype.  locktype
................................................................................
  1071   1081   */
  1072   1082   static int winUnlock(sqlite3_file *id, int locktype){
  1073   1083     int type;
  1074   1084     winFile *pFile = (winFile*)id;
  1075   1085     int rc = SQLITE_OK;
  1076   1086     assert( pFile!=0 );
  1077   1087     assert( locktype<=SHARED_LOCK );
  1078         -  OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
  1079         -          pFile->locktype, pFile->sharedLockByte);
         1088  +  OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
         1089  +          pFile->locktype, pFile->sharedLockByte));
  1080   1090     type = pFile->locktype;
  1081   1091     if( type>=EXCLUSIVE_LOCK ){
  1082   1092       UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  1083   1093       if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
  1084   1094         /* This should never happen.  We should always be able to
  1085   1095         ** reacquire the read lock */
  1086   1096         rc = SQLITE_IOERR_UNLOCK;
................................................................................
  1135   1145   ** Return a vector of device characteristics.
  1136   1146   */
  1137   1147   static int winDeviceCharacteristics(sqlite3_file *id){
  1138   1148     UNUSED_PARAMETER(id);
  1139   1149     return 0;
  1140   1150   }
  1141   1151   
         1152  +/****************************************************************************
         1153  +********************************* Shared Memory *****************************
         1154  +**
         1155  +** The next subdivision of code manages the shared-memory primitives.
         1156  +*/
         1157  +#ifndef SQLITE_OMIT_WAL
         1158  +
         1159  +/*
         1160  +** Helper functions to obtain and relinquish the global mutex. The
         1161  +** global mutex is used to protect the winLockInfo objects used by 
         1162  +** this file, all of which may be shared by multiple threads.
         1163  +**
         1164  +** Function winShmMutexHeld() is used to assert() that the global mutex 
         1165  +** is held when required. This function is only used as part of assert() 
         1166  +** statements. e.g.
         1167  +**
         1168  +**   winShmEnterMutex()
         1169  +**     assert( winShmMutexHeld() );
         1170  +**   winEnterLeave()
         1171  +*/
         1172  +static void winShmEnterMutex(void){
         1173  +  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
         1174  +}
         1175  +static void winShmLeaveMutex(void){
         1176  +  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
         1177  +}
         1178  +#ifdef SQLITE_DEBUG
         1179  +static int winShmMutexHeld(void) {
         1180  +  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
         1181  +}
         1182  +#endif
         1183  +
         1184  +/*
         1185  +** Object used to represent a single file opened and mmapped to provide
         1186  +** shared memory.  When multiple threads all reference the same
         1187  +** log-summary, each thread has its own winFile object, but they all
         1188  +** point to a single instance of this object.  In other words, each
         1189  +** log-summary is opened only once per process.
         1190  +**
         1191  +** winShmMutexHeld() must be true when creating or destroying
         1192  +** this object or while reading or writing the following fields:
         1193  +**
         1194  +**      nRef
         1195  +**      pNext 
         1196  +**
         1197  +** The following fields are read-only after the object is created:
         1198  +** 
         1199  +**      fid
         1200  +**      zFilename
         1201  +**
         1202  +** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
         1203  +** winShmMutexHeld() is true when reading or writing any other field
         1204  +** in this structure.
         1205  +**
         1206  +** To avoid deadlocks, mutex and mutexBuf are always released in the
         1207  +** reverse order that they are acquired.  mutexBuf is always acquired
         1208  +** first and released last.  This invariant is check by asserting
         1209  +** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
         1210  +** released.
         1211  +*/
         1212  +struct winShmNode {
         1213  +  sqlite3_mutex *mutex;      /* Mutex to access this object */
         1214  +  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
         1215  +  char *zFilename;           /* Name of the file */
         1216  +  winFile hFile;             /* File handle from winOpen */
         1217  +  HANDLE hMap;               /* File handle from CreateFileMapping */
         1218  +  DWORD lastErrno;           /* The Windows errno from the last I/O error */
         1219  +  int szMap;                 /* Size of the mapping of file into memory */
         1220  +  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
         1221  +  int nRef;                  /* Number of winShm objects pointing to this */
         1222  +  winShm *pFirst;            /* All winShm objects pointing to this */
         1223  +  winShmNode *pNext;         /* Next in list of all winShmNode objects */
         1224  +#ifdef SQLITE_DEBUG
         1225  +  u8 exclMask;               /* Mask of exclusive locks held */
         1226  +  u8 sharedMask;             /* Mask of shared locks held */
         1227  +  u8 nextShmId;              /* Next available winShm.id value */
         1228  +#endif
         1229  +};
         1230  +
         1231  +/*
         1232  +** A global array of all winShmNode objects.
         1233  +**
         1234  +** The winShmMutexHeld() must be true while reading or writing this list.
         1235  +*/
         1236  +static winShmNode *winShmNodeList = 0;
         1237  +
         1238  +/*
         1239  +** Structure used internally by this VFS to record the state of an
         1240  +** open shared memory connection.
         1241  +**
         1242  +** winShm.pFile->mutex must be held while reading or writing the
         1243  +** winShm.pNext and winShm.locks[] elements.
         1244  +**
         1245  +** The winShm.pFile element is initialized when the object is created
         1246  +** and is read-only thereafter.
         1247  +*/
         1248  +struct winShm {
         1249  +  winShmNode *pShmNode;      /* The underlying winShmNode object */
         1250  +  winShm *pNext;             /* Next winShm with the same winShmNode */
         1251  +  u8 lockState;              /* Current lock state */
         1252  +  u8 hasMutex;               /* True if holding the winShmNode mutex */
         1253  +  u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
         1254  +  u8 sharedMask;             /* Mask of shared locks held */
         1255  +  u8 exclMask;               /* Mask of exclusive locks held */
         1256  +#ifdef SQLITE_DEBUG
         1257  +  u8 id;                     /* Id of this connection with its winShmNode */
         1258  +#endif
         1259  +};
         1260  +
         1261  +/*
         1262  +** Size increment by which shared memory grows
         1263  +*/
         1264  +#define SQLITE_WIN_SHM_INCR  4096
         1265  +
         1266  +/*
         1267  +** Constants used for locking
         1268  +*/
         1269  +#define WIN_SHM_BASE      32        /* Byte offset of the first lock byte */
         1270  +#define WIN_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
         1271  +#define WIN_SHM_A         0x10      /* Mask for region locks... */
         1272  +#define WIN_SHM_B         0x20
         1273  +#define WIN_SHM_C         0x40
         1274  +#define WIN_SHM_D         0x80
         1275  +
         1276  +#ifdef SQLITE_DEBUG
         1277  +/*
         1278  +** Return a pointer to a nul-terminated string in static memory that
         1279  +** describes a locking mask.  The string is of the form "MSABCD" with
         1280  +** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
         1281  +** and "A" through "D" for the region locks.  If a lock is held, the
         1282  +** letter is shown.  If the lock is not held, the letter is converted
         1283  +** to ".".
         1284  +**
         1285  +** This routine is for debugging purposes only and does not appear
         1286  +** in a production build.
         1287  +*/
         1288  +static const char *winShmLockString(u8 mask){
         1289  +  static char zBuf[48];
         1290  +  static int iBuf = 0;
         1291  +  char *z;
         1292  +
         1293  +  z = &zBuf[iBuf];
         1294  +  iBuf += 8;
         1295  +  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
         1296  +
         1297  +  z[0] = (mask & WIN_SHM_DMS)   ? 'S' : '.';
         1298  +  z[1] = (mask & WIN_SHM_A)     ? 'A' : '.';
         1299  +  z[2] = (mask & WIN_SHM_B)     ? 'B' : '.';
         1300  +  z[3] = (mask & WIN_SHM_C)     ? 'C' : '.';
         1301  +  z[4] = (mask & WIN_SHM_D)     ? 'D' : '.';
         1302  +  z[5] = 0;
         1303  +  return z;
         1304  +}
         1305  +#endif /* SQLITE_DEBUG */
         1306  +
         1307  +/*
         1308  +** Apply posix advisory locks for all bytes identified in lockMask.
         1309  +**
         1310  +** lockMask might contain multiple bits but all bits are guaranteed
         1311  +** to be contiguous.
         1312  +**
         1313  +** Locks block if the mask is exactly WIN_SHM_C and are non-blocking
         1314  +** otherwise.
         1315  +*/
         1316  +#define _SHM_UNLCK  1
         1317  +#define _SHM_RDLCK  2
         1318  +#define _SHM_WRLCK  3
         1319  +static int winShmSystemLock(
         1320  +  winShmNode *pFile,    /* Apply locks to this open shared-memory segment */
         1321  +  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
         1322  +  u8 lockMask           /* Which bytes to lock or unlock */
         1323  +){
         1324  +  OVERLAPPED ovlp;
         1325  +  DWORD dwFlags;
         1326  +  int nBytes;           /* Number of bytes to lock */
         1327  +  int i;                /* Offset into the locking byte range */
         1328  +  int rc = 0;           /* Result code form Lock/UnlockFileEx() */
         1329  +  u8 mask;              /* Mask of bits in lockMask */
         1330  +
         1331  +  /* Access to the winShmNode object is serialized by the caller */
         1332  +  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
         1333  +
         1334  +  /* Initialize the locking parameters */
         1335  +  if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
         1336  +    dwFlags = 0;
         1337  +    OSTRACE(("SHM-LOCK %d requesting blocking lock %s\n", 
         1338  +             pFile->hFile.h,
         1339  +             winShmLockString(lockMask)));
         1340  +  }else{
         1341  +    dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
         1342  +    OSTRACE(("SHM-LOCK %d requesting %s %s\n", 
         1343  +             pFile->hFile.h,
         1344  +             lockType!=_SHM_UNLCK ? "lock" : "unlock", 
         1345  +             winShmLockString(lockMask)));
         1346  +  }
         1347  +  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
         1348  +
         1349  +  /* Find the first bit in lockMask that is set */
         1350  +  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
         1351  +  assert( mask!=0 );
         1352  +  memset(&ovlp, 0, sizeof(OVERLAPPED));
         1353  +  ovlp.Offset = i+WIN_SHM_BASE;
         1354  +  nBytes = 1;
         1355  +
         1356  +  /* Extend the locking range for each additional bit that is set */
         1357  +  mask <<= 1;
         1358  +  while( mask!=0 && (lockMask & mask)!=0 ){
         1359  +    nBytes++;
         1360  +    mask <<= 1;
         1361  +  }
         1362  +
         1363  +  /* Verify that all bits set in lockMask are contiguous */
         1364  +  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
         1365  +
         1366  +  /* Release/Acquire the system-level lock */
         1367  +  if( lockType==_SHM_UNLCK ){
         1368  +    for(i=0; i<nBytes; i++, ovlp.Offset++){
         1369  +      rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
         1370  +      if( !rc ) break;
         1371  +    }
         1372  +  }else{
         1373  +    /* release old individual byte locks (if any)
         1374  +    ** and set new individual byte locks */
         1375  +    for(i=0; i<nBytes; i++, ovlp.Offset++){
         1376  +      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
         1377  +      rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
         1378  +      if( !rc ) break;
         1379  +    }
         1380  +  }
         1381  +  if( !rc ){
         1382  +    OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n", 
         1383  +             pFile->hFile.h,
         1384  +             lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
         1385  +             GetLastError()));
         1386  +    /* release individual byte locks (if any) */
         1387  +    ovlp.Offset-=i;
         1388  +    for(i=0; i<nBytes; i++, ovlp.Offset++){
         1389  +      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
         1390  +    }
         1391  +  }
         1392  +  rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
         1393  +
         1394  +  /* Update the global lock state and do debug tracing */
         1395  +#ifdef SQLITE_DEBUG
         1396  +  OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
         1397  +  if( rc==SQLITE_OK ){
         1398  +    if( lockType==_SHM_UNLCK ){
         1399  +      OSTRACE(("unlock ok"));
         1400  +      pFile->exclMask &= ~lockMask;
         1401  +      pFile->sharedMask &= ~lockMask;
         1402  +    }else if( lockType==_SHM_RDLCK ){
         1403  +      OSTRACE(("read-lock ok"));
         1404  +      pFile->exclMask &= ~lockMask;
         1405  +      pFile->sharedMask |= lockMask;
         1406  +    }else{
         1407  +      assert( lockType==_SHM_WRLCK );
         1408  +      OSTRACE(("write-lock ok"));
         1409  +      pFile->exclMask |= lockMask;
         1410  +      pFile->sharedMask &= ~lockMask;
         1411  +    }
         1412  +  }else{
         1413  +    if( lockType==_SHM_UNLCK ){
         1414  +      OSTRACE(("unlock failed"));
         1415  +    }else if( lockType==_SHM_RDLCK ){
         1416  +      OSTRACE(("read-lock failed"));
         1417  +    }else{
         1418  +      assert( lockType==_SHM_WRLCK );
         1419  +      OSTRACE(("write-lock failed"));
         1420  +    }
         1421  +  }
         1422  +  OSTRACE((" - change requested %s - afterwards %s:%s\n",
         1423  +           winShmLockString(lockMask),
         1424  +           winShmLockString(pFile->sharedMask),
         1425  +           winShmLockString(pFile->exclMask)));
         1426  +#endif
         1427  +
         1428  +  return rc;
         1429  +}
         1430  +
         1431  +/*
         1432  +** For connection p, unlock all of the locks identified by the unlockMask
         1433  +** parameter.
         1434  +*/
         1435  +static int winShmUnlock(
         1436  +  winShmNode *pFile,   /* The underlying shared-memory file */
         1437  +  winShm *p,           /* The connection to be unlocked */
         1438  +  u8 unlockMask         /* Mask of locks to be unlocked */
         1439  +){
         1440  +  int rc;      /* Result code */
         1441  +  winShm *pX; /* For looping over all sibling connections */
         1442  +  u8 allMask;  /* Union of locks held by connections other than "p" */
         1443  +
         1444  +  /* Access to the winShmNode object is serialized by the caller */
         1445  +  assert( sqlite3_mutex_held(pFile->mutex) );
         1446  +
         1447  +  /* don't attempt to unlock anything we don't have locks for */
         1448  +  if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
         1449  +    OSTRACE(("SHM-LOCK %d unlocking more than we have locked - requested %s - have %s\n",
         1450  +             pFile->hFile.h,
         1451  +             winShmLockString(unlockMask),
         1452  +             winShmLockString(p->exclMask|p->sharedMask)));
         1453  +    unlockMask &= (p->exclMask|p->sharedMask);
         1454  +  }
         1455  +
         1456  +  /* Compute locks held by sibling connections */
         1457  +  allMask = 0;
         1458  +  for(pX=pFile->pFirst; pX; pX=pX->pNext){
         1459  +    if( pX==p ) continue;
         1460  +    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
         1461  +    allMask |= pX->sharedMask;
         1462  +  }
         1463  +
         1464  +  /* Unlock the system-level locks */
         1465  +  if( (unlockMask & allMask)!=unlockMask ){
         1466  +    rc = winShmSystemLock(pFile, _SHM_UNLCK, unlockMask & ~allMask);
         1467  +  }else{
         1468  +    rc = SQLITE_OK;
         1469  +  }
         1470  +
         1471  +  /* Undo the local locks */
         1472  +  if( rc==SQLITE_OK ){
         1473  +    p->exclMask &= ~unlockMask;
         1474  +    p->sharedMask &= ~unlockMask;
         1475  +  } 
         1476  +  return rc;
         1477  +}
         1478  +
         1479  +/*
         1480  +** Get reader locks for connection p on all locks in the readMask parameter.
         1481  +*/
         1482  +static int winShmSharedLock(
         1483  +  winShmNode *pFile,   /* The underlying shared-memory file */
         1484  +  winShm *p,           /* The connection to get the shared locks */
         1485  +  u8 readMask           /* Mask of shared locks to be acquired */
         1486  +){
         1487  +  int rc;        /* Result code */
         1488  +  winShm *pX;   /* For looping over all sibling connections */
         1489  +  u8 allShared;  /* Union of locks held by connections other than "p" */
         1490  +
         1491  +  /* Access to the winShmNode object is serialized by the caller */
         1492  +  assert( sqlite3_mutex_held(pFile->mutex) );
         1493  +
         1494  +  /* Find out which shared locks are already held by sibling connections.
         1495  +  ** If any sibling already holds an exclusive lock, go ahead and return
         1496  +  ** SQLITE_BUSY.
         1497  +  */
         1498  +  allShared = 0;
         1499  +  for(pX=pFile->pFirst; pX; pX=pX->pNext){
         1500  +    if( pX==p ) continue;
         1501  +    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
         1502  +    allShared |= pX->sharedMask;
         1503  +  }
         1504  +
         1505  +  /* Get shared locks at the system level, if necessary */
         1506  +  if( (~allShared) & readMask ){
         1507  +    rc = winShmSystemLock(pFile, _SHM_RDLCK, readMask);
         1508  +  }else{
         1509  +    rc = SQLITE_OK;
         1510  +  }
         1511  +
         1512  +  /* Get the local shared locks */
         1513  +  if( rc==SQLITE_OK ){
         1514  +    p->sharedMask |= readMask;
         1515  +  }
         1516  +  return rc;
         1517  +}
         1518  +
         1519  +/*
         1520  +** For connection p, get an exclusive lock on all locks identified in
         1521  +** the writeMask parameter.
         1522  +*/
         1523  +static int winShmExclusiveLock(
         1524  +  winShmNode *pFile,    /* The underlying shared-memory file */
         1525  +  winShm *p,            /* The connection to get the exclusive locks */
         1526  +  u8 writeMask           /* Mask of exclusive locks to be acquired */
         1527  +){
         1528  +  int rc;        /* Result code */
         1529  +  winShm *pX;   /* For looping over all sibling connections */
         1530  +
         1531  +  /* Access to the winShmNode object is serialized by the caller */
         1532  +  assert( sqlite3_mutex_held(pFile->mutex) );
         1533  +
         1534  +  /* Make sure no sibling connections hold locks that will block this
         1535  +  ** lock.  If any do, return SQLITE_BUSY right away.
         1536  +  */
         1537  +  for(pX=pFile->pFirst; pX; pX=pX->pNext){
         1538  +    if( pX==p ) continue;
         1539  +    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
         1540  +    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
         1541  +  }
         1542  +
         1543  +  /* Get the exclusive locks at the system level.  Then if successful
         1544  +  ** also mark the local connection as being locked.
         1545  +  */
         1546  +  rc = winShmSystemLock(pFile, _SHM_WRLCK, writeMask);
         1547  +  if( rc==SQLITE_OK ){
         1548  +    p->sharedMask &= ~writeMask;
         1549  +    p->exclMask |= writeMask;
         1550  +  }
         1551  +  return rc;
         1552  +}
         1553  +
         1554  +/*
         1555  +** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
         1556  +**
         1557  +** This is not a VFS shared-memory method; it is a utility function called
         1558  +** by VFS shared-memory methods.
         1559  +*/
         1560  +static void winShmPurge(void){
         1561  +  winShmNode **pp;
         1562  +  winShmNode *p;
         1563  +  assert( winShmMutexHeld() );
         1564  +  pp = &winShmNodeList;
         1565  +  while( (p = *pp)!=0 ){
         1566  +    if( p->nRef==0 ){
         1567  +      if( p->mutex ) sqlite3_mutex_free(p->mutex);
         1568  +      if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
         1569  +      if( p->pMMapBuf ){
         1570  +        UnmapViewOfFile(p->pMMapBuf);
         1571  +      }
         1572  +      if( INVALID_HANDLE_VALUE != p->hMap ){
         1573  +        CloseHandle(p->hMap);
         1574  +      }
         1575  +      if( p->hFile.h != INVALID_HANDLE_VALUE ) {
         1576  +        winClose((sqlite3_file *)&p->hFile);
         1577  +      }
         1578  +      *pp = p->pNext;
         1579  +      sqlite3_free(p);
         1580  +    }else{
         1581  +      pp = &p->pNext;
         1582  +    }
         1583  +  }
         1584  +}
         1585  +
         1586  +/* Forward references to VFS methods */
         1587  +static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
         1588  +static int winDelete(sqlite3_vfs *,const char*,int);
         1589  +
         1590  +/*
         1591  +** Open a shared-memory area.  This particular implementation uses
         1592  +** mmapped files.
         1593  +**
         1594  +** zName is a filename used to identify the shared-memory area.  The
         1595  +** implementation does not (and perhaps should not) use this name
         1596  +** directly, but rather use it as a template for finding an appropriate
         1597  +** name for the shared-memory storage.  In this implementation, the
         1598  +** string "-index" is appended to zName and used as the name of the
         1599  +** mmapped file.
         1600  +**
         1601  +** When opening a new shared-memory file, if no other instances of that
         1602  +** file are currently open, in this process or in other processes, then
         1603  +** the file must be truncated to zero length or have its header cleared.
         1604  +*/
         1605  +static int winShmOpen(
         1606  +  sqlite3_file *fd      /* The file to which to attach shared memory */
         1607  +){
         1608  +  struct winFile *pDbFd;             /* Database to which to attach SHM */
         1609  +  struct winShm *p;                  /* The connection to be opened */
         1610  +  struct winShmNode *pShmNode = 0;   /* The underlying mmapped file */
         1611  +  int rc;                            /* Result code */
         1612  +  struct winShmNode *pNew;           /* Newly allocated winShmNode */
         1613  +  int nName;                         /* Size of zName in bytes */
         1614  +
         1615  +  pDbFd = (winFile*)fd;
         1616  +  assert( pDbFd->pShm==0 );    /* Not previously opened */
         1617  +
         1618  +  /* Allocate space for the new sqlite3_shm object.  Also speculatively
         1619  +  ** allocate space for a new winShmNode and filename.
         1620  +  */
         1621  +  p = sqlite3_malloc( sizeof(*p) );
         1622  +  if( p==0 ) return SQLITE_NOMEM;
         1623  +  memset(p, 0, sizeof(*p));
         1624  +  nName = sqlite3Strlen30(pDbFd->zPath);
         1625  +  pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 15 );
         1626  +  if( pNew==0 ){
         1627  +    sqlite3_free(p);
         1628  +    return SQLITE_NOMEM;
         1629  +  }
         1630  +  memset(pNew, 0, sizeof(*pNew));
         1631  +  pNew->zFilename = (char*)&pNew[1];
         1632  +  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-wal-index", pDbFd->zPath);
         1633  +
         1634  +  /* Look to see if there is an existing winShmNode that can be used.
         1635  +  ** If no matching winShmNode currently exists, create a new one.
         1636  +  */
         1637  +  winShmEnterMutex();
         1638  +  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
         1639  +    /* TBD need to come up with better match here.  Perhaps
         1640  +    ** use FILE_ID_BOTH_DIR_INFO Structure.
         1641  +    */
         1642  +    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
         1643  +  }
         1644  +  if( pShmNode ){
         1645  +    sqlite3_free(pNew);
         1646  +  }else{
         1647  +    pShmNode = pNew;
         1648  +    pNew = 0;
         1649  +    pShmNode->pMMapBuf = NULL;
         1650  +    pShmNode->hMap = INVALID_HANDLE_VALUE;
         1651  +    ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
         1652  +    pShmNode->pNext = winShmNodeList;
         1653  +    winShmNodeList = pShmNode;
         1654  +
         1655  +    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
         1656  +    if( pShmNode->mutex==0 ){
         1657  +      rc = SQLITE_NOMEM;
         1658  +      goto shm_open_err;
         1659  +    }
         1660  +    pShmNode->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
         1661  +    if( pShmNode->mutexBuf==0 ){
         1662  +      rc = SQLITE_NOMEM;
         1663  +      goto shm_open_err;
         1664  +    }
         1665  +    rc = winOpen(pDbFd->pVfs,
         1666  +                 pShmNode->zFilename,             /* Name of the file (UTF-8) */
         1667  +                 (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
         1668  +                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
         1669  +                 0);
         1670  +    if( SQLITE_OK!=rc ){
         1671  +      rc = SQLITE_CANTOPEN_BKPT;
         1672  +      goto shm_open_err;
         1673  +    }
         1674  +
         1675  +    /* Check to see if another process is holding the dead-man switch.
         1676  +    ** If not, truncate the file to zero length. 
         1677  +    */
         1678  +    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS)==SQLITE_OK ){
         1679  +      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
         1680  +    }
         1681  +    if( rc==SQLITE_OK ){
         1682  +      rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS);
         1683  +    }
         1684  +    if( rc ) goto shm_open_err;
         1685  +  }
         1686  +
         1687  +  /* Make the new connection a child of the winShmNode */
         1688  +  p->pShmNode = pShmNode;
         1689  +  p->pNext = pShmNode->pFirst;
         1690  +#ifdef SQLITE_DEBUG
         1691  +  p->id = pShmNode->nextShmId++;
         1692  +#endif
         1693  +  pShmNode->pFirst = p;
         1694  +  pShmNode->nRef++;
         1695  +  pDbFd->pShm = p;
         1696  +  winShmLeaveMutex();
         1697  +  return SQLITE_OK;
         1698  +
         1699  +  /* Jump here on any error */
         1700  +shm_open_err:
         1701  +  winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS);
         1702  +  winShmPurge();                 /* This call frees pShmNode if required */
         1703  +  sqlite3_free(p);
         1704  +  sqlite3_free(pNew);
         1705  +  winShmLeaveMutex();
         1706  +  return rc;
         1707  +}
         1708  +
         1709  +/*
         1710  +** Close a connection to shared-memory.  Delete the underlying 
         1711  +** storage if deleteFlag is true.
         1712  +*/
         1713  +static int winShmClose(
         1714  +  sqlite3_file *fd,          /* Database holding shared memory */
         1715  +  int deleteFlag             /* Delete after closing if true */
         1716  +){
         1717  +  winFile *pDbFd;       /* Database holding shared-memory */
         1718  +  winShm *p;            /* The connection to be closed */
         1719  +  winShmNode *pShmNode; /* The underlying shared-memory file */
         1720  +  winShm **pp;          /* For looping over sibling connections */
         1721  +
         1722  +  pDbFd = (winFile*)fd;
         1723  +  p = pDbFd->pShm;
         1724  +  pShmNode = p->pShmNode;
         1725  +
         1726  +  /* Verify that the connection being closed holds no locks */
         1727  +  assert( p->exclMask==0 );
         1728  +  assert( p->sharedMask==0 );
         1729  +
         1730  +  /* Remove connection p from the set of connections associated
         1731  +  ** with pShmNode */
         1732  +  sqlite3_mutex_enter(pShmNode->mutex);
         1733  +  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
         1734  +  *pp = p->pNext;
         1735  +
         1736  +  /* Free the connection p */
         1737  +  sqlite3_free(p);
         1738  +  pDbFd->pShm = 0;
         1739  +  sqlite3_mutex_leave(pShmNode->mutex);
         1740  +
         1741  +  /* If pShmNode->nRef has reached 0, then close the underlying
         1742  +  ** shared-memory file, too */
         1743  +  winShmEnterMutex();
         1744  +  assert( pShmNode->nRef>0 );
         1745  +  pShmNode->nRef--;
         1746  +  if( pShmNode->nRef==0 ){
         1747  +    if( deleteFlag ) winDelete(pDbFd->pVfs, pShmNode->zFilename, 0);
         1748  +    winShmPurge();
         1749  +  }
         1750  +  winShmLeaveMutex();
         1751  +
         1752  +  return SQLITE_OK;
         1753  +}
         1754  +
         1755  +/*
         1756  +** Query and/or changes the size of the underlying storage for
         1757  +** a shared-memory segment.  The reqSize parameter is the new size
         1758  +** of the underlying storage, or -1 to do just a query.  The size
         1759  +** of the underlying storage (after resizing if resizing occurs) is
         1760  +** written into pNewSize.
         1761  +**
         1762  +** This routine does not (necessarily) change the size of the mapping 
         1763  +** of the underlying storage into memory.  Use xShmGet() to change
         1764  +** the mapping size.
         1765  +**
         1766  +** The reqSize parameter is the minimum size requested.  The implementation
         1767  +** is free to expand the storage to some larger amount if it chooses.
         1768  +*/
         1769  +static int winShmSize(
         1770  +  sqlite3_file *fd,         /* Database holding the shared memory */
         1771  +  int reqSize,              /* Requested size.  -1 for query only */
         1772  +  int *pNewSize             /* Write new size here */
         1773  +){
         1774  +  winFile *pDbFd = (winFile*)fd;
         1775  +  winShm *p = pDbFd->pShm;
         1776  +  winShmNode *pShmNode = p->pShmNode;
         1777  +  int rc = SQLITE_OK;
         1778  +
         1779  +  *pNewSize = 0;
         1780  +  if( reqSize>=0 ){
         1781  +    sqlite3_int64 sz;
         1782  +    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
         1783  +    if( SQLITE_OK==rc ){
         1784  +      reqSize = (reqSize + SQLITE_WIN_SHM_INCR - 1)/SQLITE_WIN_SHM_INCR;
         1785  +      reqSize *= SQLITE_WIN_SHM_INCR;
         1786  +      if( reqSize>sz ){
         1787  +        rc = winTruncate((sqlite3_file *)&pShmNode->hFile, reqSize);
         1788  +      }
         1789  +    }
         1790  +  }
         1791  +  if( SQLITE_OK==rc ){
         1792  +    sqlite3_int64 sz;
         1793  +    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
         1794  +    if( SQLITE_OK==rc ){
         1795  +      *pNewSize = (int)sz;
         1796  +    }else{
         1797  +      rc = SQLITE_IOERR;
         1798  +    }
         1799  +  }
         1800  +  return rc;
         1801  +}
         1802  +
         1803  +
         1804  +/*
         1805  +** Map the shared storage into memory.  The minimum size of the
         1806  +** mapping should be reqMapSize if reqMapSize is positive.  If
         1807  +** reqMapSize is zero or negative, the implementation can choose
         1808  +** whatever mapping size is convenient.
         1809  +**
         1810  +** *ppBuf is made to point to the memory which is a mapping of the
         1811  +** underlying storage.  A mutex is acquired to prevent other threads
         1812  +** from running while *ppBuf is in use in order to prevent other threads
         1813  +** remapping *ppBuf out from under this thread.  The winShmRelease()
         1814  +** call will release the mutex.  However, if the lock state is CHECKPOINT,
         1815  +** the mutex is not acquired because CHECKPOINT will never remap the
         1816  +** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
         1817  +** the mutex if and when it promotes to RECOVER.
         1818  +**
         1819  +** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
         1820  +** being remapped also prevents more than one thread from being in
         1821  +** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
         1822  +** To prevent RECOVER from losing its lock while remapping, the
         1823  +** mutex is not released by winShmRelease() when in RECOVER.
         1824  +**
         1825  +** *pNewMapSize is set to the size of the mapping.
         1826  +**
         1827  +** *ppBuf and *pNewMapSize might be NULL and zero if no space has
         1828  +** yet been allocated to the underlying storage.
         1829  +*/
         1830  +static int winShmGet(
         1831  +  sqlite3_file *fd,        /* The database file holding the shared memory */
         1832  +  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
         1833  +  int *pNewMapSize,        /* Write new size of mapping here */
         1834  +  void **ppBuf             /* Write mapping buffer origin here */
         1835  +){
         1836  +  winFile *pDbFd = (winFile*)fd;
         1837  +  winShm *p = pDbFd->pShm;
         1838  +  winShmNode *pShmNode = p->pShmNode;
         1839  +  int rc = SQLITE_OK;
         1840  +
         1841  +  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
         1842  +    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
         1843  +    sqlite3_mutex_enter(pShmNode->mutexBuf);
         1844  +    p->hasMutexBuf = 1;
         1845  +  }
         1846  +  sqlite3_mutex_enter(pShmNode->mutex);
         1847  +  if( pShmNode->szMap==0 || reqMapSize>pShmNode->szMap ){
         1848  +    int actualSize;
         1849  +    if( winShmSize(fd, -1, &actualSize)==SQLITE_OK
         1850  +     && reqMapSize<actualSize
         1851  +    ){
         1852  +      reqMapSize = actualSize;
         1853  +    }
         1854  +    if( pShmNode->pMMapBuf ){
         1855  +      if( !UnmapViewOfFile(pShmNode->pMMapBuf) ){
         1856  +        pShmNode->lastErrno = GetLastError();
         1857  +        rc = SQLITE_IOERR;
         1858  +      }
         1859  +      CloseHandle(pShmNode->hMap);
         1860  +      pShmNode->hMap = INVALID_HANDLE_VALUE;
         1861  +    }
         1862  +    if( SQLITE_OK == rc ){
         1863  +      pShmNode->pMMapBuf = 0;
         1864  +      if( reqMapSize == 0 ){
         1865  +        /* can't create 0 byte file mapping in Windows */
         1866  +        pShmNode->szMap = 0;
         1867  +      }else{
         1868  +        /* create the file mapping object */
         1869  +        if( INVALID_HANDLE_VALUE == pShmNode->hMap ){
         1870  +          /* TBD provide an object name to each file
         1871  +          ** mapping so it can be re-used across processes.
         1872  +          */
         1873  +          pShmNode->hMap = CreateFileMapping(pShmNode->hFile.h,
         1874  +                                          NULL,
         1875  +                                          PAGE_READWRITE,
         1876  +                                          0,
         1877  +                                          reqMapSize,
         1878  +                                          NULL);
         1879  +        }
         1880  +        if( NULL==pShmNode->hMap ){
         1881  +          pShmNode->lastErrno = GetLastError();
         1882  +          rc = SQLITE_IOERR;
         1883  +          pShmNode->szMap = 0;
         1884  +          pShmNode->hMap = INVALID_HANDLE_VALUE;
         1885  +        }else{
         1886  +          pShmNode->pMMapBuf = MapViewOfFile(pShmNode->hMap,
         1887  +                                          FILE_MAP_WRITE | FILE_MAP_READ,
         1888  +                                          0,
         1889  +                                          0,
         1890  +                                          reqMapSize);
         1891  +          if( !pShmNode->pMMapBuf ){
         1892  +            pShmNode->lastErrno = GetLastError();
         1893  +            rc = SQLITE_IOERR;
         1894  +            pShmNode->szMap = 0;
         1895  +          }else{
         1896  +            pShmNode->szMap = reqMapSize;
         1897  +          }
         1898  +        }
         1899  +      }
         1900  +    }
         1901  +  }
         1902  +  *pNewMapSize = pShmNode->szMap;
         1903  +  *ppBuf = pShmNode->pMMapBuf;
         1904  +  sqlite3_mutex_leave(pShmNode->mutex);
         1905  +  return rc;
         1906  +}
         1907  +
         1908  +/*
         1909  +** Release the lock held on the shared memory segment so that other
         1910  +** threads are free to resize it if necessary.
         1911  +**
         1912  +** If the lock is not currently held, this routine is a harmless no-op.
         1913  +**
         1914  +** If the shared-memory object is in lock state RECOVER, then we do not
         1915  +** really want to release the lock, so in that case too, this routine
         1916  +** is a no-op.
         1917  +*/
         1918  +static int winShmRelease(sqlite3_file *fd){
         1919  +  winFile *pDbFd = (winFile*)fd;
         1920  +  winShm *p = pDbFd->pShm;
         1921  +  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
         1922  +    winShmNode *pShmNode = p->pShmNode;
         1923  +    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
         1924  +    sqlite3_mutex_leave(pShmNode->mutexBuf);
         1925  +    p->hasMutexBuf = 0;
         1926  +  }
         1927  +  return SQLITE_OK;
         1928  +}
         1929  +
         1930  +/*
         1931  +** Symbolic names for LOCK states used for debugging.
         1932  +*/
         1933  +#ifdef SQLITE_DEBUG
         1934  +static const char *azLkName[] = {
         1935  +  "UNLOCK",
         1936  +  "READ",
         1937  +  "READ_FULL",
         1938  +  "WRITE",
         1939  +  "PENDING",
         1940  +  "CHECKPOINT",
         1941  +  "RECOVER"
         1942  +};
         1943  +#endif
         1944  +
         1945  +
         1946  +/*
         1947  +** Change the lock state for a shared-memory segment.
         1948  +*/
         1949  +static int winShmLock(
         1950  +  sqlite3_file *fd,          /* Database holding the shared memory */
         1951  +  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
         1952  +  int *pGotLock              /* The lock you actually got */
         1953  +){
         1954  +  winFile *pDbFd = (winFile*)fd;
         1955  +  winShm *p = pDbFd->pShm;
         1956  +  winShmNode *pShmNode = p->pShmNode;
         1957  +  int rc = SQLITE_PROTOCOL;
         1958  +
         1959  +  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
         1960  +  ** directly requested; they are side effects from requesting
         1961  +  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
         1962  +  */
         1963  +  assert( desiredLock==SQLITE_SHM_UNLOCK
         1964  +       || desiredLock==SQLITE_SHM_READ
         1965  +       || desiredLock==SQLITE_SHM_WRITE
         1966  +       || desiredLock==SQLITE_SHM_CHECKPOINT
         1967  +       || desiredLock==SQLITE_SHM_RECOVER );
         1968  +
         1969  +  /* Return directly if this is just a lock state query, or if
         1970  +  ** the connection is already in the desired locking state.
         1971  +  */
         1972  +  if( desiredLock==p->lockState
         1973  +   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
         1974  +  ){
         1975  +    OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s and got %s\n",
         1976  +             pShmNode->hFile.h,
         1977  +             p->id, (int)GetCurrentProcessId(), azLkName[desiredLock],
         1978  +             azLkName[p->lockState]));
         1979  +    if( pGotLock ) *pGotLock = p->lockState;
         1980  +    return SQLITE_OK;
         1981  +  }
         1982  +
         1983  +  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s->%s\n",
         1984  +           pShmNode->hFile.h,
         1985  +           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState], 
         1986  +           azLkName[desiredLock]));
         1987  +  
         1988  +  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
         1989  +    assert( sqlite3_mutex_notheld(pShmNode->mutex) );
         1990  +    sqlite3_mutex_enter(pShmNode->mutexBuf);
         1991  +    p->hasMutexBuf = 1;
         1992  +  }
         1993  +  sqlite3_mutex_enter(pShmNode->mutex);
         1994  +  switch( desiredLock ){
         1995  +    case SQLITE_SHM_UNLOCK: {
         1996  +      assert( p->lockState!=SQLITE_SHM_RECOVER );
         1997  +      winShmUnlock(pShmNode, p, WIN_SHM_A|WIN_SHM_B|WIN_SHM_C|WIN_SHM_D);
         1998  +      rc = SQLITE_OK;
         1999  +      p->lockState = SQLITE_SHM_UNLOCK;
         2000  +      break;
         2001  +    }
         2002  +    case SQLITE_SHM_READ: {
         2003  +      if( p->lockState==SQLITE_SHM_UNLOCK ){
         2004  +        int nAttempt;
         2005  +        rc = SQLITE_BUSY;
         2006  +        assert( p->lockState==SQLITE_SHM_UNLOCK );
         2007  +        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
         2008  +          rc = winShmSharedLock(pShmNode, p, WIN_SHM_A|WIN_SHM_B);
         2009  +          if( rc==SQLITE_BUSY ){
         2010  +            rc = winShmSharedLock(pShmNode, p, WIN_SHM_D);
         2011  +            if( rc==SQLITE_OK ){
         2012  +              p->lockState = SQLITE_SHM_READ_FULL;
         2013  +            }
         2014  +          }else{
         2015  +            winShmUnlock(pShmNode, p, WIN_SHM_B);
         2016  +            p->lockState = SQLITE_SHM_READ;
         2017  +          }
         2018  +        }
         2019  +      }else{
         2020  +       assert( p->lockState==SQLITE_SHM_WRITE
         2021  +               || p->lockState==SQLITE_SHM_RECOVER );
         2022  +        rc = winShmSharedLock(pShmNode, p, WIN_SHM_A);
         2023  +        winShmUnlock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
         2024  +        p->lockState = SQLITE_SHM_READ;
         2025  +      }
         2026  +      break;
         2027  +    }
         2028  +    case SQLITE_SHM_WRITE: {
         2029  +      assert( p->lockState==SQLITE_SHM_READ 
         2030  +              || p->lockState==SQLITE_SHM_READ_FULL );
         2031  +      rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C|WIN_SHM_D);
         2032  +      if( rc==SQLITE_OK ){
         2033  +        p->lockState = SQLITE_SHM_WRITE;
         2034  +      }
         2035  +      break;
         2036  +    }
         2037  +    case SQLITE_SHM_CHECKPOINT: {
         2038  +      assert( p->lockState==SQLITE_SHM_UNLOCK
         2039  +           || p->lockState==SQLITE_SHM_PENDING
         2040  +      );
         2041  +      if( p->lockState==SQLITE_SHM_UNLOCK ){
         2042  +        rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_B|WIN_SHM_C);
         2043  +        if( rc==SQLITE_OK ){
         2044  +          p->lockState = SQLITE_SHM_PENDING;
         2045  +        }
         2046  +      }
         2047  +      if( p->lockState==SQLITE_SHM_PENDING ){
         2048  +        rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_A);
         2049  +        if( rc==SQLITE_OK ){
         2050  +          p->lockState = SQLITE_SHM_CHECKPOINT;
         2051  +        }
         2052  +      }
         2053  +      break;
         2054  +    }
         2055  +    default: {
         2056  +      assert( desiredLock==SQLITE_SHM_RECOVER );
         2057  +      assert( p->lockState==SQLITE_SHM_READ
         2058  +           || p->lockState==SQLITE_SHM_READ_FULL
         2059  +      );
         2060  +      assert( sqlite3_mutex_held(pShmNode->mutexBuf) );
         2061  +      rc = winShmExclusiveLock(pShmNode, p, WIN_SHM_C);
         2062  +      if( rc==SQLITE_OK ){
         2063  +        p->lockState = SQLITE_SHM_RECOVER;
         2064  +      }
         2065  +      break;
         2066  +    }
         2067  +  }
         2068  +  sqlite3_mutex_leave(pShmNode->mutex);
         2069  +  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d got %s\n",
         2070  +           pShmNode->hFile.h, 
         2071  +           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
         2072  +  if( pGotLock ) *pGotLock = p->lockState;
         2073  +  return rc;
         2074  +}
         2075  +
         2076  +#else
         2077  +# define winShmOpen    0
         2078  +# define winShmSize    0
         2079  +# define winShmGet     0
         2080  +# define winShmRelease 0
         2081  +# define winShmLock    0
         2082  +# define winShmClose   0
         2083  +#endif /* #ifndef SQLITE_OMIT_WAL */
         2084  +/*
         2085  +***************************** End Shared Memory *****************************
         2086  +****************************************************************************/
         2087  +
  1142   2088   /*
  1143   2089   ** This vector defines all the methods that can operate on an
  1144   2090   ** sqlite3_file for win32.
  1145   2091   */
  1146   2092   static const sqlite3_io_methods winIoMethod = {
  1147         -  1,                        /* iVersion */
         2093  +  2,                        /* iVersion */
  1148   2094     winClose,
  1149   2095     winRead,
  1150   2096     winWrite,
  1151   2097     winTruncate,
  1152   2098     winSync,
  1153   2099     winFileSize,
  1154   2100     winLock,
  1155   2101     winUnlock,
  1156   2102     winCheckReservedLock,
  1157   2103     winFileControl,
  1158   2104     winSectorSize,
  1159         -  winDeviceCharacteristics
         2105  +  winDeviceCharacteristics,
         2106  +  winShmOpen,              /* xShmOpen */
         2107  +  winShmSize,              /* xShmSize */
         2108  +  winShmGet,               /* xShmGet */
         2109  +  winShmRelease,           /* xShmRelease */
         2110  +  winShmLock,              /* xShmLock */
         2111  +  winShmClose              /* xShmClose */
  1160   2112   };
  1161   2113   
  1162   2114   /***************************************************************************
  1163   2115   ** Here ends the I/O methods that form the sqlite3_io_methods object.
  1164   2116   **
  1165   2117   ** The next block of code implements the VFS methods.
  1166   2118   ****************************************************************************/
................................................................................
  1234   2186                      "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
  1235   2187     j = sqlite3Strlen30(zBuf);
  1236   2188     sqlite3_randomness(20, &zBuf[j]);
  1237   2189     for(i=0; i<20; i++, j++){
  1238   2190       zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  1239   2191     }
  1240   2192     zBuf[j] = 0;
  1241         -  OSTRACE2("TEMP FILENAME: %s\n", zBuf);
         2193  +  OSTRACE(("TEMP FILENAME: %s\n", zBuf));
  1242   2194     return SQLITE_OK; 
  1243   2195   }
  1244   2196   
  1245   2197   /*
  1246   2198   ** The return value of getLastErrorMsg
  1247   2199   ** is zero if the error message fits in the buffer, or non-zero
  1248   2200   ** otherwise (if the message was truncated).
................................................................................
  1432   2384         *pOutFlags = SQLITE_OPEN_READONLY;
  1433   2385       }
  1434   2386     }
  1435   2387     memset(pFile, 0, sizeof(*pFile));
  1436   2388     pFile->pMethod = &winIoMethod;
  1437   2389     pFile->h = h;
  1438   2390     pFile->lastErrno = NO_ERROR;
         2391  +  pFile->pVfs = pVfs;
         2392  +  pFile->pShm = 0;
         2393  +  pFile->zPath = zName;
  1439   2394     pFile->sectorSize = getSectorSize(pVfs, zUtf8Name);
  1440   2395   #if SQLITE_OS_WINCE
  1441   2396     if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) ==
  1442   2397                  (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)
  1443   2398          && !winceCreateLock(zName, pFile)
  1444   2399     ){
  1445   2400       CloseHandle(h);
................................................................................
  1503   2458       }while(   (   ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
  1504   2459                  || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
  1505   2460              && (++cnt < MX_DELETION_ATTEMPTS)
  1506   2461              && (Sleep(100), 1) );
  1507   2462   #endif
  1508   2463     }
  1509   2464     free(zConverted);
  1510         -  OSTRACE(("DELETE \"%s\" %s\n", zFilename, (   (rc == INVALID_FILE_ATTRIBUTES) 
  1511         -                                             && (error == ERROR_FILE_NOT_FOUND)) ? "ok" : "failed" ));
         2465  +  OSTRACE(("DELETE \"%s\" %s\n", zFilename,
         2466  +       ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
         2467  +         "ok" : "failed" ));
         2468  + 
  1512   2469     return (   (rc == INVALID_FILE_ATTRIBUTES) 
  1513   2470             && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
  1514   2471   }
  1515   2472   
  1516   2473   /*
  1517   2474   ** Check the existance and status of a file.
  1518   2475   */
................................................................................
  1901   2858   ** sqlite3_errmsg(), possibly making IO errors easier to debug.
  1902   2859   */
  1903   2860   static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
  1904   2861     UNUSED_PARAMETER(pVfs);
  1905   2862     return getLastErrorMsg(nBuf, zBuf);
  1906   2863   }
  1907   2864   
  1908         -#ifndef SQLITE_OMIT_WAL
  1909         -
  1910         -/*
  1911         -** Helper functions to obtain and relinquish the global mutex. The
  1912         -** global mutex is used to protect the winLockInfo objects used by 
  1913         -** this file, all of which may be shared by multiple threads.
  1914         -**
  1915         -** Function winShmMutexHeld() is used to assert() that the global mutex 
  1916         -** is held when required. This function is only used as part of assert() 
  1917         -** statements. e.g.
  1918         -**
  1919         -**   winShmEnterMutex()
  1920         -**     assert( winShmMutexHeld() );
  1921         -**   winEnterLeave()
  1922         -*/
  1923         -static void winShmEnterMutex(void){
  1924         -  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  1925         -}
  1926         -static void winShmLeaveMutex(void){
  1927         -  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  1928         -}
  1929         -#ifdef SQLITE_DEBUG
  1930         -static int winShmMutexHeld(void) {
  1931         -  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
  1932         -}
  1933         -#endif
  1934         -
  1935         -/* Forward reference */
  1936         -typedef struct winShm winShm;
  1937         -typedef struct winShmFile winShmFile;
  1938         -
  1939         -/*
  1940         -** Object used to represent a single file opened and mmapped to provide
  1941         -** shared memory.  When multiple threads all reference the same
  1942         -** log-summary, each thread has its own winFile object, but they all
  1943         -** point to a single instance of this object.  In other words, each
  1944         -** log-summary is opened only once per process.
  1945         -**
  1946         -** winShmMutexHeld() must be true when creating or destroying
  1947         -** this object or while reading or writing the following fields:
  1948         -**
  1949         -**      nRef
  1950         -**      pNext 
  1951         -**
  1952         -** The following fields are read-only after the object is created:
  1953         -** 
  1954         -**      fid
  1955         -**      zFilename
  1956         -**
  1957         -** Either winShmFile.mutex must be held or winShmFile.nRef==0 and
  1958         -** winShmMutexHeld() is true when reading or writing any other field
  1959         -** in this structure.
  1960         -**
  1961         -** To avoid deadlocks, mutex and mutexBuf are always released in the
  1962         -** reverse order that they are acquired.  mutexBuf is always acquired
  1963         -** first and released last.  This invariant is check by asserting
  1964         -** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
  1965         -** released.
  1966         -*/
  1967         -struct winShmFile {
  1968         -  sqlite3_mutex *mutex;      /* Mutex to access this object */
  1969         -  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
  1970         -  char *zFilename;           /* Name of the file */
  1971         -  winFile hFile;             /* File handle from winOpen */
  1972         -  HANDLE hMap;               /* File handle from CreateFileMapping */
  1973         -  DWORD lastErrno;           /* The Windows errno from the last I/O error */
  1974         -  int szMap;                 /* Size of the mapping of file into memory */
  1975         -  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
  1976         -  int nRef;                  /* Number of winShm objects pointing to this */
  1977         -  winShm *pFirst;            /* All winShm objects pointing to this */
  1978         -  winShmFile *pNext;         /* Next in list of all winShmFile objects */
  1979         -#ifdef SQLITE_DEBUG
  1980         -  u8 exclMask;               /* Mask of exclusive locks held */
  1981         -  u8 sharedMask;             /* Mask of shared locks held */
  1982         -  u8 nextShmId;              /* Next available winShm.id value */
  1983         -#endif
  1984         -};
  1985         -
  1986         -/*
  1987         -** A global array of all winShmFile objects.
  1988         -**
  1989         -** The winShmMutexHeld() must be true while reading or writing this list.
  1990         -*/
  1991         -static winShmFile *winShmFileList = 0;
  1992         -
  1993         -/*
  1994         -** Structure used internally by this VFS to record the state of an
  1995         -** open shared memory connection.
  1996         -**
  1997         -** winShm.pFile->mutex must be held while reading or writing the
  1998         -** winShm.pNext and winShm.locks[] elements.
  1999         -**
  2000         -** The winShm.pFile element is initialized when the object is created
  2001         -** and is read-only thereafter.
  2002         -*/
  2003         -struct winShm {
  2004         -  winShmFile *pFile;         /* The underlying winShmFile object */
  2005         -  winShm *pNext;             /* Next winShm with the same winShmFile */
  2006         -  u8 lockState;              /* Current lock state */
  2007         -  u8 hasMutex;               /* True if holding the winShmFile mutex */
  2008         -  u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
  2009         -  u8 sharedMask;             /* Mask of shared locks held */
  2010         -  u8 exclMask;               /* Mask of exclusive locks held */
  2011         -#ifdef SQLITE_DEBUG
  2012         -  u8 id;                     /* Id of this connection with its winShmFile */
  2013         -#endif
  2014         -};
  2015         -
  2016         -/*
  2017         -** Size increment by which shared memory grows
  2018         -*/
  2019         -#define SQLITE_WIN_SHM_INCR  4096
  2020         -
  2021         -/*
  2022         -** Constants used for locking
  2023         -*/
  2024         -#define WIN_SHM_BASE      32        /* Byte offset of the first lock byte */
  2025         -#define WIN_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
  2026         -#define WIN_SHM_A         0x10      /* Mask for region locks... */
  2027         -#define WIN_SHM_B         0x20
  2028         -#define WIN_SHM_C         0x40
  2029         -#define WIN_SHM_D         0x80
  2030         -
  2031         -#ifdef SQLITE_DEBUG
  2032         -/*
  2033         -** Return a pointer to a nul-terminated string in static memory that
  2034         -** describes a locking mask.  The string is of the form "MSABCD" with
  2035         -** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
  2036         -** and "A" through "D" for the region locks.  If a lock is held, the
  2037         -** letter is shown.  If the lock is not held, the letter is converted
  2038         -** to ".".
  2039         -**
  2040         -** This routine is for debugging purposes only and does not appear
  2041         -** in a production build.
  2042         -*/
  2043         -static const char *winShmLockString(u8 mask){
  2044         -  static char zBuf[48];
  2045         -  static int iBuf = 0;
  2046         -  char *z;
  2047         -
  2048         -  z = &zBuf[iBuf];
  2049         -  iBuf += 8;
  2050         -  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
  2051         -
  2052         -  z[0] = (mask & WIN_SHM_DMS)   ? 'S' : '.';
  2053         -  z[1] = (mask & WIN_SHM_A)     ? 'A' : '.';
  2054         -  z[2] = (mask & WIN_SHM_B)     ? 'B' : '.';
  2055         -  z[3] = (mask & WIN_SHM_C)     ? 'C' : '.';
  2056         -  z[4] = (mask & WIN_SHM_D)     ? 'D' : '.';
  2057         -  z[5] = 0;
  2058         -  return z;
  2059         -}
  2060         -#endif /* SQLITE_DEBUG */
  2061         -
  2062         -/*
  2063         -** Apply posix advisory locks for all bytes identified in lockMask.
  2064         -**
  2065         -** lockMask might contain multiple bits but all bits are guaranteed
  2066         -** to be contiguous.
  2067         -**
  2068         -** Locks block if the mask is exactly WIN_SHM_C and are non-blocking
  2069         -** otherwise.
  2070         -*/
  2071         -#define _SHM_UNLCK  1
  2072         -#define _SHM_RDLCK  2
  2073         -#define _SHM_WRLCK  3
  2074         -static int winShmSystemLock(
  2075         -  winShmFile *pFile,    /* Apply locks to this open shared-memory segment */
  2076         -  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
  2077         -  u8 lockMask           /* Which bytes to lock or unlock */
  2078         -){
  2079         -  OVERLAPPED ovlp;
  2080         -  DWORD dwFlags;
  2081         -  int nBytes;           /* Number of bytes to lock */
  2082         -  int i;                /* Offset into the locking byte range */
  2083         -  int rc = 0;           /* Result code form Lock/UnlockFileEx() */
  2084         -  u8 mask;              /* Mask of bits in lockMask */
  2085         -
  2086         -  /* Access to the winShmFile object is serialized by the caller */
  2087         -  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
  2088         -
  2089         -  /* Initialize the locking parameters */
  2090         -  if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
  2091         -    dwFlags = 0;
  2092         -    OSTRACE(("SHM-LOCK %d requesting blocking lock %s\n", 
  2093         -             pFile->hFile.h,
  2094         -             winShmLockString(lockMask)));
  2095         -  }else{
  2096         -    dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
  2097         -    OSTRACE(("SHM-LOCK %d requesting %s %s\n", 
  2098         -             pFile->hFile.h,
  2099         -             lockType!=_SHM_UNLCK ? "lock" : "unlock", 
  2100         -             winShmLockString(lockMask)));
  2101         -  }
  2102         -  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
  2103         -
  2104         -  /* Find the first bit in lockMask that is set */
  2105         -  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
  2106         -  assert( mask!=0 );
  2107         -  memset(&ovlp, 0, sizeof(OVERLAPPED));
  2108         -  ovlp.Offset = i+WIN_SHM_BASE;
  2109         -  nBytes = 1;
  2110         -
  2111         -  /* Extend the locking range for each additional bit that is set */
  2112         -  mask <<= 1;
  2113         -  while( mask!=0 && (lockMask & mask)!=0 ){
  2114         -    nBytes++;
  2115         -    mask <<= 1;
  2116         -  }
  2117         -
  2118         -  /* Verify that all bits set in lockMask are contiguous */
  2119         -  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
  2120         -
  2121         -  /* Release/Acquire the system-level lock */
  2122         -  if( lockType==_SHM_UNLCK ){
  2123         -    for(i=0; i<nBytes; i++, ovlp.Offset++){
  2124         -      rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
  2125         -      if( !rc ) break;
  2126         -    }
  2127         -  }else{
  2128         -    /* release old individual byte locks (if any)
  2129         -    ** and set new individual byte locks */
  2130         -    for(i=0; i<nBytes; i++, ovlp.Offset++){
  2131         -      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
  2132         -      rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
  2133         -      if( !rc ) break;
  2134         -    }
  2135         -  }
  2136         -  if( !rc ){
  2137         -    OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n", 
  2138         -             pFile->hFile.h,
  2139         -             lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx", GetLastError()));
  2140         -    /* release individual byte locks (if any) */
  2141         -    ovlp.Offset-=i;
  2142         -    for(i=0; i<nBytes; i++, ovlp.Offset++){
  2143         -      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
  2144         -    }
  2145         -  }
  2146         -  rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
  2147         -
  2148         -  /* Update the global lock state and do debug tracing */
  2149         -#ifdef SQLITE_DEBUG
  2150         -  OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
  2151         -  if( rc==SQLITE_OK ){
  2152         -    if( lockType==_SHM_UNLCK ){
  2153         -      OSTRACE(("unlock ok"));
  2154         -      pFile->exclMask &= ~lockMask;
  2155         -      pFile->sharedMask &= ~lockMask;
  2156         -    }else if( lockType==_SHM_RDLCK ){
  2157         -      OSTRACE(("read-lock ok"));
  2158         -      pFile->exclMask &= ~lockMask;
  2159         -      pFile->sharedMask |= lockMask;
  2160         -    }else{
  2161         -      assert( lockType==_SHM_WRLCK );
  2162         -      OSTRACE(("write-lock ok"));
  2163         -      pFile->exclMask |= lockMask;
  2164         -      pFile->sharedMask &= ~lockMask;
  2165         -    }
  2166         -  }else{
  2167         -    if( lockType==_SHM_UNLCK ){
  2168         -      OSTRACE(("unlock failed"));
  2169         -    }else if( lockType==_SHM_RDLCK ){
  2170         -      OSTRACE(("read-lock failed"));
  2171         -    }else{
  2172         -      assert( lockType==_SHM_WRLCK );
  2173         -      OSTRACE(("write-lock failed"));
  2174         -    }
  2175         -  }
  2176         -  OSTRACE((" - change requested %s - afterwards %s:%s\n",
  2177         -           winShmLockString(lockMask),
  2178         -           winShmLockString(pFile->sharedMask),
  2179         -           winShmLockString(pFile->exclMask)));
  2180         -#endif
  2181         -
  2182         -  return rc;
  2183         -}
  2184         -
  2185         -/*
  2186         -** For connection p, unlock all of the locks identified by the unlockMask
  2187         -** parameter.
  2188         -*/
  2189         -static int winShmUnlock(
  2190         -  winShmFile *pFile,   /* The underlying shared-memory file */
  2191         -  winShm *p,           /* The connection to be unlocked */
  2192         -  u8 unlockMask         /* Mask of locks to be unlocked */
  2193         -){
  2194         -  int rc;      /* Result code */
  2195         -  winShm *pX; /* For looping over all sibling connections */
  2196         -  u8 allMask;  /* Union of locks held by connections other than "p" */
  2197         -
  2198         -  /* Access to the winShmFile object is serialized by the caller */
  2199         -  assert( sqlite3_mutex_held(pFile->mutex) );
  2200         -
  2201         -  /* don't attempt to unlock anything we don't have locks for */
  2202         -  if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
  2203         -    OSTRACE(("SHM-LOCK %d unlocking more than we have locked - requested %s - have %s\n",
  2204         -             pFile->hFile.h,
  2205         -             winShmLockString(unlockMask),
  2206         -             winShmLockString(p->exclMask|p->sharedMask)));
  2207         -    unlockMask &= (p->exclMask|p->sharedMask);
  2208         -  }
  2209         -
  2210         -  /* Compute locks held by sibling connections */
  2211         -  allMask = 0;
  2212         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  2213         -    if( pX==p ) continue;
  2214         -    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
  2215         -    allMask |= pX->sharedMask;
  2216         -  }
  2217         -
  2218         -  /* Unlock the system-level locks */
  2219         -  if( (unlockMask & allMask)!=unlockMask ){
  2220         -    rc = winShmSystemLock(pFile, _SHM_UNLCK, unlockMask & ~allMask);
  2221         -  }else{
  2222         -    rc = SQLITE_OK;
  2223         -  }
  2224         -
  2225         -  /* Undo the local locks */
  2226         -  if( rc==SQLITE_OK ){
  2227         -    p->exclMask &= ~unlockMask;
  2228         -    p->sharedMask &= ~unlockMask;
  2229         -  } 
  2230         -  return rc;
  2231         -}
  2232         -
  2233         -/*
  2234         -** Get reader locks for connection p on all locks in the readMask parameter.
  2235         -*/
  2236         -static int winShmSharedLock(
  2237         -  winShmFile *pFile,   /* The underlying shared-memory file */
  2238         -  winShm *p,           /* The connection to get the shared locks */
  2239         -  u8 readMask           /* Mask of shared locks to be acquired */
  2240         -){
  2241         -  int rc;        /* Result code */
  2242         -  winShm *pX;   /* For looping over all sibling connections */
  2243         -  u8 allShared;  /* Union of locks held by connections other than "p" */
  2244         -
  2245         -  /* Access to the winShmFile object is serialized by the caller */
  2246         -  assert( sqlite3_mutex_held(pFile->mutex) );
  2247         -
  2248         -  /* Find out which shared locks are already held by sibling connections.
  2249         -  ** If any sibling already holds an exclusive lock, go ahead and return
  2250         -  ** SQLITE_BUSY.
  2251         -  */
  2252         -  allShared = 0;
  2253         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  2254         -    if( pX==p ) continue;
  2255         -    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
  2256         -    allShared |= pX->sharedMask;
  2257         -  }
  2258         -
  2259         -  /* Get shared locks at the system level, if necessary */
  2260         -  if( (~allShared) & readMask ){
  2261         -    rc = winShmSystemLock(pFile, _SHM_RDLCK, readMask);
  2262         -  }else{
  2263         -    rc = SQLITE_OK;
  2264         -  }
  2265         -
  2266         -  /* Get the local shared locks */
  2267         -  if( rc==SQLITE_OK ){
  2268         -    p->sharedMask |= readMask;
  2269         -  }
  2270         -  return rc;
  2271         -}
  2272         -
  2273         -/*
  2274         -** For connection p, get an exclusive lock on all locks identified in
  2275         -** the writeMask parameter.
  2276         -*/
  2277         -static int winShmExclusiveLock(
  2278         -  winShmFile *pFile,    /* The underlying shared-memory file */
  2279         -  winShm *p,            /* The connection to get the exclusive locks */
  2280         -  u8 writeMask           /* Mask of exclusive locks to be acquired */
  2281         -){
  2282         -  int rc;        /* Result code */
  2283         -  winShm *pX;   /* For looping over all sibling connections */
  2284         -
  2285         -  /* Access to the winShmFile object is serialized by the caller */
  2286         -  assert( sqlite3_mutex_held(pFile->mutex) );
  2287         -
  2288         -  /* Make sure no sibling connections hold locks that will block this
  2289         -  ** lock.  If any do, return SQLITE_BUSY right away.
  2290         -  */
  2291         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  2292         -    if( pX==p ) continue;
  2293         -    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
  2294         -    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
  2295         -  }
  2296         -
  2297         -  /* Get the exclusive locks at the system level.  Then if successful
  2298         -  ** also mark the local connection as being locked.
  2299         -  */
  2300         -  rc = winShmSystemLock(pFile, _SHM_WRLCK, writeMask);
  2301         -  if( rc==SQLITE_OK ){
  2302         -    p->sharedMask &= ~writeMask;
  2303         -    p->exclMask |= writeMask;
  2304         -  }
  2305         -  return rc;
  2306         -}
  2307         -
  2308         -/*
  2309         -** Purge the winShmFileList list of all entries with winShmFile.nRef==0.
  2310         -**
  2311         -** This is not a VFS shared-memory method; it is a utility function called
  2312         -** by VFS shared-memory methods.
  2313         -*/
  2314         -static void winShmPurge(void){
  2315         -  winShmFile **pp;
  2316         -  winShmFile *p;
  2317         -  assert( winShmMutexHeld() );
  2318         -  pp = &winShmFileList;
  2319         -  while( (p = *pp)!=0 ){
  2320         -    if( p->nRef==0 ){
  2321         -      if( p->mutex ) sqlite3_mutex_free(p->mutex);
  2322         -      if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
  2323         -      if( p->pMMapBuf ){
  2324         -        UnmapViewOfFile(p->pMMapBuf);
  2325         -      }
  2326         -      if( INVALID_HANDLE_VALUE != p->hMap ){
  2327         -        CloseHandle(p->hMap);
  2328         -      }
  2329         -      if( p->hFile.h != INVALID_HANDLE_VALUE ) {
  2330         -        winClose((sqlite3_file *)&p->hFile);
  2331         -      }
  2332         -      *pp = p->pNext;
  2333         -      sqlite3_free(p);
  2334         -    }else{
  2335         -      pp = &p->pNext;
  2336         -    }
  2337         -  }
  2338         -}
  2339         -
  2340         -/*
  2341         -** Open a shared-memory area.  This particular implementation uses
  2342         -** mmapped files.
  2343         -**
  2344         -** zName is a filename used to identify the shared-memory area.  The
  2345         -** implementation does not (and perhaps should not) use this name
  2346         -** directly, but rather use it as a template for finding an appropriate
  2347         -** name for the shared-memory storage.  In this implementation, the
  2348         -** string "-index" is appended to zName and used as the name of the
  2349         -** mmapped file.
  2350         -**
  2351         -** When opening a new shared-memory file, if no other instances of that
  2352         -** file are currently open, in this process or in other processes, then
  2353         -** the file must be truncated to zero length or have its header cleared.
  2354         -*/
  2355         -static int winShmOpen(
  2356         -  sqlite3_vfs *pVfs,    /* The VFS */
  2357         -  const char *zName,    /* Name of the corresponding database file */
  2358         -  sqlite3_shm **pShm    /* Write the winShm object created here */
  2359         -){
  2360         -  struct winShm *p;                  /* The connection to be opened */
  2361         -  struct winShmFile *pFile = 0;      /* The underlying mmapped file */
  2362         -  int rc;                            /* Result code */
  2363         -  struct winShmFile *pNew;           /* Newly allocated pFile */
  2364         -  int nName;                         /* Size of zName in bytes */
  2365         -  char zFullpath[MAX_PATH+1];        /* Temp buffer for full file name */
  2366         -
  2367         -  rc = winFullPathname(pVfs, zName, MAX_PATH, zFullpath);
  2368         -  if( rc ) return rc;
  2369         -
  2370         -  /* Allocate space for the new sqlite3_shm object.  Also speculatively
  2371         -  ** allocate space for a new winShmFile and filename.
  2372         -  */
  2373         -  p = sqlite3_malloc( sizeof(*p) );
  2374         -  if( p==0 ) return SQLITE_NOMEM;
  2375         -  memset(p, 0, sizeof(*p));
  2376         -  nName = sqlite3Strlen30(zFullpath);
  2377         -  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 15 );
  2378         -  if( pNew==0 ){
  2379         -    sqlite3_free(p);
  2380         -    return SQLITE_NOMEM;
  2381         -  }
  2382         -  memset(pNew, 0, sizeof(*pNew));
  2383         -  pNew->zFilename = (char*)&pNew[1];
  2384         -  sqlite3_snprintf(nName+12, pNew->zFilename, "%s-wal-index", zFullpath);
  2385         -
  2386         -  /* Look to see if there is an existing winShmFile that can be used.
  2387         -  ** If no matching winShmFile currently exists, create a new one.
  2388         -  */
  2389         -  winShmEnterMutex();
  2390         -  for(pFile = winShmFileList; pFile; pFile=pFile->pNext){
  2391         -    /* TBD need to come up with better match here.  Perhaps
  2392         -    ** use FILE_ID_BOTH_DIR_INFO Structure.
  2393         -    */
  2394         -    if( sqlite3StrICmp(pFile->zFilename, pNew->zFilename)==0 ) break;
  2395         -  }
  2396         -  if( pFile ){
  2397         -    sqlite3_free(pNew);
  2398         -  }else{
  2399         -    pFile = pNew;
  2400         -    pNew = 0;
  2401         -    pFile->pMMapBuf = NULL;
  2402         -    pFile->hMap = INVALID_HANDLE_VALUE;
  2403         -    ((winFile*)(&pFile->hFile))->h = INVALID_HANDLE_VALUE;
  2404         -    pFile->pNext = winShmFileList;
  2405         -    winShmFileList = pFile;
  2406         -
  2407         -    pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  2408         -    if( pFile->mutex==0 ){
  2409         -      rc = SQLITE_NOMEM;
  2410         -      goto shm_open_err;
  2411         -    }
  2412         -    pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  2413         -    if( pFile->mutexBuf==0 ){
  2414         -      rc = SQLITE_NOMEM;
  2415         -      goto shm_open_err;
  2416         -    }
  2417         -    rc = winOpen(pVfs,
  2418         -                 pFile->zFilename,                  /* Name of the file (UTF-8) */
  2419         -                 (sqlite3_file *)&pFile->hFile, /* Write the SQLite file handle here */
  2420         -                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Open mode flags */
  2421         -                 0);
  2422         -    if( SQLITE_OK!=rc ){
  2423         -      rc = SQLITE_CANTOPEN_BKPT;
  2424         -      goto shm_open_err;
  2425         -    }
  2426         -
  2427         -    /* Check to see if another process is holding the dead-man switch.
  2428         -    ** If not, truncate the file to zero length. 
  2429         -    */
  2430         -    if( winShmSystemLock(pFile, _SHM_WRLCK, WIN_SHM_DMS)==SQLITE_OK ){
  2431         -      rc = winTruncate((sqlite3_file *)&pFile->hFile, 0);
  2432         -    }
  2433         -    if( rc==SQLITE_OK ){
  2434         -      rc = winShmSystemLock(pFile, _SHM_RDLCK, WIN_SHM_DMS);
  2435         -    }
  2436         -    if( rc ) goto shm_open_err;
  2437         -  }
  2438         -
  2439         -  /* Make the new connection a child of the winShmFile */
  2440         -  p->pFile = pFile;
  2441         -  p->pNext = pFile->pFirst;
  2442         -#ifdef SQLITE_DEBUG
  2443         -  p->id = pFile->nextShmId++;
  2444         -#endif
  2445         -  pFile->pFirst = p;
  2446         -  pFile->nRef++;
  2447         -  *pShm = (sqlite3_shm*)p;
  2448         -  winShmLeaveMutex();
  2449         -  return SQLITE_OK;
  2450         -
  2451         -  /* Jump here on any error */
  2452         -shm_open_err:
  2453         -  winShmSystemLock(pFile, _SHM_UNLCK, WIN_SHM_DMS);
  2454         -  winShmPurge();                 /* This call frees pFile if required */
  2455         -  sqlite3_free(p);
  2456         -  sqlite3_free(pNew);
  2457         -  *pShm = 0;
  2458         -  winShmLeaveMutex();
  2459         -  return rc;
  2460         -}
  2461         -
  2462         -/*
  2463         -** Close a connection to shared-memory.  Delete the underlying 
  2464         -** storage if deleteFlag is true.
  2465         -*/
  2466         -static int winShmClose(
  2467         -  sqlite3_vfs *pVfs,         /* The VFS */
  2468         -  sqlite3_shm *pSharedMem,   /* The shared-memory to be closed */
  2469         -  int deleteFlag             /* Delete after closing if true */
  2470         -){
  2471         -  winShm *p;            /* The connection to be closed */
  2472         -  winShmFile *pFile;    /* The underlying shared-memory file */
  2473         -  winShm **pp;          /* For looping over sibling connections */
  2474         -
  2475         -  UNUSED_PARAMETER(pVfs);
  2476         -  if( pSharedMem==0 ) return SQLITE_OK;
  2477         -  p = (struct winShm*)pSharedMem;
  2478         -  pFile = p->pFile;
  2479         -
  2480         -  /* Verify that the connection being closed holds no locks */
  2481         -  assert( p->exclMask==0 );
  2482         -  assert( p->sharedMask==0 );
  2483         -
  2484         -  /* Remove connection p from the set of connections associated with pFile */
  2485         -  sqlite3_mutex_enter(pFile->mutex);
  2486         -  for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
  2487         -  *pp = p->pNext;
  2488         -
  2489         -  /* Free the connection p */
  2490         -  sqlite3_free(p);
  2491         -  sqlite3_mutex_leave(pFile->mutex);
  2492         -
  2493         -  /* If pFile->nRef has reached 0, then close the underlying
  2494         -  ** shared-memory file, too */
  2495         -  winShmEnterMutex();
  2496         -  assert( pFile->nRef>0 );
  2497         -  pFile->nRef--;
  2498         -  if( pFile->nRef==0 ){
  2499         -    if( deleteFlag ) winDelete(pVfs, pFile->zFilename, 0);
  2500         -    winShmPurge();
  2501         -  }
  2502         -  winShmLeaveMutex();
  2503         -
  2504         -  return SQLITE_OK;
  2505         -}
  2506         -
  2507         -/*
  2508         -** Query and/or changes the size of the underlying storage for
  2509         -** a shared-memory segment.  The reqSize parameter is the new size
  2510         -** of the underlying storage, or -1 to do just a query.  The size
  2511         -** of the underlying storage (after resizing if resizing occurs) is
  2512         -** written into pNewSize.
  2513         -**
  2514         -** This routine does not (necessarily) change the size of the mapping 
  2515         -** of the underlying storage into memory.  Use xShmGet() to change
  2516         -** the mapping size.
  2517         -**
  2518         -** The reqSize parameter is the minimum size requested.  The implementation
  2519         -** is free to expand the storage to some larger amount if it chooses.
  2520         -*/
  2521         -static int winShmSize(
  2522         -  sqlite3_vfs *pVfs,        /* The VFS */
  2523         -  sqlite3_shm *pSharedMem,  /* Pointer returned by winShmOpen() */
  2524         -  int reqSize,              /* Requested size.  -1 for query only */
  2525         -  int *pNewSize             /* Write new size here */
  2526         -){
  2527         -  winShm *p = (winShm*)pSharedMem;
  2528         -  winShmFile *pFile = p->pFile;
  2529         -  int rc = SQLITE_OK;
  2530         -
  2531         -  UNUSED_PARAMETER(pVfs);
  2532         -
  2533         -  if( reqSize>=0 ){
  2534         -    reqSize = (reqSize + SQLITE_WIN_SHM_INCR - 1)/SQLITE_WIN_SHM_INCR;
  2535         -    reqSize *= SQLITE_WIN_SHM_INCR;
  2536         -    rc = winTruncate((sqlite3_file *)&pFile->hFile, reqSize);
  2537         -  }
  2538         -  if( SQLITE_OK==rc ){
  2539         -    sqlite3_int64 sz;
  2540         -    rc = winFileSize((sqlite3_file *)&pFile->hFile, &sz);
  2541         -    if( SQLITE_OK==rc ){
  2542         -      *pNewSize = (int)sz;
  2543         -    }else{
  2544         -      *pNewSize = 0;
  2545         -      rc = SQLITE_IOERR;
  2546         -    }
  2547         -  }
  2548         -  return rc;
  2549         -}
  2550         -
  2551         -
  2552         -/*
  2553         -** Map the shared storage into memory.  The minimum size of the
  2554         -** mapping should be reqMapSize if reqMapSize is positive.  If
  2555         -** reqMapSize is zero or negative, the implementation can choose
  2556         -** whatever mapping size is convenient.
  2557         -**
  2558         -** *ppBuf is made to point to the memory which is a mapping of the
  2559         -** underlying storage.  A mutex is acquired to prevent other threads
  2560         -** from running while *ppBuf is in use in order to prevent other threads
  2561         -** remapping *ppBuf out from under this thread.  The winShmRelease()
  2562         -** call will release the mutex.  However, if the lock state is CHECKPOINT,
  2563         -** the mutex is not acquired because CHECKPOINT will never remap the
  2564         -** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
  2565         -** the mutex if and when it promotes to RECOVER.
  2566         -**
  2567         -** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
  2568         -** being remapped also prevents more than one thread from being in
  2569         -** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
  2570         -** To prevent RECOVER from losing its lock while remapping, the
  2571         -** mutex is not released by winShmRelease() when in RECOVER.
  2572         -**
  2573         -** *pNewMapSize is set to the size of the mapping.
  2574         -**
  2575         -** *ppBuf and *pNewMapSize might be NULL and zero if no space has
  2576         -** yet been allocated to the underlying storage.
  2577         -*/
  2578         -static int winShmGet(
  2579         -  sqlite3_vfs *pVfs,       /* The VFS */
  2580         -  sqlite3_shm *pSharedMem, /* Pointer returned by winShmOpen() */
  2581         -  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  2582         -  int *pNewMapSize,        /* Write new size of mapping here */
  2583         -  void **ppBuf             /* Write mapping buffer origin here */
  2584         -){
  2585         -  winShm *p = (winShm*)pSharedMem;
  2586         -  winShmFile *pFile = p->pFile;
  2587         -  int rc = SQLITE_OK;
  2588         -
  2589         -  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
  2590         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  2591         -    sqlite3_mutex_enter(pFile->mutexBuf);
  2592         -    p->hasMutexBuf = 1;
  2593         -  }
  2594         -  sqlite3_mutex_enter(pFile->mutex);
  2595         -  if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
  2596         -    int actualSize;
  2597         -    if( winShmSize(pVfs, pSharedMem, -1, &actualSize)==SQLITE_OK
  2598         -     && reqMapSize<actualSize
  2599         -    ){
  2600         -      reqMapSize = actualSize;
  2601         -    }
  2602         -    if( pFile->pMMapBuf ){
  2603         -      if( !UnmapViewOfFile(pFile->pMMapBuf) ){
  2604         -        pFile->lastErrno = GetLastError();
  2605         -        rc = SQLITE_IOERR;
  2606         -      }
  2607         -      CloseHandle(pFile->hMap);
  2608         -      pFile->hMap = INVALID_HANDLE_VALUE;
  2609         -    }
  2610         -    if( SQLITE_OK == rc ){
  2611         -      pFile->pMMapBuf = 0;
  2612         -      if( reqMapSize == 0 ){
  2613         -        /* can't create 0 byte file mapping in Windows */
  2614         -        pFile->szMap = 0;
  2615         -      }else{
  2616         -        /* create the file mapping object */
  2617         -        if( INVALID_HANDLE_VALUE == pFile->hMap ){
  2618         -          /* TBD provide an object name to each file
  2619         -          ** mapping so it can be re-used across processes.
  2620         -          */
  2621         -          pFile->hMap = CreateFileMapping(pFile->hFile.h,
  2622         -                                          NULL,
  2623         -                                          PAGE_READWRITE,
  2624         -                                          0,
  2625         -                                          reqMapSize,
  2626         -                                          NULL);
  2627         -        }
  2628         -        if( NULL==pFile->hMap ){
  2629         -          pFile->lastErrno = GetLastError();
  2630         -          rc = SQLITE_IOERR;
  2631         -          pFile->szMap = 0;
  2632         -          pFile->hMap = INVALID_HANDLE_VALUE;
  2633         -        }else{
  2634         -          pFile->pMMapBuf = MapViewOfFile(pFile->hMap,
  2635         -                                          FILE_MAP_WRITE | FILE_MAP_READ,
  2636         -                                          0,
  2637         -                                          0,
  2638         -                                          reqMapSize);
  2639         -          if( !pFile->pMMapBuf ){
  2640         -            pFile->lastErrno = GetLastError();
  2641         -            rc = SQLITE_IOERR;
  2642         -            pFile->szMap = 0;
  2643         -          }else{
  2644         -            pFile->szMap = reqMapSize;
  2645         -          }
  2646         -        }
  2647         -      }
  2648         -    }
  2649         -  }
  2650         -  *pNewMapSize = pFile->szMap;
  2651         -  *ppBuf = pFile->pMMapBuf;
  2652         -  sqlite3_mutex_leave(pFile->mutex);
  2653         -  return rc;
  2654         -}
  2655         -
  2656         -/*
  2657         -** Release the lock held on the shared memory segment so that other
  2658         -** threads are free to resize it if necessary.
  2659         -**
  2660         -** If the lock is not currently held, this routine is a harmless no-op.
  2661         -**
  2662         -** If the shared-memory object is in lock state RECOVER, then we do not
  2663         -** really want to release the lock, so in that case too, this routine
  2664         -** is a no-op.
  2665         -*/
  2666         -static int winShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pSharedMem){
  2667         -  winShm *p = (winShm*)pSharedMem;
  2668         -  UNUSED_PARAMETER(pVfs);
  2669         -  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
  2670         -    winShmFile *pFile = p->pFile;
  2671         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  2672         -    sqlite3_mutex_leave(pFile->mutexBuf);
  2673         -    p->hasMutexBuf = 0;
  2674         -  }
  2675         -  return SQLITE_OK;
  2676         -}
  2677         -
  2678         -/*
  2679         -** Symbolic names for LOCK states used for debugging.
  2680         -*/
  2681         -#ifdef SQLITE_DEBUG
  2682         -static const char *azLkName[] = {
  2683         -  "UNLOCK",
  2684         -  "READ",
  2685         -  "READ_FULL",
  2686         -  "WRITE",
  2687         -  "PENDING",
  2688         -  "CHECKPOINT",
  2689         -  "RECOVER"
  2690         -};
  2691         -#endif
  2692         -
  2693         -
  2694         -/*
  2695         -** Change the lock state for a shared-memory segment.
  2696         -*/
  2697         -static int winShmLock(
  2698         -  sqlite3_vfs *pVfs,         /* The VFS */
  2699         -  sqlite3_shm *pSharedMem,   /* Pointer from winShmOpen() */
  2700         -  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
  2701         -  int *pGotLock              /* The lock you actually got */
  2702         -){
  2703         -  winShm *p = (winShm*)pSharedMem;
  2704         -  winShmFile *pFile = p->pFile;
  2705         -  int rc = SQLITE_PROTOCOL;
  2706         -
  2707         -  UNUSED_PARAMETER(pVfs);
  2708         -
  2709         -  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
  2710         -  ** directly requested; they are side effects from requesting
  2711         -  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
  2712         -  */
  2713         -  assert( desiredLock==SQLITE_SHM_UNLOCK
  2714         -       || desiredLock==SQLITE_SHM_READ
  2715         -       || desiredLock==SQLITE_SHM_WRITE
  2716         -       || desiredLock==SQLITE_SHM_CHECKPOINT
  2717         -       || desiredLock==SQLITE_SHM_RECOVER );
  2718         -
  2719         -  /* Return directly if this is just a lock state query, or if
  2720         -  ** the connection is already in the desired locking state.
  2721         -  */
  2722         -  if( desiredLock==p->lockState
  2723         -   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
  2724         -  ){
  2725         -    OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s and got %s\n",
  2726         -             pFile->hFile.h,
  2727         -             p->id, (int)GetCurrentProcessId(), azLkName[desiredLock], azLkName[p->lockState]));
  2728         -    if( pGotLock ) *pGotLock = p->lockState;
  2729         -    return SQLITE_OK;
  2730         -  }
  2731         -
  2732         -  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s->%s\n",
  2733         -           pFile->hFile.h,
  2734         -           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState], azLkName[desiredLock]));
  2735         -  
  2736         -  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
  2737         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  2738         -    sqlite3_mutex_enter(pFile->mutexBuf);
  2739         -    p->hasMutexBuf = 1;
  2740         -  }
  2741         -  sqlite3_mutex_enter(pFile->mutex);
  2742         -  switch( desiredLock ){
  2743         -    case SQLITE_SHM_UNLOCK: {
  2744         -      assert( p->lockState!=SQLITE_SHM_RECOVER );
  2745         -      winShmUnlock(pFile, p, WIN_SHM_A|WIN_SHM_B|WIN_SHM_C|WIN_SHM_D);
  2746         -      rc = SQLITE_OK;
  2747         -      p->lockState = SQLITE_SHM_UNLOCK;
  2748         -      break;
  2749         -    }
  2750         -    case SQLITE_SHM_READ: {
  2751         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  2752         -        int nAttempt;
  2753         -        rc = SQLITE_BUSY;
  2754         -        assert( p->lockState==SQLITE_SHM_UNLOCK );
  2755         -        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
  2756         -          rc = winShmSharedLock(pFile, p, WIN_SHM_A|WIN_SHM_B);
  2757         -          if( rc==SQLITE_BUSY ){
  2758         -            rc = winShmSharedLock(pFile, p, WIN_SHM_D);
  2759         -            if( rc==SQLITE_OK ){
  2760         -              p->lockState = SQLITE_SHM_READ_FULL;
  2761         -            }
  2762         -          }else{
  2763         -            winShmUnlock(pFile, p, WIN_SHM_B);
  2764         -            p->lockState = SQLITE_SHM_READ;
  2765         -          }
  2766         -        }
  2767         -      }else{
  2768         -       assert( p->lockState==SQLITE_SHM_WRITE
  2769         -               || p->lockState==SQLITE_SHM_RECOVER );
  2770         -        rc = winShmSharedLock(pFile, p, WIN_SHM_A);
  2771         -        winShmUnlock(pFile, p, WIN_SHM_C|WIN_SHM_D);
  2772         -        p->lockState = SQLITE_SHM_READ;
  2773         -      }
  2774         -      break;
  2775         -    }
  2776         -    case SQLITE_SHM_WRITE: {
  2777         -      assert( p->lockState==SQLITE_SHM_READ 
  2778         -              || p->lockState==SQLITE_SHM_READ_FULL );
  2779         -      rc = winShmExclusiveLock(pFile, p, WIN_SHM_C|WIN_SHM_D);
  2780         -      if( rc==SQLITE_OK ){
  2781         -        p->lockState = SQLITE_SHM_WRITE;
  2782         -      }
  2783         -      break;
  2784         -    }
  2785         -    case SQLITE_SHM_CHECKPOINT: {
  2786         -      assert( p->lockState==SQLITE_SHM_UNLOCK
  2787         -           || p->lockState==SQLITE_SHM_PENDING
  2788         -      );
  2789         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  2790         -        rc = winShmExclusiveLock(pFile, p, WIN_SHM_B|WIN_SHM_C);
  2791         -        if( rc==SQLITE_OK ){
  2792         -          p->lockState = SQLITE_SHM_PENDING;
  2793         -        }
  2794         -      }
  2795         -      if( p->lockState==SQLITE_SHM_PENDING ){
  2796         -        rc = winShmExclusiveLock(pFile, p, WIN_SHM_A);
  2797         -        if( rc==SQLITE_OK ){
  2798         -          p->lockState = SQLITE_SHM_CHECKPOINT;
  2799         -        }
  2800         -      }
  2801         -      break;
  2802         -    }
  2803         -    default: {
  2804         -      assert( desiredLock==SQLITE_SHM_RECOVER );
  2805         -      assert( p->lockState==SQLITE_SHM_READ
  2806         -           || p->lockState==SQLITE_SHM_READ_FULL
  2807         -      );
  2808         -      assert( sqlite3_mutex_held(pFile->mutexBuf) );
  2809         -      rc = winShmExclusiveLock(pFile, p, WIN_SHM_C);
  2810         -      if( rc==SQLITE_OK ){
  2811         -        p->lockState = SQLITE_SHM_RECOVER;
  2812         -      }
  2813         -      break;
  2814         -    }
  2815         -  }
  2816         -  sqlite3_mutex_leave(pFile->mutex);
  2817         -  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d got %s\n",
  2818         -           pFile->hFile.h, 
  2819         -           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
  2820         -  if( pGotLock ) *pGotLock = p->lockState;
  2821         -  return rc;
  2822         -}
  2823         -
  2824         -#else
  2825         -# define winShmOpen    0
  2826         -# define winShmSize    0
  2827         -# define winShmGet     0
  2828         -# define winShmRelease 0
  2829         -# define winShmLock    0
  2830         -# define winShmClose   0
  2831         -#endif /* #ifndef SQLITE_OMIT_WAL */
  2832   2865   
  2833   2866   
  2834   2867   /*
  2835   2868   ** Initialize and deinitialize the operating system interface.
  2836   2869   */
  2837   2870   int sqlite3_os_init(void){
  2838   2871     static sqlite3_vfs winVfs = {
................................................................................
  2850   2883       winDlError,          /* xDlError */
  2851   2884       winDlSym,            /* xDlSym */
  2852   2885       winDlClose,          /* xDlClose */
  2853   2886       winRandomness,       /* xRandomness */
  2854   2887       winSleep,            /* xSleep */
  2855   2888       winCurrentTime,      /* xCurrentTime */
  2856   2889       winGetLastError,     /* xGetLastError */
  2857         -    winShmOpen,          /* xShmOpen */
  2858         -    winShmSize,          /* xShmSize */
  2859         -    winShmGet,           /* xShmGet */
  2860         -    winShmRelease,       /* xShmRelease */
  2861         -    winShmLock,          /* xShmLock */
  2862         -    winShmClose,         /* xShmClose */
  2863   2890       0,                   /* xRename */
  2864   2891       winCurrentTimeInt64, /* xCurrentTimeInt64 */
  2865   2892     };
  2866   2893   
  2867   2894     sqlite3_vfs_register(&winVfs, 1);
  2868   2895     return SQLITE_OK; 
  2869   2896   }
  2870   2897   int sqlite3_os_end(void){ 
  2871   2898     return SQLITE_OK;
  2872   2899   }
  2873   2900   
  2874   2901   #endif /* SQLITE_OS_WIN */

Changes to src/pager.c.

  1400   1400         if( pPager->journalOff==0 ){
  1401   1401           rc = SQLITE_OK;
  1402   1402         }else{
  1403   1403           rc = sqlite3OsTruncate(pPager->jfd, 0);
  1404   1404         }
  1405   1405         pPager->journalOff = 0;
  1406   1406         pPager->journalStarted = 0;
  1407         -    }else if( pPager->exclusiveMode 
  1408         -     || pPager->journalMode==PAGER_JOURNALMODE_PERSIST
         1407  +    }else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
         1408  +      || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
  1409   1409       ){
  1410   1410         rc = zeroJournalHdr(pPager, hasMaster);
  1411   1411         pager_error(pPager, rc);
  1412   1412         pPager->journalOff = 0;
  1413   1413         pPager->journalStarted = 0;
  1414   1414       }else{
  1415   1415         /* This branch may be executed with Pager.journalMode==MEMORY if
................................................................................
  1435   1435     pPager->pInJournal = 0;
  1436   1436     pPager->nRec = 0;
  1437   1437     sqlite3PcacheCleanAll(pPager->pPCache);
  1438   1438   
  1439   1439     if( pagerUseWal(pPager) ){
  1440   1440       rc2 = sqlite3WalWriteLock(pPager->pWal, 0);
  1441   1441       pPager->state = PAGER_SHARED;
         1442  +
         1443  +    /* If the connection was in locking_mode=exclusive mode but is no longer,
         1444  +    ** drop the EXCLUSIVE lock held on the database file.
         1445  +    */
         1446  +    if( rc2==SQLITE_OK 
         1447  +     && !pPager->exclusiveMode 
         1448  +     && sqlite3WalExclusiveMode(pPager->pWal, -1) 
         1449  +    ){
         1450  +      sqlite3WalExclusiveMode(pPager->pWal, 0);
         1451  +      rc2 = osUnlock(pPager->fd, SHARED_LOCK);
         1452  +    }
  1442   1453     }else if( !pPager->exclusiveMode ){
  1443   1454       rc2 = osUnlock(pPager->fd, SHARED_LOCK);
  1444   1455       pPager->state = PAGER_SHARED;
  1445   1456       pPager->changeCountDone = 0;
  1446   1457     }else if( pPager->state==PAGER_SYNCED ){
  1447   1458       pPager->state = PAGER_EXCLUSIVE;
  1448   1459     }
................................................................................
  3062   3073     u8 *pTmp = (u8 *)pPager->pTmpSpace;
  3063   3074   
  3064   3075     disable_simulated_io_errors();
  3065   3076     sqlite3BeginBenignMalloc();
  3066   3077     pPager->errCode = 0;
  3067   3078     pPager->exclusiveMode = 0;
  3068   3079   #ifndef SQLITE_OMIT_WAL
  3069         -  sqlite3WalClose(pPager->pWal, pPager->fd, 
         3080  +  sqlite3WalClose(pPager->pWal,
  3070   3081       (pPager->noSync ? 0 : pPager->sync_flags), 
  3071   3082       pPager->pageSize, pTmp
  3072   3083     );
  3073   3084     pPager->pWal = 0;
  3074   3085   #endif
  3075   3086     pager_reset(pPager);
  3076   3087     if( MEMDB ){
................................................................................
  4505   4516   ** sub-journal is implemented in-memory if pPager is an in-memory database, 
  4506   4517   ** or using a temporary file otherwise.
  4507   4518   */
  4508   4519   int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
  4509   4520     int rc = SQLITE_OK;
  4510   4521     assert( pPager->state!=PAGER_UNLOCK );
  4511   4522     pPager->subjInMemory = (u8)subjInMemory;
         4523  +
  4512   4524     if( pPager->state==PAGER_SHARED ){
  4513   4525       assert( pPager->pInJournal==0 );
  4514   4526       assert( !MEMDB && !pPager->tempFile );
  4515   4527   
  4516   4528       if( pagerUseWal(pPager) ){
         4529  +      /* If the pager is configured to use locking_mode=exclusive, and an
         4530  +      ** exclusive lock on the database is not already held, obtain it now.
         4531  +      */
         4532  +      if( pPager->exclusiveMode && !sqlite3WalExclusiveMode(pPager->pWal, -1) ){
         4533  +        rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
         4534  +        pPager->state = PAGER_SHARED;
         4535  +        if( rc!=SQLITE_OK ){
         4536  +          return rc;
         4537  +        }
         4538  +        sqlite3WalExclusiveMode(pPager->pWal, 1);
         4539  +      }
         4540  +
  4517   4541         /* Grab the write lock on the log file. If successful, upgrade to
  4518         -      ** PAGER_EXCLUSIVE state. Otherwise, return an error code to the caller.
         4542  +      ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
  4519   4543         ** The busy-handler is not invoked if another connection already
  4520   4544         ** holds the write-lock. If possible, the upper layer will call it.
         4545  +      **
         4546  +      ** WAL mode sets Pager.state to PAGER_RESERVED when it has an open
         4547  +      ** transaction, but never to PAGER_EXCLUSIVE. This is because in 
         4548  +      ** PAGER_EXCLUSIVE state the code to roll back savepoint transactions
         4549  +      ** may copy data from the sub-journal into the database file as well
         4550  +      ** as into the page cache. Which would be incorrect in WAL mode.
  4521   4551         */
  4522   4552         rc = sqlite3WalWriteLock(pPager->pWal, 1);
  4523   4553         if( rc==SQLITE_OK ){
  4524   4554           pPager->dbOrigSize = pPager->dbSize;
  4525   4555           pPager->state = PAGER_RESERVED;
  4526   4556           pPager->journalOff = 0;
  4527   4557         }
         4558  +
         4559  +      assert( rc!=SQLITE_OK || pPager->state==PAGER_RESERVED );
         4560  +      assert( rc==SQLITE_OK || pPager->state==PAGER_SHARED );
  4528   4561       }else{
  4529   4562         /* Obtain a RESERVED lock on the database file. If the exFlag parameter
  4530   4563         ** is true, then immediately upgrade this to an EXCLUSIVE lock. The
  4531   4564         ** busy-handler callback can be used when upgrading to the EXCLUSIVE
  4532   4565         ** lock, but not when obtaining the RESERVED lock.
  4533   4566         */
  4534   4567         rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
................................................................................
  5841   5874   /*
  5842   5875   ** This function is called when the user invokes "PRAGMA checkpoint".
  5843   5876   */
  5844   5877   int sqlite3PagerCheckpoint(Pager *pPager){
  5845   5878     int rc = SQLITE_OK;
  5846   5879     if( pPager->pWal ){
  5847   5880       u8 *zBuf = (u8 *)pPager->pTmpSpace;
  5848         -    rc = sqlite3WalCheckpoint(pPager->pWal, pPager->fd, 
         5881  +    rc = sqlite3WalCheckpoint(pPager->pWal,
  5849   5882           (pPager->noSync ? 0 : pPager->sync_flags),
  5850   5883           pPager->pageSize, zBuf, 
  5851   5884           pPager->xBusyHandler, pPager->pBusyHandlerArg
  5852   5885       );
  5853   5886     }
  5854   5887     return rc;
  5855   5888   }
  5856   5889   
  5857   5890   int sqlite3PagerWalCallback(Pager *pPager){
  5858   5891     return sqlite3WalCallback(pPager->pWal);
  5859   5892   }
         5893  +
         5894  +/*
         5895  +** Return true if the underlying VFS for the given pager supports the
         5896  +** primitives necessary for write-ahead logging.
         5897  +*/
         5898  +int sqlite3PagerWalSupported(Pager *pPager){
         5899  +  const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
         5900  +  return pMethods->iVersion>=2 && pMethods->xShmOpen!=0;
         5901  +}
  5860   5902   
  5861   5903   /*
  5862   5904   ** Open a connection to the write-ahead log file for pager pPager. If
  5863   5905   ** the log connection is already open, this function is a no-op.
  5864   5906   **
  5865   5907   ** The caller must be holding a SHARED lock on the database file to call
  5866   5908   ** this function.
  5867   5909   */
  5868   5910   int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){
  5869   5911     int rc = SQLITE_OK;             /* Return code */
  5870   5912   
  5871   5913     assert( pPager->state>=PAGER_SHARED );
  5872   5914     if( !pPager->pWal ){
         5915  +    if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
  5873   5916   
  5874   5917       /* Open the connection to the log file. If this operation fails, 
  5875   5918       ** (e.g. due to malloc() failure), unlock the database file and 
  5876   5919       ** return an error code.
  5877   5920       */
  5878         -    rc = sqlite3WalOpen(pPager->pVfs, pPager->zFilename, &pPager->pWal);
         5921  +    rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
         5922  +                        pPager->zFilename, &pPager->pWal);
  5879   5923       if( rc==SQLITE_OK ){
  5880   5924         pPager->journalMode = PAGER_JOURNALMODE_WAL;
  5881   5925       }
  5882   5926     }else{
  5883   5927       *pisOpen = 1;
  5884   5928     }
  5885   5929   
................................................................................
  5907   5951     if( !pPager->pWal ){
  5908   5952       int logexists = 0;
  5909   5953       rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED);
  5910   5954       if( rc==SQLITE_OK ){
  5911   5955         rc = pagerHasWAL(pPager, &logexists);
  5912   5956       }
  5913   5957       if( rc==SQLITE_OK && logexists ){
  5914         -      rc = sqlite3WalOpen(pPager->pVfs, pPager->zFilename, &pPager->pWal);
         5958  +      rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
         5959  +                          pPager->zFilename, &pPager->pWal);
  5915   5960       }
  5916   5961     }
  5917   5962       
  5918   5963     /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
  5919   5964     ** the database file, the log and log-summary files will be deleted.
  5920   5965     */
  5921   5966     if( rc==SQLITE_OK && pPager->pWal ){
  5922   5967       rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_EXCLUSIVE);
  5923   5968       if( rc==SQLITE_OK ){
  5924         -      rc = sqlite3WalClose(pPager->pWal, pPager->fd,
  5925         -        (pPager->noSync ? 0 : pPager->sync_flags), 
         5969  +      rc = sqlite3WalClose(pPager->pWal,
         5970  +                           (pPager->noSync ? 0 : pPager->sync_flags), 
  5926   5971           pPager->pageSize, (u8*)pPager->pTmpSpace
  5927   5972         );
  5928   5973         pPager->pWal = 0;
         5974  +    }else{
         5975  +      /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
         5976  +      ** that we did get back to SHARED. */
         5977  +      sqlite3OsUnlock(pPager->fd, SQLITE_LOCK_SHARED);
  5929   5978       }
  5930   5979     }
  5931   5980     return rc;
  5932   5981   }
  5933   5982   #endif
  5934   5983   
  5935   5984   #endif /* SQLITE_OMIT_DISKIO */

Changes to src/pager.h.

   131    131   int sqlite3PagerCommitPhaseTwo(Pager*);
   132    132   int sqlite3PagerRollback(Pager*);
   133    133   int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
   134    134   int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
   135    135   int sqlite3PagerSharedLock(Pager *pPager);
   136    136   
   137    137   int sqlite3PagerCheckpoint(Pager *pPager);
          138  +int sqlite3PagerWalSupported(Pager *pPager);
   138    139   int sqlite3PagerWalCallback(Pager *pPager);
   139    140   int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
   140    141   int sqlite3PagerCloseWal(Pager *pPager);
   141    142   
   142    143   /* Functions used to query pager state and configuration. */
   143    144   u8 sqlite3PagerIsreadonly(Pager*);
   144    145   int sqlite3PagerRefcount(Pager*);

Changes to src/sqlite.h.in.

   649    649     int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
   650    650     int (*xLock)(sqlite3_file*, int);
   651    651     int (*xUnlock)(sqlite3_file*, int);
   652    652     int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
   653    653     int (*xFileControl)(sqlite3_file*, int op, void *pArg);
   654    654     int (*xSectorSize)(sqlite3_file*);
   655    655     int (*xDeviceCharacteristics)(sqlite3_file*);
          656  +  /* Methods above are valid for version 1 */
          657  +  int (*xShmOpen)(sqlite3_file*);
          658  +  int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize);
          659  +  int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void**);
          660  +  int (*xShmRelease)(sqlite3_file*);
          661  +  int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock);
          662  +  int (*xShmClose)(sqlite3_file*, int deleteFlag);
          663  +  /* Methods above are valid for version 2 */
   656    664     /* Additional methods may be added in future releases */
   657    665   };
   658    666   
   659    667   /*
   660    668   ** CAPI3REF: Standard File Control Opcodes
   661    669   **
   662    670   ** These integer constants are opcodes for the xFileControl method
................................................................................
   814    822   ** the actual number of bytes of randomness obtained.
   815    823   ** The xSleep() method causes the calling thread to sleep for at
   816    824   ** least the number of microseconds given.  The xCurrentTime()
   817    825   ** method returns a Julian Day Number for the current date and time.
   818    826   **
   819    827   */
   820    828   typedef struct sqlite3_vfs sqlite3_vfs;
   821         -typedef struct sqlite3_shm sqlite3_shm;
   822    829   struct sqlite3_vfs {
   823    830     int iVersion;            /* Structure version number (currently 2) */
   824    831     int szOsFile;            /* Size of subclassed sqlite3_file */
   825    832     int mxPathname;          /* Maximum file pathname length */
   826    833     sqlite3_vfs *pNext;      /* Next registered VFS */
   827    834     const char *zName;       /* Name of this virtual file system */
   828    835     void *pAppData;          /* Pointer to application-specific data */
................................................................................
   839    846     int (*xSleep)(sqlite3_vfs*, int microseconds);
   840    847     int (*xCurrentTime)(sqlite3_vfs*, double*);
   841    848     int (*xGetLastError)(sqlite3_vfs*, int, char *);
   842    849     /*
   843    850     ** The methods above are in version 1 of the sqlite_vfs object
   844    851     ** definition.  Those that follow are added in version 2 or later
   845    852     */
   846         -  int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**);
   847         -  int (*xShmSize)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pNewSize);
   848         -  int (*xShmGet)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pSize, void**);
   849         -  int (*xShmRelease)(sqlite3_vfs*, sqlite3_shm*);
   850         -  int (*xShmLock)(sqlite3_vfs*, sqlite3_shm*, int desiredLock, int *gotLock);
   851         -  int (*xShmClose)(sqlite3_vfs*, sqlite3_shm*, int deleteFlag);
   852    853     int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
   853    854     int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
   854    855     /*
   855    856     ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
   856    857     ** New fields may be appended in figure versions.  The iVersion
   857    858     ** value will increment whenever this happens. 
   858    859     */

Changes to src/test1.c.

  5125   5125     extern int sqlite3_sync_count, sqlite3_fullsync_count;
  5126   5126     extern int sqlite3_opentemp_count;
  5127   5127     extern int sqlite3_like_count;
  5128   5128     extern int sqlite3_xferopt_count;
  5129   5129     extern int sqlite3_pager_readdb_count;
  5130   5130     extern int sqlite3_pager_writedb_count;
  5131   5131     extern int sqlite3_pager_writej_count;
  5132         -#if defined(__linux__) && defined(SQLITE_TEST) && SQLITE_THREADSAFE
  5133         -  extern int threadsOverrideEachOthersLocks;
  5134         -#endif
  5135   5132   #if SQLITE_OS_WIN
  5136   5133     extern int sqlite3_os_type;
  5137   5134   #endif
  5138   5135   #ifdef SQLITE_DEBUG
  5139   5136     extern int sqlite3WhereTrace;
  5140   5137     extern int sqlite3OSTrace;
  5141   5138     extern int sqlite3VdbeAddopTrace;
................................................................................
  5183   5180         (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
  5184   5181     Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
  5185   5182         (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
  5186   5183   #ifndef SQLITE_OMIT_UTF16
  5187   5184     Tcl_LinkVar(interp, "unaligned_string_counter",
  5188   5185         (char*)&unaligned_string_counter, TCL_LINK_INT);
  5189   5186   #endif
  5190         -#if defined(__linux__) && defined(SQLITE_TEST) && SQLITE_THREADSAFE
  5191         -  Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks",
  5192         -      (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT);
  5193         -#endif
  5194   5187   #ifndef SQLITE_OMIT_UTF16
  5195   5188     Tcl_LinkVar(interp, "sqlite_last_needed_collation",
  5196   5189         (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
  5197   5190   #endif
  5198   5191   #if SQLITE_OS_WIN
  5199   5192     Tcl_LinkVar(interp, "sqlite_os_type",
  5200   5193         (char*)&sqlite3_os_type, TCL_LINK_INT);

Changes to src/test6.c.

   515    515   */
   516    516   static int cfSectorSize(sqlite3_file *pFile){
   517    517     return g.iSectorSize;
   518    518   }
   519    519   static int cfDeviceCharacteristics(sqlite3_file *pFile){
   520    520     return g.iDeviceCharacteristics;
   521    521   }
          522  +
          523  +/*
          524  +** Pass-throughs for WAL support.
          525  +*/
          526  +static int cfShmOpen(sqlite3_file *pFile){
          527  +  return sqlite3OsShmOpen(((CrashFile*)pFile)->pRealFile);
          528  +}
          529  +static int cfShmSize(sqlite3_file *pFile, int reqSize, int *pNew){
          530  +  return sqlite3OsShmSize(((CrashFile*)pFile)->pRealFile, reqSize, pNew);
          531  +}
          532  +static int cfShmGet(sqlite3_file *pFile, int reqSize, int *pSize, void **pp){
          533  +  return sqlite3OsShmGet(((CrashFile*)pFile)->pRealFile, reqSize, pSize, pp);
          534  +}
          535  +static int cfShmRelease(sqlite3_file *pFile){
          536  +  return sqlite3OsShmRelease(((CrashFile*)pFile)->pRealFile);
          537  +}
          538  +static int cfShmLock(sqlite3_file *pFile, int desired, int *pGot){
          539  +  return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, desired, pGot);
          540  +}
          541  +static int cfShmClose(sqlite3_file *pFile, int delFlag){
          542  +  return sqlite3OsShmClose(((CrashFile*)pFile)->pRealFile, delFlag);
          543  +}
          544  +
   522    545   
   523    546   static const sqlite3_io_methods CrashFileVtab = {
   524         -  1,                            /* iVersion */
          547  +  2,                            /* iVersion */
   525    548     cfClose,                      /* xClose */
   526    549     cfRead,                       /* xRead */
   527    550     cfWrite,                      /* xWrite */
   528    551     cfTruncate,                   /* xTruncate */
   529    552     cfSync,                       /* xSync */
   530    553     cfFileSize,                   /* xFileSize */
   531    554     cfLock,                       /* xLock */
   532    555     cfUnlock,                     /* xUnlock */
   533    556     cfCheckReservedLock,          /* xCheckReservedLock */
   534    557     cfFileControl,                /* xFileControl */
   535    558     cfSectorSize,                 /* xSectorSize */
   536         -  cfDeviceCharacteristics       /* xDeviceCharacteristics */
          559  +  cfDeviceCharacteristics,      /* xDeviceCharacteristics */
          560  +  cfShmOpen,                    /* xShmOpen */
          561  +  cfShmSize,                    /* xShmSize */
          562  +  cfShmGet,                     /* xShmGet */
          563  +  cfShmRelease,                 /* xShmRelease */
          564  +  cfShmLock,                    /* xShmLock */
          565  +  cfShmClose                    /* xShmClose */
   537    566   };
   538    567   
   539    568   /*
   540    569   ** Application data for the crash VFS
   541    570   */
   542    571   struct crashAppData {
   543    572     sqlite3_vfs *pOrig;                   /* Wrapped vfs structure */
................................................................................
   653    682     sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   654    683     return pVfs->xSleep(pVfs, nMicro);
   655    684   }
   656    685   static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
   657    686     sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   658    687     return pVfs->xCurrentTime(pVfs, pTimeOut);
   659    688   }
   660         -static int cfShmOpen(sqlite3_vfs *pCfVfs, const char *zName, sqlite3_shm **pp){
   661         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   662         -  return pVfs->xShmOpen(pVfs, zName, pp);
   663         -}
   664         -static int cfShmSize(sqlite3_vfs *pCfVfs, sqlite3_shm *p,
   665         -                     int reqSize, int *pNew){
   666         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   667         -  return pVfs->xShmSize(pVfs, p, reqSize, pNew);
   668         -}
   669         -static int cfShmGet(sqlite3_vfs *pCfVfs, sqlite3_shm *p,
   670         -                    int reqSize, int *pSize, void **pp){
   671         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   672         -  return pVfs->xShmGet(pVfs, p, reqSize, pSize, pp);
   673         -}
   674         -static int cfShmRelease(sqlite3_vfs *pCfVfs, sqlite3_shm *p){
   675         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   676         -  return pVfs->xShmRelease(pVfs, p);
   677         -}
   678         -static int cfShmLock(sqlite3_vfs *pCfVfs, sqlite3_shm *p,
   679         -                     int desiredLock, int *gotLock){
   680         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   681         -  return pVfs->xShmLock(pVfs, p, desiredLock, gotLock);
   682         -}
   683         -static int cfShmClose(sqlite3_vfs *pCfVfs, sqlite3_shm *p, int delFlag){
   684         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   685         -  return pVfs->xShmClose(pVfs, p, delFlag);
   686         -}
   687    689   
   688    690   static int processDevSymArgs(
   689    691     Tcl_Interp *interp,
   690    692     int objc,
   691    693     Tcl_Obj *CONST objv[],
   692    694     int *piDeviceChar,
   693    695     int *piSectorSize
................................................................................
   806    808       cfDlError,            /* xDlError */
   807    809       cfDlSym,              /* xDlSym */
   808    810       cfDlClose,            /* xDlClose */
   809    811       cfRandomness,         /* xRandomness */
   810    812       cfSleep,              /* xSleep */
   811    813       cfCurrentTime,        /* xCurrentTime */
   812    814       0,                    /* xGetlastError */
   813         -    cfShmOpen,            /* xShmOpen */
   814         -    cfShmSize,            /* xShmSize */
   815         -    cfShmGet,             /* xShmGet */
   816         -    cfShmRelease,         /* xShmRelease */
   817         -    cfShmLock,            /* xShmLock */
   818         -    cfShmClose,           /* xShmClose */
   819    815       0,                    /* xRename */
   820    816       0,                    /* xCurrentTimeInt64 */
   821    817     };
   822    818   
   823    819     if( objc!=2 ){
   824    820       Tcl_WrongNumArgs(interp, 1, objv, "ENABLE");
   825    821       return TCL_ERROR;
................................................................................
   834    830     }
   835    831   
   836    832     if( crashVfs.pAppData==0 ){
   837    833       sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0);
   838    834       crashVfs.mxPathname = pOriginalVfs->mxPathname;
   839    835       crashVfs.pAppData = (void *)pOriginalVfs;
   840    836       crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;
   841         -    if( pOriginalVfs->iVersion<2 || pOriginalVfs->xShmOpen==0 ){
   842         -      crashVfs.xShmOpen = 0;
   843         -    }else{
   844         -      crashVfs.xShmOpen = cfShmOpen;
   845         -    }
   846    837       sqlite3_vfs_register(&crashVfs, 0);
   847    838     }else{
   848    839       crashVfs.pAppData = 0;
   849    840       sqlite3_vfs_unregister(&crashVfs);
   850    841     }
   851    842   
   852    843     return TCL_OK;

Changes to src/test_devsym.c.

    46     46   static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize);
    47     47   static int devsymLock(sqlite3_file*, int);
    48     48   static int devsymUnlock(sqlite3_file*, int);
    49     49   static int devsymCheckReservedLock(sqlite3_file*, int *);
    50     50   static int devsymFileControl(sqlite3_file*, int op, void *pArg);
    51     51   static int devsymSectorSize(sqlite3_file*);
    52     52   static int devsymDeviceCharacteristics(sqlite3_file*);
           53  +static int devsymShmOpen(sqlite3_file*);
           54  +static int devsymShmSize(sqlite3_file*,int,int*);
           55  +static int devsymShmGet(sqlite3_file*,int,int*,void**);
           56  +static int devsymShmRelease(sqlite3_file*);
           57  +static int devsymShmLock(sqlite3_file*,int,int*);
           58  +static int devsymShmClose(sqlite3_file*,int);
    53     59   
    54     60   /*
    55     61   ** Method declarations for devsym_vfs.
    56     62   */
    57     63   static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
    58     64   static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir);
    59     65   static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *);
................................................................................
    64     70   static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
    65     71   static void devsymDlClose(sqlite3_vfs*, void*);
    66     72   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
    67     73   static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
    68     74   static int devsymSleep(sqlite3_vfs*, int microseconds);
    69     75   static int devsymCurrentTime(sqlite3_vfs*, double*);
    70     76   
    71         -static int devsymShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **);
    72         -static int devsymShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *);
    73         -static int devsymShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **);
    74         -static int devsymShmRelease(sqlite3_vfs*, sqlite3_shm *);
    75         -static int devsymShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *);
    76         -static int devsymShmClose(sqlite3_vfs*, sqlite3_shm *, int);
    77         -
    78     77   static sqlite3_vfs devsym_vfs = {
    79     78     2,                     /* iVersion */
    80     79     sizeof(devsym_file),      /* szOsFile */
    81     80     DEVSYM_MAX_PATHNAME,      /* mxPathname */
    82     81     0,                     /* pNext */
    83     82     DEVSYM_VFS_NAME,          /* zName */
    84     83     0,                     /* pAppData */
................................................................................
    97     96     0,                        /* xDlSym */
    98     97     0,                        /* xDlClose */
    99     98   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
   100     99     devsymRandomness,         /* xRandomness */
   101    100     devsymSleep,              /* xSleep */
   102    101     devsymCurrentTime,        /* xCurrentTime */
   103    102     0,                        /* xGetLastError */
   104         -  devsymShmOpen,
   105         -  devsymShmSize,
   106         -  devsymShmGet,
   107         -  devsymShmRelease,
   108         -  devsymShmLock,
   109         -  devsymShmClose,
   110         -  0,
   111         -  0,
          103  +  0,                        /* xRename */
          104  +  0                         /* xCurrentTimeInt64 */
   112    105   };
   113    106   
   114    107   static sqlite3_io_methods devsym_io_methods = {
   115         -  1,                            /* iVersion */
          108  +  2,                                /* iVersion */
   116    109     devsymClose,                      /* xClose */
   117    110     devsymRead,                       /* xRead */
   118    111     devsymWrite,                      /* xWrite */
   119    112     devsymTruncate,                   /* xTruncate */
   120    113     devsymSync,                       /* xSync */
   121    114     devsymFileSize,                   /* xFileSize */
   122    115     devsymLock,                       /* xLock */
   123    116     devsymUnlock,                     /* xUnlock */
   124    117     devsymCheckReservedLock,          /* xCheckReservedLock */
   125    118     devsymFileControl,                /* xFileControl */
   126    119     devsymSectorSize,                 /* xSectorSize */
   127         -  devsymDeviceCharacteristics       /* xDeviceCharacteristics */
          120  +  devsymDeviceCharacteristics,      /* xDeviceCharacteristics */
          121  +  devsymShmOpen,                    /* xShmOpen */
          122  +  devsymShmSize,                    /* xShmSize */
          123  +  devsymShmGet,                     /* xShmGet */
          124  +  devsymShmRelease,                 /* xShmRelease */
          125  +  devsymShmLock,                    /* xShmLock */
          126  +  devsymShmClose                    /* xShmClose */
   128    127   };
   129    128   
   130    129   struct DevsymGlobal {
   131    130     sqlite3_vfs *pVfs;
   132    131     int iDeviceChar;
   133    132     int iSectorSize;
   134    133   };
................................................................................
   233    232   
   234    233   /*
   235    234   ** Return the device characteristic flags supported by an devsym-file.
   236    235   */
   237    236   static int devsymDeviceCharacteristics(sqlite3_file *pFile){
   238    237     return g.iDeviceChar;
   239    238   }
          239  +
          240  +/*
          241  +** Shared-memory methods are all pass-thrus.
          242  +*/
          243  +static int devsymShmOpen(sqlite3_file *pFile){
          244  +  devsym_file *p = (devsym_file *)pFile;
          245  +  return sqlite3OsShmOpen(p->pReal);
          246  +}
          247  +static int devsymShmSize(sqlite3_file *pFile, int reqSize, int *pSize){
          248  +  devsym_file *p = (devsym_file *)pFile;
          249  +  return sqlite3OsShmSize(p->pReal, reqSize, pSize);
          250  +}
          251  +static int devsymShmGet(sqlite3_file *pFile, int reqSz, int *pSize, void **pp){
          252  +  devsym_file *p = (devsym_file *)pFile;
          253  +  return sqlite3OsShmGet(p->pReal, reqSz, pSize, pp);
          254  +}
          255  +static int devsymShmRelease(sqlite3_file *pFile){
          256  +  devsym_file *p = (devsym_file *)pFile;
          257  +  return sqlite3OsShmRelease(p->pReal);
          258  +}
          259  +static int devsymShmLock(sqlite3_file *pFile, int desired, int *pGot){
          260  +  devsym_file *p = (devsym_file *)pFile;
          261  +  return sqlite3OsShmLock(p->pReal, desired, pGot);
          262  +}
          263  +static int devsymShmClose(sqlite3_file *pFile, int delFlag){
          264  +  devsym_file *p = (devsym_file *)pFile;
          265  +  return sqlite3OsShmClose(p->pReal, delFlag);
          266  +}
          267  +
          268  +
   240    269   
   241    270   /*
   242    271   ** Open an devsym file handle.
   243    272   */
   244    273   static int devsymOpen(
   245    274     sqlite3_vfs *pVfs,
   246    275     const char *zName,
................................................................................
   346    375   ** Return the current time as a Julian Day number in *pTimeOut.
   347    376   */
   348    377   static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
   349    378     return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
   350    379   }
   351    380   
   352    381   
   353         -static int devsymShmOpen(
   354         -  sqlite3_vfs *pVfs, 
   355         -  const char *zName, 
   356         -  sqlite3_shm **pp
   357         -){
   358         -  return g.pVfs->xShmOpen(g.pVfs, zName, pp);
   359         -}
   360         -static int devsymShmSize(
   361         -  sqlite3_vfs *pVfs,
   362         -  sqlite3_shm *p,
   363         -  int reqSize,
   364         -  int *pNewSize
   365         -){
   366         -  return g.pVfs->xShmSize(g.pVfs, p, reqSize, pNewSize);
   367         -}
   368         -static int devsymShmGet(
   369         -  sqlite3_vfs *pVfs,
   370         -  sqlite3_shm *p, 
   371         -  int reqMapSize, 
   372         -  int *pMapSize, 
   373         -  void **pp
   374         -){
   375         -  return g.pVfs->xShmGet(g.pVfs, p, reqMapSize, pMapSize, pp);
   376         -}
   377         -static int devsymShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *p){
   378         -  return g.pVfs->xShmRelease(g.pVfs, p);
   379         -}
   380         -static int devsymShmLock(
   381         -  sqlite3_vfs *pVfs,
   382         -  sqlite3_shm *p,
   383         -  int desiredLock,
   384         -  int *gotLock
   385         -){
   386         -  return g.pVfs->xShmLock(g.pVfs, p, desiredLock, gotLock);
   387         -}
   388         -static int devsymShmClose(sqlite3_vfs *pVfs, sqlite3_shm *p, int deleteFlag){
   389         -  return g.pVfs->xShmClose(g.pVfs, p, deleteFlag);
   390         -}
   391         -
   392    382   /*
   393    383   ** This procedure registers the devsym vfs with SQLite. If the argument is
   394    384   ** true, the devsym vfs becomes the new default vfs. It is the only publicly
   395    385   ** available function in this file.
   396    386   */
   397    387   void devsym_register(int iDeviceChar, int iSectorSize){
   398    388     if( g.pVfs==0 ){
   399    389       g.pVfs = sqlite3_vfs_find(0);
   400    390       devsym_vfs.szOsFile += g.pVfs->szOsFile;
   401         -    devsym_vfs.xShmOpen = (g.pVfs->xShmOpen ? devsymShmOpen : 0);
   402         -    devsym_vfs.xShmSize = (g.pVfs->xShmSize ? devsymShmSize : 0);
   403         -    devsym_vfs.xShmGet = (g.pVfs->xShmGet ? devsymShmGet : 0);
   404         -    devsym_vfs.xShmRelease = (g.pVfs->xShmRelease ? devsymShmRelease : 0);
   405         -    devsym_vfs.xShmLock = (g.pVfs->xShmLock ? devsymShmLock : 0);
   406         -    devsym_vfs.xShmClose = (g.pVfs->xShmClose ? devsymShmClose : 0);
   407    391       sqlite3_vfs_register(&devsym_vfs, 0);
   408    392     }
   409    393     if( iDeviceChar>=0 ){
   410    394       g.iDeviceChar = iDeviceChar;
   411    395     }else{
   412    396       g.iDeviceChar = 0;
   413    397     }

Changes to src/test_onefile.c.

   195    195       fsDlOpen,                                   /* xDlOpen */
   196    196       fsDlError,                                  /* xDlError */
   197    197       fsDlSym,                                    /* xDlSym */
   198    198       fsDlClose,                                  /* xDlClose */
   199    199       fsRandomness,                               /* xRandomness */
   200    200       fsSleep,                                    /* xSleep */
   201    201       fsCurrentTime,                              /* xCurrentTime */
   202         -    0,                                          /* xShmOpen */
   203         -    0,                                          /* xShmSize */
   204         -    0,                                          /* xShmLock */
   205         -    0,                                          /* xShmClose */
   206         -    0,                                          /* xShmDelete */
   207    202       0,                                          /* xRename */
   208    203       0                                           /* xCurrentTimeInt64 */
   209    204     }, 
   210    205     0,                                            /* pFileList */
   211    206     0                                             /* pParent */
   212    207   };
   213    208   
................................................................................
   220    215     fsSync,                       /* xSync */
   221    216     fsFileSize,                   /* xFileSize */
   222    217     fsLock,                       /* xLock */
   223    218     fsUnlock,                     /* xUnlock */
   224    219     fsCheckReservedLock,          /* xCheckReservedLock */
   225    220     fsFileControl,                /* xFileControl */
   226    221     fsSectorSize,                 /* xSectorSize */
   227         -  fsDeviceCharacteristics       /* xDeviceCharacteristics */
          222  +  fsDeviceCharacteristics,      /* xDeviceCharacteristics */
          223  +  0,                            /* xShmOpen */
          224  +  0,                            /* xShmSize */
          225  +  0,                            /* xShmLock */
          226  +  0,                            /* xShmClose */
          227  +  0,                            /* xShmDelete */
   228    228   };
   229    229   
   230    230   
   231    231   static sqlite3_io_methods tmp_io_methods = {
   232    232     1,                            /* iVersion */
   233    233     tmpClose,                     /* xClose */
   234    234     tmpRead,                      /* xRead */
................................................................................
   237    237     tmpSync,                      /* xSync */
   238    238     tmpFileSize,                  /* xFileSize */
   239    239     tmpLock,                      /* xLock */
   240    240     tmpUnlock,                    /* xUnlock */
   241    241     tmpCheckReservedLock,         /* xCheckReservedLock */
   242    242     tmpFileControl,               /* xFileControl */
   243    243     tmpSectorSize,                /* xSectorSize */
   244         -  tmpDeviceCharacteristics      /* xDeviceCharacteristics */
          244  +  tmpDeviceCharacteristics,     /* xDeviceCharacteristics */
          245  +  0,                            /* xShmOpen */
          246  +  0,                            /* xShmSize */
          247  +  0,                            /* xShmLock */
          248  +  0,                            /* xShmClose */
          249  +  0,                            /* xShmDelete */
   245    250   };
   246    251   
   247    252   /* Useful macros used in several places */
   248    253   #define MIN(x,y) ((x)<(y)?(x):(y))
   249    254   #define MAX(x,y) ((x)>(y)?(x):(y))
   250    255   
   251    256   

Changes to src/test_osinst.c.

    11     11   ******************************************************************************
    12     12   **
    13     13   ** This file contains the implementation of an SQLite vfs wrapper that
    14     14   ** adds instrumentation to all vfs and file methods. C and Tcl interfaces
    15     15   ** are provided to control the instrumentation.
    16     16   */
    17     17   
    18         -#ifdef SQLITE_ENABLE_INSTVFS
    19     18   /*
    20         -** C interface:
           19  +** This module contains code for a wrapper VFS that causes a log of
           20  +** all (well, technically "most") VFS calls to be written into a nominated
           21  +** file on disk. The log is stored in a compressed binary format to 
           22  +** reduce the amount of IO overhead introduced into the application
           23  +** by logging.
           24  +**
           25  +** The binary log files are read using a virtual table implementation
           26  +** also contained in this file. 
           27  +**
           28  +** CREATING LOG FILES:
           29  +**
           30  +**       int sqlite3_vfslog_new(
           31  +**         const char *zVfs,          // Name of new VFS
           32  +**         const char *zParentVfs,    // Name of parent VFS (or NULL)
           33  +**         const char *zLog           // Name of log file to write to
           34  +**       );
           35  +**
           36  +**       int sqlite3_vfslog_finalize(const char *zVfs);
           37  +**
           38  +** ANNOTATING LOG FILES:
           39  +**
           40  +**   To write an arbitrary message into a log file:
           41  +**
           42  +**       int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg);
           43  +**
           44  +** READING LOG FILES:
           45  +**
           46  +**   Log files are read using the "vfslog" virtual table implementation
           47  +**   in this file. To register the virtual table with SQLite, use:
    21     48   **
    22         -**   sqlite3_instvfs_create()
    23         -**   sqlite3_instvfs_destroy()
    24         -**   sqlite3_instvfs_configure()
           49  +**       int sqlite3_vfslog_register(sqlite3 *db);
    25     50   **
    26         -**   sqlite3_instvfs_reset()
    27         -**   sqlite3_instvfs_get()
           51  +**   Then, if the log file is named "vfs.log", the following SQL command:
    28     52   **
    29         -**   sqlite3_instvfs_binarylog
    30         -**   sqlite3_instvfs_binarylog_marker
    31         -**
    32         -** Tcl interface (omitted if SQLITE_TEST is not set):
    33         -** 
    34         -**   sqlite3_instvfs create NAME ?PARENT?
           53  +**       CREATE VIRTUAL TABLE v USING vfslog('vfs.log');
    35     54   **
    36         -**       Create and register new vfs called $NAME, which is a wrapper around
    37         -**       the existing vfs $PARENT. If the PARENT argument is omitted, the
    38         -**       new vfs is a wrapper around the current default vfs.
    39         -**
    40         -**   sqlite3_instvfs destroy NAME
    41         -**
    42         -**       Deregister and destroy the vfs named $NAME, which must have been
    43         -**       created by an earlier invocation of [sqlite3_instvfs create].
    44         -**
    45         -**   sqlite3_instvfs configure NAME SCRIPT
    46         -**
    47         -**       Configure the callback script for the vfs $NAME, which much have
    48         -**       been created by an earlier invocation of [sqlite3_instvfs create].
    49         -**       After a callback script has been configured, it is invoked each
    50         -**       time a vfs or file method is called by SQLite. Before invoking
    51         -**       the callback script, five arguments are appended to it:
           55  +**   creates a virtual table with 6 columns, as follows:
    52     56   **
    53         -**         * The name of the invoked method - i.e. "xRead".
    54         -**
    55         -**         * The time consumed by the method call as measured by 
    56         -**           sqlite3Hwtime() (an integer value)
    57         -**
    58         -**         * A string value with a different meaning for different calls. 
    59         -**           For file methods, the name of the file being operated on. For
    60         -**           other methods it is the filename argument, if any.
    61         -**
    62         -**         * A 32-bit integer value with a call-specific meaning.
    63         -**
    64         -**         * A 64-bit integer value. For xRead() and xWrite() calls this
    65         -**           is the file offset being written to or read from. Unused by
    66         -**           all other calls.
    67         -**
    68         -**   sqlite3_instvfs reset NAME
    69         -**
    70         -**       Zero the internal event counters associated with vfs $NAME, 
    71         -**       which must have been created by an earlier invocation of 
    72         -**       [sqlite3_instvfs create].
    73         -**
    74         -**   sqlite3_instvfs report NAME
    75         -**
    76         -**       Return the values of the internal event counters associated 
    77         -**       with vfs $NAME. The report format is a list with one element
    78         -**       for each method call (xWrite, xRead etc.). Each element is
    79         -**       itself a list with three elements:
    80         -**
    81         -**         * The name of the method call - i.e. "xWrite",
    82         -**         * The total number of calls to the method (an integer).
    83         -**         * The aggregate time consumed by all calls to the method as
    84         -**           measured by sqlite3Hwtime() (an integer).
           57  +**       CREATE TABLE v(
           58  +**         event    TEXT,             // "xOpen", "xRead" etc.
           59  +**         file     TEXT,             // Name of file this call applies to
           60  +**         clicks   INTEGER,          // Time spent in call
           61  +**         rc       INTEGER,          // Return value
           62  +**         size     INTEGER,          // Bytes read or written
           63  +**         offset   INTEGER           // File offset read or written
           64  +**       );
    85     65   */
    86     66   
    87     67   #include "sqlite3.h"
    88     68   #include <string.h>
    89     69   #include <assert.h>
           70  +
    90     71   
    91     72   /*
    92         -** Maximum pathname length supported by the inst backend.
           73  +** Maximum pathname length supported by the vfslog backend.
    93     74   */
    94     75   #define INST_MAX_PATHNAME 512
    95     76   
    96         -
    97         -/* File methods */
    98         -/* Vfs methods */
    99     77   #define OS_ACCESS            1
   100     78   #define OS_CHECKRESERVEDLOCK 2
   101     79   #define OS_CLOSE             3
   102     80   #define OS_CURRENTTIME       4
   103     81   #define OS_DELETE            5
   104     82   #define OS_DEVCHAR           6
   105     83   #define OS_FILECONTROL       7
................................................................................
   111     89   #define OS_READ              14 
   112     90   #define OS_SECTORSIZE        15
   113     91   #define OS_SLEEP             16
   114     92   #define OS_SYNC              17
   115     93   #define OS_TRUNCATE          18
   116     94   #define OS_UNLOCK            19
   117     95   #define OS_WRITE             20
   118         -
   119         -#define OS_NUMEVENTS         21
   120         -
   121         -#define BINARYLOG_STRING     30
   122         -#define BINARYLOG_MARKER     31
   123         -
   124         -#define BINARYLOG_PREPARE_V2 64
   125         -#define BINARYLOG_STEP       65
   126         -#define BINARYLOG_FINALIZE   66
   127         -
   128         -struct InstVfs {
   129         -  sqlite3_vfs base;
   130         -  sqlite3_vfs *pVfs;
   131         -
   132         -  void *pClient;
   133         -  void (*xDel)(void *);
   134         -  void (*xCall)(void *, int, int, sqlite3_int64, int, const char *, int, int, sqlite3_int64);
   135         -
   136         -  /* Counters */
   137         -  sqlite3_int64 aTime[OS_NUMEVENTS];
   138         -  int aCount[OS_NUMEVENTS];
   139         -
   140         -  int iNextFileId;
           96  +#define OS_SHMOPEN           21
           97  +#define OS_SHMCLOSE          22
           98  +#define OS_SHMGET            23
           99  +#define OS_SHMRELEASE        24
          100  +#define OS_SHMLOCK           25
          101  +#define OS_SHMSIZE           26
          102  +#define OS_ANNOTATE          27
          103  +
          104  +#define OS_NUMEVENTS         28
          105  +
          106  +#define VFSLOG_BUFFERSIZE 8192
          107  +
          108  +typedef struct VfslogVfs VfslogVfs;
          109  +typedef struct VfslogFile VfslogFile;
          110  +
          111  +struct VfslogVfs {
          112  +  sqlite3_vfs base;               /* VFS methods */
          113  +  sqlite3_vfs *pVfs;              /* Parent VFS */
          114  +  int iNextFileId;                /* Next file id */
          115  +  sqlite3_file *pLog;             /* Log file handle */
          116  +  sqlite3_int64 iOffset;          /* Log file offset of start of write buffer */
          117  +  int nBuf;                       /* Number of valid bytes in aBuf[] */
          118  +  char aBuf[VFSLOG_BUFFERSIZE];   /* Write buffer */
          119  +};
          120  +
          121  +struct VfslogFile {
          122  +  sqlite3_file base;              /* IO methods */
          123  +  sqlite3_file *pReal;            /* Underlying file handle */
          124  +  sqlite3_vfs *pVfslog;           /* Associated VsflogVfs object */
          125  +  int iFileId;                    /* File id number */
   141    126   };
   142         -typedef struct InstVfs InstVfs;
   143         -
   144         -#define REALVFS(p) (((InstVfs *)(p))->pVfs)
   145         -
   146         -typedef struct inst_file inst_file;
   147         -struct inst_file {
   148         -  sqlite3_file base;
   149         -  sqlite3_file *pReal;
   150         -  InstVfs *pInstVfs;
   151         -  const char *zName;
   152         -  int iFileId;               /* File id number */
   153         -  int flags;
          127  +
          128  +#define REALVFS(p) (((VfslogVfs *)(p))->pVfs)
          129  +
          130  +
          131  +
          132  +/*
          133  +** Method declarations for vfslog_file.
          134  +*/
          135  +static int vfslogClose(sqlite3_file*);
          136  +static int vfslogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
          137  +static int vfslogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
          138  +static int vfslogTruncate(sqlite3_file*, sqlite3_int64 size);
          139  +static int vfslogSync(sqlite3_file*, int flags);
          140  +static int vfslogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
          141  +static int vfslogLock(sqlite3_file*, int);
          142  +static int vfslogUnlock(sqlite3_file*, int);
          143  +static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
          144  +static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
          145  +static int vfslogSectorSize(sqlite3_file*);
          146  +static int vfslogDeviceCharacteristics(sqlite3_file*);
          147  +
          148  +static int vfslogShmOpen(sqlite3_file *pFile);
          149  +static int vfslogShmSize(sqlite3_file *pFile, int reqSize, int *pNewSize);
          150  +static int vfslogShmGet(sqlite3_file *pFile, int req, int *pSize, void **pp);
          151  +static int vfslogShmRelease(sqlite3_file *pFile);
          152  +static int vfslogShmLock(sqlite3_file *pFile, int desiredLock, int *gotLock);
          153  +static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag);
          154  +
          155  +/*
          156  +** Method declarations for vfslog_vfs.
          157  +*/
          158  +static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
          159  +static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir);
          160  +static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
          161  +static int vfslogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
          162  +static void *vfslogDlOpen(sqlite3_vfs*, const char *zFilename);
          163  +static void vfslogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
          164  +static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
          165  +static void vfslogDlClose(sqlite3_vfs*, void*);
          166  +static int vfslogRandomness(sqlite3_vfs*, int nByte, char *zOut);
          167  +static int vfslogSleep(sqlite3_vfs*, int microseconds);
          168  +static int vfslogCurrentTime(sqlite3_vfs*, double*);
          169  +
          170  +static sqlite3_vfs vfslog_vfs = {
          171  +  1,                              /* iVersion */
          172  +  sizeof(VfslogFile),             /* szOsFile */
          173  +  INST_MAX_PATHNAME,              /* mxPathname */
          174  +  0,                              /* pNext */
          175  +  0,                              /* zName */
          176  +  0,                              /* pAppData */
          177  +  vfslogOpen,                     /* xOpen */
          178  +  vfslogDelete,                   /* xDelete */
          179  +  vfslogAccess,                   /* xAccess */
          180  +  vfslogFullPathname,             /* xFullPathname */
          181  +  vfslogDlOpen,                   /* xDlOpen */
          182  +  vfslogDlError,                  /* xDlError */
          183  +  vfslogDlSym,                    /* xDlSym */
          184  +  vfslogDlClose,                  /* xDlClose */
          185  +  vfslogRandomness,               /* xRandomness */
          186  +  vfslogSleep,                    /* xSleep */
          187  +  vfslogCurrentTime,              /* xCurrentTime */
   154    188   };
   155    189   
   156         -/*
   157         -** Method declarations for inst_file.
   158         -*/
   159         -static int instClose(sqlite3_file*);
   160         -static int instRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
   161         -static int instWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
   162         -static int instTruncate(sqlite3_file*, sqlite3_int64 size);
   163         -static int instSync(sqlite3_file*, int flags);
   164         -static int instFileSize(sqlite3_file*, sqlite3_int64 *pSize);
   165         -static int instLock(sqlite3_file*, int);
   166         -static int instUnlock(sqlite3_file*, int);
   167         -static int instCheckReservedLock(sqlite3_file*, int *pResOut);
   168         -static int instFileControl(sqlite3_file*, int op, void *pArg);
   169         -static int instSectorSize(sqlite3_file*);
   170         -static int instDeviceCharacteristics(sqlite3_file*);
   171         -
   172         -/*
   173         -** Method declarations for inst_vfs.
   174         -*/
   175         -static int instOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
   176         -static int instDelete(sqlite3_vfs*, const char *zName, int syncDir);
   177         -static int instAccess(sqlite3_vfs*, const char *zName, int flags, int *);
   178         -static int instFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
   179         -static void *instDlOpen(sqlite3_vfs*, const char *zFilename);
   180         -static void instDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
   181         -static void (*instDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
   182         -static void instDlClose(sqlite3_vfs*, void*);
   183         -static int instRandomness(sqlite3_vfs*, int nByte, char *zOut);
   184         -static int instSleep(sqlite3_vfs*, int microseconds);
   185         -static int instCurrentTime(sqlite3_vfs*, double*);
   186         -
   187         -static void binarylog_blob(sqlite3_vfs *, const char *, int, int); 
   188         -
   189         -static sqlite3_vfs inst_vfs = {
   190         -  1,                      /* iVersion */
   191         -  sizeof(inst_file),      /* szOsFile */
   192         -  INST_MAX_PATHNAME,      /* mxPathname */
   193         -  0,                      /* pNext */
   194         -  0,                      /* zName */
   195         -  0,                      /* pAppData */
   196         -  instOpen,               /* xOpen */
   197         -  instDelete,             /* xDelete */
   198         -  instAccess,             /* xAccess */
   199         -  instFullPathname,       /* xFullPathname */
   200         -  instDlOpen,             /* xDlOpen */
   201         -  instDlError,            /* xDlError */
   202         -  instDlSym,              /* xDlSym */
   203         -  instDlClose,            /* xDlClose */
   204         -  instRandomness,         /* xRandomness */
   205         -  instSleep,              /* xSleep */
   206         -  instCurrentTime,        /* xCurrentTime */
          190  +static sqlite3_io_methods vfslog_io_methods = {
          191  +  2,                              /* iVersion */
          192  +  vfslogClose,                    /* xClose */
          193  +  vfslogRead,                     /* xRead */
          194  +  vfslogWrite,                    /* xWrite */
          195  +  vfslogTruncate,                 /* xTruncate */
          196  +  vfslogSync,                     /* xSync */
          197  +  vfslogFileSize,                 /* xFileSize */
          198  +  vfslogLock,                     /* xLock */
          199  +  vfslogUnlock,                   /* xUnlock */
          200  +  vfslogCheckReservedLock,        /* xCheckReservedLock */
          201  +  vfslogFileControl,              /* xFileControl */
          202  +  vfslogSectorSize,               /* xSectorSize */
          203  +  vfslogDeviceCharacteristics,    /* xDeviceCharacteristics */
          204  +  vfslogShmOpen,                  /* xShmOpen */
          205  +  vfslogShmSize,                  /* xShmSize */
          206  +  vfslogShmGet,                   /* xShmGet */
          207  +  vfslogShmRelease,               /* xShmRelease */
          208  +  vfslogShmLock,                  /* xShmLock */
          209  +  vfslogShmClose                  /* xShmClose */
   207    210   };
   208    211   
   209         -static sqlite3_io_methods inst_io_methods = {
   210         -  1,                            /* iVersion */
   211         -  instClose,                      /* xClose */
   212         -  instRead,                       /* xRead */
   213         -  instWrite,                      /* xWrite */
   214         -  instTruncate,                   /* xTruncate */
   215         -  instSync,                       /* xSync */
   216         -  instFileSize,                   /* xFileSize */
   217         -  instLock,                       /* xLock */
   218         -  instUnlock,                     /* xUnlock */
   219         -  instCheckReservedLock,          /* xCheckReservedLock */
   220         -  instFileControl,                /* xFileControl */
   221         -  instSectorSize,                 /* xSectorSize */
   222         -  instDeviceCharacteristics       /* xDeviceCharacteristics */
   223         -};
   224         -
   225         -/* 
   226         -** hwtime.h contains inline assembler code for implementing 
   227         -** high-performance timing routines.
   228         -*/
   229         -#include "hwtime.h"
   230         -
   231         -#define OS_TIME_IO(eEvent, A, B, Call) {     \
   232         -  inst_file *p = (inst_file *)pFile;         \
   233         -  InstVfs *pInstVfs = p->pInstVfs;           \
   234         -  int rc;                                    \
   235         -  sqlite_uint64 t = sqlite3Hwtime();         \
   236         -  rc = Call;                                 \
   237         -  t = sqlite3Hwtime() - t;                   \
   238         -  pInstVfs->aTime[eEvent] += t;              \
   239         -  pInstVfs->aCount[eEvent] += 1;             \
   240         -  if( pInstVfs->xCall ){                     \
   241         -    pInstVfs->xCall(                         \
   242         -      pInstVfs->pClient,eEvent,p->iFileId,t,rc,p->zName,p->flags,A,B  \
   243         -    );                                       \
   244         -  }                                          \
   245         -  return rc;                                 \
   246         -}
   247         -
   248         -#define OS_TIME_VFS(eEvent, Z, flags, A, B, Call) {      \
   249         -  InstVfs *pInstVfs = (InstVfs *)pVfs;   \
   250         -  int rc;                                \
   251         -  sqlite_uint64 t = sqlite3Hwtime();     \
   252         -  rc = Call;                             \
   253         -  t = sqlite3Hwtime() - t;               \
   254         -  pInstVfs->aTime[eEvent] += t;          \
   255         -  pInstVfs->aCount[eEvent] += 1;         \
   256         -  if( pInstVfs->xCall ){                 \
   257         -    pInstVfs->xCall(pInstVfs->pClient,eEvent,0, t, rc, Z, flags, A, B); \
   258         -  }                                      \
   259         -  return rc;                             \
   260         -}
   261         -
   262         -/*
   263         -** Close an inst-file.
   264         -*/
   265         -static int instClose(sqlite3_file *pFile){
   266         -  OS_TIME_IO(OS_CLOSE, 0, 0, 
   267         -    (p->pReal->pMethods ? p->pReal->pMethods->xClose(p->pReal) : SQLITE_OK)
   268         -  );
   269         -}
   270         -
   271         -/*
   272         -** Read data from an inst-file.
   273         -*/
   274         -static int instRead(
          212  +#if defined(SQLITE_OS_UNIX) && !defined(NO_GETTOD)
          213  +#include <sys/time.h>
          214  +static sqlite3_uint64 vfslog_time(){
          215  +  struct timeval sTime;
          216  +  gettimeofday(&sTime, 0);
          217  +  return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
          218  +}
          219  +#else
          220  +static sqlite3_uint64 vfslog_time(){
          221  +  return 0;
          222  +}
          223  +#endif
          224  +
          225  +static void vfslog_call(sqlite3_vfs *, int, int, int, int, int, int);
          226  +static void vfslog_string(sqlite3_vfs *, const char *);
          227  +
          228  +/*
          229  +** Close an vfslog-file.
          230  +*/
          231  +static int vfslogClose(sqlite3_file *pFile){
          232  +  sqlite3_uint64 t;
          233  +  int rc = SQLITE_OK;
          234  +  VfslogFile *p = (VfslogFile *)pFile;
          235  +
          236  +  t = vfslog_time();
          237  +  if( p->pReal->pMethods ){
          238  +    rc = p->pReal->pMethods->xClose(p->pReal);
          239  +  }
          240  +  t = vfslog_time() - t;
          241  +  vfslog_call(p->pVfslog, OS_CLOSE, p->iFileId, t, rc, 0, 0);
          242  +  return rc;
          243  +}
          244  +
          245  +/*
          246  +** Read data from an vfslog-file.
          247  +*/
          248  +static int vfslogRead(
   275    249     sqlite3_file *pFile, 
   276    250     void *zBuf, 
   277    251     int iAmt, 
   278    252     sqlite_int64 iOfst
   279    253   ){
   280         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs);
   281         -  OS_TIME_IO(OS_READ, iAmt, (binarylog_blob(pVfs, zBuf, iAmt, 1), iOfst), 
   282         -      p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst)
   283         -  );
          254  +  int rc;
          255  +  sqlite3_uint64 t;
          256  +  VfslogFile *p = (VfslogFile *)pFile;
          257  +  t = vfslog_time();
          258  +  rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
          259  +  t = vfslog_time() - t;
          260  +  vfslog_call(p->pVfslog, OS_READ, p->iFileId, t, rc, iAmt, (int)iOfst);
          261  +  return rc;
   284    262   }
   285    263   
   286    264   /*
   287         -** Write data to an inst-file.
          265  +** Write data to an vfslog-file.
   288    266   */
   289         -static int instWrite(
          267  +static int vfslogWrite(
   290    268     sqlite3_file *pFile,
   291    269     const void *z,
   292    270     int iAmt,
   293    271     sqlite_int64 iOfst
   294    272   ){
   295         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)(((inst_file *)pFile)->pInstVfs);
   296         -  binarylog_blob(pVfs, z, iAmt, 1);
   297         -  OS_TIME_IO(OS_WRITE, iAmt, iOfst, 
   298         -      p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst)
   299         -  );
   300         -}
   301         -
   302         -/*
   303         -** Truncate an inst-file.
   304         -*/
   305         -static int instTruncate(sqlite3_file *pFile, sqlite_int64 size){
   306         -  OS_TIME_IO(OS_TRUNCATE, 0, (int)size, 
   307         -    p->pReal->pMethods->xTruncate(p->pReal, size)
   308         -  );
   309         -}
   310         -
   311         -/*
   312         -** Sync an inst-file.
   313         -*/
   314         -static int instSync(sqlite3_file *pFile, int flags){
   315         -  OS_TIME_IO(OS_SYNC, flags, 0, p->pReal->pMethods->xSync(p->pReal, flags));
   316         -}
   317         -
   318         -/*
   319         -** Return the current file-size of an inst-file.
   320         -*/
   321         -static int instFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
   322         -  OS_TIME_IO(OS_FILESIZE, (int)(*pSize), 0, 
   323         -    p->pReal->pMethods->xFileSize(p->pReal, pSize)
   324         -  );
   325         -}
   326         -
   327         -/*
   328         -** Lock an inst-file.
   329         -*/
   330         -static int instLock(sqlite3_file *pFile, int eLock){
   331         -  OS_TIME_IO(OS_LOCK, eLock, 0, p->pReal->pMethods->xLock(p->pReal, eLock));
   332         -}
   333         -
   334         -/*
   335         -** Unlock an inst-file.
   336         -*/
   337         -static int instUnlock(sqlite3_file *pFile, int eLock){
   338         -  OS_TIME_IO(OS_UNLOCK, eLock, 0, p->pReal->pMethods->xUnlock(p->pReal, eLock));
   339         -}
   340         -
   341         -/*
   342         -** Check if another file-handle holds a RESERVED lock on an inst-file.
   343         -*/
   344         -static int instCheckReservedLock(sqlite3_file *pFile, int *pResOut){
   345         -  OS_TIME_IO(OS_CHECKRESERVEDLOCK, 0, 0, 
   346         -      p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut)
   347         -  );
   348         -}
   349         -
   350         -/*
   351         -** File control method. For custom operations on an inst-file.
   352         -*/
   353         -static int instFileControl(sqlite3_file *pFile, int op, void *pArg){
   354         -  OS_TIME_IO(OS_FILECONTROL, 0, 0, p->pReal->pMethods->xFileControl(p->pReal, op, pArg));
   355         -}
   356         -
   357         -/*
   358         -** Return the sector-size in bytes for an inst-file.
   359         -*/
   360         -static int instSectorSize(sqlite3_file *pFile){
   361         -  OS_TIME_IO(OS_SECTORSIZE, 0, 0, p->pReal->pMethods->xSectorSize(p->pReal));
   362         -}
   363         -
   364         -/*
   365         -** Return the device characteristic flags supported by an inst-file.
   366         -*/
   367         -static int instDeviceCharacteristics(sqlite3_file *pFile){
   368         -  OS_TIME_IO(OS_DEVCHAR, 0, 0, p->pReal->pMethods->xDeviceCharacteristics(p->pReal));
   369         -}
   370         -
   371         -/*
   372         -** Open an inst file handle.
   373         -*/
   374         -static int instOpen(
          273  +  int rc;
          274  +  sqlite3_uint64 t;
          275  +  VfslogFile *p = (VfslogFile *)pFile;
          276  +  t = vfslog_time();
          277  +  rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
          278  +  t = vfslog_time() - t;
          279  +  vfslog_call(p->pVfslog, OS_WRITE, p->iFileId, t, rc, iAmt, (int)iOfst);
          280  +  return rc;
          281  +}
          282  +
          283  +/*
          284  +** Truncate an vfslog-file.
          285  +*/
          286  +static int vfslogTruncate(sqlite3_file *pFile, sqlite_int64 size){
          287  +  int rc;
          288  +  sqlite3_uint64 t;
          289  +  VfslogFile *p = (VfslogFile *)pFile;
          290  +  t = vfslog_time();
          291  +  rc = p->pReal->pMethods->xTruncate(p->pReal, size);
          292  +  t = vfslog_time() - t;
          293  +  vfslog_call(p->pVfslog, OS_TRUNCATE, p->iFileId, t, rc, 0, (int)size);
          294  +  return rc;
          295  +}
          296  +
          297  +/*
          298  +** Sync an vfslog-file.
          299  +*/
          300  +static int vfslogSync(sqlite3_file *pFile, int flags){
          301  +  int rc;
          302  +  sqlite3_uint64 t;
          303  +  VfslogFile *p = (VfslogFile *)pFile;
          304  +  t = vfslog_time();
          305  +  rc = p->pReal->pMethods->xSync(p->pReal, flags);
          306  +  t = vfslog_time() - t;
          307  +  vfslog_call(p->pVfslog, OS_SYNC, p->iFileId, t, rc, flags, 0);
          308  +  return rc;
          309  +}
          310  +
          311  +/*
          312  +** Return the current file-size of an vfslog-file.
          313  +*/
          314  +static int vfslogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
          315  +  int rc;
          316  +  sqlite3_uint64 t;
          317  +  VfslogFile *p = (VfslogFile *)pFile;
          318  +  t = vfslog_time();
          319  +  rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
          320  +  t = vfslog_time() - t;
          321  +  vfslog_call(p->pVfslog, OS_FILESIZE, p->iFileId, t, rc, 0, (int)*pSize);
          322  +  return rc;
          323  +}
          324  +
          325  +/*
          326  +** Lock an vfslog-file.
          327  +*/
          328  +static int vfslogLock(sqlite3_file *pFile, int eLock){
          329  +  int rc;
          330  +  sqlite3_uint64 t;
          331  +  VfslogFile *p = (VfslogFile *)pFile;
          332  +  t = vfslog_time();
          333  +  rc = p->pReal->pMethods->xLock(p->pReal, eLock);
          334  +  t = vfslog_time() - t;
          335  +  vfslog_call(p->pVfslog, OS_LOCK, p->iFileId, t, rc, eLock, 0);
          336  +  return rc;
          337  +}
          338  +
          339  +/*
          340  +** Unlock an vfslog-file.
          341  +*/
          342  +static int vfslogUnlock(sqlite3_file *pFile, int eLock){
          343  +  int rc;
          344  +  sqlite3_uint64 t;
          345  +  VfslogFile *p = (VfslogFile *)pFile;
          346  +  t = vfslog_time();
          347  +  rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
          348  +  t = vfslog_time() - t;
          349  +  vfslog_call(p->pVfslog, OS_UNLOCK, p->iFileId, t, rc, eLock, 0);
          350  +  return rc;
          351  +}
          352  +
          353  +/*
          354  +** Check if another file-handle holds a RESERVED lock on an vfslog-file.
          355  +*/
          356  +static int vfslogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
          357  +  int rc;
          358  +  sqlite3_uint64 t;
          359  +  VfslogFile *p = (VfslogFile *)pFile;
          360  +  t = vfslog_time();
          361  +  rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
          362  +  t = vfslog_time() - t;
          363  +  vfslog_call(p->pVfslog, OS_CHECKRESERVEDLOCK, p->iFileId, t, rc, *pResOut, 0);
          364  +  return rc;
          365  +}
          366  +
          367  +/*
          368  +** File control method. For custom operations on an vfslog-file.
          369  +*/
          370  +static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
          371  +  VfslogFile *p = (VfslogFile *)pFile;
          372  +  return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
          373  +}
          374  +
          375  +/*
          376  +** Return the sector-size in bytes for an vfslog-file.
          377  +*/
          378  +static int vfslogSectorSize(sqlite3_file *pFile){
          379  +  int rc;
          380  +  sqlite3_uint64 t;
          381  +  VfslogFile *p = (VfslogFile *)pFile;
          382  +  t = vfslog_time();
          383  +  rc = p->pReal->pMethods->xSectorSize(p->pReal);
          384  +  t = vfslog_time() - t;
          385  +  vfslog_call(p->pVfslog, OS_SECTORSIZE, p->iFileId, t, rc, 0, 0);
          386  +  return rc;
          387  +}
          388  +
          389  +/*
          390  +** Return the device characteristic flags supported by an vfslog-file.
          391  +*/
          392  +static int vfslogDeviceCharacteristics(sqlite3_file *pFile){
          393  +  int rc;
          394  +  sqlite3_uint64 t;
          395  +  VfslogFile *p = (VfslogFile *)pFile;
          396  +  t = vfslog_time();
          397  +  rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
          398  +  t = vfslog_time() - t;
          399  +  vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0);
          400  +  return rc;
          401  +}
          402  +
          403  +static int vfslogShmOpen(sqlite3_file *pFile){
          404  +  int rc;
          405  +  sqlite3_uint64 t;
          406  +  VfslogFile *p = (VfslogFile *)pFile;
          407  +  t = vfslog_time();
          408  +  rc = p->pReal->pMethods->xShmOpen(p->pReal);
          409  +  t = vfslog_time() - t;
          410  +  vfslog_call(p->pVfslog, OS_SHMOPEN, p->iFileId, t, rc, 0, 0);
          411  +  return rc;
          412  +}
          413  +static int vfslogShmSize(sqlite3_file *pFile, int reqSize, int *pNewSize){
          414  +  int rc;
          415  +  sqlite3_uint64 t;
          416  +  VfslogFile *p = (VfslogFile *)pFile;
          417  +  t = vfslog_time();
          418  +  rc = p->pReal->pMethods->xShmSize(p->pReal, reqSize, pNewSize);
          419  +  t = vfslog_time() - t;
          420  +  vfslog_call(p->pVfslog, OS_SHMSIZE, p->iFileId, t, rc, 0, 0);
          421  +  return rc;
          422  +}
          423  +static int vfslogShmGet(sqlite3_file *pFile, int req, int *pSize, void **pp){
          424  +  int rc;
          425  +  sqlite3_uint64 t;
          426  +  VfslogFile *p = (VfslogFile *)pFile;
          427  +  t = vfslog_time();
          428  +  rc = p->pReal->pMethods->xShmGet(p->pReal, req, pSize, pp);
          429  +  t = vfslog_time() - t;
          430  +  vfslog_call(p->pVfslog, OS_SHMGET, p->iFileId, t, rc, 0, 0);
          431  +  return rc;
          432  +}
          433  +static int vfslogShmRelease(sqlite3_file *pFile){
          434  +  int rc;
          435  +  sqlite3_uint64 t;
          436  +  VfslogFile *p = (VfslogFile *)pFile;
          437  +  t = vfslog_time();
          438  +  rc = p->pReal->pMethods->xShmRelease(p->pReal);
          439  +  t = vfslog_time() - t;
          440  +  vfslog_call(p->pVfslog, OS_SHMRELEASE, p->iFileId, t, rc, 0, 0);
          441  +  return rc;
          442  +}
          443  +static int vfslogShmLock(sqlite3_file *pFile, int desiredLock, int *gotLock){
          444  +  int rc;
          445  +  sqlite3_uint64 t;
          446  +  VfslogFile *p = (VfslogFile *)pFile;
          447  +  t = vfslog_time();
          448  +  rc = p->pReal->pMethods->xShmLock(p->pReal, desiredLock, gotLock);
          449  +  t = vfslog_time() - t;
          450  +  vfslog_call(p->pVfslog, OS_SHMLOCK, p->iFileId, t, rc, 0, 0);
          451  +  return rc;
          452  +}
          453  +static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag){
          454  +  int rc;
          455  +  sqlite3_uint64 t;
          456  +  VfslogFile *p = (VfslogFile *)pFile;
          457  +  t = vfslog_time();
          458  +  rc = p->pReal->pMethods->xShmClose(p->pReal, deleteFlag);
          459  +  t = vfslog_time() - t;
          460  +  vfslog_call(p->pVfslog, OS_SHMCLOSE, p->iFileId, t, rc, 0, 0);
          461  +  return rc;
          462  +}
          463  +
          464  +
          465  +/*
          466  +** Open an vfslog file handle.
          467  +*/
          468  +static int vfslogOpen(
   375    469     sqlite3_vfs *pVfs,
   376    470     const char *zName,
   377    471     sqlite3_file *pFile,
   378    472     int flags,
   379    473     int *pOutFlags
   380    474   ){
   381         -  inst_file *p = (inst_file *)pFile;
   382         -  pFile->pMethods = &inst_io_methods;
          475  +  int rc;
          476  +  sqlite3_uint64 t;
          477  +  VfslogFile *p = (VfslogFile *)pFile;
          478  +  VfslogVfs *pLog = (VfslogVfs *)pVfs;
          479  +
          480  +  pFile->pMethods = &vfslog_io_methods;
   383    481     p->pReal = (sqlite3_file *)&p[1];
   384         -  p->pInstVfs = (InstVfs *)pVfs;
   385         -  p->zName = zName;
   386         -  p->flags = flags;
   387         -  p->iFileId = ++p->pInstVfs->iNextFileId;
          482  +  p->pVfslog = pVfs;
          483  +  p->iFileId = ++pLog->iNextFileId;
   388    484   
   389         -  binarylog_blob(pVfs, zName, -1, 0);
   390         -  OS_TIME_VFS(OS_OPEN, zName, flags, p->iFileId, 0,
   391         -    REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags)
   392         -  );
          485  +  t = vfslog_time();
          486  +  rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
          487  +  t = vfslog_time() - t;
          488  +
          489  +  vfslog_call(pVfs, OS_OPEN, p->iFileId, t, rc, 0, 0);
          490  +  vfslog_string(pVfs, zName);
          491  +  return rc;
   393    492   }
   394    493   
   395    494   /*
   396    495   ** Delete the file located at zPath. If the dirSync argument is true,
   397    496   ** ensure the file-system modifications are synced to disk before
   398    497   ** returning.
   399    498   */
   400         -static int instDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
   401         -  binarylog_blob(pVfs, zPath, -1, 0);
   402         -  OS_TIME_VFS(OS_DELETE, zPath, 0, dirSync, 0,
   403         -    REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync) 
   404         -  );
          499  +static int vfslogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
          500  +  int rc;
          501  +  sqlite3_uint64 t;
          502  +  t = vfslog_time();
          503  +  rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
          504  +  t = vfslog_time() - t;
          505  +  vfslog_call(pVfs, OS_DELETE, 0, t, rc, dirSync, 0);
          506  +  vfslog_string(pVfs, zPath);
          507  +  return rc;
   405    508   }
   406    509   
   407    510   /*
   408    511   ** Test for access permissions. Return true if the requested permission
   409    512   ** is available, or false otherwise.
   410    513   */
   411         -static int instAccess(
          514  +static int vfslogAccess(
   412    515     sqlite3_vfs *pVfs, 
   413    516     const char *zPath, 
   414    517     int flags, 
   415    518     int *pResOut
   416    519   ){
   417         -  binarylog_blob(pVfs, zPath, -1, 0);
   418         -  OS_TIME_VFS(OS_ACCESS, zPath, 0, flags, *pResOut, 
   419         -    REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut) 
   420         -  );
          520  +  int rc;
          521  +  sqlite3_uint64 t;
          522  +  t = vfslog_time();
          523  +  rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
          524  +  t = vfslog_time() - t;
          525  +  vfslog_call(pVfs, OS_ACCESS, 0, t, rc, flags, *pResOut);
          526  +  vfslog_string(pVfs, zPath);
          527  +  return rc;
   421    528   }
   422    529   
   423    530   /*
   424    531   ** Populate buffer zOut with the full canonical pathname corresponding
   425    532   ** to the pathname in zPath. zOut is guaranteed to point to a buffer
   426    533   ** of at least (INST_MAX_PATHNAME+1) bytes.
   427    534   */
   428         -static int instFullPathname(
          535  +static int vfslogFullPathname(
   429    536     sqlite3_vfs *pVfs, 
   430    537     const char *zPath, 
   431    538     int nOut, 
   432    539     char *zOut
   433    540   ){
   434         -  OS_TIME_VFS( OS_FULLPATHNAME, zPath, 0, 0, 0,
   435         -    REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
   436         -  );
          541  +  return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
   437    542   }
   438    543   
   439    544   /*
   440    545   ** Open the dynamic library located at zPath and return a handle.
   441    546   */
   442         -static void *instDlOpen(sqlite3_vfs *pVfs, const char *zPath){
          547  +static void *vfslogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
   443    548     return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
   444    549   }
   445    550   
   446    551   /*
   447    552   ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
   448    553   ** utf-8 string describing the most recent error encountered associated 
   449    554   ** with dynamic libraries.
   450    555   */
   451         -static void instDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
          556  +static void vfslogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
   452    557     REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
   453    558   }
   454    559   
   455    560   /*
   456    561   ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
   457    562   */
   458         -static void (*instDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
          563  +static void (*vfslogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
   459    564     return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
   460    565   }
   461    566   
   462    567   /*
   463    568   ** Close the dynamic library handle pHandle.
   464    569   */
   465         -static void instDlClose(sqlite3_vfs *pVfs, void *pHandle){
          570  +static void vfslogDlClose(sqlite3_vfs *pVfs, void *pHandle){
   466    571     REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
   467    572   }
   468    573   
   469    574   /*
   470    575   ** Populate the buffer pointed to by zBufOut with nByte bytes of 
   471    576   ** random data.
   472    577   */
   473         -static int instRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
   474         -  OS_TIME_VFS( OS_RANDOMNESS, 0, 0, nByte, 0,
   475         -    REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
   476         -  );
          578  +static int vfslogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
          579  +  return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
   477    580   }
   478    581   
   479    582   /*
   480    583   ** Sleep for nMicro microseconds. Return the number of microseconds 
   481    584   ** actually slept.
   482    585   */
   483         -static int instSleep(sqlite3_vfs *pVfs, int nMicro){
   484         -  OS_TIME_VFS( OS_SLEEP, 0, 0, nMicro, 0, 
   485         -    REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro) 
   486         -  );
          586  +static int vfslogSleep(sqlite3_vfs *pVfs, int nMicro){
          587  +  return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
   487    588   }
   488    589   
   489    590   /*
   490    591   ** Return the current time as a Julian Day number in *pTimeOut.
   491    592   */
   492         -static int instCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
   493         -  OS_TIME_VFS( OS_CURRENTTIME, 0, 0, 0, 0,
   494         -    REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut) 
   495         -  );
   496         -}
   497         -
   498         -sqlite3_vfs *sqlite3_instvfs_create(const char *zName, const char *zParent){
   499         -  int nByte;
   500         -  InstVfs *p;
   501         -  sqlite3_vfs *pParent;
   502         -
   503         -  pParent = sqlite3_vfs_find(zParent);
   504         -  if( !pParent ){
   505         -    return 0;
   506         -  }
   507         -
   508         -  nByte = strlen(zName) + 1 + sizeof(InstVfs);
   509         -  p = (InstVfs *)sqlite3_malloc(nByte);
   510         -  if( p ){
   511         -    char *zCopy = (char *)&p[1];
   512         -    memset(p, 0, nByte);
   513         -    memcpy(p, &inst_vfs, sizeof(sqlite3_vfs));
   514         -    p->pVfs = pParent;
   515         -    memcpy(zCopy, zName, strlen(zName));
   516         -    p->base.zName = (const char *)zCopy;
   517         -    p->base.szOsFile += pParent->szOsFile;
   518         -    sqlite3_vfs_register((sqlite3_vfs *)p, 0);
   519         -  }
   520         -
   521         -  return (sqlite3_vfs *)p;
   522         -}
   523         -
   524         -void sqlite3_instvfs_configure(
   525         -  sqlite3_vfs *pVfs,
   526         -  void (*xCall)(
   527         -      void*, 
   528         -      int,                           /* File id */
   529         -      int,                           /* Event code */
   530         -      sqlite3_int64, 
   531         -      int,                           /* Return code */
   532         -      const char*,                   /* File name */
   533         -      int, 
   534         -      int, 
   535         -      sqlite3_int64
   536         -  ),
   537         -  void *pClient,
   538         -  void (*xDel)(void *)
   539         -){
   540         -  InstVfs *p = (InstVfs *)pVfs;
   541         -  assert( pVfs->xOpen==instOpen );
   542         -  if( p->xDel ){
   543         -    p->xDel(p->pClient);
   544         -  }
   545         -  p->xCall = xCall;
   546         -  p->xDel = xDel;
   547         -  p->pClient = pClient;
   548         -}
   549         -
   550         -void sqlite3_instvfs_destroy(sqlite3_vfs *pVfs){
   551         -  if( pVfs ){
   552         -    sqlite3_vfs_unregister(pVfs);
   553         -    sqlite3_instvfs_configure(pVfs, 0, 0, 0);
   554         -    sqlite3_free(pVfs);
   555         -  }
   556         -}
   557         -
   558         -void sqlite3_instvfs_reset(sqlite3_vfs *pVfs){
   559         -  InstVfs *p = (InstVfs *)pVfs;
   560         -  assert( pVfs->xOpen==instOpen );
   561         -  memset(p->aTime, 0, sizeof(sqlite3_int64)*OS_NUMEVENTS);
   562         -  memset(p->aCount, 0, sizeof(int)*OS_NUMEVENTS);
   563         -}
   564         -
   565         -const char *sqlite3_instvfs_name(int eEvent){
   566         -  const char *zEvent = 0;
   567         -
   568         -  switch( eEvent ){
   569         -    case OS_CLOSE:             zEvent = "xClose"; break;
   570         -    case OS_READ:              zEvent = "xRead"; break;
   571         -    case OS_WRITE:             zEvent = "xWrite"; break;
   572         -    case OS_TRUNCATE:          zEvent = "xTruncate"; break;
   573         -    case OS_SYNC:              zEvent = "xSync"; break;
   574         -    case OS_FILESIZE:          zEvent = "xFilesize"; break;
   575         -    case OS_LOCK:              zEvent = "xLock"; break;
   576         -    case OS_UNLOCK:            zEvent = "xUnlock"; break;
   577         -    case OS_CHECKRESERVEDLOCK: zEvent = "xCheckReservedLock"; break;
   578         -    case OS_FILECONTROL:       zEvent = "xFileControl"; break;
   579         -    case OS_SECTORSIZE:        zEvent = "xSectorSize"; break;
   580         -    case OS_DEVCHAR:           zEvent = "xDeviceCharacteristics"; break;
   581         -    case OS_OPEN:              zEvent = "xOpen"; break;
   582         -    case OS_DELETE:            zEvent = "xDelete"; break;
   583         -    case OS_ACCESS:            zEvent = "xAccess"; break;
   584         -    case OS_FULLPATHNAME:      zEvent = "xFullPathname"; break;
   585         -    case OS_RANDOMNESS:        zEvent = "xRandomness"; break;
   586         -    case OS_SLEEP:             zEvent = "xSleep"; break;
   587         -    case OS_CURRENTTIME:       zEvent = "xCurrentTime"; break;
   588         -  }
   589         -
   590         -  return zEvent;
   591         -}
   592         -
   593         -void sqlite3_instvfs_get(
   594         -  sqlite3_vfs *pVfs, 
   595         -  int eEvent, 
   596         -  const char **pzEvent, 
   597         -  sqlite3_int64 *pnClick, 
   598         -  int *pnCall
   599         -){
   600         -  InstVfs *p = (InstVfs *)pVfs;
   601         -  assert( pVfs->xOpen==instOpen );
   602         -  if( eEvent<1 || eEvent>=OS_NUMEVENTS ){
   603         -    *pzEvent = 0;
   604         -    *pnClick = 0;
   605         -    *pnCall = 0;
   606         -    return;
   607         -  }
   608         -
   609         -  *pzEvent = sqlite3_instvfs_name(eEvent);
   610         -  *pnClick = p->aTime[eEvent];
   611         -  *pnCall = p->aCount[eEvent];
   612         -}
   613         -
   614         -#define BINARYLOG_BUFFERSIZE 8192
   615         -
   616         -struct InstVfsBinaryLog {
   617         -  int nBuf;
   618         -  char *zBuf;
   619         -  sqlite3_int64 iOffset;
   620         -  int log_data;
   621         -  sqlite3_file *pOut;
   622         -  char *zOut;                       /* Log file name */
   623         -};
   624         -typedef struct InstVfsBinaryLog InstVfsBinaryLog;
   625         -
   626         -static void put32bits(unsigned char *p, unsigned int v){
   627         -  p[0] = v>>24;
   628         -  p[1] = v>>16;
   629         -  p[2] = v>>8;
   630         -  p[3] = v;
   631         -}
   632         -
   633         -static void binarylog_flush(InstVfsBinaryLog *pLog){
   634         -  sqlite3_file *pFile = pLog->pOut;
   635         -
          593  +static int vfslogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
          594  +  return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
          595  +}
          596  +
          597  +static void vfslog_flush(VfslogVfs *p){
   636    598   #ifdef SQLITE_TEST
   637    599     extern int sqlite3_io_error_pending;
   638    600     extern int sqlite3_io_error_persist;
   639    601     extern int sqlite3_diskfull_pending;
   640    602   
   641    603     int pending = sqlite3_io_error_pending;
   642    604     int persist = sqlite3_io_error_persist;
................................................................................
   643    605     int diskfull = sqlite3_diskfull_pending;
   644    606   
   645    607     sqlite3_io_error_pending = 0;
   646    608     sqlite3_io_error_persist = 0;
   647    609     sqlite3_diskfull_pending = 0;
   648    610   #endif
   649    611   
   650         -  pFile->pMethods->xWrite(pFile, pLog->zBuf, pLog->nBuf, pLog->iOffset);
   651         -  pLog->iOffset += pLog->nBuf;
   652         -  pLog->nBuf = 0;
          612  +  if( p->nBuf ){
          613  +    p->pLog->pMethods->xWrite(p->pLog, p->aBuf, p->nBuf, p->iOffset);
          614  +    p->iOffset += p->nBuf;
          615  +    p->nBuf = 0;
          616  +  }
   653    617   
   654    618   #ifdef SQLITE_TEST
   655    619     sqlite3_io_error_pending = pending;
   656    620     sqlite3_io_error_persist = persist;
   657    621     sqlite3_diskfull_pending = diskfull;
   658    622   #endif
   659    623   }
   660    624   
   661         -static void binarylog_xcall(
   662         -  void *p,
   663         -  int eEvent,
   664         -  int iFileId,
   665         -  sqlite3_int64 nClick,
   666         -  int return_code,
   667         -  const char *zName,
   668         -  int flags,
   669         -  int nByte,
   670         -  sqlite3_int64 iOffset
   671         -){
   672         -  InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p;
   673         -  unsigned char *zRec;
   674         -  if( (28+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
   675         -    binarylog_flush(pLog);
   676         -  }
   677         -  zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf];
   678         -  put32bits(&zRec[0], eEvent);
   679         -  put32bits(&zRec[4], (int)iFileId);
   680         -  put32bits(&zRec[8], (int)nClick);
   681         -  put32bits(&zRec[12], return_code);
   682         -  put32bits(&zRec[16], flags);
   683         -  put32bits(&zRec[20], nByte);
   684         -  put32bits(&zRec[24], (int)iOffset);
   685         -  pLog->nBuf += 28;
   686         -}
   687         -
   688         -static void binarylog_xdel(void *p){
   689         -  /* Close the log file and free the memory allocated for the 
   690         -  ** InstVfsBinaryLog structure.
   691         -  */
   692         -  InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)p;
   693         -  sqlite3_file *pFile = pLog->pOut;
   694         -  if( pLog->nBuf ){
   695         -    binarylog_flush(pLog);
   696         -  }
   697         -  pFile->pMethods->xClose(pFile);
   698         -  sqlite3_free(pLog->pOut);
   699         -  sqlite3_free(pLog->zBuf);
   700         -  sqlite3_free(pLog);
   701         -}
   702         -
   703         -static void binarylog_blob(
   704         -  sqlite3_vfs *pVfs,
   705         -  const char *zBlob,
   706         -  int nBlob,
   707         -  int isBinary
   708         -){
   709         -  InstVfsBinaryLog *pLog;
   710         -  InstVfs *pInstVfs = (InstVfs *)pVfs;
   711         -
   712         -  if( pVfs->xOpen!=instOpen || pInstVfs->xCall!=binarylog_xcall ){
   713         -    return;
   714         -  }
   715         -  pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
   716         -  if( zBlob && (!isBinary || pLog->log_data) ){
   717         -    unsigned char *zRec;
   718         -    int nWrite;
   719         -
   720         -    if( nBlob<0 ){
   721         -      nBlob = strlen(zBlob);
   722         -    }
   723         -    nWrite = nBlob + 28;
   724         -  
   725         -    if( (nWrite+pLog->nBuf)>BINARYLOG_BUFFERSIZE ){
   726         -      binarylog_flush(pLog);
   727         -    }
   728         -  
   729         -    zRec = (unsigned char *)&pLog->zBuf[pLog->nBuf];
   730         -    memset(zRec, 0, nWrite);
   731         -    put32bits(&zRec[0], BINARYLOG_STRING);
   732         -    put32bits(&zRec[4], (int)nBlob);
   733         -    put32bits(&zRec[8], (int)isBinary);
   734         -    memcpy(&zRec[28], zBlob, nBlob);
   735         -    pLog->nBuf += nWrite;
   736         -  }
   737         -}
   738         -
   739         -void sqlite3_instvfs_binarylog_call(
          625  +static void put32bits(unsigned char *p, unsigned int v){
          626  +  p[0] = v>>24;
          627  +  p[1] = v>>16;
          628  +  p[2] = v>>8;
          629  +  p[3] = v;
          630  +}
          631  +
          632  +static void vfslog_call(
   740    633     sqlite3_vfs *pVfs,
   741    634     int eEvent,
   742         -  sqlite3_int64 nClick,
          635  +  int iFileid,
          636  +  int nClick,
   743    637     int return_code,
   744         -  const char *zString
   745         -){
   746         -  InstVfs *pInstVfs = (InstVfs *)pVfs;
   747         -  InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
   748         -
   749         -  if( zString ){
   750         -    binarylog_blob(pVfs, zString, -1, 0);
   751         -  }
   752         -  binarylog_xcall(pLog, eEvent, 0, nClick, return_code, 0, 0, 0, 0);
   753         -}
   754         -
   755         -void sqlite3_instvfs_binarylog_marker(
   756         -  sqlite3_vfs *pVfs,
   757         -  const char *zMarker
          638  +  int size,
          639  +  int offset
   758    640   ){
   759         -  InstVfs *pInstVfs = (InstVfs *)pVfs;
   760         -  InstVfsBinaryLog *pLog = (InstVfsBinaryLog *)pInstVfs->pClient;
   761         -  binarylog_blob(pVfs, zMarker, -1, 0);
   762         -  binarylog_xcall(pLog, BINARYLOG_MARKER, 0, 0, 0, 0, 0, 0, 0);
   763         -}
   764         -
   765         -sqlite3_vfs *sqlite3_instvfs_binarylog(
   766         -  const char *zVfs,
   767         -  const char *zParentVfs, 
   768         -  const char *zLog,
   769         -  int log_data
   770         -){
   771         -  InstVfsBinaryLog *p;
          641  +  VfslogVfs *p = (VfslogVfs *)pVfs;
          642  +  unsigned char *zRec;
          643  +  if( (24+p->nBuf)>sizeof(p->aBuf) ){
          644  +    vfslog_flush(p);
          645  +  }
          646  +  zRec = (unsigned char *)&p->aBuf[p->nBuf];
          647  +  put32bits(&zRec[0], eEvent);
          648  +  put32bits(&zRec[4], iFileid);
          649  +  put32bits(&zRec[8], nClick);
          650  +  put32bits(&zRec[12], return_code);
          651  +  put32bits(&zRec[16], size);
          652  +  put32bits(&zRec[20], offset);
          653  +  p->nBuf += 24;
          654  +}
          655  +
          656  +static void vfslog_string(sqlite3_vfs *pVfs, const char *zStr){
          657  +  VfslogVfs *p = (VfslogVfs *)pVfs;
          658  +  unsigned char *zRec;
          659  +  int nStr = zStr ? strlen(zStr) : 0;
          660  +  if( (4+nStr+p->nBuf)>sizeof(p->aBuf) ){
          661  +    vfslog_flush(p);
          662  +  }
          663  +  zRec = (unsigned char *)&p->aBuf[p->nBuf];
          664  +  put32bits(&zRec[0], nStr);
          665  +  if( zStr ){
          666  +    memcpy(&zRec[4], zStr, nStr);
          667  +  }
          668  +  p->nBuf += (4 + nStr);
          669  +}
          670  +
          671  +static void vfslog_finalize(VfslogVfs *p){
          672  +  if( p->pLog->pMethods ){
          673  +    vfslog_flush(p);
          674  +    p->pLog->pMethods->xClose(p->pLog);
          675  +  }
          676  +  sqlite3_free(p);
          677  +}
          678  +
          679  +int sqlite3_vfslog_finalize(const char *zVfs){
   772    680     sqlite3_vfs *pVfs;
          681  +  pVfs = sqlite3_vfs_find(zVfs);
          682  +  if( !pVfs || pVfs->xOpen!=vfslogOpen ){
          683  +    return SQLITE_ERROR;
          684  +  } 
          685  +  sqlite3_vfs_unregister(pVfs);
          686  +  vfslog_finalize((VfslogVfs *)pVfs);
          687  +  return SQLITE_OK;
          688  +}
          689  +
          690  +int sqlite3_vfslog_new(
          691  +  const char *zVfs,               /* New VFS name */
          692  +  const char *zParentVfs,         /* Parent VFS name (or NULL) */
          693  +  const char *zLog                /* Log file name */
          694  +){
          695  +  VfslogVfs *p;
   773    696     sqlite3_vfs *pParent;
   774    697     int nByte;
   775    698     int flags;
   776    699     int rc;
          700  +  char *zFile;
          701  +  int nVfs;
   777    702   
   778    703     pParent = sqlite3_vfs_find(zParentVfs);
   779    704     if( !pParent ){
   780         -    return 0;
          705  +    return SQLITE_ERROR;
   781    706     }
   782    707   
   783         -  nByte = sizeof(InstVfsBinaryLog) + pParent->mxPathname+1;
   784         -  p = (InstVfsBinaryLog *)sqlite3_malloc(nByte);
          708  +  nVfs = strlen(zVfs);
          709  +  nByte = sizeof(VfslogVfs) + pParent->szOsFile + nVfs+1+pParent->mxPathname+1;
          710  +  p = (VfslogVfs *)sqlite3_malloc(nByte);
   785    711     memset(p, 0, nByte);
   786         -  p->zBuf = sqlite3_malloc(BINARYLOG_BUFFERSIZE);
   787         -  p->zOut = (char *)&p[1];
   788         -  p->pOut = (sqlite3_file *)sqlite3_malloc(pParent->szOsFile);
   789         -  p->log_data = log_data;
   790         -  pParent->xFullPathname(pParent, zLog, pParent->mxPathname, p->zOut);
          712  +
          713  +  p->pVfs = pParent;
          714  +  p->pLog = (sqlite3_file *)&p[1];
          715  +  memcpy(&p->base, &vfslog_vfs, sizeof(sqlite3_vfs));
          716  +  p->base.zName = &((char *)p->pLog)[pParent->szOsFile];
          717  +  p->base.szOsFile += pParent->szOsFile;
          718  +  memcpy((char *)p->base.zName, zVfs, nVfs);
          719  +
          720  +  zFile = (char *)&p->base.zName[nVfs+1];
          721  +  pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile);
          722  +
   791    723     flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
   792         -  pParent->xDelete(pParent, p->zOut, 0);
   793         -  rc = pParent->xOpen(pParent, p->zOut, p->pOut, flags, &flags);
          724  +  pParent->xDelete(pParent, zFile, 0);
          725  +  rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags);
   794    726     if( rc==SQLITE_OK ){
   795         -    memcpy(p->zBuf, "sqlite_ostrace1.....", 20);
          727  +    memcpy(p->aBuf, "sqlite_ostrace1.....", 20);
   796    728       p->iOffset = 0;
   797    729       p->nBuf = 20;
          730  +    rc = sqlite3_vfs_register((sqlite3_vfs *)p, 1);
   798    731     }
   799    732     if( rc ){
   800         -    binarylog_xdel(p);
   801         -    return 0;
          733  +    vfslog_finalize(p);
          734  +  }
          735  +  return rc;
          736  +}
          737  +
          738  +int sqlite3_vfslog_annotate(const char *zVfs, const char *zMsg){
          739  +  sqlite3_vfs *pVfs;
          740  +  pVfs = sqlite3_vfs_find(zVfs);
          741  +  if( !pVfs || pVfs->xOpen!=vfslogOpen ){
          742  +    return SQLITE_ERROR;
          743  +  } 
          744  +  vfslog_call(pVfs, OS_ANNOTATE, 0, 0, 0, 0, 0);
          745  +  vfslog_string(pVfs, zMsg);
          746  +  return SQLITE_OK;
          747  +}
          748  +
          749  +static const char *vfslog_eventname(int eEvent){
          750  +  const char *zEvent = 0;
          751  +
          752  +  switch( eEvent ){
          753  +    case OS_CLOSE:             zEvent = "xClose"; break;
          754  +    case OS_READ:              zEvent = "xRead"; break;
          755  +    case OS_WRITE:             zEvent = "xWrite"; break;
          756  +    case OS_TRUNCATE:          zEvent = "xTruncate"; break;
          757  +    case OS_SYNC:              zEvent = "xSync"; break;
          758  +    case OS_FILESIZE:          zEvent = "xFilesize"; break;
          759  +    case OS_LOCK:              zEvent = "xLock"; break;
          760  +    case OS_UNLOCK:            zEvent = "xUnlock"; break;
          761  +    case OS_CHECKRESERVEDLOCK: zEvent = "xCheckResLock"; break;
          762  +    case OS_FILECONTROL:       zEvent = "xFileControl"; break;
          763  +    case OS_SECTORSIZE:        zEvent = "xSectorSize"; break;
          764  +    case OS_DEVCHAR:           zEvent = "xDeviceChar"; break;
          765  +    case OS_OPEN:              zEvent = "xOpen"; break;
          766  +    case OS_DELETE:            zEvent = "xDelete"; break;
          767  +    case OS_ACCESS:            zEvent = "xAccess"; break;
          768  +    case OS_FULLPATHNAME:      zEvent = "xFullPathname"; break;
          769  +    case OS_RANDOMNESS:        zEvent = "xRandomness"; break;
          770  +    case OS_SLEEP:             zEvent = "xSleep"; break;
          771  +    case OS_CURRENTTIME:       zEvent = "xCurrentTime"; break;
          772  +
          773  +    case OS_SHMCLOSE:          zEvent = "xShmClose"; break;
          774  +    case OS_SHMOPEN:           zEvent = "xShmOpen"; break;
          775  +    case OS_SHMGET:            zEvent = "xShmGet"; break;
          776  +    case OS_SHMSIZE:           zEvent = "xShmSize"; break;
          777  +    case OS_SHMRELEASE:        zEvent = "xShmRelease"; break;
          778  +    case OS_SHMLOCK:           zEvent = "xShmLock"; break;
          779  +
          780  +    case OS_ANNOTATE:          zEvent = "annotation"; break;
          781  +  }
          782  +
          783  +  return zEvent;
          784  +}
          785  +
          786  +typedef struct VfslogVtab VfslogVtab;
          787  +typedef struct VfslogCsr VfslogCsr;
          788  +
          789  +/*
          790  +** Virtual table type for the vfslog reader module.
          791  +*/
          792  +struct VfslogVtab {
          793  +  sqlite3_vtab base;              /* Base class */
          794  +  sqlite3_file *pFd;              /* File descriptor open on vfslog file */
          795  +  sqlite3_int64 nByte;            /* Size of file in bytes */
          796  +  char *zFile;                    /* File name for pFd */
          797  +};
          798  +
          799  +/*
          800  +** Virtual table cursor type for the vfslog reader module.
          801  +*/
          802  +struct VfslogCsr {
          803  +  sqlite3_vtab_cursor base;       /* Base class */
          804  +  sqlite3_int64 iRowid;           /* Current rowid. */
          805  +  sqlite3_int64 iOffset;          /* Offset of next record in file */
          806  +  char *zTransient;               /* Transient 'file' string */
          807  +  int nFile;                      /* Size of array azFile[] */
          808  +  char **azFile;                  /* File strings */
          809  +  unsigned char aBuf[1024];       /* Current vfs log entry (read from file) */
          810  +};
          811  +
          812  +static unsigned int get32bits(unsigned char *p){
          813  +  return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
          814  +}
          815  +
          816  +/*
          817  +** The argument must point to a buffer containing a nul-terminated string.
          818  +** If the string begins with an SQL quote character it is overwritten by
          819  +** the dequoted version. Otherwise the buffer is left unmodified.
          820  +*/
          821  +static void dequote(char *z){
          822  +  char quote;                     /* Quote character (if any ) */
          823  +  quote = z[0];
          824  +  if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
          825  +    int iIn = 1;                  /* Index of next byte to read from input */
          826  +    int iOut = 0;                 /* Index of next byte to write to output */
          827  +    if( quote=='[' ) quote = ']';  
          828  +    while( z[iIn] ){
          829  +      if( z[iIn]==quote ){
          830  +        if( z[iIn+1]!=quote ) break;
          831  +        z[iOut++] = quote;
          832  +        iIn += 2;
          833  +      }else{
          834  +        z[iOut++] = z[iIn++];
          835  +      }
          836  +    }
          837  +    z[iOut] = '\0';
          838  +  }
          839  +}
          840  +
          841  +/*
          842  +** Connect to or create a vfslog virtual table.
          843  +*/
          844  +static int vlogConnect(
          845  +  sqlite3 *db,
          846  +  void *pAux,
          847  +  int argc, const char *const*argv,
          848  +  sqlite3_vtab **ppVtab,
          849  +  char **pzErr
          850  +){
          851  +  sqlite3_vfs *pVfs;              /* VFS used to read log file */
          852  +  int flags;                      /* flags passed to pVfs->xOpen() */
          853  +  VfslogVtab *p;
          854  +  int rc;
          855  +  int nByte;
          856  +  char *zFile;
          857  +
          858  +  *ppVtab = 0;
          859  +  pVfs = sqlite3_vfs_find(0);
          860  +  nByte = sizeof(VfslogVtab) + pVfs->szOsFile + pVfs->mxPathname;
          861  +  p = sqlite3_malloc(nByte);
          862  +  if( p==0 ) return SQLITE_NOMEM;
          863  +  memset(p, 0, nByte);
          864  +
          865  +  p->pFd = (sqlite3_file *)&p[1];
          866  +  p->zFile = &((char *)p->pFd)[pVfs->szOsFile];
          867  +
          868  +  zFile = sqlite3_mprintf("%s", argv[3]);
          869  +  if( !zFile ){
          870  +    sqlite3_free(p);
          871  +    return SQLITE_NOMEM;
          872  +  }
          873  +  dequote(zFile);
          874  +  pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile);
          875  +  sqlite3_free(zFile);
          876  +
          877  +  flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL;
          878  +  rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags);
          879  +
          880  +  if( rc==SQLITE_OK ){
          881  +    p->pFd->pMethods->xFileSize(p->pFd, &p->nByte);
          882  +    sqlite3_declare_vtab(db, 
          883  +        "CREATE TABLE xxx(event, file, click, rc, size, offset)"
          884  +    );
          885  +    *ppVtab = &p->base;
          886  +  }else{
          887  +    sqlite3_free(p);
          888  +  }
          889  +
          890  +  return rc;
          891  +}
          892  +
          893  +/*
          894  +** There is no "best-index". This virtual table always does a linear
          895  +** scan of the binary VFS log file.
          896  +*/
          897  +static int vlogBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
          898  +  pIdxInfo->estimatedCost = 10.0;
          899  +  return SQLITE_OK;
          900  +}
          901  +
          902  +/*
          903  +** Disconnect from or destroy a vfslog virtual table.
          904  +*/
          905  +static int vlogDisconnect(sqlite3_vtab *pVtab){
          906  +  VfslogVtab *p = (VfslogVtab *)pVtab;
          907  +  if( p->pFd->pMethods ){
          908  +    p->pFd->pMethods->xClose(p->pFd);
          909  +    p->pFd->pMethods = 0;
          910  +  }
          911  +  sqlite3_free(p);
          912  +  return SQLITE_OK;
          913  +}
          914  +
          915  +/*
          916  +** Open a new vfslog cursor.
          917  +*/
          918  +static int vlogOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
          919  +  VfslogCsr *pCsr;                /* Newly allocated cursor object */
          920  +
          921  +  pCsr = sqlite3_malloc(sizeof(VfslogCsr));
          922  +  if( !pCsr ) return SQLITE_NOMEM;
          923  +  memset(pCsr, 0, sizeof(VfslogCsr));
          924  +  *ppCursor = &pCsr->base;
          925  +  return SQLITE_OK;
          926  +}
          927  +
          928  +/*
          929  +** Close a vfslog cursor.
          930  +*/
          931  +static int vlogClose(sqlite3_vtab_cursor *pCursor){
          932  +  VfslogCsr *p = (VfslogCsr *)pCursor;
          933  +  int i;
          934  +  for(i=0; i<p->nFile; i++){
          935  +    sqlite3_free(p->azFile[i]);
          936  +  }
          937  +  sqlite3_free(p->azFile);
          938  +  sqlite3_free(p->zTransient);
          939  +  sqlite3_free(p);
          940  +  return SQLITE_OK;
          941  +}
          942  +
          943  +/*
          944  +** Move a vfslog cursor to the next entry in the file.
          945  +*/
          946  +static int vlogNext(sqlite3_vtab_cursor *pCursor){
          947  +  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
          948  +  VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
          949  +  int rc = SQLITE_OK;
          950  +  int nRead;
          951  +
          952  +  sqlite3_free(pCsr->zTransient);
          953  +  pCsr->zTransient = 0;
          954  +
          955  +  nRead = 24;
          956  +  if( pCsr->iOffset+nRead<=p->nByte ){
          957  +    int eEvent;
          958  +    rc = p->pFd->pMethods->xRead(p->pFd, pCsr->aBuf, nRead, pCsr->iOffset);
          959  +
          960  +    eEvent = get32bits(pCsr->aBuf);
          961  +    if( (rc==SQLITE_OK)
          962  +     && (eEvent==OS_OPEN || eEvent==OS_DELETE || eEvent==OS_ACCESS) 
          963  +    ){
          964  +      char buf[4];
          965  +      rc = p->pFd->pMethods->xRead(p->pFd, buf, 4, pCsr->iOffset+nRead);
          966  +      nRead += 4;
          967  +      if( rc==SQLITE_OK ){
          968  +        int nStr = get32bits((unsigned char *)buf);
          969  +        char *zStr = sqlite3_malloc(nStr+1);
          970  +        rc = p->pFd->pMethods->xRead(p->pFd, zStr, nStr, pCsr->iOffset+nRead);
          971  +        zStr[nStr] = '\0';
          972  +        nRead += nStr;
          973  +
          974  +        if( eEvent==OS_OPEN ){
          975  +          int iFileid = get32bits(&pCsr->aBuf[4]);
          976  +          if( iFileid>=pCsr->nFile ){
          977  +            int nNew = sizeof(pCsr->azFile[0])*(iFileid+1);
          978  +            pCsr->azFile = (char **)sqlite3_realloc(pCsr->azFile, nNew);
          979  +            nNew -= sizeof(pCsr->azFile[0])*pCsr->nFile;
          980  +            memset(&pCsr->azFile[pCsr->nFile], 0, nNew);
          981  +            pCsr->nFile = iFileid+1;
          982  +          }
          983  +          sqlite3_free(pCsr->azFile[iFileid]);
          984  +          pCsr->azFile[iFileid] = zStr;
          985  +        }else{
          986  +          pCsr->zTransient = zStr;
          987  +        }
          988  +      }
          989  +    }
   802    990     }
   803    991   
   804         -  pVfs = sqlite3_instvfs_create(zVfs, zParentVfs);
   805         -  if( pVfs ){
   806         -    sqlite3_instvfs_configure(pVfs, binarylog_xcall, p, binarylog_xdel);
          992  +  pCsr->iRowid += 1;
          993  +  pCsr->iOffset += nRead;
          994  +  return rc;
          995  +}
          996  +
          997  +static int vlogEof(sqlite3_vtab_cursor *pCursor){
          998  +  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
          999  +  VfslogVtab *p = (VfslogVtab *)pCursor->pVtab;
         1000  +  return (pCsr->iOffset>=p->nByte);
         1001  +}
         1002  +
         1003  +static int vlogFilter(
         1004  +  sqlite3_vtab_cursor *pCursor, 
         1005  +  int idxNum, const char *idxStr,
         1006  +  int argc, sqlite3_value **argv
         1007  +){
         1008  +  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
         1009  +  pCsr->iRowid = 0;
         1010  +  pCsr->iOffset = 20;
         1011  +  return vlogNext(pCursor);
         1012  +}
         1013  +
         1014  +static int vlogColumn(
         1015  +  sqlite3_vtab_cursor *pCursor, 
         1016  +  sqlite3_context *ctx, 
         1017  +  int i
         1018  +){
         1019  +  unsigned int val;
         1020  +  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
         1021  +
         1022  +  assert( i<7 );
         1023  +  val = get32bits(&pCsr->aBuf[4*i]);
         1024  +
         1025  +  switch( i ){
         1026  +    case 0: {
         1027  +      sqlite3_result_text(ctx, vfslog_eventname(val), -1, SQLITE_STATIC);
         1028  +      break;
         1029  +    }
         1030  +    case 1: {
         1031  +      char *zStr = pCsr->zTransient;
         1032  +      if( val!=0 && val<pCsr->nFile ){
         1033  +        zStr = pCsr->azFile[val];
         1034  +      }
         1035  +      sqlite3_result_text(ctx, zStr, -1, SQLITE_TRANSIENT);
         1036  +      break;
         1037  +    }
         1038  +    default:
         1039  +      sqlite3_result_int(ctx, val);
         1040  +      break;
   807   1041     }
   808   1042   
   809         -  return pVfs;
         1043  +  return SQLITE_OK;
         1044  +}
         1045  +
         1046  +static int vlogRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
         1047  +  VfslogCsr *pCsr = (VfslogCsr *)pCursor;
         1048  +  *pRowid = pCsr->iRowid;
         1049  +  return SQLITE_OK;
         1050  +}
         1051  +
         1052  +int sqlite3_vfslog_register(sqlite3 *db){
         1053  +  static sqlite3_module vfslog_module = {
         1054  +    0,                            /* iVersion */
         1055  +    vlogConnect,                /* xCreate */
         1056  +    vlogConnect,                /* xConnect */
         1057  +    vlogBestIndex,              /* xBestIndex */
         1058  +    vlogDisconnect,             /* xDisconnect */
         1059  +    vlogDisconnect,             /* xDestroy */
         1060  +    vlogOpen,                   /* xOpen - open a cursor */
         1061  +    vlogClose,                  /* xClose - close a cursor */
         1062  +    vlogFilter,                 /* xFilter - configure scan constraints */
         1063  +    vlogNext,                   /* xNext - advance a cursor */
         1064  +    vlogEof,                    /* xEof - check for end of scan */
         1065  +    vlogColumn,                 /* xColumn - read data */
         1066  +    vlogRowid,                  /* xRowid - read data */
         1067  +    0,                            /* xUpdate */
         1068  +    0,                            /* xBegin */
         1069  +    0,                            /* xSync */
         1070  +    0,                            /* xCommit */
         1071  +    0,                            /* xRollback */
         1072  +    0,                            /* xFindMethod */
         1073  +    0,                            /* xRename */
         1074  +  };
         1075  +
         1076  +  sqlite3_create_module(db, "vfslog", &vfslog_module, 0);
         1077  +  return SQLITE_OK;
   810   1078   }
   811         -#endif /* SQLITE_ENABLE_INSTVFS */
         1079  +
   812   1080   
   813   1081   /**************************************************************************
   814   1082   ***************************************************************************
   815   1083   ** Tcl interface starts here.
   816   1084   */
   817         -#if SQLITE_TEST
         1085  +
         1086  +#if defined(SQLITE_TEST) || defined(TCLSH)
   818   1087   
   819   1088   #include <tcl.h>
   820   1089   
   821         -#ifdef SQLITE_ENABLE_INSTVFS
   822         -struct InstVfsCall {
   823         -  Tcl_Interp *interp;
   824         -  Tcl_Obj *pScript;
   825         -};
   826         -typedef struct InstVfsCall InstVfsCall;
   827         -
   828         -static void test_instvfs_xcall(
   829         -  void *p,
   830         -  int eEvent,
   831         -  int iFileId,
   832         -  sqlite3_int64 nClick,
   833         -  int return_code,
   834         -  const char *zName,
   835         -  int flags,
   836         -  int nByte,
   837         -  sqlite3_int64 iOffset
   838         -){
   839         -  int rc;
   840         -  InstVfsCall *pCall = (InstVfsCall *)p;
   841         -  Tcl_Obj *pObj = Tcl_DuplicateObj( pCall->pScript);
   842         -  const char *zEvent = sqlite3_instvfs_name(eEvent);
   843         -
   844         -  Tcl_IncrRefCount(pObj);
   845         -  Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zEvent, -1));
   846         -  Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(nClick));
   847         -  Tcl_ListObjAppendElement(0, pObj, Tcl_NewStringObj(zName, -1));
   848         -  Tcl_ListObjAppendElement(0, pObj, Tcl_NewIntObj(nByte));
   849         -  Tcl_ListObjAppendElement(0, pObj, Tcl_NewWideIntObj(iOffset));
   850         -
   851         -  rc = Tcl_EvalObjEx(pCall->interp, pObj, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
   852         -  if( rc ){
   853         -    Tcl_BackgroundError(pCall->interp);
   854         -  }
   855         -  Tcl_DecrRefCount(pObj);
   856         -}
   857         -
   858         -static void test_instvfs_xdel(void *p){
   859         -  InstVfsCall *pCall = (InstVfsCall *)p;
   860         -  Tcl_DecrRefCount(pCall->pScript);
   861         -  sqlite3_free(pCall);
   862         -}
   863         -
   864         -static int test_sqlite3_instvfs(
   865         -  void * clientData,
         1090  +static int test_vfslog(
         1091  +  void *clientData,
   866   1092     Tcl_Interp *interp,
   867   1093     int objc,
   868   1094     Tcl_Obj *CONST objv[]
   869   1095   ){
   870         -  static const char *IV_strs[] = 
   871         -               { "create",  "destroy",  "reset",  "report", "configure", "binarylog", "marker", 0 };
   872         -  enum IV_enum { IV_CREATE, IV_DESTROY, IV_RESET, IV_REPORT, IV_CONFIGURE, IV_BINARYLOG, IV_MARKER };
         1096  +  struct SqliteDb { sqlite3 *db; };
         1097  +  sqlite3 *db;
         1098  +  Tcl_CmdInfo cmdInfo;
         1099  +  int rc = SQLITE_ERROR;
         1100  +
         1101  +  static const char *strs[] = { "annotate", "finalize", "new",  "register", 0 };
         1102  +  enum VL_enum { VL_ANNOTATE, VL_FINALIZE, VL_NEW, VL_REGISTER };
   873   1103     int iSub;
   874   1104   
   875   1105     if( objc<2 ){
   876   1106       Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
         1107  +    return TCL_ERROR;
   877   1108     }
   878         -  if( Tcl_GetIndexFromObj(interp, objv[1], IV_strs, "sub-command", 0, &iSub) ){
         1109  +  if( Tcl_GetIndexFromObj(interp, objv[1], strs, "sub-command", 0, &iSub) ){
   879   1110       return TCL_ERROR;
   880   1111     }
   881   1112   
   882         -  switch( (enum IV_enum)iSub ){
   883         -    case IV_CREATE: {
   884         -      char *zParent = 0;
   885         -      sqlite3_vfs *p;
   886         -      int isDefault = 0;
   887         -      if( objc>2 && 0==strcmp("-default", Tcl_GetString(objv[2])) ){
   888         -        isDefault = 1;
   889         -      }
   890         -      if( (objc-isDefault)!=4 && (objc-isDefault)!=3 ){
   891         -        Tcl_WrongNumArgs(interp, 2, objv, "?-default? NAME ?PARENT-VFS?");
         1113  +  switch( (enum VL_enum)iSub ){
         1114  +    case VL_ANNOTATE: {
         1115  +      int rc;
         1116  +      char *zVfs;
         1117  +      char *zMsg;
         1118  +      if( objc!=4 ){
         1119  +        Tcl_WrongNumArgs(interp, 3, objv, "VFS");
   892   1120           return TCL_ERROR;
   893   1121         }
   894         -      if( objc==(4+isDefault) ){
   895         -        zParent = Tcl_GetString(objv[3+isDefault]);
   896         -      }
   897         -      p = sqlite3_instvfs_create(Tcl_GetString(objv[2+isDefault]), zParent);
   898         -      if( !p ){
   899         -        Tcl_AppendResult(interp, "error creating vfs ", 0);
   900         -        return TCL_ERROR;
   901         -      }
   902         -      if( isDefault ){
   903         -        sqlite3_vfs_register(p, 1);
   904         -      }
   905         -      Tcl_SetObjResult(interp, objv[2]);
   906         -      break;
   907         -    }
   908         -    case IV_BINARYLOG: {
   909         -      char *zName = 0;
   910         -      char *zLog = 0;
   911         -      char *zParent = 0;
   912         -      sqlite3_vfs *p;
   913         -      int isDefault = 0;
   914         -      int isLogdata = 0;
   915         -      int argbase = 2;
   916         -
   917         -      for(argbase=2; argbase<(objc-2); argbase++){
   918         -        if( 0==strcmp("-default", Tcl_GetString(objv[argbase])) ){
   919         -          isDefault = 1;
   920         -        }
   921         -        else if( 0==strcmp("-parent", Tcl_GetString(objv[argbase])) ){
   922         -          argbase++;
   923         -          zParent = Tcl_GetString(objv[argbase]);
   924         -        }
   925         -        else if( 0==strcmp("-logdata", Tcl_GetString(objv[argbase])) ){
   926         -          isLogdata = 1;
   927         -        }else{
   928         -          break;
   929         -        }
   930         -      }
   931         -
   932         -      if( (objc-argbase)!=2 ){
   933         -        Tcl_WrongNumArgs(
   934         -            interp, 2, objv, "?-default? ?-parent VFS? ?-logdata? NAME LOGFILE"
   935         -        );
   936         -        return TCL_ERROR;
   937         -      }
   938         -      zName = Tcl_GetString(objv[argbase]);
   939         -      zLog = Tcl_GetString(objv[argbase+1]);
   940         -      p = sqlite3_instvfs_binarylog(zName, zParent, zLog, isLogdata);
   941         -      if( !p ){
   942         -        Tcl_AppendResult(interp, "error creating vfs ", 0);
   943         -        return TCL_ERROR;
   944         -      }
   945         -      if( isDefault ){
   946         -        sqlite3_vfs_register(p, 1);
   947         -      }
   948         -      Tcl_SetObjResult(interp, objv[2]);
   949         -      break;
   950         -    }
   951         -
   952         -    case IV_MARKER: {
   953         -      sqlite3_vfs *p;
   954         -      if( objc!=4 ){
   955         -        Tcl_WrongNumArgs(interp, 2, objv, "VFS MARKER");
   956         -        return TCL_ERROR;
   957         -      }
   958         -      p = sqlite3_vfs_find(Tcl_GetString(objv[2]));
   959         -      if( !p || p->xOpen!=instOpen ){
   960         -        Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0);
   961         -        return TCL_ERROR;
   962         -      }
   963         -      sqlite3_instvfs_binarylog_marker(p, Tcl_GetString(objv[3]));
   964         -      Tcl_ResetResult(interp);
   965         -      break;
   966         -    }
   967         -
   968         -    case IV_CONFIGURE: {
   969         -      InstVfsCall *pCall;
   970         -
   971         -      sqlite3_vfs *p;
   972         -      if( objc!=4 ){
   973         -        Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
   974         -        return TCL_ERROR;
   975         -      }
   976         -      p = sqlite3_vfs_find(Tcl_GetString(objv[2]));
   977         -      if( !p || p->xOpen!=instOpen ){
   978         -        Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0);
   979         -        return TCL_ERROR;
   980         -      }
   981         -
   982         -      if( strlen(Tcl_GetString(objv[3])) ){
   983         -        pCall = (InstVfsCall *)sqlite3_malloc(sizeof(InstVfsCall));
   984         -        pCall->interp = interp;
   985         -        pCall->pScript = Tcl_DuplicateObj(objv[3]);
   986         -        Tcl_IncrRefCount(pCall->pScript);
   987         -        sqlite3_instvfs_configure(p, 
   988         -            test_instvfs_xcall, (void *)pCall, test_instvfs_xdel
   989         -        );
   990         -      }else{
   991         -        sqlite3_instvfs_configure(p, 0, 0, 0);
         1122  +      zVfs = Tcl_GetString(objv[2]);
         1123  +      zMsg = Tcl_GetString(objv[3]);
         1124  +      rc = sqlite3_vfslog_annotate(zVfs, zMsg);
         1125  +      if( rc!=SQLITE_OK ){
         1126  +        Tcl_AppendResult(interp, "failed", 0);
         1127  +        return TCL_ERROR;
   992   1128         }
   993   1129         break;
   994   1130       }
         1131  +    case VL_FINALIZE: {
         1132  +      int rc;
         1133  +      char *zVfs;
         1134  +      if( objc!=3 ){
         1135  +        Tcl_WrongNumArgs(interp, 2, objv, "VFS");
         1136  +        return TCL_ERROR;
         1137  +      }
         1138  +      zVfs = Tcl_GetString(objv[2]);
         1139  +      rc = sqlite3_vfslog_finalize(zVfs);
         1140  +      if( rc!=SQLITE_OK ){
         1141  +        Tcl_AppendResult(interp, "failed", 0);
         1142  +        return TCL_ERROR;
         1143  +      }
         1144  +      break;
         1145  +    };
         1146  +
         1147  +    case VL_NEW: {
         1148  +      int rc;
         1149  +      char *zVfs;
         1150  +      char *zParent;
         1151  +      char *zLog;
         1152  +      if( objc!=5 ){
         1153  +        Tcl_WrongNumArgs(interp, 2, objv, "VFS PARENT LOGFILE");
         1154  +        return TCL_ERROR;
         1155  +      }
         1156  +      zVfs = Tcl_GetString(objv[2]);
         1157  +      zParent = Tcl_GetString(objv[3]);
         1158  +      zLog = Tcl_GetString(objv[4]);
         1159  +      if( *zParent=='\0' ) zParent = 0;
         1160  +      rc = sqlite3_vfslog_new(zVfs, zParent, zLog);
         1161  +      if( rc!=SQLITE_OK ){
         1162  +        Tcl_AppendResult(interp, "failed", 0);
         1163  +        return TCL_ERROR;
         1164  +      }
         1165  +      break;
         1166  +    };
   995   1167   
   996         -    case IV_REPORT:
   997         -    case IV_DESTROY:
   998         -    case IV_RESET: {
   999         -      sqlite3_vfs *p;
         1168  +    case VL_REGISTER: {
         1169  +      char *zDb;
  1000   1170         if( objc!=3 ){
  1001         -        Tcl_WrongNumArgs(interp, 2, objv, "NAME");
         1171  +        Tcl_WrongNumArgs(interp, 2, objv, "DB");
  1002   1172           return TCL_ERROR;
  1003   1173         }
  1004         -      p = sqlite3_vfs_find(Tcl_GetString(objv[2]));
  1005         -      if( !p || p->xOpen!=instOpen ){
  1006         -        Tcl_AppendResult(interp, "no such vfs: ", Tcl_GetString(objv[2]), 0);
         1174  +      zDb = Tcl_GetString(objv[2]);
         1175  +      if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
         1176  +        db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
         1177  +        rc = sqlite3_vfslog_register(db);
         1178  +      }
         1179  +      if( rc!=SQLITE_OK ){
         1180  +        Tcl_AppendResult(interp, "Bad sqlite3 handle: ", zDb, 0);
  1007   1181           return TCL_ERROR;
  1008   1182         }
  1009         -
  1010         -      if( ((enum IV_enum)iSub)==IV_DESTROY ){
  1011         -        sqlite3_instvfs_destroy(p);
  1012         -      }
  1013         -      if( ((enum IV_enum)iSub)==IV_RESET ){
  1014         -        sqlite3_instvfs_reset(p);
  1015         -      }
  1016         -      if( ((enum IV_enum)iSub)==IV_REPORT ){
  1017         -        int ii;
  1018         -        Tcl_Obj *pRet = Tcl_NewObj();
  1019         -
  1020         -        const char *zName = (char *)1;
  1021         -        sqlite3_int64 nClick;
  1022         -        int nCall;
  1023         -        for(ii=1; zName; ii++){
  1024         -          sqlite3_instvfs_get(p, ii, &zName, &nClick, &nCall);
  1025         -          if( zName ){
  1026         -            Tcl_Obj *pElem = Tcl_NewObj();
  1027         -            Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj(zName, -1));
  1028         -            Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(nCall));
  1029         -            Tcl_ListObjAppendElement(0, pElem, Tcl_NewWideIntObj(nClick));
  1030         -            Tcl_ListObjAppendElement(0, pRet, pElem);
  1031         -          }
  1032         -        }
  1033         -
  1034         -        Tcl_SetObjResult(interp, pRet);
  1035         -      }
  1036         -
  1037   1183         break;
  1038         -    }
         1184  +    };
  1039   1185     }
  1040   1186   
  1041   1187     return TCL_OK;
  1042   1188   }
  1043         -#endif /* SQLITE_ENABLE_INSTVFS */
  1044         -
  1045         -/* Alternative implementation of sqlite3_instvfs when the real
  1046         -** implementation is unavailable. 
  1047         -*/
  1048         -#ifndef SQLITE_ENABLE_INSTVFS
  1049         -static int test_sqlite3_instvfs(
  1050         -  void * clientData,
  1051         -  Tcl_Interp *interp,
  1052         -  int objc,
  1053         -  Tcl_Obj *CONST objv[]
  1054         -){
  1055         -  Tcl_AppendResult(interp, 
  1056         -     "not compiled with -DSQLITE_ENABLE_INSTVFS; sqlite3_instvfs is "
  1057         -     "unavailable", (char*)0);
  1058         -  return TCL_ERROR;
  1059         -}
  1060         -#endif /* !defined(SQLITE_ENABLE_INSTVFS) */
  1061   1189   
  1062   1190   int SqlitetestOsinst_Init(Tcl_Interp *interp){
  1063         -  Tcl_CreateObjCommand(interp, "sqlite3_instvfs", test_sqlite3_instvfs, 0, 0);
         1191  +  Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0);
  1064   1192     return TCL_OK;
  1065   1193   }
  1066   1194   
  1067   1195   #endif /* SQLITE_TEST */
         1196  +

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         -typedef struct tvfs_file tvfs_file;
    20         -struct tvfs_file {
    21         -  sqlite3_file base;
    22         -  sqlite3_file *pReal;
    23         -};
    24         -
    25     19   typedef struct Testvfs Testvfs;
    26     20   typedef struct TestvfsShm TestvfsShm;
    27     21   typedef struct TestvfsBuffer TestvfsBuffer;
           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 */
           34  +};
           35  +
    28     36   
    29     37   /*
    30     38   ** An instance of this structure is allocated for each VFS created. The
    31     39   ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
    32     40   ** is set to point to it.
    33     41   */
    34     42   struct Testvfs {
................................................................................
    35     43     char *zName;                    /* Name of this VFS */
    36     44     sqlite3_vfs *pParent;           /* The VFS to use for file IO */
    37     45     sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
    38     46     Tcl_Interp *interp;             /* Interpreter to run script in */
    39     47     int nScript;                    /* Number of elements in array apScript */
    40     48     Tcl_Obj **apScript;             /* Script to execute */
    41     49     TestvfsBuffer *pBuffer;         /* List of shared buffers */
           50  +  int isNoshm;
    42     51   };
    43     52   
    44     53   /*
    45     54   ** A shared-memory buffer.
    46     55   */
    47     56   struct TestvfsBuffer {
    48     57     char *zFile;                    /* Associated file name */
    49     58     int n;                          /* Size of allocated buffer in bytes */
    50     59     u8 *a;                          /* Buffer allocated using ckalloc() */
    51     60     int nRef;                       /* Number of references to this object */
    52     61     TestvfsBuffer *pNext;           /* Next in linked list of all buffers */
    53     62   };
    54     63   
    55         -/*
    56         -** A shared-memory handle returned by tvfsShmOpen().
    57         -*/
    58         -struct TestvfsShm {
    59         -  Tcl_Obj *id;                    /* Name of this handle */
    60         -  TestvfsBuffer *pBuffer;         /* Underlying buffer */
    61         -};
    62         -
    63     64   
    64     65   #define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent)
    65     66   
    66     67   
    67     68   /*
    68         -** Method declarations for tvfs_file.
           69  +** Method declarations for TestvfsFile.
    69     70   */
    70     71   static int tvfsClose(sqlite3_file*);
    71     72   static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
    72     73   static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
    73     74   static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size);
    74     75   static int tvfsSync(sqlite3_file*, int flags);
    75     76   static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
................................................................................
    93     94   static void (*tvfsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
    94     95   static void tvfsDlClose(sqlite3_vfs*, void*);
    95     96   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
    96     97   static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
    97     98   static int tvfsSleep(sqlite3_vfs*, int microseconds);
    98     99   static int tvfsCurrentTime(sqlite3_vfs*, double*);
    99    100   
   100         -static int tvfsShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **);
   101         -static int tvfsShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *);
   102         -static int tvfsShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **);
   103         -static int tvfsShmRelease(sqlite3_vfs*, sqlite3_shm *);
   104         -static int tvfsShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *);
   105         -static int tvfsShmClose(sqlite3_vfs*, sqlite3_shm *, int);
          101  +static int tvfsShmOpen(sqlite3_file*);
          102  +static int tvfsShmSize(sqlite3_file*, int , int *);
          103  +static int tvfsShmGet(sqlite3_file*, int , int *, void **);
          104  +static int tvfsShmRelease(sqlite3_file*);
          105  +static int tvfsShmLock(sqlite3_file*, int , int *);
          106  +static int tvfsShmClose(sqlite3_file*, int);
   106    107   
   107    108   static sqlite3_io_methods tvfs_io_methods = {
   108         -  1,                            /* iVersion */
          109  +