/ Changes On Branch winLockHandle
Login

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

Changes In Branch winLockHandle Excluding Merge-Ins

This is equivalent to a diff from c405f971cf to f2906c4451

2014-05-30
21:01
Revise locking retry semantics in Win32 VFS to abort early if the file handle is reported as invalid. (check-in: a4df4a5b34 user: mistachkin tags: trunk)
16:54
Add extra checking of the database extended error code. (Closed-Leaf check-in: f2906c4451 user: mistachkin tags: winLockHandle)
16:42
Add tests for the invalid file handle detection logic in the winLock() function. (check-in: ed5a9eb4f3 user: mistachkin tags: winLockHandle)
2014-05-28
10:00
Add an extra test to verify that the FTS notindexed option is working. (check-in: c461c0fe05 user: dan tags: trunk)
09:56
Moved to "mistake" because this commit contains a typo causing a test to fail. Was: Add an extra test to further verify that the FTS notindexed option is working properly. (Leaf check-in: 7d445e593a user: dan tags: mistake)
03:27
Revise locking retry semantics in Win32 VFS to abort early if the file handle is reported as invalid. (check-in: d43e2e59b5 user: mistachkin tags: winLockHandle)
03:23
Revise how OSTRACE reports logically boolean results in the Win32 VFS. (check-in: c405f971cf user: mistachkin tags: trunk)
2014-05-27
20:19
Remove an incorrect assert() in the sorter. (check-in: b8b66103de user: drh tags: trunk)

Changes to src/os_win.c.

2920
2921
2922
2923
2924
2925
2926

2927
2928







2929
2930
2931
2932
2933
2934
2935
                                         PENDING_BYTE, 0, 1, 0))==0 ){
      /* Try 3 times to get the pending lock.  This is needed to work
      ** around problems caused by indexing and/or anti-virus software on
      ** Windows systems.
      ** If you are using this code as a model for alternative VFSes, do not
      ** copy this retry logic.  It is a hack intended for Windows only.
      */

      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
               pFile->h, cnt, res));







      if( cnt ) sqlite3_win32_sleep(1);
    }
    gotPendingLock = res;
    if( !res ){
      lastErrno = osGetLastError();
    }
  }







>


>
>
>
>
>
>
>







2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
                                         PENDING_BYTE, 0, 1, 0))==0 ){
      /* Try 3 times to get the pending lock.  This is needed to work
      ** around problems caused by indexing and/or anti-virus software on
      ** Windows systems.
      ** If you are using this code as a model for alternative VFSes, do not
      ** copy this retry logic.  It is a hack intended for Windows only.
      */
      lastErrno = osGetLastError();
      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
               pFile->h, cnt, res));
      if( lastErrno==ERROR_INVALID_HANDLE ){
        pFile->lastErrno = lastErrno;
        rc = SQLITE_IOERR_LOCK;
        OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
                 pFile->h, cnt, sqlite3ErrName(rc)));
        return rc;
      }
      if( cnt ) sqlite3_win32_sleep(1);
    }
    gotPendingLock = res;
    if( !res ){
      lastErrno = osGetLastError();
    }
  }
3165
3166
3167
3168
3169
3170
3171











3172
3173
3174
3175
3176
3177
3178
        winIoerrRetryDelay = a[1];
      }else{
        a[1] = winIoerrRetryDelay;
      }
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
    }











    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = 0;
      int rc = winGetTempname(pFile->pVfs, &zTFile);
      if( rc==SQLITE_OK ){
        *(char**)pArg = zTFile;
      }
      OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));







>
>
>
>
>
>
>
>
>
>
>







3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
        winIoerrRetryDelay = a[1];
      }else{
        a[1] = winIoerrRetryDelay;
      }
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
    }
#ifdef SQLITE_TEST
    case SQLITE_FCNTL_WIN32_SET_HANDLE: {
      LPHANDLE phFile = (LPHANDLE)pArg;
      HANDLE hOldFile = pFile->h;
      pFile->h = *phFile;
      *phFile = hOldFile;
      OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
               hOldFile, pFile->h));
      return SQLITE_OK;
    }
#endif
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = 0;
      int rc = winGetTempname(pFile->pVfs, &zTFile);
      if( rc==SQLITE_OK ){
        *(char**)pArg = zTFile;
      }
      OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));

Changes to src/sqlite.h.in.

938
939
940
941
942
943
944






945
946
947
948
949
950
951
**
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
** pointer to an integer and it writes a boolean into that integer depending
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**






** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_GET_LOCKPROXYFILE             2
#define SQLITE_SET_LOCKPROXYFILE             3
#define SQLITE_LAST_ERRNO                    4
#define SQLITE_FCNTL_SIZE_HINT               5







>
>
>
>
>
>







938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
**
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
** pointer to an integer and it writes a boolean into that integer depending
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging.  This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument.  This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_GET_LOCKPROXYFILE             2
#define SQLITE_SET_LOCKPROXYFILE             3
#define SQLITE_LAST_ERRNO                    4
#define SQLITE_FCNTL_SIZE_HINT               5
961
962
963
964
965
966
967

968
969
970
971
972
973
974
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16
#define SQLITE_FCNTL_MMAP_SIZE              18
#define SQLITE_FCNTL_TRACE                  19
#define SQLITE_FCNTL_HAS_MOVED              20
#define SQLITE_FCNTL_SYNC                   21
#define SQLITE_FCNTL_COMMIT_PHASETWO        22


/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only







>







967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16
#define SQLITE_FCNTL_MMAP_SIZE              18
#define SQLITE_FCNTL_TRACE                  19
#define SQLITE_FCNTL_HAS_MOVED              20
#define SQLITE_FCNTL_SYNC                   21
#define SQLITE_FCNTL_COMMIT_PHASETWO        22
#define SQLITE_FCNTL_WIN32_SET_HANDLE       23

/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite3_mutex].  It only

Changes to src/test1.c.

112
113
114
115
116
117
118










119
120
121
122
123
124
125
    p = (struct SqliteDb*)cmdInfo.objClientData;
    *ppDb = p->db;
  }else{
    *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
  }
  return TCL_OK;
}











extern const char *sqlite3ErrName(int);
#define t1ErrorName sqlite3ErrName

/*
** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
** fact that the sqlite3* is the first field in the Vdbe structure.







>
>
>
>
>
>
>
>
>
>







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    p = (struct SqliteDb*)cmdInfo.objClientData;
    *ppDb = p->db;
  }else{
    *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
  }
  return TCL_OK;
}

#if SQLITE_OS_WIN
/*
** Decode a Win32 HANDLE object.
*/
int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
  *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
  return TCL_OK;
}
#endif

extern const char *sqlite3ErrName(int);
#define t1ErrorName sqlite3ErrName

/*
** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
** fact that the sqlite3* is the first field in the Vdbe structure.
5206
5207
5208
5209
5210
5211
5212

5213
5214
5215
5216
5217
5218
5219
      return TCL_ERROR;
    }
  }
#endif
  return TCL_OK;  
}


/*
** tclcmd:   file_control_win32_av_retry DB  NRETRY  DELAY
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
*/
static int file_control_win32_av_retry(







>







5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
      return TCL_ERROR;
    }
  }
#endif
  return TCL_OK;  
}

#if SQLITE_OS_WIN
/*
** tclcmd:   file_control_win32_av_retry DB  NRETRY  DELAY
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
*/
static int file_control_win32_av_retry(
5239
5240
5241
5242
5243
5244
5245




































5246
5247
5248
5249
5250
5251
5252
  if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
  sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
  Tcl_AppendResult(interp, z, (char*)0);
  return TCL_OK;  
}





































