(file) Return to SubscriptionTable.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / IndicationService

File: [Pegasus] / pegasus / src / Pegasus / IndicationService / SubscriptionTable.cpp (download)
Revision: 1.12, Tue May 9 18:09:36 2006 UTC (18 years, 1 month ago) by carolann.graves
Branch: MAIN
CVS Tags: TASK_BUG_5314_IPC_REFACTORING_ROOT, TASK_BUG_5314_IPC_REFACTORING_BRANCH, TASK_BUG_5314_IPC_REFACTORING-V1, TASK_BUG_5191_QUEUE_CONSOLIDATION_ROOT, TASK_BUG_5191_QUEUE_CONSOLIDATION_BRANCH, TASK-TASK-BUG4011_WinLocalConnect-branch-New-root, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_out_to_branch, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_out_from_trunk, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_in_to_trunk, TASK-TASK-BUG4011_WinLocalConnect-branch-New-merged_in_from_branch, TASK-TASK-BUG4011_WinLocalConnect-branch-New-branch, TASK-PEP268_SSLClientCertificatePropagation-root, TASK-PEP268_SSLClientCertificatePropagation-merged_out_to_branch, TASK-PEP268_SSLClientCertificatePropagation-merged_out_from_trunk, TASK-PEP268_SSLClientCertificatePropagation-merged_in_to_trunk, TASK-PEP268_SSLClientCertificatePropagation-merged_in_from_branch, TASK-PEP268_SSLClientCertificatePropagation-branch, TASK-PEP267_SLPReregistrationSupport-root, TASK-PEP267_SLPReregistrationSupport-merging_out_to_branch, TASK-PEP267_SLPReregistrationSupport-merged_out_to_branch, TASK-PEP267_SLPReregistrationSupport-merged_out_from_trunk, TASK-PEP267_SLPReregistrationSupport-merged_in_to_trunk, TASK-PEP267_SLPReregistrationSupport-merged_in_from_branch, TASK-PEP267_SLPReregistrationSupport-branch, TASK-Bugs5690_3913_RemoteCMPI-root, TASK-Bugs5690_3913_RemoteCMPI-merged_out_to_branch, TASK-Bugs5690_3913_RemoteCMPI-merged_out_from_trunk, TASK-Bugs5690_3913_RemoteCMPI-merged_in_to_trunk, TASK-Bugs5690_3913_RemoteCMPI-merged_in_from_branch, TASK-Bugs5690_3913_RemoteCMPI-branch, TASK-BUG4011_WinLocalConnect-root, TASK-BUG4011_WinLocalConnect-merged_out_to_branch, TASK-BUG4011_WinLocalConnect-merged_out_from_trunk, TASK-BUG4011_WinLocalConnect-merged_in_to_trunk, TASK-BUG4011_WinLocalConnect-merged_in_from_branch, TASK-BUG4011_WinLocalConnect-branch-New, TASK-BUG4011_WinLocalConnect-branch
Changes since 1.11: +203 -36 lines
BUG#: 4906
TITLE: Improved handling of OOP indication provider module failure is needed

DESCRIPTION: Added a callback in the ProviderManagerService, to be called when failure of an Out-Of-Process provider module is detected.  The ProviderManagerService logs a generic message, and notifies the IndicationService of the module failure.  The IndicationService determines if any active subscriptions were affected, updates its Active Subscriptions hash table, and responds to the ProviderManagerService with the number of affected subscriptions.  If any subscriptions were affected, the ProviderManagerService updates the provider module status to Degraded, and logs a more specific warning message.

//%2006////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation, The Open Group.
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; VERITAS Software Corporation; The Open Group.
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
// EMC Corporation; Symantec Corporation; The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Carol Ann Krug Graves, Hewlett-Packard Company
//             (carolann_graves@hp.com)
//
// Modified By:  
//              Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
//              Aruran, IBM (ashanmug@in.ibm.com) for Bug# 3603
//
//%/////////////////////////////////////////////////////////////////////////////

#include <Pegasus/Common/Config.h>
#include <Pegasus/Common/Constants.h>
#include <Pegasus/Common/Tracer.h>

