diff --git a/manifest b/manifest index bf84f0f2ec..e631fa3a74 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\swindows\sbackend\sto\sretry\sread\sand\swrite\srequests\sif\sthe\sencounter\nERROR_LOCK_VIOLATION\sand\sERROR_SHARING_VIOLATION\serrors\s-\swhich\swe\sthink\nsometimes\shappens\sdue\sto\sagressive\santi-virus\ssoftware. -D 2011-07-11T18:17:56.144 +C Update\sthe\sTCL\scommands\sfor\ssetting\swindows\smanditory\slocks.\nAdd\stest\scases\sfor\smanditory\slock\sdelays\sunder\swindows. +D 2011-07-11T23:45:44.051 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -188,7 +188,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c c355b33803fb756dc09297ec84d19604301fa622 -F src/test1.c 8eef932f1024f1076a8adb8a6f5d9c5267c9e969 +F src/test1.c 6623e003ce840ed4a303918dbbc124f9e222974c F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31 F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432 F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7 @@ -911,6 +911,7 @@ F test/where9.test 24f19ad14bb1b831564ced5273e681e495662848 F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 +F test/win32lock.test 7fa3287dccc836fcaa8e0d1e77aa017de5889231 F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 F tool/build-shell.sh 12aa4391073a777fcb6dcc490b219a018ae98bac F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b @@ -951,7 +952,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262 -P 90b1aea17400bbda5ebc8ae4eb4e12127519e42e -R 349c7f009f94630db798c4428c847d95 +P c20aca06610407c197ea50ea77c2591aacf2252a +R 4c1b031b9c10734fc2cbb78ed1f104dd U drh -Z 6ec74c1e47a6a671533b542ae146a0f8 +Z 4f5517f8772eb0c19d9bc59edbaff4cc diff --git a/manifest.uuid b/manifest.uuid index 2020e584ff..688cc99f9e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c20aca06610407c197ea50ea77c2591aacf2252a \ No newline at end of file +03af4c175c6ba303ec0a5be25fd42771e38f7347 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index 7fdf54b128..91bb1b4998 100644 --- a/src/test1.c +++ b/src/test1.c @@ -5574,6 +5574,93 @@ static int test_test_control( return TCL_OK; } +#if SQLITE_OS_WIN +/* +** Information passed from the main thread into the windows file locker +** background thread. +*/ +struct win32FileLocker { + HANDLE h; /* Handle of the file to be locked */ + int delay1; /* Delay before locking */ + int delay2; /* Delay before unlocking */ + int ok; /* Finished ok */ + int err; /* True if an error occurs */ +}; +#endif + + +#if SQLITE_OS_WIN +/* +** The background thread that does file locking. +*/ +static void win32_file_locker(void *pAppData){ + struct win32FileLocker *p = (struct win32FileLocker*)pAppData; + if( p->delay1 ) Sleep(p->delay1); + if( LockFile(p->h, 0, 0, 100000000, 0) ){ + Sleep(p->delay2); + UnlockFile(p->h, 0, 0, 100000000, 0); + p->ok = 1; + }else{ + p->err = 1; + } + CloseHandle(p->h); + p->h = 0; + p->delay1 = 0; + p->delay2 = 0; +} +#endif + +#if SQLITE_OS_WIN +/* +** lock_win32_file FILENAME DELAY1 DELAY2 +** +** Get an exclusive manditory lock on file for DELAY2 milliseconds. +** Wait DELAY1 milliseconds before acquiring the lock. +*/ +static int win32_file_lock( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + static struct win32FileLocker x = { 0, 0, 0 }; + const char *zFilename; + int retry = 0; + + if( objc!=4 && objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2"); + return TCL_ERROR; + } + if( objc==1 ){ + char zBuf[200]; + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d", + x.ok, x.err, x.delay1, x.delay2, x.h); + Tcl_AppendResult(interp, zBuf, (char*)0); + return TCL_OK; + } + while( x.h && retry<10 ){ + retry++; + Sleep(100); + } + if( x.h ){ + Tcl_AppendResult(interp, "busy", (char*)0); + return TCL_ERROR; + } + if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR; + zFilename = Tcl_GetString(objv[1]); + x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + if( !x.h ){ + Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0); + return TCL_ERROR; + } + _beginthread(win32_file_locker, 0, (void*)&x); + Sleep(0); + return TCL_OK; +} +#endif /* ** optimization_control DB OPT BOOLEAN @@ -5754,6 +5841,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "restore_prng_state", restore_prng_state, 0 }, { "reset_prng_state", reset_prng_state, 0 }, { "optimization_control", optimization_control,0}, +#if SQLITE_OS_WIN + { "lock_win32_file", win32_file_lock, 0 }, +#endif { "tcl_objproc", runAsObjProc, 0 }, /* sqlite3_column_*() API */ diff --git a/test/win32lock.test b/test/win32lock.test new file mode 100644 index 0000000000..a45712d173 --- /dev/null +++ b/test/win32lock.test @@ -0,0 +1,57 @@ +# 2011 July 11 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this script is recovery from transient manditory locks +# that sometimes appear on database files due to anti-virus software. +# + +if {$tcl_platform(platform)!="windows"} return + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +set testprefix win32lock + +do_test win32lock-1.1 { + db eval { + PRAGMA cache_size=10; + CREATE TABLE t1(x,y); + INSERT INTO t1 VALUES(1,randomblob(100000)); + INSERT INTO t1 VALUES(2,randomblob(50000)); + INSERT INTO t1 VALUES(3,randomblob(25000)); + INSERT INTO t1 VALUES(4,randomblob(12500)); + SELECT x, length(y) FROM t1 ORDER BY rowid; + } +} {1 100000 2 50000 3 25000 4 12500} + +unset -nocomplain delay1 rc msg +set delay1 50 +set rc 0 +set old_pending_byte [sqlite3_test_control_pending_byte 0x40000000] +while {1} { + sqlite3_sleep 10 + lock_win32_file test.db 0 $::delay1 + set rc [catch {db eval {SELECT x, length(y) FROM t1 ORDER BY rowid}} msg] + if {$rc} { + do_test win32lock-1.2-$delay1-fin { + set ::msg + } {disk I/O error} + break + } else { + do_test win32lock-1.2-$delay1 { + set ::msg + } {1 100000 2 50000 3 25000 4 12500} + incr delay1 50 + } +} +sqlite3_test_control_pending_byte $old_pending_byte + +finish_test