📄 job.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: Job.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.EDatabase;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.variable.UserInterface;import com.sun.electric.tool.user.ActivityLogger;import com.sun.electric.tool.user.CantEditException;import com.sun.electric.tool.user.ErrorLogger;import com.sun.electric.tool.user.User;import java.awt.Toolkit;import java.io.Serializable;import java.util.Date;import java.util.Iterator;import java.util.List;import java.util.logging.Logger;/** * Jobs are processes that will run in the background, such as * DRC, NCC, Netlisters, etc. Each Job gets placed in a Job * window, and reports its status. A job can be cancelled. * * <p>To start a new job, do: * <p>Job job = new Job(name); * <p>job.start(); * * <p>Job subclass must implement "doIt" method, it may override "terminateOK" method. * <p>Job subclass is activated by "Job.startJob()". In case of exception in constructor it is not activated. * Hence "doIt" and "terminateOK" method are not called. * <p>Job subclass must be serializable for CHANGE and REMOTE_EXAMINE mode. * Serialization occurs at the moment when "Job.startJob()" is called. * Fields that are not needed on the server are escaped from serialization by "transient" keyword. * "doIt" is executed on serverDatabase for CHANGE and REMOTE_EXAMINE mode. * "doIt" is executed on clientDatabase for EXAMINE mode, Job subclass need not be serializable. * <p>"doIt" may return true, may return false, may throw JobException or any other Exception/Error. * Return true is considered normal termination. * Return false and throwing any Exception/Throwable are failure terminations. * <p>On normal termination in CHANGE or REMOTE_EXAMINE mode "fieldVariableChanged" variables are serialized. * In case of REMOTE_EXAMINE they are serialized on read-only database state. * In case of CHANGE they are serialized on database state after Constraint propagation. * In case of EXAMINE they are not serialized, but they are checked for valid field names. * Some time later the changed variables are deserialized on client database. * If serialization on server and deserialization on client was OK then terminateOK method is called on client database for * all three modes CHANGE, REMOTE_EXAMINE, EXAMINE. * If serialization/deserialization failed then terminateOK is not called, error message is issued. * <p>In case of failure termination no terminateOK is called, error message is issued, * * <p>The extendig class may override getProgress(), * which returns a string indicating the current status. * Job also contains boolean abort, which gets set when the user decides * to abort the Job. The extending class' code should check abort when/where * applicable. * * <p>Note that if your Job calls methods outside of this thread * that access shared data, those called methods should be synchronized. * * @author gainsley */public abstract class Job implements Serializable { private static boolean GLOBALDEBUG = false; /*private*/ static Mode threadMode; private static int recommendedNumThreads; private static int socketPort = 35742; // socket port for client/server static final int PROTOCOL_VERSION = 18; // Jan 30 public static boolean BATCHMODE = false; // to run it in batch mode public static boolean LOCALDEBUGFLAG; // Gilda's case// private static final String CLASS_NAME = Job.class.getName(); static final Logger logger = Logger.getLogger("com.sun.electric.tool.job"); /** * Method to tell whether Electric is running in "debug" mode. * If the program is started with the "-debug" switch, debug mode is enabled. * @return true if running in debug mode. */ public static boolean getDebug() { return GLOBALDEBUG; } public static void setDebug(boolean f) { GLOBALDEBUG = f; } /** * Mode of Job manager */ public static enum Mode { /** Full screen run of Electric. */ FULL_SCREEN, /** Batch mode. */ BATCH, /** Server side. */ SERVER, /** Client side. */ CLIENT; } /** * Type is a typesafe enum class that describes the type of job (CHANGE or EXAMINE). */ public static enum Type { /** Describes a database change. */ CHANGE, /** Describes a database undo/redo. */ UNDO, /** Describes a database examination. */ EXAMINE, /** Describes a remote database examination. */ REMOTE_EXAMINE; } /** * Priority is a typesafe enum class that describes the priority of a job. */ public static enum Priority { /** The highest priority: from the user. */ USER, /** Next lower priority: visible changes. */ VISCHANGES, /** Next lower priority: invisible changes. */ INVISCHANGES, /** Lowest priority: analysis. */ ANALYSIS; } /** default execution time in milis */ /*private*/ static final int MIN_NUM_SECONDS = 60000; /** job manager */ /*private*/ static JobManager jobManager; static AbstractUserInterface currentUI; /** delete when done if true */ /*private*/ boolean deleteWhenDone; /** display on job list if true */ private boolean display; // Job Status /** job start time */ protected long startTime; /** job end time */ protected long endTime; /** was job started? */ /*private*/boolean started; /** is job finished? */ /*private*/ boolean finished; /** thread aborted? */ /*private*/ boolean aborted; /** schedule thread to abort */ /*private*/ boolean scheduledToAbort; /** report execution time regardless MIN_NUM_SECONDS */ /*private*/ boolean reportExecution = false; /** tool running the job */ /*private*/ Tool tool;// /** priority of job */ private Priority priority;// /** bottom of "up-tree" of cells affected */private Cell upCell;// /** top of "down-tree" of cells affected */ private Cell downCell;// /** status */ private String status = null; transient EJob ejob; transient EDatabase database; public static void setThreadMode(Mode mode, AbstractUserInterface userInterface) { threadMode = mode; BATCHMODE = (mode == Mode.BATCH || mode == Mode.SERVER); currentUI = userInterface; } public static void initJobManager(int numThreads, Job initDatabaseJob, Object mode, String serverMachineName) { Job.recommendedNumThreads = numThreads; switch (threadMode) { case FULL_SCREEN: if (User.isUseClientServer()) jobManager = new ServerJobManager(numThreads, socketPort); else jobManager = new ServerJobManager(numThreads); // Calling external dependencies currentUI.initializeInitJob(initDatabaseJob, mode); initDatabaseJob.startJob(); break; case BATCH: case SERVER: jobManager = new ServerJobManager(numThreads, socketPort); initDatabaseJob.startJob(); break; case CLIENT: logger.finer("setThreadMode"); jobManager = new ClientJobManager(serverMachineName, socketPort); // unreachable break; } jobManager.runLoop(); } public static Mode getRunMode() { return threadMode; } public static int getNumThreads() { return recommendedNumThreads; } /** * Constructor creates a new instance of Job. * @param jobName a string that describes this Job. * @param tool the Tool that originated this Job. * @param jobType the Type of this Job (EXAMINE or CHANGE). * @param upCell the Cell at the bottom of a hierarchical "up cone" of change. * If this and "downCell" are null, the entire database is presumed. * @param downCell the Cell at the top of a hierarchical "down tree" of changes/examinations. * If this and "upCell" are null, the entire database is presumed. * @param priority the priority of this Job. */ public Job(String jobName, Tool tool, Type jobType, Cell upCell, Cell downCell, Priority priority) { ejob = new EJob(this, jobType, jobName); database = threadDatabase(); this.tool = tool;// this.priority = priority;// this.upCell = upCell;// this.downCell = downCell; this.display = true; this.deleteWhenDone = true; startTime = endTime = 0;// started = finished = aborted = scheduledToAbort = false;// thread = null; } /** * Start a job. By default displays Job on Job List UI, and * delete Job when done. Jobs that have state the user would like to use * after the Job finishes (like DRC, NCC, etc) should call * <code>startJob(true, true)</code>. */ public void startJob() { startJob(!BATCHMODE, true); } /** * Start a job on snapshot obtained at the end of current job. By default displays Job on Job List UI, and * delete Job when done. */ public void startJobOnMyResult() { startJob(!BATCHMODE, true, true); } /** * Start the job by placing it on the JobThread queue. * If <code>display</code> is true, display job on Job List UI. * If <code>deleteWhenDone</code> is true, Job will be deleted * after it is done (frees all data and references it stores/created) * @param deleteWhenDone delete when job is done if true, otherwise leave it around */ public void startJob(boolean display, boolean deleteWhenDone) { startJob(display, deleteWhenDone, false); } /** * Start the job by placing it on the JobThread queue. * If <code>display</code> is true, display job on Job List UI. * If <code>deleteWhenDone</code> is true, Job will be deleted * after it is done (frees all data and references it stores/created) * @param deleteWhenDone delete when job is done if true, otherwise leave it around */ private void startJob(boolean display, boolean deleteWhenDone, boolean onMySnapshot) { this.display = display; this.deleteWhenDone = deleteWhenDone; Thread currentThread = Thread.currentThread(); if (currentThread instanceof EThread && ((EThread)currentThread).ejob.jobType != Job.Type.EXAMINE) { ejob.startedByServer = true; ejob.client = ((EThread)currentThread).ejob.client; ejob.serverJob.startTime = System.currentTimeMillis(); ejob.serialize(EDatabase.serverDatabase()); ejob.clientJob = null; } else { ejob.client = Job.getExtendedUserInterface(); ejob.clientJob.startTime = System.currentTimeMillis(); ejob.serverJob = null; if (ejob.jobType != Job.Type.EXAMINE) ejob.serialize(EDatabase.clientDatabase()); } jobManager.addJob(ejob, onMySnapshot); } /** * Method to remember that a field variable of the Job has been changed by the doIt() method. * @param variableName the name of the variable that changed. */ protected void fieldVariableChanged(String variableName) { ejob.fieldVariableChanged(variableName); } //--------------------------ABSTRACT METHODS-------------------------- /** This is the main work method. This method should * perform all needed tasks. * @throws JobException TODO */ public abstract boolean doIt() throws JobException; /** * This method executes in the Client side after termination of doIt method. * This method should perform all needed termination actions. * @param jobException null if doIt terminated normally, otherwise exception thrown by doIt. */ public void terminateIt(Throwable jobException) { if (jobException == null) terminateOK(); else terminateFail(jobException); } /** * This method executes in the Client side after normal termination of doIt method. * This method should perform all needed termination actions. */ public void terminateOK() {} /** * This method executes in the Client side after exceptional termination of doIt method. * @param jobException null exception thrown by doIt. */ public void terminateFail(Throwable jobException) { if (jobException instanceof CantEditException) { ((CantEditException)jobException).presentProblem(); } else if (jobException instanceof JobException) { String message = jobException.getMessage(); if (message == null) message = "Job " + ejob.jobName + " failed"; System.out.println(message); } else { ActivityLogger.logException(jobException); } } //--------------------------PRIVATE JOB METHODS-------------------------- //--------------------------PROTECTED JOB METHODS----------------------- /** Set reportExecution flag on/off */ protected void setReportExecutionFlag(boolean flag) { reportExecution = flag; } //--------------------------PUBLIC JOB METHODS--------------------------// /**// * Method to end the current batch of changes and start another.// * Besides starting a new batch, it cleans up the constraint system, and// */// protected void flushBatch()// {// if (jobType != Type.CHANGE) return;// Undo.endChanges();// Undo.startChanges(tool, jobName, /*upCell,*/ savedHighlights, savedHighlightsOffset);// } protected synchronized void setProgress(String progress) { jobManager.setProgress(ejob, progress); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -