001 /**
002 * Copyright (c) 2010 Yahoo! Inc. All rights reserved.
003 * Licensed under the Apache License, Version 2.0 (the "License");
004 * you may not use this file except in compliance with the License.
005 * You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software
010 * distributed under the License is distributed on an "AS IS" BASIS,
011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 * See the License for the specific language governing permissions and
013 * limitations under the License. See accompanying LICENSE file.
014 */
015 package org.apache.oozie.store;
016
017 import java.sql.SQLException;
018 import java.sql.Timestamp;
019 import java.util.ArrayList;
020 import java.util.Date;
021 import java.util.List;
022 import java.util.Map;
023 import java.util.concurrent.Callable;
024
025 import javax.persistence.EntityManager;
026 import javax.persistence.Query;
027
028 import org.apache.oozie.CoordinatorActionBean;
029 import org.apache.oozie.CoordinatorJobBean;
030 import org.apache.oozie.CoordinatorJobInfo;
031 import org.apache.oozie.ErrorCode;
032 import org.apache.oozie.client.CoordinatorJob.Status;
033 import org.apache.oozie.client.CoordinatorJob.Timeunit;
034 import org.apache.oozie.service.InstrumentationService;
035 import org.apache.oozie.service.Services;
036 import org.apache.oozie.util.DateUtils;
037 import org.apache.oozie.util.Instrumentation;
038 import org.apache.oozie.util.ParamChecker;
039 import org.apache.oozie.util.XLog;
040 import org.apache.oozie.workflow.WorkflowException;
041 import org.apache.openjpa.persistence.OpenJPAPersistence;
042 import org.apache.openjpa.persistence.OpenJPAQuery;
043 import org.apache.openjpa.persistence.jdbc.FetchDirection;
044 import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan;
045 import org.apache.openjpa.persistence.jdbc.LRSSizeAlgorithm;
046 import org.apache.openjpa.persistence.jdbc.ResultSetType;
047
048 /**
049 * DB Implementation of Coord Store
050 */
051 public class CoordinatorStore extends Store {
052 private final XLog log = XLog.getLog(getClass());
053
054 private EntityManager entityManager;
055 private static final String INSTR_GROUP = "db";
056 public static final int LOCK_TIMEOUT = 50000;
057 private static final long DAY_IN_MS = 24 * 60 * 60 * 1000;
058
059 public CoordinatorStore(boolean selectForUpdate) throws StoreException {
060 super();
061 entityManager = getEntityManager();
062 }
063
064 public CoordinatorStore(Store store, boolean selectForUpdate) throws StoreException {
065 super(store);
066 entityManager = getEntityManager();
067 }
068
069 /**
070 * Create a CoordJobBean. It also creates the process instance for the job.
071 *
072 * @param workflow workflow bean
073 * @throws StoreException
074 */
075
076 public void insertCoordinatorJob(final CoordinatorJobBean coordinatorJob) throws StoreException {
077 ParamChecker.notNull(coordinatorJob, "coordinatorJob");
078
079 doOperation("insertCoordinatorJob", new Callable<Void>() {
080 public Void call() throws StoreException {
081 entityManager.persist(coordinatorJob);
082 return null;
083 }
084 });
085 }
086
087 /**
088 * Load the CoordinatorJob into a Bean and return it. Also load the Workflow Instance into the bean. And lock the
089 * Workflow depending on the locking parameter.
090 *
091 * @param id Job ID
092 * @param locking Flag for Table Lock
093 * @return CoordinatorJobBean
094 * @throws StoreException
095 */
096 public CoordinatorJobBean getCoordinatorJob(final String id, final boolean locking) throws StoreException {
097 ParamChecker.notEmpty(id, "CoordJobId");
098 CoordinatorJobBean cjBean = doOperation("getCoordinatorJob", new Callable<CoordinatorJobBean>() {
099 @SuppressWarnings("unchecked")
100 public CoordinatorJobBean call() throws StoreException {
101 Query q = entityManager.createNamedQuery("GET_COORD_JOB");
102 q.setParameter("id", id);
103 /*
104 * if (locking) { OpenJPAQuery oq = OpenJPAPersistence.cast(q);
105 * // q.setHint("openjpa.FetchPlan.ReadLockMode","WRITE");
106 * FetchPlan fetch = oq.getFetchPlan();
107 * fetch.setReadLockMode(LockModeType.WRITE);
108 * fetch.setLockTimeout(-1); // 1 second }
109 */
110 List<CoordinatorJobBean> cjBeans = q.getResultList();
111
112 if (cjBeans.size() > 0) {
113 return cjBeans.get(0);
114 }
115 else {
116 throw new StoreException(ErrorCode.E0604, id);
117 }
118 }
119 });
120
121 cjBean.setStatus(cjBean.getStatus());
122 return cjBean;
123 }
124
125 /**
126 * Get a list of Coordinator Jobs that should be materialized. Jobs with a 'last materialized time' older than the
127 * argument will be returned.
128 *
129 * @param d Date
130 * @return List of Coordinator Jobs that have a last materialized time older than input date
131 * @throws StoreException
132 */
133 public List<CoordinatorJobBean> getCoordinatorJobsToBeMaterialized(final Date d, final int limit)
134 throws StoreException {
135
136 ParamChecker.notNull(d, "Coord Job Materialization Date");
137 List<CoordinatorJobBean> cjBeans = doOperation("getCoordinatorJobsToBeMaterialized",
138 new Callable<List<CoordinatorJobBean>>() {
139 public List<CoordinatorJobBean> call() throws StoreException {
140
141 List<CoordinatorJobBean> cjBeans;
142 List<CoordinatorJobBean> jobList = new ArrayList<CoordinatorJobBean>();
143 try {
144 Query q = entityManager.createNamedQuery("GET_COORD_JOBS_OLDER_THAN");
145 q.setParameter("matTime", new Timestamp(d.getTime()));
146 if (limit > 0) {
147 q.setMaxResults(limit);
148 }
149 /*
150 OpenJPAQuery oq = OpenJPAPersistence.cast(q);
151 FetchPlan fetch = oq.getFetchPlan();
152 fetch.setReadLockMode(LockModeType.WRITE);
153 fetch.setLockTimeout(-1); // no limit
154 */
155 cjBeans = q.getResultList();
156 // copy results to a new object
157 for (CoordinatorJobBean j : cjBeans) {
158 jobList.add(j);
159 }
160 }
161 catch (IllegalStateException e) {
162 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
163 }
164 return jobList;
165
166 }
167 });
168 return cjBeans;
169 }
170
171 /**
172 * A list of Coordinator Jobs that are matched with the status and have last materialized time' older than
173 * checkAgeSecs will be returned.
174 *
175 * @param checkAgeSecs Job age in Seconds
176 * @param status Coordinator Job Status
177 * @param limit Number of results to return
178 * @param locking Flag for Table Lock
179 * @return List of Coordinator Jobs that are matched with the parameters.
180 * @throws StoreException
181 */
182 public List<CoordinatorJobBean> getCoordinatorJobsOlderThanStatus(final long checkAgeSecs, final String status,
183 final int limit, final boolean locking) throws StoreException {
184
185 ParamChecker.notNull(status, "Coord Job Status");
186 List<CoordinatorJobBean> cjBeans = doOperation("getCoordinatorJobsOlderThanStatus",
187 new Callable<List<CoordinatorJobBean>>() {
188 public List<CoordinatorJobBean> call() throws StoreException {
189
190 List<CoordinatorJobBean> cjBeans;
191 List<CoordinatorJobBean> jobList = new ArrayList<CoordinatorJobBean>();
192 try {
193 Query q = entityManager.createNamedQuery("GET_COORD_JOBS_OLDER_THAN_STATUS");
194 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
195 q.setParameter("lastModTime", ts);
196 q.setParameter("status", status);
197 if (limit > 0) {
198 q.setMaxResults(limit);
199 }
200 /*
201 * if (locking) { OpenJPAQuery oq =
202 * OpenJPAPersistence.cast(q); FetchPlan fetch =
203 * oq.getFetchPlan();
204 * fetch.setReadLockMode(LockModeType.WRITE);
205 * fetch.setLockTimeout(-1); // no limit }
206 */
207 cjBeans = q.getResultList();
208 for (CoordinatorJobBean j : cjBeans) {
209 jobList.add(j);
210 }
211 }
212 catch (Exception e) {
213 throw new StoreException(ErrorCode.E0603, e.getMessage(), e);
214 }
215 return jobList;
216
217 }
218 });
219 return cjBeans;
220 }
221
222 /**
223 * Load the CoordinatorAction into a Bean and return it.
224 *
225 * @param id action ID
226 * @return CoordinatorActionBean
227 * @throws StoreException
228 */
229 public CoordinatorActionBean getCoordinatorAction(final String id, final boolean locking) throws StoreException {
230 ParamChecker.notEmpty(id, "actionID");
231 CoordinatorActionBean caBean = doOperation("getCoordinatorAction", new Callable<CoordinatorActionBean>() {
232 public CoordinatorActionBean call() throws StoreException {
233 Query q = entityManager.createNamedQuery("GET_COORD_ACTION");
234 q.setParameter("id", id);
235 OpenJPAQuery oq = OpenJPAPersistence.cast(q);
236 /*
237 * if (locking) { //q.setHint("openjpa.FetchPlan.ReadLockMode",
238 * "WRITE"); FetchPlan fetch = oq.getFetchPlan();
239 * fetch.setReadLockMode(LockModeType.WRITE);
240 * fetch.setLockTimeout(-1); // no limit }
241 */
242
243 CoordinatorActionBean action = null;
244 List<CoordinatorActionBean> actions = q.getResultList();
245 if (actions.size() > 0) {
246 action = actions.get(0);
247 }
248 else {
249 throw new StoreException(ErrorCode.E0605, id);
250 }
251
252 /*
253 * if (locking) return action; else
254 */
255 return getBeanForRunningCoordAction(action);
256 }
257 });
258 return caBean;
259 }
260
261 /**
262 * Return CoordinatorActions for a jobID. Action should be in READY state. Number of returned actions should be <=
263 * concurrency number. Sort returned actions based on execution order (FIFO, LIFO, LAST_ONLY)
264 *
265 * @param id job ID
266 * @param numResults number of results to return
267 * @param executionOrder execution for this job - FIFO, LIFO, LAST_ONLY
268 * @return List of CoordinatorActionBean
269 * @throws StoreException
270 */
271 public List<CoordinatorActionBean> getCoordinatorActionsForJob(final String id, final int numResults,
272 final String executionOrder) throws StoreException {
273 ParamChecker.notEmpty(id, "jobID");
274 List<CoordinatorActionBean> caBeans = doOperation("getCoordinatorActionsForJob",
275 new Callable<List<CoordinatorActionBean>>() {
276 public List<CoordinatorActionBean> call() throws StoreException {
277
278 List<CoordinatorActionBean> caBeans;
279 Query q;
280 // check if executionOrder is FIFO, LIFO, or LAST_ONLY
281 if (executionOrder.equalsIgnoreCase("FIFO")) {
282 q = entityManager.createNamedQuery("GET_COORD_ACTIONS_FOR_JOB_FIFO");
283 }
284 else {
285 q = entityManager.createNamedQuery("GET_COORD_ACTIONS_FOR_JOB_LIFO");
286 }
287 q.setParameter("jobId", id);
288 // if executionOrder is LAST_ONLY, only retrieve first
289 // record in LIFO,
290 // otherwise, use numResults if it is positive.
291 if (executionOrder.equalsIgnoreCase("LAST_ONLY")) {
292 q.setMaxResults(1);
293 }
294 else {
295 if (numResults > 0) {
296 q.setMaxResults(numResults);
297 }
298 }
299 caBeans = q.getResultList();
300 return caBeans;
301 }
302 });
303 return caBeans;
304 }
305
306 /**
307 * Return CoordinatorActions for a jobID. Action should be in READY state. Number of returned actions should be <=
308 * concurrency number.
309 *
310 * @param id job ID
311 * @return Number of running actions
312 * @throws StoreException
313 */
314 public int getCoordinatorRunningActionsCount(final String id) throws StoreException {
315 ParamChecker.notEmpty(id, "jobID");
316 Integer cnt = doOperation("getCoordinatorRunningActionsCount", new Callable<Integer>() {
317 public Integer call() throws SQLException {
318
319 Query q = entityManager.createNamedQuery("GET_COORD_RUNNING_ACTIONS_COUNT");
320
321 q.setParameter("jobId", id);
322 Long count = (Long) q.getSingleResult();
323 return Integer.valueOf(count.intValue());
324 }
325 });
326 return cnt.intValue();
327 }
328
329 /**
330 * Create a new Action record in the ACTIONS table with the given Bean.
331 *
332 * @param action WorkflowActionBean
333 * @throws StoreException If the action is already present
334 */
335 public void insertCoordinatorAction(final CoordinatorActionBean action) throws StoreException {
336 ParamChecker.notNull(action, "CoordinatorActionBean");
337 doOperation("insertCoordinatorAction", new Callable<Void>() {
338 public Void call() throws StoreException {
339 entityManager.persist(action);
340 return null;
341 }
342 });
343 }
344
345 /**
346 * Update the given action bean to DB.
347 *
348 * @param action Action Bean
349 * @throws StoreException if action doesn't exist
350 */
351 public void updateCoordinatorAction(final CoordinatorActionBean action) throws StoreException {
352 ParamChecker.notNull(action, "CoordinatorActionBean");
353 doOperation("updateCoordinatorAction", new Callable<Void>() {
354 public Void call() throws StoreException {
355 Query q = entityManager.createNamedQuery("UPDATE_COORD_ACTION");
356 q.setParameter("id", action.getId());
357 setActionQueryParameters(action, q);
358 q.executeUpdate();
359 return null;
360 }
361 });
362 }
363
364 /**
365 * Update the given action bean to DB.
366 *
367 * @param action Action Bean
368 * @throws StoreException if action doesn't exist
369 */
370 public void updateCoordActionMin(final CoordinatorActionBean action) throws StoreException {
371 ParamChecker.notNull(action, "CoordinatorActionBean");
372 doOperation("updateCoordinatorAction", new Callable<Void>() {
373 public Void call() throws StoreException {
374 Query q = entityManager.createNamedQuery("UPDATE_COORD_ACTION_MIN");
375 q.setParameter("id", action.getId());
376 q.setParameter("missingDependencies", action.getMissingDependencies());
377 q.setParameter("lastModifiedTime", new Date());
378 q.setParameter("status", action.getStatus().toString());
379 q.setParameter("actionXml", action.getActionXml());
380 q.executeUpdate();
381 return null;
382 }
383 });
384 }
385
386 /**
387 * Update the given coordinator job bean to DB.
388 *
389 * @param jobbean Coordinator Job Bean
390 * @throws StoreException if action doesn't exist
391 */
392 public void updateCoordinatorJob(final CoordinatorJobBean job) throws StoreException {
393 ParamChecker.notNull(job, "CoordinatorJobBean");
394 doOperation("updateJob", new Callable<Void>() {
395 public Void call() throws StoreException {
396 Query q = entityManager.createNamedQuery("UPDATE_COORD_JOB");
397 q.setParameter("id", job.getId());
398 setJobQueryParameters(job, q);
399 q.executeUpdate();
400 return null;
401 }
402 });
403 }
404
405 public void updateCoordinatorJobStatus(final CoordinatorJobBean job) throws StoreException {
406 ParamChecker.notNull(job, "CoordinatorJobBean");
407 doOperation("updateJobStatus", new Callable<Void>() {
408 public Void call() throws StoreException {
409 Query q = entityManager.createNamedQuery("UPDATE_COORD_JOB_STATUS");
410 q.setParameter("id", job.getId());
411 q.setParameter("status", job.getStatus().toString());
412 q.setParameter("lastModifiedTime", new Date());
413 q.executeUpdate();
414 return null;
415 }
416 });
417 }
418
419 private <V> V doOperation(String name, Callable<V> command) throws StoreException {
420 try {
421 Instrumentation.Cron cron = new Instrumentation.Cron();
422 cron.start();
423 V retVal;
424 try {
425 retVal = command.call();
426 }
427 finally {
428 cron.stop();
429 }
430 Services.get().get(InstrumentationService.class).get().addCron(INSTR_GROUP, name, cron);
431 return retVal;
432 }
433 catch (StoreException ex) {
434 throw ex;
435 }
436 catch (SQLException ex) {
437 throw new StoreException(ErrorCode.E0603, name, ex.getMessage(), ex);
438 }
439 catch (Exception e) {
440 throw new StoreException(ErrorCode.E0607, name, e.getMessage(), e);
441 }
442 }
443
444 private void setJobQueryParameters(CoordinatorJobBean jBean, Query q) {
445 q.setParameter("appName", jBean.getAppName());
446 q.setParameter("appPath", jBean.getAppPath());
447 q.setParameter("concurrency", jBean.getConcurrency());
448 q.setParameter("conf", jBean.getConf());
449 q.setParameter("externalId", jBean.getExternalId());
450 q.setParameter("frequency", jBean.getFrequency());
451 q.setParameter("lastActionNumber", jBean.getLastActionNumber());
452 q.setParameter("timeOut", jBean.getTimeout());
453 q.setParameter("timeZone", jBean.getTimeZone());
454 q.setParameter("authToken", jBean.getAuthToken());
455 q.setParameter("createdTime", jBean.getCreatedTimestamp());
456 q.setParameter("endTime", jBean.getEndTimestamp());
457 q.setParameter("execution", jBean.getExecution());
458 q.setParameter("jobXml", jBean.getJobXml());
459 q.setParameter("lastAction", jBean.getLastActionTimestamp());
460 q.setParameter("lastModifiedTime", new Date());
461 q.setParameter("nextMaterializedTime", jBean.getNextMaterializedTimestamp());
462 q.setParameter("origJobXml", jBean.getOrigJobXml());
463 q.setParameter("slaXml", jBean.getSlaXml());
464 q.setParameter("startTime", jBean.getStartTimestamp());
465 q.setParameter("status", jBean.getStatus().toString());
466 q.setParameter("timeUnit", jBean.getTimeUnitStr());
467 }
468
469 private void setActionQueryParameters(CoordinatorActionBean aBean, Query q) {
470 q.setParameter("actionNumber", aBean.getActionNumber());
471 q.setParameter("actionXml", aBean.getActionXml());
472 q.setParameter("consoleUrl", aBean.getConsoleUrl());
473 q.setParameter("createdConf", aBean.getCreatedConf());
474 q.setParameter("errorCode", aBean.getErrorCode());
475 q.setParameter("errorMessage", aBean.getErrorMessage());
476 q.setParameter("externalStatus", aBean.getExternalStatus());
477 q.setParameter("missingDependencies", aBean.getMissingDependencies());
478 q.setParameter("runConf", aBean.getRunConf());
479 q.setParameter("timeOut", aBean.getTimeOut());
480 q.setParameter("trackerUri", aBean.getTrackerUri());
481 q.setParameter("type", aBean.getType());
482 q.setParameter("createdTime", aBean.getCreatedTimestamp());
483 q.setParameter("externalId", aBean.getExternalId());
484 q.setParameter("jobId", aBean.getJobId());
485 q.setParameter("lastModifiedTime", new Date());
486 q.setParameter("nominalTime", aBean.getNominalTimestamp());
487 q.setParameter("slaXml", aBean.getSlaXml());
488 q.setParameter("status", aBean.getStatus().toString());
489 }
490
491 public int purgeActions(final long olderThanDays, final long limit) throws StoreException {
492
493 Integer count = doOperation("coord-purge-actions", new Callable<Integer>() {
494 public Integer call() throws SQLException, StoreException, WorkflowException {
495 Timestamp createdTime = new Timestamp(System.currentTimeMillis() - (olderThanDays * DAY_IN_MS));
496 /*
497 * this may be better - but does not work? Query g =
498 * entityManager
499 * .createNamedQuery("DELETE_COMPLETED_COORD_ACTIONS");
500 * g.setParameter("id", id); int deleted_action =
501 * g.executeUpdate();
502 */
503 Query q = entityManager.createNamedQuery("GET_COMPLETED_ACTIONS_OLDER_THAN");
504 q.setParameter("createdTime", createdTime);
505 q.setMaxResults((int) limit);
506 List<CoordinatorActionBean> coordactions = q.getResultList();
507 for (CoordinatorActionBean a : coordactions) {
508 String id = a.getId();
509 // remove surely removes - but expensive - to be compared?
510 entityManager.remove(a);
511
512 }
513
514 return coordactions.size();
515 }
516 });
517 return Integer.valueOf(count);
518 }
519
520 public int purgeJobs(final long olderThanDays, final long limit) throws StoreException {
521
522 Integer count = doOperation("coord-purge-jobs", new Callable<Integer>() {
523 public Integer call() throws SQLException, StoreException, WorkflowException {
524
525 Timestamp lastModTm = new Timestamp(System.currentTimeMillis() - (olderThanDays * DAY_IN_MS));
526
527 Query jobQ = entityManager.createNamedQuery("GET_COMPLETED_COORD_JOBS_OLDER_THAN_STATUS");
528 jobQ.setParameter("lastModTime", lastModTm);
529 jobQ.setMaxResults((int) limit);
530 List<CoordinatorJobBean> coordJobs = jobQ.getResultList();
531 int deleted = 0;
532 for (CoordinatorJobBean a : coordJobs) {
533 String jobId = a.getId();
534
535 Query actionQ = entityManager.createNamedQuery("GET_COORD_ACTIONS_COUNT_BY_JOBID");
536 actionQ.setParameter("jobId", jobId);
537 Long count = (Long) actionQ.getSingleResult();
538
539 if (count.intValue() == 0) {
540 // remove surely removes - but expensive - to be
541 // compared?
542 entityManager.remove(a);
543 deleted++;
544 }
545 }
546
547 return deleted;
548 }
549 });
550 return Integer.valueOf(count);
551 }
552
553 public void commit() throws StoreException {
554 }
555
556 public void close() throws StoreException {
557 }
558
559 public CoordinatorJobBean getCoordinatorJobs(String id) {
560 // TODO Auto-generated method stub
561 return null;
562 }
563
564 public CoordinatorJobInfo getCoordinatorInfo(final Map<String, List<String>> filter, final int start, final int len)
565 throws StoreException {
566
567 CoordinatorJobInfo coordJobInfo = doOperation("getCoordinatorJobInfo", new Callable<CoordinatorJobInfo>() {
568 public CoordinatorJobInfo call() throws SQLException, StoreException {
569 List<String> orArray = new ArrayList<String>();
570 List<String> colArray = new ArrayList<String>();
571 List<String> valArray = new ArrayList<String>();
572 StringBuilder sb = new StringBuilder("");
573
574 StoreStatusFilter.filter(filter, orArray, colArray, valArray, sb, StoreStatusFilter.coordSeletStr,
575 StoreStatusFilter.coordCountStr);
576
577 int realLen = 0;
578
579 Query q = null;
580 Query qTotal = null;
581 if (orArray.size() == 0) {
582 q = entityManager.createNamedQuery("GET_COORD_JOBS_COLUMNS");
583 q.setFirstResult(start - 1);
584 q.setMaxResults(len);
585 qTotal = entityManager.createNamedQuery("GET_COORD_JOBS_COUNT");
586 }
587 else {
588 StringBuilder sbTotal = new StringBuilder(sb);
589 sb.append(" order by w.createdTimestamp desc ");
590 XLog.getLog(getClass()).debug("Created String is **** " + sb.toString());
591 q = entityManager.createQuery(sb.toString());
592 q.setFirstResult(start - 1);
593 q.setMaxResults(len);
594 qTotal = entityManager.createQuery(sbTotal.toString().replace(StoreStatusFilter.coordSeletStr,
595 StoreStatusFilter.coordCountStr));
596 }
597
598 for (int i = 0; i < orArray.size(); i++) {
599 q.setParameter(colArray.get(i), valArray.get(i));
600 qTotal.setParameter(colArray.get(i), valArray.get(i));
601 }
602
603 OpenJPAQuery kq = OpenJPAPersistence.cast(q);
604 JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan();
605 fetch.setFetchBatchSize(20);
606 fetch.setResultSetType(ResultSetType.SCROLL_INSENSITIVE);
607 fetch.setFetchDirection(FetchDirection.FORWARD);
608 fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.LAST);
609 List<?> resultList = q.getResultList();
610 List<Object[]> objectArrList = (List<Object[]>) resultList;
611 List<CoordinatorJobBean> coordBeansList = new ArrayList<CoordinatorJobBean>();
612
613 for (Object[] arr : objectArrList) {
614 CoordinatorJobBean ww = getBeanForCoordinatorJobFromArray(arr);
615 coordBeansList.add(ww);
616 }
617
618 realLen = ((Long) qTotal.getSingleResult()).intValue();
619
620 return new CoordinatorJobInfo(coordBeansList, start, len, realLen);
621 }
622 });
623 return coordJobInfo;
624 }
625
626 private CoordinatorJobBean getBeanForCoordinatorJobFromArray(Object[] arr) {
627 CoordinatorJobBean bean = new CoordinatorJobBean();
628 bean.setId((String) arr[0]);
629 if (arr[1] != null) {
630 bean.setAppName((String) arr[1]);
631 }
632 if (arr[2] != null) {
633 bean.setStatus(Status.valueOf((String) arr[2]));
634 }
635 if (arr[3] != null) {
636 bean.setUser((String) arr[3]);
637 }
638 if (arr[4] != null) {
639 bean.setGroup((String) arr[4]);
640 }
641 if (arr[5] != null) {
642 bean.setStartTime((Timestamp) arr[5]);
643 }
644 if (arr[6] != null) {
645 bean.setEndTime((Timestamp) arr[6]);
646 }
647 if (arr[7] != null) {
648 bean.setAppPath((String) arr[7]);
649 }
650 if (arr[8] != null) {
651 bean.setConcurrency(((Integer) arr[8]).intValue());
652 }
653 if (arr[9] != null) {
654 bean.setFrequency(((Integer) arr[9]).intValue());
655 }
656 if (arr[10] != null) {
657 bean.setLastActionTime((Timestamp) arr[10]);
658 }
659 if (arr[11] != null) {
660 bean.setNextMaterializedTime((Timestamp) arr[11]);
661 }
662 if (arr[13] != null) {
663 bean.setTimeUnit(Timeunit.valueOf((String) arr[13]));
664 }
665 if (arr[14] != null) {
666 bean.setTimeZone((String) arr[14]);
667 }
668 if (arr[15] != null) {
669 bean.setTimeout((Integer) arr[15]);
670 }
671 return bean;
672 }
673
674 /**
675 * Loads all actions for the given Coordinator job.
676 *
677 * @param jobId coordinator job id
678 * @param locking true if Actions are to be locked
679 * @return A List of CoordinatorActionBean
680 * @throws StoreException
681 */
682 public List<CoordinatorActionBean> getActionsForCoordinatorJob(final String jobId, final boolean locking)
683 throws StoreException {
684 ParamChecker.notEmpty(jobId, "CoordinatorJobID");
685 List<CoordinatorActionBean> actions = doOperation("getActionsForCoordinatorJob",
686 new Callable<List<CoordinatorActionBean>>() {
687 @SuppressWarnings("unchecked")
688 public List<CoordinatorActionBean> call() throws StoreException {
689 List<CoordinatorActionBean> actions;
690 List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>();
691 try {
692 Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_COORD_JOB");
693 q.setParameter("jobId", jobId);
694 /*
695 * if (locking) { //
696 * q.setHint("openjpa.FetchPlan.ReadLockMode", //
697 * "READ"); OpenJPAQuery oq =
698 * OpenJPAPersistence.cast(q); JDBCFetchPlan fetch =
699 * (JDBCFetchPlan) oq.getFetchPlan();
700 * fetch.setReadLockMode(LockModeType.WRITE);
701 * fetch.setLockTimeout(-1); // 1 second }
702 */
703 actions = q.getResultList();
704 for (CoordinatorActionBean a : actions) {
705 CoordinatorActionBean aa = getBeanForRunningCoordAction(a);
706 actionList.add(aa);
707 }
708 }
709 catch (IllegalStateException e) {
710 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
711 }
712 /*
713 * if (locking) { return actions; } else {
714 */
715 return actionList;
716 // }
717 }
718 });
719 return actions;
720 }
721
722 /**
723 * Loads given number of actions for the given Coordinator job.
724 *
725 * @param jobId coordinator job id
726 * @param start offset for select statement
727 * @param len number of Workflow Actions to be returned
728 * @return A List of CoordinatorActionBean
729 * @throws StoreException
730 */
731 public List<CoordinatorActionBean> getActionsSubsetForCoordinatorJob(final String jobId, final int start,
732 final int len) throws StoreException {
733 ParamChecker.notEmpty(jobId, "CoordinatorJobID");
734 List<CoordinatorActionBean> actions = doOperation("getActionsForCoordinatorJob",
735 new Callable<List<CoordinatorActionBean>>() {
736 @SuppressWarnings("unchecked")
737 public List<CoordinatorActionBean> call() throws StoreException {
738 List<CoordinatorActionBean> actions;
739 List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>();
740 try {
741 Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_COORD_JOB");
742 q.setParameter("jobId", jobId);
743 q.setFirstResult(start - 1);
744 q.setMaxResults(len);
745 actions = q.getResultList();
746 for (CoordinatorActionBean a : actions) {
747 CoordinatorActionBean aa = getBeanForRunningCoordAction(a);
748 actionList.add(aa);
749 }
750 }
751 catch (IllegalStateException e) {
752 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
753 }
754 return actionList;
755 }
756 });
757 return actions;
758 }
759
760 protected CoordinatorActionBean getBeanForRunningCoordAction(CoordinatorActionBean a) {
761 if (a != null) {
762 CoordinatorActionBean action = new CoordinatorActionBean();
763 action.setId(a.getId());
764 action.setActionNumber(a.getActionNumber());
765 action.setActionXml(a.getActionXml());
766 action.setConsoleUrl(a.getConsoleUrl());
767 action.setCreatedConf(a.getCreatedConf());
768 //action.setErrorCode(a.getErrorCode());
769 //action.setErrorMessage(a.getErrorMessage());
770 action.setExternalStatus(a.getExternalStatus());
771 action.setMissingDependencies(a.getMissingDependencies());
772 action.setRunConf(a.getRunConf());
773 action.setTimeOut(a.getTimeOut());
774 action.setTrackerUri(a.getTrackerUri());
775 action.setType(a.getType());
776 action.setCreatedTime(a.getCreatedTime());
777 action.setExternalId(a.getExternalId());
778 action.setJobId(a.getJobId());
779 action.setLastModifiedTime(a.getLastModifiedTime());
780 action.setNominalTime(a.getNominalTime());
781 action.setSlaXml(a.getSlaXml());
782 action.setStatus(a.getStatus());
783 return action;
784 }
785 return null;
786 }
787
788 public CoordinatorActionBean getAction(String id, boolean b) {
789 return null;
790 }
791
792 /*
793 * do not need this public void updateCoordinatorActionForExternalId(final
794 * CoordinatorActionBean action) throws StoreException { // TODO
795 * Auto-generated method stub ParamChecker.notNull(action,
796 * "updateCoordinatorActionForExternalId");
797 * doOperation("updateCoordinatorActionForExternalId", new Callable<Void>()
798 * { public Void call() throws SQLException, StoreException,
799 * WorkflowException { Query q =
800 * entityManager.createNamedQuery("UPDATE_COORD_ACTION_FOR_EXTERNALID");
801 * setActionQueryParameters(action,q); q.executeUpdate(); return null; } });
802 * }
803 */
804 public CoordinatorActionBean getCoordinatorActionForExternalId(final String externalId) throws StoreException {
805 // TODO Auto-generated method stub
806 ParamChecker.notEmpty(externalId, "coodinatorActionExternalId");
807 CoordinatorActionBean cBean = doOperation("getCoordinatorActionForExternalId",
808 new Callable<CoordinatorActionBean>() {
809 public CoordinatorActionBean call() throws StoreException {
810 CoordinatorActionBean caBean = null;
811 Query q = entityManager.createNamedQuery("GET_COORD_ACTION_FOR_EXTERNALID");
812 q.setParameter("externalId", externalId);
813 List<CoordinatorActionBean> actionList = q.getResultList();
814 if (actionList.size() > 0) {
815 caBean = actionList.get(0);
816 }
817 return caBean;
818 }
819 });
820 return cBean;
821 }
822
823 public List<CoordinatorActionBean> getRunningActionsForCoordinatorJob(final String jobId, final boolean locking)
824 throws StoreException {
825 ParamChecker.notEmpty(jobId, "CoordinatorJobID");
826 List<CoordinatorActionBean> actions = doOperation("getRunningActionsForCoordinatorJob",
827 new Callable<List<CoordinatorActionBean>>() {
828 @SuppressWarnings("unchecked")
829 public List<CoordinatorActionBean> call() throws StoreException {
830 List<CoordinatorActionBean> actions;
831 try {
832 Query q = entityManager.createNamedQuery("GET_RUNNING_ACTIONS_FOR_COORD_JOB");
833 q.setParameter("jobId", jobId);
834 /*
835 * if (locking) {
836 * q.setHint("openjpa.FetchPlan.ReadLockMode",
837 * "READ"); OpenJPAQuery oq =
838 * OpenJPAPersistence.cast(q); FetchPlan fetch =
839 * oq.getFetchPlan();
840 * fetch.setReadLockMode(LockModeType.WRITE);
841 * fetch.setLockTimeout(-1); // no limit }
842 */
843 actions = q.getResultList();
844 return actions;
845 }
846 catch (IllegalStateException e) {
847 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
848 }
849 }
850 });
851 return actions;
852 }
853
854 public List<CoordinatorActionBean> getRunningActionsOlderThan(final long checkAgeSecs, final boolean locking)
855 throws StoreException {
856 List<CoordinatorActionBean> actions = doOperation("getRunningActionsOlderThan",
857 new Callable<List<CoordinatorActionBean>>() {
858 @SuppressWarnings("unchecked")
859 public List<CoordinatorActionBean> call() throws StoreException {
860 List<CoordinatorActionBean> actions;
861 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
862 try {
863 Query q = entityManager.createNamedQuery("GET_RUNNING_ACTIONS_OLDER_THAN");
864 q.setParameter("lastModifiedTime", ts);
865 /*
866 * if (locking) { OpenJPAQuery oq =
867 * OpenJPAPersistence.cast(q); FetchPlan fetch =
868 * oq.getFetchPlan();
869 * fetch.setReadLockMode(LockModeType.WRITE);
870 * fetch.setLockTimeout(-1); // no limit }
871 */
872 actions = q.getResultList();
873 return actions;
874 }
875 catch (IllegalStateException e) {
876 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
877 }
878 }
879 });
880 return actions;
881 }
882
883 public List<CoordinatorActionBean> getRecoveryActionsOlderThan(final long checkAgeSecs, final boolean locking)
884 throws StoreException {
885 List<CoordinatorActionBean> actions = doOperation("getRunningActionsOlderThan",
886 new Callable<List<CoordinatorActionBean>>() {
887 @SuppressWarnings("unchecked")
888 public List<CoordinatorActionBean> call() throws StoreException {
889 List<CoordinatorActionBean> actions;
890 try {
891 Query q = entityManager.createNamedQuery("GET_WAITING_SUBMITTED_ACTIONS_OLDER_THAN");
892 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
893 q.setParameter("lastModifiedTime", ts);
894 /*
895 * if (locking) { OpenJPAQuery oq =
896 * OpenJPAPersistence.cast(q); FetchPlan fetch =
897 * oq.getFetchPlan();
898 * fetch.setReadLockMode(LockModeType.WRITE);
899 * fetch.setLockTimeout(-1); // no limit }
900 */
901 actions = q.getResultList();
902 return actions;
903 }
904 catch (IllegalStateException e) {
905 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
906 }
907 }
908 });
909 return actions;
910 }
911
912 /**
913 * Get coordinator action beans for given start date and end date
914 *
915 * @param startDate
916 * @param endDate
917 * @return list of coordinator action beans
918 * @throws StoreException
919 */
920 public List<CoordinatorActionBean> getCoordActionsForDates(final String jobId, final Date startDate,
921 final Date endDate)
922 throws StoreException {
923 List<CoordinatorActionBean> actions = doOperation("getCoordActionsForDates",
924 new Callable<List<CoordinatorActionBean>>() {
925 @SuppressWarnings("unchecked")
926 public List<CoordinatorActionBean> call() throws StoreException {
927 List<CoordinatorActionBean> actions;
928 try {
929 Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_DATES");
930 q.setParameter("jobId", jobId);
931 q.setParameter("startTime", new Timestamp(startDate.getTime()));
932 q.setParameter("endTime", new Timestamp(endDate.getTime()));
933 actions = q.getResultList();
934
935 List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>();
936 for (CoordinatorActionBean a : actions) {
937 CoordinatorActionBean aa = getBeanForRunningCoordAction(a);
938 actionList.add(aa);
939 }
940 return actionList;
941 }
942 catch (IllegalStateException e) {
943 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
944 }
945 }
946 });
947 return actions;
948 }
949
950 /**
951 * Get coordinator action bean for given date
952 *
953 * @param nominalTime
954 * @return CoordinatorActionBean
955 * @throws StoreException
956 */
957 public CoordinatorActionBean getCoordActionForNominalTime(final String jobId, final Date nominalTime)
958 throws StoreException {
959 CoordinatorActionBean action = doOperation("getCoordActionForNominalTime",
960 new Callable<CoordinatorActionBean>() {
961 @SuppressWarnings("unchecked")
962 public CoordinatorActionBean call() throws StoreException {
963 List<CoordinatorActionBean> actions;
964 Query q = entityManager.createNamedQuery("GET_ACTION_FOR_NOMINALTIME");
965 q.setParameter("jobId", jobId);
966 q.setParameter("nominalTime", new Timestamp(nominalTime.getTime()));
967 actions = q.getResultList();
968
969 CoordinatorActionBean action = null;
970 if (actions.size() > 0) {
971 action = actions.get(0);
972 }
973 else {
974 throw new StoreException(ErrorCode.E0605, DateUtils.convertDateToString(nominalTime));
975 }
976 return getBeanForRunningCoordAction(action);
977 }
978 });
979 return action;
980 }
981
982 public List<String> getRecoveryActionsGroupByJobId(final long checkAgeSecs) throws StoreException {
983 List<String> jobids = doOperation("getRecoveryActionsGroupByJobId", new Callable<List<String>>() {
984 @SuppressWarnings("unchecked")
985 public List<String> call() throws StoreException {
986 List<String> jobids = new ArrayList<String>();
987 try {
988 Query q = entityManager.createNamedQuery("GET_READY_ACTIONS_GROUP_BY_JOBID");
989 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000);
990 q.setParameter(1, ts);
991 List<Object[]> list = q.getResultList();
992
993 for (Object[] arr : list) {
994 if (arr != null && arr[0] != null) {
995 jobids.add((String) arr[0]);
996 }
997 }
998
999 return jobids;
1000 }
1001 catch (IllegalStateException e) {
1002 throw new StoreException(ErrorCode.E0601, e.getMessage(), e);
1003 }
1004 }
1005 });
1006 return jobids;
1007 }
1008 }