]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Preliminary changes to support the xMremap VFS method on Windows.
authormistachkin <mistachkin@noemail.net>
Sat, 23 Mar 2013 09:56:39 +0000 (09:56 +0000)
committermistachkin <mistachkin@noemail.net>
Sat, 23 Mar 2013 09:56:39 +0000 (09:56 +0000)
FossilOrigin-Name: 75a85a1c6ac59f2d021c28fa2161afb1118deea4

manifest
manifest.uuid
src/os_win.c
src/test1.c

index 868c9e01731eb4125c19422a1523e4ea7c96e406..b81d7d1140ebb550dbd73eeacb51357861470a7a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\swal\smode\stests\sso\sthat\sthey\swork\swith\sthe\smmap\stest\spermutation.
-D 2013-03-22T20:15:31.365
+C Preliminary\schanges\sto\ssupport\sthe\sxMremap\sVFS\smethod\son\sWindows.
+D 2013-03-23T09:56:39.403
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 9a804abbd3cae82d196e4d33aba13239e32522a5
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -161,7 +161,7 @@ F src/os.c 87ea1cd1259c5840848e34007d72e772a2ab7528
 F src/os.h 8d92f87f5fe14b060a853ca704b8ef6d3daee79b
 F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
 F src/os_unix.c 55d110879332831b734fd510cfbc5700e96a83cf
-F src/os_win.c f7da4dc0a2545c0a430080380809946ae4d676d6
+F src/os_win.c 46d2bbad7a65d2867ec0e9afb4aa28478402e9dc
 F src/pager.c 12b8ff12519fe529a92884c4cdb99afecb1bea3c
 F src/pager.h bbc9170281c9d5d603b2175fdc8ea908e47269a7
 F src/parse.y 5d5e12772845805fdfeb889163516b84fbb9ae95
@@ -184,7 +184,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
 F src/tclsqlite.c 3213f3101e3b85f047d6e389da5a53d76d3d7540
-F src/test1.c 39378e3e14a8162e29dc90d1e05399d12e8a569e
+F src/test1.c 26e66b839f42c2eed6833f9023e0098f0d863f35
 F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
 F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
 F src/test4.c bf9fa9bece01de08e6f5e02314e4af5c13590dfa
@@ -1039,7 +1039,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P e81ccdcd87a1387f7ca08d4d7c899311e2180d32
-R f5bd57e0d254253276d114325fd2ea6d
-U dan
-Z 0c2e4f926a5fed4f3d574bc2f3c43e20
+P f7295872a36539d10edaf0c633f935f25cf73657
+R 33ae184619389f0a2e2f45e36bcba41c
+U mistachkin
+Z 7a5b6171912da74b28162981ae14cd6f
index a8b241dcada7fc6beb2973480490bd41ab228723..ade491dce4384a1217bbb4c65c65526bd1015386 100644 (file)
@@ -1 +1 @@
-f7295872a36539d10edaf0c633f935f25cf73657
\ No newline at end of file
+75a85a1c6ac59f2d021c28fa2161afb1118deea4
\ No newline at end of file
index 970a94b5e8abb5e8683f88a0e7d95b4c44c6d203..fd0c8aeb8950bd08b2613acd8da0009916d7af6b 100644 (file)
@@ -150,11 +150,15 @@ struct winFile {
   winceLock local;        /* Locks obtained by this instance of winFile */
   winceLock *shared;      /* Global shared lock memory for the file  */
 #endif
+  HANDLE hMap;            /* Handle for accessing memory mapping */
+  void *pMapRegion;       /* Area memory mapped */
+  sqlite3_int64 mmapSize; /* Size of xMremap() */
 };
 
 /*
 ** Allowed values for winFile.ctrlFlags
 */
+#define WINFILE_RDONLY          0x02   /* Connection is read only */
 #define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
 #define WINFILE_PSOW            0x10   /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
 
@@ -2061,6 +2065,9 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
 #endif
 }
 