#include "IndicationConstants.h"
#include "IndicationService.h"
#include "SubscriptionTable.h"

PEGASUS_USING_STD;

PEGASUS_NAMESPACE_BEGIN

SubscriptionTable::SubscriptionTable (
    SubscriptionRepository * subscriptionRepository)
    : _subscriptionRepository (subscriptionRepository)
{
}

SubscriptionTable::~SubscriptionTable ()
{
}

Boolean SubscriptionTable::getSubscriptionEntry (
    const CIMObjectPath & subscriptionPath,
    ActiveSubscriptionsTableEntry & tableValue) const
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::getSubscriptionEntry");

    Boolean succeeded = false;
    CIMObjectPath activeSubscriptionsKey = _generateActiveSubscriptionsKey
        (subscriptionPath);
    if (_lockedLookupActiveSubscriptionsEntry
        (activeSubscriptionsKey, tableValue))
    {
        succeeded = true;
    }
    else
    {
        //
        //  Subscription not found in Active Subscriptions table
        //
        PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL2,
            "Subscription (" + activeSubscriptionsKey.toString () +
            ") not found in ActiveSubscriptionsTable");
    }

    PEG_METHOD_EXIT ();
    return succeeded;
}

Array <CIMInstance> SubscriptionTable::getMatchingSubscriptions (
    const CIMName & supportedClass,
    const Array <CIMNamespaceName> nameSpaces,
    const Boolean checkProvider,
    const CIMInstance & provider) const
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::getMatchingSubscriptions");

    Array <CIMInstance> matchingSubscriptions;
    Array <CIMInstance> subscriptions;

    for (Uint32 i = 0; i < nameSpaces.size (); i++)
    {
        //
        //  Look up the indicationClass-sourceNamespace pair in the
        //  Subscription Classes table
        //
        String subscriptionClassesKey = _generateSubscriptionClassesKey
            (supportedClass, nameSpaces [i]);
        SubscriptionClassesTableEntry tableValue;
        if (_lockedLookupSubscriptionClassesEntry (subscriptionClassesKey,
            tableValue))
        {
            subscriptions = tableValue.subscriptions;
            for (Uint32 j = 0; j < subscriptions.size (); j++)
            {
                Boolean match = true;

                if (checkProvider)
                {
                    //
                    //  Check if the provider who generated this indication
                    //  accepted this subscription
                    //
                    CIMObjectPath activeSubscriptionsKey =
                        _generateActiveSubscriptionsKey
                            (subscriptions [j].getPath ());
                    ActiveSubscriptionsTableEntry tableValue;
                    if (_lockedLookupActiveSubscriptionsEntry
                        (activeSubscriptionsKey, tableValue))
                    {
                        //
                        //  If provider is not in list, it did not accept the
                        //  subscription
                        //
                        if ((providerInList (provider, tableValue)) ==
                            PEG_NOT_FOUND)
                        {
                            match = false;
                            break;
                        }
                    }
                }

                if (match)
                {
                    //
                    //  Add current subscription to list
                    //
                    matchingSubscriptions.append (subscriptions [j]);
                }
            }
        }
    }

    PEG_METHOD_EXIT ();
    return matchingSubscriptions;
}

