locplgmgr.cpp

来自「Windows CE 6.0 Server 源码」· C++ 代码 · 共 1,677 行 · 第 1/5 页

CPP
1,677
字号
            // For a resolver, first we need to try and start providers
            // that can generate reports that this resolver can resolve
            resolver_t *pRes = (resolver_t*)pPlugin;
            pRes->RequestReportGeneration(pReportType);
            ret = StartDependentProviderIfNeeded(pReportType,pRes);
        }
    }
    break;

    default:
    {
        // Should not be able to get here.
        DEBUGCHK(0);
    }
    }

    // Returning TRUE indicates that we're going to use this plugin
    // to generate the report.  Notify the reports collector to this fact if
    // there has been a state change
    if (ret && (reportState != pPlugin->GetReportTypeState(pReportType))) {
        reportCol_t *pRC = FindRC(pReportType);
        pRC->PluginStateChange();
    }

    return ret;
}

// Either an app is explicitly requesting pReportType in this call, or
// we're trying to start up a new plugin because the current one generating
// this report has become unavailable.  

// minStartOrder indicates which plugin in the list we should start with. 
// When attempting to restart after a plugin went unavailable, this saves 
// us from rescanning over higher priority plugins that are known to be unavailable.
DWORD pluginMgr_t::StartPluginForReportType(const GUID *pReportType, DWORD minStartOrder) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(g_serviceState == SERVICE_STATE_ON);

    pluginListIter_t it    = GetPluginOfStartOrder(minStartOrder);
    pluginListIter_t itEnd = m_pluginList.end();

    // Iterate through each plugin, in priority order, and try to start
    // it for this report type.
    for (; it != itEnd; ++it) {
        if (StartPluginIfPossible(*it,pReportType))
            return ERROR_SUCCESS;
    }

    return ERROR_DEV_NOT_EXIST;
}

// When a plugin fails (either UNAVAILABLE or ERROR), attempt to start
// the next plugin in line to generate any registered reports
void pluginMgr_t::StartNextPluginsOnFailure(plugin_t *pPlugin) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(g_serviceState == SERVICE_STATE_ON);

    GUID generatedReports[MAX_PLUGIN_REPORT_TYPES];
    DWORD numGeneratedReports;
    pPlugin->GetGeneratedReportInfo(generatedReports,&numGeneratedReports);

    DWORD minStartOrder = pPlugin->GetStartOrder() + 1;
    DWORD i;

    DEBUGMSG(ZONE_PLUGIN,(L"LOC: Plugin <%s> is no longer available.  Trying to start next plugins in line\r\n",
             pPlugin->GetName()));

    // Try to restart next possible plugin for any report types that this 
    // plugin can generate that were explicitly requested by an APPLICATION
    // (via LocationRegisterForReport).  Restarting based on RESOLVER dependancy
    // logic is NOT handled in this function, but elsewhere.

    for (i = 0; i < numGeneratedReports; i++) {
        // Indicate to reports collectors the fact that current plugin is failing.
        reportCol_t *pRC = FindRC(&generatedReports[i]);
        pRC->PluginStateChange();

        if (! IsPluginNeededForReport(pPlugin,&generatedReports[i],TRUE))
            continue;

        StartPluginForReportType(&generatedReports[i], minStartOrder);
    }      
}


