⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 locplgmgr.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    DEBUGCHK(g_pLocLock->IsLocked());

    reportColListIter_t it      = m_reportColList.begin();
    reportColListIter_t itEnd   = m_reportColList.end();

    for (; it != itEnd; ++it) {
        if (NULL != (*it)->FindRegisteredApp(pLocHandle)) {
            DWORD err = UnRegisterAppForReport(pLocHandle,(*it)->GetReportType());
            // Even if we don't stop the plugin, this should always succeed
            // since only error cases involve bogus input (which we know is valid)
            DEBUGCHK(err == ERROR_SUCCESS);
        }
    }
}

//*****************************************************************************
//  Routines for determining relationships between plugins - especially 
//  with regards to whether certain plugins need to be on at a given time
//*****************************************************************************

// Get the iteration pointer to the plugin of specified start order.
pluginListIter_t pluginMgr_t::GetPluginOfStartOrder(DWORD minStartOrder) {
    DEBUGCHK(minStartOrder <= (m_pluginList.size()));

    if (minStartOrder == (m_pluginList.size())) {
        // This indicates that we're requesting an index one past max
        // number of plugins on system.  This happens when the lowest priority
        // plugin asks to load the next lower prio (which doesn't exist).
        // To avoid sprinkling special case checks for lowestPrio plugin all over the 
        // place, just return iterator::end directly.
        return m_pluginList.end();
    }

    return m_pluginList.begin() + minStartOrder;
}


// Determines if plugin is required for pReportType.  See IsPluginNeeded()
// for details about when/why we call this.
BOOL pluginMgr_t::IsPluginNeededForReport(plugin_t *pPlugin, const GUID *pReportType, BOOL checkRegAppsOnly) {
    // If nothing has registered for this report type, then we do not nee
    DEBUGCHK(pPlugin->CanGenerateReportType(pReportType));
    reportCol_t *pRC = FindRC(pReportType);

    if (checkRegAppsOnly || pPlugin->IsAResolver()) {
        // We only care if a user application 
        // has registered for this report type.  We do NOT care if another resolver
        // has registered for this report type because even if the pPlugin
        // generated this report, the other resolver would never get it
        // since resolvers don't send reports to each other.
        if (! pRC->HasRegisteredApps())
            return FALSE;
    }
    else {
        // For a provider (and checkRegAppsOnly=0), either a resolver or an 
        // application being registered for this report type is interesting.
        if (! pRC->HasRegisteredAppsOrResolvers())
            return FALSE;
    }

    // In this case, there is some client that cares about this report
    // Determine if a higher priority plugin can generate it.
    BOOL highPrioPluginAvail = ExistsHigherPrioPluginForReport(pPlugin,pReportType);

    if (! highPrioPluginAvail) {
        // If this plugin is highest priority on the system that 
        // can generate this particular report type, it's still needed
        // Unless...

        if (pPlugin->IsAProvider() && 
            IsProviderRedundantForResolvers((provider_t*)pPlugin,pReportType))
        {
            // ... there is a special case for providers where
            // the provider may not be needed after all.  See 
            // IsProviderRedundantForResolvers for details.
            return FALSE;
        }
        return TRUE;
    }

    // If none of above conditions are met, then plugin isn't needed
    // in order to generate pReportType.
    return FALSE;
}

// When a plugin goes from the unavailable to available state, plugins
// of a lower priority that generate the same report should be stopped.
// This function determines if a given plugin is in such a state - namely
// are all the reports that it has been requested to generate already
// being generated by a higher priority plugin.

