]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Rework the changes for ticket #176 (check-ins (760) and (761)) to be
authordrh <drh@noemail.net>
Sun, 20 Oct 2002 18:19:45 +0000 (18:19 +0000)
committerdrh <drh@noemail.net>
Sun, 20 Oct 2002 18:19:45 +0000 (18:19 +0000)
more consistent with the rest of the source code. (CVS 768)

FossilOrigin-Name: f50a177b4239bc7a83563ac9361e830ec04e81fb

manifest
manifest.uuid
src/os.c

index 743a360b23c7622590e173f1b154dde5ce43c121..788f2e06a13a2f1749aa64367f30c9284c9ea810 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C The\s"table_info"\spragma\sreports\sunspecified\scolumn\stypes\sas\s"numeric"\sinstead\nof\s"text".\s\sFix\sfor\sticket\s#174.\s(CVS\s767)
-D 2002-10-20T16:00:28
+C Rework\sthe\schanges\sfor\sticket\s#176\s(check-ins\s(760)\sand\s(761))\sto\sbe\nmore\sconsistent\swith\sthe\srest\sof\sthe\ssource\scode.\s(CVS\s768)
+D 2002-10-20T18:19:45
 F Makefile.in d6c9a85c2a5e696843201d090dcf8bf2f8716f2a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -30,7 +30,7 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c 764300a0bd8074a2174946c0bf8a550bd833397a
 F src/main.c ff7c05ef88fa1374e5540ce20173ae8e1836f8a4
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
-F src/os.c c045297aae5a99710222baf939985498c5bb76d4
+F src/os.c ede7346dffdbab40c6de20d2f325981f3f1168fd
 F src/os.h 3009379b06941e7796a9812d1b6cbc59b26248c8
 F src/pager.c 592e5931fdc65e952a6c3e152bc822580856532a
 F src/pager.h 6991c9c2dc5e4c7f2df4d4ba47d1c6458f763a32
@@ -149,7 +149,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P d5470dfe102ef9b1dac3b15a2f5cc225e3c26129
-R 7ecb20627c80bbfd79b6dbcc45bd92d1
+P 395ab5fac201a37d6eca833ffd6f58ac8a0121a2
+R 839af7b0330753291020e1f24ae79a14
 U drh
-Z fbad8ba3d35f7e19e8e9a6b0f6544aa0
+Z 224ddb64edfd2ea0e4f95e777cac97ff
index e41c3bde3198d6aedfe27e1a75d5a1049c7faf76..8aed6c306d764c4cfa1157c7ca25d6bee57c4bfb 100644 (file)
@@ -1 +1 @@
-395ab5fac201a37d6eca833ffd6f58ac8a0121a2
\ No newline at end of file
+f50a177b4239bc7a83563ac9361e830ec04e81fb
\ No newline at end of file
index ae29b37b6d1e6cd093f615e0f7cdbacaf6772973..42dc89dd6b7efbda24ca88a837fceeaf14f42784 100644 (file)
--- a/src/os.c
+++ b/src/os.c
@@ -90,14 +90,14 @@ static int last_page = 0;
 ** cnt>0 means there are cnt shared locks on the file.
 **
 ** Any attempt to lock or unlock a file first checks the locking