Array <CIMInstance> SubscriptionTable::reflectProviderDisable (
    const CIMInstance & provider)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::reflectProviderDisable");

    Array <CIMInstance> providerSubscriptions;

    //
    //  Iterate through the subscription table to find subscriptions served by
    //  the provider
    //  NOTE: updating entries (remove and insert) while iterating through the
    //  table does not work reliably, and it is not clear if that is supposed to
    //  work; for now, the SubscriptionTable first iterates through the
    //  active subscriptions table to find subscriptions served by the
    //  provider, then looks up and updates each affected subscription
    //
    {
        //
        //  Acquire and hold the write lock during the entire
        //  lookup/remove/insert process, allowing competing threads to apply
        //  their logic over a consistent view of the data.
        //  Do not call any other methods that need 
        //  _activeSubscriptionsTableLock.
        //
        WriteLock lock (_activeSubscriptionsTableLock);

        for (ActiveSubscriptionsTable::Iterator i =
            _activeSubscriptionsTable.start (); i; i++)
        {
            //
            //  If provider matches, append subscription to the list
            //
            ActiveSubscriptionsTableEntry tableValue = i.value ();
            for (Uint32 j = 0; j < tableValue.providers.size (); j++)
            {
                if (tableValue.providers [j].provider.getPath ().identical
                    (provider.getPath ()))
                {
                    //
                    //  Add the subscription to the list
                    //
                    providerSubscriptions.append (tableValue.subscription);
                    break;
                }
            }
        }

        //
        //  Look up and update hash table entry for each affected subscription
        //
        for (Uint32 k = 0; k < providerSubscriptions.size (); k++)
        {
            //
            //  Update the entry in the active subscriptions hash table
            //
            CIMObjectPath activeSubscriptionsKey =
                _generateActiveSubscriptionsKey
                    (providerSubscriptions [k].getPath ());
            ActiveSubscriptionsTableEntry tableValue;
            if (_activeSubscriptionsTable.lookup (activeSubscriptionsKey,
                tableValue))
            {
                //
                //  Remove the provider from the list of providers serving the
                //  subscription
                //
                Uint32 providerIndex = providerInList (provider, tableValue);
                if (providerIndex != PEG_NOT_FOUND)
                {
                    tableValue.providers.remove (providerIndex);

                    _updateSubscriptionProviders (activeSubscriptionsKey,
                        tableValue.subscription, tableValue.providers);
                }
                else
                {
                    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL,
                        Tracer::LEVEL2,
                        "Provider (" + provider.getPath().toString() +
                        ") not found in list for Subscription (" +
                        activeSubscriptionsKey.toString () +
                        ") in ActiveSubscriptionsTable");
                }
            }
            else
            {
                PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, 
                    Tracer::LEVEL2,
                    "Subscription (" + activeSubscriptionsKey.toString () +
                    ") not found in ActiveSubscriptionsTable");
                //
                //  The subscription may have been deleted in the mean time
                //  If so, no further update is required
                //
            }
        }
    }

    PEG_METHOD_EXIT ();
    return providerSubscriptions;
}

