/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.oozie.store;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.apache.oozie.CoordinatorActionBean;
import org.apache.oozie.CoordinatorJobBean;
import org.apache.oozie.CoordinatorJobInfo;
import org.apache.oozie.ErrorCode;
import org.apache.oozie.client.Job.Status;
import org.apache.oozie.client.CoordinatorJob.Timeunit;
import org.apache.oozie.service.InstrumentationService;
import org.apache.oozie.service.Services;
import org.apache.oozie.util.DateUtils;
import org.apache.oozie.util.Instrumentation;
import org.apache.oozie.util.ParamChecker;
import org.apache.oozie.util.XLog;
import org.apache.oozie.workflow.WorkflowException;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.apache.openjpa.persistence.OpenJPAQuery;
import org.apache.openjpa.persistence.jdbc.FetchDirection;
import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan;
import org.apache.openjpa.persistence.jdbc.LRSSizeAlgorithm;
import org.apache.openjpa.persistence.jdbc.ResultSetType;
/**
* DB Implementation of Coord Store
*/
public class CoordinatorStore extends Store {
private final XLog log = XLog.getLog(getClass());
private EntityManager entityManager;
private static final String INSTR_GROUP = "db";
public static final int LOCK_TIMEOUT = 50000;
private static final long DAY_IN_MS = 24 * 60 * 60 * 1000;
public CoordinatorStore(boolean selectForUpdate) throws StoreException {
super();
entityManager = getEntityManager();
}
public CoordinatorStore(Store store, boolean selectForUpdate) throws StoreException {
super(store);
entityManager = getEntityManager();
}
/**
* Create a CoordJobBean. It also creates the process instance for the job.
*
* @param workflow workflow bean
* @throws StoreException
*/
public void insertCoordinatorJob(final CoordinatorJobBean coordinatorJob) throws StoreException {
ParamChecker.notNull(coordinatorJob, "coordinatorJob");
doOperation("insertCoordinatorJob", new Callable<Void>() {
public Void call() throws StoreException {
entityManager.persist(coordinatorJob);
return null;
}
});
}
/**
* Load the CoordinatorJob into a Bean and return it. Also load the Workflow Instance into the bean. And lock the
* Workflow depending on the locking parameter.
*
* @param id Job ID
* @param locking Flag for Table Lock
* @return CoordinatorJobBean
* @throws StoreException
*/
public CoordinatorJobBean getCoordinatorJob(final String id, final boolean locking) throws StoreException {
ParamChecker.notEmpty(id, "CoordJobId");
CoordinatorJobBean cjBean = doOperation("getCoordinatorJob", new Callable<CoordinatorJobBean>() {
@SuppressWarnings("unchecked")
public CoordinatorJobBean call() throws StoreException {
Query q = entityManager.createNamedQuery("GET_COORD_JOB");
q.setParameter("id", id);
/*
* if (locking) { OpenJPAQuery oq = OpenJPAPersistence.cast(q);
* // q.setHint("openjpa.FetchPlan.ReadLockMode","WRITE");
* FetchPlan fetch = oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // 1 second }
*/
List<CoordinatorJobBean> cjBeans = q.getResultList();
if (cjBeans.size() > 0) {
return cjBeans.get(0);
}
else {
throw new StoreException(ErrorCode.E0604, id);
}
}
});
cjBean.setStatus(cjBean.getStatus());
return cjBean;
}
/**
* Get a list of Coordinator Jobs that should be materialized. Jobs with a 'last materialized time' older than the
* argument will be returned.
*
* @param d Date
* @return List of Coordinator Jobs that have a last materialized time older than input date
* @throws StoreException
*/
public List<CoordinatorJobBean> getCoordinatorJobsToBeMaterialized(final Date d, final int limit)
throws StoreException {
ParamChecker.notNull(d, "Coord Job Materialization Date");
List<CoordinatorJobBean> cjBeans = doOperation("getCoordinatorJobsToBeMaterialized",
new Callable<List<CoordinatorJobBean>>() {
public List<CoordinatorJobBean> call() throws StoreException {
List<CoordinatorJobBean> cjBeans;
List<CoordinatorJobBean> jobList = new ArrayList<CoordinatorJobBean>();
try {
Query q = entityManager.createNamedQuery("GET_COORD_JOBS_OLDER_THAN");
q.setParameter("matTime", new Timestamp(d.getTime()));
if (limit > 0) {
q.setMaxResults(limit);
}
/*
OpenJPAQuery oq = OpenJPAPersistence.cast(q);
FetchPlan fetch = oq.getFetchPlan();
fetch.setReadLockMode(LockModeType.WRITE);
fetch.setLockTimeout(-1); // no limit
*/
cjBeans = q.getResultList();
// copy results to a new object
for (CoordinatorJobBean j : cjBeans) {
jobList.add(j);
}
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
return jobList;
}
});
return cjBeans;
}
/**
* A list of Coordinator Jobs that are matched with the status and have last materialized time' older than
* checkAgeSecs will be returned.
*
* @param checkAgeSecs Job age in Seconds
* @param status Coordinator Job Status
* @param limit Number of results to return
* @param locking Flag for Table Lock
* @return List of Coordinator Jobs that are matched with the parameters.
* @throws StoreException
*/
public List<CoordinatorJobBean> getCoordinatorJobsOlderThanStatus(final long checkAgeSecs, final String status,
final int limit, final boolean locking) throws StoreException {
ParamChecker.notNull(status, "Coord Job Status");
List<CoordinatorJobBean> cjBeans = doOperation("getCoordinatorJobsOlderThanStatus",
new Callable<List<CoordinatorJobBean>>() {
public List<CoordinatorJobBean> call() throws StoreException {
List<CoordinatorJobBean> cjBeans;
List<CoordinatorJobBean> jobList = new ArrayList<CoordinatorJobBean>();
try {
Query q = entityManager.createNamedQuery("GET_COORD_JOBS_OLDER_THAN_STATUS");
Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
q.setParameter("lastModTime", ts);
q.setParameter("status", status);
if (limit > 0) {
q.setMaxResults(limit);
}
/*
* if (locking) { OpenJPAQuery oq =
* OpenJPAPersistence.cast(q); FetchPlan fetch =
* oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // no limit }
*/
cjBeans = q.getResultList();
for (CoordinatorJobBean j : cjBeans) {
jobList.add(j);
}
}
catch (Exception e) {
throw new StoreException(ErrorCode.E0603, e.getMessage(), e);
}
return jobList;
}
});
return cjBeans;
}
/**
* Load the CoordinatorAction into a Bean and return it.
*
* @param id action ID
* @return CoordinatorActionBean
* @throws StoreException
*/
public CoordinatorActionBean getCoordinatorAction(final String id, final boolean locking) throws StoreException {
ParamChecker.notEmpty(id, "actionID");
CoordinatorActionBean caBean = doOperation("getCoordinatorAction", new Callable<CoordinatorActionBean>() {
public CoordinatorActionBean call() throws StoreException {
Query q = entityManager.createNamedQuery("GET_COORD_ACTION");
q.setParameter("id", id);
OpenJPAQuery oq = OpenJPAPersistence.cast(q);
/*
* if (locking) { //q.setHint("openjpa.FetchPlan.ReadLockMode",
* "WRITE"); FetchPlan fetch = oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // no limit }
*/
CoordinatorActionBean action = null;
List<CoordinatorActionBean> actions = q.getResultList();
if (actions.size() > 0) {
action = actions.get(0);
}
else {
throw new StoreException(ErrorCode.E0605, id);
}
/*
* if (locking) return action; else
*/
return getBeanForRunningCoordAction(action);
}
});
return caBean;
}
/**
* Return CoordinatorActions for a jobID. Action should be in READY state. Number of returned actions should be <=
* concurrency number. Sort returned actions based on execution order (FIFO, LIFO, LAST_ONLY)
*
* @param id job ID
* @param numResults number of results to return
* @param executionOrder execution for this job - FIFO, LIFO, LAST_ONLY
* @return List of CoordinatorActionBean
* @throws StoreException
*/
public List<CoordinatorActionBean> getCoordinatorActionsForJob(final String id, final int numResults,
final String executionOrder) throws StoreException {
ParamChecker.notEmpty(id, "jobID");
List<CoordinatorActionBean> caBeans = doOperation("getCoordinatorActionsForJob",
new Callable<List<CoordinatorActionBean>>() {
public List<CoordinatorActionBean> call() throws StoreException {
List<CoordinatorActionBean> caBeans;
Query q;
// check if executionOrder is FIFO, LIFO, or LAST_ONLY
if (executionOrder.equalsIgnoreCase("FIFO")) {
q = entityManager.createNamedQuery("GET_COORD_ACTIONS_FOR_JOB_FIFO");
}
else {
q = entityManager.createNamedQuery("GET_COORD_ACTIONS_FOR_JOB_LIFO");
}
q.setParameter("jobId", id);
// if executionOrder is LAST_ONLY, only retrieve first
// record in LIFO,
// otherwise, use numResults if it is positive.
if (executionOrder.equalsIgnoreCase("LAST_ONLY")) {
q.setMaxResults(1);
}
else {
if (numResults > 0) {
q.setMaxResults(numResults);
}
}
caBeans = q.getResultList();
return caBeans;
}
});
return caBeans;
}
/**
* Return CoordinatorActions for a jobID. Action should be in READY state. Number of returned actions should be <=
* concurrency number.
*
* @param id job ID
* @return Number of running actions
* @throws StoreException
*/
public int getCoordinatorRunningActionsCount(final String id) throws StoreException {
ParamChecker.notEmpty(id, "jobID");
Integer cnt = doOperation("getCoordinatorRunningActionsCount", new Callable<Integer>() {
public Integer call() throws SQLException {
Query q = entityManager.createNamedQuery("GET_COORD_RUNNING_ACTIONS_COUNT");
q.setParameter("jobId", id);
Long count = (Long) q.getSingleResult();
return Integer.valueOf(count.intValue());
}
});
return cnt.intValue();
}
/**
* Create a new Action record in the ACTIONS table with the given Bean.
*
* @param action WorkflowActionBean
* @throws StoreException If the action is already present
*/
public void insertCoordinatorAction(final CoordinatorActionBean action) throws StoreException {
ParamChecker.notNull(action, "CoordinatorActionBean");
doOperation("insertCoordinatorAction", new Callable<Void>() {
public Void call() throws StoreException {
entityManager.persist(action);
return null;
}
});
}
/**
* Update the given action bean to DB.
*
* @param action Action Bean
* @throws StoreException if action doesn't exist
*/
public void updateCoordinatorAction(final CoordinatorActionBean action) throws StoreException {
ParamChecker.notNull(action, "CoordinatorActionBean");
doOperation("updateCoordinatorAction", new Callable<Void>() {
public Void call() throws StoreException {
Query q = entityManager.createNamedQuery("UPDATE_COORD_ACTION");
q.setParameter("id", action.getId());
setActionQueryParameters(action, q);
q.executeUpdate();
return null;
}
});
}
/**
* Update the given action bean to DB.
*
* @param action Action Bean
* @throws StoreException if action doesn't exist
*/
public void updateCoordActionMin(final CoordinatorActionBean action) throws StoreException {
ParamChecker.notNull(action, "CoordinatorActionBean");
doOperation("updateCoordinatorAction", new Callable<Void>() {
public Void call() throws StoreException {
Query q = entityManager.createNamedQuery("UPDATE_COORD_ACTION_MIN");
q.setParameter("id", action.getId());
q.setParameter("missingDependencies", action.getMissingDependencies());
q.setParameter("lastModifiedTime", new Date());
q.setParameter("status", action.getStatus().toString());
q.setParameter("actionXml", action.getActionXml());
q.executeUpdate();
return null;
}
});
}
/**
* Update the given coordinator job bean to DB.
*
* @param jobbean Coordinator Job Bean
* @throws StoreException if action doesn't exist
*/
public void updateCoordinatorJob(final CoordinatorJobBean job) throws StoreException {
ParamChecker.notNull(job, "CoordinatorJobBean");
doOperation("updateJob", new Callable<Void>() {
public Void call() throws StoreException {
Query q = entityManager.createNamedQuery("UPDATE_COORD_JOB");
q.setParameter("id", job.getId());
setJobQueryParameters(job, q);
q.executeUpdate();
return null;
}
});
}
public void updateCoordinatorJobStatus(final CoordinatorJobBean job) throws StoreException {
ParamChecker.notNull(job, "CoordinatorJobBean");
doOperation("updateJobStatus", new Callable<Void>() {
public Void call() throws StoreException {
Query q = entityManager.createNamedQuery("UPDATE_COORD_JOB_STATUS");
q.setParameter("id", job.getId());
q.setParameter("status", job.getStatus().toString());
q.setParameter("lastModifiedTime", new Date());
q.executeUpdate();
return null;
}
});
}
private <V> V doOperation(String name, Callable<V> command) throws StoreException {
try {
Instrumentation.Cron cron = new Instrumentation.Cron();
cron.start();
V retVal;
try {
retVal = command.call();
}
finally {
cron.stop();
}
Services.get().get(InstrumentationService.class).get().addCron(INSTR_GROUP, name, cron);
return retVal;
}
catch (StoreException ex) {
throw ex;
}
catch (SQLException ex) {
throw new StoreException(ErrorCode.E0603, name, ex.getMessage(), ex);
}
catch (Exception e) {
throw new StoreException(ErrorCode.E0607, name, e.getMessage(), e);
}
}
private void setJobQueryParameters(CoordinatorJobBean jBean, Query q) {
q.setParameter("appName", jBean.getAppName());
q.setParameter("appPath", jBean.getAppPath());
q.setParameter("concurrency", jBean.getConcurrency());
q.setParameter("conf", jBean.getConf());
q.setParameter("externalId", jBean.getExternalId());
q.setParameter("frequency", jBean.getFrequency());
q.setParameter("lastActionNumber", jBean.getLastActionNumber());
q.setParameter("timeOut", jBean.getTimeout());
q.setParameter("timeZone", jBean.getTimeZone());
q.setParameter("authToken", jBean.getAuthToken());
q.setParameter("createdTime", jBean.getCreatedTimestamp());
q.setParameter("endTime", jBean.getEndTimestamp());
q.setParameter("execution", jBean.getExecution());
q.setParameter("jobXml", jBean.getJobXml());
q.setParameter("lastAction", jBean.getLastActionTimestamp());
q.setParameter("lastModifiedTime", new Date());
q.setParameter("nextMaterializedTime", jBean.getNextMaterializedTimestamp());
q.setParameter("origJobXml", jBean.getOrigJobXml());
q.setParameter("slaXml", jBean.getSlaXml());
q.setParameter("startTime", jBean.getStartTimestamp());
q.setParameter("status", jBean.getStatus().toString());
q.setParameter("timeUnit", jBean.getTimeUnitStr());
}
private void setActionQueryParameters(CoordinatorActionBean aBean, Query q) {
q.setParameter("actionNumber", aBean.getActionNumber());
q.setParameter("actionXml", aBean.getActionXml());
q.setParameter("consoleUrl", aBean.getConsoleUrl());
q.setParameter("createdConf", aBean.getCreatedConf());
q.setParameter("errorCode", aBean.getErrorCode());
q.setParameter("errorMessage", aBean.getErrorMessage());
q.setParameter("externalStatus", aBean.getExternalStatus());
q.setParameter("missingDependencies", aBean.getMissingDependencies());
q.setParameter("runConf", aBean.getRunConf());
q.setParameter("timeOut", aBean.getTimeOut());
q.setParameter("trackerUri", aBean.getTrackerUri());
q.setParameter("type", aBean.getType());
q.setParameter("createdTime", aBean.getCreatedTimestamp());
q.setParameter("externalId", aBean.getExternalId());
q.setParameter("jobId", aBean.getJobId());
q.setParameter("lastModifiedTime", new Date());
q.setParameter("nominalTime", aBean.getNominalTimestamp());
q.setParameter("slaXml", aBean.getSlaXml());
q.setParameter("status", aBean.getStatus().toString());
}
/**
* Purge the coordinators completed older than given days.
*
* @param olderThanDays number of days for which to preserve the coordinators
* @param limit maximum number of coordinator jobs to be purged
* @throws StoreException
*/
public void purge(final long olderThanDays, final int limit) throws StoreException {
doOperation("coord-purge", new Callable<Void>() {
public Void call() throws SQLException, StoreException, WorkflowException {
Timestamp lastModTm = new Timestamp(System.currentTimeMillis() - (olderThanDays * DAY_IN_MS));
Query jobQ = entityManager.createNamedQuery("GET_COMPLETED_COORD_JOBS_OLDER_THAN_STATUS");
jobQ.setParameter("lastModTime", lastModTm);
jobQ.setMaxResults(limit);
List<CoordinatorJobBean> coordJobs = jobQ.getResultList();
int actionDeleted = 0;
if (coordJobs.size() != 0) {
for (CoordinatorJobBean coord : coordJobs) {
String jobId = coord.getId();
entityManager.remove(coord);
Query g = entityManager.createNamedQuery("DELETE_COMPLETED_ACTIONS_FOR_COORDINATOR");
g.setParameter("jobId", jobId);
actionDeleted += g.executeUpdate();
}
}
XLog.getLog(getClass()).debug("ENDED Coord Purge deleted jobs :" + coordJobs.size() + " and actions " + actionDeleted);
return null;
}
});
}
public void commit() throws StoreException {
}
public void close() throws StoreException {
}
public CoordinatorJobBean getCoordinatorJobs(String id) {
// TODO Auto-generated method stub
return null;
}
public CoordinatorJobInfo getCoordinatorInfo(final Map<String, List<String>> filter, final int start, final int len)
throws StoreException {
CoordinatorJobInfo coordJobInfo = doOperation("getCoordinatorJobInfo", new Callable<CoordinatorJobInfo>() {
public CoordinatorJobInfo call() throws SQLException, StoreException {
List<String> orArray = new ArrayList<String>();
List<String> colArray = new ArrayList<String>();
List<String> valArray = new ArrayList<String>();
StringBuilder sb = new StringBuilder("");
StoreStatusFilter.filter(filter, orArray, colArray, valArray, sb, StoreStatusFilter.coordSeletStr,
StoreStatusFilter.coordCountStr);
int realLen = 0;
Query q = null;
Query qTotal = null;
if (orArray.size() == 0) {
q = entityManager.createNamedQuery("GET_COORD_JOBS_COLUMNS");
q.setFirstResult(start - 1);
q.setMaxResults(len);
qTotal = entityManager.createNamedQuery("GET_COORD_JOBS_COUNT");
}
else {
StringBuilder sbTotal = new StringBuilder(sb);
sb.append(" order by w.createdTimestamp desc ");
XLog.getLog(getClass()).debug("Created String is **** " + sb.toString());
q = entityManager.createQuery(sb.toString());
q.setFirstResult(start - 1);
q.setMaxResults(len);
qTotal = entityManager.createQuery(sbTotal.toString().replace(StoreStatusFilter.coordSeletStr,
StoreStatusFilter.coordCountStr));
}
for (int i = 0; i < orArray.size(); i++) {
q.setParameter(colArray.get(i), valArray.get(i));
qTotal.setParameter(colArray.get(i), valArray.get(i));
}
OpenJPAQuery kq = OpenJPAPersistence.cast(q);
JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan();
fetch.setFetchBatchSize(20);
fetch.setResultSetType(ResultSetType.SCROLL_INSENSITIVE);
fetch.setFetchDirection(FetchDirection.FORWARD);
fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.LAST);
List<?> resultList = q.getResultList();
List<Object[]> objectArrList = (List<Object[]>) resultList;
List<CoordinatorJobBean> coordBeansList = new ArrayList<CoordinatorJobBean>();
for (Object[] arr : objectArrList) {
CoordinatorJobBean ww = getBeanForCoordinatorJobFromArray(arr);
coordBeansList.add(ww);
}
realLen = ((Long) qTotal.getSingleResult()).intValue();
return new CoordinatorJobInfo(coordBeansList, start, len, realLen);
}
});
return coordJobInfo;
}
private CoordinatorJobBean getBeanForCoordinatorJobFromArray(Object[] arr) {
CoordinatorJobBean bean = new CoordinatorJobBean();
bean.setId((String) arr[0]);
if (arr[1] != null) {
bean.setAppName((String) arr[1]);
}
if (arr[2] != null) {
bean.setStatus(Status.valueOf((String) arr[2]));
}
if (arr[3] != null) {
bean.setUser((String) arr[3]);
}
if (arr[4] != null) {
bean.setGroup((String) arr[4]);
}
if (arr[5] != null) {
bean.setStartTime((Timestamp) arr[5]);
}
if (arr[6] != null) {
bean.setEndTime((Timestamp) arr[6]);
}
if (arr[7] != null) {
bean.setAppPath((String) arr[7]);
}
if (arr[8] != null) {
bean.setConcurrency(((Integer) arr[8]).intValue());
}
if (arr[9] != null) {
bean.setFrequency(((Integer) arr[9]).intValue());
}
if (arr[10] != null) {
bean.setLastActionTime((Timestamp) arr[10]);
}
if (arr[11] != null) {
bean.setNextMaterializedTime((Timestamp) arr[11]);
}
if (arr[13] != null) {
bean.setTimeUnit(Timeunit.valueOf((String) arr[13]));
}
if (arr[14] != null) {
bean.setTimeZone((String) arr[14]);
}
if (arr[15] != null) {
bean.setTimeout((Integer) arr[15]);
}
return bean;
}
/**
* Loads all actions for the given Coordinator job.
*
* @param jobId coordinator job id
* @param locking true if Actions are to be locked
* @return A List of CoordinatorActionBean
* @throws StoreException
*/
public Integer getActionsForCoordinatorJob(final String jobId, final boolean locking)
throws StoreException {
ParamChecker.notEmpty(jobId, "CoordinatorJobID");
Integer actionsCount = doOperation("getActionsForCoordinatorJob",
new Callable<Integer>() {
@SuppressWarnings("unchecked")
public Integer call() throws StoreException {
List<CoordinatorActionBean> actions;
List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>();
try {
Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_COORD_JOB");
q.setParameter("jobId", jobId);
/*
* if (locking) { //
* q.setHint("openjpa.FetchPlan.ReadLockMode", //
* "READ"); OpenJPAQuery oq =
* OpenJPAPersistence.cast(q); JDBCFetchPlan fetch =
* (JDBCFetchPlan) oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // 1 second }
*/
Long count = (Long) q.getSingleResult();
return Integer.valueOf(count.intValue());
/*actions = q.getResultList();
for (CoordinatorActionBean a : actions) {
CoordinatorActionBean aa = getBeanForRunningCoordAction(a);
actionList.add(aa);
}*/
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
/*
* if (locking) { return actions; } else {
*/
// }
}
});
return actionsCount;
}
/**
* Loads given number of actions for the given Coordinator job.
*
* @param jobId coordinator job id
* @param start offset for select statement
* @param len number of Workflow Actions to be returned
* @return A List of CoordinatorActionBean
* @throws StoreException
*/
public List<CoordinatorActionBean> getActionsSubsetForCoordinatorJob(final String jobId, final int start,
final int len) throws StoreException {
ParamChecker.notEmpty(jobId, "CoordinatorJobID");
List<CoordinatorActionBean> actions = doOperation("getActionsForCoordinatorJob",
new Callable<List<CoordinatorActionBean>>() {
@SuppressWarnings("unchecked")
public List<CoordinatorActionBean> call() throws StoreException {
List<CoordinatorActionBean> actions;
List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>();
try {
Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_COORD_JOB");
q.setParameter("jobId", jobId);
q.setFirstResult(start - 1);
q.setMaxResults(len);
actions = q.getResultList();
for (CoordinatorActionBean a : actions) {
CoordinatorActionBean aa = getBeanForRunningCoordAction(a);
actionList.add(aa);
}
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
return actionList;
}
});
return actions;
}
protected CoordinatorActionBean getBeanForRunningCoordAction(CoordinatorActionBean a) {
if (a != null) {
CoordinatorActionBean action = new CoordinatorActionBean();
action.setId(a.getId());
action.setActionNumber(a.getActionNumber());
action.setActionXml(a.getActionXml());
action.setConsoleUrl(a.getConsoleUrl());
action.setCreatedConf(a.getCreatedConf());
//action.setErrorCode(a.getErrorCode());
//action.setErrorMessage(a.getErrorMessage());
action.setExternalStatus(a.getExternalStatus());
action.setMissingDependencies(a.getMissingDependencies());
action.setRunConf(a.getRunConf());
action.setTimeOut(a.getTimeOut());
action.setTrackerUri(a.getTrackerUri());
action.setType(a.getType());
action.setCreatedTime(a.getCreatedTime());
action.setExternalId(a.getExternalId());
action.setJobId(a.getJobId());
action.setLastModifiedTime(a.getLastModifiedTime());
action.setNominalTime(a.getNominalTime());
action.setSlaXml(a.getSlaXml());
action.setStatus(a.getStatus());
return action;
}
return null;
}
public CoordinatorActionBean getAction(String id, boolean b) {
return null;
}
public List<CoordinatorActionBean> getRunningActionsForCoordinatorJob(final String jobId, final boolean locking)
throws StoreException {
ParamChecker.notEmpty(jobId, "CoordinatorJobID");
List<CoordinatorActionBean> actions = doOperation("getRunningActionsForCoordinatorJob",
new Callable<List<CoordinatorActionBean>>() {
@SuppressWarnings("unchecked")
public List<CoordinatorActionBean> call() throws StoreException {
List<CoordinatorActionBean> actions;
try {
Query q = entityManager.createNamedQuery("GET_RUNNING_ACTIONS_FOR_COORD_JOB");
q.setParameter("jobId", jobId);
/*
* if (locking) {
* q.setHint("openjpa.FetchPlan.ReadLockMode",
* "READ"); OpenJPAQuery oq =
* OpenJPAPersistence.cast(q); FetchPlan fetch =
* oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // no limit }
*/
actions = q.getResultList();
return actions;
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
}
});
return actions;
}
public List<CoordinatorActionBean> getRunningActionsOlderThan(final long checkAgeSecs, final boolean locking)
throws StoreException {
List<CoordinatorActionBean> actions = doOperation("getRunningActionsOlderThan",
new Callable<List<CoordinatorActionBean>>() {
@SuppressWarnings("unchecked")
public List<CoordinatorActionBean> call() throws StoreException {
List<CoordinatorActionBean> actions;
Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
try {
Query q = entityManager.createNamedQuery("GET_RUNNING_ACTIONS_OLDER_THAN");
q.setParameter("lastModifiedTime", ts);
/*
* if (locking) { OpenJPAQuery oq =
* OpenJPAPersistence.cast(q); FetchPlan fetch =
* oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // no limit }
*/
actions = q.getResultList();
return actions;
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
}
});
return actions;
}
public List<CoordinatorActionBean> getRecoveryActionsOlderThan(final long checkAgeSecs, final boolean locking)
throws StoreException {
List<CoordinatorActionBean> actions = doOperation("getRunningActionsOlderThan",
new Callable<List<CoordinatorActionBean>>() {
@SuppressWarnings("unchecked")
public List<CoordinatorActionBean> call() throws StoreException {
List<CoordinatorActionBean> actions;
try {
Query q = entityManager.createNamedQuery("GET_COORD_ACTIONS_FOR_RECOVERY_OLDER_THAN");
Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
q.setParameter("lastModifiedTime", ts);
/*
* if (locking) { OpenJPAQuery oq =
* OpenJPAPersistence.cast(q); FetchPlan fetch =
* oq.getFetchPlan();
* fetch.setReadLockMode(LockModeType.WRITE);
* fetch.setLockTimeout(-1); // no limit }
*/
actions = q.getResultList();
return actions;
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
}
});
return actions;
}
/**
* Get coordinator action beans for given start date and end date
*
* @param startDate
* @param endDate
* @return list of coordinator action beans
* @throws StoreException
*/
public List<CoordinatorActionBean> getCoordActionsForDates(final String jobId, final Date startDate,
final Date endDate)
throws StoreException {
List<CoordinatorActionBean> actions = doOperation("getCoordActionsForDates",
new Callable<List<CoordinatorActionBean>>() {
@SuppressWarnings("unchecked")
public List<CoordinatorActionBean> call() throws StoreException {
List<CoordinatorActionBean> actions;
try {
Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_DATES");
q.setParameter("jobId", jobId);
q.setParameter("startTime", new Timestamp(startDate.getTime()));
q.setParameter("endTime", new Timestamp(endDate.getTime()));
actions = q.getResultList();
List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>();
for (CoordinatorActionBean a : actions) {
CoordinatorActionBean aa = getBeanForRunningCoordAction(a);
actionList.add(aa);
}
return actionList;
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
}
});
return actions;
}
/**
* Get coordinator action bean for given date
*
* @param nominalTime
* @return CoordinatorActionBean
* @throws StoreException
*/
public CoordinatorActionBean getCoordActionForNominalTime(final String jobId, final Date nominalTime)
throws StoreException {
CoordinatorActionBean action = doOperation("getCoordActionForNominalTime",
new Callable<CoordinatorActionBean>() {
@SuppressWarnings("unchecked")
public CoordinatorActionBean call() throws StoreException {
List<CoordinatorActionBean> actions;
Query q = entityManager.createNamedQuery("GET_ACTION_FOR_NOMINALTIME");
q.setParameter("jobId", jobId);
q.setParameter("nominalTime", new Timestamp(nominalTime.getTime()));
actions = q.getResultList();
CoordinatorActionBean action = null;
if (actions.size() > 0) {
action = actions.get(0);
}
else {
throw new StoreException(ErrorCode.E0605, DateUtils.convertDateToString(nominalTime));
}
return getBeanForRunningCoordAction(action);
}
});
return action;
}
public List<String> getRecoveryActionsGroupByJobId(final long checkAgeSecs) throws StoreException {
List<String> jobids = doOperation("getRecoveryActionsGroupByJobId", new Callable<List<String>>() {
@SuppressWarnings("unchecked")
public List<String> call() throws StoreException {
List<String> jobids = new ArrayList<String>();
try {
Query q = entityManager.createNamedQuery("GET_READY_ACTIONS_GROUP_BY_JOBID");
Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
q.setParameter(1, ts);
List<Object[]> list = q.getResultList();
for (Object[] arr : list) {
if (arr != null && arr[0] != null) {
jobids.add((String) arr[0]);
}
}
return jobids;
}
catch (IllegalStateException e) {
throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
}
}
});
return jobids;
}
}