// This is complicated by the fact that plugins can generate multiple report
// types.  Consider for instance plugin P1 that generates reports R1, R2, R3.
// Plugin P2 generates R2, R3, and R4.  If P1 was asked to generate R2 but
// becomes unavailable, then P2 will be started.  If P1 becomes available again,
// we would stop P2 now UNLESS another app requested report R4 to be generated.
// Since P1 doesn't generate R4, we would need to leave P2 on to do this.
BOOL pluginMgr_t::IsPluginNeeded(plugin_t *pPlugin) {
    GUID  generatedReports[MAX_PLUGIN_REPORT_TYPES];
    DWORD numGeneratedReports;
    DWORD minStartOrder = pPlugin->GetStartOrder();

    DEBUGCHK(pPlugin->GetState() >= PLUGIN_STATE_SHUTTING_DOWN);

    pPlugin->GetGeneratedReportInfo(generatedReports, &numGeneratedReports);

    // For each possible report the plugin can generate, determine whether plugin
    // needs to be left on for it.
    for (DWORD i = 0; i < numGeneratedReports; i++) {
        if (IsPluginNeededForReport(pPlugin,&generatedReports[i],FALSE))
            return TRUE;
    }

    return FALSE;
}


// IsProviderRedundantForResolvers determines if provider is no longer 
// required for dependent resolvers since a suitable substitute has been found.

// For instance, consider a system with Providers P1 and P2, P1 higher prio.
// P1 generates report type Rep1, P2 generates report type Rep2.  Resolver Res1
// can support either R1 or R2.
// P1 was unavailable and P2 is on to service Res1.  However once P1 becomes
// available again, we no longer need P2 (assuming no apps registered for Rep2)
// since P1 will generate reports for Res1.

// The base IsPluginNeeded() logic will not detect this subtle relationship
// between providers and resolvers, so we do this extra check here.
BOOL pluginMgr_t::IsProviderRedundantForResolvers(provider_t *pProv, const GUID *pReportType) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK((pProv->GetState() >= PLUGIN_STATE_UNAVAILABLE) || (pProv->GetState() == PLUGIN_STATE_ERROR));
    DEBUGCHK(! ExistsHigherPrioPluginForReport(pProv,pReportType));

    reportCol_t *pRC = FindRC(pReportType);
    DEBUGCHK(pRC->HasRegisteredAppsOrResolvers());

    if (pRC->HasRegisteredApps()) {
        // If an application has registered for this report type
        // and this is highest priority plugin on system that 
        // can generate it, then the resolver redandancy does not apply
        return FALSE;
    }

    // For each resolver that supports this report type, see if there is an 
    // active provider that can generate reports for the resolver as well.

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

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

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

        if (pRes->GetState() < PLUGIN_STATE_UNAVAILABLE) {
            // If the resolver is attempting to determine location, then 
            // no provider is needed for it.
            continue;
        }

        if (! pRes->CanSupportReportType(pReportType)) {
            // If resolver can't generate this type anyway, then this provider
            // generating it is irrelevant
            continue;
        }

        // Now see if there is a provider of higher priority than pProv
        // that is active and can generate a report the resolver supports.
        // If one does not exist, then this provider is needed (hence not redundant)
        if (! ExistsHigherPrioActiveProviderForResolver(pRes,pProv->GetStartOrder()))
            return FALSE;
    }

    // For each resolver on the system that supports pReportType, we have 
    // verified that pProv is not needed.
    return TRUE;
}

// Determines if for pReportType, whether there is a higher priority
// plugin AVAILABLE on the system to service it than pPlugin.
BOOL pluginMgr_t::ExistsHigherPrioPluginForReport(plugin_t *pPlugin, const GUID *pReportType) {
    pluginListIter_t it    = m_pluginList.begin();
    pluginListIter_t itEnd = GetPluginOfStartOrder(pPlugin->GetStartOrder());

    // Iterate through each plugin on the system, from highest prio
    // until we reach the current pPlugin.
    for (; it != itEnd; it++) {
        if (! (*it)->CanGenerateReportType(pReportType)) {
            // Plugin can't generate this report in any event.
            continue;
        }

        PLUGIN_STATE pluginState = (*it)->GetReportTypeState(pReportType);
        if (pluginState >= PLUGIN_STATE_STARTING_UP) {
            // There is a higher priority plugin on the system that
            // can generate this report type.
            return TRUE;
        }
    }

    // No higher priority plugin for this report found
    return FALSE;
}

