void* MemoryMappedFile::createReadOnlyMap() { verify( maphandle ); stdx::lock_guard<stdx::mutex> lk(mapViewMutex); void* readOnlyMapAddress = NULL; int current_retry = 0; 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 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; } log() << "MapViewOfFileEx for " << filename() << " at address " << thisAddress << " failed with error " << errnoWithDescription(dosError) << " (file size is " << len << ")" << " in MemoryMappedFile::createReadOnlyMap" << endl; fassertFailed(16165); } break; } views.push_back( readOnlyMapAddress ); return readOnlyMapAddress; }
void* MemoryMappedFile::createReadOnlyMap() { verify( maphandle ); scoped_lock lk(mapViewMutex); LPVOID thisAddress = getNextMemoryMappedFileLocation( len ); void* 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(); log() << "MapViewOfFileEx for " << filename() << " failed with error " << errnoWithDescription( dosError ) << " (file size is " << len << ")" << " in MemoryMappedFile::createReadOnlyMap" << endl; fassertFailed( 16165 ); } memconcept::is( readOnlyMapAddress, memconcept::concept::other, filename() ); views.push_back( readOnlyMapAddress ); return readOnlyMapAddress; }
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 ); { 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; { 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; { scoped_lock lk(mapViewMutex); DWORD access = ( options & READONLY ) ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS; 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 if ( view == 0 ) { DWORD dosError = GetLastError(); log() << "MapViewOfFileEx for " << filename << " failed with " << errnoWithDescription( dosError ) << " (file size is " << length << ")" << " in MemoryMappedFile::map" << endl; close(); fassertFailed( 16166 ); } } views.push_back(view); memconcept::is(view, memconcept::concept::memorymappedfile, this->filename(), (unsigned) length); len = length; return view; }
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 ); { 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; { 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) { 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 if (view == 0) { 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; } #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."; } } #endif log() << "MapViewOfFileEx for " << filename << " at address " << thisAddress << " failed with " << errnoWithDescription(dosError) << " (file size is " << length << ")" << " in MemoryMappedFile::map" << endl; close(); fassertFailed(16166); } break; } } views.push_back(view); len = length; return view; }