// The specified resolver has been requested to register for a certain report.
// First we (may) need to start required providers for this resolver.
// This function iterates through each provider on the system and attempts
// to start it for each supportedType the resolver has, stopping if it 
// has a successful startup.
BOOL pluginMgr_t::StartDependentProviderIfNeeded(const GUID *pReportType, resolver_t *pRes) {
#ifdef DEBUG
    PLUGIN_STATE pluginState = pRes->GetState();
    // If resolver is shutting down or in a fatal error, then we should
    // not be trying to startup new providers for it in the first place. 
    DEBUGCHK((pluginState != PLUGIN_STATE_SHUTTING_DOWN) || (pluginState != PLUGIN_STATE_ERROR));
#endif

    DWORD i;

    DEBUGMSG(ZONE_PLUGIN,(L"LOC: Attempting to start dependent provider for resolver <%s>\r\n",
             pRes->GetName()));

    // The resolver has not registered at all for any report types.
    // Do so now.
    pluginListIter_t it    = m_pluginList.begin();
    pluginListIter_t itEnd = m_pluginList.end();

    GUID  supportedReports[MAX_PLUGIN_REPORT_TYPES];
    DWORD numSupportedReports;
    pRes->GetSupportedReportInfo(supportedReports,&numSupportedReports);

    // 
    // Register resolver with each possible report type
    //
    for (i = 0; i < numSupportedReports; i++) {
        // Do this because ultimately the resolver doesn't care where the report
        // comes from, it just needs to be tied into this.
        reportCol_t *pRC = FindRC(&supportedReports[i]);
        if (NULL == pRC) {
            // Just because a resolver supports a report doesn't mean anything 
            // on the system generates it (and hence no reports collector)
            continue; 
        }
        pRC->RegisterResolverForReport(pRes);
    }

    //
    // Visit each plugin in priority order.  From there, determine for
    // each report that the resolver generates whether it can be done
    //

    for (; it != itEnd; ++it) {
        // We can only generate provider generated reports, not those
        // from other resolvers, so filter these out now.
        if ((*it)->IsAResolver())
            continue;

        // Foreach report type, try to start it for this plugin.
        for (i = 0; i < numSupportedReports; i++) {
            if (StartPluginIfPossible(*it,&supportedReports[i])) {
                if (pReportType)
                    pRes->RequestReportGeneration(pReportType);
                return TRUE;
            }
        }
    }

    // Unable to find a provider that was on or could be started up
    // to service this resolver.
    if (pReportType)
        pRes->ReportTypeUnavailable(pReportType);

    DEBUGMSG(ZONE_PLUGIN,(L"LOC: Failed to start dependent provider for resolver <%s>\r\n",
             pRes->GetName()));

    return FALSE;
}


// Stops all plugins registered for given report if possible.  This can
// be either when an application deregisters for a given event type, or when
// a higher priority plugin ((minStartOrder-1) element in list) becomes available
// and lower prio plugins should be stopped if possible.
void pluginMgr_t::StopPlugins(const GUID *pReportType, pluginList_t *pPluginsToStop, DWORD minStartOrder) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(g_serviceState == SERVICE_STATE_ON);

    // Do not begin with start of list, but rather minStartOrder as passed by caller.
    // This is for instance if a higher prio plugin has become available
    // for a report, it would indicate to stop all plugins generating
    // same report type only if they had a lower priority.
    pluginListIter_t it    = GetPluginOfStartOrder(minStartOrder);
    pluginListIter_t itEnd = m_pluginList.end();
    // Whether we should alert associated RC of a state change
    BOOL             stateChange = FALSE;

    // For each plugin, indicate (if needed) that it no longer needs to generate
    // this report type and then determine if the plugin can be stopped
    // because nothing else requires it now.
    for (; it != itEnd; ++it) {
        if (! (*it)->CanGenerateReportType(pReportType)) {
            // If we can't generate this report type, no point continuing.
            continue;
        }

        PLUGIN_STATE pluginState = (*it)->GetState();
        if (pluginState < PLUGIN_STATE_UNAVAILABLE) {
            // If the plugin is off or shutting down or in fatal error,
            // then telling it to stop again is redundant.
            continue;
        }

        (*it)->CancelReportGeneration(pReportType);

        if (IsPluginNeeded((*it))) {
            // Some other app/resolver needs another report this plugin
            // can generate, so we can't stop it now.
            continue;
        }
            
        pPluginsToStop->push_back(*it);
        (*it)->StopPlugin();
        stateChange = TRUE;
    }

    if (stateChange) {
        reportCol_t *pRC = FindRC(pReportType);
        pRC->PluginStateChange();
    }
}

// Indicate to plugins with prio order greater than minStartOrder that
// they no longer need to generate this report.
void pluginMgr_t::StopPluginsForReportType(const GUID *pReportType, DWORD minStartOrder) {
    pluginList_t  pluginsToStop;

    StopPlugins(pReportType,&pluginsToStop,minStartOrder);

    pluginListIter_t it    = pluginsToStop.begin();
    pluginListIter_t itEnd = pluginsToStop.end();

    // While stopping plugins above, it's possible that we stopped a resolver
    // that itself had registered to receive other reports from providers.
    // Unregister these reports as well.
    for (; it != itEnd; ++it) {
        // Only resolvers add dependencies, so skip providers
        if ((*it)->IsAProvider())
            continue;

        resolver_t  *pRes   = (resolver_t*)((plugin_t*)(*it));
        StopDependentProvidersForResolver(pRes);
    }
}

