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 + -
显示快捷键?