//%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" PEGASUS_USING_STD; PEGASUS_NAMESPACE_BEGIN Uint32 IndServiceHashFunc::hash(const String& key) { Uint32 hashCode = 0; const Uint16* p = (const Uint16*)key.getChar16Data(); Uint32 keySize = key.size(); if (keySize > 1) { hashCode = p[0] + p[keySize/2] + 3*p[keySize - 1]; } return (hashCode); } 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.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 & 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); } } 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); // Initialize matchedIndCountPerSubscription Array providersList = providers; #ifdef PEGASUS_ENABLE_INDICATION_COUNT for (Uint32 i = 0; i < providers.size(); i++) { providersList[i].matchedIndCountPerSubscription = 0; } #endif _insertActiveSubscriptionsEntry (subscription, providersList); } // // 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 (); } Array > SubscriptionTable:: getMatchingClassNamespaceSubscriptions ( const CIMName & supportedClass, const CIMNamespaceName & nameSpace, const CIMInstance & provider) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::getMatchingClassNamespaceSubscriptions"); Array > matchingClassNamespaceSubscriptions; Array subscriptions; // // 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 // matchingClassNamespaceSubscriptions.append( Pair(subscriptions [j], activeSubscriptionsKey)); } } } } PEG_METHOD_EXIT (); return matchingClassNamespaceSubscriptions; } #ifdef PEGASUS_ENABLE_INDICATION_COUNT void SubscriptionTable::updateMatchedIndCounts ( const Array& activeSubscriptionsKeys, const CIMInstance & provider) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::updateMatchedIndCounts"); // Acquire and hold the write lock during this process { WriteLock lock (_activeSubscriptionsTableLock); for (Uint32 i = 0; i < activeSubscriptionsKeys.size(); i++) { ActiveSubscriptionsTable::Bucket* bucket; ActiveSubscriptionsTableEntry entry; if (_activeSubscriptionsTable.getBucket(activeSubscriptionsKeys[i], bucket)) { entry = bucket->getValue(); Uint32 providerIndex = providerInList(provider, entry); if (providerIndex != PEG_NOT_FOUND) { entry.providers[providerIndex]. matchedIndCountPerSubscription++; bucket->putValue(entry); } } 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 (); } void SubscriptionTable::updateGeneratedIndCount ( const String& providerName, const String& providerModuleName, Boolean isOrphan) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::updateGeneratedIndCount"); String providerKey = _generateProviderIndCountKey(providerName, providerModuleName); ProviderIndCountTable::Bucket* bucket; ProviderIndCountTableEntry entry; { // // Acquire and hold the write lock during the entire process // WriteLock lock(_providerIndCountTableLock); if (_providerIndCountTable.getBucket(providerKey, bucket)) { entry = bucket->getValue(); entry.indCount++; if (isOrphan) { entry.orphanIndCount++; } bucket->putValue(entry); } else { // // The entry is not in the table yet, insert the entry to the table // entry.providerModuleName = providerModuleName; entry.providerName = providerName; entry.indCount = 1; if (isOrphan) { entry.orphanIndCount = 1; } else { entry.orphanIndCount = 0; } // // Insert returns true on success // Boolean succeeded = _providerIndCountTable.insert(providerKey, entry); PEGASUS_ASSERT (succeeded); } } PEG_METHOD_EXIT (); } void SubscriptionTable::removeProviderIndCountTableEntry ( const CIMInstance & provider) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::removeProviderIndCountTableEntry"); String providerName, providerModuleName; Array keys = provider.getPath().getKeyBindings(); for (Uint32 i = 0; i < keys.size(); i++) { if (keys[i].getName().equal(PEGASUS_PROPERTYNAME_NAME)) { providerName = keys[i].getValue(); } else if (keys[i].getName().equal(_PROPERTY_PROVIDERMODULENAME)) { providerModuleName = keys[i].getValue(); } } String providerKey = _generateProviderIndCountKey(providerName, providerModuleName); ProviderIndCountTableEntry entry; { // // Acquire and hold the write lock during the entire process // WriteLock lock(_providerIndCountTableLock); if (_providerIndCountTable.lookup(providerKey, entry)) { // // Remove entry, returns true on success // Boolean isRemoved = _providerIndCountTable.remove(providerKey); PEGASUS_ASSERT(isRemoved); } } PEG_METHOD_EXIT (); } void SubscriptionTable::reflectModuleFailureForProviderIndCountTable ( const String & providerModuleName) { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::reflectModuleFailureForProviderIndCountTable"); // // Iterate through the ProviderIndCount table to remove entries which // match the specified provider module name // { WriteLock lock (_providerIndCountTableLock); for (ProviderIndCountTable::Iterator i = _providerIndCountTable.start (); i; i++) { // // If provider module name matches, delete the entry from the table // if (String::compare(i.value().providerModuleName, providerModuleName) == 0) { String providerKey = _generateProviderIndCountKey( i.value().providerName, providerModuleName); Boolean isRemoved = _providerIndCountTable.remove(providerKey); PEGASUS_ASSERT(isRemoved); } } } PEG_METHOD_EXIT (); } Array SubscriptionTable::retrieveProviderIndCount() { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::retrieveProviderIndCount"); Array providerIndCountEntries; // // Iterate through the ProviderIndCount table to get entire provider // indication count table entries // { // // Acquire and hold the read lock during the process // ReadLock lock (_providerIndCountTableLock); for (ProviderIndCountTable::Iterator i = _providerIndCountTable.start (); i; i++) { providerIndCountEntries.append(i.value ()); } } PEG_METHOD_EXIT (); return (providerIndCountEntries); } Array SubscriptionTable::retrieveSubscriptionIndCount() { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::retrieveSubscriptionIndCount"); Array subscriptionsEntries; // // Iterate through the ActiveSubscriptions table to get entire active // subscriptions table entries // { // // Acquire and hold the read lock during the process // ReadLock lock (_activeSubscriptionsTableLock); for (ActiveSubscriptionsTable::Iterator i = _activeSubscriptionsTable.start (); i; i++) { subscriptionsEntries.append(i.value ()); } } PEG_METHOD_EXIT (); return (subscriptionsEntries); } String SubscriptionTable::_generateProviderIndCountKey ( const String & providerName, const String & providerModuleName) const { PEG_METHOD_ENTER (TRC_INDICATION_SERVICE, "SubscriptionTable::_generateProviderIndCountKey"); char providerNameLength[32]; sprintf(providerNameLength, "%d", providerName.size()); String providerIndCountKey(providerName); providerIndCountKey.append(providerModuleName); providerIndCountKey.append(":"); providerIndCountKey.append(providerNameLength); PEG_METHOD_EXIT (); return (providerIndCountKey); } #endif PEGASUS_NAMESPACE_END