/ Check-in [abef0535]
Login

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

Overview
Comment:Get read-only SHM file tests passing on Win32.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | readonly-wal-recovery
Files: files | file ages | folders
SHA3-256: abef05353554e72f4d08aff562b87ff8530e8537a79e58d831205ea8c46eed07
User & Date: mistachkin 2017-11-09 20:02:44
Context
2017-11-09
20:34
Enhance walro2.test to better ensure that readonly_shm clients are not using invalid *-shm files. check-in: ff630b66 user: dan tags: readonly-wal-recovery
20:02
Get read-only SHM file tests passing on Win32. check-in: abef0535 user: mistachkin tags: readonly-wal-recovery
18:53
Further corrections to read-only SHM file handling on Win32. check-in: 43c31170 user: mistachkin tags: readonly-wal-recovery
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_win.c.

2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113










2114
2115
2116
2117
2118
2119
2120
....
3870
3871
3872
3873
3874
3875
3876
3877
3878


3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
....
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
#endif
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;

/*
** The "winIsLockingError" macro is used to determine if a particular I/O
** error code is due to file locking.  It must accept the error code DWORD
** as its only argument and should return non-zero if the error code is due
** to file locking.
*/
#if !defined(winIsLockingError)
#define winIsLockingError(a) (((a)==NO_ERROR)                   || \
                              ((a)==ERROR_LOCK_VIOLATION)       || \
                              ((a)==ERROR_HANDLE_EOF)           || \
                              ((a)==ERROR_IO_PENDING))
#endif











/*
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
** error code obtained via GetLastError() is eligible to be retried.  It
** must accept the error code DWORD as its only argument and should return
** non-zero if the error code is transient in nature and the operation
** responsible for generating the original error might succeed upon being
** retried.  The argument to this macro should be a variable.
................................................................................
  pOverlapped = &overlapped;
#endif
  if( bReadOnly ||
      !osWriteFile(pFile->h, &notUsed1, 1, &notUsed2, pOverlapped) ){
    DWORD lastErrno = bReadOnly ? NO_ERROR : osGetLastError();
    if( !osReadFile(pFile->h, &notUsed1, 1, &notUsed2, pOverlapped) ){
      lastErrno = osGetLastError();
      if( winIsLockingError(lastErrno) ){
        if( pLockType ) *pLockType = WINSHM_WRLCK;


      }else{
        return SQLITE_IOERR_READ;
      }
    }else{
      if( winIsLockingError(lastErrno) ){
        if( pLockType ) *pLockType = WINSHM_RDLCK;
      }else{
        return SQLITE_IOERR_WRITE;
      }
    }
  }else{
    if( pLockType ) *pLockType = WINSHM_UNLCK;
................................................................................
    if( rc2!=SQLITE_OK ){
      rc2 = winOpen(pDbFd->pVfs,
                    pShmNode->zFilename,
                    (sqlite3_file*)&pShmNode->hFile,
                    SQLITE_OPEN_WAL|SQLITE_OPEN_READONLY,
                    0);
      if( rc2!=SQLITE_OK ){
        rc = winLogError(SQLITE_CANTOPEN_BKPT, osGetLastError(),
                         "winOpenShm", pShmNode->zFilename);
        goto shm_open_err;
      }
      pShmNode->isReadonly = 1;
    }

    rc = winLockSharedMemory(pShmNode);
    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;







|
|
|
<

|
|

<



>
>
>
>
>
>
>
>
>
>







 







|

>
>




|







 







|
|







2095
2096
2097
2098
2099
2100
2101
2102
2103
2104

2105
2106
2107
2108

2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
....
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
....
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
#endif
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;

/*
** The "winIsLockConflict" macro is used to determine if a particular I/O
** error code is due to a file locking conflict.  It must accept the error
** code DWORD as its only argument.

*/
#if !defined(winIsLockConflict)
#define winIsLockConflict(a) (((a)==NO_ERROR)                   || \
                              ((a)==ERROR_LOCK_VIOLATION)       || \

                              ((a)==ERROR_IO_PENDING))
#endif

