/*
* RHQ Management Platform
* Copyright (C) 2005-2014 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, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.domain.alert;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
* A log record for a triggered alert condition.
*
* @author Joseph Marques
*/
@Entity
@NamedQueries({
@NamedQuery(name = AlertConditionLog.QUERY_FIND_UNMATCHED_LOG_BY_ALERT_CONDITION_ID, //
query = "SELECT acl " //
+ " FROM AlertConditionLog AS acl " //
+ " WHERE acl.condition.id = :alertConditionId " //
+ " AND acl.alert IS NULL"),
@NamedQuery(name = AlertConditionLog.QUERY_FIND_UNMATCHED_LOGS_BY_ALERT_DEFINITION_ID, //
query = "SELECT acl " //
+ " FROM AlertConditionLog AS acl " //
+ " WHERE acl.condition.alertDefinition.id = :alertDefinitionId " //
+ " AND acl.alert IS NULL"), //
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_ALL, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.alert.id IN ( SELECT alert.id " //
+ " FROM Alert alert )"),
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_ALERT_IDS, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.id IN ( SELECT ac.id " //
+ " FROM Alert a " //
+ " JOIN a.conditionLogs ac" //
+ " WHERE a.id IN ( :alertIds ) )"),
// This query removes condition logs via the alert def, not alerts, because not every condition log may
// yet be associated with an alert. This is required by Resource bulk delete to pick up the condition logs missed
// by QUERY_DELETE_BY_RESOURCES. It will not get the logs for AlertConditions detached from the AlertDefinition.
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCES_BULK_DELETE, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.condition.id IN ( SELECT ac.id " //
+ " FROM AlertCondition ac " //
+ " JOIN ac.alertDefinition ad " //
+ " WHERE ad.resource.id IN ( :resourceIds ) ))"),
// This query will remove condition logs for conditions that are associated with alerts, regardless of whether
// the AlertCondition has been detached from the AlertDef. This is what you want if you are deleting alerts for
// a resource. It does not fully satisfy Resource bulk delete.
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCES, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.alert.id IN ( SELECT alert.id " //
+ " FROM AlertDefinition alertDef " //
+ " JOIN alertDef.alerts alert " //
+ " WHERE alertDef.resource.id IN ( :resourceIds ) ))"),
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCE_TEMPLATE, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.alert.id IN (SELECT alert.id "
+ " FROM AlertDefinition alertDef "
+ " JOIN alertDef.alerts alert "
+ " WHERE alertDef.resourceType.id = :resourceTypeId)"),
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_RESOURCE_GROUPS, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.alert.id IN ( SELECT alert.id " //
+ " FROM AlertDefinition ad " //
+ " JOIN ad.alerts alert " //
+ " JOIN ad.resource res " //
+ " JOIN res.implicitGroups rg " //
+ " WHERE rg.id IN ( :groupIds ) ))"),
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_BY_ALERT_CTIME, //
query = "DELETE AlertConditionLog acl " //
+ " WHERE acl.id IN ( SELECT iacl.id " //
+ " FROM AlertConditionLog iacl " //
+ " WHERE iacl.alert.ctime BETWEEN :begin AND :end )"),
@NamedQuery(name = AlertConditionLog.QUERY_DELETE_UNMATCHED_BY_ALERT_DEFINITION_ID, //
query = "DELETE AlertConditionLog acl" //
+ " WHERE acl.id IN ( SELECT iacl.id " //
+ " FROM AlertConditionLog iacl" //
+ " WHERE iacl.condition.alertDefinition.id = :alertDefinitionId )" //
+ " AND acl.alert IS NULL") })
@SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_ALERT_CONDITION_LOG_ID_SEQ", sequenceName = "RHQ_ALERT_CONDITION_LOG_ID_SEQ")
@Table(name = "RHQ_ALERT_CONDITION_LOG")
public class AlertConditionLog implements Serializable {
public static final String QUERY_FIND_UNMATCHED_LOG_BY_ALERT_CONDITION_ID = "AlertConditinLog.findUnmatchedLogByAlertConditionId";
public static final String QUERY_FIND_UNMATCHED_LOGS_BY_ALERT_DEFINITION_ID = "AlertConditinLog.findUnmatchedLogsByAlertDefinitionId";
public static final String QUERY_DELETE_ALL = "AlertConditionLog.deleteByAll";
public static final String QUERY_DELETE_BY_ALERT_IDS = "AlertConditionLog.deleteByAlertIds";
public static final String QUERY_DELETE_BY_RESOURCES = "AlertConditionLog.deleteByResources";
public static final String QUERY_DELETE_BY_RESOURCES_BULK_DELETE = "AlertConditionLog.deleteByResourcesBulkDelete";
public static final String QUERY_DELETE_BY_RESOURCE_TEMPLATE = "AlertConditionLog.deleteByResourceType";
public static final String QUERY_DELETE_BY_RESOURCE_GROUPS = "AlertConditionLog.deleteByResourceGroups";
/**
* @deprecated as of RHQ 4.13, no longer used
*/
@Deprecated
public static final String QUERY_DELETE_BY_ALERT_CTIME = "AlertConditionLog.deleteByAlertCTime";
public static final String QUERY_DELETE_UNMATCHED_BY_ALERT_DEFINITION_ID = "AlertConditionLog.deleteUnmatchedByAlertDefinitionId";
/**
* @deprecated as of RHQ 4.13, no longer used
*/
@Deprecated
public static final String QUERY_NATIVE_TRUNCATE_SQL = "TRUNCATE TABLE RHQ_ALERT_CONDITION_LOG";
/**
* this is a character limit, when stored certain vendors may require the string be clipped to
* satisfy a byte limit (postgres can store the 4000 chars, oracle only 4000 bytes).
*/
public static final int MAX_LOG_LENGTH = 4000;
private static final long serialVersionUID = 1L;
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "RHQ_ALERT_CONDITION_LOG_ID_SEQ")
@Id
private int id;
/**
* Since alert conditions can occur at potentially grossly different times in the system, and since the process for
* calculating whether an alert should fire based on the states of these independently derived conditions is
* out-of-band, THIS ctime is now actually more meaningful than the ctime on the alert.
*/
@Column(name = "CTIME", nullable = false)
private long ctime;
@Column(name = "VALUE", nullable = false)
private String value;
@JoinColumn(name = "ALERT_ID", referencedColumnName = "ID")
@ManyToOne
private Alert alert;
@JoinColumn(name = "CONDITION_ID", referencedColumnName = "ID", nullable = false)
@ManyToOne
private AlertCondition condition;
/**
* Creates a new alert condition log record. (required by EJB3 spec, but not used)
*/
protected AlertConditionLog() {
}
/**
* Creates a new log record for the specified alert condition. The alert that triggered the condition will be filled
* in later by a separate out-of-band process that ensures all requisite conditions have been satisfied on the
* corresponding alert.
*
* @param cond condition that is being logged
* @param ctime the time in millis when this condition was known to be true
*/
public AlertConditionLog(AlertCondition cond, long ctime) {
this.condition = cond;
this.ctime = ctime;
}
public int getId() {
return this.id;
}
public long getCtime() {
return ctime;
}
public void setCtime(long ctime) {
this.ctime = ctime;
}
public String getValue() {
return this.value;
}
/**
* Make sure the value passed to this setter goes through this process:
* <pre>
* String value = ...
* DatabaseType dbType = ...
* value = dbType.getString(value, AlertConditionLog.MAX_LOG_LENGTH);
* </pre>
*
* @param value on Postgres shouldn't be longer than <code>MAX_LOG_LENGTH</code> chars,
* on Oracle <code>MAX_LOG_LENGTH</code> bytes.
*/
public void setValue(String value) {
if ((value != null) && (value.length() >= MAX_LOG_LENGTH)) {
value = value.substring(0, MAX_LOG_LENGTH);
}
this.value = value;
}
public Alert getAlert() {
return this.alert;
}
public void setAlert(Alert alert) {
this.alert = alert;
}
public AlertCondition getCondition() {
return this.condition;
}
public void setCondition(AlertCondition condition) {
this.condition = condition;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if ((obj == null) || !(obj instanceof AlertConditionLog)) {
return false;
}
AlertConditionLog that = (AlertConditionLog) obj;
if (id != that.id) {
return false;
}
if ((value != null) ? (!value.equals(that.value)) : (that.value != null)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = id;
result = (31 * result) + ((value != null) ? value.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "org.rhq.core.domain.alert.AlertConditionLog" + "[ " + "id=" + id + ", " + "value=" + value + ", "
+ condition + " ]";
}
}