Example #1
0
__declspec(noinline) void PointerToDurableMappedFile::makeChunkWritable(size_t chunkno) {
    stdx::lock_guard<stdx::mutex> lkPrivateViews(_m);

    if (writable.get(chunkno))  // double check lock
        return;

    // remap all maps in this chunk.
    // common case is a single map, but could have more than one with smallfiles or .ns files
    size_t chunkStart = chunkno * MemoryMappedCOWBitset::ChunkSize;
    size_t chunkNext = chunkStart + MemoryMappedCOWBitset::ChunkSize;

    stdx::lock_guard<stdx::mutex> lkMapView(mapViewMutex);

    map<void*, DurableMappedFile*>::iterator i = _views.upper_bound((void*)(chunkNext - 1));
    while (1) {
        const pair<void*, DurableMappedFile*> x = *(--i);
        DurableMappedFile* mmf = x.second;
        if (mmf == 0)
            break;

        size_t viewStart = reinterpret_cast<size_t>(x.first);
        size_t viewEnd = viewStart + mmf->length();
        if (viewEnd <= chunkStart)
            break;

        size_t protectStart = std::max(viewStart, chunkStart);
        dassert(protectStart < chunkNext);

        size_t protectEnd = std::min(viewEnd, chunkNext);
        size_t protectSize = protectEnd - protectStart;
        dassert(protectSize > 0 && protectSize <= MemoryMappedCOWBitset::ChunkSize);

        DWORD oldProtection;
        bool ok = VirtualProtect(
                      reinterpret_cast<void*>(protectStart), protectSize, PAGE_WRITECOPY, &oldProtection);
        if (!ok) {
            DWORD dosError = GetLastError();

            if (dosError == ERROR_COMMITMENT_LIMIT) {
                // System has run out of memory between physical RAM & page file, tell the user
                BSONObjBuilder bb;

                ProcessInfo p;
                p.getExtraInfo(bb);

                severe() << "MongoDB has exhausted the system memory capacity.";
                severe() << "Current Memory Status: " << bb.obj();
            }

            severe() << "VirtualProtect for " << mmf->filename() << " chunk " << chunkno
                     << " failed with " << errnoWithDescription(dosError) << " (chunk size is "
                     << protectSize << ", address is " << hex << protectStart << dec << ")"
                     << " in mongo::makeChunkWritable, terminating" << endl;

            fassertFailed(16362);
        }
    }

    writable.set(chunkno);
}