]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Initial work on blocking locks for the Win32 VFS. Various other small enhancements.
authormistachkin <mistachkin@noemail.net>
Thu, 15 Jul 2021 23:12:27 +0000 (23:12 +0000)
committermistachkin <mistachkin@noemail.net>
Thu, 15 Jul 2021 23:12:27 +0000 (23:12 +0000)
FossilOrigin-Name: 584c24252a37ef050ced5926a93e52fc47a41d9017b291dc1c1c796712e391d7

manifest
manifest.uuid
src/os_win.c

index e552a4aba7b8a0f206da4c038bf3aeeb4dcecf4d..ff54209df41d00f47d14dfe03962d94224c0c28a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\sthe\sWindows\sVFS\sto\srecognize\sSQLITE_FCNTL_LOCK_TIMEOUT\sand\smake\nthe\svalue\sset\sthere\savailable\sto\sthe\swinLockFile()\sfunction.
-D 2021-07-14T19:35:45.291
+C Initial\swork\son\sblocking\slocks\sfor\sthe\sWin32\sVFS.\s\sVarious\sother\ssmall\senhancements.
+D 2021-07-15T23:12:27.529
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -529,7 +529,7 @@ F src/os.h 26890f540b475598cd9881dcc68931377b8d429d3ea3e2eeb64470cde64199f8
 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
 F src/os_unix.c b11e4610769922253dec27d7af4a07ff84f65169d19bda5e9b12a152a706f7f5
-F src/os_win.c dc54e0a4b15a0c151dc9f01e64976d8f435d8020f0a8507d7acc5452b438d229
+F src/os_win.c 15c4dce3a03801a18d6de2f636373cbe6d3843b99932d1bfe16758336ada818a
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0
 F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
@@ -1920,10 +1920,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c378e99250fe06fae8ca40c62185b607f004d6806e07dbb9f964dd849b4e55f8
-R 21f9449dd33d80268629340267e31b8d
-T *branch * win-blocking-locks
-T *sym-win-blocking-locks *
-T -sym-trunk *
-U drh
-Z 229f4697970d0911e5dbcc6bd7ebdd8d
+P 954b5d61299d82312a9ca2764f904e2d8318c469f6749d84f8a6871d12a575a8
+R ce6cfd7eda001c4ee216459a1054a7c1
+U mistachkin
+Z b59d01fb46dfdd3d864282a4891b32ce
index bfa8f19f1ec9c95a82d65721d02f30f5fcb2ca3f..8b4119f50682789926606f05b2889aaad696a6e6 100644 (file)
@@ -1 +1 @@
-954b5d61299d82312a9ca2764f904e2d8318c469f6749d84f8a6871d12a575a8
\ No newline at end of file
+584c24252a37ef050ced5926a93e52fc47a41d9017b291dc1c1c796712e391d7
\ No newline at end of file
index 059e884ee3f21dc6c07be5a188313d35225f89fe..e54708faffb27de5174609e681c9ce55bdfaf13f 100644 (file)
@@ -1127,7 +1127,7 @@ static struct win_syscall {
   { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
 
 #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
-        SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
+        SQLITE_WIN32_VOLATILE*,LONG,LONG))aSyscall[76].pCurrent)
 #endif /* defined(InterlockedCompareExchange) */
 
 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
