blob: ca9f9ba39a6e094de8e32936f08909025fa8548a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 IBM Corporation.
* 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:
* IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.ptp.rm.mpi.openmpi.core.rtsystem;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.ptp.rm.core.utils.DebugUtil;
import org.eclipse.ptp.rm.mpi.openmpi.core.rtsystem.OpenMPIHostMap.Host;
/**
*
* @author Daniel Felix Ferber
*
*/
public class OpenMPIHostMapParser {
private OpenMPIHostMapParser() {
// Do not allow instances.
}
OpenMPIHostMap map = new OpenMPIHostMap();
// boolean hasErrors = false;
static Pattern pattern = Pattern.compile("\\s*(\\S+)((?:\\s+\\S+=\\d+)*)\\s*"); //$NON-NLS-1$
static Pattern paramPattern = Pattern.compile("\\s*(\\S+)=(\\d+)"); //$NON-NLS-1$
// static Pattern hostnamePattern = Pattern.compile("\\s*(\\S+)");
// static Pattern slotsPattern = Pattern.compile("\\s+(?:slots|cpus|count)\\s*=\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
// static Pattern maxSlotsPattern = Pattern.compile("\\s+max-slots\\s*=\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
/*
* Some very advanced regex. Maches a line that does NOT contain a valid parameter.
* In other words, matches a line with any invalid parameter.
* ^ - match beginning of line
* (! ) - match string that does not satisfy the enclosed regex
* (.*\\s(?:count|cpus|slots)\\s*= - matches the words count,cpus or slots starting anywhere,
* with a space before, and followed by equal with optional interleaving space.
*/
// static Pattern othersPattern = Pattern.compile("^(?!.*\\s(?:count|cpus|slots|max-slots)\\s*=)", Pattern.CASE_INSENSITIVE);
public static OpenMPIHostMap parse(BufferedReader reader) throws IOException {
OpenMPIHostMapParser parser = new OpenMPIHostMapParser();
String line;
while ((line = reader.readLine()) != null) {
/*
* Remove comments from line.
*/
int index = line.indexOf('#');
if (index != -1) {
line = line.substring(0, index);
}
line = line.trim();
if (line.length()==0) {
// Ignore empty line
continue;
}
Matcher matcher = pattern.matcher(line);
if (! matcher.matches()) {
// Ignore the line
parser.map.hasErrors = true;
DebugUtil.error(DebugUtil.RTS_DISCOVER_TRACING, "Ignoring invalid line: '{0}'", line); //$NON-NLS-1$
continue;
}
/*
* Add host. According to MacOS X man page for mpirun:
* - If the number of slots and max-slots are omitted, then openmpi understands that the host accepts
* only one process and that oversubscribing is allowed. This is assumed as default.
* - If number of slots is omitted, but not max-slots, the it is assumed that slots=max-slots.
* - If both number of slots and max-slots are give, then their values are kept, as long as slots<=max-slots.
*/
OpenMPIHostMap.Host host = new OpenMPIHostMap.Host(matcher.group(1));
parser.map.hosts.add(host);
host.setNumProcessors(0);
host.setMaxNumProcessors(0);
String parameters = matcher.group(2);
matcher = paramPattern.matcher(parameters);
/*
* Try to get slots and max-slots information.
*/
while (matcher.find()) {
// for (int i = 2; i <= matcher.groupCount(); i+=2) {
String key = matcher.group(1);
String value = matcher.group(2);
if (key.equalsIgnoreCase("slots") || key.equalsIgnoreCase("cpus") || key.equalsIgnoreCase("count")) { //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
/*
* On failure to parse, assume 0 processors (no info available).
*/
try {
host.setNumProcessors(Integer.parseInt(value));
if (host.getNumProcessors() <= 1) {
host.setNumProcessors(0);
}
} catch (NumberFormatException e) {
host.addErrors(OpenMPIHostMap.Host.ERR_NUM_SLOTS);
host.setNumProcessors(1);
}
} else if (key.equalsIgnoreCase("max-slots")) { //$NON-NLS-1$
try {
/*
* On failure to parse, assume 0 (no information available).
*/
host.setMaxNumProcessors(Integer.parseInt(value));
if (host.getMaxNumProcessors() <= 1) {
host.setMaxNumProcessors(0);
}
} catch (NumberFormatException e) {
host.addErrors(Host.ERR_MAX_NUM_SLOTS);
host.setMaxNumProcessors(0);
}
} else {
DebugUtil.error(DebugUtil.RTS_DISCOVER_TRACING, "Invalud attribute: '{0}'", matcher.group()); //$NON-NLS-1$
host.addErrors(OpenMPIHostMap.Host.ERR_UNKNOWN_ATTR);
}
}
/*
* Validate numbers.
*/
if (host.getNumProcessors() == 0) {
if (host.getMaxNumProcessors() == 0) {
host.setNumProcessors(1);
} else {
host.setNumProcessors(host.getMaxNumProcessors());
}
} else {
if (host.getMaxNumProcessors() > 0) {
if (host.getNumProcessors() > host.getMaxNumProcessors()) {
host.addErrors(Host.ERR_MAX_NUM_SLOTS);
host.setNumProcessors(host.getMaxNumProcessors());
}
}
}
DebugUtil.trace(DebugUtil.RTS_DISCOVER_TRACING, " {0} slots={1} max-slots={2}", host.getName(), host.getNumProcessors(), host.getMaxNumProcessors()); //$NON-NLS-1$
}
return parser.map;
}
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\s*(\\S+)(?:\\s+(\\S+)\\s*=\\s*(\\d+))*"); //$NON-NLS-1$
Matcher m = pattern.matcher("e slots=3 max-slots=4 r=5"); //$NON-NLS-1$
if (!m.matches()) {
System.out.println("no"); //$NON-NLS-1$
return;
}
for(int i = 1; i <= m.groupCount(); i++) {
System.out.println(m.group(i));
}
}
}