package org.apache.solr.hadoop;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.solr.hadoop.SolrDocumentConverter;
import org.apache.solr.hadoop.SolrOutputFormat;
public class CSVIndexer extends Configured implements Tool {
private static final Log LOG = LogFactory.getLog(CSVIndexer.class);
public static final String FIELD_NAMES_KEY = "csv.names.";
public int run(String[] args) throws Exception {
if (args.length < 2) {
System.err.println("Usage: CSVIndexer <outputDir> -solr <solrHome> <inputDir> [<inputDir2> ...] [-shards NNN] [-compress_output]");
System.err.println("\tinputDir\tinput directory(-ies) containing CSV files");
System.err.println("\toutputDir\toutput directory containing Solr indexes.");
System.err.println("\tsolr <solrHome>\tlocal directory containing Solr conf/ and lib/");
System.err.println("\tshards NNN\tset the number of output shards to NNN");
System.err.println("\t\t(default: the default number of reduce tasks)");
System.err.println("\tcompress_output\tto compress the output of the reducer tasks (create .zip file)");
return -1;
}
Job job = new Job(getConf());
job.setJarByClass(CSVIndexer.class);
int shards = -1;
boolean compressOutput = false;
String solrHome = null;
Path out = new Path(args[0]);
for (int i = 1; i < args.length; i++) {
if (args[i] == null) continue;
if (args[i].equals("-shards")) {
shards = Integer.parseInt(args[++i]);
} else if (args[i].equals("-compress_output")) {
compressOutput = true;
} else if (args[i].equals("-solr")) {
solrHome = args[++i];
continue;
} else {
Path p = new Path(args[i]);
FileInputFormat.addInputPath(job, p);
FileSystem fs = p.getFileSystem(job.getConfiguration());
for (FileStatus stat : fs.listStatus(p)) {
if (stat.isDir()) {
continue;
}
getHeader(fs, stat, job);
}
}
}
if (solrHome == null || !new File(solrHome).exists()) {
throw new IOException("You must specify a valid solr.home directory!");
}
job.setMapperClass(CSVMapper.class);
job.setReducerClass(CSVReducer.class);
job.setOutputFormatClass(SolrOutputFormat.class);
SolrOutputFormat.setupSolrHomeCache(new File(solrHome), job.getConfiguration());
if (shards > 0) {
job.setNumReduceTasks(shards);
}
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(MapWritable.class);
SolrDocumentConverter.setSolrDocumentConverter(CSVDocumentConverter.class, job.getConfiguration());
FileOutputFormat.setOutputPath(job, out);
SolrOutputFormat.setOutputZipFormat(compressOutput, job.getConfiguration());
return job.waitForCompletion(true) ? 0 : -1;
}
private void getHeader(FileSystem fs, FileStatus s, Job job) throws IOException {
InputStream is = fs.open(s.getPath());
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line = br.readLine();
br.close();
String[] fields = line.split(",");
LOG.debug("storing header for: " + s.getPath().toUri().getPath());
job.getConfiguration().setStrings(FIELD_NAMES_KEY + s.getPath().toUri().getPath(), fields);
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
int res = ToolRunner.run(conf, new CSVIndexer(), args);
System.exit(res);
}
}