@@ -1156,6 +1156,23 @@ static struct win_syscall {
 #define osFlushViewOfFile \
         ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
 
+#if !SQLITE_OS_WINRT
+  { "GetFileInformationByHandle", (SYSCALL)GetFileInformationByHandle, 0 },
+#else
+  { "GetFileInformationByHandle", (SYSCALL)0,                  0 },
+#endif
+
+#define osGetFileInformationByHandle ((BOOL(WINAPI*)(HANDLE, \
+        LPBY_HANDLE_FILE_INFORMATION))aSyscall[80].pCurrent)
+
+#if !SQLITE_OS_WINRT
+  { "SleepEx",                 (SYSCALL)SleepEx,                 0 },
+#else
+  { "SleepEx",                 (SYSCALL)0,                       0 },
+#endif
+
+#define osSleepEx ((VOID(WINAPI*)(DWORD,BOOL))aSyscall[81].pCurrent)
+
 }; /* End of the overrideable system calls */
 
 /*
@@ -1380,18 +1397,25 @@ void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
 static HANDLE sleepObj = NULL;
 #endif
 
-void sqlite3_win32_sleep(DWORD milliseconds){
+void sqlite3Win32Sleep(DWORD milliseconds, BOOL alertable){
 #if SQLITE_OS_WINRT
   if ( sleepObj==NULL ){
     sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
                                 SYNCHRONIZE);
   }
   assert( sleepObj!=NULL );
-  osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
+  osWaitForSingleObjectEx(sleepObj, milliseconds, alertable);
 #else
-  osSleep(milliseconds);
+  if( alertable ){
+    osSleepEx(milliseconds, alertable);
+  }else{
+    osSleep(milliseconds);
+  }
 #endif
 }
+void sqlite3_win32_sleep(DWORD milliseconds){
+  sqlite3Win32Sleep(milliseconds, FALSE);
+}
 
 #if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
         SQLITE_THREADSAFE>0
@@ -2155,13 +2179,13 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
     return 0;
   }
   if( winIoerrCanRetry1(e) ){
-    sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
+    sqlite3Win32Sleep(winIoerrRetryDelay*(1+*pnRetry), TRUE);
     ++*pnRetry;
     return 1;
   }
 #if defined(winIoerrCanRetry2)
   else if( winIoerrCanRetry2(e) ){
-    sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
+    sqlite3Win32Sleep(winIoerrRetryDelay*(1+*pnRetry), TRUE);
     ++*pnRetry;
     return 1;
   }
@@ -2526,11 +2550,25 @@ static BOOL winLockFile(
                        numBytesLow, numBytesHigh);
 #else
   if( osIsNT() ){
+    BOOL bResult;
     OVERLAPPED ovlp;
     memset(&ovlp, 0, sizeof(OVERLAPPED));
     ovlp.Offset = offsetLow;
     ovlp.OffsetHigh = offsetHigh;
-    return osLockFileEx(pFile->h, flags, 0, numBytesLow, numBytesHigh, &ovlp);
+    bResult = osLockFileEx(pFile->h, flags, 0, numBytesLow,
+                           numBytesHigh, &ovlp);
+    if( !bResult && pFile->iBusyTimeout>0 ){
+      unsigned iDelay = (unsigned)winIoerrRetryDelay;
+      if( iDelay>0 ){
+        u64 iTotalDelay = 0;
+        do{
+          sqlite3Win32Sleep(iDelay, TRUE); iTotalDelay += iDelay;
+          bResult = osLockFileEx(pFile->h, flags, 0, numBytesLow,
+                                 numBytesHigh, &ovlp);
+        }while( !bResult && iTotalDelay<pFile->iBusyTimeout );
+      }
+    }
+    return bResult;
   }else{
     return osLockFile(pFile->h, offsetLow, offsetHigh, numBytesLow,
                       numBytesHigh);
@@ -2678,7 +2716,7 @@ static int winClose(sqlite3_file *id){
   do{
     rc = osCloseHandle(pFile->h);
     /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
-  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
+  }while( rc==0 && ++cnt<MX_CLOSE_ATTEMPT && (sqlite3Win32Sleep(100,TRUE), 1) );
 #if SQLITE_OS_WINCE
 #define WINCE_DELETION_ATTEMPTS 3
   {
@@ -2694,7 +2732,7 @@ static int winClose(sqlite3_file *id){
         && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
         && cnt++ < WINCE_DELETION_ATTEMPTS
     ){
-       sqlite3_win32_sleep(100);  /* Wait a little before trying again */
+       sqlite3Win32Sleep(100, TRUE);  /* Wait a little before trying again */
     }
     sqlite3_free(pFile->zDeleteOnClose);
   }
