summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/mmap_v1/mmap_windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/mmap_v1/mmap_windows.cpp')
-rw-r--r--src/mongo/db/storage/mmap_v1/mmap_windows.cpp762
1 files changed, 368 insertions, 394 deletions
diff --git a/src/mongo/db/storage/mmap_v1/mmap_windows.cpp b/src/mongo/db/storage/mmap_v1/mmap_windows.cpp
index 2969028575a..88abedd9c77 100644
--- a/src/mongo/db/storage/mmap_v1/mmap_windows.cpp
+++ b/src/mongo/db/storage/mmap_v1/mmap_windows.cpp
@@ -43,498 +43,472 @@
namespace mongo {
- using std::endl;
- using std::string;
- using std::vector;
+using std::endl;
+using std::string;
+using std::vector;
- namespace {
- mongo::AtomicUInt64 mmfNextId(0);
- }
+namespace {
+mongo::AtomicUInt64 mmfNextId(0);
+}
- static size_t fetchMinOSPageSizeBytes() {
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- size_t minOSPageSizeBytes = si.dwPageSize;
- minOSPageSizeBytesTest(minOSPageSizeBytes);
- return minOSPageSizeBytes;
- }
- const size_t g_minOSPageSizeBytes = fetchMinOSPageSizeBytes();
-
- // MapViewMutex
- //
- // Protects:
- // 1. Ensures all MapViewOfFile/UnMapViewOfFile operations are serialized to reduce chance of
- // "address in use" errors (error code 487)
- // - These errors can still occur if the memory is used for other purposes
- // (stack storage, heap)
- // 2. Prevents calls to VirtualProtect while we remapping files.
- // Lock Ordering:
- // - If taken, must be after previewViews._m to prevent deadlocks
- stdx::mutex mapViewMutex;
-
- MAdvise::MAdvise(void *,unsigned, Advice) { }
- MAdvise::~MAdvise() { }
-
- const unsigned long long memoryMappedFileLocationFloor = 256LL * 1024LL * 1024LL * 1024LL;
- static unsigned long long _nextMemoryMappedFileLocation = memoryMappedFileLocationFloor;
-
- // nextMemoryMappedFileLocationMutex
- //
- // Protects:
- // Windows 64-bit specific allocation of virtual memory regions for
- // placing memory mapped files in memory
- // Lock Ordering:
- // No restrictions
- static SimpleMutex _nextMemoryMappedFileLocationMutex;
-
- unsigned long long AlignNumber(unsigned long long number, unsigned long long granularity)
- {
- return (number + granularity - 1) & ~(granularity - 1);
+static size_t fetchMinOSPageSizeBytes() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ size_t minOSPageSizeBytes = si.dwPageSize;
+ minOSPageSizeBytesTest(minOSPageSizeBytes);
+ return minOSPageSizeBytes;
+}
+const size_t g_minOSPageSizeBytes = fetchMinOSPageSizeBytes();
+
+// MapViewMutex
+//
+// Protects:
+// 1. Ensures all MapViewOfFile/UnMapViewOfFile operations are serialized to reduce chance of
+// "address in use" errors (error code 487)
+// - These errors can still occur if the memory is used for other purposes
+// (stack storage, heap)
+// 2. Prevents calls to VirtualProtect while we remapping files.
+// Lock Ordering:
+// - If taken, must be after previewViews._m to prevent deadlocks
+stdx::mutex mapViewMutex;
+
+MAdvise::MAdvise(void*, unsigned, Advice) {}
+MAdvise::~MAdvise() {}
+
+const unsigned long long memoryMappedFileLocationFloor = 256LL * 1024LL * 1024LL * 1024LL;
+static unsigned long long _nextMemoryMappedFileLocation = memoryMappedFileLocationFloor;
+
+// nextMemoryMappedFileLocationMutex
+//
+// Protects:
+// Windows 64-bit specific allocation of virtual memory regions for
+// placing memory mapped files in memory
+// Lock Ordering:
+// No restrictions
+static SimpleMutex _nextMemoryMappedFileLocationMutex;
+
+unsigned long long AlignNumber(unsigned long long number, unsigned long long granularity) {
+ return (number + granularity - 1) & ~(granularity - 1);
+}
+
+static void* getNextMemoryMappedFileLocation(unsigned long long mmfSize) {
+ if (4 == sizeof(void*)) {
+ return 0;
}
+ stdx::lock_guard<SimpleMutex> lk(_nextMemoryMappedFileLocationMutex);
- static void* getNextMemoryMappedFileLocation(unsigned long long mmfSize) {
- if (4 == sizeof(void*)) {
- return 0;
- }
- stdx::lock_guard<SimpleMutex> lk(_nextMemoryMappedFileLocationMutex);
+ static unsigned long long granularity = 0;
- static unsigned long long granularity = 0;
+ if (0 == granularity) {
+ SYSTEM_INFO systemInfo;
+ GetSystemInfo(&systemInfo);
+ granularity = static_cast<unsigned long long>(systemInfo.dwAllocationGranularity);
+ }
- if (0 == granularity) {
- SYSTEM_INFO systemInfo;
- GetSystemInfo(&systemInfo);
- granularity = static_cast<unsigned long long>(systemInfo.dwAllocationGranularity);
- }
+ unsigned long long thisMemoryMappedFileLocation = _nextMemoryMappedFileLocation;
- unsigned long long thisMemoryMappedFileLocation = _nextMemoryMappedFileLocation;
+ int current_retry = 1;
- int current_retry = 1;
+ while (true) {
+ MEMORY_BASIC_INFORMATION memInfo;
- while (true) {
- MEMORY_BASIC_INFORMATION memInfo;
-
- if (VirtualQuery(reinterpret_cast<LPCVOID>(thisMemoryMappedFileLocation),
- &memInfo, sizeof(memInfo)) == 0) {
- DWORD gle = GetLastError();
-
- // If we exceed the limits of Virtual Memory
- // - 8TB before Windows 8.1/2012 R2, 128 TB after
- // restart scanning from our memory mapped floor once more
- // This is a linear scan of regions, not of every VM page
- if (gle == ERROR_INVALID_PARAMETER && current_retry == 1) {
- thisMemoryMappedFileLocation = memoryMappedFileLocationFloor;
- ++current_retry;
- continue;
- }
+ if (VirtualQuery(reinterpret_cast<LPCVOID>(thisMemoryMappedFileLocation),
+ &memInfo,
+ sizeof(memInfo)) == 0) {
+ DWORD gle = GetLastError();
- log() << "VirtualQuery of " << thisMemoryMappedFileLocation
- << " failed with error " << errnoWithDescription(gle);
- fassertFailed(17484);
+ // If we exceed the limits of Virtual Memory
+ // - 8TB before Windows 8.1/2012 R2, 128 TB after
+ // restart scanning from our memory mapped floor once more
+ // This is a linear scan of regions, not of every VM page
+ if (gle == ERROR_INVALID_PARAMETER && current_retry == 1) {
+ thisMemoryMappedFileLocation = memoryMappedFileLocationFloor;
+ ++current_retry;
+ continue;
}
- // Free memory regions that we can use for memory map files
- // 1. Marked MEM_FREE, not MEM_RESERVE
- // 2. Marked as PAGE_NOACCESS, not anything else
- if (memInfo.Protect == PAGE_NOACCESS &&
- memInfo.State == MEM_FREE &&
- memInfo.RegionSize > mmfSize)
- break;
-
- thisMemoryMappedFileLocation = reinterpret_cast<unsigned long long>(memInfo.BaseAddress)
- + memInfo.RegionSize;
+ log() << "VirtualQuery of " << thisMemoryMappedFileLocation << " failed with error "
+ << errnoWithDescription(gle);
+ fassertFailed(17484);
}
- _nextMemoryMappedFileLocation = thisMemoryMappedFileLocation
- + AlignNumber(mmfSize, granularity);
+ // Free memory regions that we can use for memory map files
+ // 1. Marked MEM_FREE, not MEM_RESERVE
+ // 2. Marked as PAGE_NOACCESS, not anything else
+ if (memInfo.Protect == PAGE_NOACCESS && memInfo.State == MEM_FREE &&
+ memInfo.RegionSize > mmfSize)
+ break;
- return reinterpret_cast<void*>(static_cast<uintptr_t>(thisMemoryMappedFileLocation));
+ thisMemoryMappedFileLocation =
+ reinterpret_cast<unsigned long long>(memInfo.BaseAddress) + memInfo.RegionSize;
}
- MemoryMappedFile::MemoryMappedFile()
- : _uniqueId(mmfNextId.fetchAndAdd(1)),
- fd(0),
- maphandle(0),
- len(0) {
+ _nextMemoryMappedFileLocation =
+ thisMemoryMappedFileLocation + AlignNumber(mmfSize, granularity);
- created();
- }
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(thisMemoryMappedFileLocation));
+}
- void MemoryMappedFile::close() {
- LockMongoFilesShared::assertExclusivelyLocked();
+MemoryMappedFile::MemoryMappedFile()
+ : _uniqueId(mmfNextId.fetchAndAdd(1)), fd(0), maphandle(0), len(0) {
+ created();
+}
- // Prevent flush and close from concurrently running
- stdx::lock_guard<stdx::mutex> lk(_flushMutex);
+void MemoryMappedFile::close() {
+ LockMongoFilesShared::assertExclusivelyLocked();
- {
- stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
+ // Prevent flush and close from concurrently running
+ stdx::lock_guard<stdx::mutex> lk(_flushMutex);
- for (vector<void*>::iterator i = views.begin(); i != views.end(); i++) {
- UnmapViewOfFile(*i);
- }
- }
+ {
+ stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
- views.clear();
- if ( maphandle )
- CloseHandle(maphandle);
- maphandle = 0;
- if ( fd )
- CloseHandle(fd);
- fd = 0;
- destroyed(); // cleans up from the master list of mmaps
+ for (vector<void*>::iterator i = views.begin(); i != views.end(); i++) {
+ UnmapViewOfFile(*i);
+ }
}
- unsigned long long mapped = 0;
+ views.clear();
+ if (maphandle)
+ CloseHandle(maphandle);
+ maphandle = 0;
+ if (fd)
+ CloseHandle(fd);
+ fd = 0;
+ destroyed(); // cleans up from the master list of mmaps
+}
- void* MemoryMappedFile::createReadOnlyMap() {
- verify( maphandle );
+unsigned long long mapped = 0;
- stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
+void* MemoryMappedFile::createReadOnlyMap() {
+ verify(maphandle);
- void* readOnlyMapAddress = NULL;
- int current_retry = 0;
+ stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
- while (true) {
+ void* readOnlyMapAddress = NULL;
+ int current_retry = 0;
- LPVOID thisAddress = getNextMemoryMappedFileLocation(len);
+ while (true) {
+ LPVOID thisAddress = getNextMemoryMappedFileLocation(len);
- readOnlyMapAddress = MapViewOfFileEx(
- maphandle, // file mapping handle
- FILE_MAP_READ, // access
- 0, 0, // file offset, high and low
- 0, // bytes to map, 0 == all
- thisAddress); // address to place file
+ readOnlyMapAddress = MapViewOfFileEx(maphandle, // file mapping handle
+ FILE_MAP_READ, // access
+ 0,
+ 0, // file offset, high and low
+ 0, // bytes to map, 0 == all
+ thisAddress); // address to place file
- if (0 == readOnlyMapAddress) {
- DWORD dosError = GetLastError();
-
- ++current_retry;
-
- // If we failed to allocate a memory mapped file, try again in case we picked
- // an address that Windows is also trying to use for some other VM allocations
- if (dosError == ERROR_INVALID_ADDRESS && current_retry < 5) {
- continue;
- }
+ if (0 == readOnlyMapAddress) {
+ DWORD dosError = GetLastError();
- log() << "MapViewOfFileEx for " << filename()
- << " at address " << thisAddress
- << " failed with error " << errnoWithDescription(dosError)
- << " (file size is " << len << ")"
- << " in MemoryMappedFile::createReadOnlyMap"
- << endl;
+ ++current_retry;
- fassertFailed(16165);
+ // If we failed to allocate a memory mapped file, try again in case we picked
+ // an address that Windows is also trying to use for some other VM allocations
+ if (dosError == ERROR_INVALID_ADDRESS && current_retry < 5) {
+ continue;
}
- break;
+ log() << "MapViewOfFileEx for " << filename() << " at address " << thisAddress
+ << " failed with error " << errnoWithDescription(dosError) << " (file size is "
+ << len << ")"
+ << " in MemoryMappedFile::createReadOnlyMap" << endl;
+
+ fassertFailed(16165);
}
- views.push_back( readOnlyMapAddress );
- return readOnlyMapAddress;
+ break;
}
- void* MemoryMappedFile::map(const char *filenameIn, unsigned long long &length, int options) {
- verify( fd == 0 && len == 0 ); // can't open more than once
- setFilename(filenameIn);
- FileAllocator::get()->allocateAsap( filenameIn, length );
- /* big hack here: Babble uses db names with colons. doesn't seem to work on windows. temporary perhaps. */
- char filename[256];
- strncpy(filename, filenameIn, 255);
- filename[255] = 0;
- {
- size_t len = strlen( filename );
- for ( size_t i=len-1; i>=0; i-- ) {
- if ( filename[i] == '/' ||
- filename[i] == '\\' )
- break;
+ views.push_back(readOnlyMapAddress);
+ return readOnlyMapAddress;
+}
- if ( filename[i] == ':' )
- filename[i] = '_';
- }
+void* MemoryMappedFile::map(const char* filenameIn, unsigned long long& length, int options) {
+ verify(fd == 0 && len == 0); // can't open more than once
+ setFilename(filenameIn);
+ FileAllocator::get()->allocateAsap(filenameIn, length);
+ /* big hack here: Babble uses db names with colons. doesn't seem to work on windows. temporary perhaps. */
+ char filename[256];
+ strncpy(filename, filenameIn, 255);
+ filename[255] = 0;
+ {
+ size_t len = strlen(filename);
+ for (size_t i = len - 1; i >= 0; i--) {
+ if (filename[i] == '/' || filename[i] == '\\')
+ break;
+
+ if (filename[i] == ':')
+ filename[i] = '_';
}
+ }
- updateLength( filename, length );
+ updateLength(filename, length);
- {
- DWORD createOptions = FILE_ATTRIBUTE_NORMAL;
- if ( options & SEQUENTIAL )
- createOptions |= FILE_FLAG_SEQUENTIAL_SCAN;
- DWORD rw = GENERIC_READ | GENERIC_WRITE;
- fd = CreateFileW(
- toWideString(filename).c_str(),
- rw, // desired access
- FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode
- NULL, // security
- OPEN_ALWAYS, // create disposition
- createOptions , // flags
- NULL); // hTempl
- if ( fd == INVALID_HANDLE_VALUE ) {
- DWORD dosError = GetLastError();
- log() << "CreateFileW for " << filename
- << " failed with " << errnoWithDescription( dosError )
- << " (file size is " << length << ")"
- << " in MemoryMappedFile::map"
- << endl;
- return 0;
- }
+ {
+ DWORD createOptions = FILE_ATTRIBUTE_NORMAL;
+ if (options & SEQUENTIAL)
+ createOptions |= FILE_FLAG_SEQUENTIAL_SCAN;
+ DWORD rw = GENERIC_READ | GENERIC_WRITE;
+ fd = CreateFileW(toWideString(filename).c_str(),
+ rw, // desired access
+ FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode
+ NULL, // security
+ OPEN_ALWAYS, // create disposition
+ createOptions, // flags
+ NULL); // hTempl
+ if (fd == INVALID_HANDLE_VALUE) {
+ DWORD dosError = GetLastError();
+ log() << "CreateFileW for " << filename << " failed with "
+ << errnoWithDescription(dosError) << " (file size is " << length << ")"
+ << " in MemoryMappedFile::map" << endl;
+ return 0;
}
+ }
- mapped += length;
+ mapped += length;
- {
- DWORD flProtect = PAGE_READWRITE; //(options & READONLY)?PAGE_READONLY:PAGE_READWRITE;
- maphandle = CreateFileMappingW(fd, NULL, flProtect,
- length >> 32 /*maxsizehigh*/,
- (unsigned) length /*maxsizelow*/,
- NULL/*lpName*/);
- if ( maphandle == NULL ) {
- DWORD dosError = GetLastError();
- log() << "CreateFileMappingW for " << filename
- << " failed with " << errnoWithDescription( dosError )
- << " (file size is " << length << ")"
- << " in MemoryMappedFile::map"
- << endl;
- close();
- fassertFailed( 16225 );
- }
+ {
+ DWORD flProtect = PAGE_READWRITE; //(options & READONLY)?PAGE_READONLY:PAGE_READWRITE;
+ maphandle = CreateFileMappingW(fd,
+ NULL,
+ flProtect,
+ length >> 32 /*maxsizehigh*/,
+ (unsigned)length /*maxsizelow*/,
+ NULL /*lpName*/);
+ if (maphandle == NULL) {
+ DWORD dosError = GetLastError();
+ log() << "CreateFileMappingW for " << filename << " failed with "
+ << errnoWithDescription(dosError) << " (file size is " << length << ")"
+ << " in MemoryMappedFile::map" << endl;
+ close();
+ fassertFailed(16225);
}
+ }
- void *view = 0;
- {
- stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
- DWORD access = ( options & READONLY ) ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS;
-
- int current_retry = 0;
- while (true) {
+ void* view = 0;
+ {
+ stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
+ DWORD access = (options & READONLY) ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS;
- LPVOID thisAddress = getNextMemoryMappedFileLocation(length);
+ int current_retry = 0;
+ while (true) {
+ LPVOID thisAddress = getNextMemoryMappedFileLocation(length);
- view = MapViewOfFileEx(
- maphandle, // file mapping handle
- access, // access
- 0, 0, // file offset, high and low
- 0, // bytes to map, 0 == all
- thisAddress); // address to place file
+ view = MapViewOfFileEx(maphandle, // file mapping handle
+ access, // access
+ 0,
+ 0, // file offset, high and low
+ 0, // bytes to map, 0 == all
+ thisAddress); // address to place file
- if (view == 0) {
- DWORD dosError = GetLastError();
+ if (view == 0) {
+ DWORD dosError = GetLastError();
- ++current_retry;
+ ++current_retry;
- // If we failed to allocate a memory mapped file, try again in case we picked
- // an address that Windows is also trying to use for some other VM allocations
- if (dosError == ERROR_INVALID_ADDRESS && current_retry < 5) {
- continue;
- }
+ // If we failed to allocate a memory mapped file, try again in case we picked
+ // an address that Windows is also trying to use for some other VM allocations
+ if (dosError == ERROR_INVALID_ADDRESS && current_retry < 5) {
+ continue;
+ }
#ifndef _WIN64
- // Warn user that if they are running a 32-bit app on 64-bit Windows
- if (dosError == ERROR_NOT_ENOUGH_MEMORY) {
- BOOL wow64Process;
- BOOL retWow64 = IsWow64Process(GetCurrentProcess(), &wow64Process);
- if (retWow64 && wow64Process) {
- log() << "This is a 32-bit MongoDB binary running on a 64-bit"
- " operating system that has run out of virtual memory for"
- " databases. Switch to a 64-bit build of MongoDB to open"
- " the databases.";
- }
+ // Warn user that if they are running a 32-bit app on 64-bit Windows
+ if (dosError == ERROR_NOT_ENOUGH_MEMORY) {
+ BOOL wow64Process;
+ BOOL retWow64 = IsWow64Process(GetCurrentProcess(), &wow64Process);
+ if (retWow64 && wow64Process) {
+ log() << "This is a 32-bit MongoDB binary running on a 64-bit"
+ " operating system that has run out of virtual memory for"
+ " databases. Switch to a 64-bit build of MongoDB to open"
+ " the databases.";
}
+ }
#endif
- log() << "MapViewOfFileEx for " << filename
- << " at address " << thisAddress
- << " failed with " << errnoWithDescription(dosError)
- << " (file size is " << length << ")"
- << " in MemoryMappedFile::map"
- << endl;
-
- close();
- fassertFailed(16166);
- }
+ log() << "MapViewOfFileEx for " << filename << " at address " << thisAddress
+ << " failed with " << errnoWithDescription(dosError) << " (file size is "
+ << length << ")"
+ << " in MemoryMappedFile::map" << endl;
- break;
+ close();
+ fassertFailed(16166);
}
- }
- views.push_back(view);
- len = length;
- return view;
+ break;
+ }
}
- extern stdx::mutex mapViewMutex;
-
- void* MemoryMappedFile::createPrivateMap() {
- verify( maphandle );
-
- stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
+ views.push_back(view);
+ len = length;
+ return view;
+}
- LPVOID thisAddress = getNextMemoryMappedFileLocation( len );
+extern stdx::mutex mapViewMutex;
- void* privateMapAddress = NULL;
- int current_retry = 0;
+void* MemoryMappedFile::createPrivateMap() {
+ verify(maphandle);
- while (true) {
+ stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
- privateMapAddress = MapViewOfFileEx(
- maphandle, // file mapping handle
- FILE_MAP_READ, // access
- 0, 0, // file offset, high and low
- 0, // bytes to map, 0 == all
- thisAddress); // address to place file
+ LPVOID thisAddress = getNextMemoryMappedFileLocation(len);
- if (privateMapAddress == 0) {
- DWORD dosError = GetLastError();
+ void* privateMapAddress = NULL;
+ int current_retry = 0;
- ++current_retry;
+ while (true) {
+ privateMapAddress = MapViewOfFileEx(maphandle, // file mapping handle
+ FILE_MAP_READ, // access
+ 0,
+ 0, // file offset, high and low
+ 0, // bytes to map, 0 == all
+ thisAddress); // address to place file
- // If we failed to allocate a memory mapped file, try again in case we picked
- // an address that Windows is also trying to use for some other VM allocations
- if (dosError == ERROR_INVALID_ADDRESS && current_retry < 5) {
- continue;
- }
+ if (privateMapAddress == 0) {
+ DWORD dosError = GetLastError();
- log() << "MapViewOfFileEx for " << filename()
- << " failed with error " << errnoWithDescription(dosError)
- << " (file size is " << len << ")"
- << " in MemoryMappedFile::createPrivateMap"
- << endl;
+ ++current_retry;
- fassertFailed(16167);
+ // If we failed to allocate a memory mapped file, try again in case we picked
+ // an address that Windows is also trying to use for some other VM allocations
+ if (dosError == ERROR_INVALID_ADDRESS && current_retry < 5) {
+ continue;
}
- break;
+ log() << "MapViewOfFileEx for " << filename() << " failed with error "
+ << errnoWithDescription(dosError) << " (file size is " << len << ")"
+ << " in MemoryMappedFile::createPrivateMap" << endl;
+
+ fassertFailed(16167);
}
- views.push_back( privateMapAddress );
- return privateMapAddress;
+ break;
}
- void* MemoryMappedFile::remapPrivateView(void *oldPrivateAddr) {
- LockMongoFilesExclusive lockMongoFiles;
+ views.push_back(privateMapAddress);
+ return privateMapAddress;
+}
- privateViews.clearWritableBits(oldPrivateAddr, len);
+void* MemoryMappedFile::remapPrivateView(void* oldPrivateAddr) {
+ LockMongoFilesExclusive lockMongoFiles;
- stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
+ privateViews.clearWritableBits(oldPrivateAddr, len);
- if( !UnmapViewOfFile(oldPrivateAddr) ) {
- DWORD dosError = GetLastError();
- log() << "UnMapViewOfFile for " << filename()
- << " failed with error " << errnoWithDescription( dosError )
- << " in MemoryMappedFile::remapPrivateView"
- << endl;
- fassertFailed( 16168 );
- }
+ stdx::lock_guard<stdx::mutex> lk(mapViewMutex);
- void* newPrivateView = MapViewOfFileEx(
- maphandle, // file mapping handle
- FILE_MAP_READ, // access
- 0, 0, // file offset, high and low
- 0, // bytes to map, 0 == all
- oldPrivateAddr ); // we want the same address we had before
- if ( 0 == newPrivateView ) {
- DWORD dosError = GetLastError();
- log() << "MapViewOfFileEx for " << filename()
- << " failed with error " << errnoWithDescription( dosError )
- << " (file size is " << len << ")"
- << " in MemoryMappedFile::remapPrivateView"
- << endl;
- }
- fassert( 16148, newPrivateView == oldPrivateAddr );
- return newPrivateView;
+ if (!UnmapViewOfFile(oldPrivateAddr)) {
+ DWORD dosError = GetLastError();
+ log() << "UnMapViewOfFile for " << filename() << " failed with error "
+ << errnoWithDescription(dosError) << " in MemoryMappedFile::remapPrivateView" << endl;
+ fassertFailed(16168);
}
- class WindowsFlushable : public MemoryMappedFile::Flushable {
- public:
- WindowsFlushable( MemoryMappedFile* theFile,
- void * view,
- HANDLE fd,
- const uint64_t id,
- const std::string& filename,
- stdx::mutex& flushMutex )
- : _theFile(theFile), _view(view), _fd(fd), _id(id), _filename(filename),
- _flushMutex(flushMutex)
- {}
-
- void flush() {
- if (!_view || !_fd)
- return;
+ void* newPrivateView =
+ MapViewOfFileEx(maphandle, // file mapping handle
+ FILE_MAP_READ, // access
+ 0,
+ 0, // file offset, high and low
+ 0, // bytes to map, 0 == all
+ oldPrivateAddr); // we want the same address we had before
+ if (0 == newPrivateView) {
+ DWORD dosError = GetLastError();
+ log() << "MapViewOfFileEx for " << filename() << " failed with error "
+ << errnoWithDescription(dosError) << " (file size is " << len << ")"
+ << " in MemoryMappedFile::remapPrivateView" << endl;
+ }
+ fassert(16148, newPrivateView == oldPrivateAddr);
+ return newPrivateView;
+}
- {
- LockMongoFilesShared mmfilesLock;
+class WindowsFlushable : public MemoryMappedFile::Flushable {
+public:
+ WindowsFlushable(MemoryMappedFile* theFile,
+ void* view,
+ HANDLE fd,
+ const uint64_t id,
+ const std::string& filename,
+ stdx::mutex& flushMutex)
+ : _theFile(theFile),
+ _view(view),
+ _fd(fd),
+ _id(id),
+ _filename(filename),
+ _flushMutex(flushMutex) {}
+
+ void flush() {
+ if (!_view || !_fd)
+ return;
- std::set<MongoFile*> mmfs = MongoFile::getAllFiles();
- std::set<MongoFile*>::const_iterator it = mmfs.find(_theFile);
- if ( it == mmfs.end() || (*it)->getUniqueId() != _id ) {
- // this was deleted while we were unlocked
- return;
- }
+ {
+ LockMongoFilesShared mmfilesLock;
- // Hold the flush mutex to ensure the file is not closed during flush
- _flushMutex.lock();
+ std::set<MongoFile*> mmfs = MongoFile::getAllFiles();
+ std::set<MongoFile*>::const_iterator it = mmfs.find(_theFile);
+ if (it == mmfs.end() || (*it)->getUniqueId() != _id) {
+ // this was deleted while we were unlocked
+ return;
}
- stdx::lock_guard<stdx::mutex> lk(_flushMutex, stdx::adopt_lock);
-
- int loopCount = 0;
- bool success = false;
- bool timeout = false;
- int dosError = ERROR_SUCCESS;
- const int maximumTimeInSeconds = 60 * 15;
- Timer t;
- while ( !success && !timeout ) {
- ++loopCount;
- success = FALSE != FlushViewOfFile( _view, 0 );
- if ( !success ) {
- dosError = GetLastError();
- if ( dosError != ERROR_LOCK_VIOLATION ) {
- break;
- }
- timeout = t.seconds() > maximumTimeInSeconds;
- }
- }
- if ( success && loopCount > 1 ) {
- log() << "FlushViewOfFile for " << _filename
- << " succeeded after " << loopCount
- << " attempts taking " << t.millis()
- << "ms" << endl;
- }
- else if ( !success ) {
- log() << "FlushViewOfFile for " << _filename
- << " failed with error " << dosError
- << " after " << loopCount
- << " attempts taking " << t.millis()
- << "ms" << endl;
- // Abort here to avoid data corruption
- fassert(16387, false);
- }
+ // Hold the flush mutex to ensure the file is not closed during flush
+ _flushMutex.lock();
+ }
- success = FALSE != FlushFileBuffers(_fd);
+ stdx::lock_guard<stdx::mutex> lk(_flushMutex, stdx::adopt_lock);
+
+ int loopCount = 0;
+ bool success = false;
+ bool timeout = false;
+ int dosError = ERROR_SUCCESS;
+ const int maximumTimeInSeconds = 60 * 15;
+ Timer t;
+ while (!success && !timeout) {
+ ++loopCount;
+ success = FALSE != FlushViewOfFile(_view, 0);
if (!success) {
- int err = GetLastError();
- log() << "FlushFileBuffers failed: " << errnoWithDescription( err )
- << " file: " << _filename << endl;
- dataSyncFailedHandler();
+ dosError = GetLastError();
+ if (dosError != ERROR_LOCK_VIOLATION) {
+ break;
+ }
+ timeout = t.seconds() > maximumTimeInSeconds;
}
}
+ if (success && loopCount > 1) {
+ log() << "FlushViewOfFile for " << _filename << " succeeded after " << loopCount
+ << " attempts taking " << t.millis() << "ms" << endl;
+ } else if (!success) {
+ log() << "FlushViewOfFile for " << _filename << " failed with error " << dosError
+ << " after " << loopCount << " attempts taking " << t.millis() << "ms" << endl;
+ // Abort here to avoid data corruption
+ fassert(16387, false);
+ }
- MemoryMappedFile* _theFile; // this may be deleted while we are running
- void * _view;
- HANDLE _fd;
- const uint64_t _id;
- string _filename;
- stdx::mutex& _flushMutex;
- };
-
- void MemoryMappedFile::flush(bool sync) {
- uassert(13056, "Async flushing not supported on windows", sync);
- if( !views.empty() ) {
- WindowsFlushable f(this, viewForFlushing(), fd, _uniqueId, filename(), _flushMutex);
- f.flush();
+ success = FALSE != FlushFileBuffers(_fd);
+ if (!success) {
+ int err = GetLastError();
+ log() << "FlushFileBuffers failed: " << errnoWithDescription(err)
+ << " file: " << _filename << endl;
+ dataSyncFailedHandler();
}
}
- MemoryMappedFile::Flushable * MemoryMappedFile::prepareFlush() {
- return new WindowsFlushable(this, viewForFlushing(), fd, _uniqueId,
- filename(), _flushMutex);
+ MemoryMappedFile* _theFile; // this may be deleted while we are running
+ void* _view;
+ HANDLE _fd;
+ const uint64_t _id;
+ string _filename;
+ stdx::mutex& _flushMutex;
+};
+
+void MemoryMappedFile::flush(bool sync) {
+ uassert(13056, "Async flushing not supported on windows", sync);
+ if (!views.empty()) {
+ WindowsFlushable f(this, viewForFlushing(), fd, _uniqueId, filename(), _flushMutex);
+ f.flush();
}
+}
+MemoryMappedFile::Flushable* MemoryMappedFile::prepareFlush() {
+ return new WindowsFlushable(this, viewForFlushing(), fd, _uniqueId, filename(), _flushMutex);
+}
}