Array <ActiveSubscriptionsTableEntry>
SubscriptionTable::reflectProviderModuleFailure
    (const String & moduleName,
     const String & userName,
     Boolean authenticationEnabled)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::reflectProviderModuleFailure");

    Array <ActiveSubscriptionsTableEntry> providerModuleSubscriptions;

    //
    //  Iterate through the subscription table to find subscriptions served by
    //  a provider in the specified module, with the specified userName as the
    //  subscription creator
    //  NOTE: updating entries (remove and insert) while iterating through the
    //  table is not allowed
    //  The SubscriptionTable first iterates through the active subscriptions
    //  table to find matching subscriptions served by a provider in the
    //  specified module, then looks up and updates each affected subscription
    //
    {
        //
        //  Acquire and hold the write lock during the entire
        //  lookup/remove/insert process, allowing competing threads to apply
        //  their logic over a consistent view of the data.
        //  Do not call any other methods that need 
        //  _activeSubscriptionsTableLock.
        //
        WriteLock lock (_activeSubscriptionsTableLock);

        for (ActiveSubscriptionsTable::Iterator i =
            _activeSubscriptionsTable.start (); i; i++)
        {
            ActiveSubscriptionsTableEntry tableValue;
            //
            //  Get subscription creator
            //
            tableValue = i.value ();
            String creator;
            CIMValue creatorValue = tableValue.subscription.getProperty
                (tableValue.subscription.findProperty
                (PEGASUS_PROPERTYNAME_INDSUB_CREATOR)).getValue();
            creatorValue.get (creator);

            Array <ProviderClassList> failedProviderList;
            for (Uint32 j = 0; j < tableValue.providers.size (); j++)
            {
                //
                //  Get provider module name
                //
                String providerModuleName;
                CIMValue nameValue =
                    tableValue.providers [j].providerModule.getProperty
                    (tableValue.providers [j].providerModule.findProperty
                    (_PROPERTY_NAME)).getValue ();
                nameValue.get (providerModuleName);

                //
                //  Get module user context setting
                //
                Uint16 moduleContext = PEGASUS_DEFAULT_PROV_USERCTXT;
                CIMValue contextValue = 
                    tableValue.providers [j].providerModule.getProperty
                    (tableValue.providers [j].providerModule.findProperty
                    (PEGASUS_PROPERTYNAME_MODULE_USERCONTEXT)).getValue ();
                if (!contextValue.isNull ())
                {
                    contextValue.get (moduleContext);
                }

                //
                //  If provider module name matches, 
                //  add provider to the list of failed providers
                //
                if (providerModuleName == moduleName)
                {
                    //
                    //  If authentication is enabled, and module was run as
                    //  requestor, subscription creator must also match module
                    //  user context name, to add provider to the list of
                    //  failed providers
                    //
                    if ((moduleContext != PG_PROVMODULE_USERCTXT_REQUESTOR) ||
                        (!authenticationEnabled) || (creator == userName))
                    {
                        //
                        //  Add the provider to the list
                        //
                        failedProviderList.append
                            (tableValue.providers [j]);
                    }
                }  //  if provider module name matches
            }  //  for each subscription provider

            //
            //  If there were any failed providers, add the subscription
            //  entry to the list of affected subscriptions
            //
            if (failedProviderList.size () > 0)
            {
                ActiveSubscriptionsTableEntry subscription;
                subscription.subscription = tableValue.subscription;
                subscription.providers = failedProviderList;
                providerModuleSubscriptions.append (subscription);
            }
        }

        //
        //  Look up and update hash table entry for each affected subscription
        //
        for (Uint32 k = 0; k < providerModuleSubscriptions.size (); k++)
        {
            //
            //  Update the entry in the active subscriptions hash table
            //
            CIMObjectPath activeSubscriptionsKey =
                _generateActiveSubscriptionsKey
                    (providerModuleSubscriptions [k].subscription.getPath ());
            ActiveSubscriptionsTableEntry tableValue;
            if (_activeSubscriptionsTable.lookup (activeSubscriptionsKey,
                tableValue))
            {
                Array <ProviderClassList> updatedProviderList;    
                for (Uint32 l = 0; l < tableValue.providers.size (); l++)
                {
                    String providerModuleName;
                    CIMValue nameValue =
                        tableValue.providers [l].providerModule.getProperty
                        (tableValue.providers [l].providerModule.findProperty
                        (_PROPERTY_NAME)).getValue ();
                    nameValue.get (providerModuleName);
                    if (providerModuleName != moduleName)
                    {
                        //
                        //  Provider is not in the failed module
                        //  Append provider to list of providers still serving
                        //  the subscription
                        //
                        updatedProviderList.append (tableValue.providers [l]);
                    }
                }

                _updateSubscriptionProviders (activeSubscriptionsKey,
                    tableValue.subscription, updatedProviderList);
            }
        }
    }

    PEG_METHOD_EXIT ();
    return providerModuleSubscriptions;
}

CIMObjectPath SubscriptionTable::_generateActiveSubscriptionsKey (
    const CIMObjectPath & subscription) const
{
    //
    //  Get filter and handler object paths from subscription Filter and Handler
    //  reference property values
    //
    Array<CIMKeyBinding> subscriptionKB = subscription.getKeyBindings ();
    CIMObjectPath filterPath;
    CIMObjectPath handlerPath;
    for (Uint32 i = 0; i < subscriptionKB.size (); i++)
    {
        if ((subscriptionKB [i].getName () == _PROPERTY_FILTER) &&
            (subscriptionKB [i].getType () == CIMKeyBinding::REFERENCE))
        {
            filterPath = subscriptionKB [i].getValue ();
        }
        if ((subscriptionKB [i].getName () == _PROPERTY_HANDLER) &&
            (subscriptionKB [i].getType () == CIMKeyBinding::REFERENCE))
        {
            handlerPath = subscriptionKB [i].getValue ();
        }
    }

    //
    //  Construct subscription object name for key
    //
    filterPath.setHost (String::EMPTY);
    handlerPath.setHost (String::EMPTY);
    Array <CIMKeyBinding> kb;
    kb.append (CIMKeyBinding (_PROPERTY_FILTER, CIMValue (filterPath)));
    kb.append (CIMKeyBinding (_PROPERTY_HANDLER, CIMValue (handlerPath)));
    CIMObjectPath activeSubscriptionsKey ("", subscription.getNameSpace (),
        subscription.getClassName (), kb);

    return activeSubscriptionsKey;
}