/*
** The "winIsLockMissing" macro is used to determine if a particular I/O
** error code is due to being unable to obtain a file lock because all or
** part of the range requested within the file is missing.  It must accept
** the error code DWORD as its only argument.
*/
#if !defined(winIsLockMissing)
#define winIsLockMissing(a) (((a)==ERROR_HANDLE_EOF))
#endif

/*
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
** error code obtained via GetLastError() is eligible to be retried.  It
** must accept the error code DWORD as its only argument and should return
** non-zero if the error code is transient in nature and the operation
** responsible for generating the original error might succeed upon being
** retried.  The argument to this macro should be a variable.
................................................................................
  pOverlapped = &overlapped;
#endif
  if( bReadOnly ||
      !osWriteFile(pFile->h, &notUsed1, 1, &notUsed2, pOverlapped) ){
    DWORD lastErrno = bReadOnly ? NO_ERROR : osGetLastError();
    if( !osReadFile(pFile->h, &notUsed1, 1, &notUsed2, pOverlapped) ){
      lastErrno = osGetLastError();
      if( winIsLockConflict(lastErrno) ){
        if( pLockType ) *pLockType = WINSHM_WRLCK;
      }else if( winIsLockMissing(lastErrno) ){
        if( pLockType ) *pLockType = WINSHM_UNLCK;
      }else{
        return SQLITE_IOERR_READ;
      }
    }else{
      if( winIsLockConflict(lastErrno) ){
        if( pLockType ) *pLockType = WINSHM_RDLCK;
      }else{
        return SQLITE_IOERR_WRITE;
      }
    }
  }else{
    if( pLockType ) *pLockType = WINSHM_UNLCK;
................................................................................
    if( rc2!=SQLITE_OK ){
      rc2 = winOpen(pDbFd->pVfs,
                    pShmNode->zFilename,
                    (sqlite3_file*)&pShmNode->hFile,
                    SQLITE_OPEN_WAL|SQLITE_OPEN_READONLY,
                    0);
      if( rc2!=SQLITE_OK ){
        rc = winLogError(rc2, osGetLastError(), "winOpenShm",
                         pShmNode->zFilename);
        goto shm_open_err;
      }
      pShmNode->isReadonly = 1;
    }

    rc = winLockSharedMemory(pShmNode);
    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;

Changes to test/walro2.test.

251
252
253
254
255
256
257


258
259
260
261
262
263
264
        SELECT count(*) FROM t2;
    } 
  } {500}
  do_test 4.2.2 {
    file size test.db-wal
  } {461152}
  do_test 4.2.4 {


    forcecopy test.db test.db2
    forcecopy test.db-wal test.db2-wal
    forcecopy test.db-shm test.db2-shm

    code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
    sql2 {
      SELECT * FROM t1;







>
>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
        SELECT count(*) FROM t2;
    } 
  } {500}
  do_test 4.2.2 {
    file size test.db-wal
  } {461152}
  do_test 4.2.4 {
    file_control_persist_wal db 1; db close

    forcecopy test.db test.db2
    forcecopy test.db-wal test.db2-wal
    forcecopy test.db-shm test.db2-shm

    code2 { sqlite3 db2 file:test.db2?readonly_shm=1 }
    sql2 {
      SELECT * FROM t1;

Changes to test/walrofault.test.

38
39
40
41
42
43
44

45
46
47
48
49
50
51
  INSERT INTO t1 VALUES('world');
  INSERT INTO t1 VALUES('hello');
  PRAGMA cache_size = 10;
  BEGIN;
    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<30 ) 
    INSERT INTO t1(b) SELECT randomblob(800) FROM s;
} {wal}

faultsim_save_and_close

do_faultsim_test 1 -faults oom* -prep {
  catch { db close }
  faultsim_restore
  sqlite3 db file:test.db?readonly_shm=1
} -body {







>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  INSERT INTO t1 VALUES('world');
  INSERT INTO t1 VALUES('hello');
  PRAGMA cache_size = 10;
  BEGIN;
    WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<30 ) 
    INSERT INTO t1(b) SELECT randomblob(800) FROM s;
} {wal}
file_control_persist_wal db 1; db close
faultsim_save_and_close

do_faultsim_test 1 -faults oom* -prep {
  catch { db close }
  faultsim_restore
  sqlite3 db file:test.db?readonly_shm=1
} -body {