extensions/net.sf.basedb.opengrid/trunk/src/net/sf/basedb/opengrid/JobDefinition.java

Code
Comments
Other
Rev Date Author Line
4130 26 Sep 16 nicklas 1 package net.sf.basedb.opengrid;
4130 26 Sep 16 nicklas 2
4130 26 Sep 16 nicklas 3 import java.util.ArrayList;
6666 05 Apr 22 nicklas 4 import java.util.Arrays;
6666 05 Apr 22 nicklas 5 import java.util.Collections;
6660 01 Apr 22 nicklas 6 import java.util.Date;
6666 05 Apr 22 nicklas 7 import java.util.HashSet;
4130 26 Sep 16 nicklas 8 import java.util.List;
6666 05 Apr 22 nicklas 9 import java.util.Set;
6660 01 Apr 22 nicklas 10 import java.util.concurrent.atomic.AtomicInteger;
4130 26 Sep 16 nicklas 11
6660 01 Apr 22 nicklas 12 import net.sf.basedb.core.Application;
4203 02 Nov 16 nicklas 13 import net.sf.basedb.core.Job;
6672 11 Apr 22 nicklas 14 import net.sf.basedb.opengrid.config.BatchConfig;
4270 16 Dec 16 nicklas 15 import net.sf.basedb.opengrid.config.ClusterConfig;
4254 25 Nov 16 nicklas 16 import net.sf.basedb.opengrid.config.JobConfig;
5982 07 Jul 20 nicklas 17 import net.sf.basedb.opengrid.engine.OpenGridEngine;
4130 26 Sep 16 nicklas 18 import net.sf.basedb.opengrid.filetransfer.FilePermission;
4130 26 Sep 16 nicklas 19 import net.sf.basedb.opengrid.filetransfer.UploadSource;
6660 01 Apr 22 nicklas 20 import net.sf.basedb.util.MD5;
6660 01 Apr 22 nicklas 21 import net.sf.basedb.util.formatter.DateFormatter;
4130 26 Sep 16 nicklas 22
4130 26 Sep 16 nicklas 23 /**
5982 07 Jul 20 nicklas 24   Define a job that should be submitted to the cluster.
4297 13 Jan 17 nicklas 25   The definition consists of four parts:
4130 26 Sep 16 nicklas 26   
4130 26 Sep 16 nicklas 27    * The command/bash script that should be executed
5982 07 Jul 20 nicklas 28    * Options for the job (eg. parameters to the 'qsub'/'sbatch' command)
4130 26 Sep 16 nicklas 29    * Files that must be transmitted to the cluster before the job can be executed
4297 13 Jan 17 nicklas 30    * A BASE job item that acts as a proxy for the job. This is optional but without it 
4297 13 Jan 17 nicklas 31      the job will not be managed by this extension.
4130 26 Sep 16 nicklas 32   
4130 26 Sep 16 nicklas 33   @author nicklas
4130 26 Sep 16 nicklas 34   @since 1.0
4130 26 Sep 16 nicklas 35 */
4130 26 Sep 16 nicklas 36 public class JobDefinition 
4130 26 Sep 16 nicklas 37 {
4130 26 Sep 16 nicklas 38
6660 01 Apr 22 nicklas 39   // For generating unique names
6825 31 Aug 22 nicklas 40   private static final DateFormatter DF = new DateFormatter("yyMMdd-HHmm");
6660 01 Apr 22 nicklas 41   private static final AtomicInteger COUNTER = new AtomicInteger(0);
6660 01 Apr 22 nicklas 42   
4130 26 Sep 16 nicklas 43   private final String name;
4234 11 Nov 16 nicklas 44   private final JobConfig config;
6672 11 Apr 22 nicklas 45   private final BatchConfig batchConfig;
4203 02 Nov 16 nicklas 46   private final Job baseJob;
4130 26 Sep 16 nicklas 47   private String cmd;
4270 16 Dec 16 nicklas 48   private boolean debug;
4130 26 Sep 16 nicklas 49   private final List<UploadSourceWithPermission> filesToUpload;
4229 10 Nov 16 nicklas 50   
4203 02 Nov 16 nicklas 51   
4130 26 Sep 16 nicklas 52   /**
4203 02 Nov 16 nicklas 53     Create a new job definition that is not connected to a
4203 02 Nov 16 nicklas 54     BASE job item. The given prefix is combined 
4130 26 Sep 16 nicklas 55     with a random UUID to create a unique name for the job.
4203 02 Nov 16 nicklas 56   
4130 26 Sep 16 nicklas 57     @param namePrefix A prefix for the job name. Checked with 
4130 26 Sep 16 nicklas 58       {@link OpenGrid#checkValidFilename(String)}
4130 26 Sep 16 nicklas 59   */
4234 11 Nov 16 nicklas 60   public JobDefinition(String namePrefix, JobConfig config)
4130 26 Sep 16 nicklas 61   {
6672 11 Apr 22 nicklas 62     this(namePrefix, config, null, null);
4203 02 Nov 16 nicklas 63   }
4203 02 Nov 16 nicklas 64
4203 02 Nov 16 nicklas 65   /**
4203 02 Nov 16 nicklas 66     Create a new job definition that is connected to a BASE job.
4203 02 Nov 16 nicklas 67     The given prefix is combined with a random UUID to create a 
4203 02 Nov 16 nicklas 68     unique name for the job.
4203 02 Nov 16 nicklas 69
4203 02 Nov 16 nicklas 70     @param namePrefix A prefix for the job name. Checked with 
4203 02 Nov 16 nicklas 71       {@link OpenGrid#checkValidFilename(String)}
4301 13 Jan 17 nicklas 72     @param config Configuration settings for the job, or null
4234 11 Nov 16 nicklas 73       to use {@link JobConfig#DEFAULT}
4234 11 Nov 16 nicklas 74     @param baseJob Optional BASE {@link Job} item that is a
4234 11 Nov 16 nicklas 75       representation of the job on the cluster
4203 02 Nov 16 nicklas 76   */
4234 11 Nov 16 nicklas 77   public JobDefinition(String namePrefix, JobConfig config, Job baseJob)
4203 02 Nov 16 nicklas 78   {
6672 11 Apr 22 nicklas 79     this(namePrefix, config, null, baseJob);
6672 11 Apr 22 nicklas 80   }
6672 11 Apr 22 nicklas 81   
6672 11 Apr 22 nicklas 82   /**
6672 11 Apr 22 nicklas 83     Create a job definition with a batch configuration that overrides the
6672 11 Apr 22 nicklas 84     default job configuration.
6672 11 Apr 22 nicklas 85     @param batchConfig A batch configuration, if null the {@link JobConfig#getBatchConfig()}
6672 11 Apr 22 nicklas 86       is used
6672 11 Apr 22 nicklas 87     @since 1.5
6672 11 Apr 22 nicklas 88   */
6672 11 Apr 22 nicklas 89   public JobDefinition(String namePrefix, JobConfig config, BatchConfig batchConfig, Job baseJob)
6672 11 Apr 22 nicklas 90   {
4234 11 Nov 16 nicklas 91     this.config = config == null ? JobConfig.DEFAULT : config.lock();
6687 21 Apr 22 nicklas 92     this.batchConfig = batchConfig == null ? this.config.getBatchConfig() : batchConfig;
4130 26 Sep 16 nicklas 93     this.filesToUpload = new ArrayList<>();
6660 01 Apr 22 nicklas 94     // Name is prefix+current date/time+counter+random string
6660 01 Apr 22 nicklas 95     this.name = OpenGrid.checkValidFilename(namePrefix) +
6660 01 Apr 22 nicklas 96       "-" + DF.format(new Date()) +
6660 01 Apr 22 nicklas 97       "-" + MD5.leftPad(Integer.toString(COUNTER.addAndGet(1)), '0', 4) +
6660 01 Apr 22 nicklas 98       "-" + Application.generateRandomId(3);
4203 02 Nov 16 nicklas 99     this.baseJob = baseJob;
4130 26 Sep 16 nicklas 100   }
6672 11 Apr 22 nicklas 101
4130 26 Sep 16 nicklas 102   
4130 26 Sep 16 nicklas 103   /**
4130 26 Sep 16 nicklas 104     Get the name of this job definition.
4130 26 Sep 16 nicklas 105   */
4130 26 Sep 16 nicklas 106   public String getName()
4130 26 Sep 16 nicklas 107   {
4130 26 Sep 16 nicklas 108     return name;
4130 26 Sep 16 nicklas 109   }
4130 26 Sep 16 nicklas 110   
4130 26 Sep 16 nicklas 111   /**
4234 11 Nov 16 nicklas 112     Get the configuration settings for this job.
4234 11 Nov 16 nicklas 113   */
4234 11 Nov 16 nicklas 114   public JobConfig getConfig()
4234 11 Nov 16 nicklas 115   {
4234 11 Nov 16 nicklas 116     return config;
4234 11 Nov 16 nicklas 117   }
4234 11 Nov 16 nicklas 118   
4234 11 Nov 16 nicklas 119   /**
6672 11 Apr 22 nicklas 120     Get the batch configuration settings.
6672 11 Apr 22 nicklas 121     @since 1.5
6672 11 Apr 22 nicklas 122   */
6672 11 Apr 22 nicklas 123   public BatchConfig getBatchConfig()
6672 11 Apr 22 nicklas 124   {
6672 11 Apr 22 nicklas 125     return batchConfig;
6672 11 Apr 22 nicklas 126   }
6672 11 Apr 22 nicklas 127   
6672 11 Apr 22 nicklas 128   /**
4203 02 Nov 16 nicklas 129     Get the BASE job that this job definition is connected with.
4203 02 Nov 16 nicklas 130     @return A BASE Job item or null if not connected to a a job
4203 02 Nov 16 nicklas 131   */
4203 02 Nov 16 nicklas 132   public Job getBaseJob()
4203 02 Nov 16 nicklas 133   {
4203 02 Nov 16 nicklas 134     return baseJob;
4203 02 Nov 16 nicklas 135   }
4203 02 Nov 16 nicklas 136   
4203 02 Nov 16 nicklas 137   /**
4130 26 Sep 16 nicklas 138     Set the command/bash script to execute as part of this job.
4130 26 Sep 16 nicklas 139   */
4130 26 Sep 16 nicklas 140   public void setCmd(String cmd)
4130 26 Sep 16 nicklas 141   {
4130 26 Sep 16 nicklas 142     this.cmd = cmd;
4130 26 Sep 16 nicklas 143   }
4130 26 Sep 16 nicklas 144   public String getCmd()
4130 26 Sep 16 nicklas 145   {
4130 26 Sep 16 nicklas 146     return cmd;
4130 26 Sep 16 nicklas 147   }
4130 26 Sep 16 nicklas 148
4130 26 Sep 16 nicklas 149   /**
4270 16 Dec 16 nicklas 150     Set the debug flag. This affectes which temporary working folder
4270 16 Dec 16 nicklas 151     to use and if it should automatically be deleted after a job has
4270 16 Dec 16 nicklas 152     been completed or not.
4301 13 Jan 17 nicklas 153     @see ClusterConfig#getTmpFolder(boolean)
4270 16 Dec 16 nicklas 154   */
4270 16 Dec 16 nicklas 155   public void setDebug(boolean debug)
4270 16 Dec 16 nicklas 156   {
4270 16 Dec 16 nicklas 157     this.debug = debug;
4270 16 Dec 16 nicklas 158   }
4270 16 Dec 16 nicklas 159   public boolean getDebug()
4270 16 Dec 16 nicklas 160   {
4270 16 Dec 16 nicklas 161     return debug;
4270 16 Dec 16 nicklas 162   }
4270 16 Dec 16 nicklas 163   
4270 16 Dec 16 nicklas 164   /**
4130 26 Sep 16 nicklas 165     @see #addFile(UploadSource, FilePermission)
4130 26 Sep 16 nicklas 166   */
4130 26 Sep 16 nicklas 167   public void addFile(UploadSource file)
4130 26 Sep 16 nicklas 168   {
4130 26 Sep 16 nicklas 169     addFile(file, null);
4130 26 Sep 16 nicklas 170   }
4130 26 Sep 16 nicklas 171
4130 26 Sep 16 nicklas 172   /**
4130 26 Sep 16 nicklas 173     Register a file that should be uploaded to the cluster as part
4130 26 Sep 16 nicklas 174     of this job. The file will be stored in the working directory of 
4130 26 Sep 16 nicklas 175     the job under the name {@link UploadSource#getName()}. The actual
4130 26 Sep 16 nicklas 176     upload of the file is done as part of registering the job with
4301 13 Jan 17 nicklas 177     an Open Grid cluster. See {@link OpenGridSession#qsub(DbControl, List)}.
4130 26 Sep 16 nicklas 178     @param file The file to upload
4130 26 Sep 16 nicklas 179     @param permission The permission to give to the file 
4130 26 Sep 16 nicklas 180       ({@link FilePermission#USER_RW} is used as default)
4130 26 Sep 16 nicklas 181   */
4130 26 Sep 16 nicklas 182   public void addFile(UploadSource file, FilePermission permission)
4130 26 Sep 16 nicklas 183   {
4130 26 Sep 16 nicklas 184     filesToUpload.add(new UploadSourceWithPermission(file, permission));
4130 26 Sep 16 nicklas 185   }
4130 26 Sep 16 nicklas 186   
4130 26 Sep 16 nicklas 187   /**
4130 26 Sep 16 nicklas 188     Get all files that should be uploaded to the cluster as part
4130 26 Sep 16 nicklas 189     of this job.
4130 26 Sep 16 nicklas 190   */
4130 26 Sep 16 nicklas 191   public List<UploadSourceWithPermission> getFiles()
4130 26 Sep 16 nicklas 192   {
4130 26 Sep 16 nicklas 193     return filesToUpload;
4130 26 Sep 16 nicklas 194   }
4130 26 Sep 16 nicklas 195
4130 26 Sep 16 nicklas 196   /**
4130 26 Sep 16 nicklas 197     Generate a script for this job that fits what
4130 26 Sep 16 nicklas 198     'qsub' expects.
5982 07 Jul 20 nicklas 199     @deprecated In 1.4, use {@link OpenGridEngine#createQsubScript(JobDefinition, String, String)} instead
4130 26 Sep 16 nicklas 200   */
5982 07 Jul 20 nicklas 201   @Deprecated
4270 16 Dec 16 nicklas 202   public String asJobScript(String workFolder, String tmpFolder)
4130 26 Sep 16 nicklas 203   {
5982 07 Jul 20 nicklas 204     return new OpenGridEngine().createQsubScript(this, workFolder, tmpFolder);
4130 26 Sep 16 nicklas 205   }
4130 26 Sep 16 nicklas 206
4130 26 Sep 16 nicklas 207   /**
4130 26 Sep 16 nicklas 208     Class for storing a file and a permission as one
4130 26 Sep 16 nicklas 209     entity. If no permission is specified, the default
6627 07 Mar 22 nicklas 210     is to use {@link FilePermission#USER_RW}. If the
6627 07 Mar 22 nicklas 211     uploaded file name ends with '.sh' the default is 
6627 07 Mar 22 nicklas 212     {@link FilePermission#USER_RWX}.
4130 26 Sep 16 nicklas 213   */
4130 26 Sep 16 nicklas 214   public static class UploadSourceWithPermission
4130 26 Sep 16 nicklas 215   {
4130 26 Sep 16 nicklas 216     
6666 05 Apr 22 nicklas 217     /**
6666 05 Apr 22 nicklas 218       File endings that should automatially be executable when uploaded.
6666 05 Apr 22 nicklas 219     */
6666 05 Apr 22 nicklas 220     public static Set<String> EXECUTABLE_FILES = Collections.unmodifiableSet(
6666 05 Apr 22 nicklas 221       new HashSet<>(Arrays.asList( new String[] { ".sh", ".pl", ".awk", ".py", ".R" } )));
6666 05 Apr 22 nicklas 222     
6666 05 Apr 22 nicklas 223     public static boolean isExecutable(String fileName)
6666 05 Apr 22 nicklas 224     {
6666 05 Apr 22 nicklas 225       int i = fileName.lastIndexOf('.');
6666 05 Apr 22 nicklas 226       return i >= 0 ? EXECUTABLE_FILES.contains(fileName.substring(i)) : false;
6666 05 Apr 22 nicklas 227     }
6666 05 Apr 22 nicklas 228     
4130 26 Sep 16 nicklas 229     private final UploadSource upload;
4130 26 Sep 16 nicklas 230     private final FilePermission permission;
4130 26 Sep 16 nicklas 231     
4130 26 Sep 16 nicklas 232     UploadSourceWithPermission(UploadSource upload, FilePermission permission)
4130 26 Sep 16 nicklas 233     {
4130 26 Sep 16 nicklas 234       this.upload = upload;
6666 05 Apr 22 nicklas 235       this.permission = permission == null ? (isExecutable(upload.getName()) ? FilePermission.USER_RWX : FilePermission.USER_RW) : permission;
4130 26 Sep 16 nicklas 236     }
4130 26 Sep 16 nicklas 237     
4130 26 Sep 16 nicklas 238     public UploadSource getUploadSource()
4130 26 Sep 16 nicklas 239     {
4130 26 Sep 16 nicklas 240       return upload;
4130 26 Sep 16 nicklas 241     }
4130 26 Sep 16 nicklas 242     
4130 26 Sep 16 nicklas 243     public FilePermission getFilePermission()
4130 26 Sep 16 nicklas 244     {
4130 26 Sep 16 nicklas 245       return permission;
4130 26 Sep 16 nicklas 246     }
4130 26 Sep 16 nicklas 247   }
4130 26 Sep 16 nicklas 248   
4130 26 Sep 16 nicklas 249 }