/ Check-in [38cbcedb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Experimental changes to pre-cache a database file prior to it being fully opened.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | winPreCache
Files: files | file ages | folders
SHA1: 38cbcedbb6e57dc3c2d452a0eb573cabc7df0c75
User & Date: mistachkin 2014-05-08 22:01:26
Context
2014-05-08
22:05
Update comments and only include the thread routine when required. check-in: a60c545f user: mistachkin tags: winPreCache
22:01
Experimental changes to pre-cache a database file prior to it being fully opened. check-in: 38cbcedb user: mistachkin tags: winPreCache
22:01
Fix static variable declaration issue on Windows. check-in: a41d2969 user: mistachkin tags: threads
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_win.c.

   263    263     int nFetchOut;                /* Number of outstanding xFetch references */
   264    264     HANDLE hMap;                  /* Handle for accessing memory mapping */
   265    265     void *pMapRegion;             /* Area memory mapped */
   266    266     sqlite3_int64 mmapSize;       /* Usable size of mapped region */
   267    267     sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
   268    268     sqlite3_int64 mmapSizeMax;    /* Configured FCNTL_MMAP_SIZE value */
   269    269   #endif
          270  +  SQLiteThread *preCacheThread; /* Thread used to pre-cache file contents */
   270    271   };
   271    272   
   272    273   /*
   273    274   ** Allowed values for winFile.ctrlFlags
   274    275   */
   275    276   #define WINFILE_RDONLY          0x02   /* Connection is read only */
   276    277   #define WINFILE_PERSIST_WAL     0x04   /* Persistent WAL mode */
................................................................................
  1040   1041   #else
  1041   1042     { "CreateFileMappingFromApp", (SYSCALL)0,                      0 },
  1042   1043   #endif
  1043   1044   
  1044   1045   #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
  1045   1046           LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
  1046   1047   
         1048  +  { "DuplicateHandle",          (SYSCALL)DuplicateHandle,        0 },
         1049  +
         1050  +#define osDuplicateHandle ((BOOL(WINAPI*)(HANDLE, \
         1051  +        HANDLE,HANDLE,LPHANDLE,DWORD,BOOL,DWORD))aSyscall[76].pCurrent)
         1052  +
  1047   1053   }; /* End of the overrideable system calls */
  1048   1054   
  1049   1055   /*
  1050   1056   ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
  1051   1057   ** "win32" VFSes.  Return SQLITE_OK opon successfully updating the
  1052   1058   ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
  1053   1059   ** system call named zName.
................................................................................
  2349   2355   
  2350   2356     assert( id!=0 );
  2351   2357   #ifndef SQLITE_OMIT_WAL
  2352   2358     assert( pFile->pShm==0 );
  2353   2359   #endif
  2354   2360     assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
  2355   2361     OSTRACE(("CLOSE file=%p\n", pFile->h));
         2362  +
         2363  +#if SQLITE_MAX_WORKER_THREADS>0
         2364  +  if( pFile->preCacheThread ){
         2365  +    void *pOut = 0;
         2366  +    sqlite3ThreadJoin(pFile->preCacheThread, &pOut);
         2367  +  }
         2368  +#endif
  2356   2369   
  2357   2370   #if SQLITE_MAX_MMAP_SIZE>0
  2358   2371     winUnmapfile(pFile);
  2359   2372   #endif
  2360   2373   
  2361   2374     do{
  2362   2375       rc = osCloseHandle(pFile->h);
................................................................................
  3193   3206   ** Return a vector of device characteristics.
  3194   3207   */
  3195   3208   static int winDeviceCharacteristics(sqlite3_file *id){
  3196   3209     winFile *p = (winFile*)id;
  3197   3210     return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
  3198   3211            ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
  3199   3212   }
         3213  +
         3214  +/*
         3215  +** Thread routine that seeks to the end of an open file and reads one byte.
         3216  +** This is used to provide a hint to the operating system that the entire
         3217  +** file should be held in the cache.
         3218  +*/
         3219  +static void *winPreCacheThread(void *pCtx){
         3220  +  winFile *pFile = (winFile*)pCtx;
         3221  +  void *pBuf = 0;
         3222  +  DWORD lastErrno;
         3223  +  HANDLE dupHandle = NULL;
         3224  +  DWORD dwSize, dwRet;
         3225  +  DWORD dwAmt;
         3226  +  DWORD nRead;
         3227  +
         3228  +  if( !osDuplicateHandle(GetCurrentProcess(), pFile->h, GetCurrentProcess(),
         3229  +                         &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) ){
         3230  +    pFile->lastErrno = osGetLastError();
         3231  +    OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR\n", dupHandle));
         3232  +    return winLogError(SQLITE_IOERR, pFile->lastErrno,
         3233  +                       "winPreCacheThread1", pFile->zPath);
         3234  +  }
         3235  +  dwSize = osSetFilePointer(dupHandle, 0, 0, FILE_END);
         3236  +  if( (dwSize==INVALID_SET_FILE_POINTER
         3237  +      && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
         3238  +    pFile->lastErrno = lastErrno;
         3239  +    osCloseHandle(dupHandle);
         3240  +    OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_SEEK\n", dupHandle));
         3241  +    return winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
         3242  +                       "winPreCacheThread2", pFile->zPath);
         3243  +  }
         3244  +  dwRet = osSetFilePointer(dupHandle, 0, 0, FILE_BEGIN);
         3245  +  if( (dwRet==INVALID_SET_FILE_POINTER
         3246  +      && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
         3247  +    pFile->lastErrno = lastErrno;
         3248  +    osCloseHandle(dupHandle);
         3249  +    OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_SEEK\n", dupHandle));
         3250  +    return winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
         3251  +                       "winPreCacheThread2", pFile->zPath);
         3252  +  }
         3253  +  dwAmt = 4194304; /* TODO: Tuning. */
         3254  +  if( dwSize<dwAmt ){
         3255  +    dwAmt = dwSize;
         3256  +  }
         3257  +  pBuf = sqlite3MallocZero( dwAmt );
         3258  +  if( pBuf==0 ){
         3259  +    osCloseHandle(dupHandle);
         3260  +    OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_NOMEM\n", dupHandle));
         3261  +    return SQLITE_IOERR_NOMEM;
         3262  +  }
         3263  +  while( 1 ){
         3264  +    if( !osReadFile(dupHandle, pBuf, dwAmt, &nRead, 0) ){
         3265  +      pFile->lastErrno = osGetLastError();
         3266  +      osCloseHandle(dupHandle);
         3267  +      OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_READ\n", dupHandle));
         3268  +      return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
         3269  +                         "winPreCacheThread3", pFile->zPath);
         3270  +    }
         3271  +    if( nRead<dwAmt ){
         3272  +      osCloseHandle(dupHandle);
         3273  +      OSTRACE(("PRE-CACHE file=%p, rc=SQLITE_IOERR_SHORT_READ\n", dupHandle));
         3274  +      return winLogError(SQLITE_IOERR_SHORT_READ, pFile->lastErrno,
         3275  +                         "winPreCacheThread4", pFile->zPath);
         3276  +    }
         3277  +    dwSize -= dwAmt;
         3278  +    if( dwSize==0 ){
         3279  +      break;
         3280  +    }
         3281  +  }
         3282  +  osCloseHandle(dupHandle);
         3283  +  return SQLITE_OK;
         3284  +}
  3200   3285   
  3201   3286   /* 
  3202   3287   ** Windows will only let you create file view mappings
  3203   3288   ** on allocation size granularity boundaries.
  3204   3289   ** During sqlite3_os_init() we do a GetSystemInfo()
  3205   3290   ** to get the granularity size.
  3206   3291   */
