001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.structure.align; 022 023import org.biojava.nbio.structure.align.client.FarmJobParameters; 024import org.biojava.nbio.structure.align.client.FarmJobRunnable; 025import org.biojava.nbio.structure.align.events.AlignmentProgressListener; 026import org.biojava.nbio.structure.align.util.CliTools; 027import org.biojava.nbio.structure.align.util.ConfigurationException; 028import org.biojava.nbio.structure.align.util.UserConfiguration; 029import org.biojava.nbio.structure.scop.CachedRemoteScopInstallation; 030import org.biojava.nbio.structure.scop.ScopDatabase; 031import org.biojava.nbio.structure.scop.ScopFactory; 032import org.biojava.nbio.core.util.InputStreamProvider; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036import java.io.IOException; 037import java.util.ArrayList; 038import java.util.Arrays; 039import java.util.List; 040 041 042/** A job as it can be run on the farm. 043 * 044 * @author Andreas Prlic 045 * 046 * for arguments see the printHelp() method. 047 * 048 * 049 * 050 */ 051public class FarmJob implements Runnable { 052 053 private final static Logger logger = LoggerFactory.getLogger(FarmJob.class); 054 055 private static final String[] mandParams = new String[] {"pdbFilePath"}; 056 057 private static final List<String> mandatoryArgs= Arrays.asList(mandParams); 058 059 List<AlignmentProgressListener> progressListeners; 060 List<FarmJobRunnable> jobs; 061 062 FarmJobParameters params ; 063 064 public FarmJob(){ 065 progressListeners = null; 066 067 // send a flag to the PDb file loader to cache the gzip compressed files. 068 System.setProperty(InputStreamProvider.CACHE_PROPERTY, "true"); 069 070 071 } 072 073 public FarmJobParameters getParams() { 074 return params; 075 } 076 077 public void setParams(FarmJobParameters params) { 078 this.params = params; 079 } 080 081 public void addAlignmentProgressListener(AlignmentProgressListener listener){ 082 if (progressListeners == null) 083 progressListeners = new ArrayList<AlignmentProgressListener>(); 084 085 progressListeners.add(listener); 086 } 087 088 public void clearListeners(){ 089 progressListeners.clear(); 090 progressListeners = null; 091 } 092 093 public static void main(String[] argv){ 094 095 FarmJob job = new FarmJob(); 096 097 if (argv.length == 0 ) { 098 job.printHelp(); 099 return; 100 } 101 102 if ( argv.length == 1){ 103 if (argv[0].equalsIgnoreCase("-h") || argv[0].equalsIgnoreCase("-help")|| argv[0].equalsIgnoreCase("--help")){ 104 job.printHelp(); 105 return; 106 } 107 } 108 109 FarmJobParameters params = new FarmJobParameters(); 110 111 for (int i = 0 ; i < argv.length; i++){ 112 String arg = argv[i]; 113 114 String value = null; 115 if ( i < argv.length -1) 116 value = argv[i+1]; 117 118 // if value starts with - then the arg does not have a value. 119 if (value != null && value.startsWith("-")) 120 value = null; 121 else 122 i++; 123 124 125 String[] tmp = {arg,value}; 126 127 try { 128 129 CliTools.configureBean(params, tmp); 130 131 } catch (ConfigurationException e){ 132 133 logger.error("Exception", e); 134 135 if ( mandatoryArgs.contains(arg) ) { 136 // there must not be a ConfigurationException with mandatory arguments. 137 return; 138 } else { 139 // but there can be with optional ... 140 } 141 } 142 } 143 144 145 if (( params.getNrAlignments() == -1) && (params.getTime() == -1)){ 146 logger.error("Please provide either the -time or the -nrAlignments argument!"); 147 return; 148 } 149 150 151 logger.info("Using parameters: {}", params); 152 153 job.setParams(params); 154 job.run(); 155 156 } 157 158 @Override 159 public void run(){ 160 161 162 // set the system wide PDB path 163 164 String path = params.getPdbFilePath(); 165 System.setProperty(UserConfiguration.PDB_DIR,path); 166 167 String cachePath = params.getCacheFilePath(); 168 if ( cachePath != null && ! cachePath.equals("")) 169 System.setProperty(UserConfiguration.PDB_CACHE_DIR,cachePath); 170 else { 171 // if not provided, we use pdbFilePath as the default CACHE path 172 System.setProperty(UserConfiguration.PDB_CACHE_DIR,path); 173 } 174 // declare SCOP to be locally cached, but fetching new stuff from remote 175 ScopDatabase scop = null; 176 try { 177 scop = new CachedRemoteScopInstallation(true); 178 } catch (IOException e) { 179 throw new RuntimeException("Could not load " + CachedRemoteScopInstallation.class.getName(), e); 180 } 181 ScopFactory.setScopDatabase(scop); 182 183 String username = params.getUsername(); 184 jobs = new ArrayList<FarmJobRunnable>(); 185 for ( int i = 0 ; i < params.getThreads();i++){ 186 logger.info("starting thread #{}", (i+1)); 187 FarmJobRunnable runner = new FarmJobRunnable(params); 188 params.setUsername(username+"_thread_" + (i+1)); 189 jobs.add(runner); 190 191 if ( progressListeners != null) { 192 for (AlignmentProgressListener li : progressListeners){ 193 runner.addAlignmentProgressListener(li); 194 } 195 } 196 197 198 Thread t = new Thread(runner); 199 if ( ( (params.getThreads() > 1 ) && ( i < params.getThreads() - 1) )|| ( params.isRunBackground())) { 200 logger.info("starting thread #{} in background.", (i + 1)); 201 t.start(); 202 } else { 203 // single CPU jobs are run in the main thread and the last job is also run in the main thread 204 logger.info("starting thread #{} in main thread.", (i + 1)); 205 t.run(); 206 } 207 } 208 } 209 210 public void terminate(){ 211 212 logger.info("terminating jobs"); 213 214 if ( jobs == null) 215 return; 216 217 int js = jobs.size(); 218 logger.info("number of jobs: {}", js); 219 220 221 for (FarmJobRunnable runner : jobs){ 222 // runner.terminate() is already synchronized 223 runner.terminate(); 224 } 225 226 clearListeners(); 227 } 228 229 public void printHelp(){ 230 System.out.println("-------------------"); 231 System.out.println("FarmJob help:"); 232 System.out.println("-------------------"); 233 234 System.out.println("FarmJob accepts the following parameters:"); 235 System.out.println(""); 236 System.out.println(" Mandatory:"); 237 System.out.println(" -pdbFilePath (mandatory) Path to the directory in your file system that contains the PDB files."); 238 239 System.out.println(" provide either -time or -nrAlignments. If both are provided the job stops as soon as any of the criteria has been reached."); 240 System.out.println(" -time maximum number of time to run (in seconds). -1 means no time limit, but run -nrAlignment arguments. Default: " + FarmJobParameters.DEFAULT_JOB_TIME ); 241 System.out.println(" -nrAlignments number of alignments to calculate. Default: " + FarmJobParameters.DEFAULT_NR_ALIGNMENTS) ; 242 System.out.println(""); 243 System.out.println(" Optional: "); 244 System.out.println(" -threads number of parallel threads to calculate alignments. Should be nr. of available CPUs. Default: " + FarmJobParameters.DEFAULT_NR_THREADS); 245 System.out.println(" -server the location of the server URL to talk to. Default : " + FarmJobParameters.DEFAULT_SERVER_URL); 246 System.out.println(" -username a unique name that can be given to this client. Can be used to give credit for who is doing the calculations. Default: IP and a random id"); 247 System.out.println(" -stepSize the number of pairs to be requsted from server. Default: " + FarmJobParameters.DEFAULT_BATCH_SIZE); 248 } 249}