// Determines if there is a provider with start order < minStartOrder AND
// is active AND can generate a report that the given resolver supports.
BOOL pluginMgr_t::ExistsHigherPrioActiveProviderForResolver(resolver_t *pRes, DWORD minStartOrder) {
    pluginListIter_t it    = m_pluginList.begin();
    pluginListIter_t itEnd = GetPluginOfStartOrder(minStartOrder);

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

        if ((*it)->GetState() < PLUGIN_STATE_STARTING_UP) {
            // Plugin is not active
            continue;
        }

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

        for (DWORD i = 0; i < numGeneratedReports; i++) {
            if (pRes->CanSupportReportType(&generatedReports[i])) {
                // This resolver could be service by provider (*it).
                return TRUE;
            } 
        }
    }

    // No suitable providers found that can generate reports for this resolver.
    return FALSE;
}


//*****************************************************************************
//  Routines for starting up and stopping plugins 
//*****************************************************************************

// Tries to start a particular plugin for the given reportType.  This function
// verifies that the plugin can support the report type and if it can, will
// determine how to proceeed based on the current plugin state.
BOOL pluginMgr_t::StartPluginIfPossible(plugin_t *pPlugin, const GUID *pReportType) {
    DEBUGCHK(g_pLocLock->IsLocked());
    DEBUGCHK(g_serviceState == SERVICE_STATE_ON);

    BOOL ret;

    // If plugin can't even support requested type, then we're done
    if (! pPlugin->CanGenerateReportType(pReportType))
        return FALSE;

    PLUGIN_STATE reportState = pPlugin->GetReportTypeState(pReportType);

    // If this is a resolver, check its state for particular type
    // against unavailable first.  Resolver as a whole may be on
    // but this report may already have been tried but marked unavailable.
    if (pPlugin->IsAResolver() && (reportState == PLUGIN_STATE_UNAVAILABLE))
        return FALSE;

    // The plugin can generate this report type.  How we proceed is 
    // based on the current state the plugin is in.
    switch (pPlugin->GetState()) {
    case PLUGIN_STATE_ON:
    {
        // If plugin is on already, then we're where we want to be.

        // Explicitly (possibly redundant) register for this report in case 
        // this is a resolver, since resolver may be on for another report but
        // not this one.
        pPlugin->RequestReportGeneration(pReportType);
        ret = TRUE;
    }
    break;
    
    case PLUGIN_STATE_STARTING_UP:
    {
        // If plugin starting up, then we'll use it while realizing
        // it may be some time before it's ready. 
        pPlugin->RequestReportGeneration(pReportType);
        ret = TRUE;
    }
    break;

    case PLUGIN_STATE_SHUTTING_DOWN:
    {
        // If plugin was in middle of shutdown, just let it know
        // that we want to restart right away.  We'll have to let the
        // shutdown complete before we can do anything else, so just indicate this for now.
        pPlugin->RequestReportGeneration(pReportType);
        pPlugin->SetImmediateRestart();
        ret = TRUE;
    }
    break;

    case PLUGIN_STATE_ERROR:
    {
        // Plugin is in non-recoverable state.  Nothing we can do.
        ret = FALSE;
    }
    break;

    case PLUGIN_STATE_UNAVAILABLE:
    {
        // Plugin is temporarily unavailable (i.e. GPS device is inside)
        // then we can't start it.  When the device becomes available again,
        // our retry logic will stop any lower-prio plugins automatically.
        pPlugin->RequestReportGeneration(pReportType);
        ret = FALSE;
    }
    break;

    case PLUGIN_STATE_OFF:
    {
        // Plugin is off but we want it on.
        if (pPlugin->IsAProvider()) {
            // For provider case, need to spin up a thread to call
            // ProviderGetLocation export
            provider_t *pProv = (provider_t*)pPlugin;

            if (ERROR_SUCCESS != pProv->ScheduleWorkerIfNeeded())
                return FALSE;

            pProv->RequestReportGeneration(pReportType);
            pProv->StartingUp();
            ret = TRUE;
        }
        else {

⌨️ 快捷键说明

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