/ Check-in [76504726]
Login

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

Overview
Comment:Updates to WAL support in os_win.c: pulled in latest changes from src/os_unix.c; updated tracing; misc. improvements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal-win32
Files: files | file ages | folders
SHA1: 76504726a1ef7f6a0445ec800776462138b22d72
User & Date: shaneh 2010-05-12 17:14:59
Context
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
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
2010-05-11
02:49
Initial port of WAL VFS support from os_unix.c to os_win.c. check-in: 111ad59f user: shaneh tags: wal-win32
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_win.c.

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
....
1409
1410
1411
1412
1413
1414
1415

1416

1417
1418
1419
1420
1421
1422
1423
....
2083
2084
2085
2086
2087
2088
2089


2090
2091
2092



2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
....
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
2137
2138

2139
2140



2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
....
2198
2199
2200
2201
2202
2203
2204
2205

2206
2207
2208
2209
2210
2211
2212
....
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365




2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
....
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
....
2716
2717
2718
2719
2720
2721
2722
2723

2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737
....
2806
2807
2808
2809
2810
2811
2812
2813

2814
2815
2816
2817
2818
2819
2820
  int res = 1;           /* Result of a windows lock call */
  int newLocktype;       /* Set pFile->locktype to this value before exiting */
  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
  winFile *pFile = (winFile*)id;
  DWORD error = NO_ERROR;

  assert( id!=0 );
  OSTRACE5("LOCK %d %d was %d(%d)\n",
          pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);

  /* If there is already a lock of this type or more restrictive on the
  ** OsFile, do nothing. Don't use the end_lock: exit path, as
  ** sqlite3OsEnterMutex() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    return SQLITE_OK;
................................................................................
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       NULL
    );
#endif
  }

  OSTRACE4("OPEN %d %s 0x%lx\n", h, zName, dwDesiredAccess);

  if( h==INVALID_HANDLE_VALUE ){
    free(zConverted);
    if( flags & SQLITE_OPEN_READWRITE ){
      return winOpen(pVfs, zName, id, 
             ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
    }else{
      return SQLITE_CANTOPEN_BKPT;
................................................................................

  /* Access to the winShmFile object is serialized by the caller */
  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );

  /* Initialize the locking parameters */
  if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
    dwFlags = 0;


    OSTRACE(("SHM-LOCK requesting blocking lock %s\n", winShmLockString(lockMask)));
  }else{
    dwFlags = LOCKFILE_FAIL_IMMEDIATELY;



    OSTRACE(("SHM-LOCK requesting %s %s\n", lockType!=_SHM_UNLCK ? "unlock" : "lock", winShmLockString(lockMask)));
  }
  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;

  /* Find the first bit in lockMask that is set */
  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
  assert( mask!=0 );
  memset(&ovlp, 0, sizeof(OVERLAPPED));
  ovlp.Offset = i+WIN_SHM_BASE;
  ovlp.OffsetHigh = 0;
  nBytes = 1;

  /* Extend the locking range for each additional bit that is set */
  mask <<= 1;
  while( mask!=0 && (lockMask & mask)!=0 ){
    nBytes++;
    mask <<= 1;
................................................................................

  /* Release/Acquire the system-level lock */
  if( lockType==_SHM_UNLCK ){
    for(i=0; i<nBytes; i++, ovlp.Offset++){
      rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
      if( !rc ) break;
    }
    if( !rc ){
      OSTRACE(("SHM-LOCK UnlockFileEx ERROR %d - 0x%08lx\n", rc, GetLastError()));
      /* continue to release individual byte locks (if any) */
      for(; i<nBytes; i++, ovlp.Offset++){
        UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
      }
    }
  }else{
    /* release old individual byte locks (if any). */

    for(i=0; i<nBytes; i++, ovlp.Offset++){
      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
    }
    ovlp.Offset-=nBytes;
    /* set new individual byte locks */
    for(i=0; i<(int)nBytes; i++, ovlp.Offset++){
      rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
      if( !rc ) break;
    }

    if( !rc ){
      OSTRACE(("SHM-LOCK LockFileEx ERROR %d - 0x%08lx\n", rc, GetLastError()));



      /* release individual byte locks (if any) */
      ovlp.Offset-=i;
      for(i=0; i<nBytes; i++, ovlp.Offset++){
        UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
      }
    }
  }
  rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;

  /* Update the global lock state and do debug tracing */
#ifdef SQLITE_DEBUG
  OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
................................................................................
  u8 allMask;  /* Union of locks held by connections other than "p" */

  /* Access to the winShmFile object is serialized by the caller */
  assert( sqlite3_mutex_held(pFile->mutex) );

  /* don't attempt to unlock anything we don't have locks for */
  if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
    OSTRACE(("SHM-UNLOCKING more than we have locked - requested %s - have %s\n",

             winShmLockString(unlockMask),
             winShmLockString(p->exclMask|p->sharedMask)));
    unlockMask &= (p->exclMask|p->sharedMask);
  }

  /* Compute locks held by sibling connections */
  allMask = 0;
