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    }