// When a provider becomes available after having been unavailable, 
// this function will stop any plugins of lower priority that were started
// for it.  This will stop plugins for ALL report types the provider
// generates (not just the one it received a report for) since providers
// can either generate all report types or none.
void pluginMgr_t::StopPluginsOnProviderAvailable(provider_t *pProv) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(pProv->GetState() == PLUGIN_STATE_ON);

    DEBUGMSG(ZONE_PROVIDER,(L"LOC: Stoping any lower priority plugins started now that provider <%s> is available\r\n",
             pProv->GetName()));

    GUID  generatedReports[MAX_PLUGIN_REPORT_TYPES];
    DWORD numGeneratedReports;

    pluginList_t pluginsToStop;
    pProv->GetGeneratedReportInfo(generatedReports,&numGeneratedReports);
    DWORD  minStartOrder = pProv->GetStartOrder() + 1;

    for (DWORD i = 0; i < numGeneratedReports; i++)
        StopPluginsForReportType(&generatedReports[i], minStartOrder);

    StopRedundantProvidersForResolvers(minStartOrder);
}

// When a provider becomes available again, it's possible that some additional
// providers are not needed anymore and that these providers were not detected
// during the initial StopPluginForReportType() calls.  See 
// IsProviderRedundantForResolvers comments for details on this scenario.

// This function runs through each lower priority plugin and determines
// if it needs to be stopped.
void pluginMgr_t::StopRedundantProvidersForResolvers(DWORD minStartOrder) {
    DEBUGCHK(g_pLocLock->IsLocked());

    pluginListIter_t it    = GetPluginOfStartOrder(minStartOrder);
    pluginListIter_t itEnd = m_pluginList.end();

    for (; it != itEnd; ++it) {
        if ((*it)->IsAResolver()) {
            // Only care about providers;
            continue;
        }

        if ((*it)->GetState() < PLUGIN_STATE_UNAVAILABLE) {
            // If the plugin is off or shutting down or in fatal error,
            // then telling it to stop again is redundant.
            continue;
        }

        if (IsPluginNeeded((*it))) {
            // Some other app/resolver needs another report this plugin
            // can generate, so we can't stop it now.
            continue;
        }

        DEBUGMSG(ZONE_PLUGIN,(L"LOC: Detecting provider <%s> is redundant since another provider will take care of dependent resolvers\r\n",
                              (*it)->GetName()));

        (*it)->StopPlugin();

        // Unlike StopPlugins(), no need to shutdown resolvers at this stage
        // since we know that provider going down is only being taken down
        // because there's another provider for its resolvers.
    }
}

// Stop providers that resolver started now that resolver is unavailable/error state/shutting down.
// We do this in order to save battery life.  For instance, assume that
// an Active Directory Resolver had an 802.11 Provider started to get
// nearby access points.  If the AD can no longer get data (or app deregisters for it), 
// then it's pointless to keep the 802.11 driver active to create reports no one
// will ever use.

void pluginMgr_t::StopDependentProvidersForResolver(resolver_t *pRes) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(pRes->GetState() <= PLUGIN_STATE_UNAVAILABLE);

    pluginList_t  pluginsToStop;

    DEBUGMSG(ZONE_PLUGIN,(L"LOC: Resolver <%s> is unavailable.  Stopping any plugins it may have loaded\r\n",
             pRes->GetName()));

    DWORD numSupportedReports;
    GUID  supportedReports[MAX_PLUGIN_REPORT_TYPES];
    pRes->GetSupportedReportInfo(supportedReports,&numSupportedReports);

    // For each report type that the resolver can support, unregister
    // from RC (if it was) and then stop associated plugins.

    for (DWORD i = 0; i < numSupportedReports; i++) {
        reportCol_t *pRC = FindRC(&supportedReports[i]);
        if (NULL == pRC) {
            // Just because a resolver supports a particular report type
            // does not mean a report collector for it was created.  We only
            // create an RC when a plugin actually generates that report.
            continue;
        }

        if (ERROR_SUCCESS != pRC->UnRegisterResolverForReport(pRes)) {
            // If the resolver wasn't registered with the RC in 1st place, continue

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?