................................................................................
** the file must be truncated to zero length or have its header cleared.
*/
static int winShmOpen(
  sqlite3_vfs *pVfs,    /* The VFS */
  const char *zName,    /* Name of the corresponding database file */
  sqlite3_shm **pShm    /* Write the winShm object created here */
){
  struct winShm *p = 0;              /* The connection to be opened */
  struct winShmFile *pFile = 0;      /* The underlying mmapped file */
  int rc;                            /* Result code */
  struct winShmFile *pNew;           /* Newly allocated pFile */
  int nName;                         /* Size of zName in bytes */





  /* Allocate space for the new sqlite3_shm object.  Also speculatively
  ** allocate space for a new winShmFile and filename.
  */
  p = sqlite3_malloc( sizeof(*p) );
  if( p==0 ) return SQLITE_NOMEM;
  memset(p, 0, sizeof(*p));
  nName = strlen(zName);
  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 15 );
  if( pNew==0 ){
    sqlite3_free(p);
    return SQLITE_NOMEM;
  }
  memset(pNew, 0, sizeof(*pNew));
  pNew->zFilename = (char*)&pNew[1];
  sqlite3_snprintf(nName+11, pNew->zFilename, "%s-wal-index", zName);

  /* Look to see if there is an existing winShmFile that can be used.
  ** If no matching winShmFile currently exists, create a new one.
  */
  winShmEnterMutex();
  for(pFile = winShmFileList; pFile; pFile=pFile->pNext){
    /* TBD need to come up with better match here.  Perhaps
    ** use winFullPathname() or FILE_ID_BOTH_DIR_INFO Structure.
    */
    if( strcmp(pFile->zFilename, pNew->zFilename)==0 ) break;
  }
  if( pFile ){
    sqlite3_free(pNew);
  }else{
    pFile = pNew;
    pNew = 0;
    pFile->pMMapBuf = NULL;
................................................................................
      goto shm_open_err;
    }
    pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    if( pFile->mutexBuf==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }

    rc = winOpen(pVfs,
                 pFile->zFilename,                  /* Name of the file (UTF-8) */
                 (sqlite3_file *)&pFile->hFile, /* Write the SQLite file handle here */
                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Open mode flags */
                 0);
    if( SQLITE_OK!=rc ){
      rc = SQLITE_CANTOPEN_BKPT;
................................................................................

  /* Return directly if this is just a lock state query, or if
  ** the connection is already in the desired locking state.
  */
  if( desiredLock==p->lockState
   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
  ){
    OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n",

             p->id, (int)GetCurrentProcessId(), azLkName[desiredLock], azLkName[p->lockState]));
    if( pGotLock ) *pGotLock = p->lockState;
    return SQLITE_OK;
  }

  OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",

            p->id, (int)GetCurrentProcessId(), azLkName[p->lockState], azLkName[desiredLock]));
  
  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
    assert( sqlite3_mutex_notheld(pFile->mutex) );
    sqlite3_mutex_enter(pFile->mutexBuf);
    p->hasMutexBuf = 1;
  }
  sqlite3_mutex_enter(pFile->mutex);
................................................................................
      if( rc==SQLITE_OK ){
        p->lockState = SQLITE_SHM_RECOVER;
      }
      break;
    }
  }
  sqlite3_mutex_leave(pFile->mutex);
  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",

           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
  if( pGotLock ) *pGotLock = p->lockState;
  return rc;
}

#else
# define winShmOpen    0







|
|







 







>
|
>







 







>
>
|


>
>
>
|








<







 







