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;
016    
017    import java.io.DataInput;
018    import java.io.DataOutput;
019    import java.io.IOException;
020    import java.sql.Timestamp;
021    import java.util.Date;
022    
023    import javax.persistence.Basic;
024    import javax.persistence.Column;
025    import javax.persistence.ColumnResult;
026    import javax.persistence.Entity;
027    import javax.persistence.Lob;
028    import javax.persistence.NamedNativeQueries;
029    import javax.persistence.NamedNativeQuery;
030    import javax.persistence.NamedQueries;
031    import javax.persistence.NamedQuery;
032    import javax.persistence.SqlResultSetMapping;
033    
034    import org.apache.hadoop.io.Writable;
035    import org.apache.oozie.client.CoordinatorAction;
036    import org.apache.oozie.client.rest.JsonCoordinatorAction;
037    import org.apache.oozie.util.DateUtils;
038    import org.apache.oozie.util.WritableUtils;
039    import org.apache.openjpa.persistence.jdbc.Index;
040    
041    @SqlResultSetMapping(
042            name = "CoordActionJobIdLmt",
043            columns = {@ColumnResult(name = "job_id"),
044                @ColumnResult(name = "min_lmt")})
045    
046    @Entity
047    @NamedQueries({
048    
049        @NamedQuery(name = "UPDATE_COORD_ACTION", query = "update CoordinatorActionBean w set w.actionNumber = :actionNumber, w.actionXml = :actionXml, w.consoleUrl = :consoleUrl, w.createdConf = :createdConf, w.errorCode = :errorCode, w.errorMessage = :errorMessage, w.externalStatus = :externalStatus, w.missingDependencies = :missingDependencies, w.runConf = :runConf, w.timeOut = :timeOut, w.trackerUri = :trackerUri, w.type = :type, w.createdTimestamp = :createdTime, w.externalId = :externalId, w.jobId = :jobId, w.lastModifiedTimestamp = :lastModifiedTime, w.nominalTimestamp = :nominalTime, w.slaXml = :slaXml, w.status = :status where w.id = :id"),
050    
051        @NamedQuery(name = "UPDATE_COORD_ACTION_MIN", query = "update CoordinatorActionBean w set w.actionXml = :actionXml, w.missingDependencies = :missingDependencies, w.lastModifiedTimestamp = :lastModifiedTime, w.status = :status where w.id = :id"),
052    
053        @NamedQuery(name = "DELETE_COMPLETED_ACTIONS_FOR_COORDINATOR", query = "delete from CoordinatorActionBean a where a.jobId = :jobId and (a.status = 'SUCCEEDED' OR a.status = 'FAILED' OR a.status= 'KILLED')"),
054    
055        @NamedQuery(name = "GET_COORD_ACTIONS", query = "select OBJECT(w) from CoordinatorActionBean w"),
056    
057        @NamedQuery(name = "GET_COMPLETED_ACTIONS_OLDER_THAN", query = "select OBJECT(a) from CoordinatorActionBean a where a.createdTimestamp < :createdTime and (a.status = 'SUCCEEDED' OR a.status = 'FAILED' OR a.status = 'KILLED')"),
058    
059        @NamedQuery(name = "GET_COORD_ACTION", query = "select OBJECT(a) from CoordinatorActionBean a where a.id = :id"),
060    
061        @NamedQuery(name = "GET_COORD_ACTION_FOR_EXTERNALID", query = "select OBJECT(a) from CoordinatorActionBean a where a.externalId = :externalId"),
062    
063        @NamedQuery(name = "GET_COORD_ACTIONS_FOR_JOB_FIFO", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.status = 'READY' order by a.nominalTimestamp"),
064    
065        @NamedQuery(name = "GET_COORD_ACTIONS_FOR_JOB_LIFO", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.status = 'READY' order by a.nominalTimestamp desc"),
066    
067        @NamedQuery(name = "GET_COORD_RUNNING_ACTIONS_COUNT", query = "select count(a) from CoordinatorActionBean a where a.jobId = :jobId AND (a.status = 'RUNNING' OR a.status='SUBMITTED')"),
068    
069        @NamedQuery(name = "GET_COORD_ACTIONS_COUNT_BY_JOBID", query = "select count(a) from CoordinatorActionBean a where a.jobId = :jobId"),
070    
071        @NamedQuery(name = "GET_COORD_ACTIVE_ACTIONS_COUNT_BY_JOBID", query = "select count(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.status = 'WAITING'"),
072    
073        @NamedQuery(name = "GET_COORD_ACTIONS_PENDING_FALSE_COUNT", query = "select count(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.pending = 0 AND (a.status = 'SUSPENDED' OR a.status = 'TIMEDOUT' OR a.status = 'SUCCEEDED' OR a.status = 'KILLED' OR a.status = 'FAILED')"),
074    
075        @NamedQuery(name = "GET_COORD_ACTIONS_PENDING_FALSE_STATUS_COUNT", query = "select count(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.pending = 0 AND a.status = :status"),
076    
077        @NamedQuery(name = "GET_ACTIONS_FOR_COORD_JOB", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId"),
078    
079        @NamedQuery(name = "GET_COORD_ACTION_FOR_COORD_JOB_BY_ACTION_NUMBER", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.actionNumber = :actionNumber"),
080    
081        @NamedQuery(name = "GET_COORD_ACTIONS_BY_LAST_MODIFIED_TIME", query = "select OBJECT(w) from CoordinatorActionBean w where w.lastModifiedTimestamp >= :lastModifiedTime"),
082    
083        @NamedQuery(name = "GET_RUNNING_ACTIONS_FOR_COORD_JOB", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.status = 'RUNNING'"),
084    
085        @NamedQuery(name = "GET_RUNNING_ACTIONS_OLDER_THAN", query = "select OBJECT(a) from CoordinatorActionBean a where a.status = 'RUNNING' AND a.lastModifiedTimestamp <= :lastModifiedTime"),
086    
087        @NamedQuery(name = "GET_COORD_ACTIONS_WAITING_SUBMITTED_OLDER_THAN", query = "select OBJECT(a) from CoordinatorActionBean a where (a.status = 'WAITING' OR a.status = 'SUBMITTED') AND a.lastModifiedTimestamp <= :lastModifiedTime"),
088    
089        @NamedQuery(name = "GET_COORD_ACTIONS_FOR_RECOVERY_OLDER_THAN", query = "select OBJECT(a) from CoordinatorActionBean a where a.pending > 0 AND (a.status = 'SUSPENDED' OR a.status = 'KILLED' OR a.status = 'RUNNING') AND a.lastModifiedTimestamp <= :lastModifiedTime"),
090    
091        @NamedQuery(name = "GET_ACTIONS_FOR_DATES", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId AND (a.status = 'TIMEDOUT' OR a.status = 'SUCCEEDED' OR a.status = 'KILLED' OR a.status = 'FAILED') AND a.nominalTimestamp >= :startTime AND a.nominalTimestamp <= :endTime"),
092    
093        @NamedQuery(name = "GET_ACTION_FOR_NOMINALTIME", query = "select OBJECT(a) from CoordinatorActionBean a where a.jobId = :jobId AND a.nominalTimestamp = :nominalTime"),
094    
095        @NamedQuery(name = "GET_COORD_ACTIONS_COUNT", query = "select count(w) from CoordinatorActionBean w")})
096    
097    @NamedNativeQueries({
098    
099        @NamedNativeQuery(name = "GET_READY_ACTIONS_GROUP_BY_JOBID", query = "select a.job_id as job_id, MIN(a.last_modified_time) as min_lmt from COORD_ACTIONS a where a.status = 'READY' GROUP BY a.job_id HAVING MIN(a.last_modified_time) < ?", resultSetMapping = "CoordActionJobIdLmt")
100            })
101    public class CoordinatorActionBean extends JsonCoordinatorAction implements
102            Writable {
103        @Basic
104        @Index
105        @Column(name = "job_id")
106        private String jobId;
107    
108        @Basic
109        @Index
110        @Column(name = "status")
111        private String status = null;
112    
113        @Basic
114        @Column(name = "nominal_time")
115        private java.sql.Timestamp nominalTimestamp = null;
116    
117        @Basic
118        @Index
119        @Column(name = "last_modified_time")
120        private java.sql.Timestamp lastModifiedTimestamp = null;
121    
122        @Basic
123        @Index
124        @Column(name = "created_time")
125        private java.sql.Timestamp createdTimestamp = null;
126    
127        @Basic
128        @Index
129        @Column(name = "rerun_time")
130        private java.sql.Timestamp rerunTimestamp = null;
131    
132        @Basic
133        @Index
134        @Column(name = "external_id")
135        private String externalId;
136    
137        @Column(name = "sla_xml")
138        @Lob
139        private String slaXml = null;
140    
141        @Basic
142        @Column(name = "pending")
143        private int pending = 0;
144    
145        public CoordinatorActionBean() {
146        }
147    
148        /**
149         * Serialize the coordinator bean to a data output.
150         *
151         * @param dataOutput data output.
152         * @throws IOException thrown if the coordinator bean could not be serialized.
153         */
154        public void write(DataOutput dataOutput) throws IOException {
155            WritableUtils.writeStr(dataOutput, getJobId());
156            WritableUtils.writeStr(dataOutput, getType());
157            WritableUtils.writeStr(dataOutput, getId());
158            WritableUtils.writeStr(dataOutput, getCreatedConf());
159            WritableUtils.writeStr(dataOutput, getStatus().toString());
160            dataOutput.writeInt(getActionNumber());
161            WritableUtils.writeStr(dataOutput, getRunConf());
162            WritableUtils.writeStr(dataOutput, getExternalStatus());
163            WritableUtils.writeStr(dataOutput, getTrackerUri());
164            WritableUtils.writeStr(dataOutput, getConsoleUrl());
165            WritableUtils.writeStr(dataOutput, getErrorCode());
166            WritableUtils.writeStr(dataOutput, getErrorMessage());
167            dataOutput.writeLong((getCreatedTime() != null) ? getCreatedTime().getTime() : -1);
168            dataOutput.writeLong((getLastModifiedTime() != null) ? getLastModifiedTime().getTime() : -1);
169        }
170    
171        /**
172         * Deserialize a coordinator bean from a data input.
173         *
174         * @param dataInput data input.
175         * @throws IOException thrown if the workflow bean could not be deserialized.
176         */
177        public void readFields(DataInput dataInput) throws IOException {
178            setJobId(WritableUtils.readStr(dataInput));
179            setType(WritableUtils.readStr(dataInput));
180            setId(WritableUtils.readStr(dataInput));
181            setCreatedConf(WritableUtils.readStr(dataInput));
182            setStatus(CoordinatorAction.Status.valueOf(WritableUtils.readStr(dataInput)));
183            setActionNumber(dataInput.readInt());
184            setRunConf(WritableUtils.readStr(dataInput));
185            setExternalStatus(WritableUtils.readStr(dataInput));
186            setTrackerUri(WritableUtils.readStr(dataInput));
187            setConsoleUrl(WritableUtils.readStr(dataInput));
188            setErrorCode(WritableUtils.readStr(dataInput));
189            setErrorMessage(WritableUtils.readStr(dataInput));
190            long d = dataInput.readLong();
191            if (d != -1) {
192                setCreatedTime(new Date(d));
193            }
194            d = dataInput.readLong();
195            if (d != -1) {
196                setLastModifiedTime(new Date(d));
197            }
198        }
199    
200        @Override
201        public String getJobId() {
202            return this.jobId;
203        }
204    
205        @Override
206        public void setJobId(String id) {
207            super.setJobId(id);
208            this.jobId = id;
209        }
210    
211        @Override
212        public Status getStatus() {
213            return Status.valueOf(status);
214        }
215    
216        @Override
217        public void setStatus(Status status) {
218            super.setStatus(status);
219            this.status = status.toString();
220        }
221    
222        @Override
223        public void setCreatedTime(Date createdTime) {
224            this.createdTimestamp = DateUtils.convertDateToTimestamp(createdTime);
225            super.setCreatedTime(createdTime);
226        }
227    
228        public void setRerunTime(Date rerunTime) {
229            this.rerunTimestamp = DateUtils.convertDateToTimestamp(rerunTime);
230        }
231    
232        @Override
233        public void setNominalTime(Date nominalTime) {
234            this.nominalTimestamp = DateUtils.convertDateToTimestamp(nominalTime);
235            super.setNominalTime(nominalTime);
236        }
237    
238        @Override
239        public void setLastModifiedTime(Date lastModifiedTime) {
240            this.lastModifiedTimestamp = DateUtils.convertDateToTimestamp(lastModifiedTime);
241            super.setLastModifiedTime(lastModifiedTime);
242        }
243    
244        @Override
245        public Date getCreatedTime() {
246            return DateUtils.toDate(createdTimestamp);
247        }
248    
249        public Timestamp getCreatedTimestamp() {
250            return createdTimestamp;
251        }
252    
253        public Date getRerunTime() {
254            return DateUtils.toDate(rerunTimestamp);
255        }
256    
257        public Timestamp getRerunTimestamp() {
258            return rerunTimestamp;
259        }
260    
261        @Override
262        public Date getLastModifiedTime() {
263            return DateUtils.toDate(lastModifiedTimestamp);
264        }
265    
266        public Timestamp getLastModifiedTimestamp() {
267            return lastModifiedTimestamp;
268        }
269    
270        @Override
271        public Date getNominalTime() {
272            return DateUtils.toDate(nominalTimestamp);
273        }
274    
275        public Timestamp getNominalTimestamp() {
276            return nominalTimestamp;
277        }
278    
279        @Override
280        public String getExternalId() {
281            return externalId;
282        }
283    
284        @Override
285        public void setExternalId(String externalId) {
286            super.setExternalId(externalId);
287            this.externalId = externalId;
288        }
289    
290        public String getSlaXml() {
291            return slaXml;
292        }
293    
294        public void setSlaXml(String slaXml) {
295            this.slaXml = slaXml;
296        }
297    
298        /**
299         * @return true if in terminal status
300         */
301        public boolean isTerminalStatus() {
302            boolean isTerminal = true;
303            switch (getStatus()) {
304                case WAITING:
305                case READY:
306                case SUBMITTED:
307                case RUNNING:
308                case SUSPENDED:
309                    isTerminal = false;
310                    break;
311                default:
312                    isTerminal = true;
313                    break;
314            }
315            return isTerminal;
316        }
317    
318        /**
319         * Set some actions are in progress for particular coordinator action.
320         *
321         * @param pending set pending to true
322         */
323        public void setPending(int pending) {
324            this.pending = pending;
325        }
326    
327        /**
328         * increment pending and return it
329         *
330         * @return pending
331         */
332        public int incrementAndGetPending() {
333            this.pending++;
334            return pending;
335        }
336    
337        /**
338         * decrement pending and return it
339         *
340         * @return pending
341         */
342        public int decrementAndGetPending() {
343            this.pending = Math.max(this.pending-1, 0);
344            return pending;
345        }
346    
347        /**
348         * Get some actions are in progress for particular bundle action.
349         *
350         * @return pending
351         */
352        public int getPending() {
353            return this.pending;
354        }
355    
356        /**
357         * Return if the action is pending.
358         *
359         * @return if the action is pending.
360         */
361        public boolean isPending() {
362            return pending > 0 ? true : false;
363        }
364    }