From 62e603a904e8d4c48ba70df5ef1376dcfdb27e73 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 7 May 2014 15:09:24 +0000 Subject: [PATCH] Add test cases and documentation for the nolock and immutable query parameters. FossilOrigin-Name: 19d56cbaca222b32e2e354063149cccd89441d73 --- manifest | 15 ++--- manifest.uuid | 2 +- src/sqlite.h.in | 29 +++++++++- src/test_vfs.c | 73 +++++++++++++++++------- test/nolock.test | 143 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 232 insertions(+), 30 deletions(-) create mode 100644 test/nolock.test diff --git a/manifest b/manifest index 6ac75f7987..f945a392c4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Take\sout\sthe\sspecial\shandling\sof\snolock=true\sin\sos_win.c\sand\sadd\sit\sto\npager.c,\sso\sthat\sit\sworks\sfor\sall\sVFSes.\s\sAdd\sthe\spPager->noLock\sboolean\nfor\sclarity. -D 2014-05-01T01:49:22.279 +C Add\stest\scases\sand\sdocumentation\sfor\sthe\snolock\sand\simmutable\squery\nparameters. +D 2014-05-07T15:09:24.618 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -220,7 +220,7 @@ F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c ed459f7f478a1e533d19c4b953693b3ffa2efd15 F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be -F src/sqlite.h.in ad2bbeb6a41c228f6a9dbf24df62e4d3eff79ee5 +F src/sqlite.h.in 564fc23db33870b5096b20d72df7491ce0b8b74f F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqliteInt.h b2947801eccefd7ba3e5f14e1353289351a83cf3 @@ -270,7 +270,7 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb -F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9 +F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7 @@ -713,6 +713,7 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660 F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a +F test/nolock.test 77b278317fa765b1ada5f88d59219cdeb8364f8f F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 @@ -1166,7 +1167,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1829c38c3233c8cb194fae6d560d35a8916b1348 -R 9585bcff14fbe775451a3a647d896079 +P 725c1c14be331bce9bf074960dbfa7b6d4c1ba87 +R 89db3fd7a34cc009fbfa4be31d82927f U drh -Z 3dae204f6c4a7be4483961b87ae0c17a +Z 2af631f996ea658459fe7078e363eaf4 diff --git a/manifest.uuid b/manifest.uuid index d015fa2fa6..164fe70792 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -725c1c14be331bce9bf074960dbfa7b6d4c1ba87 \ No newline at end of file +19d56cbaca222b32e2e354063149cccd89441d73 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 81220a8822..9be07fc1e6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2778,6 +2778,30 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** ^If sqlite3_open_v2() is used and the "cache" parameter is present in ** a URI filename, its value overrides any behavior requested by setting ** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. +** +**
  • psow: ^The psow parameter may be "true" (or "on" or "yes" or +** "1") or "false" (or "off" or "no" or "0") to indicate that the +** [powersafe overwrite] property does or does not apply to the +** storage media on which the database file resides. ^The psow query +** parameter only works for the built-in unix and Windows VFSes. +** +**
  • nolock: ^The nolock parameter is a boolean query parameter +** which if set disables file locking in rollback journal modes. This +** is useful for accessing a database on a filesystem that does not +** support locking. Caution: Database corruption might result if two +** or more processes write to the same database and any one of those +** processes uses nolock=1. +** +**
  • immutable: ^The immutable parameter is a boolean query +** parameter that indicates that the database file is stored on +** read-only media. ^When immutable is set, SQLite assumes that the +** database file cannot be changed, even by a process with higher +** privilege, and so the database is opened read-only and all locking +** and change detection is disabled. Caution: Setting the immutable +** property on a database file that does in fact change can result +** in incorrect query results and/or [SQLITE_CORRUPT] errors. +** See also: [SQLITE_IOCAP_IMMUTABLE]. +** ** ** ** ^Specifying an unknown parameter in the query component of a URI is not an @@ -2807,8 +2831,9 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** Open file "data.db" in the current directory for read-only access. ** Regardless of whether or not shared-cache mode is enabled by ** default, use a private cache. -** file:/home/fred/data.db?vfs=unix-nolock -** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". +** file:/home/fred/data.db?vfs=unix-dotfile +** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile" +** that uses dot-files in place of posix advisory locking. ** file:data.db?mode=readonly ** An error. "readonly" is not a valid option for the "mode" parameter. ** diff --git a/src/test_vfs.c b/src/test_vfs.c index 613b0fce77..7ee2a93453 100644 --- a/src/test_vfs.c +++ b/src/test_vfs.c @@ -127,8 +127,10 @@ struct Testvfs { #define TESTVFS_FULLPATHNAME_MASK 0x00008000 #define TESTVFS_READ_MASK 0x00010000 #define TESTVFS_UNLOCK_MASK 0x00020000 +#define TESTVFS_LOCK_MASK 0x00040000 +#define TESTVFS_CKLOCK_MASK 0x00080000 -#define TESTVFS_ALL_MASK 0x0003FFFF +#define TESTVFS_ALL_MASK 0x000FFFFF #define TESTVFS_MAX_PAGES 1024 @@ -466,8 +468,15 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ ** Lock an tvfs-file. */ static int tvfsLock(sqlite3_file *pFile, int eLock){ - TestvfsFd *p = tvfsGetFd(pFile); - return sqlite3OsLock(p->pReal, eLock); + TestvfsFd *pFd = tvfsGetFd(pFile); + Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; + if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){ + char zLock[30]; + sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock); + tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1), + Tcl_NewStringObj(zLock, -1), 0, 0); + } + return sqlite3OsLock(pFd->pReal, eLock); } /* @@ -476,6 +485,12 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){ static int tvfsUnlock(sqlite3_file *pFile, int eLock){ TestvfsFd *pFd = tvfsGetFd(pFile); Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; + if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){ + char zLock[30]; + sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock); + tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1), + Tcl_NewStringObj(zLock, -1), 0, 0); + } if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){ return SQLITE_IOERR_UNLOCK; } @@ -486,8 +501,13 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){ ** Check if another file-handle holds a RESERVED lock on an tvfs-file. */ static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ - TestvfsFd *p = tvfsGetFd(pFile); - return sqlite3OsCheckReservedLock(p->pReal, pResOut); + TestvfsFd *pFd = tvfsGetFd(pFile); + Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; + if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){ + tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1), + 0, 0, 0); + } + return sqlite3OsCheckReservedLock(pFd->pReal, pResOut); } /* @@ -1111,26 +1131,32 @@ static int testvfs_obj_cmd( break; } + /* TESTVFS filter METHOD-LIST + ** + ** Activate special processing for those methods contained in the list + */ case CMD_FILTER: { static struct VfsMethod { char *zName; int mask; } vfsmethod [] = { - { "xShmOpen", TESTVFS_SHMOPEN_MASK }, - { "xShmLock", TESTVFS_SHMLOCK_MASK }, - { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, - { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, - { "xShmMap", TESTVFS_SHMMAP_MASK }, - { "xSync", TESTVFS_SYNC_MASK }, - { "xDelete", TESTVFS_DELETE_MASK }, - { "xWrite", TESTVFS_WRITE_MASK }, - { "xRead", TESTVFS_READ_MASK }, - { "xTruncate", TESTVFS_TRUNCATE_MASK }, - { "xOpen", TESTVFS_OPEN_MASK }, - { "xClose", TESTVFS_CLOSE_MASK }, - { "xAccess", TESTVFS_ACCESS_MASK }, - { "xFullPathname", TESTVFS_FULLPATHNAME_MASK }, - { "xUnlock", TESTVFS_UNLOCK_MASK }, + { "xShmOpen", TESTVFS_SHMOPEN_MASK }, + { "xShmLock", TESTVFS_SHMLOCK_MASK }, + { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, + { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, + { "xShmMap", TESTVFS_SHMMAP_MASK }, + { "xSync", TESTVFS_SYNC_MASK }, + { "xDelete", TESTVFS_DELETE_MASK }, + { "xWrite", TESTVFS_WRITE_MASK }, + { "xRead", TESTVFS_READ_MASK }, + { "xTruncate", TESTVFS_TRUNCATE_MASK }, + { "xOpen", TESTVFS_OPEN_MASK }, + { "xClose", TESTVFS_CLOSE_MASK }, + { "xAccess", TESTVFS_ACCESS_MASK }, + { "xFullPathname", TESTVFS_FULLPATHNAME_MASK }, + { "xUnlock", TESTVFS_UNLOCK_MASK }, + { "xLock", TESTVFS_LOCK_MASK }, + { "xCheckReservedLock", TESTVFS_CKLOCK_MASK }, }; Tcl_Obj **apElem = 0; int nElem = 0; @@ -1162,6 +1188,12 @@ static int testvfs_obj_cmd( break; } + /* + ** TESTVFS script ?SCRIPT? + ** + ** Query or set the script to be run when filtered VFS events + ** occur. + */ case CMD_SCRIPT: { if( objc==3 ){ int nByte; @@ -1248,6 +1280,7 @@ static int testvfs_obj_cmd( { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN }, { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE }, + { "immutable", SQLITE_IOCAP_IMMUTABLE }, { 0, 0 } }; Tcl_Obj *pRet; diff --git a/test/nolock.test b/test/nolock.test new file mode 100644 index 0000000000..98ed762cac --- /dev/null +++ b/test/nolock.test @@ -0,0 +1,143 @@ +# 2014-05-07 +# +# 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 file is testing the nolock=1 and immutable=1 query +# parameters and the SQLITE_IOCAP_IMMUTABLE device characteristic. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +unset -nocomplain tvfs_calls +proc tvfs_reset {} { + global tvfs_calls + array set tvfs_calls {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0} +} +proc tvfs_callback {op args} { + global tvfs_calls + incr tvfs_calls($op) + return SQLITE_OK +} +tvfs_reset + +testvfs tvfs +tvfs script tvfs_callback +tvfs filter {xLock xUnlock xCheckReservedLock xAccess} + +############################################################################ +# Verify that the nolock=1 query parameter for URI filenames disables all +# calls to xLock and xUnlock for rollback databases. +# +do_test nolock-1.0 { + db close + forcedelete test.db + tvfs_reset + sqlite db test.db -vfs tvfs + db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);} + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) +} {xLock 7 xUnlock 5 xCheckReservedLock 0} + +do_test nolock-1.1 { + db close + forcedelete test.db + tvfs_reset + sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1 + db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);} + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) +} {xLock 7 xUnlock 5 xCheckReservedLock 0} + +do_test nolock-1.2 { + db close + forcedelete test.db + tvfs_reset + sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1 + db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);} + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) +} {xLock 0 xUnlock 0 xCheckReservedLock 0} + +############################################################################# +# Verify that immutable=1 disables both locking and xAccess calls to the +# journal files. +# +do_test nolock-2.0 { + db close + forcedelete test.db + # begin by creating a test database + sqlite3 db test.db + db eval { + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES('hello','world'); + CREATE TABLE t2(x,y); + INSERT INTO t2 VALUES(12345,67890); + SELECT * FROM t1, t2; + } +} {hello world 12345 67890} +do_test nolock-2.1 { + tvfs_reset + sqlite3 db2 test.db -vfs tvfs + db2 eval {SELECT * FROM t1, t2} +} {hello world 12345 67890} +do_test nolock-2.2 { + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \ + xAccess $::tvfs_calls(xAccess) +} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4} + + +do_test nolock-2.11 { + db2 close + tvfs_reset + sqlite3 db2 file:test.db?immutable=0 -vfs tvfs -uri 1 + db2 eval {SELECT * FROM t1, t2} +} {hello world 12345 67890} +do_test nolock-2.12 { + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \ + xAccess $::tvfs_calls(xAccess) +} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4} + + +do_test nolock-2.21 { + db2 close + tvfs_reset + sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1 + db2 eval {SELECT * FROM t1, t2} +} {hello world 12345 67890} +do_test nolock-2.22 { + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \ + xAccess $::tvfs_calls(xAccess) +} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0} + +############################################################################ +# Verify that the SQLITE_IOCAP_IMMUTABLE flag works +# +do_test nolock-3.1 { + db2 close + tvfs devchar immutable + tvfs_reset + sqlite3 db2 test.db -vfs tvfs + db2 eval {SELECT * FROM t1, t2} +} {hello world 12345 67890} +do_test nolock-3.2 { + list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \ + xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \ + xAccess $::tvfs_calls(xAccess) +} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0} + +db2 close +db close +tvfs delete +finish_test -- 2.47.2