Boolean SubscriptionTable::_lockedLookupActiveSubscriptionsEntry (
    const CIMObjectPath & key,
    ActiveSubscriptionsTableEntry & tableEntry) const
{
    ReadLock lock(_activeSubscriptionsTableLock);

    return (_activeSubscriptionsTable.lookup (key, tableEntry));
}

void SubscriptionTable::_insertActiveSubscriptionsEntry (
    const CIMInstance & subscription,
    const Array <ProviderClassList> & providers)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::_insertActiveSubscriptionsEntry");

    CIMObjectPath activeSubscriptionsKey = _generateActiveSubscriptionsKey
        (subscription.getPath ());
    ActiveSubscriptionsTableEntry entry;
    entry.subscription = subscription;
    entry.providers = providers;

    //
    //  Insert returns true on success, false if duplicate key
    //
    Boolean succeeded = _activeSubscriptionsTable.insert
        (activeSubscriptionsKey, entry);
    PEGASUS_ASSERT (succeeded);

#ifdef PEGASUS_INDICATION_HASHTRACE
    String traceString;
    traceString.append (activeSubscriptionsKey);
    traceString.append (" Providers: ");
    for (Uint32 i = 0; i < providers.size (); i++)
    {
        String providerName = providers [i].provider.getProperty
            (providers [i].provider.findProperty
            (_PROPERTY_NAME)).getValue ().toString ();
        traceString.append (providerName);
        traceString.append ("  Classes: ");
        for (Uint32 j = 0; j < providers[i].classList.size (); j++)
        {
             traceString.append (providers[i].classList[j].getString());
             traceString.append ("  ");
        }
    }

    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL3,
        "INSERTED _activeSubscriptionsTable entry: " + traceString);
#endif

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::_removeActiveSubscriptionsEntry (
    const CIMObjectPath & key)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::_removeActiveSubscriptionsEntry");

    //
    //  Remove returns true on success, false if not found
    //
    Boolean succeeded = _activeSubscriptionsTable.remove (key);
    PEGASUS_ASSERT (succeeded);

#ifdef PEGASUS_INDICATION_HASHTRACE
    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL,
                      Tracer::LEVEL3,
                      "REMOVED _activeSubscriptionsTable entry: " +
                      key.toString ());
#endif

    PEG_METHOD_EXIT ();
}

String SubscriptionTable::_generateSubscriptionClassesKey (
    const CIMName & indicationClassName,
    const CIMNamespaceName & sourceNamespaceName) const
{
    String subscriptionClassesKey;

    //
    //  Append indication class name to key
    //
    subscriptionClassesKey.append (indicationClassName.getString ());

    //
    //  Append source namespace name to key
    //
    subscriptionClassesKey.append (sourceNamespaceName.getString ());

    return subscriptionClassesKey;
}

Boolean SubscriptionTable::_lockedLookupSubscriptionClassesEntry (
    const String & key,
    SubscriptionClassesTableEntry & tableEntry) const
{
    ReadLock lock(_subscriptionClassesTableLock);

    return (_subscriptionClassesTable.lookup (key, tableEntry));
}

void SubscriptionTable::_insertSubscriptionClassesEntry (
    const CIMName & indicationClassName,
    const CIMNamespaceName & sourceNamespaceName,
    const Array <CIMInstance> & subscriptions)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::_insertSubscriptionClassesEntry");

    String subscriptionClassesKey = _generateSubscriptionClassesKey
        (indicationClassName, sourceNamespaceName);
    SubscriptionClassesTableEntry entry;
    entry.indicationClassName = indicationClassName;
    entry.sourceNamespaceName = sourceNamespaceName;
    entry.subscriptions = subscriptions;

    //
    //  Insert returns true on success, false if duplicate key
    //
    Boolean succeeded = _subscriptionClassesTable.insert
        (subscriptionClassesKey, entry);
    PEGASUS_ASSERT (succeeded);

