/** * Copyright © 2013 enioka. All rights reserved * Authors: Marc-Antoine GOUILLART (marc-antoine.gouillart@enioka.com) * Pierre COPPEE (pierre.coppee@enioka.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.enioka.jqm.model; import java.io.Serializable; import java.util.Calendar; import com.enioka.jqm.jdbc.DbConn; /** * <strong>Not part of any API - this an internal JQM class and may change without notice.</strong> <br> * Persistence class for storing the execution log. All finished {@link JobInstance}s end up in this table (and are purged from * {@link JobInstance}). */ public class History implements Serializable { private static final long serialVersionUID = -5249529794213078668L; private Integer id; /************/ /* Identity */ private int jd; private String applicationName; private int queue_id; private String queueName; // null if cancelled before running private int node; private String nodeName; private boolean highlander = false; /***********/ /* RESULTS */ private State status = State.SUBMITTED; private Integer return_code; private Integer progress; /***********/ /* TIME */ private Calendar enqueue_Date; private Calendar attributionDate; private Calendar execution_date; private Calendar end_date; /***************************/ /* Instance classification */ private String session_id; private String userName; private String email; private Integer parent_job_id; private String instance_application; private String instance_module; private String instance_keyword1; private String instance_keyword2; private String instance_keyword3; /**************************/ /* Job Def classification */ private String keyword1; private String keyword2; private String keyword3; private String application; private String module; /** * This is both the ID (PK) of the {@link History} (i.e. log) object and the ID of the {@link JobInstance} which was the source of this * log. Therefore it is NOT generated by the database and must be set. */ public Integer getId() { return id; } /** * See {@link #getId()} */ public void setId(final Integer id) { this.id = id; } /** * Time at which the execution request was committed inside the database. */ public Calendar getEnqueueDate() { return enqueue_Date; } /** * See {@link #getEnqueueDate()} */ public void setEnqueueDate(final Calendar enqueueDate) { this.enqueue_Date = enqueueDate; } /** * Time at which the execution request entered the RUNNING status - a few milliseconds before actual execution. */ public Calendar getExecutionDate() { return execution_date; } /** * See {@link #getExecutionDate()} */ public void setExecutionDate(final Calendar executionDate) { this.execution_date = executionDate; } /** * Time at which the payload (i.e. user code) returned. */ public Calendar getEndDate() { return end_date; } /** * See {@link #getEndDate()} */ public void setEndDate(final Calendar endDate) { this.end_date = endDate; } /** * The {@link Queue} on which the {@link JobInstance} run took place. the actual queue, not necessarily the one defined inside * {@link JobDef} as it can be overloaded in the execution request) */ public int getQueue() { return queue_id; } /** * See {@link #getQueue()} */ public void setQueue(final int queue) { this.queue_id = queue; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getUserName() { return userName; } /** * See {@link #getUserName()} */ public void setUserName(final String userName) { this.userName = userName; } /** * The actual {@link Node} (i.e. JQM engine) that has run the {@link JobInstance}. */ public int getNode() { return node; } /** * See {@link #getNode()} */ public void setNode(final int node) { this.node = node; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getSessionId() { return session_id; } /** * See {@link #getSessionId()} */ public void setSessionId(final String sessionId) { this.session_id = sessionId; } /** * The {@link JobDef} that was run (i.e. the {@link JobInstance} is actually an instance of this {@link JobDef}). */ public int getJd() { return jd; } /** * See {@link #getJd()} */ public void setJd(int jd) { this.jd = jd; } /** * Comes directly from the execution request. If specified, an e-mail is sent to this address at run end. Stored in {@link History} only * for the sake of being able to duplicate a launch. */ public String getEmail() { return email; } /** * See {@link #getEmail()} */ public void setEmail(String email) { this.email = email; } /** * Only set when a job request is created by a running job, in which case it contains the job ID. */ public Integer getParentJobId() { return parent_job_id; } /** * See {@link #getParentJobId()} */ public void setParentJobId(Integer parentJobId) { this.parent_job_id = parentJobId; } /** * The end status of the job (CRASHED, ENDED, ...) */ public State getStatus() { return status; } /** * See {@link #getStatus()} */ public State getState() { return status; } /** * See {@link #getStatus()} */ public void setStatus(State status) { this.status = status; } /** * An optional classification tag which can be specified inside the {@link JobDef} (default is NULL). */ public String getKeyword1() { return keyword1; } /** * See {@link #getKeyword1()} */ public void setKeyword1(String keyword1) { this.keyword1 = keyword1; } /** * An optional classification tag which can be specified inside the {@link JobDef} (default is NULL). */ public String getKeyword2() { return keyword2; } /** * See {@link #getKeyword2()} */ public void setKeyword2(String keyword2) { this.keyword2 = keyword2; } /** * An optional classification tag which can be specified inside the {@link JobDef} (default is NULL). */ public String getKeyword3() { return keyword3; } /** * See {@link #getKeyword3()} */ public void setKeyword3(String keyword3) { this.keyword3 = keyword3; } /** * An optional classification tag which can be specified inside the {@link JobDef} (default is NULL). */ public String getApplication() { return application; } /** * See {@link #getApplication()} */ public void setApplication(String application) { this.application = application; } /** * An optional classification tag which can be specified inside the {@link JobDef} (default is NULL). */ public String getModule() { return module; } /** * See {@link #getModule()} */ public void setModule(String module) { this.module = module; } /** * User code may signal its progress through this integer. Purely optional. */ public Integer getProgress() { return progress; } /** * See {@link #getProgress()} */ public void setProgress(Integer progress) { this.progress = progress; } /** * True if the {@link JobInstance} was run in Highlander mode (i.e. never more than one concurrent execution of the same {@link JobDef} * inside the whole cluster) */ public boolean isHighlander() { return highlander; } /** * See {@link #isHighlander()} */ public void setHighlander(boolean highlander) { this.highlander = highlander; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getInstanceApplication() { return instance_application; } /** * See {@link #getInstanceApplication()} */ public void setInstanceApplication(String instanceApplication) { this.instance_application = instanceApplication; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getInstanceModule() { return instance_module; } /** * See {@link #setInstanceModule(String)} */ public void setInstanceModule(String instanceModule) { this.instance_module = instanceModule; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getInstanceKeyword1() { return instance_keyword1; } /** * See {@link #setInstanceKeyword1(String)} */ public void setInstanceKeyword1(String instanceKeyword1) { this.instance_keyword1 = instanceKeyword1; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getInstanceKeyword2() { return instance_keyword2; } /** * See {@link #setInstanceKeyword2(String)} */ public void setInstanceKeyword2(String instanceKeyword2) { this.instance_keyword2 = instanceKeyword2; } /** * An optional classification tag which can be specified inside the execution request (default is NULL). */ public String getInstanceKeyword3() { return instance_keyword3; } /** * See {@link #setInstanceKeyword3(String)} */ public void setInstanceKeyword3(String instanceKeyword3) { this.instance_keyword3 = instanceKeyword3; } /** * Time at which the job execution request (the {@link JobInstance}) was taken by an engine. */ public Calendar getAttributionDate() { return attributionDate; } /** * See {@link #getAttributionDate()} */ public void setAttributionDate(Calendar attributionDate) { this.attributionDate = attributionDate; } /** * The applicative key of the {@link JobDef} that has run. {@link JobDef} are always retrieved through this name.<br> * Max length is 100. */ public String getApplicationName() { return this.applicationName; } /** * See {@link #getApplicationName()} */ public void setApplicationName(String applicationName) { this.applicationName = applicationName; } /** * Functional key. Queues are specified by name inside all APIs. Must be unique.<br> * Max length is 50. */ public String getQueueName() { return queueName; } /** * See {@link #getQueueName()} */ public void setQueueName(String queueName) { this.queueName = queueName; } /** * The functional key of the node. It is unique.<br> * Max length is 100. */ public String getNodeName() { return nodeName; } /** * See {@link #getName()} */ public void setNodeName(final String nodeName) { this.nodeName = nodeName; } /** * Create an History object from a {@link JobInstance}. * */ public static void create(DbConn cnx, JobInstance ji, State finalState, Calendar endDate) { JobDef jd = ji.getJD(); Node n = ji.getNode(); Queue q = ji.getQ(); if (endDate == null) { cnx.runUpdate("history_insert", ji.getId(), jd.getApplication(), jd.getApplicationName(), ji.getAttributionDate(), ji.getEmail(), ji.getCreationDate(), ji.getExecutionDate(), jd.isHighlander(), ji.getApplication(), ji.getKeyword1(), ji.getKeyword2(), ji.getKeyword3(), ji.getModule(), jd.getKeyword1(), jd.getKeyword2(), jd.getKeyword3(), jd.getModule(), n == null ? null : n.getName(), ji.getParentId(), ji.getProgress(), q == null ? null : q.getName(), 0, ji.getSessionID(), finalState.toString(), ji.getUserName(), ji.getJd(), n == null ? null : n.getId(), ji.getQueue()); } else { cnx.runUpdate("history_insert_with_end_date", ji.getId(), jd.getApplication(), jd.getApplicationName(), ji.getAttributionDate(), ji.getEmail(), endDate, ji.getCreationDate(), ji.getExecutionDate(), jd.isHighlander(), ji.getApplication(), ji.getKeyword1(), ji.getKeyword2(), ji.getKeyword3(), ji.getModule(), jd.getKeyword1(), jd.getKeyword2(), jd.getKeyword3(), jd.getModule(), n.getName(), ji.getParentId(), ji.getProgress(), q.getName(), 0, ji.getSessionID(), finalState.toString(), ji.getUserName(), ji.getJd(), ji.getNode().getId(), ji.getQueue()); } } /** * Create an History object from a {@link JobInstance}. (if it does not exist, exception). * */ public static void create(DbConn cnx, int launchId, State finalState, Calendar endDate) { JobInstance ji = JobInstance.select_id(cnx, launchId); create(cnx, ji, finalState, endDate); } }