001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie; 020 021import java.io.DataInput; 022import java.io.DataOutput; 023import java.io.IOException; 024import java.sql.Timestamp; 025import java.text.MessageFormat; 026import java.util.Date; 027import java.util.List; 028import java.util.Properties; 029 030import javax.persistence.Basic; 031import javax.persistence.Column; 032import javax.persistence.Entity; 033import javax.persistence.Id; 034import javax.persistence.Lob; 035import javax.persistence.NamedQueries; 036import javax.persistence.NamedQuery; 037import javax.persistence.Table; 038 039import org.apache.hadoop.io.Writable; 040import org.apache.oozie.client.WorkflowAction; 041import org.apache.oozie.client.rest.JsonBean; 042import org.apache.oozie.client.rest.JsonTags; 043import org.apache.oozie.client.rest.JsonUtils; 044import org.apache.oozie.util.DateUtils; 045import org.apache.oozie.util.ParamChecker; 046import org.apache.oozie.util.PropertiesUtils; 047import org.apache.oozie.util.WritableUtils; 048import org.apache.openjpa.persistence.jdbc.Index; 049import org.apache.openjpa.persistence.jdbc.Strategy; 050 051import org.json.simple.JSONArray; 052import org.json.simple.JSONObject; 053 054/** 055 * Bean that contains all the information to start an action for a workflow 056 * node. 057 */ 058@Entity 059@NamedQueries({ 060 061 @NamedQuery(name = "UPDATE_ACTION", query = "update WorkflowActionBean a set a.conf = :conf, a.consoleUrl = :consoleUrl," 062 + " a.data = :data, a.stats = :stats, a.externalChildIDs = :externalChildIDs, a.errorCode = :errorCode," 063 + " a.errorMessage = :errorMessage, a.externalId = :externalId, a.externalStatus = :externalStatus, a.name = :name," 064 + " a.cred = :cred , a.retries = :retries, a.trackerUri = :trackerUri, a.transition = :transition, a.type = :type," 065 + " a.endTimestamp = :endTime, a.executionPath = :executionPath, a.lastCheckTimestamp = :lastCheckTime, a.logToken " 066 + "= :logToken, a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.signalValue = :signalValue, a.slaXml " 067 + "= :slaXml, a.startTimestamp = :startTime, a.statusStr = :status, a.wfId=:wfId where a.id = :id"), 068 069 @NamedQuery(name = "UPDATE_ACTION_FOR_LAST_CHECKED_TIME", query = "update WorkflowActionBean a set a.lastCheckTimestamp " 070 + "= :lastCheckTime where a.id = :id"), 071 072 @NamedQuery(name = "UPDATE_ACTION_START", query = "update WorkflowActionBean a set a.startTimestamp = :startTime," 073 + " a.externalChildIDs = :externalChildIDs, a.conf = :conf, a.errorCode = :errorCode, a.errorMessage = :errorMessage," 074 + " a.startTimestamp = :startTime, a.externalId = :externalId, a.trackerUri = :trackerUri, a.consoleUrl " 075 + "= :consoleUrl, a.lastCheckTimestamp = :lastCheckTime, a.statusStr = :status, a.externalStatus = :externalStatus," 076 + " a.data = :data, a.retries = :retries, a.pending = :pending, a.pendingAgeTimestamp = :pendingAge, a.userRetryCount" 077 + " = :userRetryCount where a.id = :id"), 078 079 @NamedQuery(name = "UPDATE_ACTION_CHECK", query = "update WorkflowActionBean a set a.userRetryCount = :userRetryCount," 080 + " a.stats = :stats, a.externalChildIDs = :externalChildIDs, a.externalStatus = :externalStatus, a.statusStr " 081 + "= :status, a.data = :data, a.pending = :pending, a.errorCode = :errorCode, a.errorMessage = :errorMessage," 082 + " a.lastCheckTimestamp = :lastCheckTime, a.retries = :retries, a.pendingAgeTimestamp = :pendingAge," 083 + " a.startTimestamp = :startTime where a.id = :id"), 084 085 @NamedQuery(name = "UPDATE_ACTION_END", query = "update WorkflowActionBean a set a.stats = :stats, a.errorCode = :errorCode," 086 + " a.errorMessage = :errorMessage, a.retries = :retries, a.endTimestamp = :endTime, a.statusStr = :status, a.pending" 087 + " = :pending, a.pendingAgeTimestamp = :pendingAge, a.signalValue = :signalValue, a.userRetryCount " 088 + "= :userRetryCount, a.externalStatus = :externalStatus where a.id = :id"), 089 090 @NamedQuery(name = "UPDATE_ACTION_PENDING", query = "update WorkflowActionBean a set a.pending = :pending," 091 + " a.pendingAgeTimestamp = :pendingAge, a.executionPath = :executionPath where a.id = :id"), 092 093 @NamedQuery(name = "UPDATE_ACTION_STATUS_PENDING", query = "update WorkflowActionBean a set a.statusStr = :status, a.pending" 094 + " = :pending, a.pendingAgeTimestamp = :pendingAge where a.id = :id"), 095 096 @NamedQuery(name = "UPDATE_ACTION_PENDING_TRANS", query = "update WorkflowActionBean a set a.pending = :pending," 097 + " a.pendingAgeTimestamp = :pendingAge, a.transition = :transition where a.id = :id"), 098 099 @NamedQuery(name = "UPDATE_ACTION_PENDING_TRANS_ERROR", query = "update WorkflowActionBean a set a.pending = :pending," 100 + " a.pendingAgeTimestamp = :pendingAge, a.transition = :transition, a.errorCode = :errorCode, a.errorMessage " 101 + "= :errorMessage, a.statusStr = :status where a.id = :id"), 102 103 @NamedQuery(name = "DELETE_ACTION", query = "delete from WorkflowActionBean a where a.id IN (:id)"), 104 105 @NamedQuery(name = "DELETE_ACTIONS_FOR_WORKFLOW", query = "delete from WorkflowActionBean a where a.wfId IN (:wfId)"), 106 107 @NamedQuery(name = "GET_ACTIONS", query = "select OBJECT(a) from WorkflowActionBean a"), 108 109 @NamedQuery(name = "GET_ACTION", query = "select OBJECT(a) from WorkflowActionBean a where a.id = :id"), 110 111 @NamedQuery(name = "GET_ACTION_ID_TYPE_LASTCHECK", query = "select a.id, a.type, a.lastCheckTimestamp " 112 + "from WorkflowActionBean a where a.id = :id"), 113 114 @NamedQuery(name = "GET_ACTION_FAIL", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.type, a.logToken," 115 + " a.transition, a.errorCode, a.errorMessage from WorkflowActionBean a where a.id = :id"), 116 117 @NamedQuery(name = "GET_ACTION_SIGNAL", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.pendingAgeTimestamp," 118 + " a.type, a.logToken, a.transition, a.errorCode, a.errorMessage, a.executionPath, a.signalValue, a.slaXml," 119 + " a.externalId from WorkflowActionBean a where a.id = :id"), 120 121 @NamedQuery(name = "GET_ACTION_CHECK", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.pendingAgeTimestamp," 122 + " a.type, a.logToken, a.transition, a.retries, a.userRetryCount, a.userRetryMax, a.userRetryInterval, a.trackerUri," 123 + " a.startTimestamp, a.endTimestamp, a.lastCheckTimestamp, a.errorCode, a.errorMessage, a.externalId," 124 + " a.externalStatus, a.externalChildIDs, a.conf from WorkflowActionBean a where a.id = :id"), 125 126 @NamedQuery(name = "GET_ACTION_END", query = "select a.id, a.wfId, a.name, a.statusStr, a.pending, a.pendingAgeTimestamp," 127 + " a.type, a.logToken, a.transition, a.retries, a.trackerUri, a.userRetryCount, a.userRetryMax, a.userRetryInterval," 128 + " a.startTimestamp, a.endTimestamp, a.errorCode, a.errorMessage, a.externalId, a.externalStatus," 129 + " a.externalChildIDs, a.conf, a.data, a.stats from WorkflowActionBean a where a.id = :id"), 130 131 @NamedQuery(name = "GET_ACTION_COMPLETED", query = "select a.id, a.wfId, a.statusStr, a.type, a.logToken " 132 + "from WorkflowActionBean a where a.id = :id"), 133 134 @NamedQuery(name = "GET_ACTION_FOR_UPDATE", query = "select OBJECT(a) from WorkflowActionBean a where a.id = :id"), 135 136 @NamedQuery(name = "GET_ACTION_FOR_SLA", query = "select a.id, a.statusStr, a.startTimestamp, a.endTimestamp " 137 + "from WorkflowActionBean a where a.id = :id"), 138 139 @NamedQuery(name = "GET_ACTIONS_FOR_WORKFLOW", query = "select OBJECT(a) from WorkflowActionBean a where a.wfId = :wfId " 140 + "order by a.startTimestamp"), 141 142 @NamedQuery(name = "GET_ACTIONS_OF_WORKFLOW_FOR_UPDATE", query = "select OBJECT(a) from WorkflowActionBean a where a.wfId " 143 + "= :wfId order by a.startTimestamp"), 144 145 @NamedQuery(name = "GET_PENDING_ACTIONS", query = "select a.id, a.wfId, a.statusStr, a.type, a.pendingAgeTimestamp from" 146 + " WorkflowActionBean a where a.pending = 1 AND a.pendingAgeTimestamp < :pendingAge AND a.statusStr <> 'RUNNING' " 147 + "AND a.createdTimeTS >= :createdTime"), 148 149 @NamedQuery(name = "GET_RUNNING_ACTIONS", query = "select a.id from WorkflowActionBean a where a.pending = 1 AND a.statusStr" 150 + " = 'RUNNING' AND a.lastCheckTimestamp < :lastCheckTime"), 151 152 @NamedQuery(name = "GET_RETRY_MANUAL_ACTIONS", query = "select OBJECT(a) from WorkflowActionBean a where a.wfId = :wfId " 153 + "AND (a.statusStr = 'START_RETRY' OR a.statusStr = 'START_MANUAL' OR a.statusStr = 'END_RETRY' OR a.statusStr " 154 + "= 'END_MANUAL')"), 155 156 @NamedQuery(name = "GET_ACTIONS_FOR_WORKFLOW_RERUN", query = "select a.id, a.name, a.statusStr, a.endTimestamp, a.type " 157 + "from WorkflowActionBean a where a.wfId = :wfId order by a.startTimestamp") }) 158@Table(name = "WF_ACTIONS") 159public class WorkflowActionBean implements Writable, WorkflowAction, JsonBean { 160 @Id 161 private String id; 162 163 @Basic 164 @Index 165 @Column(name = "wf_id") 166 private String wfId = null; 167 168 @Basic 169 @Column(name = "created_time") 170 private Timestamp createdTimeTS = null; 171 172 @Basic 173 @Index 174 @Column(name = "status") 175 private String statusStr = WorkflowAction.Status.PREP.toString(); 176 177 @Basic 178 @Column(name = "last_check_time") 179 private Timestamp lastCheckTimestamp; 180 181 @Basic 182 @Column(name = "end_time") 183 private Timestamp endTimestamp = null; 184 185 @Basic 186 @Column(name = "start_time") 187 private Timestamp startTimestamp = null; 188 189 @Basic 190 @Column(name = "execution_path", length = 1024) 191 private String executionPath = null; 192 193 @Basic 194 @Column(name = "pending") 195 private int pending = 0; 196 197 @Basic 198 @Index 199 @Column(name = "pending_age") 200 private Timestamp pendingAgeTimestamp = null; 201 202 @Basic 203 @Column(name = "signal_value") 204 private String signalValue = null; 205 206 @Basic 207 @Column(name = "log_token") 208 private String logToken = null; 209 210 @Basic 211 @Column(name = "sla_xml") 212 @Lob 213 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 214 private StringBlob slaXml; 215 216 @Basic 217 @Column(name = "name") 218 private String name = null; 219 220 @Basic 221 @Column(name = "cred") 222 private String cred = null; 223 224 @Basic 225 @Column(name = "type") 226 private String type = null; 227 228 @Basic 229 @Column(name = "conf") 230 @Lob 231 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 232 private StringBlob conf; 233 234 @Basic 235 @Column(name = "retries") 236 private int retries; 237 238 @Basic 239 @Column(name = "user_retry_count") 240 private int userRetryCount; 241 242 @Basic 243 @Column(name = "user_retry_max") 244 private int userRetryMax; 245 246 @Basic 247 @Column(name = "user_retry_interval") 248 private int userRetryInterval; 249 250 @Basic 251 @Column(name = "transition") 252 private String transition = null; 253 254 @Basic 255 @Column(name = "data") 256 @Lob 257 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 258 private StringBlob data; 259 260 @Basic 261 @Column(name = "stats") 262 @Lob 263 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 264 private StringBlob stats; 265 266 @Basic 267 @Column(name = "external_child_ids") 268 @Lob 269 @Strategy("org.apache.oozie.executor.jpa.StringBlobValueHandler") 270 private StringBlob externalChildIDs; 271 272 @Basic 273 @Column(name = "external_id") 274 private String externalId = null; 275 276 @Basic 277 @Column(name = "external_status") 278 private String externalStatus = null; 279 280 @Basic 281 @Column(name = "tracker_uri") 282 private String trackerUri = null; 283 284 @Basic 285 @Column(name = "console_url") 286 private String consoleUrl = null; 287 288 @Basic 289 @Column(name = "error_code") 290 private String errorCode = null; 291 292 @Column(name = "error_message", length = 500) 293 private String errorMessage = null; 294 295 /** 296 * Default constructor. 297 */ 298 public WorkflowActionBean() { 299 } 300 301 /** 302 * Serialize the action bean to a data output. 303 * 304 * @param dataOutput data output. 305 * @throws IOException thrown if the action bean could not be serialized. 306 */ 307 308 public void write(DataOutput dataOutput) throws IOException { 309 WritableUtils.writeStr(dataOutput, getId()); 310 WritableUtils.writeStr(dataOutput, getName()); 311 WritableUtils.writeStr(dataOutput, getCred()); 312 WritableUtils.writeStr(dataOutput, getType()); 313 WritableUtils.writeStr(dataOutput, getConf()); 314 WritableUtils.writeStr(dataOutput, getStatusStr()); 315 dataOutput.writeInt(getRetries()); 316 dataOutput.writeLong((getStartTime() != null) ? getStartTime().getTime() : -1); 317 dataOutput.writeLong((getEndTime() != null) ? getEndTime().getTime() : -1); 318 dataOutput.writeLong((getLastCheckTime() != null) ? getLastCheckTime().getTime() : -1); 319 WritableUtils.writeStr(dataOutput, getTransition()); 320 WritableUtils.writeStr(dataOutput, getData()); 321 WritableUtils.writeStr(dataOutput, getStats()); 322 WritableUtils.writeStr(dataOutput, getExternalChildIDs()); 323 WritableUtils.writeStr(dataOutput, getExternalId()); 324 WritableUtils.writeStr(dataOutput, getExternalStatus()); 325 WritableUtils.writeStr(dataOutput, getTrackerUri()); 326 WritableUtils.writeStr(dataOutput, getConsoleUrl()); 327 WritableUtils.writeStr(dataOutput, getErrorCode()); 328 WritableUtils.writeStr(dataOutput, getErrorMessage()); 329 WritableUtils.writeStr(dataOutput, wfId); 330 WritableUtils.writeStr(dataOutput, executionPath); 331 dataOutput.writeInt(pending); 332 dataOutput.writeLong((getPendingAge() != null) ? getPendingAge().getTime() : -1); 333 WritableUtils.writeStr(dataOutput, signalValue); 334 WritableUtils.writeStr(dataOutput, logToken); 335 dataOutput.writeInt(getUserRetryCount()); 336 dataOutput.writeInt(getUserRetryInterval()); 337 dataOutput.writeInt(getUserRetryMax()); 338 } 339 340 /** 341 * Deserialize an action bean from a data input. 342 * 343 * @param dataInput data input. 344 * @throws IOException thrown if the action bean could not be deserialized. 345 */ 346 public void readFields(DataInput dataInput) throws IOException { 347 setId(WritableUtils.readStr(dataInput)); 348 setName(WritableUtils.readStr(dataInput)); 349 setCred(WritableUtils.readStr(dataInput)); 350 setType(WritableUtils.readStr(dataInput)); 351 setConf(WritableUtils.readStr(dataInput)); 352 setStatus(WorkflowAction.Status.valueOf(WritableUtils.readStr(dataInput))); 353 setRetries(dataInput.readInt()); 354 long d = dataInput.readLong(); 355 if (d != -1) { 356 setStartTime(new Date(d)); 357 } 358 d = dataInput.readLong(); 359 if (d != -1) { 360 setEndTime(new Date(d)); 361 } 362 d = dataInput.readLong(); 363 if (d != -1) { 364 setLastCheckTime(new Date(d)); 365 } 366 setTransition(WritableUtils.readStr(dataInput)); 367 setData(WritableUtils.readStr(dataInput)); 368 setStats(WritableUtils.readStr(dataInput)); 369 setExternalChildIDs(WritableUtils.readStr(dataInput)); 370 setExternalId(WritableUtils.readStr(dataInput)); 371 setExternalStatus(WritableUtils.readStr(dataInput)); 372 setTrackerUri(WritableUtils.readStr(dataInput)); 373 setConsoleUrl(WritableUtils.readStr(dataInput)); 374 setErrorInfo(WritableUtils.readStr(dataInput), WritableUtils.readStr(dataInput)); 375 wfId = WritableUtils.readStr(dataInput); 376 executionPath = WritableUtils.readStr(dataInput); 377 pending = dataInput.readInt(); 378 d = dataInput.readLong(); 379 if (d != -1) { 380 pendingAgeTimestamp = DateUtils.convertDateToTimestamp(new Date(d)); 381 } 382 signalValue = WritableUtils.readStr(dataInput); 383 logToken = WritableUtils.readStr(dataInput); 384 setUserRetryCount(dataInput.readInt()); 385 setUserRetryInterval(dataInput.readInt()); 386 setUserRetryMax(dataInput.readInt()); 387 } 388 389 /** 390 * Return whether workflow action in terminal state or not 391 * 392 * @return isTerminalState Return whether workflow action in terminal state or not 393 */ 394 public boolean inTerminalState() { 395 boolean isTerminalState = false; 396 switch (WorkflowAction.Status.valueOf(statusStr)) { 397 case ERROR: 398 case FAILED: 399 case KILLED: 400 case OK: 401 isTerminalState = true; 402 break; 403 default: 404 break; 405 } 406 return isTerminalState; 407 } 408 409 /** 410 * Return if the action execution is complete. 411 * 412 * @return if the action start is complete. 413 */ 414 public boolean isExecutionComplete() { 415 return getStatus() == WorkflowAction.Status.DONE; 416 } 417 418 /** 419 * Return if the action is START_RETRY or START_MANUAL or END_RETRY or 420 * END_MANUAL. 421 * 422 * @return boolean true if status is START_RETRY or START_MANUAL or 423 * END_RETRY or END_MANUAL 424 */ 425 public boolean isRetryOrManual() { 426 return (getStatus() == WorkflowAction.Status.START_RETRY || getStatus() == WorkflowAction.Status.START_MANUAL 427 || getStatus() == WorkflowAction.Status.END_RETRY || getStatus() == WorkflowAction.Status.END_MANUAL); 428 } 429 430 /** 431 * Return true if the action is USER_RETRY 432 * 433 * @return boolean true if status is USER_RETRY 434 */ 435 public boolean isUserRetry() { 436 return (getStatus() == WorkflowAction.Status.USER_RETRY); 437 } 438 439 /** 440 * Return if the action is complete. 441 * 442 * @return if the action is complete. 443 */ 444 public boolean isComplete() { 445 return getStatus() == WorkflowAction.Status.OK || getStatus() == WorkflowAction.Status.KILLED 446 || getStatus() == WorkflowAction.Status.ERROR; 447 } 448 449 /** 450 * Return if the action is complete with failure. 451 * 452 * @return if the action is complete with failure. 453 */ 454 public boolean isTerminalWithFailure() { 455 boolean result = false; 456 switch (getStatus()) { 457 case FAILED: 458 case KILLED: 459 case ERROR: 460 result = true; 461 } 462 return result; 463 } 464 465 /** 466 * Set the action pending flag to true. 467 */ 468 public void setPendingOnly() { 469 pending = 1; 470 } 471 472 /** 473 * Set the action as pending and the current time as pending. 474 */ 475 public void setPending() { 476 pending = 1; 477 pendingAgeTimestamp = DateUtils.convertDateToTimestamp(new Date()); 478 } 479 480 /** 481 * Set pending flag 482 * @param i the flag 483 */ 484 public void setPending(int i) { 485 pending = i; 486 } 487 488 /** 489 * Set a time when the action will be pending, normally a time in the 490 * future. 491 * 492 * @param pendingAge the time when the action will be pending. 493 */ 494 public void setPendingAge(Date pendingAge) { 495 this.pendingAgeTimestamp = DateUtils.convertDateToTimestamp(pendingAge); 496 } 497 498 /** 499 * Return the pending age of the action. 500 * 501 * @return the pending age of the action, <code>null</code> if the action is 502 * not pending. 503 */ 504 public Date getPendingAge() { 505 return DateUtils.toDate(pendingAgeTimestamp); 506 } 507 508 /** 509 * Return if the action is pending. 510 * 511 * @return if the action is pending. 512 */ 513 public boolean isPending() { 514 return pending == 1 ? true : false; 515 } 516 517 /** 518 * Removes the pending flag and pendingAge from the action. 519 */ 520 public void resetPending() { 521 pending = 0; 522 pendingAgeTimestamp = null; 523 } 524 525 /** 526 * Removes the pending flag from the action. 527 */ 528 public void resetPendingOnly() { 529 pending = 0; 530 } 531 532 /** 533 * Increments the number of retries for the action. 534 */ 535 public void incRetries() { 536 setRetries(getRetries() + 1); 537 } 538 539 /** 540 * Set a tracking information for an action, and set the action status to 541 * {@link org.apache.oozie.client.WorkflowAction.Status#DONE} 542 * 543 * @param externalId external ID for the action. 544 * @param trackerUri tracker URI for the action. 545 * @param consoleUrl console URL for the action. 546 */ 547 public void setStartData(String externalId, String trackerUri, String consoleUrl) { 548 setExternalId(ParamChecker.notEmpty(externalId, "externalId")); 549 setTrackerUri(ParamChecker.notEmpty(trackerUri, "trackerUri")); 550 setConsoleUrl(ParamChecker.notEmpty(consoleUrl, "consoleUrl")); 551 Date now = new Date(); 552 if (this.startTimestamp == null) { 553 setStartTime(now); 554 } 555 setLastCheckTime(now); 556 setStatus(Status.RUNNING); 557 } 558 559 /** 560 * Set the completion information for an action start. Sets the Action 561 * status to {@link org.apache.oozie.client.WorkflowAction.Status#DONE} 562 * 563 * @param externalStatus action external end status. 564 * @param actionData action output data, <code>null</code> if there is no 565 * action output data. 566 */ 567 public void setExecutionData(String externalStatus, Properties actionData) { 568 setStatus(Status.DONE); 569 setExternalStatus(ParamChecker.notEmpty(externalStatus, "externalStatus")); 570 if (actionData != null) { 571 setData(PropertiesUtils.propertiesToString(actionData)); 572 } 573 } 574 575 /** 576 * Return the action statistics info. 577 * 578 * @return Json representation of the stats. 579 */ 580 public String getExecutionStats() { 581 return getStats(); 582 } 583 584 /** 585 * Set the action statistics info for the workflow action. 586 * 587 * @param jsonStats representation of the stats. 588 */ 589 public void setExecutionStats(String jsonStats) { 590 setStats(jsonStats); 591 } 592 593 /** 594 * Return the external child IDs. 595 * 596 * @return externalChildIDs as a string. 597 */ 598 @Override 599 public String getExternalChildIDs() { 600 return externalChildIDs == null ? null : externalChildIDs.getString(); 601 } 602 603 /** 604 * Set the external child IDs for the workflow action. 605 * 606 * @param externalChildIDs as a string. 607 */ 608 public void setExternalChildIDs(String externalChildIDs) { 609 if (this.externalChildIDs == null) { 610 this.externalChildIDs = new StringBlob(externalChildIDs); 611 } 612 else { 613 this.externalChildIDs.setString(externalChildIDs); 614 } 615 } 616 617 /** 618 * Set external child ids 619 * 620 * @param externalChildIDs the external child ids 621 */ 622 public void setExternalChildIDsBlob(StringBlob externalChildIDs) { 623 this.externalChildIDs = externalChildIDs; 624 } 625 626 /** 627 * Get external ChildIds 628 * 629 * @return externalChildIDs Get external ChildIds 630 */ 631 public StringBlob getExternalChildIDsBlob() { 632 return externalChildIDs; 633 } 634 635 /** 636 * Set the completion information for an action end. 637 * 638 * @param status action status, {@link org.apache.oozie.client.WorkflowAction.Status#OK} or 639 * {@link org.apache.oozie.client.WorkflowAction.Status#ERROR} or 640 * {@link org.apache.oozie.client.WorkflowAction.Status#KILLED} 641 * @param signalValue the signal value. In most cases, the value should be 642 * OK or ERROR. 643 */ 644 public void setEndData(Status status, String signalValue) { 645 if (status == null || (status != Status.OK && status != Status.ERROR && status != Status.KILLED)) { 646 throw new IllegalArgumentException("Action status must be OK, ERROR or KILLED. Received [" 647 + (status == null ? "null" : status.toString()) + "]"); 648 } 649 if (status == Status.OK) { 650 setErrorInfo(null, null); 651 } 652 setStatus(status); 653 setSignalValue(ParamChecker.notEmpty(signalValue, "signalValue")); 654 } 655 656 /** 657 * Return the job Id. 658 * 659 * @return the job Id. 660 */ 661 public String getJobId() { 662 return wfId; 663 } 664 665 /** 666 * Return the job Id. 667 * 668 * @return the job Id. 669 */ 670 public String getWfId() { 671 return wfId; 672 } 673 674 /** 675 * Set the job id. 676 * 677 * @param id jobId; 678 */ 679 public void setJobId(String id) { 680 this.wfId = id; 681 } 682 683 public void setSlaXml(String slaXmlStr) { 684 if (this.slaXml == null) { 685 this.slaXml = new StringBlob(slaXmlStr); 686 } 687 else { 688 this.slaXml.setString(slaXmlStr); 689 } 690 } 691 692 public String getSlaXml() { 693 return slaXml == null ? null : slaXml.getString(); 694 } 695 696 public void setSlaXmlBlob(StringBlob slaXml) { 697 this.slaXml = slaXml; 698 } 699 700 public StringBlob getSlaXmlBlob() { 701 return slaXml; 702 } 703 704 /** 705 * Set status of job 706 * 707 * @param val the status 708 */ 709 public void setStatus(Status val) { 710 this.statusStr = val.toString(); 711 } 712 713 @Override 714 public Status getStatus() { 715 return Status.valueOf(this.statusStr); 716 } 717 718 /** 719 * Set status 720 * 721 * @param statusStr the status 722 */ 723 public void setStatusStr(String statusStr) { 724 this.statusStr = statusStr; 725 } 726 727 /** 728 * Get status 729 * 730 * @return statusStr Get status 731 */ 732 public String getStatusStr() { 733 return statusStr; 734 } 735 736 /** 737 * Return the node execution path. 738 * 739 * @return the node execution path. 740 */ 741 public String getExecutionPath() { 742 return executionPath; 743 } 744 745 /** 746 * Set the node execution path. 747 * 748 * @param executionPath the node execution path. 749 */ 750 public void setExecutionPath(String executionPath) { 751 this.executionPath = executionPath; 752 } 753 754 /** 755 * Return the signal value for the action. 756 * <p> 757 * For decision nodes it is the choosen transition, for actions it is OK or 758 * ERROR. 759 * 760 * @return the action signal value. 761 */ 762 public String getSignalValue() { 763 return signalValue; 764 } 765 766 /** 767 * Set the signal value for the action. 768 * <p> 769 * For decision nodes it is the choosen transition, for actions it is OK or 770 * ERROR. 771 * 772 * @param signalValue the action signal value. 773 */ 774 public void setSignalValue(String signalValue) { 775 this.signalValue = signalValue; 776 } 777 778 /** 779 * Return the job log token. 780 * 781 * @return the job log token. 782 */ 783 public String getLogToken() { 784 return logToken; 785 } 786 787 /** 788 * Set the job log token. 789 * 790 * @param logToken the job log token. 791 */ 792 public void setLogToken(String logToken) { 793 this.logToken = logToken; 794 } 795 796 /** 797 * Return the action last check time 798 * 799 * @return the last check time 800 */ 801 public Date getLastCheckTime() { 802 return DateUtils.toDate(lastCheckTimestamp); 803 } 804 805 /** 806 * Return the action last check time 807 * 808 * @return the last check time 809 */ 810 public Timestamp getLastCheckTimestamp() { 811 return lastCheckTimestamp; 812 } 813 814 /** 815 * Return the action last check time 816 * 817 * @return the last check time 818 */ 819 public Timestamp getStartTimestamp() { 820 return startTimestamp; 821 } 822 823 /** 824 * Return the action last check time 825 * 826 * @return the last check time 827 */ 828 public Timestamp getEndTimestamp() { 829 return endTimestamp; 830 } 831 832 /** 833 * Return the action last check time 834 * 835 * @return the last check time 836 */ 837 public Timestamp getPendingAgeTimestamp() { 838 return pendingAgeTimestamp; 839 } 840 841 /** 842 * Sets the action last check time 843 * 844 * @param lastCheckTime the last check time to set. 845 */ 846 public void setLastCheckTime(Date lastCheckTime) { 847 this.lastCheckTimestamp = DateUtils.convertDateToTimestamp(lastCheckTime); 848 } 849 850 public int getPending() { 851 return this.pending; 852 } 853 854 @Override 855 public Date getStartTime() { 856 return DateUtils.toDate(startTimestamp); 857 } 858 859 /** 860 * Set start time 861 * 862 * @param startTime the start time 863 */ 864 public void setStartTime(Date startTime) { 865 this.startTimestamp = DateUtils.convertDateToTimestamp(startTime); 866 } 867 868 @Override 869 public Date getEndTime() { 870 return DateUtils.toDate(endTimestamp); 871 } 872 873 /** 874 * Set end time 875 * 876 * @param endTime the end time 877 */ 878 public void setEndTime(Date endTime) { 879 this.endTimestamp = DateUtils.convertDateToTimestamp(endTime); 880 } 881 882 @SuppressWarnings("unchecked") 883 public JSONObject toJSONObject() { 884 return toJSONObject("GMT"); 885 } 886 887 @SuppressWarnings("unchecked") 888 public JSONObject toJSONObject(String timeZoneId) { 889 JSONObject json = new JSONObject(); 890 json.put(JsonTags.WORKFLOW_ACTION_ID, id); 891 json.put(JsonTags.WORKFLOW_ACTION_NAME, name); 892 json.put(JsonTags.WORKFLOW_ACTION_AUTH, cred); 893 json.put(JsonTags.WORKFLOW_ACTION_TYPE, type); 894 json.put(JsonTags.WORKFLOW_ACTION_CONF, getConf()); 895 json.put(JsonTags.WORKFLOW_ACTION_STATUS, statusStr); 896 json.put(JsonTags.WORKFLOW_ACTION_RETRIES, (long) retries); 897 json.put(JsonTags.WORKFLOW_ACTION_START_TIME, JsonUtils.formatDateRfc822(getStartTime(), timeZoneId)); 898 json.put(JsonTags.WORKFLOW_ACTION_END_TIME, JsonUtils.formatDateRfc822(getEndTime(), timeZoneId)); 899 json.put(JsonTags.WORKFLOW_ACTION_TRANSITION, transition); 900 json.put(JsonTags.WORKFLOW_ACTION_DATA, getData()); 901 json.put(JsonTags.WORKFLOW_ACTION_STATS, getStats()); 902 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_CHILD_IDS, getExternalChildIDs()); 903 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_ID, externalId); 904 json.put(JsonTags.WORKFLOW_ACTION_EXTERNAL_STATUS, externalStatus); 905 json.put(JsonTags.WORKFLOW_ACTION_TRACKER_URI, trackerUri); 906 json.put(JsonTags.WORKFLOW_ACTION_CONSOLE_URL, consoleUrl); 907 json.put(JsonTags.WORKFLOW_ACTION_ERROR_CODE, errorCode); 908 json.put(JsonTags.WORKFLOW_ACTION_ERROR_MESSAGE, errorMessage); 909 json.put(JsonTags.TO_STRING, toString()); 910 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_INTERVAL, userRetryInterval); 911 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_COUNT, userRetryCount); 912 json.put(JsonTags.WORKFLOW_ACTION_USER_RETRY_MAX, userRetryMax); 913 json.put(JsonTags.WORKFLOW_ACTION_CRED, cred); 914 return json; 915 } 916 917 @Override 918 public String getId() { 919 return id; 920 } 921 922 public void setId(String id) { 923 this.id = id; 924 } 925 926 public Timestamp getCreatedTimestamp() { 927 return createdTimeTS; 928 } 929 930 public Date getCreatedTime() { 931 return DateUtils.toDate(createdTimeTS); 932 } 933 934 public void setCreatedTime(Date createdTime) { 935 this.createdTimeTS = DateUtils.convertDateToTimestamp(createdTime); 936 } 937 938 @Override 939 public String getName() { 940 return name; 941 } 942 943 public void setName(String name) { 944 this.name = name; 945 } 946 947 @Override 948 public String getCred() { 949 return cred; 950 } 951 952 public void setCred(String cred) { 953 this.cred = cred; 954 } 955 956 @Override 957 public String getType() { 958 return type; 959 } 960 961 public void setType(String type) { 962 this.type = type; 963 } 964 965 @Override 966 public String getConf() { 967 return conf == null ? null : conf.getString(); 968 } 969 970 public void setConf(String conf) { 971 if (this.conf == null) { 972 this.conf = new StringBlob(conf); 973 } 974 else { 975 this.conf.setString(conf); 976 } 977 } 978 979 public void setConfBlob(StringBlob conf) { 980 this.conf = conf; 981 } 982 983 public StringBlob getConfBlob() { 984 return conf; 985 } 986 987 @Override 988 public int getRetries() { 989 return retries; 990 } 991 992 public void setRetries(int retries) { 993 this.retries = retries; 994 } 995 996 @Override 997 public int getUserRetryCount() { 998 return userRetryCount; 999 } 1000 1001 public void setUserRetryCount(int retryCount) { 1002 this.userRetryCount = retryCount; 1003 } 1004 1005 public void incrmentUserRetryCount() { 1006 this.userRetryCount++; 1007 } 1008 1009 @Override 1010 public int getUserRetryMax() { 1011 return userRetryMax; 1012 } 1013 1014 /** 1015 * Set user retry max 1016 * 1017 * @param retryMax the maximum retry count 1018 */ 1019 public void setUserRetryMax(int retryMax) { 1020 this.userRetryMax = retryMax; 1021 } 1022 1023 @Override 1024 public int getUserRetryInterval() { 1025 return userRetryInterval; 1026 } 1027 1028 public void setUserRetryInterval(int retryInterval) { 1029 this.userRetryInterval = retryInterval; 1030 } 1031 1032 @Override 1033 public String getTransition() { 1034 return transition; 1035 } 1036 1037 /** 1038 * Set transition 1039 * 1040 * @param transition the transition 1041 */ 1042 public void setTransition(String transition) { 1043 this.transition = transition; 1044 } 1045 1046 @Override 1047 public String getData() { 1048 return data == null ? null : data.getString(); 1049 } 1050 1051 /** 1052 * Set data 1053 * 1054 * @param data the data 1055 */ 1056 public void setData(String data) { 1057 if (this.data == null) { 1058 this.data = new StringBlob(data); 1059 } 1060 else { 1061 this.data.setString(data); 1062 } 1063 } 1064 1065 public void setDataBlob(StringBlob data) { 1066 this.data = data; 1067 } 1068 1069 public StringBlob getDataBlob() { 1070 return data; 1071 } 1072 1073 @Override 1074 public String getStats() { 1075 return stats == null ? null : stats.getString(); 1076 } 1077 1078 /** 1079 * Set stats 1080 * 1081 * @param stats the action stats 1082 */ 1083 public void setStats(String stats) { 1084 if (this.stats == null) { 1085 this.stats = new StringBlob(stats); 1086 } 1087 else { 1088 this.stats.setString(stats); 1089 } 1090 } 1091 1092 public void setStatsBlob(StringBlob stats) { 1093 this.stats = stats; 1094 } 1095 1096 public StringBlob getStatsBlob() { 1097 return this.stats; 1098 } 1099 1100 @Override 1101 public String getExternalId() { 1102 return externalId; 1103 } 1104 1105 /** 1106 * Set external Id 1107 * 1108 * @param externalId the id 1109 */ 1110 public void setExternalId(String externalId) { 1111 this.externalId = externalId; 1112 } 1113 1114 @Override 1115 public String getExternalStatus() { 1116 return externalStatus; 1117 } 1118 1119 /** 1120 * Set external status 1121 * 1122 * @param externalStatus the external status 1123 */ 1124 public void setExternalStatus(String externalStatus) { 1125 this.externalStatus = externalStatus; 1126 } 1127 1128 @Override 1129 public String getTrackerUri() { 1130 return trackerUri; 1131 } 1132 1133 /** 1134 * Set tracker uri 1135 * 1136 * @param trackerUri the URI 1137 */ 1138 public void setTrackerUri(String trackerUri) { 1139 this.trackerUri = trackerUri; 1140 } 1141 1142 @Override 1143 public String getConsoleUrl() { 1144 return consoleUrl; 1145 } 1146 1147 /** 1148 * Set console URL 1149 * 1150 * @param consoleUrl the URL 1151 */ 1152 public void setConsoleUrl(String consoleUrl) { 1153 this.consoleUrl = consoleUrl; 1154 } 1155 1156 @Override 1157 public String getErrorCode() { 1158 return errorCode; 1159 } 1160 1161 @Override 1162 public String getErrorMessage() { 1163 return errorMessage; 1164 } 1165 1166 /** 1167 * Set the error Info 1168 * 1169 * @param errorCode the error code 1170 * @param errorMessage the error message 1171 */ 1172 public void setErrorInfo(String errorCode, String errorMessage) { 1173 this.errorCode = errorCode; 1174 if (errorMessage != null && errorMessage.length() > 500) { 1175 errorMessage = errorMessage.substring(0, 500); 1176 } 1177 this.errorMessage = errorMessage; 1178 } 1179 1180 @Override 1181 public String toString() { 1182 return MessageFormat.format("Action name[{0}] status[{1}]", getName(), getStatus()); 1183 } 1184 1185 /** 1186 * Convert a nodes list into a JSONArray. 1187 * 1188 * @param nodes nodes list. 1189 * @param timeZoneId time zone to use for dates in the JSON array. 1190 * @return the corresponding JSON array. 1191 */ 1192 @SuppressWarnings("unchecked") 1193 public static JSONArray toJSONArray(List<WorkflowActionBean> nodes, String timeZoneId) { 1194 JSONArray array = new JSONArray(); 1195 for (WorkflowActionBean node : nodes) { 1196 array.add(node.toJSONObject(timeZoneId)); 1197 } 1198 return array; 1199 } 1200 1201}