diff --git a/manifest b/manifest index fea2bf8e0e..59494574f5 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index a3dab974a5..00dada9fa4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8b8fa0fff26107912f0bec4e44df207c7885e273 \ No newline at end of file +8c402db7e0745622d9950e5ca5d4d8e933da436c \ No newline at end of file diff --git a/src/os.c b/src/os.c index 46f22a4341..2193b64a0e 100644 --- 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; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 699facf806..dd0650a775 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 diff --git a/www/faq.tcl b/www/faq.tcl index a7de4f8202..f19049d673 100644 --- a/www/faq.tcl +++ b/www/faq.tcl @@ -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 { @@ -199,10 +199,15 @@ faq {

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.

+ 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.

Locking in SQLite is very course-grained. SQLite locks the entire database. Big database servers (PostgreSQL, Oracle, etc.)