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 492 /** 493 * Purge the coordinators completed older than given days. 494 * 495 * @param olderThanDays number of days for which to preserve the coordinators 496 * @param limit maximum number of coordinator jobs to be purged 497 * @throws StoreException 498 */ 499 public void purge(final long olderThanDays, final int limit) throws StoreException { 500 doOperation("coord-purge", new Callable<Void>() { 501 public Void call() throws SQLException, StoreException, WorkflowException { 502 Timestamp lastModTm = new Timestamp(System.currentTimeMillis() - (olderThanDays * DAY_IN_MS)); 503 Query jobQ = entityManager.createNamedQuery("GET_COMPLETED_COORD_JOBS_OLDER_THAN_STATUS"); 504 jobQ.setParameter("lastModTime", lastModTm); 505 jobQ.setMaxResults(limit); 506 List<CoordinatorJobBean> coordJobs = jobQ.getResultList(); 507 508 int actionDeleted = 0; 509 if (coordJobs.size() != 0) { 510 for (CoordinatorJobBean coord : coordJobs) { 511 String jobId = coord.getId(); 512 entityManager.remove(coord); 513 Query g = entityManager.createNamedQuery("DELETE_COMPLETED_ACTIONS_FOR_COORDINATOR"); 514 g.setParameter("jobId", jobId); 515 actionDeleted += g.executeUpdate(); 516 } 517 } 518 519 XLog.getLog(getClass()).debug("ENDED Coord Purge deleted jobs :" + coordJobs.size() + " and actions " + actionDeleted); 520 return null; 521 } 522 }); 523 } 524 525 public void commit() throws StoreException { 526 } 527 528 public void close() throws StoreException { 529 } 530 531 public CoordinatorJobBean getCoordinatorJobs(String id) { 532 // TODO Auto-generated method stub 533 return null; 534 } 535 536 public CoordinatorJobInfo getCoordinatorInfo(final Map<String, List<String>> filter, final int start, final int len) 537 throws StoreException { 538 539 CoordinatorJobInfo coordJobInfo = doOperation("getCoordinatorJobInfo", new Callable<CoordinatorJobInfo>() { 540 public CoordinatorJobInfo call() throws SQLException, StoreException { 541 List<String> orArray = new ArrayList<String>(); 542 List<String> colArray = new ArrayList<String>(); 543 List<String> valArray = new ArrayList<String>(); 544 StringBuilder sb = new StringBuilder(""); 545 546 StoreStatusFilter.filter(filter, orArray, colArray, valArray, sb, StoreStatusFilter.coordSeletStr, 547 StoreStatusFilter.coordCountStr); 548 549 int realLen = 0; 550 551 Query q = null; 552 Query qTotal = null; 553 if (orArray.size() == 0) { 554 q = entityManager.createNamedQuery("GET_COORD_JOBS_COLUMNS"); 555 q.setFirstResult(start - 1); 556 q.setMaxResults(len); 557 qTotal = entityManager.createNamedQuery("GET_COORD_JOBS_COUNT"); 558 } 559 else { 560 StringBuilder sbTotal = new StringBuilder(sb); 561 sb.append(" order by w.createdTimestamp desc "); 562 XLog.getLog(getClass()).debug("Created String is **** " + sb.toString()); 563 q = entityManager.createQuery(sb.toString()); 564 q.setFirstResult(start - 1); 565 q.setMaxResults(len); 566 qTotal = entityManager.createQuery(sbTotal.toString().replace(StoreStatusFilter.coordSeletStr, 567 StoreStatusFilter.coordCountStr)); 568 } 569 570 for (int i = 0; i < orArray.size(); i++) { 571 q.setParameter(colArray.get(i), valArray.get(i)); 572 qTotal.setParameter(colArray.get(i), valArray.get(i)); 573 } 574 575 OpenJPAQuery kq = OpenJPAPersistence.cast(q); 576 JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan(); 577 fetch.setFetchBatchSize(20); 578 fetch.setResultSetType(ResultSetType.SCROLL_INSENSITIVE); 579 fetch.setFetchDirection(FetchDirection.FORWARD); 580 fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.LAST); 581 List<?> resultList = q.getResultList(); 582 List<Object[]> objectArrList = (List<Object[]>) resultList; 583 List<CoordinatorJobBean> coordBeansList = new ArrayList<CoordinatorJobBean>(); 584 585 for (Object[] arr : objectArrList) { 586 CoordinatorJobBean ww = getBeanForCoordinatorJobFromArray(arr); 587 coordBeansList.add(ww); 588 } 589 590 realLen = ((Long) qTotal.getSingleResult()).intValue(); 591 592 return new CoordinatorJobInfo(coordBeansList, start, len, realLen); 593 } 594 }); 595 return coordJobInfo; 596 } 597 598 private CoordinatorJobBean getBeanForCoordinatorJobFromArray(Object[] arr) { 599 CoordinatorJobBean bean = new CoordinatorJobBean(); 600 bean.setId((String) arr[0]); 601 if (arr[1] != null) { 602 bean.setAppName((String) arr[1]); 603 } 604 if (arr[2] != null) { 605 bean.setStatus(Status.valueOf((String) arr[2])); 606 } 607 if (arr[3] != null) { 608 bean.setUser((String) arr[3]); 609 } 610 if (arr[4] != null) { 611 bean.setGroup((String) arr[4]); 612 } 613 if (arr[5] != null) { 614 bean.setStartTime((Timestamp) arr[5]); 615 } 616 if (arr[6] != null) { 617 bean.setEndTime((Timestamp) arr[6]); 618 } 619 if (arr[7] != null) { 620 bean.setAppPath((String) arr[7]); 621 } 622 if (arr[8] != null) { 623 bean.setConcurrency(((Integer) arr[8]).intValue()); 624 } 625 if (arr[9] != null) { 626 bean.setFrequency(((Integer) arr[9]).intValue()); 627 } 628 if (arr[10] != null) { 629 bean.setLastActionTime((Timestamp) arr[10]); 630 } 631 if (arr[11] != null) { 632 bean.setNextMaterializedTime((Timestamp) arr[11]); 633 } 634 if (arr[13] != null) { 635 bean.setTimeUnit(Timeunit.valueOf((String) arr[13])); 636 } 637 if (arr[14] != null) { 638 bean.setTimeZone((String) arr[14]); 639 } 640 if (arr[15] != null) { 641 bean.setTimeout((Integer) arr[15]); 642 } 643 return bean; 644 } 645 646 /** 647 * Loads all actions for the given Coordinator job. 648 * 649 * @param jobId coordinator job id 650 * @param locking true if Actions are to be locked 651 * @return A List of CoordinatorActionBean 652 * @throws StoreException 653 */ 654 public List<CoordinatorActionBean> getActionsForCoordinatorJob(final String jobId, final boolean locking) 655 throws StoreException { 656 ParamChecker.notEmpty(jobId, "CoordinatorJobID"); 657 List<CoordinatorActionBean> actions = doOperation("getActionsForCoordinatorJob", 658 new Callable<List<CoordinatorActionBean>>() { 659 @SuppressWarnings("unchecked") 660 public List<CoordinatorActionBean> call() throws StoreException { 661 List<CoordinatorActionBean> actions; 662 List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>(); 663 try { 664 Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_COORD_JOB"); 665 q.setParameter("jobId", jobId); 666 /* 667 * if (locking) { // 668 * q.setHint("openjpa.FetchPlan.ReadLockMode", // 669 * "READ"); OpenJPAQuery oq = 670 * OpenJPAPersistence.cast(q); JDBCFetchPlan fetch = 671 * (JDBCFetchPlan) oq.getFetchPlan(); 672 * fetch.setReadLockMode(LockModeType.WRITE); 673 * fetch.setLockTimeout(-1); // 1 second } 674 */ 675 actions = q.getResultList(); 676 for (CoordinatorActionBean a : actions) { 677 CoordinatorActionBean aa = getBeanForRunningCoordAction(a); 678 actionList.add(aa); 679 } 680 } 681 catch (IllegalStateException e) { 682 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 683 } 684 /* 685 * if (locking) { return actions; } else { 686 */ 687 return actionList; 688 // } 689 } 690 }); 691 return actions; 692 } 693 694 /** 695 * Loads given number of actions for the given Coordinator job. 696 * 697 * @param jobId coordinator job id 698 * @param start offset for select statement 699 * @param len number of Workflow Actions to be returned 700 * @return A List of CoordinatorActionBean 701 * @throws StoreException 702 */ 703 public List<CoordinatorActionBean> getActionsSubsetForCoordinatorJob(final String jobId, final int start, 704 final int len) throws StoreException { 705 ParamChecker.notEmpty(jobId, "CoordinatorJobID"); 706 List<CoordinatorActionBean> actions = doOperation("getActionsForCoordinatorJob", 707 new Callable<List<CoordinatorActionBean>>() { 708 @SuppressWarnings("unchecked") 709 public List<CoordinatorActionBean> call() throws StoreException { 710 List<CoordinatorActionBean> actions; 711 List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>(); 712 try { 713 Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_COORD_JOB"); 714 q.setParameter("jobId", jobId); 715 q.setFirstResult(start - 1); 716 q.setMaxResults(len); 717 actions = q.getResultList(); 718 for (CoordinatorActionBean a : actions) { 719 CoordinatorActionBean aa = getBeanForRunningCoordAction(a); 720 actionList.add(aa); 721 } 722 } 723 catch (IllegalStateException e) { 724 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 725 } 726 return actionList; 727 } 728 }); 729 return actions; 730 } 731 732 protected CoordinatorActionBean getBeanForRunningCoordAction(CoordinatorActionBean a) { 733 if (a != null) { 734 CoordinatorActionBean action = new CoordinatorActionBean(); 735 action.setId(a.getId()); 736 action.setActionNumber(a.getActionNumber()); 737 action.setActionXml(a.getActionXml()); 738 action.setConsoleUrl(a.getConsoleUrl()); 739 action.setCreatedConf(a.getCreatedConf()); 740 //action.setErrorCode(a.getErrorCode()); 741 //action.setErrorMessage(a.getErrorMessage()); 742 action.setExternalStatus(a.getExternalStatus()); 743 action.setMissingDependencies(a.getMissingDependencies()); 744 action.setRunConf(a.getRunConf()); 745 action.setTimeOut(a.getTimeOut()); 746 action.setTrackerUri(a.getTrackerUri()); 747 action.setType(a.getType()); 748 action.setCreatedTime(a.getCreatedTime()); 749 action.setExternalId(a.getExternalId()); 750 action.setJobId(a.getJobId()); 751 action.setLastModifiedTime(a.getLastModifiedTime()); 752 action.setNominalTime(a.getNominalTime()); 753 action.setSlaXml(a.getSlaXml()); 754 action.setStatus(a.getStatus()); 755 return action; 756 } 757 return null; 758 } 759 760 public CoordinatorActionBean getAction(String id, boolean b) { 761 return null; 762 } 763 764 /* 765 * do not need this public void updateCoordinatorActionForExternalId(final 766 * CoordinatorActionBean action) throws StoreException { // TODO 767 * Auto-generated method stub ParamChecker.notNull(action, 768 * "updateCoordinatorActionForExternalId"); 769 * doOperation("updateCoordinatorActionForExternalId", new Callable<Void>() 770 * { public Void call() throws SQLException, StoreException, 771 * WorkflowException { Query q = 772 * entityManager.createNamedQuery("UPDATE_COORD_ACTION_FOR_EXTERNALID"); 773 * setActionQueryParameters(action,q); q.executeUpdate(); return null; } }); 774 * } 775 */ 776 public CoordinatorActionBean getCoordinatorActionForExternalId(final String externalId) throws StoreException { 777 // TODO Auto-generated method stub 778 ParamChecker.notEmpty(externalId, "coodinatorActionExternalId"); 779 CoordinatorActionBean cBean = doOperation("getCoordinatorActionForExternalId", 780 new Callable<CoordinatorActionBean>() { 781 public CoordinatorActionBean call() throws StoreException { 782 CoordinatorActionBean caBean = null; 783 Query q = entityManager.createNamedQuery("GET_COORD_ACTION_FOR_EXTERNALID"); 784 q.setParameter("externalId", externalId); 785 List<CoordinatorActionBean> actionList = q.getResultList(); 786 if (actionList.size() > 0) { 787 caBean = actionList.get(0); 788 } 789 return caBean; 790 } 791 }); 792 return cBean; 793 } 794 795 public List<CoordinatorActionBean> getRunningActionsForCoordinatorJob(final String jobId, final boolean locking) 796 throws StoreException { 797 ParamChecker.notEmpty(jobId, "CoordinatorJobID"); 798 List<CoordinatorActionBean> actions = doOperation("getRunningActionsForCoordinatorJob", 799 new Callable<List<CoordinatorActionBean>>() { 800 @SuppressWarnings("unchecked") 801 public List<CoordinatorActionBean> call() throws StoreException { 802 List<CoordinatorActionBean> actions; 803 try { 804 Query q = entityManager.createNamedQuery("GET_RUNNING_ACTIONS_FOR_COORD_JOB"); 805 q.setParameter("jobId", jobId); 806 /* 807 * if (locking) { 808 * q.setHint("openjpa.FetchPlan.ReadLockMode", 809 * "READ"); OpenJPAQuery oq = 810 * OpenJPAPersistence.cast(q); FetchPlan fetch = 811 * oq.getFetchPlan(); 812 * fetch.setReadLockMode(LockModeType.WRITE); 813 * fetch.setLockTimeout(-1); // no limit } 814 */ 815 actions = q.getResultList(); 816 return actions; 817 } 818 catch (IllegalStateException e) { 819 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 820 } 821 } 822 }); 823 return actions; 824 } 825 826 public List<CoordinatorActionBean> getRunningActionsOlderThan(final long checkAgeSecs, final boolean locking) 827 throws StoreException { 828 List<CoordinatorActionBean> actions = doOperation("getRunningActionsOlderThan", 829 new Callable<List<CoordinatorActionBean>>() { 830 @SuppressWarnings("unchecked") 831 public List<CoordinatorActionBean> call() throws StoreException { 832 List<CoordinatorActionBean> actions; 833 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000); 834 try { 835 Query q = entityManager.createNamedQuery("GET_RUNNING_ACTIONS_OLDER_THAN"); 836 q.setParameter("lastModifiedTime", ts); 837 /* 838 * if (locking) { OpenJPAQuery oq = 839 * OpenJPAPersistence.cast(q); FetchPlan fetch = 840 * oq.getFetchPlan(); 841 * fetch.setReadLockMode(LockModeType.WRITE); 842 * fetch.setLockTimeout(-1); // no limit } 843 */ 844 actions = q.getResultList(); 845 return actions; 846 } 847 catch (IllegalStateException e) { 848 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 849 } 850 } 851 }); 852 return actions; 853 } 854 855 public List<CoordinatorActionBean> getRecoveryActionsOlderThan(final long checkAgeSecs, final boolean locking) 856 throws StoreException { 857 List<CoordinatorActionBean> actions = doOperation("getRunningActionsOlderThan", 858 new Callable<List<CoordinatorActionBean>>() { 859 @SuppressWarnings("unchecked") 860 public List<CoordinatorActionBean> call() throws StoreException { 861 List<CoordinatorActionBean> actions; 862 try { 863 Query q = entityManager.createNamedQuery("GET_WAITING_SUBMITTED_ACTIONS_OLDER_THAN"); 864 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000); 865 q.setParameter("lastModifiedTime", ts); 866 /* 867 * if (locking) { OpenJPAQuery oq = 868 * OpenJPAPersistence.cast(q); FetchPlan fetch = 869 * oq.getFetchPlan(); 870 * fetch.setReadLockMode(LockModeType.WRITE); 871 * fetch.setLockTimeout(-1); // no limit } 872 */ 873 actions = q.getResultList(); 874 return actions; 875 } 876 catch (IllegalStateException e) { 877 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 878 } 879 } 880 }); 881 return actions; 882 } 883 884 /** 885 * Get coordinator action beans for given start date and end date 886 * 887 * @param startDate 888 * @param endDate 889 * @return list of coordinator action beans 890 * @throws StoreException 891 */ 892 public List<CoordinatorActionBean> getCoordActionsForDates(final String jobId, final Date startDate, 893 final Date endDate) 894 throws StoreException { 895 List<CoordinatorActionBean> actions = doOperation("getCoordActionsForDates", 896 new Callable<List<CoordinatorActionBean>>() { 897 @SuppressWarnings("unchecked") 898 public List<CoordinatorActionBean> call() throws StoreException { 899 List<CoordinatorActionBean> actions; 900 try { 901 Query q = entityManager.createNamedQuery("GET_ACTIONS_FOR_DATES"); 902 q.setParameter("jobId", jobId); 903 q.setParameter("startTime", new Timestamp(startDate.getTime())); 904 q.setParameter("endTime", new Timestamp(endDate.getTime())); 905 actions = q.getResultList(); 906 907 List<CoordinatorActionBean> actionList = new ArrayList<CoordinatorActionBean>(); 908 for (CoordinatorActionBean a : actions) { 909 CoordinatorActionBean aa = getBeanForRunningCoordAction(a); 910 actionList.add(aa); 911 } 912 return actionList; 913 } 914 catch (IllegalStateException e) { 915 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 916 } 917 } 918 }); 919 return actions; 920 } 921 922 /** 923 * Get coordinator action bean for given date 924 * 925 * @param nominalTime 926 * @return CoordinatorActionBean 927 * @throws StoreException 928 */ 929 public CoordinatorActionBean getCoordActionForNominalTime(final String jobId, final Date nominalTime) 930 throws StoreException { 931 CoordinatorActionBean action = doOperation("getCoordActionForNominalTime", 932 new Callable<CoordinatorActionBean>() { 933 @SuppressWarnings("unchecked") 934 public CoordinatorActionBean call() throws StoreException { 935 List<CoordinatorActionBean> actions; 936 Query q = entityManager.createNamedQuery("GET_ACTION_FOR_NOMINALTIME"); 937 q.setParameter("jobId", jobId); 938 q.setParameter("nominalTime", new Timestamp(nominalTime.getTime())); 939 actions = q.getResultList(); 940 941 CoordinatorActionBean action = null; 942 if (actions.size() > 0) { 943 action = actions.get(0); 944 } 945 else { 946 throw new StoreException(ErrorCode.E0605, DateUtils.convertDateToString(nominalTime)); 947 } 948 return getBeanForRunningCoordAction(action); 949 } 950 }); 951 return action; 952 } 953 954 public List<String> getRecoveryActionsGroupByJobId(final long checkAgeSecs) throws StoreException { 955 List<String> jobids = doOperation("getRecoveryActionsGroupByJobId", new Callable<List<String>>() { 956 @SuppressWarnings("unchecked") 957 public List<String> call() throws StoreException { 958 List<String> jobids = new ArrayList<String>(); 959 try { 960 Query q = entityManager.createNamedQuery("GET_READY_ACTIONS_GROUP_BY_JOBID"); 961 Timestamp ts = new Timestamp(System.currentTimeMillis() - checkAgeSecs * 1000); 962 q.setParameter(1, ts); 963 List<Object[]> list = q.getResultList(); 964 965 for (Object[] arr : list) { 966 if (arr != null && arr[0] != null) { 967 jobids.add((String) arr[0]); 968 } 969 } 970 971 return jobids; 972 } 973 catch (IllegalStateException e) { 974 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 975 } 976 } 977 }); 978 return jobids; 979 } 980 981 public List<CoordinatorActionBean> getActionsOlderThan(final String jobId, final Date olderThan, final boolean locking) 982 throws StoreException { 983 List<CoordinatorActionBean> actions = doOperation("getActionsOlderThan", 984 new Callable<List<CoordinatorActionBean>>() { 985 @SuppressWarnings("unchecked") 986 public List<CoordinatorActionBean> call() throws StoreException { 987 List<CoordinatorActionBean> actions; 988 Timestamp ts = new Timestamp(olderThan.getTime()); 989 try { 990 Query q = entityManager.createNamedQuery("GET_COORD_ACTIONS_FOR_JOB_OLDER_THAN"); 991 q.setParameter("jobId", jobId); 992 q.setParameter("lastModifiedTime", ts); 993 actions = q.getResultList(); 994 return actions; 995 } 996 catch (IllegalStateException e) { 997 throw new StoreException(ErrorCode.E0601, e.getMessage(), e); 998 } 999 } 1000 }); 1001 return actions; 1002 } 1003 1004 public void deleteAction(final CoordinatorActionBean action) throws StoreException { 1005 doOperation("deleteAction", 1006 new Callable<Void>() { 1007 @SuppressWarnings("unchecked") 1008 public Void call() throws StoreException { 1009 entityManager.remove(action); 1010 return null; 1011 } 1012 }); 1013 } 1014 1015 }