................................................................................
  4700   4785   #if SQLITE_MAX_MMAP_SIZE>0
  4701   4786     pFile->hMap = NULL;
  4702   4787     pFile->pMapRegion = 0;
  4703   4788     pFile->mmapSize = 0;
  4704   4789     pFile->mmapSizeActual = 0;
  4705   4790     pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
  4706   4791   #endif
         4792  +#if SQLITE_MAX_WORKER_THREADS>0
         4793  +  sqlite3ThreadCreate(&pFile->preCacheThread, winPreCacheThread, pFile);
         4794  +
         4795  +  {
         4796  +    void *pOut = 0;
         4797  +    sqlite3ThreadJoin(pFile->preCacheThread, &pOut);
         4798  +    pFile->preCacheThread = 0;
         4799  +  }
         4800  +#endif
  4707   4801   
  4708   4802     OpenCounter(+1);
  4709   4803     return rc;
  4710   4804   }
  4711   4805   
  4712   4806   /*
  4713   4807   ** Delete the named file.
................................................................................
  5418   5512       winGetSystemCall,    /* xGetSystemCall */
  5419   5513       winNextSystemCall,   /* xNextSystemCall */
  5420   5514     };
  5421   5515   #endif
  5422   5516   
  5423   5517     /* Double-check that the aSyscall[] array has been constructed
  5424   5518     ** correctly.  See ticket [bb3a86e890c8e96ab] */
  5425         -  assert( ArraySize(aSyscall)==76 );
         5519  +  assert( ArraySize(aSyscall)==77 );
  5426   5520   
  5427   5521     /* get memory map allocation granularity */
  5428   5522     memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
  5429   5523   #if SQLITE_OS_WINRT
  5430   5524     osGetNativeSystemInfo(&winSysInfo);
  5431   5525   #else
  5432   5526     osGetSystemInfo(&winSysInfo);