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 }