/ Check-in [95d0c58d]
Login

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

Overview
Comment:Fix a bug causing the POWERSAFE_OVERWRITE device-characteristic flag to be set incorrectly if file opening is deferred.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | deferred-open
Files: files | file ages | folders
SHA1: 95d0c58d2791d81b432e7d263f3fc2f26858d395
User & Date: dan 2014-02-10 21:09:39
Context
2014-02-11
05:26
Merge latest trunk changes. check-in: 1f2e1b0c user: dan tags: deferred-open
2014-02-10
21:09
Fix a bug causing the POWERSAFE_OVERWRITE device-characteristic flag to be set incorrectly if file opening is deferred. check-in: 95d0c58d user: dan tags: deferred-open
19:37
Experimental change to os_unix.c to delay creating a database file until it is first written. check-in: 538f7b25 user: dan tags: deferred-open
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/os_unix.c.

1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
....
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
....
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
....
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
....
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
....
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895

5896
5897










5898
5899
5900
5901
5902
5903
5904




5905
5906
5907
5908
5909
5910
5911



5912
5913
5914
5915
5916
5917
5918
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;

  assert( pFile );
  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){
    *pResOut = 0;
    return SQLITE_OK;
  }

  unixEnterMutex(); /* Because pFile->pInode is shared across threads */

  /* Check if a thread in this process holds such a lock */
