/ Check-in [a92c1851]
Login

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

Overview
Comment:The first 6 WAL tests now work. It's a start.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal
Files: files | file ages | folders
SHA1: a92c1851da10acf51e7f6f086b8a23bd731940b3
User & Date: drh 2010-04-30 02:13:27
Context
2010-04-30
06:02
Merge latest bugfix into wal branch. check-in: 265e66e6 user: dan tags: wal
02:13
The first 6 WAL tests now work. It's a start. check-in: a92c1851 user: drh tags: wal
2010-04-29
22:34
Refactor wal.c to use the VFS. This check-in compiles and links and works ok as long as you leave WAL turned off, but WAL does not work. check-in: 62db5fa3 user: drh tags: wal
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
....
4728
4729
4730
4731
4732
4733
4734

4735
4736
4737
4738
4739
4740
4741

4742
4743
4744
4745
4746
4747
4748
....
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
....
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
....
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
  struct flock f;       /* The posix advisory locking structure */
  int lockOp;           /* The opcode for fcntl() */
  int i;                /* Offset into the locking byte range */
  int rc;               /* Result code form fcntl() */
  u8 mask;              /* Mask of bits in lockMask */

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

  /* Initialize the locking parameters */
  memset(&f, 0, sizeof(f));
  f.l_type = lockType;
  f.l_whence = SEEK_SET;
  if( (lockMask & UNIX_SHM_MUTEX)!=0 && lockType!=F_UNLCK ){
    lockOp = F_SETLKW;
................................................................................
  f.l_start = i+UNIX_SHM_BASE;
  f.l_len = 1;

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

  }

  /* Verify that all bits set in lockMask are contiguous */
  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );

  /* Acquire the system-level lock */
  rc = (fcntl(pFile->h, lockOp, &f)==0) ? SQLITE_OK : SQLITE_BUSY;


  /* Update the global lock state and do debug tracing */
