📄 locplgmgr.cpp
字号:
continue;
}
if (pRC->HasRegisteredAppsOrResolvers()) {
// If the report type has other clients, we can't deregister it.
continue;
}
// Stop since this was the last client associated with the report
StopPlugins(&supportedReports[i],&pluginsToStop,0);
}
}
// When a provider becomes unavailable, it is possible that it had
// resolvers depending on it to generate reports. In this function,
// we will see if no other running providers generate this report and if they
// do not then we will try to start one.
// If it is not possible to start another plugin and hence a given resolver
// has no possibility of having a provider generate reports for it,
// then indicate to the resolver that is de facto unavailable (even
// if resolver could still in theory operate).
// For instance, suppose an Active Directory resolver relies on 802.11
// reports that the 802.11 provider generates. If the 802.11 provider
// becomes unavailable, then we should mark the AD Resolver as unavailable
// if and only if there are no other providers that could generate a report
// the AD supports.
void pluginMgr_t::ProcessProviderFailureOnResolvers(provider_t *pProv) {
DEBUGCHK(g_pLocLock->IsLocked());
DEBUGCHK((pProv->GetState() == PLUGIN_STATE_UNAVAILABLE) ||
(pProv->GetState() == PLUGIN_STATE_ERROR));
pluginListIter_t it = m_pluginList.begin();
pluginListIter_t itEnd = m_pluginList.end();
DEBUGMSG(ZONE_PLUGIN,(L"LOC: Determining which resolvers depended on unavailable provider <%s> and trying to restart\r\n",
pProv->GetName()));
// Iterate through each resolver, detecting if this provider was the last
// one that could generate reports.
for (; it != itEnd; ++it) {
if ((*it)->IsAProvider()) {
// Providers generate reports independent of one another. If
// one provider is unavailable it has no effect on other providers.
continue;
}
if ((*it)->GetState() < PLUGIN_STATE_UNAVAILABLE) {
// The resolver was not actively trying to determine new
// reports, so continue.
continue;
}
resolver_t *pRes = (resolver_t*)((plugin_t*)(*it));
BOOL noProvsAvailable = TRUE;
if (! pRes->HasProvidersAvailable()) {
// Resolver is already in state where nothing is available.
// Don't bother recomputing all this.
continue;
}
DWORD numSupportedReports;
GUID supportedReports[MAX_PLUGIN_REPORT_TYPES];
pRes->GetSupportedReportInfo(supportedReports,&numSupportedReports);
// For each report type that the resolver can support, determine
// if there is any *provider* that can generate the given type.
// Even one match is enough to indicate that the resolver is still valid.
for (DWORD i = 0; i < numSupportedReports; i++) {
PLUGIN_STATE repState = GetPluginInfoForReport(&supportedReports[i],NULL,TRUE);
if (repState >= PLUGIN_STATE_STARTING_UP) {
noProvsAvailable = FALSE;
break;
}
}
if (noProvsAvailable) {
// First, try to startup a new provider to do this work.
if (! StartDependentProviderIfNeeded(NULL,pRes)) {
// No providers can support this resolver even after this attempt.
// Indicate this to the resolver so it can take appropriate action.
pRes->NoProvidersAvailable();
// Try to startup next plugin for any reports that were registered
// for this resolver. Even if resolver would've been available
// otherwise, it's dead in the water without a provider.
StartNextPluginsOnFailure(pRes);
}
}
}
}
//*****************************************************************************
// Callback implementations
//*****************************************************************************
// A new provider report is available via NewProviderReport. Alert
// registered apps & resolvers, possibly stop lower priority plugins that
// were started up if this plugin was previously unavailable.
DWORD pluginMgr_t::NewProviderReportInd(HANDLE provContext, LOCATION_REPORT *pNewReport) {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Received NewProviderReport callback. Context=<0x%08x>, report=<0x%08x>\r\n",
provContext,pNewReport));
if (pNewReport == NULL) {
DEBUGMSG(ZONE_ERROR,(L"LOC: NewProviderReportInd passed NULL report, invalid\r\n"));
return ERROR_INVALID_PARAMETER;
}
provider_t *pProv;
reportCol_t *pRC;
LOCATION_REPORT_BASE *pNewReportBase = (LOCATION_REPORT_BASE *)pNewReport;
GUID *pNewReportType = &pNewReportBase->type;
DWORD err;
if (pNewReportBase->size < sizeof(LOCATION_REPORT_BASE)) {
DEBUGMSG(ZONE_ERROR,(L"LOC: NewProviderReportInd passed in report that is too small\r\n"));
return ERROR_INVALID_PARAMETER;
}
g_pLocLock->Lock();
if (g_serviceState != SERVICE_STATE_ON) {
// This indicates that the location service is shutting down. The last
// thing we want to do is start stopping & starting plugins, because
// otherwise the shutdown logic becomes much harder.
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Ignoring NewProviderReport since loc service is not on\r\n"));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
pProv = FindProvider(provContext);
if (!pProv) {
err = ERROR_INVALID_PARAMETER;
goto done;
}
PLUGIN_STATE oldState = pProv->GetState();
if (oldState < PLUGIN_STATE_UNAVAILABLE) {
// In this case, plugin isn't registered anymore so throw out
// any reports it may still be generating.
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Ignoring Provider Report for <%s> because state is off/error\r\n",
pProv->GetName()));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
// Indicate to reports collector monitoring this report type
if (! pProv->CanGenerateReportType(pNewReportType)) {
// For instance, if a lat/long only provider generates an 802.11 address or
// if we're not currently registered for the report, then ignore.
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Provider report for <%s> is not a report the provider is configured to generate\r\n",
pProv->GetName()));
err = ERROR_INVALID_PARAMETER;
goto done;
}
pRC = FindRC(pNewReportType);
pProv->ReportsAvailable();
if (pRC->NewReport(pProv,pNewReport)) {
// NewReport returns TRUE if the RC will use this report
// (i.e. not a higher prio plugin available).
if (! pProv->HasReceivedReport(pNewReportType)) {
// This is the first time on this ProviderGetLocation cycle
// that this report has been generated OR it's coming back
// from unavailable state. Indicate this state change to applications
// only the first time we transition to ON.
pRC->PluginStateChange();
}
}
pProv->IndicateReceivedReport(pNewReportType);
if ((oldState == PLUGIN_STATE_UNAVAILABLE) || (oldState == PLUGIN_STATE_STARTING_UP)) {
// In this case, the plugin was temporarily unavailable and
// lower priority plugins may have been started. Stop them.
StopPluginsOnProviderAvailable(pProv);
}
err = ERROR_SUCCESS;
done:
g_pLocLock->Unlock();
return err;
}
// Provider calls ProviderUnavailable callback. Move provider to
// the unavailable state.
DWORD pluginMgr_t::ProviderUnavailableInd(HANDLE provContext) {
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Received ProviderUnavailable callback. Context=<0x%08x>\r\n",
provContext));
provider_t *pProv;
DWORD err;
g_pLocLock->Lock();
if (g_serviceState != SERVICE_STATE_ON) {
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Ignoring ProviderUnavailable since loc service is not on\r\n"));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
pProv = FindProvider(provContext);
if (!pProv) {
err = ERROR_INVALID_PARAMETER;
goto done;
}
PLUGIN_STATE oldState = pProv->GetState();
if (oldState <= PLUGIN_STATE_UNAVAILABLE) {
// In this case, provider has already been put into the unavailable
// state. The provider is basically calling unavaibale a 2nd time
// (before giving new data) and hence we ignore this report.
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Ignoring Provider Unavialable for <%s> because state is off/error/unavail\r\n",
pProv->GetName()));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
pProv->ReportsUnavailable();
DEBUGMSG(ZONE_PROVIDER,(L"LOC: Marking provider <%s> as unavailable\r\n",pProv->GetName()));
// It doesn't matter if plugin was on or just starting up at this point -
// either way we need to try to start next plugin in line.
StartNextPluginsOnFailure(pProv);
// If there were resolvers that were relying on this provider to
// generate reports for them, need to either startup new providers
// or if that fails, disable the resolvers.
ProcessProviderFailureOnResolvers(pProv);
err = ERROR_SUCCESS;
done:
g_pLocLock->Unlock();
return err;
}
// Resolver cannot resolve a particular report.
DWORD pluginMgr_t::NewResolverReportInd(HANDLE resContext, LOCATION_REPORT *pNewReport) {
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Received NewResolverReport callback. Context=<0x%08x>, report=<0x%08x>\r\n",
resContext,pNewReport));
DWORD err;
if (pNewReport == NULL) {
DEBUGMSG(ZONE_ERROR,(L"LOC: NewResolverReport passed NULL report, invalid\r\n"));
return ERROR_SUCCESS;
}
LOCATION_REPORT_BASE *pNewReportBase = (LOCATION_REPORT_BASE*)pNewReport;
if (pNewReportBase->size < sizeof(LOCATION_REPORT_BASE)) {
DEBUGMSG(ZONE_ERROR,(L"LOC: NewResolverReport passed in report that is too small\r\n"));
return ERROR_INVALID_PARAMETER;
}
g_pLocLock->Lock();
if (g_serviceState != SERVICE_STATE_ON) {
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Ignoring NewResolverReport since loc service is not on\r\n"));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
resolver_t *pRes;
reportCol_t *pRC;
GUID *pNewReportType = &pNewReportBase->type;
pRes = FindResolver(resContext);
if (!pRes) {
err = ERROR_INVALID_PARAMETER;
goto done;
}
if (! pRes->CanGenerateReportType(pNewReportType)) {
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Resolver report for <%s> is not a report the resolver is requested to generate\r\n",
pRes->GetName()));
err = ERROR_INVALID_PARAMETER;
goto done;
}
PLUGIN_STATE oldStatePlugin = pRes->GetState();
PLUGIN_STATE oldStateReport = pRes->GetReportTypeState(pNewReportType);
if (oldStateReport < PLUGIN_STATE_UNAVAILABLE) {
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Resolver <%s> is not requested to generate this report type, ignoring report\r\n",
pRes->GetName()));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
if (! pRes->HasProvidersAvailable()) {
// If the resolver has all plugins inactive during its ResolverGetLocation
// call, then just throw out reports the resolver generates in the interim
// In theory we could still push these up to the app but it would greatly
// complicate the state maintenence for little gain.
DEBUGMSG(ZONE_RESOLVER,(L"LOC: Resolver <%s> does not have providers available, ignoring report\r\n",
pRes->GetName()));
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
// Indicate to reports collector monitoring this report type
pRC = FindRC(pNewReportType);
// Regardless of how we process report, always have resolver
// remember the fact it has received it so that when ResolverGetLocation
// callback returns resolver will not mark it as unavailable.
pRes->IndicateReceivedReport(pNewReportType);
if (oldStateReport == PLUGIN_STATE_ON) {
// If the plugin for this type is already in the ON state, then
// no further action is required.
pRC->NewReport(pRes,pNewReport);
err = ERROR_SUCCESS;
goto done;
}
if (oldStatePlugin == PLUGIN_STATE_UNAVAILABLE) {
// When the resolver entered the unavailable state, it stopped
// all the plugins that could register reports for it in order
// to save them from generating reports for nothing. Now that
// the resolver has returned, we need to start at least 1 up again.
if (! StartDependentProviderIfNeeded(pNewReportType,pRes)) {
// If we were unable to start providers, then we're dead in the water
// again. Take no further action
err = ERROR_SERVICE_NOT_ACTIVE;
goto done;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -