[Fix] AOF rewrite not working.
Fix for issue https://github.com/MSOpenTech/redis/issues/275 An existing fix was not working in Release mode because the compiler optimization was removing the code that forces the VEH to map the memory page.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c), Microsoft Open Technologies, Inc.
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "Win32_Common.h"
|
||||
|
||||
namespace Globals
|
||||
{
|
||||
size_t pageSize = 0;
|
||||
}
|
||||
|
||||
/* This function is used to force the VEH on the entire size of the buffer length,
|
||||
in the event that the buffer crosses the memory page boundaries */
|
||||
void EnsureMemoryIsMapped(const void *buffer, size_t size) {
|
||||
/* Use 'volatile' to make sure the compiler doesn't remove "c = *((char*) (p + offset));" */
|
||||
volatile char c;
|
||||
char* p = (char*) buffer;
|
||||
char* pStart = p - ((size_t) p % Globals::pageSize);
|
||||
char* pEnd = p + size;
|
||||
if ((size_t) (pEnd - pStart) > Globals::pageSize) {
|
||||
size_t offset = 0;
|
||||
while (offset < size) {
|
||||
if (size < offset) {
|
||||
offset = size;
|
||||
} else {
|
||||
offset += Globals::pageSize;
|
||||
}
|
||||
c = *((char*) (p + offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c), Microsoft Open Technologies, Inc.
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WIN32_COMMON_H
|
||||
#define WIN32_COMMON_H
|
||||
|
||||
void EnsureMemoryIsMapped(const void *buffer, size_t size);
|
||||
|
||||
namespace Globals {
|
||||
// forward declarations only
|
||||
extern size_t pageSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,7 @@
|
||||
<ClCompile Include="win32fixes.c" />
|
||||
<ClCompile Include="Win32_ANSI.c" />
|
||||
<ClCompile Include="Win32_CommandLine.cpp" />
|
||||
<ClCompile Include="Win32_Common.cpp" />
|
||||
<ClCompile Include="Win32_dlmalloc.c" />
|
||||
<ClCompile Include="Win32_EventLog.cpp" />
|
||||
<ClCompile Include="Win32_FDAPI.cpp" />
|
||||
@@ -45,6 +46,7 @@
|
||||
<ClInclude Include="Win32_EventLog.h" />
|
||||
<ClInclude Include="Win32_FDAPI.h" />
|
||||
<ClInclude Include="Win32_fdapi_crt.h" />
|
||||
<ClInclude Include="Win32_Common.h" />
|
||||
<ClInclude Include="Win32_QFork.h" />
|
||||
<ClInclude Include="Win32_QFork_impl.h" />
|
||||
<ClInclude Include="Win32_RedisLog.h" />
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "win32_types.h"
|
||||
#include "Win32_FDAPI.h"
|
||||
#include "Win32_Common.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <WinNT.h>
|
||||
@@ -161,7 +162,6 @@ const SIZE_T cAllocationGranularity = 1 << 18; // 256KB per h
|
||||
const int cMaxBlocks = 1 << 24; // 256KB * 16M heap blocks = 4TB. 4TB is the largest memory config Windows supports at present.
|
||||
const char* cMapFileBaseName = "RedisQFork";
|
||||
const int cDeadForkWait = 30000;
|
||||
size_t pageSize = 0;
|
||||
|
||||
#ifndef _WIN64
|
||||
size_t cDefaultmaxHeap32Bit = 1 << 29; // 512MB
|
||||
@@ -693,7 +693,7 @@ StartupStatus QForkStartup(int argc, char** argv) {
|
||||
::redisLog(REDIS_WARNING, "Failing startup.\n");
|
||||
return StartupStatus::ssFAILED;
|
||||
}
|
||||
pageSize = perfinfo.PageSize;
|
||||
Globals::pageSize = perfinfo.PageSize;
|
||||
|
||||
/*
|
||||
Not specifying the maxmemory or maxheap flags will result in the default behavior of: new key generation not
|
||||
@@ -740,7 +740,7 @@ StartupStatus QForkStartup(int argc, char** argv) {
|
||||
maxheapBytes = cSentinelHeapSize;
|
||||
} else {
|
||||
#ifdef _WIN64
|
||||
maxheapBytes = perfinfo.PhysicalTotal * pageSize;
|
||||
maxheapBytes = perfinfo.PhysicalTotal * Globals::pageSize;
|
||||
#else
|
||||
maxheapBytes = cDefaultmaxHeap32Bit;
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "Win32_fdapi_crt.h"
|
||||
#include "Win32_Common.h"
|
||||
#include <io.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -56,22 +57,14 @@ int crtsetmode(int fd, int mode) {
|
||||
return ::_setmode(fd, mode);
|
||||
}
|
||||
|
||||
size_t crt_fwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File) {
|
||||
size_t crt_fwrite(const void *buffer, size_t size, size_t count, FILE *file) {
|
||||
// fwrite() somehow locks its view of the buffer. If during a fork operation the buffer has not been loaded into the forkee's process space,
|
||||
// the VEH will be called to load the missing pages. Although the page gets loaded, fwrite() will not see the loaded page. The result is
|
||||
// that fwrite will fail with errno set to ERROR_INVALID_USER_BUFFER. The fix is to force the buffer into memory before fwrite(). This only
|
||||
// impacts wirites that straddle page boundaries.
|
||||
const intptr_t pageSize = 4096;
|
||||
char* p = (char*)_Str;
|
||||
char* pageStart = p - ((intptr_t)p % pageSize);
|
||||
char* pEnd = p + _Size;
|
||||
if ((intptr_t)(pEnd - pageStart) > pageSize) {
|
||||
for (size_t n = 0; n < _Size; n++) {
|
||||
char x = *((char*)_Str + n);
|
||||
}
|
||||
}
|
||||
// impacts writes that straddle page boundaries.
|
||||
EnsureMemoryIsMapped(buffer, size);
|
||||
return ::fwrite(buffer, size, count, file);
|
||||
|
||||
return ::fwrite(_Str, _Size, _Count, _File);
|
||||
}
|
||||
|
||||
int crt_fclose(FILE* file) {
|
||||
@@ -93,4 +86,3 @@ int crt_access(const char *pathname, int mode) {
|
||||
__int64 crt_lseek64(int fd, __int64 offset, int origin) {
|
||||
return _lseeki64(fd, offset, origin);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ int crt_open(const char *filename, int oflag, int pmode);
|
||||
int crt_open_osfhandle(intptr_t osfhandle, int flags);
|
||||
intptr_t crtget_osfhandle(int fd);
|
||||
int crtsetmode(int fd, int mode);
|
||||
size_t crt_fwrite(const void * _Str, size_t _Size, size_t _Count, FILE * _File);
|
||||
size_t crt_fwrite(const void *buffer, size_t size, size_t count, FILE *file);
|
||||
int crt_fclose(FILE* file);
|
||||
int crt_fileno(FILE* file);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user