void BasicProviderManagerRouter::unloadIdleProviders()
{
    PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
        "BasicProviderManagerRouter::unloadIdleProviders");

    //
    // Save pointers to the ProviderManagerContainers so we don't hold the
    // _providerManagerTableLock while unloading idle providers
    //
    Array<ProviderManagerContainer*> pmcs;
    {
        ReadLock tableLock(_providerManagerTableLock);
        for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
        {
            pmcs.append(_providerManagerTable[i]);
        }
    }

    //
    // Unload idle providers in each of the active ProviderManagers
    // _providerManagerTableLock while unloading idle providers
    //
    for (Uint32 i = 0; i < pmcs.size(); i++)
    {
        pmcs[i]->getProviderManager()->unloadIdleProviders();
    }

    PEG_METHOD_EXIT();
}
예제 #2
0
bool FMallocBinned::validateHeap()
{
#ifdef USE_COARSE_GRAIN_LOCKS
    FScopeLock ScopedLock(&AccessGuard);
#endif

    for( int32_t i = 0; i < PoolCount; i++ )
    {
        FPoolTable* table = &poolTable[i];
#ifdef USE_FINE_GRAIN_LOCKS
        std::lock_guard<std::mutex> tableLock(table->mutex);
#endif
        for( FPoolInfo** poolPtr = &table->firstPool; *poolPtr; poolPtr = &(*poolPtr)->next )
        {
            FPoolInfo* pool = *poolPtr;
            FAssert(pool->prevLink == poolPtr);
            FAssert(!!pool->firstMem);
            for( FFreeMem* free = pool->firstMem; free; free = free->next )
            {
                FAssert(free->numFreeBlocks > 0);
            }
        }

        for( FPoolInfo** poolPtr = &table->exhaustedPool; *poolPtr; poolPtr = &(*poolPtr)->next )
        {
            FPoolInfo* pool = *poolPtr;
            FAssert(pool->prevLink == poolPtr);
            FAssert(!pool->firstMem);
        }
    }

    return true;
}
Boolean BasicProviderManagerRouter::hasActiveProviders()
{
    PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
        "BasicProviderManagerRouter::hasActiveProviders");

    ReadLock tableLock(_providerManagerTableLock);
    for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
    {
        ProviderManagerContainer* pmc = _providerManagerTable[i];
        if (pmc->getProviderManager()->hasActiveProviders())
        {
            PEG_METHOD_EXIT();
            return true;
        }
    }

    PEG_METHOD_EXIT();
    return false;
}
예제 #4
0
void* FMallocBinned::malloc(size_t size, uint32_t alignment)
{
#ifdef USE_COARSE_GRAIN_LOCKS
    FScopeLock ScopedLock(&AccessGuard);
#endif

    flushPendingFrees();

    // Handle DEFAULT_ALIGNMENT for binned allocator.
    if (alignment == DefaultAlignment)
    {
        alignment = default_binned_allocator_alignment;
    }

    FAssert(alignment <= pageSize);

    alignment = std::max<uint32_t>(alignment, default_binned_allocator_alignment);

    size = std::max<size_t>(alignment, FAlign(size, alignment));

    MEM_TIME(MemTime -= FPlatformTime::Seconds());

    STAT(currentAllocs++);
    STAT(totalAllocs++);

    FFreeMem* free = nullptr;

    if( size < binnedSizeLimit )
    {
        // Allocate from pool.
        FPoolTable* table = memSizeToPoolTable[size];
#ifdef USE_FINE_GRAIN_LOCKS
        std::lock_guard<std::mutex> tableLock(table->mutex);
#endif
        FAssert(size <= table->blockSize);

        trackStats(table, (uint32_t)size);

        FPoolInfo* pool = table->firstPool;
        if( !pool )
        {
            pool = allocatePoolMemory(table, binned_alloc_pool_size/*PageSize*/, size);
        }

        free = allocateBlockFromPool(table, pool);
    }
    else if ( ((size >= binnedSizeLimit && size <= pagePoolTable[0].blockSize) ||
               (size > pageSize && size <= pagePoolTable[1].blockSize))
             && alignment == default_binned_allocator_alignment )
    {
        // Bucket in a pool of 3*PageSize or 6*PageSize
        uint32_t binType = size < pageSize ? 0 : 1;
        uint32_t pageCount = 3 * binType + 3;

        FPoolTable* table = &pagePoolTable[binType];
#ifdef USE_FINE_GRAIN_LOCKS
        std::lock_guard<std::mutex> tableLock(table->mutex);
#endif
        FAssert(size <= table->blockSize);

        trackStats(table, (uint32_t)size);

        FPoolInfo* pool = table->firstPool;
        if( !pool )
        {
            pool = allocatePoolMemory(table, pageCount * pageSize, binnedSizeLimit + binType);
        }

        free = allocateBlockFromPool(table, pool);
    }
    else
    {
        // Use OS for large allocations.
        UIntPtr_t alignedSize = FAlign(size, pageSize);

        size_t actualPoolSize; //TODO: use this to reduce waste?
        free = (FFreeMem*)osAlloc(alignedSize, actualPoolSize);
        if( !free )
        {
            outOfMemory(alignedSize);
        }

        FAssert(!((size_t)free & (pageSize - 1)));

        // Create indirect.
        FPoolInfo* pool;
        {
#ifdef USE_FINE_GRAIN_LOCKS
            std::lock_guard<std::mutex> poolInfoLock(accessGuard);
#endif
            pool = getPoolInfo((UIntPtr_t)free);
        }

        pool->setAllocationSizes((uint32_t)size, alignedSize, (uint32_t)binnedOSTableIndex, (uint32_t)binnedOSTableIndex);

        STAT(osPeak = std::max(osPeak, osCurrent += alignedSize));
        STAT(usedPeak = std::max(usedPeak, usedCurrent += size));
        STAT(wastePeak = std::max(wastePeak, wasteCurrent += alignedSize - size));
    }
    
    MEM_TIME(MemTime += FPlatformTime::Seconds());
    return free;

}
// ATTN: May need to add interfaceVersion parameter to further constrain lookup
ProviderManager* BasicProviderManagerRouter::_getProviderManager(
    const String& interfaceType,
    const String& providerModuleName,
    const String& providerManagerPath)
{
    PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
        "BasicProviderManagerRouter::_getProviderManager");

    //
    // Search for this InterfaceType in the table of loaded ProviderManagers
    //
    {
        ReadLock tableLock(_providerManagerTableLock);

        ProviderManager* pm = _lookupProviderManager(interfaceType);
        if (pm)
        {
            PEG_METHOD_EXIT();
            return pm;
        }
    }

    //
    // Load the ProviderManager for this InterfaceType and add it to the table
    //
    {
        WriteLock tableLock(_providerManagerTableLock);

        ProviderManager* pm = _lookupProviderManager(interfaceType);
        if (pm)
        {
            PEG_METHOD_EXIT();
            return pm;
        }

        // The DefaultProviderManager is now statically linked rather than
        // dynamically loaded. This code is no longer used but remains for
        // reference purposes.

#if defined(PEGASUS_ENABLE_DEFAULT_PROVIDER_MANAGER)
        if (interfaceType == "C++Default" &&
            _createDefaultProviderManagerCallback)
        {
            pm = (*_createDefaultProviderManagerCallback)();
            ProviderManagerContainer* pmc = new ProviderManagerContainer(
                "C++Default",
                _indicationCallback,
                _responseChunkCallback,
                _subscriptionInitComplete,
                pm);
            _providerManagerTable.append(pmc);
            PEG_METHOD_EXIT();
            return pmc->getProviderManager();
        }
#endif

        ProviderManagerContainer* pmc = new ProviderManagerContainer(
            providerManagerPath,
            interfaceType,
            interfaceType,
            _indicationCallback,
            _responseChunkCallback,
            _subscriptionInitComplete);
        _providerManagerTable.append(pmc);
        PEG_METHOD_EXIT();
        return pmc->getProviderManager();
    }

}
Message* BasicProviderManagerRouter::processMessage(Message * message)
{
    PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
        "BasicProviderManagerRouter::processMessage");

    CIMRequestMessage* request = dynamic_cast<CIMRequestMessage *>(message);
    PEGASUS_ASSERT(request != 0);

    Message* response = 0;
    Boolean remoteNameSpaceRequest=false;

    //
    // Retrieve the ProviderManager routing information
    //

    CIMInstance providerModule;

    if ((dynamic_cast<CIMOperationRequestMessage*>(request) != 0) ||
        (request->getType() == CIM_EXPORT_INDICATION_REQUEST_MESSAGE))
    {
        // Provider information is in OperationContext
        ProviderIdContainer pidc = (ProviderIdContainer)
            request->operationContext.get(ProviderIdContainer::NAME);
        providerModule = pidc.getModule();
        remoteNameSpaceRequest=pidc.isRemoteNameSpace();
    }
    else if (dynamic_cast<CIMIndicationRequestMessage*>(request) != 0)
    {
        // Provider information is in CIMIndicationRequestMessage
        CIMIndicationRequestMessage* indReq =
            dynamic_cast<CIMIndicationRequestMessage*>(request);
        ProviderIdContainer pidc =
            indReq->operationContext.get(ProviderIdContainer::NAME);
        providerModule = pidc.getModule();
    }
    else if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
    {
        // Provider information is in CIMEnableModuleRequestMessage
        CIMEnableModuleRequestMessage* emReq =
            dynamic_cast<CIMEnableModuleRequestMessage*>(request);
        providerModule = emReq->providerModule;
    }
    else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
    {
        // Provider information is in CIMDisableModuleRequestMessage
        CIMDisableModuleRequestMessage* dmReq =
            dynamic_cast<CIMDisableModuleRequestMessage*>(request);
        providerModule = dmReq->providerModule;
    }
    else if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
             (request->getType() ==
              CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
             (request->getType() ==
              CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE) ||
             (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE))
    {
        // This operation is not provider-specific
    }
    else
    {
        // Error: Unrecognized message type.
        PEGASUS_ASSERT(0);
        CIMResponseMessage* resp = request->buildResponse();
        resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
            "Unknown message type.");
        response = resp;
    }

    //
    // Forward the request to the appropriate ProviderManager(s)
    //

    if ((request->getType() == CIM_STOP_ALL_PROVIDERS_REQUEST_MESSAGE) ||
        (request->getType() ==
            CIM_SUBSCRIPTION_INIT_COMPLETE_REQUEST_MESSAGE) ||
        (request->getType() ==
            CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE))
    {
        if (request->getType() ==
            CIM_INDICATION_SERVICE_DISABLED_REQUEST_MESSAGE)
        {
            _subscriptionInitComplete = false;
        }
        else
        {
            _subscriptionInitComplete = true;
        }

        // Send CIMStopAllProvidersRequestMessage or
        // CIMIndicationServiceDisabledRequestMessage or
        // CIMSubscriptionInitCompleteRequestMessage to all ProviderManagers
        ReadLock tableLock(_providerManagerTableLock);
        for (Uint32 i = 0, n = _providerManagerTable.size(); i < n; i++)
        {
            ProviderManagerContainer* pmc=_providerManagerTable[i];
            Message* resp = pmc->getProviderManager()->processMessage(request);
            delete resp;
        }

        response = request->buildResponse();
    }
    else if (request->getType() == CIM_NOTIFY_CONFIG_CHANGE_REQUEST_MESSAGE)
    {
        // Do not need to forward this request to in-process provider
        // managers
        response = request->buildResponse();
    }
    else
    {
        // Retrieve the provider interface type
        String interfaceType;
        CIMValue itValue = providerModule.getProperty(
            providerModule.findProperty("InterfaceType")).getValue();
        itValue.get(interfaceType);
        // Get ProviderModule name.
        String providerModuleName;
        CIMValue nameValue = providerModule.getProperty(
            providerModule.findProperty(PEGASUS_PROPERTYNAME_NAME)).getValue();
        nameValue.get(providerModuleName);
        // Get providerManager path
        String provMgrPath;
        if (request->operationContext.contains(ProviderIdContainer::NAME))
        {
            ProviderIdContainer pidc = (ProviderIdContainer)
            request->operationContext.get(ProviderIdContainer::NAME);
            provMgrPath = pidc.getProvMgrPath();
        }

        ProviderManager* pm = 0;
        Boolean gotError = false;
        try
        {
            // Look up the appropriate ProviderManager by InterfaceType

            pm = _getProviderManager(interfaceType, providerModuleName,
                provMgrPath);
        }
        catch (const CIMException& e)
        {
            // This is not an error incase of CIMEnableModuleRequestMessage or
            // CIMDisableModuleRequestMessage. This means there is no provider
            // to enable or disable.
            if (request->getType() == CIM_ENABLE_MODULE_REQUEST_MESSAGE)
            {
                CIMEnableModuleResponseMessage* emResponse =
                    dynamic_cast<CIMEnableModuleResponseMessage*>(
                        request->buildResponse());
                emResponse->operationalStatus.append(
                    CIM_MSE_OPSTATUS_VALUE_OK);
                response = emResponse;
            }
            else if (request->getType() == CIM_DISABLE_MODULE_REQUEST_MESSAGE)
            {
                CIMDisableModuleResponseMessage* dmResponse =
                    dynamic_cast<CIMDisableModuleResponseMessage*>(
                        request->buildResponse());
                dmResponse->operationalStatus.append(
                    CIM_MSE_OPSTATUS_VALUE_STOPPED);
                response = dmResponse;
            }
            else
            {
                CIMResponseMessage *cimResponse = request->buildResponse();
                cimResponse->cimException = e;
                response = cimResponse;
            }
            gotError = true;
        }

        if (!gotError && remoteNameSpaceRequest &&
            !pm->supportsRemoteNameSpaces())
        {
            CIMResponseMessage* resp = request->buildResponse();
            resp->cimException = PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
                "Remote Namespace operations not supported for interface type "
                    + interfaceType);
            response = resp;
            gotError = true;
        }

        if (!gotError)
        {
            response = pm->processMessage(request);
        }
    }

    PEG_METHOD_EXIT();
    return response;
}
// ATTN: May need to add interfaceVersion parameter to further constrain lookup
ProviderManager* BasicProviderManagerRouter::_getProviderManager(
    const String& interfaceType,
    const String& providerManagerPath,
    Boolean loadProviderManager)
{
    PEG_METHOD_ENTER(TRC_PROVIDERMANAGER,
                     "BasicProviderManagerRouter::_getProviderManager");

    //
    // Search for this InterfaceType in the table of loaded ProviderManagers
    //
    {
        ReadLock tableLock(_providerManagerTableLock);

        ProviderManager* pm = _lookupProviderManager(interfaceType);
        if (pm)
        {
            PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
                       "Provider Manager for interfaceType '%s' already loaded.",
                       (const char*)interfaceType.getCString()));
            PEG_METHOD_EXIT();
            return pm;
        }
    }

    //
    // If requested, do not load the ProviderManger.
    //
    if (!loadProviderManager)
    {
        PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
                   "Requested not to load the Provider Manager "
                   "for interfaceType '%s'.",
                   (const char*)interfaceType.getCString()));
        PEG_METHOD_EXIT();
        return 0;
    }

    //
    // Load the ProviderManager for this InterfaceType and add it to the table
    //
    {
        WriteLock tableLock(_providerManagerTableLock);

        ProviderManager* pm = _lookupProviderManager(interfaceType);
        if (pm)
        {
            PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
                       "Provider Manager for interfaceType '%s' already loaded.",
                       (const char*)interfaceType.getCString()));
            PEG_METHOD_EXIT();
            return pm;
        }

        // The DefaultProviderManager is now statically linked rather than
        // dynamically loaded. This code is no longer used but remains for
        // reference purposes.

#if defined(PEGASUS_ENABLE_DEFAULT_PROVIDER_MANAGER)
        if (interfaceType == "C++Default" &&
                _createDefaultProviderManagerCallback)
        {
            pm = (*_createDefaultProviderManagerCallback)();
            ProviderManagerContainer* pmc = new ProviderManagerContainer(
                "C++Default",
                _indicationCallback,
                _responseChunkCallback,
                _subscriptionInitComplete,
                pm);
            _providerManagerTable.append(pmc);
            PEG_METHOD_EXIT();
            return pmc->getProviderManager();
        }
#endif

        PEG_TRACE((TRC_PROVIDERMANAGER, Tracer::LEVEL4,
                   "Crating new Provider Manager for interfaceType '%s', "
                   "providerManagerPath '%s'.",
                   (const char*)interfaceType.getCString(),
                   (const char*)providerManagerPath.getCString()));

        ProviderManagerContainer* pmc = new ProviderManagerContainer(
            providerManagerPath,
            interfaceType,
            interfaceType,
            _indicationCallback,
            _responseChunkCallback,
            _subscriptionInitComplete);
        _providerManagerTable.append(pmc);
        PEG_METHOD_EXIT();
        return pmc->getProviderManager();
    }

}