//%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. // //============================================================================== // //%///////////////////////////////////////////////////////////////////////////// #include #include #include #include "IndicationConstants.h" #include "IndicationService.h" #include "SubscriptionTable.h" #ifdef PEGASUS_ENABLE_INDICATION_COUNT # include "ProviderIndicationCountTable.h" #endif 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; String 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 + ") not found in ActiveSubscriptionsTable"); } PEG_METHOD_EXIT (); return succeeded; } Array SubscriptionTable::getMatchingSubscriptions ( const CIMName & supportedClass, const Array nameSpaces, const Boolean checkProvider, const CIMInstance & provider) const { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::getMatchingSubscriptions"); Array matchingSubscriptions; Array 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 // String 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 SubscriptionTable::reflectProviderDisable ( const CIMInstance & provider) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::reflectProviderDisable"); Array 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 // String 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 + ") in ActiveSubscriptionsTable"); } } else { PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL2, "Subscription (" + activeSubscriptionsKey + ") 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 SubscriptionTable::reflectProviderModuleFailure (const String & moduleName, const String & userName, Boolean authenticationEnabled) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::reflectProviderModuleFailure"); Array 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 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 (PEGASUS_PROPERTYNAME_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 // String activeSubscriptionsKey = _generateActiveSubscriptionsKey (providerModuleSubscriptions [k].subscription.getPath ()); ActiveSubscriptionsTableEntry tableValue; if (_activeSubscriptionsTable.lookup (activeSubscriptionsKey, tableValue)) { Array updatedProviderList; for (Uint32 l = 0; l < tableValue.providers.size (); l++) { String providerModuleName; CIMValue nameValue = tableValue.providers [l].providerModule.getProperty (tableValue.providers [l].providerModule.findProperty (PEGASUS_PROPERTYNAME_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; } String SubscriptionTable::_generateActiveSubscriptionsKey ( const CIMObjectPath & subscription) const { // // Get filter and handler object paths from subscription Filter and Handler // reference property values // Array subscriptionKB = subscription.getKeyBindings (); String filterPath; String handlerPath; for (Uint32 i = 0; i < subscriptionKB.size (); i++) { if ((subscriptionKB [i].getName () == PEGASUS_PROPERTYNAME_FILTER) && (subscriptionKB [i].getType () == CIMKeyBinding::REFERENCE)) { filterPath = subscriptionKB [i].getValue (); } else if ((subscriptionKB [i].getName () == PEGASUS_PROPERTYNAME_HANDLER) && (subscriptionKB [i].getType () == CIMKeyBinding::REFERENCE)) { handlerPath = subscriptionKB [i].getValue (); } } // // Construct subscription key from handler and filter. // To avoid ambiguity, the hostname part is removed, since the // hostname can only point to the local machine anyway. // const Char16 slash = '/'; if ((filterPath[0]==slash) && (filterPath[1]==slash)) { Uint32 index = filterPath.find(2,slash); filterPath = filterPath.subString(index+1); } if ((handlerPath[0]==slash) && (handlerPath[1]==slash)) { Uint32 index = handlerPath.find(2,slash); handlerPath = handlerPath.subString(index+1); } // // Assuming that most subscriptions will differ in the filter and handler // names, the namespace and classname of the subscription are added at the // end of the key. // String activeSubscriptionsKey(filterPath); activeSubscriptionsKey.append(handlerPath); activeSubscriptionsKey.append(slash); activeSubscriptionsKey.append(subscription.getNameSpace().getString()); activeSubscriptionsKey.append(slash); activeSubscriptionsKey.append(subscription.getClassName().getString()); return activeSubscriptionsKey; } Boolean SubscriptionTable::_lockedLookupActiveSubscriptionsEntry ( const String & key, ActiveSubscriptionsTableEntry & tableEntry) const { ReadLock lock(_activeSubscriptionsTableLock); return (_activeSubscriptionsTable.lookup (key, tableEntry)); } void SubscriptionTable::_insertActiveSubscriptionsEntry ( const CIMInstance & subscription, const Array & providers) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::_insertActiveSubscriptionsEntry"); String 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 (PEGASUS_PROPERTYNAME_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 String & 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); #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 & 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 String & activeSubscriptionsKey, const CIMInstance & subscription, const Array & 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); } else { // Delete subscription entries from SubscriptionClassesTable. WriteLock lock(_subscriptionClassesTableLock); Array tableValues; for (SubscriptionClassesTable::Iterator i = _subscriptionClassesTable.start(); i; i++) { SubscriptionClassesTableEntry value = i.value(); for (Uint32 j = 0, n = value.subscriptions.size(); j < n; ++j) { if (value.subscriptions[j].getPath().identical( subscription.getPath())) { value.subscriptions.remove(j); tableValues.append(value); break; } } } for (Uint32 i = 0, n = tableValues.size(); i < n; ++i) { String subscriptionClassesKey = _generateSubscriptionClassesKey( tableValues[i].indicationClassName, tableValues[i].sourceNamespaceName); // If this is the only subscription for this class-namespace // pair delete the entry else update the subscription list // for this class-namespace pair. if (tableValues[i].subscriptions.size()) { SubscriptionClassesTableEntry *entry = 0; _subscriptionClassesTable.lookupReference( subscriptionClassesKey, entry); PEGASUS_ASSERT(entry); entry->subscriptions = tableValues[i].subscriptions; } else { _removeSubscriptionClassesEntry(subscriptionClassesKey); } } } } PEG_METHOD_EXIT (); } void SubscriptionTable::insertSubscription ( const CIMInstance & subscription, const Array & providers, const Array & 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 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 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"); String 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 + ") 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 + ") in ActiveSubscriptionsTable"); } } } else { PEG_TRACE_STRING (TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL2, "Subscription (" + activeSubscriptionsKey + ") 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"); String 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 + ") in ActiveSubscriptionsTable"); } } else { // // Subscription not found in Active Subscriptions table // } } PEG_METHOD_EXIT (); } void SubscriptionTable::removeSubscription ( const CIMInstance & subscription, const Array & indicationSubclassNames, const CIMNamespaceName & sourceNamespaceName, const Array & 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 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 (); } void SubscriptionTable::getMatchingClassNamespaceSubscriptions( const CIMName & supportedClass, const CIMNamespaceName & nameSpace, const CIMInstance& provider, Array& matchingSubscriptions, Array& matchingSubscriptionKeys) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::getMatchingClassNamespaceSubscriptions"); Array subscriptions; matchingSubscriptions.clear(); matchingSubscriptionKeys.clear(); // // Look up the indicationClass-sourceNamespace pair in the // Subscription Classes table // String subscriptionClassesKey = _generateSubscriptionClassesKey (supportedClass, nameSpace); SubscriptionClassesTableEntry tableValue; if (_lockedLookupSubscriptionClassesEntry (subscriptionClassesKey, tableValue)) { subscriptions = tableValue.subscriptions; for (Uint32 j = 0; j < subscriptions.size (); j++) { // // Check if the provider who generated this indication // accepted this subscription // String activeSubscriptionsKey = _generateActiveSubscriptionsKey (subscriptions [j].getPath ()); ActiveSubscriptionsTableEntry tableValue; if (_lockedLookupActiveSubscriptionsEntry (activeSubscriptionsKey, tableValue)) { // // If provider is in list, the subscription is acceptted // if ((providerInList (provider, tableValue)) != PEG_NOT_FOUND) { // // Add current subscription to list // matchingSubscriptions.append(subscriptions[j]); matchingSubscriptionKeys.append(activeSubscriptionsKey); } } } } PEGASUS_ASSERT( matchingSubscriptions.size() == matchingSubscriptionKeys.size()); PEG_METHOD_EXIT (); } #ifdef PEGASUS_ENABLE_INDICATION_COUNT void SubscriptionTable::updateMatchedIndicationCounts( const CIMInstance & providerInstance, const Array& activeSubscriptionsKeys) { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::updateMatchedIndicationCounts"); WriteLock lock(_activeSubscriptionsTableLock); for (Uint32 i = 0; i < activeSubscriptionsKeys.size(); i++) { ActiveSubscriptionsTableEntry* entry = 0; if (_activeSubscriptionsTable.lookupReference( activeSubscriptionsKeys[i], entry)) { Uint32 providerIndex = providerInList(providerInstance, *entry); if (providerIndex != PEG_NOT_FOUND) { entry->providers[providerIndex]. matchedIndCountPerSubscription++; } } else { // The subscription may have been deleted in the mean time. // If so, no further update is required. PEG_TRACE((TRC_INDICATION_SERVICE_INTERNAL, Tracer::LEVEL2, "Subscription %s not found in ActiveSubscriptionsTable", (const char *) activeSubscriptionsKeys[i].getCString())); } } PEG_METHOD_EXIT(); } Array SubscriptionTable::_getAllActiveSubscriptionEntries() { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::_getAllActiveSubscriptionEntries"); Array subscriptionsEntries; // // Iterate through the ActiveSubscriptions table to get all active // subscriptions table entries // ReadLock lock(_activeSubscriptionsTableLock); for (ActiveSubscriptionsTable::Iterator i = _activeSubscriptionsTable.start(); i; i++) { subscriptionsEntries.append(i.value()); } PEG_METHOD_EXIT(); return subscriptionsEntries; } Array SubscriptionTable::enumerateSubscriptionIndicationDataInstances() { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::enumerateSubscriptionIndicationDataInstances"); Array instances; // // Get all active subscriptions table entries // Array activeSubscriptionEntries = _getAllActiveSubscriptionEntries(); for (Uint32 i = 0; i < activeSubscriptionEntries.size(); i++) { // // Gets filter name and handler name of the subscription // CIMInstance subscription = activeSubscriptionEntries[i].subscription; String sourceNS = subscription.getPath().getNameSpace().getString(); String filterName; String handlerName; _getFilterAndHandlerNames(subscription, filterName, handlerName); Array providers = activeSubscriptionEntries[i].providers; for (Uint32 j = 0; j < providers.size(); j++) { // // Gets provider name and provider module name // String providerName, providerModuleName; ProviderIndicationCountTable::getProviderKeys( providers[j].provider, providerModuleName, providerName); CIMInstance subscriptionIndDataInstance = _buildSubscriptionIndDataInstance( filterName, handlerName, sourceNS, providerModuleName, providerName, providers[j].matchedIndCountPerSubscription); instances.append(subscriptionIndDataInstance); } } PEG_METHOD_EXIT(); return instances; } Array SubscriptionTable::enumerateSubscriptionIndicationDataInstanceNames() { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::enumerateSubscriptionIndicationDataInstanceNames"); Array instanceNames; // // Get all active subscriptions table entries // Array activeSubscriptionEntries = _getAllActiveSubscriptionEntries(); for (Uint32 i = 0; i < activeSubscriptionEntries.size(); i++) { // // Gets filter name and handler name of the subscription // CIMInstance subscription = activeSubscriptionEntries[i].subscription; String sourceNS = subscription.getPath().getNameSpace().getString(); String filterName; String handlerName; _getFilterAndHandlerNames(subscription, filterName, handlerName); Array providers = activeSubscriptionEntries[i].providers; for (Uint32 j = 0; j < providers.size(); j++) { // // Gets provider name and provider module name // String providerName, providerModuleName; ProviderIndicationCountTable::getProviderKeys( providers[j].provider, providerModuleName, providerName); CIMObjectPath path = _buildSubscriptionIndDataInstanceName( filterName, handlerName, sourceNS, providerModuleName, providerName); instanceNames.append(path); } } PEG_METHOD_EXIT(); return instanceNames; } CIMInstance SubscriptionTable::getSubscriptionIndicationDataInstance( const CIMObjectPath& instanceName) { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::getSubscriptionIndicationDataInstance"); String filterName; String handlerName; String sourceNS; String specifiedProviderModuleName; String specifiedProviderName; // // Gets handler name, filter name, source namespace, provider module name, // and provider name from a PG_SubscriptionIndicationData instanceName // _getSubscriptionIndicationDataKeys( instanceName, filterName, handlerName, sourceNS, specifiedProviderModuleName, specifiedProviderName); // Builds the PG_Provider object path CIMObjectPath providerName = _buildProviderPath( specifiedProviderModuleName, specifiedProviderName); // // Builds subscription path by using the specified parameters // CIMObjectPath subscriptionPath = _buildSubscriptionPath( filterName, handlerName, sourceNS); // // Look up the subscription in the active subscriptions table // ActiveSubscriptionsTableEntry tableValue; if (getSubscriptionEntry(subscriptionPath, tableValue)) { Array providers = tableValue.providers; for (Uint32 i = 0; i < providers.size(); i++) { if (providerName.identical(providers[i].provider.getPath())) { CIMInstance subIndDataInstance = _buildSubscriptionIndDataInstance( filterName, handlerName, sourceNS, specifiedProviderModuleName, specifiedProviderName, providers[i].matchedIndCountPerSubscription); PEG_METHOD_EXIT(); return subIndDataInstance; } } } PEG_METHOD_EXIT(); throw CIMObjectNotFoundException(instanceName.toString()); } void SubscriptionTable::_getFilterAndHandlerNames( const CIMInstance& subscription, String& filterName, String& handlerName) { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::_getFilterAndHandlerNames"); CIMObjectPath filterPath; CIMObjectPath handlerPath; subscription.getProperty(subscription.findProperty( PEGASUS_PROPERTYNAME_FILTER)).getValue().get(filterPath); subscription.getProperty(subscription.findProperty( PEGASUS_PROPERTYNAME_HANDLER)).getValue().get(handlerPath); // // Get Filter namespace - if not set in Filter reference property // value, namespace is the namespace of the subscription // CIMNamespaceName filterNS = filterPath.getNameSpace(); if (filterNS.isNull()) { filterNS = subscription.getPath().getNameSpace(); } // // Get filter name // Array filterKeyBindings = filterPath.getKeyBindings(); for (Uint32 i = 0; i < filterKeyBindings.size(); i++) { if (filterKeyBindings[i].getName().equal(PEGASUS_PROPERTYNAME_NAME)) { filterName.append(filterNS.getString()); filterName.append(":"); filterName.append(filterKeyBindings[i].getValue()); break; } } // // Get handler namespace - if not set in handler reference property // value, namespace is the namespace of the subscription // CIMNamespaceName handlerNS = handlerPath.getNameSpace(); if (handlerNS.isNull()) { handlerNS = subscription.getPath().getNameSpace(); } // // Get handler name // Array handlerKeyBindings = handlerPath.getKeyBindings(); for (Uint32 i = 0; i < handlerKeyBindings.size(); i++) { if (handlerKeyBindings[i].getName().equal(PEGASUS_PROPERTYNAME_NAME)) { handlerName.append(handlerNS.getString()); handlerName.append(":"); handlerName.append(handlerPath.getClassName().getString()); handlerName.append("."); handlerName.append(handlerKeyBindings[i].getValue()); break; } } PEG_METHOD_EXIT(); } void SubscriptionTable::_getSubscriptionIndicationDataKeys( const CIMObjectPath& instanceName, String& filterName, String& handlerName, String& sourceNS, String& providerModuleName, String& providerName) { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::_getSubscriptionIndicationDataKeys"); Array keys = instanceName.getKeyBindings(); for (Uint32 i = 0; i < keys.size(); i++) { if (keys[i].getName() == "FilterName") { filterName = keys[i].getValue(); } else if (keys[i].getName() == "HandlerName") { handlerName = keys[i].getValue(); } else if (keys[i].getName() == "SourceNamespace") { sourceNS = keys[i].getValue(); } else if (keys[i].getName() == "ProviderModuleName") { providerModuleName = keys[i].getValue(); } else if (keys[i].getName() == "ProviderName") { providerName = keys[i].getValue(); } } PEG_METHOD_EXIT(); } CIMObjectPath SubscriptionTable::_buildFilterPath(const String& filterName) { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::_buildFilterPath"); // // creates filter object path from input string filterName // (namespace:filtername) // String name; Uint32 colonIndex = filterName.find(':'); if (colonIndex != PEG_NOT_FOUND) { name = filterName.subString(colonIndex + 1); } Array filterKeys; filterKeys.append(CIMKeyBinding( "SystemCreationClassName", System::getSystemCreationClassName(), CIMKeyBinding::STRING)); filterKeys.append(CIMKeyBinding( "SystemName", System::getFullyQualifiedHostName(), CIMKeyBinding::STRING)); filterKeys.append(CIMKeyBinding( "CreationClassName", PEGASUS_CLASSNAME_INDFILTER.getString(), CIMKeyBinding::STRING)); filterKeys.append(CIMKeyBinding( "Name", name, CIMKeyBinding::STRING)); CIMObjectPath filterPath = CIMObjectPath( String::EMPTY, CIMNamespaceName(), PEGASUS_CLASSNAME_INDFILTER, filterKeys); PEG_METHOD_EXIT(); return filterPath; } CIMObjectPath SubscriptionTable::_buildHandlerPath(const String& handlerName) { PEG_METHOD_ENTER(TRC_INDICATION_SERVICE, "SubscriptionTable::_buildHandlerPath"); // // creates handler object path from input string handlerName // (namespace:classname.handlername) // String name; String classname; Uint32 colonIndex = handlerName.find(':'); Uint32 dotIndex = handlerName.find('.'); if (colonIndex != PEG_NOT_FOUND) { if ((dotIndex != PEG_NOT_FOUND) && (dotIndex > colonIndex)) { classname = handlerName.subString( colonIndex + 1, dotIndex - 1 - colonIndex); name = handlerName.subString(dotIndex + 1); } } Array handlerKeys; handlerKeys.append(CIMKeyBinding( "SystemCreationClassName", System::getSystemCreationClassName(), CIMKeyBinding::STRING)); handlerKeys.append(CIMKeyBinding( "SystemName", System::getFullyQualifiedHostName(), CIMKeyBinding::STRING)); handlerKeys.append(CIMKeyBinding( "CreationClassName", classname, CIMKeyBinding::STRING)); handlerKeys.append(CIMKeyBinding( "Name", name, CIMKeyBinding::STRING)); CIMObjectPath handlerPath = CIMObjectPath( String::EMPTY, CIMNamespaceName(), classname, handlerKeys); PEG_METHOD_EXIT(); return handlerPath; } CIMObjectPath SubscriptionTable::_buildSubscriptionPath( const String& filterName, const String& handlerName, const String& sourceNS) { CIMObjectPath filterPath = _buildFilterPath(filterName); CIMObjectPath handlerPath = _buildHandlerPath(handlerName); CIMObjectPath subscriptionPath; Array keyBindings; keyBindings.append(CIMKeyBinding( PEGASUS_PROPERTYNAME_FILTER, filterPath.toString(), CIMKeyBinding::REFERENCE)); keyBindings.append(CIMKeyBinding( PEGASUS_PROPERTYNAME_HANDLER, handlerPath.toString(), CIMKeyBinding::REFERENCE)); subscriptionPath.setClassName(PEGASUS_CLASSNAME_INDSUBSCRIPTION); subscriptionPath.setNameSpace(sourceNS); subscriptionPath.setKeyBindings(keyBindings); return subscriptionPath; } CIMInstance SubscriptionTable::_buildSubscriptionIndDataInstance( const String& filterName, const String& handlerName, const String& sourceNS, const String& providerModuleName, const String& providerName, Uint32 matchedIndicationCount) { CIMInstance subscriptionIndDataInstance( PEGASUS_CLASSNAME_SUBSCRIPTIONINDDATA); subscriptionIndDataInstance.addProperty(CIMProperty( CIMName("FilterName"), filterName)); subscriptionIndDataInstance.addProperty(CIMProperty( CIMName("HandlerName"), handlerName)); subscriptionIndDataInstance.addProperty(CIMProperty( CIMName("SourceNamespace"), sourceNS)); subscriptionIndDataInstance.addProperty(CIMProperty( CIMName("ProviderModuleName"), providerModuleName)); subscriptionIndDataInstance.addProperty(CIMProperty( CIMName("ProviderName"), providerName)); subscriptionIndDataInstance.addProperty(CIMProperty( CIMName("MatchedIndicationCount"), matchedIndicationCount)); CIMObjectPath path = _buildSubscriptionIndDataInstanceName( filterName, handlerName, sourceNS, providerModuleName, providerName); subscriptionIndDataInstance.setPath(path); return subscriptionIndDataInstance; } CIMObjectPath SubscriptionTable::_buildSubscriptionIndDataInstanceName( const String& filterName, const String& handlerName, const String& sourceNS, const String& providerModuleName, const String& providerName) { CIMObjectPath path; Array keyBindings; keyBindings.append(CIMKeyBinding( "FilterName", filterName, CIMKeyBinding::STRING)); keyBindings.append(CIMKeyBinding( "HandlerName", handlerName, CIMKeyBinding::STRING)); keyBindings.append(CIMKeyBinding( "SourceNamespace", sourceNS, CIMKeyBinding::STRING)); keyBindings.append(CIMKeyBinding( "ProviderModuleName", providerModuleName, CIMKeyBinding::STRING)); keyBindings.append(CIMKeyBinding( "ProviderName", providerName, CIMKeyBinding::STRING)); path.setClassName(PEGASUS_CLASSNAME_SUBSCRIPTIONINDDATA); path.setKeyBindings(keyBindings); return path; } CIMObjectPath SubscriptionTable::_buildProviderPath( const String& providerModuleName, const String& providerName) { CIMObjectPath path; Array keyBindings; keyBindings.append(CIMKeyBinding( _PROPERTY_PROVIDERMODULENAME, providerModuleName, CIMKeyBinding::STRING)); keyBindings.append(CIMKeyBinding( PEGASUS_PROPERTYNAME_NAME, providerName, CIMKeyBinding::STRING)); path.setClassName(PEGASUS_CLASSNAME_PROVIDER); path.setKeyBindings(keyBindings); return path; } #endif PEGASUS_NAMESPACE_END