#ifdef PEGASUS_INDICATION_HASHTRACE
    String traceString;
    traceString.append (subscriptionClassesKey);
    traceString.append (" Subscriptions: ");
    for (Uint32 i = 0; i < subscriptions.size (); i++)
    {
        traceString.append (subscriptions [i].getPath ().toString());
        traceString.append ("  ");
    }

    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL3,
        "INSERTED _subscriptionClassesTable entry: " + traceString);
#endif

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::_removeSubscriptionClassesEntry (
    const String & key)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::_removeSubscriptionClassesEntry");

    //
    //  Remove returns true on success, false if not found
    //
    Boolean succeeded = _subscriptionClassesTable.remove (key);
    PEGASUS_ASSERT (succeeded);

#ifdef PEGASUS_INDICATION_HASHTRACE
    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL3,
        "REMOVED _subscriptionClassesTable entry: " + key);
#endif

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::_updateSubscriptionProviders
    (const CIMObjectPath & activeSubscriptionsKey,
     const CIMInstance & subscription,
     const Array <ProviderClassList> & updatedProviderList)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::_updateSubscriptionProviders");

    if (updatedProviderList.size () > 0)
    {
        //
        //  At least one provider is still serving the
        //  subscription
        //  Update entry in Active Subscriptions table
        //
        _removeActiveSubscriptionsEntry (activeSubscriptionsKey);
        _insertActiveSubscriptionsEntry (subscription, updatedProviderList);
    }
    else
    {
        //
        //  The disabled or failed provider(s) was (were) the only provider(s)
        //  serving the subscription
        //  Implement the subscription's On Fatal Error Policy
        //
        Boolean removedOrDisabled =
            _subscriptionRepository->reconcileFatalError (subscription);
        _removeActiveSubscriptionsEntry (activeSubscriptionsKey);
        if (!removedOrDisabled)
        {
            //
            //  If subscription was not disabled or deleted
            //  Update entry in Active Subscriptions table
            //  Note that in this case the updatedProviderList is
            //  empty - no providers are serving the subscription
            //  currently
            //
            _insertActiveSubscriptionsEntry (subscription,
                updatedProviderList);
        }
    }

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::insertSubscription (
    const CIMInstance & subscription,
    const Array <ProviderClassList> & providers,
    const Array <CIMName> & indicationSubclassNames,
    const CIMNamespaceName & sourceNamespaceName)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::insertSubscription");

    //
    //  Insert entry into active subscriptions table
    //
    {
        WriteLock lock(_activeSubscriptionsTableLock);

        _insertActiveSubscriptionsEntry (subscription, providers);
    }

    //
    //  Insert or update entries in subscription classes table
    //
    {
        //
        //  Acquire and hold the write lock during the entire
        //  lookup/remove/insert process, allowing competing threads to apply
        //  their logic over a consistent view of the data.
        //  Do not call any other methods that need 
        //  _subscriptionClassesTableLock.
        //
        WriteLock lock (_subscriptionClassesTableLock);
        for (Uint32 i = 0; i < indicationSubclassNames.size (); i++)
        {
            String subscriptionClassesKey = _generateSubscriptionClassesKey
                (indicationSubclassNames [i], sourceNamespaceName);
            SubscriptionClassesTableEntry tableValue;
            if (_subscriptionClassesTable.lookup (subscriptionClassesKey,
                tableValue))
            {
                //
                //  If entry exists for this IndicationClassName-SourceNamespace
                //  pair, remove old entry and insert new entry
                //
                Array <CIMInstance> subscriptions = tableValue.subscriptions;
                subscriptions.append (subscription);
                _removeSubscriptionClassesEntry (subscriptionClassesKey);
                _insertSubscriptionClassesEntry (indicationSubclassNames [i],
                    sourceNamespaceName, subscriptions);
            }
            else
            {
                //
                //  If no entry exists for this
                //  IndicationClassName-SourceNamespace pair, insert new entry
                //
                Array <CIMInstance> subscriptions;
                subscriptions.append (subscription);
                _insertSubscriptionClassesEntry (indicationSubclassNames [i],
                    sourceNamespaceName, subscriptions);
            }
        }
    }

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::updateProviders (
    const CIMObjectPath & subscriptionPath,
    const ProviderClassList & provider,
    Boolean addProvider)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::updateProviders");

    CIMObjectPath activeSubscriptionsKey = _generateActiveSubscriptionsKey
        (subscriptionPath);
    ActiveSubscriptionsTableEntry tableValue;
    {
        //
        //  Acquire and hold the write lock during the entire
        //  lookup/remove/insert process, allowing competing threads to apply
        //  their logic over a consistent view of the data.
        //  Do not call any other methods that need 
        //  _activeSubscriptionsTableLock.
        //
        WriteLock lock (_activeSubscriptionsTableLock);
        if (_activeSubscriptionsTable.lookup (activeSubscriptionsKey,
            tableValue))
        {
            Uint32 providerIndex = providerInList (provider.provider, 
                tableValue);
            if (addProvider)
            {
                if (providerIndex == PEG_NOT_FOUND)
                {
                    tableValue.providers.append (provider);
                    _removeActiveSubscriptionsEntry (activeSubscriptionsKey);
                    _insertActiveSubscriptionsEntry (tableValue.subscription,
                        tableValue.providers);
                }
                else
                {
                    CIMInstance p = provider.provider;
                    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL,
                        Tracer::LEVEL2,
                        "Provider " + 
                        IndicationService::getProviderLogString (p) +
                        " already in list for Subscription (" +
                        activeSubscriptionsKey.toString () +
                        ") in ActiveSubscriptionsTable");
                }
            }
            else
            {
                if (providerIndex != PEG_NOT_FOUND)
                {
                    tableValue.providers.remove (providerIndex);
                    _removeActiveSubscriptionsEntry (activeSubscriptionsKey);
                    _insertActiveSubscriptionsEntry (tableValue.subscription,
                        tableValue.providers);
                }
                else
                {
                    CIMInstance p = provider.provider;
                    PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL,
                        Tracer::LEVEL2,
                        "Provider " + 
                        IndicationService::getProviderLogString (p) +
                        " not found in list for Subscription (" +
                        activeSubscriptionsKey.toString () +
                        ") in ActiveSubscriptionsTable");
                }
            }
        }
        else
        {
            PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL2,
                "Subscription (" + activeSubscriptionsKey.toString () +
                ") not found in ActiveSubscriptionsTable");
    
            //
            //  The subscription may have been deleted in the mean time
            //  If so, no further update is required
            //
        }
    }

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::updateClasses (
    const CIMObjectPath & subscriptionPath,
    const CIMInstance & provider,
    const CIMName & className)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::updateClasses");

    CIMObjectPath activeSubscriptionsKey = _generateActiveSubscriptionsKey
        (subscriptionPath);
    ActiveSubscriptionsTableEntry tableValue;

    {
        //
        //  Acquire and hold the write lock during the entire
        //  lookup/remove/insert process, allowing competing threads to apply
        //  their logic over a consistent view of the data.
        //  Do not call any other methods that need 
        //  _activeSubscriptionsTableLock.
        //
        WriteLock lock (_activeSubscriptionsTableLock);
        if (_activeSubscriptionsTable.lookup (activeSubscriptionsKey, 
            tableValue))
        {
            Uint32 providerIndex = providerInList (provider, tableValue);
            if (providerIndex != PEG_NOT_FOUND)
            {
                Uint32 classIndex = classInList (className,
                    tableValue.providers [providerIndex]);
                if (classIndex == PEG_NOT_FOUND)
                {
                    tableValue.providers [providerIndex].classList.append
                        (className);
                }
                else //  classIndex != PEG_NOT_FOUND
                {
                    tableValue.providers [providerIndex].classList.remove
                        (classIndex);
                }

                _removeActiveSubscriptionsEntry (activeSubscriptionsKey);
                _insertActiveSubscriptionsEntry (tableValue.subscription,
                    tableValue.providers);
            }
            else
            {
                PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, 
                    Tracer::LEVEL2,
                    "Provider (" + provider.getPath ().toString () +
                    ") not found in list for Subscription (" +
                    activeSubscriptionsKey.toString () +
                    ") in ActiveSubscriptionsTable");
            }
        }
        else
        {
            //
            //  Subscription not found in Active Subscriptions table
            //
        }
    }

    PEG_METHOD_EXIT ();
}

