/** * HiveDB is an Open Source (LGPL) system for creating large, high-transaction-volume * data storage systems. */ package org.hivedb.meta.persistence; import org.hivedb.HiveRuntimeException; import org.hivedb.Lockable.Status; import org.hivedb.meta.HiveSemaphore; import org.hivedb.meta.HiveSemaphoreImpl; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.support.JdbcDaoSupport; import org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy; import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; /** * @author Justin McCarthy (jmccarthy@cafepress.com) * @author Britt Crawford (bcrawford@cafepress.com) */ public class HiveSemaphoreDao extends JdbcDaoSupport { public HiveSemaphoreDao(DataSource ds) { this.setDataSource(ds); } //Changed to delegate but kept the method to perserve the interface public HiveSemaphore get() { return getSemaphore(); } private HiveSemaphore getSemaphore() { JdbcTemplate t = getJdbcTemplate(); HiveSemaphore result; try { result = (HiveSemaphore) t.queryForObject("SELECT * FROM semaphore_metadata", new HiveSemaphoreRowMapper()); } catch (BadSqlGrammarException ex) { throw new HiveSemaphoreNotFound( "Exception loading HiveSemaphore -- verify that semaphore_metadata has one and only one row: " + ex.getMessage()); } catch (EmptyResultDataAccessException ex) { throw new HiveSemaphoreNotFound( "Exception loading HiveSemaphore -- verify that semaphore_metadata has one and only one row: " + ex.getMessage()); } catch (RuntimeException re) { String url = (getJdbcTemplate().getDataSource() instanceof HiveBasicDataSource) ? ((HiveBasicDataSource) getJdbcTemplate().getDataSource()).getUrl() : ((HiveBasicDataSource) ((LazyConnectionDataSourceProxy) getJdbcTemplate().getDataSource()).getTargetDataSource()).getUrl(); throw new HiveRuntimeException(String.format("Error connecting to the hive database %s", url), re); } return result; } public HiveSemaphore create() { HiveSemaphore hs; if (doesHiveSemaphoreExist()) hs = get(); else { JdbcTemplate j = getJdbcTemplate(); hs = new HiveSemaphoreImpl(Status.writable, 1); Object[] parameters = new Object[]{hs.getStatus().getValue(), hs.getRevision()}; try { j.update("INSERT INTO semaphore_metadata (status,revision) VALUES (?,?)", parameters); } catch (BadSqlGrammarException e) { throw new HiveSemaphoreNotFound(e.getMessage()); } } return hs; } /** * ************************************************************************ * Update HiveSemaphore. Will perform a single attempt to create the * semaphore if any Exception is encountered. * * @param hs */ public HiveSemaphore update(HiveSemaphore hs) { //Unilateral decision to abandon implicit creation Object[] parameters = new Object[]{hs.getStatus().getValue(), hs.getRevision()}; JdbcTemplate j = getJdbcTemplate(); try { int rows = j.update("UPDATE semaphore_metadata SET status = ?, revision = ?", parameters); if (rows != 1) throw new IllegalStateException("Hive semaphore contians more than one row and has been corrupted."); } catch (BadSqlGrammarException e) { throw new HiveSemaphoreNotFound(e.getMessage()); } return hs; } public boolean doesHiveSemaphoreExist() { boolean exists; try { get(); exists = true; } catch (HiveSemaphoreNotFound e) { exists = false; } return exists; } protected class HiveSemaphoreRowMapper implements RowMapper { public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { return new HiveSemaphoreImpl(Status.getByValue(rs.getInt("status")), rs.getInt("revision")); } } public void incrementAndPersist() { HiveSemaphore hs = get(); hs.incrementRevision(); update(hs); } public class HiveSemaphoreNotFound extends HiveRuntimeException { private static final long serialVersionUID = 7237048097222555154L; public HiveSemaphoreNotFound(String msg) { super(msg); } } }