/*
** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_PERSIST_WAL opcode.
*/
static int file_control_persist_wal(







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







5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
  if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
  sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
  Tcl_AppendResult(interp, z, (char*)0);
  return TCL_OK;  
}

/*
** tclcmd:   file_control_win32_set_handle DB HANDLE
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
*/
static int file_control_win32_set_handle(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3 *db;
  int rc;
  HANDLE hFile = NULL;
  char z[100];

  if( objc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
    return TCL_ERROR;
  }
  if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
    return TCL_ERROR;
  }
  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
                            (void*)&hFile);
  sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
  Tcl_AppendResult(interp, z, (char*)0);
  return TCL_OK;  
}
#endif

/*
** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_PERSIST_WAL opcode.
*/
static int file_control_persist_wal(
6468
6469
6470
6471
6472
6473
6474

6475


6476
6477
6478
6479
6480
6481
6482
     { "vfs_unregister_all",         vfs_unregister_all,  0   },
     { "vfs_reregister_all",         vfs_reregister_all,  0   },
     { "file_control_test",          file_control_test,   0   },
     { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
     { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
     { "file_control_chunksize_test", file_control_chunksize_test,  0   },
     { "file_control_sizehint_test",  file_control_sizehint_test,   0   },

     { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },


     { "file_control_persist_wal",    file_control_persist_wal,     0   },
     { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
     { "file_control_vfsname",        file_control_vfsname,         0   },
     { "file_control_tempfilename",   file_control_tempfilename,    0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },
     { "sqlite3_create_function_v2", test_create_function_v2, 0 },








>

>
>







6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
     { "vfs_unregister_all",         vfs_unregister_all,  0   },
     { "vfs_reregister_all",         vfs_reregister_all,  0   },
     { "file_control_test",          file_control_test,   0   },
     { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
     { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
     { "file_control_chunksize_test", file_control_chunksize_test,  0   },
     { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
#if SQLITE_OS_WIN
     { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
     { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
#endif
     { "file_control_persist_wal",    file_control_persist_wal,     0   },
     { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
     { "file_control_vfsname",        file_control_vfsname,         0   },
     { "file_control_tempfilename",   file_control_tempfilename,    0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },
     { "sqlite3_create_function_v2", test_create_function_v2, 0 },

Changes to test/win32lock.test.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

set testprefix win32lock

db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  lappend ::log $msg 
}
sqlite3 db test.db
db eval {PRAGMA mmap_size=0}

do_test win32lock-1.1 {
  db eval {
    PRAGMA cache_size=10;







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

set testprefix win32lock

db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  lappend ::log $msg
}
sqlite3 db test.db
db eval {PRAGMA mmap_size=0}

do_test win32lock-1.1 {
  db eval {
    PRAGMA cache_size=10;
123
124
125
126
127
128
129
130














































131
132
133
134
    break
  }
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
db close














































sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test








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

|


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    break
  }
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
db close
forcedelete test.db

sqlite3 db test.db
sqlite3 db2 test.db

do_test win32lock-3.0 {
  db eval {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
  }
} {}

do_test win32lock-3.1 {
  db eval {
    BEGIN EXCLUSIVE;
    INSERT INTO t1 VALUES(4);
  }
} {}

do_test win32lock-3.2 {
  catchsql {
    BEGIN EXCLUSIVE;
    INSERT INTO t1 VALUES(5);
    COMMIT;
  } db2
} {1 {database is locked}}

do_test win32lock-3.3 {
  db eval {
    COMMIT;
  }
} {}

do_test win32lock-3.4 {
  set handle [lindex [file_control_win32_set_handle db 0] end]
  list [catchsql {
    BEGIN EXCLUSIVE;
    INSERT INTO t1 VALUES(6);
    COMMIT;
  }] [file_control_win32_set_handle db $handle] [sqlite3_extended_errcode db]
} {{1 {disk I/O error}} {0 0} SQLITE_IOERR_LOCK}

db2 close
db close
sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize
finish_test