From d90dbb8c1c44a3c1759afc7c88c771fe1295288e Mon Sep 17 00:00:00 2001 From: mistachkin Date: Thu, 29 Jun 2017 12:54:58 +0000 Subject: [PATCH] Implement xUnlink, xShmMap, and xShmUnmap for lsm1 on Win32. FossilOrigin-Name: 680cc064c9e809ddc643074b5e65677f484d904b3d52826f6def480ddaa8f0ab --- ext/lsm1/lsm_win32.c | 256 ++++++++++++++++++++++++++++++++++--------- manifest | 12 +- manifest.uuid | 2 +- 3 files changed, 210 insertions(+), 60 deletions(-) diff --git a/ext/lsm1/lsm_win32.c b/ext/lsm1/lsm_win32.c index af58176609..88b275f8e9 100644 --- a/ext/lsm1/lsm_win32.c +++ b/ext/lsm1/lsm_win32.c @@ -41,8 +41,9 @@ struct Win32File { HANDLE hMap; /* File handle for mapping */ LPVOID pMap; /* Pointer to mapping of file fd */ size_t nMap; /* Size of mapping at pMap in bytes */ - int nShm; /* Number of entries in array apShm[] */ - void **apShm; /* Array of 32K shared memory segments */ + int nShm; /* Number of entries in ahShm[]/apShm[] */ + LPHANDLE ahShm; /* Array of handles for shared mappings */ + LPVOID *apShm; /* Array of 32K shared memory segments */ }; static char *win32ShmFile(Win32File *p){ @@ -187,6 +188,57 @@ static char *win32UnicodeToUtf8(lsm_env *pEnv, LPCWSTR zWideText){ ((a)==ERROR_PATH_NOT_FOUND)) #endif +static int win32Open( + lsm_env *pEnv, + const char *zFile, + int flags, + LPHANDLE phFile +){ + int rc; + LPWSTR zConverted; + + zConverted = win32Utf8ToUnicode(pEnv, zFile); + if( zConverted==0 ){ + rc = LSM_NOMEM_BKPT; + }else{ + int bReadonly = (flags & LSM_OPEN_READONLY); + DWORD dwDesiredAccess; + DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + HANDLE hFile; + int nRetry = 0; + if( bReadonly ){ + dwDesiredAccess = GENERIC_READ; + dwCreationDisposition = OPEN_EXISTING; + }else{ + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + dwCreationDisposition = OPEN_ALWAYS; + } + while( (hFile = CreateFileW((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL))==INVALID_HANDLE_VALUE && + win32RetryIoerr(pEnv, &nRetry) ){ + /* Noop */ + } + lsmFree(pEnv, zConverted); + if( hFile!=INVALID_HANDLE_VALUE ){ + *phFile = hFile; + rc = LSM_OK; + }else{ + if( win32IsNotFound(GetLastError()) ){ + rc = lsmErrorBkpt(LSM_IOERR_NOENT); + }else{ + rc = LSM_IOERR_BKPT; + } + } + } + return rc; +} + static int lsmWin32OsOpen( lsm_env *pEnv, const char *zFile, @@ -200,51 +252,16 @@ static int lsmWin32OsOpen( if( pWin32File==0 ){ rc = LSM_NOMEM_BKPT; }else{ - LPWSTR zConverted; - int bReadonly = (flags & LSM_OPEN_READONLY); - DWORD dwDesiredAccess; - DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - DWORD dwCreationDisposition; - DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; HANDLE hFile; - zConverted = win32Utf8ToUnicode(pEnv, zFile); - if( zConverted==0 ){ + rc = win32Open(pEnv, zFile, flags, &hFile); + if( rc==LSM_OK ){ + pWin32File->pEnv = pEnv; + pWin32File->zName = zFile; + pWin32File->hFile = hFile; + }else{ lsmFree(pEnv, pWin32File); pWin32File = 0; - rc = LSM_NOMEM_BKPT; - }else{ - int nRetry = 0; - if( bReadonly ){ - dwDesiredAccess = GENERIC_READ; - dwCreationDisposition = OPEN_EXISTING; - }else{ - dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - dwCreationDisposition = OPEN_ALWAYS; - } - while( (hFile = CreateFileW((LPCWSTR)zConverted, - dwDesiredAccess, - dwShareMode, NULL, - dwCreationDisposition, - dwFlagsAndAttributes, - NULL))==INVALID_HANDLE_VALUE && - win32RetryIoerr(pEnv, &nRetry) ){ - /* Noop */ - } - lsmFree(pEnv, zConverted); - if( hFile!=INVALID_HANDLE_VALUE ){ - pWin32File->pEnv = pEnv; - pWin32File->zName = zFile; - pWin32File->hFile = hFile; - }else{ - lsmFree(pEnv, pWin32File); - pWin32File = 0; - if( win32IsNotFound(GetLastError()) ){ - rc = lsmErrorBkpt(LSM_IOERR_NOENT); - }else{ - rc = LSM_IOERR_BKPT; - } - } } } *ppFile = (lsm_file *)pWin32File; @@ -286,23 +303,29 @@ static int lsmWin32OsWrite( return LSM_OK; } -static int lsmWin32OsTruncate( - lsm_file *pFile, /* File to write to */ - lsm_i64 nSize /* Size to truncate file to */ +static int win32Truncate( + HANDLE hFile, + lsm_i64 nSize ){ - Win32File *pWin32File = (Win32File *)pFile; LARGE_INTEGER offset; - offset.QuadPart = nSize; - if( !SetFilePointerEx(pWin32File->hFile, offset, 0, FILE_BEGIN) ){ + if( !SetFilePointerEx(hFile, offset, 0, FILE_BEGIN) ){ return LSM_IOERR_BKPT; } - if (!SetEndOfFile(pWin32File->hFile) ){ + if (!SetEndOfFile(hFile) ){ return LSM_IOERR_BKPT; } return LSM_OK; } +static int lsmWin32OsTruncate( + lsm_file *pFile, /* File to write to */ + lsm_i64 nSize /* Size to truncate file to */ +){ + Win32File *pWin32File = (Win32File *)pFile; + return win32Truncate(pWin32File->hFile, nSize); +} + static int lsmWin32OsRead( lsm_file *pFile, /* File to read from */ lsm_i64 iOff, /* Offset to read from */ @@ -508,8 +531,47 @@ static int lsmWin32OsFileid( return LSM_OK; } +static int win32Delete( + lsm_env *pEnv, + const char *zFile +){ + int rc; + LPWSTR zConverted; + + zConverted = win32Utf8ToUnicode(pEnv, zFile); + if( zConverted==0 ){ + rc = LSM_NOMEM_BKPT; + }else{ + int nRetry = 0; + DWORD attr; + DWORD lastErrno; + + do { + attr = GetFileAttributesW(zConverted); + if ( attr==INVALID_FILE_ATTRIBUTES ){ + rc = LSM_IOERR_BKPT; + break; + } + if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ + rc = LSM_IOERR_BKPT; /* Files only. */ + break; + } + if ( DeleteFileW(zConverted) ){ + rc = LSM_OK; /* Deleted OK. */ + break; + } + if ( !win32RetryIoerr(pEnv, &nRetry) ){ + rc = LSM_IOERR_BKPT; /* No more retries. */ + break; + } + }while( 1 ); + } + lsmFree(pEnv, zConverted); + return rc; +} + static int lsmWin32OsUnlink(lsm_env *pEnv, const char *zFile){ - return LSM_ERROR; + return win32Delete(pEnv, zFile); } int lsmWin32OsLock(lsm_file *pFile, int iLock, int eType){ @@ -569,7 +631,73 @@ int lsmWin32OsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){ } int lsmWin32OsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){ - return LSM_ERROR; + int rc; + Win32File *pWin32File = (Win32File *)pFile; + + *ppShm = NULL; + assert( sz>=0 ); + assert( sz==LSM_SHM_CHUNK_SIZE ); + if( iChunk>=pWin32File->nShm ){ + int i; + void **apNew; + int nNew = iChunk+1; + lsm_i64 nReq = nNew * sz; + LARGE_INTEGER fileSize; + + /* If the shared-memory file has not been opened, open it now. */ + if( pWin32File->hShmFile==NULL ){ + char *zShm = win32ShmFile(pWin32File); + if( !zShm ) return LSM_NOMEM_BKPT; + rc = win32Open(pWin32File->pEnv, zShm, 0, &pWin32File->hShmFile); + lsmFree(pWin32File->pEnv, zShm); + if( rc!=LSM_OK ){ + return rc; + } + } + + /* If the shared-memory file is not large enough to contain the + ** requested chunk, cause it to grow. */ + memset(&fileSize, 0, sizeof(LARGE_INTEGER)); + if( !GetFileSizeEx(pWin32File->hShmFile, &fileSize) ){ + return LSM_IOERR_BKPT; + } + assert( fileSize.QuadPart>=0 ); + if( fileSize.QuadParthShmFile, nReq); + if( rc!=LSM_OK ){ + return rc; + } + } + + apNew = (void **)lsmRealloc(pWin32File->pEnv, pWin32File->apShm, + sizeof(LPVOID) * nNew); + if( !apNew ) return LSM_NOMEM_BKPT; + for(i=pWin32File->nShm; iapShm = apNew; + pWin32File->nShm = nNew; + } + + if( pWin32File->apShm[iChunk]==NULL ){ + HANDLE hMap; + LPVOID pMap; + hMap = CreateFileMappingW(pWin32File->hShmFile, NULL, PAGE_READWRITE, 0, + (DWORD)sz, NULL); + if( hMap==NULL ){ + return LSM_IOERR_BKPT; + } + pWin32File->ahShm[iChunk] = hMap; + pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, + (SIZE_T)sz); + if( pMap==NULL ){ + return LSM_IOERR_BKPT; + } + pWin32File->apShm[iChunk] = pMap; + pWin32File->nMap = (SIZE_T)sz; + } + *ppShm = pWin32File->apShm[iChunk]; + return LSM_OK; } void lsmWin32OsShmBarrier(void){ @@ -577,7 +705,29 @@ void lsmWin32OsShmBarrier(void){ } int lsmWin32OsShmUnmap(lsm_file *pFile, int bDelete){ - return LSM_ERROR; + Win32File *pWin32File = (Win32File *)pFile; + + if( pWin32File->hShmFile!=NULL ){ + int i; + for(i=0; inShm; i++){ + if( pWin32File->apShm[i]!=NULL ){ + UnmapViewOfFile(pWin32File->apShm[i]); + pWin32File->apShm[i] = NULL; + } + if( pWin32File->ahShm[i]!=NULL ){ + CloseHandle(pWin32File->ahShm[i]); + pWin32File->ahShm[i] = NULL; + } + } + CloseHandle(pWin32File->hShmFile); + pWin32File->hShmFile = 0; + if( bDelete ){ + char *zShm = win32ShmFile(pWin32File); + if( zShm ){ win32Delete(pWin32File->pEnv, zShm); } + lsmFree(pWin32File->pEnv, zShm); + } + } + return LSM_OK; } #define MX_CLOSE_ATTEMPT 3 diff --git a/manifest b/manifest index 6fee259a7a..7973b1262a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Implement\sxRemap\sfor\slsm1\son\sWin32.\s\sAlso,\szero\sfile\shandle\swhen\sclosing\sit. -D 2017-06-29T00:20:42.289 +C Implement\sxUnlink,\sxShmMap,\sand\sxShmUnmap\sfor\slsm1\son\sWin32. +D 2017-06-29T12:54:58.254 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d389c6fb3344ea6887b386d56784a6d8a5c85107294448aeda50ac404285a1ef @@ -249,7 +249,7 @@ F ext/lsm1/lsm_tree.c 5d9fb2bc58a1a70c75126bd8d7198f7b627e165b F ext/lsm1/lsm_unix.c ee0201dff10ce2008ef13a65f52a6ea348f287e795270f651596f812fcfccdcc F ext/lsm1/lsm_varint.c b19ae9bd26b5a1e8402fb8a564b25d9542338a41 F ext/lsm1/lsm_vtab.c fff303ce03168eca9e333add3c1429b3471674b0 -F ext/lsm1/lsm_win32.c 4896cd8af7a65dcd2b2dacca81455be896130b23ca19cf4a7e3f6eed5442d812 +F ext/lsm1/lsm_win32.c bd3f7e82ec71ad09a1487d5b64fbc03e99398dc7e8ec0160b9cd0deb3ce4421c F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2 F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb @@ -1624,7 +1624,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 9112117dad8085c385aa614cd982b307f5822761607ba358f34df7848c549134 -R 887ca9ca211e19ac7f1bf925dfe592df +P 93c9aa7d9aea46b331c53ff579ef704e88ce90f96600b69479a87a4bb4ca2a91 +R c37c412a3ae97e64852f2f71114bfb03 U mistachkin -Z 2dc70b160b5c8095c4a09a655916e2c6 +Z 58e908e3128eb99a98afbb7831a85730 diff --git a/manifest.uuid b/manifest.uuid index 63f7e3d038..f40f6d75a8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -93c9aa7d9aea46b331c53ff579ef704e88ce90f96600b69479a87a4bb4ca2a91 \ No newline at end of file +680cc064c9e809ddc643074b5e65677f484d904b3d52826f6def480ddaa8f0ab \ No newline at end of file -- 2.39.5