package com.scaleunlimited.cascading.local; import java.io.File; import java.util.Map.Entry; import java.util.Properties; import org.apache.commons.io.FileUtils; import cascading.flow.FlowConnector; import cascading.flow.FlowProcess; import cascading.flow.local.LocalFlowConnector; import cascading.flow.local.LocalFlowProcess; import cascading.scheme.Scheme; import cascading.tap.SinkMode; import cascading.tap.Tap; import cascading.tap.local.FileTap; import cascading.tap.local.PartitionTap; import cascading.tap.local.TemplateTap; import cascading.tap.partition.Partition; import cascading.tuple.Fields; import com.scaleunlimited.cascading.BasePath; import com.scaleunlimited.cascading.BasePlatform; import com.scaleunlimited.cascading.Level; @SuppressWarnings({ "unchecked", "rawtypes", "serial" }) public class LocalPlatform extends BasePlatform { public static final String PLATFORM_TYPE = "local"; public LocalPlatform(Class applicationJarClass) { super(applicationJarClass); } @Override public String getPlatformType() { return PLATFORM_TYPE; } @Override public boolean isLocal() { return true; } @Override public File getDefaultLogDir() { return new File("./"); } @Override public String getProperty(String name) { return super.getPropertyHelper(name); } @Override public boolean getBooleanProperty(String name) { return super.getBooleanPropertyHelper(name); } @Override public int getIntProperty(String name) { return super.getIntPropertyHelper(name); } @Override public BasePath getTempDir() throws Exception { return new LocalPath(FileUtils.getTempDirectoryPath()); } @Override public boolean isTextSchemeCompressable() { // TextLineScheme can read/write compressed files. return true; } @Override public void setNumReduceTasks(int numReduceTasks) throws Exception { // We can't control the number of reduce tasks here. } @Override public int getNumReduceTasks() throws Exception { return 1; } @Override public void setFlowPriority(FlowPriority priority) throws Exception { // Nothing to do here } @Override public void setLogLevel(Level level, String... packageNames) { for (String packageName : packageNames) { if (packageName.isEmpty()) { // TODO set the logging level for the local job... // but we can't do that (???) using slf4j, so this would only work // if we assume log4j is being used. } } super.setLogLevelHelper(level, packageNames); } @Override public void setProperty(String name, String value) { super.setPropertyHelper(name, value); } @Override public void setProperty(String name, int value) { super.setPropertyHelper(name, value); } @Override public void setProperty(String name, boolean value) { super.setPropertyHelper(name, value); } @Override public FlowConnector makeFlowConnector() throws Exception { return new LocalFlowConnector(_props); } @Override public FlowProcess makeFlowProcess() throws Exception { // TODO why does this require Properties, but LocalFlowConnector takes map<object, object>? Properties props = new Properties(); for (Entry<Object, Object> entry : _props.entrySet()) { if ((entry.getKey() instanceof String) && (entry.getValue() instanceof String)) { props.setProperty((String)entry.getKey(), (String)entry.getValue()); } } return new LocalFlowProcess(props); } @Override public BasePath makePath(String path) throws Exception { return new LocalPath(path); } @Override public BasePath makePath(BasePath parent, String subdir) throws Exception { return new LocalPath(parent, subdir); } @Override public Tap makeTap(Scheme scheme, BasePath path, SinkMode mode) throws Exception { return new DirectoryTap(scheme, path.getAbsolutePath(), mode); } @SuppressWarnings("deprecation") @Override public Tap makeTemplateTap(Tap tap, String pattern, Fields fields) throws Exception { return new TemplateTap((FileTap) tap, pattern, fields); } @Override public Tap makePartitionTap(Tap parentTap, Partition partition, SinkMode mode) throws Exception { if (parentTap instanceof DirectoryTap) { // The local PartitionTap is hard-coded to only work with a FileTap (it expects that the child paths // will be paths to files, not directories). FileTap tap = new FileTap(parentTap.getScheme(), parentTap.getIdentifier(), parentTap.getSinkMode()); return new PartitionTap(tap, partition, mode); } else if (parentTap instanceof FileTap) { FileTap tap = (FileTap)parentTap; return new PartitionTap(tap, partition, mode); } else { throw new RuntimeException("parentTap needs to an instance of FileTap - instead got: " + parentTap.getClass().getName()); } } @Override public Scheme makeBinaryScheme(Fields fields) { return new KryoScheme(fields); } @Override public Scheme makeTextScheme(boolean isEnableCompression) { if (isEnableCompression) { return new TextLineScheme(true); } else { return makeTextScheme(); } } @Override public Scheme makeTextScheme() { return new TextLineScheme(); } @Override public boolean rename(BasePath src, BasePath dst) throws Exception { File srcFile = new File(src.getAbsolutePath()); File dstFile = new File (dst.getAbsolutePath()); return srcFile.renameTo(dstFile); } @Override public String shareLocalDir(String localDirName) { // Local builds just leave directory in localDirName (which is shared) return localDirName; } @Override public String copySharedDirToLocal( FlowProcess flowProcess, String sharedDirName) { return sharedDirName; } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public File getLogDir() { return super.getLogDirHelper(); } @Override public Tap makeTap(Scheme scheme, BasePath path) throws Exception { return makeTap(scheme, path, SinkMode.KEEP); } @Override public Tap makePartitionTap(Tap parentTap, Partition partition) throws Exception { return makePartitionTap(parentTap, partition, SinkMode.KEEP); } @Override public void setJobPollingInterval(long interval) { super.setJobPollingIntervalHelper(interval); } @Override public void setLogDir(File logDir) { super.setLogDirHealer(logDir); } }