#ifdef SQLITE_DEBUG
  OSTRACE(("SHM-LOCK "));
  if( rc==SQLITE_OK ){
    if( lockType==F_UNLCK ){
      OSTRACE(("unlock ok"));
................................................................................
  int rc;      /* Result code */
  unixShm *pX; /* For looping over all sibling connections */
  u8 allMask;  /* Union of locks held by connections other than "p" */

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

  /* We never try to unlock locks that we do not hold */
  assert( ((p->exclMask|p->sharedMask) & unlockMask)==unlockMask );

  /* Compute locks held by sibling connections */
  for(pX=pFile->pFirst; pX; pX=pX->pNext){
    if( pX==p ) continue;
    assert( (pX->exclMask & unlockMask)==0 );
    allMask |= pX->sharedMask;
  }

................................................................................
  if( pFile==0 ){
    int nName = strlen(zName);
    pFile = sqlite3_malloc( sizeof(*pFile) + nName + 1 );
    if( pFile==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }
    memset(pFile, 0, sizeof(pFile));
    pFile->zFilename = (char*)&pFile[1];
    memcpy(pFile->zFilename, zName, nName+1);
    pFile->h = -1;
    pFile->pNext = unixShmFileList;
    unixShmFileList = pFile;

    pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
................................................................................
    }
    pFile->mutexRecov = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    if( pFile->mutexRecov==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }

    pFile->h = open(zName, O_CREAT, 0664);
    if( pFile->h<0 ){
      rc = SQLITE_CANTOPEN;
      goto shm_open_err;
    }

    rc = fstat(pFile->h, &sStat);
    if( rc ){







|







 







>






|
>







 







<
<
<







 







|







 







|







4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
....
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
....
4791
4792
4793
4794
4795
4796
4797



4798
4799
4800
4801
4802
4803
4804
....
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
....
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
  struct flock f;       /* The posix advisory locking structure */
  int lockOp;           /* The opcode for fcntl() */
  int i;                /* Offset into the locking byte range */
  int rc;               /* Result code form fcntl() */
  u8 mask;              /* Mask of bits in lockMask */

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

  /* Initialize the locking parameters */
  memset(&f, 0, sizeof(f));
  f.l_type = lockType;
  f.l_whence = SEEK_SET;
  if( (lockMask & UNIX_SHM_MUTEX)!=0 && lockType!=F_UNLCK ){
    lockOp = F_SETLKW;
................................................................................
  f.l_start = i+UNIX_SHM_BASE;
  f.l_len = 1;

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

  /* Verify that all bits set in lockMask are contiguous */
  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );

  /* Acquire the system-level lock */
  rc = fcntl(pFile->h, lockOp, &f);
  rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;

  /* Update the global lock state and do debug tracing */
#ifdef SQLITE_DEBUG
  OSTRACE(("SHM-LOCK "));
  if( rc==SQLITE_OK ){
    if( lockType==F_UNLCK ){
      OSTRACE(("unlock ok"));
................................................................................
  int rc;      /* Result code */
  unixShm *pX; /* For looping over all sibling connections */
  u8 allMask;  /* Union of locks held by connections other than "p" */

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




  /* Compute locks held by sibling connections */
  for(pX=pFile->pFirst; pX; pX=pX->pNext){
    if( pX==p ) continue;
    assert( (pX->exclMask & unlockMask)==0 );
    allMask |= pX->sharedMask;
  }

................................................................................
  if( pFile==0 ){
    int nName = strlen(zName);
    pFile = sqlite3_malloc( sizeof(*pFile) + nName + 1 );
    if( pFile==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }
    memset(pFile, 0, sizeof(*pFile));
    pFile->zFilename = (char*)&pFile[1];
    memcpy(pFile->zFilename, zName, nName+1);
    pFile->h = -1;
    pFile->pNext = unixShmFileList;
    unixShmFileList = pFile;

    pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
................................................................................
    }
    pFile->mutexRecov = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    if( pFile->mutexRecov==0 ){
      rc = SQLITE_NOMEM;
      goto shm_open_err;
    }

    pFile->h = open(zName, O_RDWR|O_CREAT, 0664);
    if( pFile->h<0 ){
      rc = SQLITE_CANTOPEN;
      goto shm_open_err;
    }

    rc = fstat(pFile->h, &sStat);
    if( rc ){

Changes to src/wal.c.

374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393

394
395
396
397
398
399












400
401
402
403
404
405
406
...
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
...
782
783
784
785
786
787
788





789
790
791
792
793
794


795
796
797
798
799
800
801
  if( pWal->pWiData ){
    pWal->pVfs->xShmRelease(pWal->pWIndex);
    pWal->pWiData = 0;
  }
}

/*
** Map the wal-index file into memory if it isn't already.
*/
static int walIndexMap(Wal *pWal){
  int rc = SQLITE_OK;
  if( pWal->pWiData==0 ){
    rc = pWal->pVfs->xShmSize(pWal->pWIndex, -1,
                              &pWal->szWIndex, (void**)(char*)&pWal->pWiData);
  }
  return rc;
}

/*
** Resize the wal-index file.

*/
static int walIndexRemap(Wal *pWal, int newSize){
  int rc;
  walIndexUnmap(pWal);
  rc = pWal->pVfs->xShmSize(pWal->pWIndex, newSize,
                            &pWal->szWIndex, (void**)(char*)&pWal->pWiData);












  return rc;
}

/*
** Increment by which to increase the wal-index file size.
*/
#define WALINDEX_MMAP_INCREMENT (64*1024)
................................................................................
  *ppWal = 0;
  nWal = strlen(zDb);
  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal+11);
  if( !pRet ) goto wal_open_out;
  pRet->pVfs = pVfs;
  pRet->pFd = (sqlite3_file *)&pRet[1];
  zWal = pVfs->szOsFile + (char*)pRet->pFd;
  sqlite3_snprintf(nWal, zWal, "%s-wal-index", zDb);
  rc = pVfs->xShmOpen(pVfs, zWal, &pRet->pWIndex);
  if( rc ) goto wal_open_out;

  /* Open file handle on the write-ahead log file. */
  zWal[nWal-6] = 0;
  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
  rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);

wal_open_out:
  if( rc!=SQLITE_OK ){
    if( pRet ){
      pVfs->xShmClose(pRet->pWIndex);
................................................................................
** Otherwise leave *pChanged unmodified.
**
** If the checksum cannot be verified return SQLITE_ERROR.
*/
int walIndexTryHdr(Wal *pWal, int *pChanged){
  u32 aCksum[2] = {1, 1};
  u32 aHdr[WALINDEX_HDR_NFIELD+2];






  /* Read the header. The caller may or may not have locked the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return SQLITE_ERROR. The caller will
  ** retry. Or, if the caller has already locked the file and the header
  ** still looks inconsistent, it will run recovery.


  */
  memcpy(aHdr, pWal->pWiData, sizeof(aHdr));
  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
  ){
    return SQLITE_ERROR;







<
<
<
<
<
<
<
<
<
<
<
<
|
>






>
>
>
>
>
>
>
>
>
>
>
>







 







|




|







 







>
>
>
>
>






>
>







374
375
376
377
378
379
380












381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
...
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
...
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
  if( pWal->pWiData ){
    pWal->pVfs->xShmRelease(pWal->pWIndex);
    pWal->pWiData = 0;
  }
}

/*












** Resize the wal-index file.  If newSize is negative, leave the size
** unchanged.
*/
static int walIndexRemap(Wal *pWal, int newSize){
  int rc;
  walIndexUnmap(pWal);
  rc = pWal->pVfs->xShmSize(pWal->pWIndex, newSize,
                            &pWal->szWIndex, (void**)(char*)&pWal->pWiData);
  if( rc==SQLITE_OK && pWal->pWiData==0 ){
    assert( pWal->szWIndex==0 );
    pWal->pWiData = &pWal->iCallback;
  }
  return rc;
}

/*
** Map the wal-index file into memory if it isn't already.
*/
static int walIndexMap(Wal *pWal){
  int rc = walIndexRemap(pWal, -1);
  return rc;
}

/*
** Increment by which to increase the wal-index file size.
*/
#define WALINDEX_MMAP_INCREMENT (64*1024)
................................................................................
  *ppWal = 0;
  nWal = strlen(zDb);
  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal+11);
  if( !pRet ) goto wal_open_out;
  pRet->pVfs = pVfs;
  pRet->pFd = (sqlite3_file *)&pRet[1];
  zWal = pVfs->szOsFile + (char*)pRet->pFd;
  sqlite3_snprintf(nWal+11, zWal, "%s-wal-index", zDb);
  rc = pVfs->xShmOpen(pVfs, zWal, &pRet->pWIndex);
  if( rc ) goto wal_open_out;

  /* Open file handle on the write-ahead log file. */
  zWal[nWal+4] = 0;
  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
  rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);

wal_open_out:
  if( rc!=SQLITE_OK ){
    if( pRet ){
      pVfs->xShmClose(pRet->pWIndex);
................................................................................
** Otherwise leave *pChanged unmodified.
**
** If the checksum cannot be verified return SQLITE_ERROR.
*/
int walIndexTryHdr(Wal *pWal, int *pChanged){
  u32 aCksum[2] = {1, 1};
  u32 aHdr[WALINDEX_HDR_NFIELD+2];

  if( pWal->szWIndex==0 ){
    int rc = walIndexRemap(pWal, WALINDEX_MMAP_INCREMENT);
    if( rc ) return rc;
  }

  /* Read the header. The caller may or may not have locked the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return SQLITE_ERROR. The caller will
  ** retry. Or, if the caller has already locked the file and the header
  ** still looks inconsistent, it will run recovery.
  **
  ** FIX-ME:  It is no longer possible to have not locked the wal-index.
  */
  memcpy(aHdr, pWal->pWiData, sizeof(aHdr));
  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
  ){
    return SQLITE_ERROR;