<
<
<
<
<
<
<

|
>


<
<
<
<



>
|
<
>
>
>
|
|
|
|
<







 







|
>







 







|




>
>
>
>







|







|







|

|







 







<







 







|
>





|
>
|







 







|
>







920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
....
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
....
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115
....
2120
2121
2122
2123
2124
2125
2126







2127
2128
2129
2130
2131




2132
2133
2134
2135
2136

2137
2138
2139
2140
2141
2142
2143

2144
2145
2146
2147
2148
2149
2150
....
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
....
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
....
2410
2411
2412
2413
2414
2415
2416

2417
2418
2419
2420
2421
2422
2423
....
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
....
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
  int res = 1;           /* Result of a windows lock call */
  int newLocktype;       /* Set pFile->locktype to this value before exiting */
  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
  winFile *pFile = (winFile*)id;
  DWORD error = NO_ERROR;

  assert( id!=0 );
  OSTRACE(("LOCK %d %d was %d(%d)\n",
           pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));

  /* If there is already a lock of this type or more restrictive on the
  ** OsFile, do nothing. Don't use the end_lock: exit path, as
  ** sqlite3OsEnterMutex() hasn't been called yet.
  */
  if( pFile->locktype>=locktype ){
    return SQLITE_OK;
................................................................................
       NULL,
       dwCreationDisposition,
       dwFlagsAndAttributes,
       NULL
    );