+/* Forward references to VFS methods */
+static int winUnmap(sqlite3_file *);
+
 /*
 ** Close a file.
 **
@@ -2082,6 +2089,10 @@ static int winClose(sqlite3_file *id){
 #endif
   OSTRACE(("CLOSE %d\n", pFile->h));
   assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
+
+  rc = winUnmap(id);
+  if( rc!=SQLITE_OK ) return rc;
+
   do{
     rc = osCloseHandle(pFile->h);
     /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -2130,6 +2141,8 @@ static int winRead(
   int nRetry = 0;                 /* Number of retrys */
 
   assert( id!=0 );
+  assert( amt>0 );
+  assert( offset>=pFile->mmapSize ); /* Never read from the mmapped region */
   SimulateIOError(return SQLITE_IOERR_READ);
   OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
 
@@ -2176,6 +2189,7 @@ static int winWrite(
   int nRetry = 0;                 /* Number of retries */
 
   assert( amt>0 );
+  assert( offset>=pFile->mmapSize ); /* Never write into the mmapped region */
   assert( pFile );
   SimulateIOError(return SQLITE_IOERR_WRITE);
   SimulateDiskfullError(return SQLITE_FULL);
@@ -2249,12 +2263,16 @@ static int winWrite(
 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
   winFile *pFile = (winFile*)id;  /* File handle object */
   int rc = SQLITE_OK;             /* Return code for this function */
+  DWORD lastErrno;
 
   assert( pFile );
 
   OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
   SimulateIOError(return SQLITE_IOERR_TRUNCATE);
 
+  rc = winUnmap(id);
+  if( rc!=SQLITE_OK ) return rc;
+
   /* If the user has configured a chunk-size for this file, truncate the
   ** file so that it consists of an integer number of chunks (i.e. the
   ** actual file size after the operation may be larger than the requested
@@ -2267,11 +2285,20 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
   /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
   if( seekWinFile(pFile, nByte) ){
     rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-             "winTruncate1", pFile->zPath);
-  }else if( 0==osSetEndOfFile(pFile->h) ){
-    pFile->lastErrno = osGetLastError();
+                     "winTruncate1", pFile->zPath);
+  }else if( 0==osSetEndOfFile(pFile->h) &&
+            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
+    pFile->lastErrno = lastErrno;
     rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
-             "winTruncate2", pFile->zPath);
+                     "winTruncate2", pFile->zPath);
+  }else{
+    /* If the file was just truncated to a size smaller than the currently
+    ** mapped region, reduce the effective mapping size as well. SQLite will
+    ** use read() and write() to access data beyond this point from now on.
+    */
+    if( pFile->pMapRegion && nByte<pFile->mmapSize ){
+      pFile->mmapSize = nByte;
+    }
   }
 
   OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
@@ -3451,6 +3478,154 @@ shmpage_out:
 # define winShmUnmap   0
 #endif /* #ifndef SQLITE_OMIT_WAL */
 
+/*
+** Arguments x and y are both integers. Argument y must be a power of 2.
+** Round x up to the nearest integer multiple of y. For example:
+**
+**     ROUNDUP(0,  8) ->  0
+**     ROUNDUP(13, 8) -> 16
+**     ROUNDUP(32, 8) -> 32
+*/
+#define ROUNDUP(x,y)     (((x)+y-1)&~(y-1))
+
+/*
+** Cleans up the mapped region of the specified file, if any.
+*/
+static int winUnmap(
+  sqlite3_file *id
+){
+  winFile *pFile = (winFile*)id;
+  assert( pFile!=0 );
+  if( pFile->pMapRegion ){
+    if( !osUnmapViewOfFile(pFile->pMapRegion) ){
+      pFile->lastErrno = osGetLastError();
+      return winLogError(SQLITE_IOERR_MREMAP, pFile->lastErrno,
+                         "winUnmap1", pFile->zPath);
+    }
+    pFile->pMapRegion = 0;
+    pFile->mmapSize = 0;
+  }
+  if( pFile->hMap!=NULL ){
+    if( !osCloseHandle(pFile->hMap) ){
+      pFile->lastErrno = osGetLastError();
+      return winLogError(SQLITE_IOERR_MREMAP, pFile->lastErrno,
+                         "winUnmap2", pFile->zPath);
+    }
+    pFile->hMap = NULL;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Map, remap or unmap part of the database file.
+*/
+static int winMremap(
+  sqlite3_file *id,               /* Main database file */
+  int flags,                      /* Mask of SQLITE_MREMAP_XXX flags */
+  sqlite3_int64 iOff,             /* Offset to start mapping at */
+  sqlite3_int64 nOld,             /* Size of old mapping, or zero */
+  sqlite3_int64 nNew,             /* Size of new mapping, or zero */
+  void **ppMap                    /* IN/OUT: Old/new mappings */
+){
+  winFile *pFile = (winFile*)id;  /* The underlying database file */
+  int rc = SQLITE_OK;             /* Return code */
+  HANDLE hMap = NULL;             /* New mapping handle */
+  void *pNew = 0;                 /* New mapping */
+  i64 nNewRnd;                    /* nNew rounded up */
+  i64 nOldRnd;                    /* nOld rounded up */
+
+  assert( pFile!=0 );
+  assert( iOff==0 );
+  assert( nOld>=0 );
+  assert( nOld==0 || pFile->pMapRegion==(*ppMap) );
+  assert( nNew>=0 );
+  assert( ppMap );
+  assert( pFile->hMap==NULL || pFile->pMapRegion==(*ppMap) );
+  assert( pFile->pMapRegion==0 || pFile->pMapRegion==(*ppMap) );
+  /* assert( pFile->mmapSize==nOld ); */
+
+  assert( winSysInfo.dwPageSize>0 );
+  nNewRnd = ROUNDUP(nNew, winSysInfo.dwPageSize*1);
+  assert( nNewRnd>=0 );
+  nOldRnd = ROUNDUP(nOld, winSysInfo.dwPageSize*1);
+  assert( nOldRnd>=0 );
+
+  if( nNewRnd==nOldRnd ){
+    pFile->mmapSize = nNew;
+    return SQLITE_OK;
+  }
+
+  /* If the SQLITE_MREMAP_EXTEND flag is set, then the size of the requested
+  ** mapping (nNew bytes) may be greater than the size of the database file.
+  ** If this is the case, extend the file on disk using ftruncate().  */
+  assert( nNewRnd>0 || (flags & SQLITE_MREMAP_EXTEND)==0 );
+  if( flags & SQLITE_MREMAP_EXTEND ){
+    sqlite3_int64 oldSz;
+    rc = winFileSize(id, &oldSz);
+    if( rc==SQLITE_OK && nNewRnd>oldSz ){
+      rc = winTruncate(id, nNewRnd);
+    }
+    if( rc!=SQLITE_OK ) return rc;
+  }
+
+  /* If we get this far, unmap any old mapping. */
+  rc = winUnmap(id);
+  if( rc!=SQLITE_OK ) return rc;
+
+  /* And, if required, create a new mapping. */
+  if( nNewRnd>0 ){
+    i64 offset = ((iOff / winSysInfo.dwAllocationGranularity) *
+                  (winSysInfo.dwAllocationGranularity));
+    DWORD protect = PAGE_READONLY;
+    DWORD flags = FILE_MAP_READ;
+    if( (pFile->ctrlFlags & WINFILE_RDONLY)==0 ){
+      protect = PAGE_READWRITE;
+      flags |= FILE_MAP_WRITE;
+    }
+#if SQLITE_OS_WINRT
+    hMap = osCreateFileMappingFromApp(pFile->h, NULL, protect, nNewRnd, NULL);
+#elif defined(SQLITE_WIN32_HAS_WIDE)
+    hMap = osCreateFileMappingW(pFile->h, NULL, protect,
+                                (DWORD)((nNewRnd>>32) & 0xffffffff),
+                                (DWORD)(nNewRnd & 0xffffffff), NULL);
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+    hMap = osCreateFileMappingA(pFile->h, NULL, protect,
+                                (DWORD)((nNewRnd>>32) & 0xffffffff),
+                                (DWORD)(nNewRnd & 0xffffffff), NULL);
+#endif
+    if( hMap==NULL ){
+      pFile->lastErrno = osGetLastError();
+      rc = winLogError(SQLITE_IOERR_MREMAP, pFile->lastErrno,
+                       "winMremap1", pFile->zPath);
+      return rc;
+    }
+    assert( (nNewRnd % winSysInfo.dwPageSize)==0 );
+#if SQLITE_OS_WINRT
+    pNew = osMapViewOfFileFromApp(hMap, flags, offset, nNewRnd);
+#else
+    assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nNewRnd<=0xffffffff );
+    pNew = osMapViewOfFile(hMap, flags,
+                           (DWORD)((offset>>32) & 0xffffffff),
+                           (DWORD)(offset & 0xffffffff),
+                           (SIZE_T)nNewRnd);
+#endif
+    if( pNew==NULL ){
+      osCloseHandle(hMap);
+      hMap = NULL;
+      pFile->lastErrno = osGetLastError();
+      rc = winLogError(SQLITE_IOERR_MREMAP, pFile->lastErrno,
+                       "winMremap2", pFile->zPath);
+    }
+  }
+
+  pFile->hMap = hMap;
+  pFile->pMapRegion = pNew;
+  pFile->mmapSize = nNew;
+
+  *ppMap = pNew;
+  return rc;
+}
+
 /*
 ** Here ends the implementation of all sqlite3_file methods.
 **
@@ -3462,7 +3637,7 @@ shmpage_out:
 ** sqlite3_file for win32.
 */
 static const sqlite3_io_methods winIoMethod = {
-  2,                              /* iVersion */
+  3,                              /* iVersion */
   winClose,                       /* xClose */
   winRead,                        /* xRead */
   winWrite,                       /* xWrite */
@@ -3478,7 +3653,8 @@ static const sqlite3_io_methods winIoMethod = {
   winShmMap,                      /* xShmMap */
   winShmLock,                     /* xShmLock */
   winShmBarrier,                  /* xShmBarrier */
-  winShmUnmap                     /* xShmUnmap */
+  winShmUnmap,                    /* xShmUnmap */
+  winMremap,                      /* xMremap */
 };
 
 /****************************************************************************
@@ -3654,9 +3830,7 @@ static int winOpen(
   int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
   int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
   int isCreate     = (flags & SQLITE_OPEN_CREATE);
-#ifndef NDEBUG
   int isReadonly   = (flags & SQLITE_OPEN_READONLY);
-#endif
   int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
 
 #ifndef NDEBUG
@@ -3867,11 +4041,17 @@ static int winOpen(
   pFile->pMethod = &winIoMethod;
   pFile->pVfs = pVfs;
   pFile->h = h;
+  if( isReadonly ){
+    pFile->ctrlFlags |= WINFILE_RDONLY;
+  }
   if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
     pFile->ctrlFlags |= WINFILE_PSOW;
   }
   pFile->lastErrno = NO_ERROR;
   pFile->zPath = zName;
+  pFile->hMap = NULL;
+  pFile->pMapRegion = 0;
+  pFile->mmapSize = 0;
 
   OpenCounter(+1);
   return rc;
@@ -4500,7 +4680,6 @@ int sqlite3_os_init(void){
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
   assert( ArraySize(aSyscall)==74 );
 
-#ifndef SQLITE_OMIT_WAL
   /* get memory map allocation granularity */
   memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
 #if SQLITE_OS_WINRT
@@ -4508,8 +4687,8 @@ int sqlite3_os_init(void){
 #else
   osGetSystemInfo(&winSysInfo);
 #endif
-  assert(winSysInfo.dwAllocationGranularity > 0);
-#endif
+  assert( winSysInfo.dwAllocationGranularity>0 );
+  assert( winSysInfo.dwPageSize>0 );
 
   sqlite3_vfs_register(&winVfs, 1);
   return SQLITE_OK; 
index 500d60e0fe9de0d552cbdda81b07de46e40684f4..fb340f92d0280a01ec142340511e1fb17ea5b81f 100644 (file)
@@ -5844,6 +5844,7 @@ static int test_test_control(
   return TCL_OK;
 }
 
+#if SQLITE_OS_UNIX
 #include <sys/time.h>
 #include <sys/resource.h>
 
@@ -5866,6 +5867,7 @@ static int test_getrusage(
   Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
   return TCL_OK;
 }
+#endif
 
 #if SQLITE_OS_WIN
 /*
@@ -6256,7 +6258,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "print_explain_query_plan", test_print_eqp, 0  },
 #endif
      { "sqlite3_test_control", test_test_control },
+#if SQLITE_OS_UNIX
      { "getrusage", test_getrusage },
+#endif
   };
   static int bitmask_size = sizeof(Bitmask)*8;
   int i;