package org.apache.hadoop.mapred; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.LocalDirAllocator; import org.apache.hadoop.fs.Path; import org.apache.hadoop.util.CoronaFailureEvent; import org.apache.hadoop.util.CoronaFailureEventInjector; import org.apache.hadoop.util.Shell; public class CoronaJobTrackerRunner extends TaskRunner { @SuppressWarnings("unused") private final CoronaSessionInfo coronaSessionInfo; private final File workDir; private final String originalPath; private final String releasePath; private Path localizedJobFile; @SuppressWarnings("deprecation") public CoronaJobTrackerRunner( TaskTracker.TaskInProgress tip, Task task, TaskTracker tracker, JobConf ttConf, CoronaSessionInfo info, String originalPath, String releasePath) throws IOException { super(tip, task, tracker, ttConf); this.coronaSessionInfo = info; this.originalPath = originalPath; this.releasePath = releasePath; LocalDirAllocator lDirAlloc = new LocalDirAllocator("mapred.local.dir"); workDir = new File(lDirAlloc.getLocalPathForWrite( TaskTracker.getLocalTaskDir( task.getJobID().toString(), task.getTaskID().toString(), task.isTaskCleanupTask()) + Path.SEPARATOR + MRConstants.WORKDIR, conf). toString()); if (!workDir.mkdirs()) { if (!workDir.isDirectory()) { throw new IOException("Mkdirs failed to create " + workDir.toString()); } } localizeTaskConfiguration(tracker, ttConf, workDir.toString(), task, task .getJobID()); } /** * Copies the job file to the working directory of the process that will be * started. */ @SuppressWarnings("deprecation") private void localizeTaskConfiguration(TaskTracker tracker, JobConf ttConf, String workDir, Task t, JobID jobID) throws IOException { Path jobFile = new Path(t.getJobFile()); FileSystem systemFS = tracker.systemFS; this.localizedJobFile = new Path(workDir, jobID + ".xml"); LOG.info("Localizing CJT configuration from " + jobFile + " to " + localizedJobFile); systemFS.copyToLocalFile(jobFile, localizedJobFile); JobConf localJobConf = new JobConf(localizedJobFile); boolean modified = Task.saveStaticResolutions(localJobConf); if (modified) { FSDataOutputStream out = new FSDataOutputStream( new FileOutputStream(localizedJobFile.toUri().getPath())); try { localJobConf.writeXml(out); } catch (IOException e) { out.close(); throw e; } } // Add the values from the job conf to the configuration of this runner this.conf.addResource(localizedJobFile); } /** Delete any temporary files from previous failed attempts. */ @Override public boolean prepare() throws IOException { if (!super.prepare()) { return false; } mapOutputFile.removeAll(getTask().getTaskID()); return true; } /** Delete all of the temporary map output files. */ @Override public void close() throws IOException { LOG.info(getTask()+" done; removing files."); mapOutputFile.removeAll(getTask().getTaskID()); } private String getCJTJavaOpts(JobConf conf) { return conf.get("mapred.corona.standalonecjt.java.opts", JobConf.DEFAULT_MAPRED_TASK_JAVA_OPTS); } private static File getJobStdLogFile(TaskAttemptID taskid, TaskLog.LogName filter) { return new File( CoronaTaskTracker.jobTrackerLogDir() + File.separator + "userlogs" + File.separator+ taskid.toString() + File.separator + filter.toString() ); } @SuppressWarnings("deprecation") @Override public void run() { Task task = getTask(); TaskAttemptID taskid = task.getTaskID(); try { if (!prepare()) { return; } String sep = System.getProperty("path.separator"); StringBuffer classPath = new StringBuffer(); // The alternate runtime can be used to debug tasks by putting a // custom version of the mapred libraries. This will get loaded before // the TT's jars. String debugRuntime = conf.get("mapred.task.debug.runtime.classpath"); if (debugRuntime != null) { classPath.append(debugRuntime); classPath.append(sep); } // start with same classpath as parent process String systemClassPath = System.getProperty("java.class.path"); if (releasePath != null && !releasePath.isEmpty() && originalPath != null && !releasePath.isEmpty()) { systemClassPath = systemClassPath.replaceAll(originalPath, releasePath); } classPath.append(systemClassPath); classPath.append(sep); // Build exec child jmv args. Vector<String> vargs = new Vector<String>(8); File jvm = // use same jvm as parent new File(new File(System.getProperty("java.home"), "bin"), "java"); vargs.add(jvm.toString()); // Add child (task) java-vm options. String javaOpts = getCJTJavaOpts(conf); javaOpts = javaOpts.replace("@taskid@", taskid.toString()); String [] javaOptsSplit = javaOpts.split(" "); for (int i = 0; i < javaOptsSplit.length; i++) { vargs.add(javaOptsSplit[i]); } // add java.io.tmpdir given by mapred.child.tmp String tmp = conf.get("mapred.child.tmp", "./tmp"); Path tmpDir = new Path(tmp); // if temp directory path is not absolute // prepend it with workDir. if (!tmpDir.isAbsolute()) { tmpDir = new Path(workDir.toString(), tmp); } FileSystem localFs = FileSystem.getLocal(conf); if (!localFs.mkdirs(tmpDir) && !localFs.getFileStatus(tmpDir).isDir()) { throw new IOException("Mkdirs failed to create " + tmpDir.toString()); } vargs.add("-Djava.io.tmpdir=" + tmpDir.toString()); // Add classpath. vargs.add("-classpath"); vargs.add(classPath.toString()); // Setup the log4j prop long logSize = TaskLog.getTaskLogLength(conf); vargs.add("-Dhadoop.log.dir=" + CoronaTaskTracker.jobTrackerLogDir()); boolean logToScribe = conf.getBoolean("mapred.task.log.scribe", false); if (logToScribe) { vargs.addAll(conf.getStringCollection("mapred.task.log.scribe.conf")); } String logger = logToScribe ? "INFO,TLA,scribe" : "INFO,TLA"; vargs.add("-Dhadoop.root.logger=" + logger); vargs.add("-Dhadoop.tasklog.taskid=" + taskid); vargs.add("-Dhadoop.tasklog.totalLogFileSize=" + logSize); Path systemDirectory = tracker.systemDirectory; if (!systemDirectory.isAbsolute()) { systemDirectory = new Path(tracker.systemFS.getWorkingDirectory(), systemDirectory); } systemDirectory = systemDirectory.makeQualified(tracker.systemFS); vargs.add("-Dmapred.system.dir=" + systemDirectory); // Add main class and its arguments vargs.add(CoronaJobTracker.class.getName()); // main of CJT vargs.add(task.getJobID().toString()); // Pass job id. vargs.add(task.getTaskID().toString()); // Pass attempt id. vargs.add(coronaSessionInfo.getJobTrackerAddr().getHostName()); vargs.add(Integer.toString(coronaSessionInfo.getJobTrackerAddr() .getPort())); // add the task log http server host and port vargs.add(this.tracker.localHostname); vargs.add(Integer.toString(this.tracker.httpPort)); // inject the job tracker failure event if needed if (this.tracker instanceof CoronaTaskTracker) { CoronaFailureEventInjector jtEventInjector = ((CoronaTaskTracker)this.tracker).jtFailureEventInjector; if (jtEventInjector != null) { LOG.info("Injecting failure event to RJT"); CoronaFailureEvent failureEvent = jtEventInjector.pollFailureEvent(); if (failureEvent != null) { LOG.info("Injecting failure event " + failureEvent.toString()); vargs.add(failureEvent.toString()); } } } //vargs.add("2:0"); tracker.addToMemoryManager(task.getTaskID(), task.isMapTask(), conf, false); // set memory limit using ulimit if feasible and necessary ... String[] ulimitCmd = Shell.getUlimitMemoryCommand(getChildUlimit(conf)); List<String> setup = null; if (ulimitCmd != null) { setup = new ArrayList<String>(); for (String arg : ulimitCmd) { setup.add(arg); } } // Set up the redirection of the task's stdout and stderr streams File stdout = getJobStdLogFile(taskid, TaskLog.LogName.STDOUT); File stderr = getJobStdLogFile(taskid, TaskLog.LogName.STDERR); stdout.getParentFile().mkdirs(); Map<String, String> env = new HashMap<String, String>(); StringBuffer ldLibraryPath = new StringBuffer(); ldLibraryPath.append(workDir.toString()); String oldLdLibraryPath = null; oldLdLibraryPath = System.getenv("LD_LIBRARY_PATH"); if (oldLdLibraryPath != null) { ldLibraryPath.append(sep); ldLibraryPath.append(oldLdLibraryPath); } env.put("LD_LIBRARY_PATH", ldLibraryPath.toString()); LOG.info("Launching CJT " + taskid + " in working directory " + workDir + " Command line " + vargs); jvmManager.launchJvm(this, jvmManager.constructJvmEnv(setup,vargs,stdout,stderr,logSize, workDir, env, conf)); synchronized (lock) { while (!done) { lock.wait(); } } } catch (IOException e) { LOG.error("Error while launching CJT ", e); } catch (InterruptedException e) { LOG.warn("Error while launching CJT ", e); } } }