/** * Licensed to JumpMind Inc under one or more contributor * license agreements. See the NOTICE file distributed * with this work for additional information regarding * copyright ownership. JumpMind Inc licenses this file * to you under the GNU General Public License, version 3.0 (GPLv3) * (the "License"); you may not use this file except in compliance * with the License. * * You should have received a copy of the GNU General Public License, * version 3.0 (GPLv3) along with this library; if not, see * <http://www.gnu.org/licenses/>. * * 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 org.jumpmind.symmetric.model; import java.io.Serializable; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.Date; public class ProcessInfo implements Serializable, Comparable<ProcessInfo>, Cloneable { private static final long serialVersionUID = 1L; public static enum Status { NEW, QUERYING, EXTRACTING, LOADING, TRANSFERRING, ACKING, PROCESSING, OK, ERROR; public String toString() { switch (this) { case NEW: return "New"; case QUERYING: return "Querying"; case EXTRACTING: return "Extracting"; case LOADING: return "Loading"; case TRANSFERRING: return "Transferring"; case ACKING: return "Acking"; case PROCESSING: return "Processing"; case OK: return "Ok"; case ERROR: return "Error"; default: return name(); } } }; private ProcessInfoKey key; private Status status = Status.NEW; private long currentDataCount; private long dataCount = -1; private long batchCount; private long currentBatchId; private String currentChannelId; private String currentTableName; private transient Thread thread; private Date currentBatchStartTime; private long currentLoadId; private Date startTime = new Date(); private Date lastStatusChangeTime = new Date(); private Date endTime; public ProcessInfo() { this(new ProcessInfoKey("", "", null)); } public ProcessInfo(ProcessInfoKey key) { this.key = key; thread = Thread.currentThread(); this.currentChannelId = key.getChannelId(); } public String getSourceNodeId() { return this.key.getSourceNodeId(); } public String getTargetNodeId() { return this.key.getTargetNodeId(); } public ProcessType getProcessType() { return this.key.getProcessType(); } public ProcessInfoKey getKey() { return key; } public void setKey(ProcessInfoKey key) { this.key = key; } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; this.lastStatusChangeTime = new Date(); if (status == Status.OK || status == Status.ERROR) { this.endTime = new Date(); } } public long getCurrentDataCount() { return currentDataCount; } public void setCurrentDataCount(long dataCount) { this.currentDataCount = dataCount; } public long getBatchCount() { return batchCount; } public void setBatchCount(long batchCount) { this.batchCount = batchCount; } public void incrementCurrentDataCount() { this.currentDataCount++; } public void incrementBatchCount() { this.batchCount++; } public long getCurrentBatchId() { return currentBatchId; } public void setCurrentBatchId(long currentBatchId) { this.currentBatchId = currentBatchId; this.currentBatchStartTime = new Date(); this.currentDataCount = 0; } public void setCurrentLoadId(long loadId) { this.currentLoadId = loadId; } public long getCurrentLoadId() { return currentLoadId; } public String getCurrentChannelId() { return currentChannelId; } public void setCurrentChannelId(String currentChannelId) { this.currentChannelId = currentChannelId; } public Thread getThread() { return thread; } public void setThread(Thread thread) { this.thread = thread; } public Date getStartTime() { return startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public void setCurrentTableName(String currentTableName) { this.currentTableName = currentTableName; } public String getCurrentTableName() { return currentTableName; } public Date getLastStatusChangeTime() { return lastStatusChangeTime; } public void setDataCount(long dataCount) { this.dataCount = dataCount; } public long getDataCount() { return dataCount; } public Date getCurrentBatchStartTime() { if (currentBatchStartTime == null) { return startTime; } else { return currentBatchStartTime; } } public void setCurrentBatchStartTime(Date currentBatchStartTime) { this.currentBatchStartTime = currentBatchStartTime; } @Override public String toString() { return String.format("%s,status=%s,startTime=%s", key.toString(), status.toString(), startTime.toString()); } public String showInError(String identityNodeId) { if (status == Status.ERROR) { switch (key.getProcessType()) { case MANUAL_LOAD: return null; case EXTRACT_FOR_PUSH: return key.getTargetNodeId(); case PULL_JOB: return key.getSourceNodeId(); case LOAD_FROM_PUSH: return key.getSourceNodeId(); case PULL_HANDLER: return key.getTargetNodeId(); case ROUTER_JOB: return key.getSourceNodeId(); case ROUTER_READER: return key.getSourceNodeId(); case GAP_DETECT: return key.getSourceNodeId(); default: return null; } } else { return null; } } public int compareTo(ProcessInfo o) { if (status == Status.ERROR && o.status != Status.ERROR) { return -1; } else if (o.status == Status.ERROR && status != Status.ERROR) { return 1; } else if (status != Status.OK && o.status == Status.OK) { return -1; } else if (o.status != Status.OK && status == Status.OK) { return 1; } else { return o.startTime.compareTo(startTime); } } public ThreadData getThreadData() { if (thread != null && thread.isAlive()) { return getThreadData(thread.getId()); } else { return null; } } public static ThreadData getThreadData(long threadId) { ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); ThreadInfo info = threadBean.getThreadInfo(threadId, 100); if (info != null) { String threadName = info.getThreadName(); StringBuilder formattedTrace = new StringBuilder(); StackTraceElement[] trace = info.getStackTrace(); for (StackTraceElement stackTraceElement : trace) { formattedTrace.append(stackTraceElement.getClassName()); formattedTrace.append("."); formattedTrace.append(stackTraceElement.getMethodName()); formattedTrace.append("()"); int lineNumber = stackTraceElement.getLineNumber(); if (lineNumber > 0) { formattedTrace.append(": "); formattedTrace.append(stackTraceElement.getLineNumber()); } formattedTrace.append("\n"); } return new ThreadData(threadName, formattedTrace.toString()); } else { return null; } } static public class ThreadData { public ThreadData(String threadName, String stackTrace) { this.threadName = threadName; this.stackTrace = stackTrace; } private String threadName; private String stackTrace; public String getStackTrace() { return stackTrace; } public String getThreadName() { return threadName; } } public ProcessInfo copy() { try { return (ProcessInfo)this.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } }