/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.alert.engine.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.alert.AlertConditionOperator;
import org.rhq.enterprise.server.alert.engine.AlertConditionCacheStats;
import org.rhq.enterprise.server.alert.engine.jms.CachedConditionProducerLocal;
import org.rhq.enterprise.server.alert.engine.model.AbstractCacheElement;
import org.rhq.enterprise.server.alert.engine.model.CacheElementActivity;
import org.rhq.enterprise.server.util.LookupUtil;
/**
* @author Joseph Marques
*/
abstract class AbstractConditionCache {
static final Log log = LogFactory.getLog(AlertConditionCacheCoordinator.class);
static final int PAGE_SIZE = 250;
private CachedConditionProducerLocal cachedConditionProducer;
public AbstractConditionCache() {
cachedConditionProducer = LookupUtil.getCachedConditionProducerLocal();
}
<T extends AbstractCacheElement<S>, S> void processCacheElements(List<T> cacheElements, S providedValue,
long timestamp, AlertConditionCacheStats stats, Object... extraParams) {
if (cacheElements == null) {
return; // nothing to do
}
int errors = 0;
for (T cacheElement : cacheElements) {
boolean matched = cacheElement.process(providedValue, extraParams);
if (matched) // send positive event in case of a match
{
try {
/*
* Set the active property for alertCondition-based cache elements, and send it on its way;
* Thus, even if the element is already active, we're going to send another message with the new
* value
*/
cacheElement.setActivity(CacheElementActivity.ACTIVE); // no harm to always set active (though, technically, STATELESS operators don't need it)
cachedConditionProducer.sendActivateAlertConditionMessage(
cacheElement.getAlertConditionTriggerId(), timestamp,
cacheElement.convertValueToString(providedValue), extraParams);
stats.matched++;
} catch (Exception e) {
log.error("Error processing matched cache element '" + cacheElement + "': " + e.getMessage());
errors++;
}
} else // no match, negative event
{
/*
* but only send negative events if we're, 1) a type of operator that supports STATEFUL events, and
* 2) currently active
*/
if (cacheElement.isType(AlertConditionOperator.Type.STATEFUL) && cacheElement.getActivity().maybeActive()) {
cacheElement.setActivity(CacheElementActivity.INACTIVE);
try {
// send negative message
cachedConditionProducer.sendDeactivateAlertConditionMessage(
cacheElement.getAlertConditionTriggerId(), timestamp);
} catch (Exception e) {
log.error("Error sending deactivation message for cache element '" + cacheElement + "': "
+ e.getMessage());
errors++;
}
} else {
/*
* negative message, but nothing was active...so do nothing.
*
* this will occur in the overwhelming majority of cases. in theory, since most of the time
* conditions exist to alert people of non-ideal system state, it will not fire in the POSITIVE very
* often. thus, we suppress the firing of negative events unless we know we've already sent a
* POSITIVE event that we need to compensate for.
*/
}
}
}
if (errors != 0) {
log.error("There were " + errors + " alert conditions that did not fire. "
+ "Please check the configuration of the JMS subsystem and try again. ");
}
}
<T extends AbstractCacheElement<?>> boolean addTo(String mapName, Map<Integer, List<T>> cache, Integer key,
T cacheElement, int alertConditionId, AlertConditionCacheStats stats) {
List<T> cacheElements = cache.get(key);
if (cacheElements == null) {
cacheElements = new ArrayList<T>();
cache.put(key, cacheElements);
}
boolean success;
if (cacheElement != null) {
if (log.isTraceEnabled()) {
log.trace("Inserting '" + mapName + "' element: " + "key=" + key + ", " + "value=" + cacheElement);
}
// and finally update stats and return whether it was success
success = (cacheElement != null) ? cacheElements.add(cacheElement) : false;
if (success) {
stats.created++;
}
} else {
success = false;
log.warn("Cannot insert null cache element in '" + mapName + "' element: " + "key=" + key);
}
return success;
}
public abstract int getCacheSize(AlertConditionCacheCoordinator.Cache cache);
}