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 }