@@ -3298,7 +3336,7 @@ static int winLock(sqlite3_file *id, int locktype){
                  pFile->h, cnt, sqlite3ErrName(rc)));
         return rc;
       }
-      if( cnt ) sqlite3_win32_sleep(1);
+      if( cnt ) sqlite3Win32Sleep(1, TRUE);
     }
     gotPendingLock = res;
     if( !res ){
@@ -3835,6 +3873,134 @@ static int winShmSystemLock(
 /* Forward references to VFS methods */
 static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
 static int winDelete(sqlite3_vfs *,const char*,int);
+static int winFullPathname(sqlite3_vfs *,const char *,int,char *);
+static void *winConvertFromUtf8Filename(const char *);
+
+#if !SQLITE_OS_WINRT
+/*
+** This function attempts to query the metadata information for the
+** specified file.  Upon success, SQLITE_OK is returned; otherwise,
+** an appropriate error code is returned.
+*/
+
+static int winGetFileInfo(
+  const char *zFilename,
+  winFile *pFile,
+  LPBY_HANDLE_FILE_INFORMATION pFileInfo
+){
+  int rc = SQLITE_OK;
+  HANDLE hFile = NULL;
+  int lastError = 0;
+  void *zConverted = winConvertFromUtf8Filename(zFilename);
+  if( zConverted==0 ){
+    lastError = osGetLastError();
+    if( pFile ) pFile->lastErrno = lastError;
+    return winLogError(SQLITE_IOERR_NOMEM, lastError,
+                       "winGetFileInfo1", zFilename);
+  }
+  if( osIsNT() ){
+    hFile = osCreateFileW(
+        (LPCWSTR)zConverted, GENERIC_READ,
+        FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
+    );
+#ifdef SQLITE_WIN32_HAS_ANSI
+  }else{
+    hFile = osCreateFileA(
+        (LPCSTR)zConverted, GENERIC_READ,
+        FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
+    );
+#endif
+  }
+  sqlite3_free(zConverted);
+  if( hFile==INVALID_HANDLE_VALUE ){
+    lastError = osGetLastError();
+    if( pFile ) pFile->lastErrno = lastError;
+    return winLogError(SQLITE_CANTOPEN, lastError,
+                       "winGetFileInfo2", zFilename);
+  }
+  if( !osGetFileInformationByHandle(hFile, pFileInfo) ){
+    lastError = osGetLastError();
+    if( pFile ) pFile->lastErrno = lastError;
+    rc = winLogError(SQLITE_IOERR_FSTAT, lastError,
+                     "winGetFileInfo3", zFilename);
+  }
+  osCloseHandle(hFile);
+  return rc;
+}
+#endif
+
+/*
+** Returns non-zero if both of the specified file names refer to the same
+** underlying file.  On some sub-platforms, this function may return zero
+** even when both file names refer to the same underlying file; however,
+** it will never return non-zero unless both file names refer to the same
+** underlying file.
+*/
+
+static int winIsSameFile(
+  sqlite3_vfs *pVfs,
+  winFile *pFile,
+  const char *zFilename1,
+  const char *zFilename2,
+  BOOL *pbSame
+){
+  *pbSame = 0; /* initially, assume not the same file */
+
+#if !SQLITE_OS_WINRT
+  {
+    BY_HANDLE_FILE_INFORMATION info1;
+    BY_HANDLE_FILE_INFORMATION info2;
+
+    if( !winGetFileInfo(zFilename1, pFile, &info1)
+     || !winGetFileInfo(zFilename2, pFile, &info2) ){
+      /* wrong file system type?  ok, use fallback. */
+      goto fallback;
+    }
+    if( info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber
+           && info1.nFileIndexHigh == info2.nFileIndexHigh
+            && info1.nFileIndexLow == info2.nFileIndexLow ){
+      OSTRACE(("SAME pid=%lu, pFile=%p, name1=%s, name2=%s, "
+               "YES, rc=SQLITE_OK\n", osGetCurrentProcessId(),
+               pFile, zFilename1, zFilename2));
+      *pbSame = 1;
+      return SQLITE_OK;
+    }
+  }
+#endif
+
+fallback:
+  {
+    int rc = SQLITE_OK;
+    int nFull = pVfs->mxPathname+1;
+    char *zFull1 = NULL;
+    char *zFull2 = NULL;
+
+    zFull1 = sqlite3MallocZero( nFull );
+    if( zFull1==0 ){
+      rc = SQLITE_IOERR_NOMEM_BKPT;
+      goto done;
+    }
+    zFull2 = sqlite3MallocZero( nFull );
+    if( zFull2==0 ){
+      rc = SQLITE_IOERR_NOMEM_BKPT;
+      goto done;
+    }
+    rc = winFullPathname(pVfs, zFilename1, nFull, zFull1);
+    if( rc!=SQLITE_OK ) goto done;
+    rc = winFullPathname(pVfs, zFilename2, nFull, zFull2);
+    if( rc!=SQLITE_OK ) goto done;
+    *pbSame = sqlite3StrICmp(zFull1, zFull2)==0;
+done:
+    if( zFull2 ) sqlite3_free(zFull2);
+    if( zFull1 ) sqlite3_free(zFull1);
+    OSTRACE(("SAME pid=%lu, pFile=%p, name1=%s, name2=%s, %s, rc=%s\n",
+             osGetCurrentProcessId(), pFile, zFilename1, zFilename2,
+             *pbSame?"YES":"NO", sqlite3ErrName(rc)));
+    return rc;
+  }
+}
 
 /*
 ** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
@@ -3951,10 +4117,13 @@ static int winOpenSharedMemory(winFile *pDbFd){
   */
   winShmEnterMutex();
   for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
-    /* TBD need to come up with better match here.  Perhaps
-    ** use FILE_ID_BOTH_DIR_INFO Structure.
-    */
-    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
+    BOOL bSame;
+    rc = winIsSameFile(
+        pDbFd->pVfs, pDbFd, pShmNode->zFilename, pNew->zFilename,
+        &bSame
+    );
+    if( rc!=SQLITE_OK ) goto shm_open_err;
+    if( bSame ) break;
   }
   if( pShmNode ){
     sqlite3_free(pNew);
@@ -5002,7 +5171,7 @@ static int winOpen(
   int flags,                /* Open mode flags */
   int *pOutFlags            /* Status return flags */
 ){
-  HANDLE h;
+  HANDLE h = INVALID_HANDLE_VALUE;
   DWORD lastErrno = 0;
   DWORD dwDesiredAccess;
   DWORD dwShareMode;
@@ -5289,7 +5458,7 @@ static int winOpen(
     pFile->ctrlFlags |= WINFILE_RDONLY;
   }
   if( (flags & SQLITE_OPEN_MAIN_DB)
-   && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) 
+   && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
   ){
     pFile->ctrlFlags |= WINFILE_PSOW;
   }
@@ -5896,7 +6065,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
 ** Sleep for a little while.  Return the amount of time slept.
 */
 static int winSleep(sqlite3_vfs *pVfs, int microsec){
-  sqlite3_win32_sleep((microsec+999)/1000);
+  sqlite3Win32Sleep((microsec+999)/1000, FALSE);
   UNUSED_PARAMETER(pVfs);
   return ((microsec+999)/1000)*1000;
 }
@@ -6117,7 +6286,7 @@ int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==80 );
+  assert( ArraySize(aSyscall)==82 );
 
   /* get memory map allocation granularity */
   memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));