Java tutorial
/** * Copyright 2014 Yahoo! Inc. Licensed under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law * or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. See accompanying * LICENSE file. */ package com.yahoo.sql4d.indexeragent.meta; import com.google.common.collect.ImmutableMap; import static com.yahoo.sql4d.indexeragent.Agent.*; import static com.yahoo.sql4d.indexeragent.sql.SqlMeta.*; import com.yahoo.sql4d.indexeragent.meta.beans.DataSource; import com.yahoo.sql4d.indexeragent.meta.beans.StatusTrail; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Handles database interaction specifically for Indexer Agent. * @author srikalyan */ public class DBHandler { private static final Logger log = LoggerFactory.getLogger(DBHandler.class); private final EntityManagerFactory emFactory; enum Action { ADD, UPDATE, DELETE } public DBHandler() { String host = getHost(); int port = getPort(); String id = getId(); String password = getPassword(); String dbName = getDbName(); String dbType = getDbType(); String connectUrl, dialect, driver; switch (dbType) { case "mysql": connectUrl = String.format("jdbc:mysql://%s:%d/%s?autoReconnectForPools=true", host, port, dbName); driver = "com.mysql.jdbc.Driver"; dialect = "org.hibernate.dialect.MySQLDialect"; break; case "derby": default: connectUrl = String.format("jdbc:derby://%s:%d/%s;create=true", host, port, dbName); driver = "org.apache.derby.jdbc.ClientDriver"; dialect = "org.hibernate.dialect.DerbyDialect"; } Map<String, String> configOverride = ImmutableMap.of("javax.persistence.jdbc.url", connectUrl, "javax.persistence.jdbc.user", id, "javax.persistence.jdbc.password", password, "hibernate.dialect", dialect, "javax.persistence.jdbc.driver", driver); log.info("Overriding database configuration : {}", configOverride); emFactory = Persistence.createEntityManagerFactory("indexerAgent", configOverride); } private EntityManager getEntityManager() { return emFactory.createEntityManager(); } private void addUpdateDeleteEntity(Object entity, Action action) { EntityManager em = getEntityManager(); try { em.getTransaction().begin(); switch (action) { case ADD: em.persist(entity); break; case UPDATE: em.merge(entity); break; case DELETE: em.remove(entity); break; } } catch (RuntimeException e) { log.error("Something wrong persisting/merging/removing entity {}, so rolling back . Exception is {}", entity, ExceptionUtils.getStackTrace(e)); em.getTransaction().rollback(); } finally { if (em.getTransaction().isActive()) { em.getTransaction().commit(); } em.close(); } } public void addDataSource(DataSource ds) { addUpdateDeleteEntity(ds, Action.ADD); } public void updateDataSource(DataSource ds) { addUpdateDeleteEntity(ds, Action.UPDATE); } public void removeDataSource(DataSource ds) { addUpdateDeleteEntity(ds, Action.DELETE); } public void addStatusTrail(StatusTrail st) { addUpdateDeleteEntity(st, Action.ADD); } public void updateStatusTrail(StatusTrail st) { addUpdateDeleteEntity(st, Action.UPDATE); } public void removeStatusTrail(StatusTrail st) { addUpdateDeleteEntity(st, Action.DELETE); } public List<DataSource> getAllDataSources() { EntityManager em = getEntityManager(); try { return em.createQuery("SELECT ds FROM DataSource ds", DataSource.class).getResultList(); } finally { em.close(); } } public DataSource getDataSource(String tableName) { EntityManager em = getEntityManager(); try { List<DataSource> resultList = em .createQuery("SELECT ds FROM DataSource ds WHERE ds.name = :name", DataSource.class) .setParameter("name", tableName).getResultList(); return resultList.isEmpty() ? null : resultList.get(0); } finally { em.close(); } } public DataSource getDataSource(int id) { EntityManager em = getEntityManager(); try { return em.find(DataSource.class, id); } finally { em.close(); } } /** * Tasks whose status:not_done and givenUp:zero * @param ds * @return */ public List<StatusTrail> getIncompleteTasks(DataSource ds) { EntityManager em = getEntityManager(); try { return em.createQuery( "SELECT st FROM StatusTrail st WHERE st.dataSourceId = :dataSourceId " + "AND st.status = 'not_done' AND st.givenUp = 0 ORDER BY st.id DESC", StatusTrail.class).setParameter("dataSourceId", ds.getId()).getResultList(); } finally { em.close(); } } /** * * @return */ public List<StatusTrail> getAllIncompleteTasks() { EntityManager em = getEntityManager(); try { return em .createQuery( "SELECT st FROM StatusTrail st WHERE " + " st.status = 'not_done' AND st.givenUp = 0 ORDER BY st.id DESC", StatusTrail.class) .getResultList(); } finally { em.close(); } } /** * * @return */ public List<StatusTrail> getAllInprogressTasks() { EntityManager em = getEntityManager(); try { return em.createQuery( "SELECT st FROM StatusTrail st WHERE " + " st.status = 'in_progress' AND st.givenUp = 0", StatusTrail.class).getResultList(); } finally { em.close(); } } /** * * @return */ public long getInprogressTasksCount() { EntityManager em = getEntityManager(); try { return (long) em.createQuery("SELECT COUNT(st.id) FROM StatusTrail st WHERE " + " st.status = 'in_progress' AND st.givenUp = 0").getSingleResult(); } finally { em.close(); } } /** * Change the status of a task. * @param st * @param success */ public void markTask(StatusTrail st, boolean success) { st.setStatus(success ? JobStatus.done : JobStatus.not_done); st.setAttemptsDone(st.getAttemptsDone() + 1); st.setGivenUp(st.getAttemptsDone() >= getMaxTaskAttempts() ? 1 : 0); updateStatusTrail(st); } public void shutdown() { log.info("Shutting down and cleaning up database connections.."); emFactory.close(); } }