................................................................................
  */
  if( pFile->eFileLock>=eFileLock ){
    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
            azFileLock(eFileLock)));
    return SQLITE_OK;
  }

  if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){
    int eOrigLock = pFile->eFileLock;
    if( eFileLock==SHARED_LOCK ){
      int statrc;
      struct stat sBuf;
      memset(&sBuf, 0, sizeof(sBuf));
      statrc = osStat(pFile->zPath, &sBuf);
      if( statrc && errno==ENOENT ){
................................................................................
      getpid()));

  assert( eFileLock<=SHARED_LOCK );
  if( pFile->eFileLock<=eFileLock ){
    return SQLITE_OK;
  }
  unixEnterMutex();
  if( pFile->ctrlFlags==UNIXFILE_DEFERRED ) goto end_unlock;
  pInode = pFile->pInode;
  assert( pInode->nShared!=0 );
  if( pFile->eFileLock>SHARED_LOCK ){
    assert( pInode->eFileLock==pFile->eFileLock );

#ifdef SQLITE_DEBUG
    /* When reducing a lock such that other processes can start
................................................................................
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif

  if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){
    int rc;
    struct stat sBuf;
    memset(&sBuf, 0, sizeof(sBuf));
    rc = osStat(pFile->zPath, &sBuf);
    if( rc!=0 ){
      memset(pBuf, 0, amt);
      rc = (errno==ENOENT ? SQLITE_IOERR_SHORT_READ : SQLITE_IOERR_FSTAT);
................................................................................
** Determine the current size of a file in bytes
*/
static int unixFileSize(sqlite3_file *id, i64 *pSize){
  unixFile *pFile = (unixFile*)id;
  int rc;
  struct stat buf;
  assert( id );
  if( pFile->ctrlFlags==UNIXFILE_DEFERRED ){
    rc = osStat(pFile->zPath, &buf);
    if( rc && errno==ENOENT ){
      rc = 0;
      buf.st_size = 0;
    }
  }else{
    rc = osFstat(pFile->h, &buf);
................................................................................
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  const int mask1 = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE
                  | SQLITE_OPEN_CREATE;
  const int mask2 = SQLITE_OPEN_READONLY  | SQLITE_OPEN_DELETEONCLOSE
                  | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_AUTOPROXY;
  int rc = SQLITE_OK;          /* Return code */

  /* If all the flags in mask1 are set, and all the flags in mask2 are

  ** clear, then this will be a deferred open.  */
  if( zPath && (flags & (mask1 | mask2))==mask1 ){










    unixFile *p = (unixFile*)pFile;
    memset(p, 0, sizeof(unixFile));

    p->pMethod = (**(finder_type*)pVfs->pAppData)(0, 0);
    p->pVfs = pVfs;
    p->h = -1;
    p->ctrlFlags = UNIXFILE_DEFERRED;




    p->openFlags = flags;
    p->zPath = zPath;
    if( pOutFlags ) *pOutFlags = flags;
  }else{
    rc = unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
  }
  return rc;



}

/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
static int unixDelete(







|







 







|







 







|







 







|







 







|







 







<


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




>
>
>
>



|
<
|
<
>
>
>







1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
....
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
....
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
....
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
....
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
....
5886
5887
5888
5889
5890
5891
5892

5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909

5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921

5922

5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;

  assert( pFile );
  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    *pResOut = 0;
    return SQLITE_OK;
  }

  unixEnterMutex(); /* Because pFile->pInode is shared across threads */

  /* Check if a thread in this process holds such a lock */
................................................................................
  */
  if( pFile->eFileLock>=eFileLock ){
    OSTRACE(("LOCK    %d %s ok (already held) (unix)\n", pFile->h,
            azFileLock(eFileLock)));
    return SQLITE_OK;
  }

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    int eOrigLock = pFile->eFileLock;
    if( eFileLock==SHARED_LOCK ){
      int statrc;
      struct stat sBuf;
      memset(&sBuf, 0, sizeof(sBuf));
      statrc = osStat(pFile->zPath, &sBuf);
      if( statrc && errno==ENOENT ){
................................................................................
      getpid()));

  assert( eFileLock<=SHARED_LOCK );
  if( pFile->eFileLock<=eFileLock ){
    return SQLITE_OK;
  }
  unixEnterMutex();
  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ) goto end_unlock;
  pInode = pFile->pInode;
  assert( pInode->nShared!=0 );
  if( pFile->eFileLock>SHARED_LOCK ){
    assert( pInode->eFileLock==pFile->eFileLock );

#ifdef SQLITE_DEBUG
    /* When reducing a lock such that other processes can start
................................................................................
#if 0
  assert( pFile->pUnused==0
       || offset>=PENDING_BYTE+512
       || offset+amt<=PENDING_BYTE 
  );
#endif

  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    int rc;
    struct stat sBuf;
    memset(&sBuf, 0, sizeof(sBuf));
    rc = osStat(pFile->zPath, &sBuf);
    if( rc!=0 ){
      memset(pBuf, 0, amt);
      rc = (errno==ENOENT ? SQLITE_IOERR_SHORT_READ : SQLITE_IOERR_FSTAT);
................................................................................
** Determine the current size of a file in bytes
*/
static int unixFileSize(sqlite3_file *id, i64 *pSize){
  unixFile *pFile = (unixFile*)id;
  int rc;
  struct stat buf;
  assert( id );
  if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
    rc = osStat(pFile->zPath, &buf);
    if( rc && errno==ENOENT ){
      rc = 0;
      buf.st_size = 0;
    }
  }else{
    rc = osFstat(pFile->h, &buf);
................................................................................
  int flags,                   /* Input flags to control the opening */
  int *pOutFlags               /* Output flags returned to SQLite core */
){
  const int mask1 = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE
                  | SQLITE_OPEN_CREATE;
  const int mask2 = SQLITE_OPEN_READONLY  | SQLITE_OPEN_DELETEONCLOSE
                  | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_AUTOPROXY;


  /* If all the flags in mask1 are set, and all the flags in mask2 are
  ** clear, the file does not exist but the directory does and is
  ** writable, then this is a deferred open.  */
  if( 0 && zPath && (flags & (mask1 | mask2))==mask1 ){
    int posixrc;
    posixrc = osAccess(zPath, F_OK);
    if( posixrc && errno==ENOENT ){
      char zDirname[MAX_PATHNAME+1];
      int i;
      for(i=(int)strlen(zPath); i>1 && zPath[i]!='/'; i--);
      memcpy(zDirname, zPath, i);
      zDirname[i] = '\0';
      posixrc = osAccess(zDirname, W_OK);
      if( posixrc==0 ){
        unixFile *p = (unixFile*)pFile;
        memset(p, 0, sizeof(unixFile));

        p->pMethod = (**(finder_type*)pVfs->pAppData)(0, 0);
        p->pVfs = pVfs;
        p->h = -1;
        p->ctrlFlags = UNIXFILE_DEFERRED;
        if( sqlite3_uri_boolean(((flags & UNIXFILE_URI) ? zPath : 0),
                           "psow", SQLITE_POWERSAFE_OVERWRITE) ){
          p->ctrlFlags |= UNIXFILE_PSOW;
        }
        p->openFlags = flags;
        p->zPath = zPath;
        if( pOutFlags ) *pOutFlags = flags;
        return SQLITE_OK;

      }

    }
  }
  return unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
}

/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
static int unixDelete(