]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Modify the windows locking code so that it works correctly for a database
authordrh <drh@noemail.net>
Thu, 29 May 2003 17:43:08 +0000 (17:43 +0000)
committerdrh <drh@noemail.net>
Thu, 29 May 2003 17:43:08 +0000 (17:43 +0000)
being shared between Win95/98/ME and WinNT/2K/XP systems.  Ticket #310. (CVS 988)

FossilOrigin-Name: 8c402db7e0745622d9950e5ca5d4d8e933da436c

manifest
manifest.uuid
src/os.c
src/sqliteInt.h
www/faq.tcl

index fea2bf8e0e7e7cc17fc19a7193587f4ed79a7c05..59494574f565e1b392a06885e89e5dc25d08f777 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Added\stypeof()\soperator.\nMinor\sadditions\sfor\sATTACH/DETACH.\s(CVS\s987)
-D 2003-05-29T04:21:39
+C Modify\sthe\swindows\slocking\scode\sso\sthat\sit\sworks\scorrectly\sfor\sa\sdatabase\r\nbeing\sshared\sbetween\sWin95/98/ME\sand\sWinNT/2K/XP\ssystems.\s\sTicket\s#310.\s(CVS\s988)
+D 2003-05-29T17:43:08
 F Makefile.in 1ff85c27d4350c74118341024e8a4fb2a04a3a43
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -35,7 +35,7 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c 2f26b95cc1055062411cbdea06e2e1b40a8b0d8d
 F src/main.c 717aaf32d468667dabeaec80054e11bfdb6309b6
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
-F src/os.c 94b618c0c0a76210e53857d77c96d2f042dc33b1
+F src/os.c 080238f03015057879cdf53bc4af9e497f2ba724
 F src/os.h 9e5bbddff123187295e3d00d49af06192cd1cd49
 F src/pager.c 51fdfda63e2d8c01fff8f7fe0c49f2636d5b1321
 F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
@@ -47,7 +47,7 @@ F src/select.c 15d921308065c9320363af6f43c01d9f09ea7118
 F src/shell.c b63089a91d6584df06eaa2e53ea1150c68ab1e61
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in eec06462cba262c0ee03f38462a18a4bc66dda4e
-F src/sqliteInt.h 3ba355793a1e0b891cfa414901759189c9287a18
+F src/sqliteInt.h e5ae70c84c07100561eff4ef88ac7b5f1b4dff1e
 F src/table.c 4301926464d88d2c2c7cd21c3360aa75bf068b95
 F src/tclsqlite.c 9e25f98f1765afa0716144ef57abda75c88f688d
 F src/test1.c 4596acd9d9f2a49fda0160a8a6dee5bfc7c6c325
@@ -151,7 +151,7 @@ F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
 F www/datatypes.tcl 0cb28565580554fa7e03e8fcb303e87ce57757ae
 F www/download.tcl 0932d7f4f0e8b2adbbd22fac73132f86e43ab4a9
 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
-F www/faq.tcl 12d1788d4abcfe1ff3054e17605df2418883bf6f
+F www/faq.tcl 88d3b95d9cd8e374772daa3a646c4d107e7f3e9b
 F www/fileformat.tcl d9b586416c0d099b82e02e469d532c9372f98f3f
 F www/formatchng.tcl cbaf0f410096c71f86a7537cf9249fa04b9a659c
 F www/index.tcl a34315cada875af0b098b4c45981da8ab33fe7b6