#endif
  }
  OSTRACE(("OPEN %d %s 0x%lx %s\n", 
           h, zName, dwDesiredAccess, 
           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
  if( h==INVALID_HANDLE_VALUE ){
    free(zConverted);
    if( flags & SQLITE_OPEN_READWRITE ){
      return winOpen(pVfs, zName, id, 
             ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
    }else{
      return SQLITE_CANTOPEN_BKPT;
................................................................................

  /* Access to the winShmFile object is serialized by the caller */
  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );

  /* Initialize the locking parameters */
  if( lockMask==WIN_SHM_C && lockType!=_SHM_UNLCK ){
    dwFlags = 0;
    OSTRACE(("SHM-LOCK %d requesting blocking lock %s\n", 
             pFile->hFile.h,
             winShmLockString(lockMask)));
  }else{
    dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
    OSTRACE(("SHM-LOCK %d requesting %s %s\n", 
             pFile->hFile.h,
             lockType!=_SHM_UNLCK ? "lock" : "unlock", 
             winShmLockString(lockMask)));
  }
  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;

  /* Find the first bit in lockMask that is set */
  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
  assert( mask!=0 );
  memset(&ovlp, 0, sizeof(OVERLAPPED));
  ovlp.Offset = i+WIN_SHM_BASE;

  nBytes = 1;

  /* Extend the locking range for each additional bit that is set */
  mask <<= 1;
  while( mask!=0 && (lockMask & mask)!=0 ){
    nBytes++;
    mask <<= 1;
................................................................................

  /* Release/Acquire the system-level lock */
  if( lockType==_SHM_UNLCK ){
    for(i=0; i<nBytes; i++, ovlp.Offset++){
      rc = UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);
      if( !rc ) break;
    }







  }else{
    /* release old individual byte locks (if any)
    ** and set new individual byte locks */
    for(i=0; i<nBytes; i++, ovlp.Offset++){
      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);




      rc = LockFileEx(pFile->hFile.h, dwFlags, 0, 1, 0, &ovlp);
      if( !rc ) break;
    }
  }
  if( !rc ){

    OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n", 
             pFile->hFile.h,
             lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx", GetLastError()));
    /* release individual byte locks (if any) */
    ovlp.Offset-=i;
    for(i=0; i<nBytes; i++, ovlp.Offset++){
      UnlockFileEx(pFile->hFile.h, 0, 1, 0, &ovlp);

    }
  }
  rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;

  /* Update the global lock state and do debug tracing */
#ifdef SQLITE_DEBUG
  OSTRACE(("SHM-LOCK %d ", pFile->hFile.h));
................................................................................
  u8 allMask;  /* Union of locks held by connections other than "p" */

  /* Access to the winShmFile object is serialized by the caller */
  assert( sqlite3_mutex_held(pFile->mutex) );

  /* don't attempt to unlock anything we don't have locks for */
  if( (unlockMask & (p->exclMask|p->sharedMask)) != unlockMask ){
    OSTRACE(("SHM-LOCK %d unlocking more than we have locked - requested %s - have %s\n",
             pFile->hFile.h,
             winShmLockString(unlockMask),
             winShmLockString(p->exclMask|p->sharedMask)));
    unlockMask &= (p->exclMask|p->sharedMask);
  }

  /* Compute locks held by sibling connections */
  allMask = 0;
................................................................................
** the file must be truncated to zero length or have its header cleared.
*/
static int winShmOpen(
  sqlite3_vfs *pVfs,    /* The VFS */
  const char *zName,    /* Name of the corresponding database file */
  sqlite3_shm **pShm    /* Write the winShm object created here */
){
  struct winShm *p;                  /* The connection to be opened */
  struct winShmFile *pFile = 0;      /* The underlying mmapped file */
  int rc;                            /* Result code */
  struct winShmFile *pNew;           /* Newly allocated pFile */
  int nName;                         /* Size of zName in bytes */
  char zFullpath[MAX_PATH+1];        /* Temp buffer for full file name */

  rc = winFullPathname(pVfs, zName, MAX_PATH, zFullpath);
  if( rc ) return rc;

  /* Allocate space for the new sqlite3_shm object.  Also speculatively
  ** allocate space for a new winShmFile and filename.
  */
  p = sqlite3_malloc( sizeof(*p) );
  if( p==0 ) return SQLITE_NOMEM;
  memset(p, 0, sizeof(*p));
  nName = sqlite3Strlen30(zFullpath);
  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 15 );
  if( pNew==0 ){
    sqlite3_free(p);
    return SQLITE_NOMEM;
  }
  memset(pNew, 0, sizeof(*pNew));
  pNew->zFilename = (char*)&pNew[1];
  sqlite3_snprintf(nName+12, pNew->zFilename, "%s-wal-index", zFullpath);

  /* Look to see if there is an existing winShmFile that can be used.
  ** If no matching winShmFile currently exists, create a new one.
  */
  winShmEnterMutex();
  for(pFile = winShmFileList; pFile; pFile=pFile->pNext){
    /* TBD need to come up with better match here.  Perhaps
    ** use FILE_ID_BOTH_DIR_INFO Structure.
    */
    if( sqlite3StrICmp(pFile->zFilename, pNew->zFilename)==0 ) break;
  }
  if( pFile ){
    sqlite3_free(pNew);
  }else{
    pFile = pNew;
    pNew = 0;
    pFile->pMMapBuf = NULL;
................................................................................
      goto shm_open_err;
    }
    pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    if( pFile->mutexBuf==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }

    rc = winOpen(pVfs,
                 pFile->zFilename,                  /* Name of the file (UTF-8) */
                 (sqlite3_file *)&pFile->hFile, /* Write the SQLite file handle here */
                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Open mode flags */
                 0);
    if( SQLITE_OK!=rc ){
      rc = SQLITE_CANTOPEN_BKPT;
................................................................................

  /* Return directly if this is just a lock state query, or if
  ** the connection is already in the desired locking state.
  */
  if( desiredLock==p->lockState
   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
  ){
    OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s and got %s\n",
             pFile->hFile.h,
             p->id, (int)GetCurrentProcessId(), azLkName[desiredLock], azLkName[p->lockState]));
    if( pGotLock ) *pGotLock = p->lockState;
    return SQLITE_OK;
  }

  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d request %s->%s\n",
           pFile->hFile.h,
           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState], azLkName[desiredLock]));
  
  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
    assert( sqlite3_mutex_notheld(pFile->mutex) );
    sqlite3_mutex_enter(pFile->mutexBuf);
    p->hasMutexBuf = 1;
  }
  sqlite3_mutex_enter(pFile->mutex);
................................................................................
      if( rc==SQLITE_OK ){
        p->lockState = SQLITE_SHM_RECOVER;
      }
      break;
    }
  }
  sqlite3_mutex_leave(pFile->mutex);
  OSTRACE(("SHM-LOCK %d shmid-%d, pid-%d got %s\n",
           pFile->hFile.h, 
           p->id, (int)GetCurrentProcessId(), azLkName[p->lockState]));
  if( pGotLock ) *pGotLock = p->lockState;
  return rc;
}

#else
# define winShmOpen    0