This repository has been archived by the owner on Mar 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 55
/
JobLauncher.java
1973 lines (1768 loc) · 59.9 KB
/
JobLauncher.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*******************************************************************************
* Copyright (c) 2013, 2014 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Initial API and implementation and/or initial documentation - Jay Jay Billings,
* Jordan H. Deyton, Dasha Gorin, Alexander J. McCaskey, Taylor Patterson,
* Claire Saunders, Matthew Wang, Anna Wojtowicz
*******************************************************************************/
package org.eclipse.ice.item.jobLauncher;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.eclipse.ice.datastructures.ICEObject.ICEJAXBHandler;
import org.eclipse.ice.datastructures.ICEObject.ICEObject;
import org.eclipse.ice.datastructures.form.TableComponent;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.ice.datastructures.form.DataComponent;
import org.eclipse.ice.datastructures.form.Entry;
import org.eclipse.ice.datastructures.form.FormStatus;
import org.eclipse.ice.datastructures.form.Form;
import org.eclipse.ice.datastructures.form.ResourceComponent;
import org.eclipse.ice.datastructures.resource.ICEResource;
import org.eclipse.ice.datastructures.ICEObject.IUpdateable;
import org.eclipse.ice.io.serializable.IReader;
import org.eclipse.ice.item.Item;
import org.eclipse.ice.item.ItemType;
import org.eclipse.ice.item.action.JobLaunchAction;
import org.eclipse.ice.item.jobLauncher.JobLauncherForm;
import org.eclipse.ice.item.utilities.moose.MOOSEFileHandler;
/**
* <!-- begin-UML-doc -->
* <p>
* The JobLauncher class handles local and remote job launch of simulations and
* other tasks. It implements process(), reviewEntries() and setupForm().
* Subclasses must override setupForm(), call super.setupForm() to properly
* construct the Form and JobLauncher Item and call setExecutable() with the
* executable name, description and command name. It uses a LocalExecutorAction
* or a RemoteExecutorAction, depending on whether or not the job should be
* launched locally or remotely. If the job is launched remotely, the
* JobLauncher may need to request additional information for a username and
* password, (possibly even a keyboard-interactive password).
* </p>
* <p>
* The platforms on which the job can be launched must be configured with the
* addHost() operation.
* </p>
* <p>
* It is possible to direct the JobLauncher to enable support for parallelism
* via TBB, OpenMP and MPI. This will only work so long as MPI is installed on
* the remote system and available on the user's PATH and if the executable is
* compiled with MPI, TBB and/or OpenMP support. It is possible to enable MPI,
* TBB and/or OpenMP support at the same time.
* </p>
* <p>
* The JobLauncher gets its input information from the DataComponent on the
* JobLauncherForm and it places ICEResources that represent its output on the
* ResourceComponent on the JobLauncherForm.
* </p>
* <p>
* The setExecutable() operation uses string replacement to replace a select
* number of flags in the executable string. See that operation for details. The
* flags are:
* </p>
* <p>
* ${installDir} - The installation directory of the executable on the current
* host.
* </p>
* <p>
* ${inputFile} - The input file for the job.
* </p>
* <p>
* These flags can be inserted as part of the executable name and the
* JobLauncher will automatically replace them for the appropriate host so long
* as they are provided. By defeault the JobLauncher appends the name of the
* input file to the end of the executable string. This option can be disabled
* by calling setAppendInputFlag.
* </p>
* <p>
* The setExecutable() operation should not be called with MPI, OpenMP or Intel
* TBB directives as part of the executable. If it is, the JobLauncher will not
* attempt consider the launch command as hard-wired and it will not try to
* change the number of cores or threads. It will still perform any string
* replacement that may be required for any included flags.
* </p>
* <p>
* JobLaunchers expect that there will always be at least one input file and
* always configures itself to require at least one file. Some situations may
* require multiple types of input files. For example, a particular simulator
* may require run time parameters, a 3d mesh and materials information in one
* file and another simulator may expect three separate files for this
* information. The two additional input file types can be added to the job
* launcher by calling the addInputType() operation.
* </p>
* <!-- end-UML-doc -->
*
* @author Jay Jay Billings
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlRootElement(name = "JobLauncher")
public class JobLauncher extends Item {
/**
* <!-- begin-UML-doc -->
* <p>
* The name of the executable command that should be launched. This is
* different than the proper name of the executable. For example, the name
* of a popular Linux text editor is Vi Improved, but its executable command
* name is vim. In order to use JPA on this object, there is a string limit
* of 1000 characters.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlAttribute()
private String executableCommandName;
/**
* <!-- begin-UML-doc -->
* <p>
* The table of hosts on which the job can be launched. The table's columns
* are the hostname, the operating system and the installation directory of
* the executable on that platform. In order to use JPA on this object,
* there is a string limit of 1000 characters.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlElement(name = "TableComponent")
private TableComponent hostsTable;
/**
* <!-- begin-UML-doc -->
* <p>
* True if the job should be launched with MPI, false otherwise and by
* default.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlAttribute()
private boolean mpiEnabled = false;
/**
* <!-- begin-UML-doc -->
* <p>
* True if the job should be launched OpenMP, false otherwise and by
* default.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlAttribute
private boolean openMPEnabled = false;
/**
* True if the launcher should append the name of the input file to the
* launch command, false otherwise.
*/
@XmlAttribute
private boolean appendInput;
/**
* True if the launcher should upload input file(s) to a remote machine,
* otherwise false. Setting this flag to false will still allow the
*/
@XmlAttribute
private boolean uploadInput;
/**
* <!-- begin-UML-doc -->
* <p>
* The set of hosts available for the job. In order to use JPA on this
* object, there is a string limit of 1000 characters.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlElement
private ArrayList<String> hosts;
/**
* <!-- begin-UML-doc -->
* <p>
* The list of input files from which a client may select for the job.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlElement
private ArrayList<String> inputFiles;
/**
* <!-- begin-UML-doc -->
* <p>
* True if the job should be launched with Intel's Thread Building Blocks
* (TBB), false otherwise and by default.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlAttribute
private boolean tbbEnabled = false;
/**
* <!-- begin-UML-doc -->
* <p>
* The directory on the remote machine from which files should be
* downloaded.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
@XmlTransient()
private String remoteDownloadDir;
/**
* A map for storing key-value pairs needed by the actions.
*/
@XmlTransient()
private Dictionary<String, String> actionDataMap;
/**
* The set of resources stored in the JobLauncher's working directory, and
* their last modification time. It may be different than what is returned by
* IResource.getModificationTime(), which is exactly why we are tracking it.
*/
@XmlTransient()
private HashMap<IResource, Long> workingDirMemberModMap;
/**
* This is a utility class used to describe a type of file by the
* JobLauncher.
*
* @author Jay Jay Billings
*/
private static class FileType {
/**
* The name of the input file type. ("Input" or "Host configuration" or
* "Materials information" for example)
*/
public String name = "";
/**
* The name that will be used to refer to this input file when it is
* referred to by a variable in, for example, the executable string that
* is used by the JobLauncher. This name must end with the word "file"
* and, by convention, it should not contain white space or special
* symbols. If it does not end with the word "file," the JobLauncher
* will attempt to add it. This parameter may not be null.
*/
public String varName = "";
/**
* A short description of the input file.
*/
public String desc = "";
/**
* The file type extension that should be used to filter files from the
* project space for this input. If this parameter is null, then it will
* ignored.
*/
public String typeExt = "";
};
/**
* A map for storing the names of input files and their file types
*/
@XmlTransient()
protected HashMap<String, FileType> inputFileNameMap;
/**
* <!-- begin-UML-doc -->
* <p>
* This operation is used to set the executable name, description and
* command name for the job that should be launched. It may contain one of
* two flags that will be replaced by string replacement before launch:
* ${inputFile} and ${installDir}. The ${inputFile} flag will be replaced
* with the name of the input file that should be used during the launch and
* the ${installDir} flag will be replaced with the installation directory
* of the executable for the given host as configured with the addHost()
* operation. If the ${inputFile} flag is used, the JobLauncher will set
* inputFile=none in the dictionary used by the RemoteExecutorAction.
* </p>
* <p>
* Set executable should only be called once.
* </p>
* <!-- end-UML-doc -->
*
* @param execName
* <p>
* The proper and full name of the job that will be launched
* (e.g. - Microsoft Word). The JobLauncher class appends
* " Launcher" to this name.
* </p>
* @param execDesc
* <p>
* The description of the executable.
* </p>
* @param execCommand
* <p>
* The name of the executable command that should be launched.
* This is different than the proper name of the executable. For
* example, the name of a popular Linux text editor is Vi
* Improved, but its executable command name is vim.
* </p>
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
public void setExecutable(String execName, String execDesc,
String execCommand) {
// begin-user-code
// Set the executable command name
executableCommandName = execCommand;
// Set the name of the Form
String nameAppend = execName.contains("Launcher") ? "" : " Launcher";
form.setName(execName + nameAppend);
// Set the Form description
form.setDescription(execDesc);
// end-user-code
}
/**
* <!-- begin-UML-doc -->
* <p>
* The constructor with a project space in which files should be
* manipulated.
* </p>
* <!-- end-UML-doc -->
*
* @param projectSpace
* <p>
* The Eclipse project where files should be stored and from
* which they should be retrieved.
* </p>
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
public JobLauncher(IProject projectSpace) {
// begin-user-code
// Call the Item constructor
super(projectSpace);
// Setup the resource list
workingDirMemberModMap = new HashMap<IResource, Long>();
// end-user-code
}
/**
* <!-- begin-UML-doc -->
* <p>
* This is a private operation used by JobLauncher.process() to create the
* standard output and standard error output files in the project directory.
* It also adds the paths of these files to the map. It should only be
* called by JobLauncher.process() because it is solely a utility function
* for code cleanliness.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
private void createOutputFiles() {
// begin-user-code
// Local Declarations
ResourceComponent outputData = (ResourceComponent) form
.getComponent(JobLauncherForm.outputId);
String stdOutHeader, stdErrHeader, stdOutFileName, stdErrFileName;
// Setup the headers
stdOutHeader = createOutputHeader("standard output");
stdErrHeader = createOutputHeader("standard error");
// Setup the file names
stdOutFileName = form.getName().replaceAll("\\s+", "_") + "_stdout_"
+ getId() + ".txt";
stdErrFileName = form.getName().replaceAll("\\s+", "_") + "_stderr_"
+ getId() + ".txt";
// Create the stdout file in the project space
if (project != null) {
// Create the Eclipse Resources IFile handle for standard out
IFile stdOutProjectFile = project.getFile(stdOutFileName);
// Create the Eclipse Resources IFile handle for standard error
IFile stdErrProjectFile = project.getFile(stdErrFileName);
// Create the standard out project file
try {
// Delete the file if it already exists - we want a clean one
if (stdOutProjectFile.exists()) {
stdOutProjectFile.delete(true, null);
}
// Create the managed file - creation closes the input
// stream
stdOutProjectFile.create(
new ByteArrayInputStream(stdOutHeader.getBytes()),
false, null);
} catch (CoreException e) {
// Complain
e.printStackTrace();
}
// Create the standard error project file
try {
// Delete the file if it already exists - we want a clean one
if (stdErrProjectFile.exists()) {
stdErrProjectFile.delete(true, null);
}
// Create the managed file - creation closes the input
// stream
stdErrProjectFile.create(
new ByteArrayInputStream(stdErrHeader.getBytes()),
false, null);
} catch (CoreException e) {
// Complain
e.printStackTrace();
}
// Put the paths to the standard error and out files into the map.
// Note that the toOSSString() operation returns the file path with
// the proper file separators ("/" vs. "\") added.
actionDataMap.put("stdOutFileName", stdOutProjectFile.getLocation()
.toOSString());
actionDataMap.put("stdErrFileName", stdErrProjectFile.getLocation()
.toOSString());
System.out.println("JobLauncher Message: File paths: "
+ "\n\tStandard Out File = "
+ actionDataMap.get("stdOutFileName")
+ "\n\tStandard Error File = "
+ actionDataMap.get("stdErrFileName"));
try {
// Add the output files to the resource component
addOutputFile(1, stdOutProjectFile, "Standard Output",
outputData);
addOutputFile(2, stdErrProjectFile, "Standard Error Output",
outputData);
// Grab the current list of project members that are managed for
// this item.
IResource[] members = project.members();
for (int i = 0; i < members.length; i++) {
// Add the resource and its modification time stamp to the
// list.
workingDirMemberModMap.put(members[i],
members[i].getModificationStamp());
}
} catch (CoreException | IOException e) {
e.printStackTrace();
}
}
return;
// end-user-code
}
/**
* This operation updates the contents of the resource component after a run
* so that it contains any files that were created during the processing
* action.
*/
protected void updateResourceComponent() {
// Local Declarations
int lastId;
long lastTimeStamp;
ResourceComponent resources =
(ResourceComponent) form.getComponent(2);
ArrayList<ICEResource> resourceList = resources.getResources();
ArrayList<String> resourceNames = new ArrayList<String>();
String fileName, workingDirName;
IFolder workingDir = null;
String separator = System.getProperty("file.separator");
try {
// Refresh the project space
project.refreshLocal(IResource.DEPTH_INFINITE, null);
// Get the list of members
String workingDirPath = getWorkingDirectory();
if (workingDirPath != null && !workingDirPath.isEmpty()) {
// Get the working directory name
int lastDir = workingDirPath.lastIndexOf(separator);
workingDirName = workingDirPath.substring(lastDir + 1);
workingDir =
project.getFolder("jobs" + separator + workingDirName);
}
IResource[] latestMembers = workingDir.members();
// Get the names of the current resources
for (ICEResource namedResource : resourceList) {
resourceNames.add(namedResource.getPath().toASCIIString());
}
// Get the last resource id. Kinda messy. Nothing doing though.
lastId = resources.getResources()
.get(resources.getResources().size() - 1).getId();
// Find the members that are new
for (int i = 0; i < latestMembers.length; i++) {
IResource currentResource = latestMembers[i];
if (!workingDirMemberModMap.keySet().contains(currentResource)) {
System.out.println("JobLauncher Message: " + "Adding file "
+ currentResource.getName() + " to list.");
// Get the file as an ICEResource object
ICEResource resource = getResource(
currentResource.getLocation().toOSString());
if (resource != null) {
// Set the name, ID, description
resource.setName(currentResource.getName());
resource.setId(lastId + i + 1);
resource.setDescription(currentResource.getName()
+ " from " + getName() + " " + getId());
// Add the resource to the ResourceComponent
resources.addResource(resource);
}
} else {
// If we already have the file, get it.
lastTimeStamp = workingDirMemberModMap.get(currentResource);
// Get its file full file name
fileName = currentResource.getLocationURI().toASCIIString();
// Check the time stamp to see if it was modified AND make
// sure that the file is not already in the resource list.
if (lastTimeStamp != currentResource.getModificationStamp()
&& !resourceNames.contains(fileName)) {
System.out.println("JobLauncher Message: "
+ "Adding file " + currentResource.getName()
+ " to list.");
// Get the file as an ICEResource
ICEResource resource = getResource(
currentResource.getLocation().toOSString());
if (resource != null) {
// Set the name, ID, description
resource.setName(currentResource.getName());
resource.setId(lastId + i + 1);
resource.setDescription(currentResource.getName()
+ " from " + getName() + " " + getId());
// Add the resource to the ResourceComponent
resources.addResource(resource);
}
}
}
}
} catch (CoreException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* <!-- begin-UML-doc -->
* <p>
* This operation fills the data dictionary for the JobLaunchAction based on
* the contents of the Form.
* </p>
* <!-- end-UML-doc -->
*
* @return <p>
* The status of the operation. It will only equal
* FormStatus.ReadyToProcess or FormStatus.InfoError and should
* cause the calling operation to fail if the latter is returned.
* </p>
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
private FormStatus fillActionDataMap() {
// begin-user-code
// Local Declarations
String filename = null, hostname = null;
String installDir = ".";
IResource fileResource = null;
String os = "linux", accountCode = "";
DataComponent fileData = null, parallelData = null;
Entry fileEntry = null, mpiEntry = null;
int numProcs = 1, numTBBThreads = 1;
// Get the project space directory
String projectSpace = project.getLocation().toOSString();
// Assign the data components
fileData = (DataComponent) form.getComponent(JobLauncherForm.filesId);
parallelData = (DataComponent) form
.getComponent(JobLauncherForm.parallelId);
// Check the components and fail if they are null
if (fileData == null) {
return FormStatus.InfoError;
} else {
// Make sure if there are any additional input files, that they are
// all valid too
for (Entry entry : fileData.retrieveAllEntries()) {
if (entry.getValue() == null || entry.getValue().isEmpty()) {
System.out.println("JobLauncher Error: All input file "
+ "entries must be set!");
return FormStatus.InfoError;
}
}
}
// Allocate the map
actionDataMap = new Hashtable<String, String>();
// Write the file name for debug info
for (String entryName : inputFileNameMap.keySet()) {
fileEntry = fileData.retrieveEntry(entryName);
if (fileEntry != null) {
// Get the IResource for the file
fileResource = project.findMember(fileEntry.getValue());
// Make sure the file exists
if (fileResource == null || !fileResource.exists()) {
System.out.println("JobLauncher Message: Base filename = "
+ filename);
System.out
.println("JobLauncher Message: Allowed file names = "
+ fileEntry.getAllowedValues());
return FormStatus.InfoError;
}
// Get the full filename
filename = fileResource.getLocation().toOSString();
actionDataMap.put(inputFileNameMap.get(entryName).varName,
filename);
} else {
System.out.println("File not found in Form: " + entryName);
}
}
// Get the hostname and OS by identifying the host in the table. Start
// by getting the selected row ids from the host table.
ArrayList<Integer> selectedRowIds = hostsTable.getSelectedRows();
// Default to the first row
int selectedRowId = 1;
// If there were rows selected, set the hostname from the first
// *selected* row. Default to the first row.
selectedRowId = 0; // FIXME! Row id should be > 0! This is a known
// issue.
if (selectedRowIds != null) {
selectedRowId = selectedRowIds.get(0);
}
// Get the hostname and os
ArrayList<Entry> hostEntries = hostsTable.getRow(selectedRowId);
hostname = hostEntries.get(0).getValue();
os = hostEntries.get(1).getValue();
installDir = hostEntries.get(2).getValue();
// Could put the queue type in the map here
// Get the parallel launch parameters from the form
if (parallelData != null) {
// Figure out whether or not MPI should be used. Get the MPI Entry
// first.
mpiEntry = parallelData.retrieveEntry("Number of MPI Processes");
// Get the number of cores if the Entry is there
if (mpiEntry != null) {
numProcs = Math.max(numProcs,
Integer.parseInt(mpiEntry.getValue()));
}
// Figure out whether or not TBB threads should be used.
Entry tbbThreadsEntry = parallelData
.retrieveEntry("Number of TBB Threads");
// Get the number of cores if the Entry is there
if (tbbThreadsEntry != null) {
numTBBThreads = Math.max(numTBBThreads,
Integer.parseInt(tbbThreadsEntry.getValue()));
}
// Get the account code
Entry accountEntry = parallelData
.retrieveEntry("Account Code/Project Code");
accountCode = accountEntry.getValue();
}
// Load the dictionary with the remaining parameters. Make sure to put
// the set the noAppendInputFlag in there depending on whether or not
// the execution string has been modified! (c.f.-
// JobLaunchAction docs)
actionDataMap.put("executable", executableCommandName);
actionDataMap.put("uploadInput", String.valueOf(uploadInput));
// Note: "no append" is reversed logic from "append". ICE also checks
// the command name to determine it too.
if (appendInput && !executableCommandName.contains("${inputFile}")) {
actionDataMap.put("noAppendInput", "false");
} else {
actionDataMap.put("noAppendInput", "true");
}
actionDataMap.put("installDir", installDir);
actionDataMap.put("hostname", hostname);
actionDataMap.put("os", os);
actionDataMap.put("accountCode", accountCode);
actionDataMap.put("projectSpaceDir", projectSpace);
// Add the number of processors to the action data dictionary. It will
// always be at least 1.
actionDataMap.put("numProcs", String.valueOf(numProcs));
actionDataMap.put("numTBBThreads", String.valueOf(numTBBThreads));
// Set the download directory if possible
if (remoteDownloadDir != null) {
actionDataMap.put("downloadDirectory", remoteDownloadDir);
}
// Dump the action map if debugging is enabled
if (debuggingEnabled) {
System.out.println("JobLauncher Message: " + "Action Data Map = "
+ actionDataMap);
}
return FormStatus.ReadyToProcess;
// end-user-code
}
/**
* This operation adds an output file to the output data resource. It is a
* utility function used primarily by createOutputFiles().
*
* @param resourceId
* The id of the ICEResource in the ResourceComponent
* @param file
* The IFile that will store the data.
* @param resourceName
* A short descriptive name of the resource. It will be appended
* to the name of the Form.
* @param outputComp
* The ResourceComponent that contains the data.
* @throws IOException
*/
private void addOutputFile(int resourceId, IFile file, String resourceName,
ResourceComponent outputComp) throws IOException {
// Get the file as an ICEResource (returns null if invalid filepath)
ICEResource outputResource =
this.getResource(file.getLocation().toOSString());
// If the filepath corresponded to a valid resource, we add it to the
// ResourceComponent
if (outputResource != null) {
System.out.println("Resource location = "
+ file.getFullPath().toString());
// Set the properties
outputResource.setName(form.getName() + " " + resourceName);
outputResource.setId(resourceId);
outputResource.setDescription(resourceName + " from the job.");
// Add the ICEResource to the Output component
outputComp.addResource(outputResource);
}
return;
}
/**
* This operation creates a standard header that contains information about
* the job being launched. It is used primarily by the createOutputFiles()
* operation.
*
* @param logName
* The name that should be used to identify the log in its
* header.
* @return The header.
*/
private String createOutputHeader(String logName) {
// Local Declarations
String header = null;
// Get the identity of this machine as the point of origin for the job
// launch
try {
// Get the address of localhost
InetAddress addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
// Identify the log
header = "# Log of " + logName + " collected by ICE for " + getName()
+ " " + getId() + "\n";
return header;
}
/**
* <!-- begin-UML-doc -->
* <p>
* This operation sets up the JobLauncherForm.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
protected void setupForm() {
// begin-user-code
ArrayList<Entry> columnNames = new ArrayList<Entry>();
Entry entry1 = new Entry();
Entry entry2 = new Entry();
Entry entry3 = new Entry();
// Initialize the host and input lists
hosts = new ArrayList<String>();
inputFiles = new ArrayList<String>();
inputFileNameMap = new HashMap<String, FileType>();
// Set the Item Type
itemType = ItemType.Simulation;
// Setup TableComponent
hostsTable = new TableComponent();
hostsTable.setId(JobLauncherForm.parallelId + 1);
hostsTable.setName("Hosts");
hostsTable.setDescription("The available hosts for the job.");
// Setup the Entries that define the row template for the table
entry1.setName("Hostnames");
entry2.setName("Operating Systems");
entry3.setName("Execution Path");
// Add the Entries to the the array list of column names
columnNames.add(entry1);
columnNames.add(entry2);
columnNames.add(entry3);
// Set the row template
hostsTable.setRowTemplate(columnNames);
// Setup the list of actions
allowedActions = new ArrayList<String>();
allowedActions.add("Launch the Job");
// Create the JobLauncherForm
form = new JobLauncherForm();
form.setActionList(allowedActions);
// Add the generic input file type
String desc = "The input file that should be used in the launch.";
addInputType("Input File", "inputFile", desc, null);
appendInput = true;
uploadInput = true;
// Add the host table to the form
form.addComponent(hostsTable);
// Every JobLauncher should observe the Input File Entry
((DataComponent) form.getComponent(JobLauncherForm.filesId))
.retrieveEntry("Input File").register(this);
return;
// end-user-code
}
/**
* <!-- begin-UML-doc -->
* <p>
* This operation reviews the Entries in the JobLauncherForm to make sure
* that it can actually perform the launch.
* </p>
* <!-- end-UML-doc -->
*
* @param preparedForm
* <p>
* The Form to review.
* </p>
* @return <p>
* The status.
* </p>
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
protected FormStatus reviewEntries(Form preparedForm) {
// begin-user-code
// Local Declarations
FormStatus status = FormStatus.InfoError;
// Check the Form and reset the name
if (preparedForm != null) {
// Make sure the Forms are the same
if (form.getId() == preparedForm.getId()
&& form.getItemID() == preparedForm.getItemID()) {
// Check the hosts table
// FIXME
TableComponent updatedHostsTable = (TableComponent) form
.getComponent(JobLauncherForm.parallelId + 1);
if (updatedHostsTable.numberOfRows() > 0) {
// Update the hosts table
hostsTable = updatedHostsTable;
// Mark the Form as ready, update the Form and set the
// status.
preparedForm.markReady(true);
form = preparedForm;
status = FormStatus.ReadyToProcess;
} else if (debuggingEnabled) {
System.err.println("JobLauncher Message: "
+ "Found an empty hosts table "
+ "during entry review!");
}
} else if (debuggingEnabled) {
System.err.println("JobLauncher Message: "
+ "Invalid form id for submitted form during review!");
}
}
return status;
// end-user-code
}
/**
* <!-- begin-UML-doc -->
* <p>
* The constructor.
* </p>
* <!-- end-UML-doc -->
*
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
public JobLauncher() {
// begin-user-code
// Just call the other constructor with a null argument
this(null);
// end-user-code
}
/**
* <!-- begin-UML-doc -->
* <p>
* This operation performs the job launch if the action name is equal to
* "Launch the Job"
* </p>
* <!-- end-UML-doc -->
*
* @param actionName
* <p>
* The name of the action to perform.
* </p>
* @return <p>
* The status.
* </p>
* @generated
* "UML to Java (com.ibm.xtools.transform.uml2.java5.internal.UML2JavaTransform)"
*/
public FormStatus process(String actionName) {
// begin-user-code
// Local Declarations
FormStatus localStatus = FormStatus.InfoError;
// Only process the job if the Item is enabled
if (isEnabled()) {
// Check the action name and return and error if the action name is
// not equal to "Launch the Job"
if (!actionName.equals(allowedActions.get(0))) {
return FormStatus.InfoError;
}