Coverage details for umich.cac.data.NodesField

LineHitsSource
1 package umich.cac.data;
2  
3 import java.util.logging.Level;
4 import java.util.logging.Logger;
5  
6 /**
7  * This class encapsulates Nodes fields, which is pretty complex, the most
8  * complex of all fields. A node consists of just the number of nodes, like
9  * Resource_List.nodes=2. The nodes resource_list item (i.e. the node
10  * configuration) declares the node requirements for a job. It is a string of
11  * individual node specifications separated by plus signs, +. For example,
12  *
13  * <pre>
14  * 3+2:fast
15  * </pre>
16  *
17  * requests 3 plain nodes and 2 ``fast'' nodes. A node specification is
18  * generally one of the following types the name of a particular node in the
19  * cluster,
20  * <OL>
21  * <LI>a node with a particular set of properties (e.g. fast and compute),
22  * <LI>a number of nodes,
23  * <LI>a number of nodes with a particular set of properties.
24  * </OL>
25  * In the last case, the number of nodes is specified first, and the properties
26  * of the nodes are listed afterwards, colon-separated. For instance,
27  *
28  * <pre>
29  * 4:fast:compute:db
30  * </pre>
31  *
32  * <P>
33  *
34  * Two important properties that may be specified are: <b>shared</b>
35  * indicates that the nodes are not to be allocated exclusively for the job. If
36  * this property is not specified, the PBS scheduler will allocate each
37  * processor exclusively to the job. * Note: The shared property may only be
38  * used as a global modifier. <b>ppn=&ltnumber of processors per node&gt</b>
39  * requests a certain number of processors per node be allocated. The node
40  * configuration may also have one or more global modifiers of the form #<i>
41  * property</i>
42  *
43  * appended to the end of it which is equivalent to appending <i>property</i>
44  *
45  * to each node specification individually. That is,
46  *
47  * <pre>
48  * 4+5:fast+2:compute#large
49  * </pre>
50  *
51  * is completely equivalent to
52  *
53  * <pre>
54  * 4:large+5:fast:large+2:compute:large
55  * </pre>: The following are some possible configurations.
56  * <p>
57  * specified number of nodes:
58  *
59  * <pre>
60  * nodes=&ltnum nodes&gt nodes=&ltnum nodes&gt#shared
61  * </pre>
62  *
63  * specified number of nodes with a certain number of processors per node:
64  *
65  * <pre>
66  * nodes=&ltnum nodes&gt:ppn=&ltnum procs per node&gt nodes=&ltnum nodes&gt:ppn=&ltnum procs per node&gt#shared
67  * *</pre>
68  *
69  * specific nodes:
70  *
71  * <pre>
72  * nodes=hosta+hostb+hostc nodes=hosta+hostb+hostc#shared
73  * *</pre>
74  *
75  * specified number of nodes with particular properties
76  *
77  * <pre>
78  * nodes=num nodes:property1:property2#shared
79  * </pre>
80  *
81  * or I have found
82  *
83  * <pre>
84  * nodes=hostname:ppn=2
85  * </pre>
86  *
87  *
88  * Example encoding is as follows
89  *
90  * <pre>
91  * &ltneednodes&gt &ltglobalproperty&gt shared&lt/globalproperty&gt &ltnodegroup numnodes="10" ppn="8"&gt&lt/nodegroup&gt &ltnodegroup numnodes="1"&gt &ltnodename&gthostname&lt/nodename&gt &lt/nodegroup&gt &ltnodegroup numnodes="12" ppn="2"&gt &ltproperty&gtbigdisk&lt/property&gt &ltproperty&gtfatmemory&lt/property&gt &lt/nodegroup&gt
92  * </pre>
93  *
94  * @author rmach@umich.edu
95  * @version $Header: /cvsroot/pbsaccounting/pbsaccounting/src/umich/cac/data/NodesField.java,v 1.3 2003/10/21 19:08:00 rodmach Exp $
96  */
97  
98 public class NodesField extends Field {
99  
100     /**
101      * Logger
102      */
103  
10445    private Logger logger = Logger.getLogger(NodesField.class.getName());
105  
106     /**
107      * Constructor for Nodes field
108      *
109      * @param fieldName
110      * Name of this field
111      * @param rawValue
112      * the raw value of this field from PBS accounting data
113      * @param fieldType
114      * Description of the Parameter
115      */
116  
117     public NodesField(
118         FieldName fieldName,
119         String rawValue,
120         FieldType fieldType) {
1210        super(fieldName, rawValue, fieldType);
1220        setup(fieldName, rawValue, fieldType);
123  
1240    }
125  
126     /**
127      * Constructor for Nodes field, for a RESOURCE_LIST field type
128      *
129      * @param fieldName
130      * Name of this field
131      * @param rawValue
132      * the raw value of this field from PBS accounting data
133      */
134  
135     public NodesField(FieldName fieldName, String rawValue) {
13642        super(fieldName, rawValue, FieldType.RESOURCE_LIST);
13742        setup(fieldName, rawValue, FieldType.RESOURCE_LIST);
138  
13942    }
140  
141     /**
142      * Sets up the Nodes field
143      *
144      * @param fieldName
145      * Name of this field
146      * @param rawValue
147      * the raw value of this field from PBS accounting data
148      * @param fieldType
149      * The field type this should be under Resource_List
150      */
151  
152     private void setup(
153         FieldName fieldName,
154         String rawValue,
155         FieldType fieldType) {
156  
157         /*
158          * 4+5:fast+2:compute#large foo+bar+taz
159          * 4+2:ppn=2:fatdisk:bigscratch#shared
160          */
161  
162         //Step one, remove any global properties, and handle those
16342        int globalIndex = rawValue.indexOf("#");
164  
16542        if (globalIndex == -1) {
166             //There are no global properties
16736            logger.fine("No global properties found");
168         } else {
1696            String globalProperties = rawValue.substring(globalIndex);
1706            addGlobalProperties(globalProperties);
171             //Strip off the globalProperties
1726            rawValue = rawValue.substring(0, globalIndex);
173         }
174  
175         /*
176          * Nope, then the format happens to be the + separated version, with
177          * properties delimited with : Resource_List.nodes=2:ppn=2
178          * 4+2:ppn=2:fatdisk:bigscratch
179          */
180  
181         // + separates node requirements
18242        String needNodes[] = rawValue.split("\\+");
183  
18499        for (int i = 0; i < needNodes.length; i++) {
185  
18657            int propertySeparator = needNodes[i].indexOf(":");
187  
188             //Check if this node requirement has any properties
18957            if (propertySeparator != -1) {
190  
19127                String numNodes = needNodes[i].substring(0, propertySeparator);
19227                String propertiesArray =
193                     needNodes[i].substring(propertySeparator);
194  
195                 // : separates properties
19627                String properties[] = propertiesArray.split(":");
197  
19827                FieldName needNodesFieldName =
199                     new FieldName("nodegroup", "none", FieldType.RESOURCE_LIST);
20027                Field nodeGroupField =
201                     new Field(needNodesFieldName, "", FieldType.RESOURCE_LIST);
202  
20327                if (isNumeric(numNodes)) {
20418                    Attribute nodesAttribute =
205                         new Attribute("numnodes", numNodes);
20618                    nodeGroupField.addAttribute(nodesAttribute);
207                 } else {
208                     /*
209                      * This is like nodes=hostname:ppn=2:fatdisk, e.g. the part
210                      * before the colon is the "hostname" instead of the number
211                      * of hosts with the feature. I just set it to "1" since
212                      * this would be same as nodes=1:ppn=2:fatdisk
213                      */
214  
2159                    FieldName nodeNameFieldName =
216                         new FieldName(
217                             "nodename",
218                             "none",
219                             FieldType.RESOURCE_LIST);
220                     //Here numNodes is just the hostname
2219                    Field nodeNameField =
222                         new Field(
223                             nodeNameFieldName,
224                             numNodes,
225                             FieldType.RESOURCE_LIST);
2269                    nodeGroupField.addChild(nodeNameField);
227  
2289                    Attribute nodesAttribute = new Attribute("numnodes", "1");
2299                    nodeGroupField.addAttribute(nodesAttribute);
230  
231                 }
232  
23393                for (int j = 0; j < properties.length; j++) {
234  
23566                    if (properties[j].equals("")) {
23627                        continue;
237                     }
23839                    if (properties[j].startsWith("ppn=")) {
23918                        int ppnAttributeIndex = properties[j].indexOf("=");
24018                        String ppnAttributeValue =
241                             properties[j].substring(ppnAttributeIndex + 1);
24218                        Attribute attribute =
243                             new Attribute("ppn", ppnAttributeValue);
24418                        nodeGroupField.addAttribute(attribute);
245  
246                     } else {
24721                        FieldName propertyFieldName =
248                             new FieldName(
249                                 "property",
250                                 "none",
251                                 FieldType.RESOURCE_LIST);
25221                        Field propertiesField =
253                             new Field(
254                                 propertyFieldName,
255                                 properties[j],
256                                 FieldType.RESOURCE_LIST);
25721                        nodeGroupField.addChild(propertiesField);
258                     }
259                 }
260  
26127                addChild(nodeGroupField);
262  
263             } else {
264                 //Else, we have a node with no additional properties.
265  
26630                if (isNumeric(needNodes[i])) {
267  
26821                    FieldName needNodesFieldName =
269                         new FieldName(
270                             "nodegroup",
271                             "none",
272                             FieldType.RESOURCE_LIST);
27321                    Field nodeGroupField =
274                         new Field(
275                             needNodesFieldName,
276                             "",
277                             FieldType.RESOURCE_LIST);
27821                    Attribute nodesAttribute =
279                         new Attribute("numnodes", needNodes[i]);
28021                    nodeGroupField.addAttribute(nodesAttribute);
28121                    addChild(nodeGroupField);
282                 } else {
2839                    addHost(needNodes[i]);
284                 }
285  
286             }
287         }
288  
28942    }
290  
291     private void addHost(String hostString) {
292  
2939        FieldName needNodesFieldName =
294             new FieldName("nodegroup", "none", FieldType.RESOURCE_LIST);
2959        Field nodeGroupField =
296             new Field(needNodesFieldName, "", FieldType.RESOURCE_LIST);
2979        Attribute nodesAttribute = new Attribute("numnodes", "1");
2989        nodeGroupField.addAttribute(nodesAttribute);
299  
3009        FieldName nodeNameFieldName =
301             new FieldName("nodename", "none", FieldType.RESOURCE_LIST);
3029        Field nodeNameField =
303             new Field(nodeNameFieldName, hostString, FieldType.RESOURCE_LIST);
304  
3059        nodeGroupField.addChild(nodeNameField);
3069        addChild(nodeGroupField);
3079    }
308  
309     /**
310      * Add global properties, the global properties are list of global
311      * properties delimited by a # sign
312      *
313      * @param globalPropertiesString
314      * the global properties to add
315      */
316  
317     private void addGlobalProperties(String globalPropertiesString) {
318  
3196        String[] globalProperties = globalPropertiesString.split("#");
320  
32118        for (int i = 0; i < globalProperties.length; i++) {
32212            String propertyValue = globalProperties[i];
323  
324             //To prevent the empty property value resulting from the split
32512            if (propertyValue.length() == 0) {
3266                continue;
327             }
328  
3296            if (logger.isLoggable(Level.INFO)) {
3306                logger.info(
331                     "Adding global property with value " + propertyValue);
332             }
333  
3346            FieldName propertyFieldName =
335                 new FieldName(
336                     "globalproperty",
337                     "none",
338                     FieldType.RESOURCE_LIST);
339  
3406            Field propertyField =
341                 new Field(
342                     propertyFieldName,
343                     propertyValue,
344                     FieldType.RESOURCE_LIST);
3456            addChild(propertyField);
346         }
347  
3486    }
349  
350     /**
351      * Decide whether data is numeric. It is numeric if each of its characters
352      * is a digit.
353      *
354      * @param s
355      * String to test if it is numeric, contains all digits
356      */
357     private boolean isNumeric(String s) {
35857        boolean isNumeric = false;
359  
36096        for (int i = 0; i < s.length(); i++) {
36157            if (!Character.isDigit(s.charAt(i))) {
36218                isNumeric = false;
36318                break;
364             } else {
36539                isNumeric = true;
366             }
367  
368         }
369  
37057        return isNumeric;
371     }
372  
373 }

this report was generated by version 1.0.5 of jcoverage.
visit www.jcoverage.com for updates.

copyright © 2003, jcoverage ltd. all rights reserved.
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.