blob: 88ef99b438f009872ae641efd31eca1631075b83 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.streaming;
import java.text.DecimalFormat;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.jar.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapreduce.MRJobConfig;
import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig;
/** Utilities not available elsewhere in Hadoop.
*
*/
public class StreamUtil {
private static final Log LOG =
LogFactory.getLog(StreamUtil.class.getName());
/** It may seem strange to silently switch behaviour when a String
* is not a classname; the reason is simplified Usage:<pre>
* -mapper [classname | program ]
* instead of the explicit Usage:
* [-mapper program | -javamapper classname], -mapper and -javamapper are mutually exclusive.
* (repeat for -reducer, -combiner) </pre>
*/
public static Class goodClassOrNull(Configuration conf, String className, String defaultPackage) {
Class clazz = null;
try {
clazz = conf.getClassByName(className);
} catch (ClassNotFoundException cnf) {
}
if (clazz == null) {
if (className.indexOf('.') == -1 && defaultPackage != null) {
className = defaultPackage + "." + className;
try {
clazz = conf.getClassByName(className);
} catch (ClassNotFoundException cnf) {
}
}
}
return clazz;
}
public static String findInClasspath(String className) {
return findInClasspath(className, StreamUtil.class.getClassLoader());
}
/** @return a jar file path or a base directory or null if not found.
*/
public static String findInClasspath(String className, ClassLoader loader) {
String relPath = className;
relPath = relPath.replace('.', '/');
relPath += ".class";
java.net.URL classUrl = loader.getResource(relPath);
String codePath;
if (classUrl != null) {
boolean inJar = classUrl.getProtocol().equals("jar");
codePath = classUrl.toString();
if (codePath.startsWith("jar:")) {
codePath = codePath.substring("jar:".length());
}
if (codePath.startsWith("file:")) { // can have both
codePath = codePath.substring("file:".length());
}
if (inJar) {
// A jar spec: remove class suffix in /path/my.jar!/package/Class
int bang = codePath.lastIndexOf('!');
codePath = codePath.substring(0, bang);
} else {
// A class spec: remove the /my/package/Class.class portion
int pos = codePath.lastIndexOf(relPath);
if (pos == -1) {
throw new IllegalArgumentException("invalid codePath: className=" + className
+ " codePath=" + codePath);
}
codePath = codePath.substring(0, pos);
}
} else {
codePath = null;
}
return codePath;
}
// copied from TaskRunner
static void unJar(File jarFile, File toDir) throws IOException {
JarFile jar = new JarFile(jarFile);
try {
Enumeration entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
if (!entry.isDirectory()) {
InputStream in = jar.getInputStream(entry);
try {
File file = new File(toDir, entry.getName());
boolean b = file.getParentFile().mkdirs();
if (!b) { LOG.warn("Ignoring failure of mkdirs"); }
OutputStream out = new FileOutputStream(file);
try {
byte[] buffer = new byte[8192];
int i;
while ((i = in.read(buffer)) != -1) {
out.write(buffer, 0, i);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
}
} finally {
jar.close();
}
}
final static long KB = 1024L * 1;
final static long MB = 1024L * KB;
final static long GB = 1024L * MB;
final static long TB = 1024L * GB;
final static long PB = 1024L * TB;
static DecimalFormat dfm = new DecimalFormat("####.000");
static DecimalFormat ifm = new DecimalFormat("###,###,###,###,###");
public static String dfmt(double d) {
return dfm.format(d);
}
public static String ifmt(double d) {
return ifm.format(d);
}
public static String formatBytes(long numBytes) {
StringBuffer buf = new StringBuffer();
boolean bDetails = true;
double num = numBytes;
if (numBytes < KB) {
buf.append(numBytes).append(" B");
bDetails = false;
} else if (numBytes < MB) {
buf.append(dfmt(num / KB)).append(" KB");
} else if (numBytes < GB) {
buf.append(dfmt(num / MB)).append(" MB");
} else if (numBytes < TB) {
buf.append(dfmt(num / GB)).append(" GB");
} else if (numBytes < PB) {
buf.append(dfmt(num / TB)).append(" TB");
} else {
buf.append(dfmt(num / PB)).append(" PB");
}
if (bDetails) {
buf.append(" (").append(ifmt(numBytes)).append(" bytes)");
}
return buf.toString();
}
public static String formatBytes2(long numBytes) {
StringBuffer buf = new StringBuffer();
long u = 0;
if (numBytes >= TB) {
u = numBytes / TB;
numBytes -= u * TB;
buf.append(u).append(" TB ");
}
if (numBytes >= GB) {
u = numBytes / GB;
numBytes -= u * GB;
buf.append(u).append(" GB ");
}
if (numBytes >= MB) {
u = numBytes / MB;
numBytes -= u * MB;
buf.append(u).append(" MB ");
}
if (numBytes >= KB) {
u = numBytes / KB;
buf.append(u).append(" KB ");
}
buf.append(u).append(" B"); //even if zero
return buf.toString();
}
static Environment env;
static String HOST;
static {
try {
env = new Environment();
HOST = env.getHost();
} catch (IOException io) {
io.printStackTrace();
}
}
static class StreamConsumer extends Thread {
StreamConsumer(InputStream in, OutputStream out) {
this.bin = new LineNumberReader(new BufferedReader(new InputStreamReader(in)));
if (out != null) {
this.bout = new DataOutputStream(out);
}
}
public void run() {
try {
String line;
while ((line = bin.readLine()) != null) {
if (bout != null) {
bout.writeUTF(line); //writeChars
bout.writeChar('\n');
}
}
bout.flush();
} catch (IOException io) {
}
}
LineNumberReader bin;
DataOutputStream bout;
}
static void exec(String arg, PrintStream log) {
exec(new String[] { arg }, log);
}
static void exec(String[] args, PrintStream log) {
try {
log.println("Exec: start: " + Arrays.asList(args));
Process proc = Runtime.getRuntime().exec(args);
new StreamConsumer(proc.getErrorStream(), log).start();
new StreamConsumer(proc.getInputStream(), log).start();
int status = proc.waitFor();
//if status != 0
log.println("Exec: status=" + status + ": " + Arrays.asList(args));
} catch (InterruptedException in) {
in.printStackTrace();
} catch (IOException io) {
io.printStackTrace();
}
}
static String qualifyHost(String url) {
try {
return qualifyHost(new URL(url)).toString();
} catch (IOException io) {
return url;
}
}
static URL qualifyHost(URL url) {
try {
InetAddress a = InetAddress.getByName(url.getHost());
String qualHost = a.getCanonicalHostName();
URL q = new URL(url.getProtocol(), qualHost, url.getPort(), url.getFile());
return q;
} catch (IOException io) {
return url;
}
}
static final String regexpSpecials = "[]()?*+|.!^-\\~@";
public static String regexpEscape(String plain) {
StringBuffer buf = new StringBuffer();
char[] ch = plain.toCharArray();
int csup = ch.length;
for (int c = 0; c < csup; c++) {
if (regexpSpecials.indexOf(ch[c]) != -1) {
buf.append("\\");
}
buf.append(ch[c]);
}
return buf.toString();
}
public static String safeGetCanonicalPath(File f) {
try {
String s = f.getCanonicalPath();
return (s == null) ? f.toString() : s;
} catch (IOException io) {
return f.toString();
}
}
static String slurp(File f) throws IOException {
int len = (int) f.length();
byte[] buf = new byte[len];
FileInputStream in = new FileInputStream(f);
String contents = null;
try {
in.read(buf, 0, len);
contents = new String(buf, "UTF-8");
} finally {
in.close();
}
return contents;
}
static String slurpHadoop(Path p, FileSystem fs) throws IOException {
int len = (int) fs.getFileStatus(p).getLen();
byte[] buf = new byte[len];
FSDataInputStream in = fs.open(p);
String contents = null;
try {
in.readFully(in.getPos(), buf);
contents = new String(buf, "UTF-8");
} finally {
in.close();
}
return contents;
}
public static String rjustify(String s, int width) {
if (s == null) s = "null";
if (width > s.length()) {
s = getSpace(width - s.length()) + s;
}
return s;
}
public static String ljustify(String s, int width) {
if (s == null) s = "null";
if (width > s.length()) {
s = s + getSpace(width - s.length());
}
return s;
}
static char[] space;
static {
space = new char[300];
Arrays.fill(space, '\u0020');
}
public static String getSpace(int len) {
if (len > space.length) {
space = new char[Math.max(len, 2 * space.length)];
Arrays.fill(space, '\u0020');
}
return new String(space, 0, len);
}
static private Environment env_;
static Environment env() {
if (env_ != null) {
return env_;
}
try {
env_ = new Environment();
} catch (IOException io) {
io.printStackTrace();
}
return env_;
}
public static String makeJavaCommand(Class main, String[] argv) {
ArrayList vargs = new ArrayList();
File javaHomeBin = new File(System.getProperty("java.home"), "bin");
File jvm = new File(javaHomeBin, "java");
vargs.add(jvm.toString());
// copy parent classpath
vargs.add("-classpath");
vargs.add("\"" + System.getProperty("java.class.path") + "\"");
// add heap-size limit
vargs.add("-Xmx" + Runtime.getRuntime().maxMemory());
// Add main class and its arguments
vargs.add(main.getName());
for (int i = 0; i < argv.length; i++) {
vargs.add(argv[i]);
}
return collate(vargs, " ");
}
public static String collate(Object[] args, String sep) {
return collate(Arrays.asList(args), sep);
}
public static String collate(List args, String sep) {
StringBuffer buf = new StringBuffer();
Iterator it = args.iterator();
while (it.hasNext()) {
if (buf.length() > 0) {
buf.append(" ");
}
buf.append(it.next());
}
return buf.toString();
}
// JobConf helpers
public static FileSplit getCurrentSplit(JobConf job) {
String path = job.get(MRJobConfig.MAP_INPUT_FILE);
if (path == null) {
return null;
}
Path p = new Path(path);
long start = Long.parseLong(job.get(MRJobConfig.MAP_INPUT_START));
long length = Long.parseLong(job.get(MRJobConfig.MAP_INPUT_PATH));
return new FileSplit(p, start, length, job);
}
static class TaskId {
boolean mapTask;
String jobid;
int taskid;
int execid;
}
public static boolean isLocalJobTracker(JobConf job) {
return job.get(JTConfig.JT_IPC_ADDRESS, "local").equals("local");
}
public static TaskId getTaskInfo(JobConf job) {
TaskId res = new TaskId();
String id = job.get(MRJobConfig.TASK_ATTEMPT_ID);
if (isLocalJobTracker(job)) {
// it uses difft naming
res.mapTask = job.getBoolean(MRJobConfig.TASK_ISMAP, true);
res.jobid = "0";
res.taskid = 0;
res.execid = 0;
} else {
String[] e = id.split("_");
res.mapTask = e[3].equals("m");
res.jobid = e[1] + "_" + e[2];
res.taskid = Integer.parseInt(e[4]);
res.execid = Integer.parseInt(e[5]);
}
return res;
}
public static void touch(File file) throws IOException {
file = file.getAbsoluteFile();
FileOutputStream out = new FileOutputStream(file);
out.close();
if (!file.exists()) {
throw new IOException("touch failed: " + file);
}
}
public static boolean isCygwin() {
String OS = System.getProperty("os.name");
return (OS.indexOf("Windows") > -1);
}
public static String localizeBin(String path) {
if (isCygwin()) {
path = "C:/cygwin/" + path;
}
return path;
}
/** @param name foo where &lt;junit>&lt;sysproperty key="foo" value="${foo}"/>
* If foo is undefined then Ant sets the unevaluated value.
* Take this into account when setting defaultVal. */
public static String getBoundAntProperty(String name, String defaultVal)
{
String val = System.getProperty(name);
if (val != null && val.indexOf("${") >= 0) {
val = null;
}
if (val == null) {
val = defaultVal;
}
return val;
}
}