void SubscriptionTable::removeSubscription (
    const CIMInstance & subscription,
    const Array <CIMName> & indicationSubclassNames,
    const CIMNamespaceName & sourceNamespaceName,
    const Array <ProviderClassList> & providers)
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::removeSubscription");

    //
    //  Remove entry from active subscriptions table
    //
    {
        WriteLock lock(_activeSubscriptionsTableLock);

        _removeActiveSubscriptionsEntry (
            _generateActiveSubscriptionsKey (subscription.getPath ()));
    }

    //
    //  Remove or update entries in subscription classes table
    //
    {
        //
        //  Acquire and hold the write lock during the entire
        //  lookup/remove/insert process, allowing competing threads to apply
        //  their logic over a consistent view of the data.
        //  Do not call any other methods that need 
        //  _subscriptionClassesTableLock.
        //
        WriteLock lock (_subscriptionClassesTableLock);
        for (Uint32 i = 0; i < indicationSubclassNames.size (); i++)
        {
            String subscriptionClassesKey = _generateSubscriptionClassesKey
                (indicationSubclassNames [i], sourceNamespaceName);
            SubscriptionClassesTableEntry tableValue;
            if (_subscriptionClassesTable.lookup (subscriptionClassesKey,
                tableValue))
            {
                //
                //  If entry exists for this IndicationClassName-SourceNamespace
                //  pair, remove subscription from the list
                //
                Array <CIMInstance> subscriptions = tableValue.subscriptions;
                for (Uint32 j = 0; j < subscriptions.size (); j++)
                {
                    if (subscriptions [j].getPath().identical
                       (subscription.getPath()))
                    {
                        subscriptions.remove (j);
                    }
                }
    
                //
                //  Remove the old entry
                //
                _removeSubscriptionClassesEntry (subscriptionClassesKey);
    
                //
                //  If there are still subscriptions in the list, insert the
                //  new entry
                //
                if (subscriptions.size () > 0)
                {
                    _insertSubscriptionClassesEntry (
                        indicationSubclassNames [i],
                        sourceNamespaceName, subscriptions);
                }
            }
            else
            {
                //
                //  Entry not found in Subscription Classes table
                //
                PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, 
                    Tracer::LEVEL2,
                    "Indication subclass and namespace (" + 
                    subscriptionClassesKey +
                    ") not found in SubscriptionClassesTable");
            }
        }
    }

    PEG_METHOD_EXIT ();
}