@@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
 F www/sqlite.tcl 4bd1729e320f5fa9125f0022b281fbe839192125
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P e8566cf5a381fa7655caacbc0fe95091e1137fea
-R 2370f3a91a8462e6af77d63e50ad9dc5
-U jplyon
-Z b0d55a69cad4bca6e8fe74221533622d
+P 8b8fa0fff26107912f0bec4e44df207c7885e273
+R b9d0e8972fcc9a231c0902a3a73faac1
+U drh
+Z 03fcc024f3cf3df89cb775ce044ef1b0
index a3dab974a515e79afd372d12b8d8c37bc38d9a20..00dada9fa42b9f55baac36a84fc2f8ce82dc97a5 100644 (file)
@@ -1 +1 @@
-8b8fa0fff26107912f0bec4e44df207c7885e273
\ No newline at end of file
+8c402db7e0745622d9950e5ca5d4d8e933da436c
\ No newline at end of file
index 46f22a43410cadecbc9d3ab6d6a8c8f134b706fe..2193b64a0eb78265882a82fbfee685c1b0eff321 100644 (file)
--- a/src/os.c
+++ b/src/os.c
@@ -992,10 +992,18 @@ int sqliteOsFileSize(OsFile *id, off_t *pSize){
 /*
 ** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
 ** Return false (zero) for Win95, Win98, or WinME.
+**
+** Here is an interesting observation:  Win95, Win98, and WinME lack
+** the LockFileEx() API.  But we can still statically link against that
+** API as long as we don't call it win running Win95/98/ME.  A call to
+** this routine is used to determine if the host is Win95/98/ME or
+** WinNT/2K/XP so that we will know whether or not we can safely call
+** the LockFileEx() API.
 */
 int isNT(void){
   static osType = 0;   /* 0=unknown 1=win95 2=winNT */
   if( osType==0 ){
+    int tmpOsType;
     OSVERSIONINFO sInfo;
     sInfo.dwOSVersionInfoSize = sizeof(sInfo);
     GetVersionEx(&sInfo);
@@ -1006,10 +1014,10 @@ int isNT(void){
 #endif
 
 /*
-** Windows file locking notes:  [the same/equivalent applies to MacOS]
+** Windows file locking notes:  [similar issues apply to MacOS]
 **
-** We cannot use LockFileEx() or UnlockFileEx() because those functions
-** are not available under Win95/98/ME.  So we use only LockFile() and
+** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
+** those functions are not available.  So we use only LockFile() and
 ** UnlockFile().
 **
 ** LockFile() prevents not just writing but also reading by other processes.
@@ -1034,6 +1042,14 @@ int isNT(void){
 ** another process jumping into the middle and messing us up.  The same
 ** argument applies to sqliteOsWriteLock().
 **
+** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
+** which means we can use reader/writer locks.  When reader writer locks
+** are used, the lock is placed on the same range of bytes that is used
+** for probabilistic locking in Win95/98/ME.  Hence, the locking scheme
+** will support two or more Win95 readers or two or more WinNT readers.
+** But a single Win95 reader will lock out all WinNT readers and a single
+** WinNT reader will lock out all other Win95 readers.
+**
 ** Note: On MacOS we use the resource fork for locking.
 **
 ** The following #defines specify the range of bytes used for locking.
@@ -1096,14 +1112,22 @@ int sqliteOsReadLock(OsFile *id){
     int lk = (sqliteRandomInteger() & 0x7ffffff)%N_LOCKBYTE+1;
     int res;
     int cnt = 100;
-    int page = isNT() ? 0xffffffff : 0;
-    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, page, 1, 0))==0 ){
+    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
       Sleep(1);
     }
     if( res ){
-      UnlockFile(id->h, FIRST_LOCKBYTE+1, page, N_LOCKBYTE, 0);
-      res = LockFile(id->h, FIRST_LOCKBYTE+lk, page, 1, 0);
-      UnlockFile(id->h, FIRST_LOCKBYTE, page, 1, 0);
+      UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
+      if( isNT() ){
+        OVERLAPPED ovlp;
+        ovlp.Offset = FIRST_LOCKBYTE+1;
+        ovlp.OffsetHigh = 0;
+        ovlp.hEvent = 0;
+        res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 
+                          0, N_LOCKBYTE, 0, &ovlp);
+      }else{
+        res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
+      }
+      UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
     }
     if( res ){
       id->locked = lk;
@@ -1191,18 +1215,23 @@ int sqliteOsWriteLock(OsFile *id){
   }else{
     int res;
     int cnt = 100;
-    int page = isNT() ? 0xffffffff : 0;
-    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, page, 1, 0))==0 ){
+    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
       Sleep(1);
     }
     if( res ){
-      if( id->locked==0 
-            || UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, page, 1, 0) ){
-        res = LockFile(id->h, FIRST_LOCKBYTE+1, page, N_LOCKBYTE, 0);
+      if( id->locked>0 ){
+        if( isNT() ){
+          UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
+        }else{
+          res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
+        }
+      }
+      if( res ){
+        res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
       }else{
         res = 0;
       }
-      UnlockFile(id->h, FIRST_LOCKBYTE, page, 1, 0);
+      UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
     }
     if( res ){
       id->locked = -1;
@@ -1291,15 +1320,14 @@ int sqliteOsUnlock(OsFile *id){
 #endif
 #if OS_WIN
   int rc;
-  int page = isNT() ? 0xffffffff : 0;
   if( id->locked==0 ){
     rc = SQLITE_OK;
-  }else if( id->locked<0 ){
-    UnlockFile(id->h, FIRST_LOCKBYTE+1, page, N_LOCKBYTE, 0);
+  }else if( isNT() || id->locked<0 ){
+    UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
     rc = SQLITE_OK;
     id->locked = 0;
   }else{
-    UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, page, 1, 0);
+    UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
     rc = SQLITE_OK;
     id->locked = 0;
   }
index 699facf806c0f4180861830d55841e896593e4a8..dd0650a7754a727edadfc12079636b7f12f9c5ab 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.186 2003/05/17 19:04:04 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.187 2003/05/29 17:43:08 drh Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -132,8 +132,13 @@ typedef unsigned INTPTR_TYPE uptr; /* Big enough to hold a pointer */
 ** multi-megabyte records are OK.  If your needs are different, you can
 ** change this define and recompile to increase or decrease the record
 ** size.
+**
+** The 16777198 is computed as follows:  238 bytes of payload on the
+** original pages plus 16448 overflow pages each holding 1020 bytes of
+** data.
 */
-#define MAX_BYTES_PER_ROW  1048576
+/* #define MAX_BYTES_PER_ROW  1048576 */
+#define MAX_BYTES_PER_ROW 16777198
 
 /*
 ** If memory allocation problems are found, recompile with
index a7de4f8202970b86ee72bcc93a6fa11e6dd1fc4a..f19049d673063ac11f04c0e80895bdb5023f0ab1 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this script to generated a faq.html output file
 #
-set rcsid {$Id: faq.tcl,v 1.22 2003/05/03 19:04:04 drh Exp $}
+set rcsid {$Id: faq.tcl,v 1.23 2003/05/29 17:43:08 drh Exp $}
 
 puts {<html>
 <head>
@@ -199,10 +199,15 @@ faq {
 
   <p>The locking mechanism used to control simultaneous access might
   not work correctly if the database file is kept on an NFS filesystem.
+  This is because file locking is broken on some NFS implementations.
   You should avoid putting SQLite database files on NFS if multiple
   processes might try to access the file at the same time.  On Windows,
   Microsoft's documentation says that locking may not work under FAT
-  filesystems if you are not running the Share.exe daemon.</p>
+  filesystems if you are not running the Share.exe daemon.  People who
+  have a lot of experience with Windows tell me that file locking of
+  network files is very buggy and is not dependable.  If what they
+  say is true, sharing an SQLite database between two or more Windows
+  machines might cause unexpected problems.</p>
 
   <p>Locking in SQLite is very course-grained.  SQLite locks the
   entire database.  Big database servers (PostgreSQL, Oracle, etc.)