/*****************************************************************************
*
* Copyright (C) Zenoss, Inc. 2011, all rights reserved.
*
* This content is made available according to terms specified in
* License.zenoss under the directory where your Zenoss product is installed.
*
****************************************************************************/
package org.zenoss.zep.dao.impl;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcOperations;
import org.zenoss.protobufs.zep.Zep.DaemonHeartbeat;
import org.zenoss.zep.ZepException;
import org.zenoss.zep.annotations.TransactionalReadOnly;
import org.zenoss.zep.annotations.TransactionalRollbackAllExceptions;
import org.zenoss.zep.dao.HeartbeatDao;
import org.zenoss.zep.dao.impl.compat.DatabaseCompatibility;
import org.zenoss.zep.dao.impl.compat.NestedTransactionService;
import org.zenoss.zep.dao.impl.compat.TypeConverter;
import org.zenoss.zep.dao.impl.SimpleJdbcTemplateProxy;
import java.lang.reflect.Proxy;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementation of {@link org.zenoss.zep.dao.HeartbeatDao}.
*/
public class HeartbeatDaoImpl implements HeartbeatDao {
private static final String COLUMN_MONITOR = "monitor";
private static final String COLUMN_DAEMON = "daemon";
private static final String COLUMN_TIMEOUT_SECONDS = "timeout_seconds";
private static final String COLUMN_LAST_TIME = "last_time";
private final SimpleJdbcOperations template;
private DatabaseCompatibility databaseCompatibility;
private NestedTransactionService nestedTransactionService;
public HeartbeatDaoImpl(DataSource ds) {
this.template = (SimpleJdbcOperations) Proxy.newProxyInstance(SimpleJdbcOperations.class.getClassLoader(),
new Class<?>[] {SimpleJdbcOperations.class}, new SimpleJdbcTemplateProxy(ds));
}
public void setDatabaseCompatibility(DatabaseCompatibility databaseCompatibility) {
this.databaseCompatibility = databaseCompatibility;
}
public void setNestedTransactionService(NestedTransactionService nestedTransactionService) {
this.nestedTransactionService = nestedTransactionService;
}
@Override
@TransactionalRollbackAllExceptions
public void createHeartbeat(DaemonHeartbeat heartbeat) throws ZepException {
TypeConverter<Long> timestampConverter = databaseCompatibility.getTimestampConverter();
final long now = System.currentTimeMillis();
final Map<String,Object> fields = new HashMap<String,Object>();
fields.put(COLUMN_MONITOR, heartbeat.getMonitor());
fields.put(COLUMN_DAEMON, heartbeat.getDaemon());
fields.put(COLUMN_TIMEOUT_SECONDS, heartbeat.getTimeoutSeconds());
fields.put(COLUMN_LAST_TIME, timestampConverter.toDatabaseType(now));
String insertSql = "INSERT INTO daemon_heartbeat (monitor, daemon, timeout_seconds, last_time)" +
" VALUES(:monitor, :daemon, :timeout_seconds, :last_time)";
String updateSql = "UPDATE daemon_heartbeat SET timeout_seconds=:timeout_seconds, last_time=:last_time" +
" WHERE monitor=:monitor AND daemon=:daemon";
// In most cases, we insert and then retry as an update, however in these cases we will mostly be doing updates
// so we try an update first before the insert/update.
DaoUtils.updateOrInsert(nestedTransactionService, template, insertSql, updateSql, fields);
}
@Override
@TransactionalReadOnly
public List<DaemonHeartbeat> findAll() throws ZepException {
final String sql = "SELECT * FROM daemon_heartbeat";
return this.template.query(sql, MAPPER);
}
@Override
@TransactionalReadOnly
public List<DaemonHeartbeat> findByMonitor(String monitor) throws ZepException {
final Map<String,String> fields = Collections.singletonMap(COLUMN_MONITOR, monitor);
final String sql = "SELECT * FROM daemon_heartbeat WHERE monitor=:monitor";
return this.template.query(sql, MAPPER, fields);
}
@Override
@TransactionalRollbackAllExceptions
public int deleteAll() throws ZepException {
final String sql = "DELETE FROM daemon_heartbeat";
return this.template.update(sql);
}
@Override
@TransactionalRollbackAllExceptions
public int deleteByMonitor(String monitor) throws ZepException {
final Map<String,String> fields = Collections.singletonMap(COLUMN_MONITOR, monitor);
final String sql = "DELETE FROM daemon_heartbeat WHERE monitor=:monitor";
return this.template.update(sql, fields);
}
@Override
@TransactionalRollbackAllExceptions
public int deleteByMonitorAndDaemon(String monitor, String daemon) throws ZepException {
final Map<String, String> fields = new HashMap<String, String>(2);
fields.put(COLUMN_MONITOR, monitor);
fields.put(COLUMN_DAEMON, daemon);
final String sql = "DELETE FROM daemon_heartbeat WHERE monitor=:monitor AND daemon=:daemon";
return this.template.update(sql, fields);
}
private final RowMapper<DaemonHeartbeat> MAPPER = new RowMapper<DaemonHeartbeat>()
{
@Override
public DaemonHeartbeat mapRow(ResultSet rs, int rowNum) throws SQLException {
TypeConverter<Long> timestampConverter = databaseCompatibility.getTimestampConverter();
DaemonHeartbeat.Builder hb = DaemonHeartbeat.newBuilder();
hb.setMonitor(rs.getString(COLUMN_MONITOR));
hb.setDaemon(rs.getString(COLUMN_DAEMON));
hb.setTimeoutSeconds(rs.getInt(COLUMN_TIMEOUT_SECONDS));
hb.setLastTime(timestampConverter.fromDatabaseType(rs, COLUMN_LAST_TIME));
return hb.build();
}
};
}