Uint32 SubscriptionTable::providerInList
    (const CIMInstance & provider,
     const ActiveSubscriptionsTableEntry & tableValue) const
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE,
        "SubscriptionTable::providerInList");

    //
    //  Look for the provider in the list
    //
    for (Uint32 i = 0; i < tableValue.providers.size (); i++)
    {
        if (tableValue.providers [i].provider.getPath ().identical
            (provider.getPath ()))
        {
            PEG_METHOD_EXIT ();
            return i;
        }
    }

    PEG_METHOD_EXIT ();
    return PEG_NOT_FOUND;
}


Uint32 SubscriptionTable::classInList
    (const CIMName & className,
     const ProviderClassList & providerClasses) const
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::classInList");

    //
    //  Look for the class in the list
    //
    for (Uint32 i = 0; i < providerClasses.classList.size (); i++)
    {
        if (providerClasses.classList [i].equal (className))
        {
            PEG_METHOD_EXIT ();
            return i;
        }
    }

    PEG_METHOD_EXIT ();
    return PEG_NOT_FOUND;
}

void SubscriptionTable::clear ()
{
    PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::clear");

    {
        WriteLock lock (_activeSubscriptionsTableLock);
        _activeSubscriptionsTable.clear ();
    }
    {
        WriteLock lock (_subscriptionClassesTableLock);
        _subscriptionClassesTable.clear ();
    }

    PEG_METHOD_EXIT ();
}

PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2