-** structure.  The fcntl() system call is only invoked to set a
+** structure.  The fcntl() system call is only invoked to set a 
 ** POSIX lock if the internal lock structure transitions between
 ** a locked and an unlocked state.
 */
 
 /*
 ** An instance of the following structure serves as the key used
-** to locate a particular lockInfo structure given its inode.
+** to locate a particular lockInfo structure given its inode. 
 */
 struct inodeKey {
   dev_t dev;   /* Device number */
@@ -116,7 +116,7 @@ struct lockInfo {
   int nRef;             /* Number of pointers to this structure */
 };
 
-/*
+/* 
 ** This hash table maps inodes (in the form of inodeKey structures) into
 ** pointers to lockInfo structures.
 */
@@ -236,7 +236,7 @@ int sqliteOsOpenReadWrite(
   if( id->fd<0 ){
     id->fd = open(zFilename, O_RDONLY);
     if( id->fd<0 ){
-      return SQLITE_CANTOPEN;
+      return SQLITE_CANTOPEN; 
     }
     *pReadonly = 1;
   }else{
@@ -328,7 +328,7 @@ int sqliteOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
   HANDLE h;
   int fileflags;
   if( delFlag ){
-    fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
+    fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS 
                      | FILE_FLAG_DELETE_ON_CLOSE;
   }else{
     fileflags = FILE_FLAG_RANDOM_ACCESS;
@@ -448,7 +448,7 @@ int sqliteOsTempFileName(char *zBuf){
     if( !sqliteOsFileExists(zBuf) ) break;
   }
 #endif
-  return SQLITE_OK;
+  return SQLITE_OK; 
 }
 
 /*
@@ -492,7 +492,7 @@ int sqliteOsRead(OsFile *id, void *pBuf, int amt){
   if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
     got = 0;
   }
-  if( (int)got==amt ){
+  if( got==(DWORD)amt ){
     return SQLITE_OK;
   }else{
     return SQLITE_IOERR;
@@ -605,6 +605,23 @@ int sqliteOsFileSize(OsFile *id, int *pSize){
 #endif
 }
 
+#if OS_WIN
+/*
+** Return true (non-zero) if we are running under WinNT, Win2K or WinXP.
+** Return false (zero) for Win95, Win98, or WinME.
+*/
+int isNT(void){
+  static osType = 0;   /* 0=unknown 1=win95 2=winNT */
+  if( osType==0 ){
+    OSVERSIONINFO sInfo;
+    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+    GetVersionEx(&sInfo);
+    osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
+  }
+  return osType==2;
+}
+#endif
+
 /*
 ** Windows file locking notes:
 **
@@ -612,84 +629,36 @@ int sqliteOsFileSize(OsFile *id, int *pSize){
 ** are not available under Win95/98/ME.  So we use only LockFile() and
 ** UnlockFile().
 **
-** A read lock is obtained by locking a single random byte in the
-** range of 1 to MX_LOCKBYTE.  The lock byte is obtained at random so
-** two separate readers can probably access the file at the same time,
-** unless they are unlucky and choose the same lock byte.  A write lock
-** is obtained by locking all bytes in the range of 1 to MX_LOCKBYTE.
-** There can only be one writer.
+** LockFile() prevents not just writing but also reading by other processes.
+** (This is a design error on the part of Windows, but there is nothing
+** we can do about that.)  So the region used for locking is at the
+** end of the file where it is unlikely to ever interfere with an
+** actual read attempt.
 **
-** A lock is obtained on byte 0 before acquiring either a read lock or
-** a write lock.  This prevents two processes from attempting to get a
-** lock at a same time.  The semantics of sqliteOsReadLock() require that
-** if there is already a write lock, that lock is converted into a read
-** lock atomically.  The lock on byte 0 allows us to drop the old write
-** lock and get the read lock without another process jumping into the
-** middle and messing us up.  The same argument applies to sqliteOsWriteLock().
+** A database read lock is obtained by locking a single randomly-chosen 
+** byte out of a specific range of bytes. The lock byte is obtained at 
+** random so two separate readers can probably access the file at the 
+** same time, unless they are unlucky and choose the same lock byte.
+** A database write lock is obtained by locking all bytes in the range.
+** There can only be one writer.
 **
-** Locks must be obtained in an area that does not overlap the "real data area"
-** otherwise read/write operations will conflict with lock operations. Locking beyond EOF
-** is allowed in windows.
+** A lock is obtained on the first byte of the lock range before acquiring
+** either a read lock or a write lock.  This prevents two processes from
+** attempting to get a lock at a same time.  The semantics of 
+** sqliteOsReadLock() require that if there is already a write lock, that
+** lock is converted into a read lock atomically.  The lock on the first
+** byte allows us to drop the old write lock and get the read lock without
+** another process jumping into the middle and messing us up.  The same
+** argument applies to sqliteOsWriteLock().
 **
-** There are a finite number of read locks under windows.  That number
-** is determined by the following variable:
+** The following #defines specify the range of bytes used for locking.
+** N_LOCKBYTE is the number of bytes available for doing the locking.
+** The first byte used to hold the lock while the lock is changing does
+** not count toward this number.  FIRST_LOCKBYTE is the address of
+** the first byte in the range of bytes used for locking.
 */
-
-#define MX_LOCKBYTE 0xFFF0
-
-#if OS_WIN
-
-// get the platform id to decide how to calculate the lock offset
-
-int mkPlatformId(void){
-
- static long init=0;
- static long lock=0;
-
- static int pid=VER_PLATFORM_WIN32_WINDOWS;
- OSVERSIONINFOA info;
-
- while (!init) {
-  if (InterlockedIncrement(&lock)==1)
-   {
-    info.dwOSVersionInfoSize=sizeof(info);
-    if (GetVersionEx(&info)) pid=info.dwPlatformId;
-    init=1;
-   }
-  else
-   Sleep(1);
-  }
- return pid;
-}
-
-// locks and unlocks beyond eof. uses platformid to move the lock as far as possible.
-int mklock(HANDLE h, WORD base, WORD size)
-{
- if (mkPlatformId()==VER_PLATFORM_WIN32_WINDOWS)
-  return LockFile(h,0xFFFF0000+base,0,size,0);
- else
-  return LockFile(h,base,0xFFFFFFFF,size,0);
-}
-
-int mkunlock(HANDLE h, WORD base, WORD size)
-{
- if (mkPlatformId()==VER_PLATFORM_WIN32_WINDOWS)
-  return UnlockFile(h,0xFFFF0000+base,0,size,0);
- else
-  return UnlockFile(h,base,0xFFFFFFFF,size,0);
-}
-
-//obtain the sync lock on a handle
-
-void synclock(HANDLE h){
- while (!mklock(h,0,1)) Sleep(1);
-}
-
-void syncunlock(HANDLE h){
- mkunlock(h,0,1);
-}
-
-#endif
+#define N_LOCKBYTE       10239
+#define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)
 
 /*
 ** Change the status of the lock on the file "id" to be a readlock.
@@ -698,7 +667,6 @@ void syncunlock(HANDLE h){
 **
 ** Return SQLITE_OK on success and SQLITE_BUSY on failure.
 */
-
 int sqliteOsReadLock(OsFile *id){
 #if OS_UNIX
   int rc;
@@ -732,14 +700,18 @@ int sqliteOsReadLock(OsFile *id){
   if( id->locked>0 ){
     rc = SQLITE_OK;
   }else{
-    int lk = (sqliteRandomInteger() & 0x7ffffff)%MX_LOCKBYTE + 1;
+    int lk = (sqliteRandomInteger() & 0x7ffffff)%N_LOCKBYTE+1;
     int res;
-
-    synclock(id->h);
-    if (id->locked<0) mkunlock(id->h,1,MX_LOCKBYTE); // release write lock if we have it
-    res=mklock(id->h,lk,1);
-    syncunlock(id->h);
-
+    int cnt = 100;
+    int page = isNT() ? 0xffffffff : 0;
+    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, page, 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);
+    }
     if( res ){
       id->locked = lk;
       rc = SQLITE_OK;
@@ -783,13 +755,21 @@ int sqliteOsWriteLock(OsFile *id){
     rc = SQLITE_OK;
   }else{
     int res;
-
-    synclock(id->h);
-    if (id->locked>0) mkunlock(id->h,id->locked,1); // release read lock
-    res=mklock(id->h,1,MX_LOCKBYTE);
-    syncunlock(id->h);
-
-    if(res){
+    int cnt = 100;
+    int page = isNT() ? 0xffffffff : 0;
+    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, page, 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);
+      }else{
+        res = 0;
+      }
+      UnlockFile(id->h, FIRST_LOCKBYTE, page, 1, 0);
+    }
+    if( res ){
       id->locked = -1;
       rc = SQLITE_OK;
     }else{
@@ -831,13 +811,19 @@ int sqliteOsUnlock(OsFile *id){
 #endif
 #if OS_WIN
   int rc;
-  if(id->locked<0 ) {
-    mkunlock(id->h,1,MX_LOCKBYTE);
-  }else if (id->locked>0) {
-    mkunlock(id->h,id->locked,1);
+  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);
+    rc = SQLITE_OK;
+    id->locked = 0;
+  }else{
+    UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, page, 1, 0);
+    rc = SQLITE_OK;
+    id->locked = 0;
   }
-  id->locked = 0;
-  return SQLITE_OK;
+  return rc;
 #endif
 }