Extracting the spark stream processor to allow for generic usage.
Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/2db2ee80 Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/2db2ee80 Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/2db2ee80 Branch: refs/heads/master Commit: 2db2ee802e4272a2b3c3888008432e5eb19ac82a Parents: fdabc5e Author: Aaron McCurry <[email protected]> Authored: Sun Jan 11 23:15:06 2015 -0500 Committer: Aaron McCurry <[email protected]> Committed: Sun Jan 11 23:15:06 2015 -0500 ---------------------------------------------------------------------- contrib/blur-spark/pom.xml | 220 +++++++-------- .../blur/spark/BlurBulkLoadSparkProcessor.java | 59 ++++ .../blur/spark/BlurLoadSparkProcessor.java | 166 +++++++++++ .../spark/BlurMRBulkLoadSparkProcessor.java | 145 ++++++++++ .../apache/blur/spark/BlurSparkPartitioner.java | 37 ++- .../java/org/apache/blur/spark/Consumer.java | 280 ------------------- .../org/apache/blur/spark/ConsumerEnqueue.java | 240 ---------------- .../spark/example/SimpleSparkLoaderExample.java | 143 ++++++++++ .../apache/blur/spark/util/JavaSparkUtil.java | 137 +++++++++ 9 files changed, 769 insertions(+), 658 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/pom.xml ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/pom.xml b/contrib/blur-spark/pom.xml index 47e5904..83f845c 100644 --- a/contrib/blur-spark/pom.xml +++ b/contrib/blur-spark/pom.xml @@ -1,22 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> -<!-- -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. ---> +<!-- 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. --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> @@ -24,7 +16,7 @@ under the License. <groupId>org.apache.blur</groupId> <artifactId>blur</artifactId> <version>0.2.4-incubating-SNAPSHOT</version> - <relativePath>../../pom.xml</relativePath> + <relativePath>../../pom.xml</relativePath> </parent> <groupId>org.apache.blur</groupId> <artifactId>blur-spark-connector</artifactId> @@ -108,59 +100,9 @@ under the License. <dependencies> <dependency> - <groupId>org.apache.blur</groupId> - <artifactId>blur-thrift</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.blur</groupId> - <artifactId>blur-util</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.blur</groupId> - <artifactId>blur-core</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.blur</groupId> - <artifactId>blur-store</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.blur</groupId> - <artifactId>blur-query</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.blur</groupId> - <artifactId>blur-mapred-hadoop1</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-core</artifactId> - <version>${lucene.version}</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-spatial</artifactId> - <version>${lucene.version}</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-codecs</artifactId> - <version>${lucene.version}</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-analyzers-common</artifactId> - <version>${lucene.version}</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-queries</artifactId> - <version>${lucene.version}</version> + <groupId>org.apache.spark</groupId> + <artifactId>spark-streaming_2.10</artifactId> + <version>1.2.0</version> </dependency> <dependency> <groupId>junit</groupId> @@ -168,44 +110,8 @@ under the License. <version>${junit.version}</version> <scope>test</scope> </dependency> - <!-- dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - <version>1.3</version> - </dependency> - <dependency> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - <version>1.1.3</version> - </dependency> - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-core</artifactId> - <version>1.2.1</version> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - <version>1.7.4</version> - </dependency --> - - <dependency> - <groupId>org.apache.spark</groupId> - <artifactId>spark-core_2.10</artifactId> - <version>1.1.0</version> -</dependency> -<dependency> - <groupId>org.apache.spark</groupId> - <artifactId>spark-streaming_2.10</artifactId> - <version>1.1.0</version> -</dependency> - <!-- dependency> - <groupId>kafka.spark.consumer</groupId> - <artifactId>kafka-spark-consumer</artifactId> - <version>0.0.1-SNAPSHOT</version> - </dependency --> </dependencies> - + <profiles> <profile> <id>hadoop1</id> @@ -214,9 +120,35 @@ under the License. <name>hadoop1</name> </property> </activation> - <properties> - <projectVersion>${project.parent.version}-hadoop1</projectVersion> - </properties> + <dependencies> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-core</artifactId> + <version>${hadoop.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.blur</groupId> + <artifactId>blur-mapred-hadoop1</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <groupId>org.apache.blur</groupId> + <artifactId>blur-status</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-webapp</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-test</artifactId> + <version>${hadoop.version}</version> + <scope>test</scope> + </dependency> + </dependencies> </profile> <profile> <id>hadoop2-mr1</id> @@ -225,9 +157,35 @@ under the License. <name>hadoop2-mr1</name> </property> </activation> - <properties> - <projectVersion>${project.parent.version}-hadoop2-mr1</projectVersion> - </properties> + <dependencies> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-client</artifactId> + <version>${hadoop.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-minicluster</artifactId> + <version>${hadoop.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.blur</groupId> + <artifactId>blur-mapred-hadoop1</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <groupId>org.apache.blur</groupId> + <artifactId>blur-status</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-webapp</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> </profile> <profile> <id>hadoop2</id> @@ -236,9 +194,35 @@ under the License. <name>hadoop2</name> </property> </activation> - <properties> - <projectVersion>${project.parent.version}-hadoop2</projectVersion> - </properties> + <dependencies> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-client</artifactId> + <version>${hadoop.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-minicluster</artifactId> + <version>${hadoop.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.blur</groupId> + <artifactId>blur-mapred-hadoop2</artifactId> + <version>${project.version}</version> + <exclusions> + <exclusion> + <groupId>org.apache.blur</groupId> + <artifactId>blur-status</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-webapp</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> </profile> </profiles> </project> http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurBulkLoadSparkProcessor.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurBulkLoadSparkProcessor.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurBulkLoadSparkProcessor.java new file mode 100644 index 0000000..b89f981 --- /dev/null +++ b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurBulkLoadSparkProcessor.java @@ -0,0 +1,59 @@ +package org.apache.blur.spark; + +/** + * 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. + */ + +import org.apache.blur.thrift.generated.Blur.Iface; +import org.apache.blur.thrift.generated.RowMutation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.function.Function2; +import org.apache.spark.streaming.Time; + +import scala.Tuple2; + +@SuppressWarnings("serial") +public abstract class BlurBulkLoadSparkProcessor<T> extends BlurLoadSparkProcessor<T> { + + private static final Log LOG = LogFactory.getLog(BlurBulkLoadSparkProcessor.class); + + @Override + protected Function2<JavaPairRDD<String, RowMutation>, Time, Void> getFunction() { + return new Function2<JavaPairRDD<String, RowMutation>, Time, Void>() { + // Blur Thrift Client + @Override + public Void call(JavaPairRDD<String, RowMutation> rdd, Time time) throws Exception { + Iface client = getBlurClient(); + for (Tuple2<String, RowMutation> tuple : rdd.collect()) { + if (tuple != null) { + try { + RowMutation rm = tuple._2; + // Index using enqueue mutate call + client.enqueueMutate(rm); + } catch (Exception ex) { + LOG.error("Unknown error while trying to call enqueueMutate.", ex); + throw ex; + } + } + } + return null; + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurLoadSparkProcessor.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurLoadSparkProcessor.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurLoadSparkProcessor.java new file mode 100644 index 0000000..daa856c --- /dev/null +++ b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurLoadSparkProcessor.java @@ -0,0 +1,166 @@ +package org.apache.blur.spark; + +/** + * 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. + */ + +import java.io.IOException; +import java.io.Serializable; +import java.util.List; + +import org.apache.blur.mapreduce.lib.BlurMutate; +import org.apache.blur.spark.util.JavaSparkUtil; +import org.apache.blur.thrift.generated.Blur.Iface; +import org.apache.blur.thrift.generated.RowMutation; +import org.apache.hadoop.conf.Configuration; +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.function.Function2; +import org.apache.spark.api.java.function.PairFunction; +import org.apache.spark.storage.StorageLevel; +import org.apache.spark.streaming.Duration; +import org.apache.spark.streaming.Time; +import org.apache.spark.streaming.api.java.JavaDStream; +import org.apache.spark.streaming.api.java.JavaPairDStream; +import org.apache.spark.streaming.api.java.JavaStreamingContext; + +import scala.Tuple2; + +@SuppressWarnings("serial") +public abstract class BlurLoadSparkProcessor<T> implements Serializable { + + protected static final String MAPRED_OUTPUT_COMMITTER_CLASS = "mapred.output.committer.class"; + protected static final String MAPREDUCE_PARTITIONER_CLASS = "mapreduce.partitioner.class"; + protected static final String SPARK_STREAMING_BLOCK_INTERVAL = "spark.streaming.blockInterval"; + protected static final String SPARK_EXECUTOR_EXTRA_CLASS_PATH = "spark.executor.extraClassPath"; + protected static final String ORG_APACHE_SPARK_SERIALIZER_KRYO_SERIALIZER = "org.apache.spark.serializer.KryoSerializer"; + protected static final String SPARK_SERIALIZER = "spark.serializer"; + + public void run() throws IOException { + SparkConf conf = new SparkConf(); + conf.setAppName(getAppName()); + conf.set(SPARK_SERIALIZER, ORG_APACHE_SPARK_SERIALIZER_KRYO_SERIALIZER); + JavaSparkUtil.packProjectJars(conf); + setupSparkConf(conf); + + JavaStreamingContext ssc = new JavaStreamingContext(conf, getDuration()); + List<JavaDStream<T>> streamsList = getStreamsList(ssc); + + // Union all the streams if there is more than 1 stream + JavaDStream<T> streams = unionStreams(ssc, streamsList); + + JavaPairDStream<String, RowMutation> pairDStream = streams.mapToPair(new PairFunction<T, String, RowMutation>() { + public Tuple2<String, RowMutation> call(T t) { + RowMutation rowMutation = convert(t); + return new Tuple2<String, RowMutation>(rowMutation.getRowId(), rowMutation); + } + }); + + pairDStream.foreachRDD(getFunction()); + + ssc.start(); + ssc.awaitTermination(); + } + + protected abstract Function2<JavaPairRDD<String, RowMutation>, Time, Void> getFunction(); + + private JavaDStream<T> unionStreams(JavaStreamingContext ssc, List<JavaDStream<T>> streamsList) { + JavaDStream<T> unionStreams; + if (streamsList.size() > 1) { + unionStreams = ssc.union(streamsList.get(0), streamsList.subList(1, streamsList.size())); + } else { + // Otherwise, just use the 1 stream + unionStreams = streamsList.get(0); + } + return unionStreams; + } + + protected abstract String getOutputPath(); + + /** + * Gets the storage level for the spark job, default of MEMORY_ONLY_2. + * + * @return + */ + protected StorageLevel getStorageLevel() { + return StorageLevel.MEMORY_AND_DISK(); + } + + /** + * Called just before spark job is executed. + * + * @param configuration + */ + protected void setupBlurHadoopConfig(Configuration configuration) { + + } + + /** + * Add custom spark information. + * + * @param conf + */ + protected void setupSparkConf(SparkConf conf) { + + } + + /** + * Gets the duration for the batch, default of 10 seconds. + * + * @return + */ + protected Duration getDuration() { + return new Duration(10000); + } + + /** + * Gets the blur table name to load. + * + * @return + */ + protected abstract String getBlurTableName(); + + /** + * Gets the blur client for the table. + * + * @return + */ + protected abstract Iface getBlurClient(); + + /** + * Gets the spark application name. + * + * @return + */ + protected abstract String getAppName(); + + /** + * Gets the list of streams to load into Blur. + * + * @param ssc + * + * @return + */ + protected abstract List<JavaDStream<T>> getStreamsList(JavaStreamingContext ssc); + + /** + * Converts the data into a {@link BlurMutate} object. + * + * @param t + * @return + */ + protected abstract RowMutation convert(T t); +} http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurMRBulkLoadSparkProcessor.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurMRBulkLoadSparkProcessor.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurMRBulkLoadSparkProcessor.java new file mode 100644 index 0000000..124b000 --- /dev/null +++ b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurMRBulkLoadSparkProcessor.java @@ -0,0 +1,145 @@ +package org.apache.blur.spark; + +/** + * 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. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.blur.manager.BlurPartitioner; +import org.apache.blur.mapreduce.lib.BlurColumn; +import org.apache.blur.mapreduce.lib.BlurMutate; +import org.apache.blur.mapreduce.lib.BlurMutate.MUTATE_TYPE; +import org.apache.blur.mapreduce.lib.BlurOutputCommitter; +import org.apache.blur.mapreduce.lib.BlurOutputFormat; +import org.apache.blur.mapreduce.lib.BlurRecord; +import org.apache.blur.thrift.generated.Blur.Iface; +import org.apache.blur.thrift.generated.Column; +import org.apache.blur.thrift.generated.Record; +import org.apache.blur.thrift.generated.RecordMutation; +import org.apache.blur.thrift.generated.RowMutation; +import org.apache.blur.thrift.generated.TableDescriptor; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.io.Text; +import org.apache.hadoop.mapreduce.Job; +import org.apache.hadoop.mapreduce.Partitioner; +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.function.Function2; +import org.apache.spark.api.java.function.PairFlatMapFunction; +import org.apache.spark.streaming.Time; + +import scala.Tuple2; + +@SuppressWarnings("serial") +public abstract class BlurMRBulkLoadSparkProcessor<T> extends BlurLoadSparkProcessor<T> { + + @Override + protected Function2<JavaPairRDD<String, RowMutation>, Time, Void> getFunction() { + return new Function2<JavaPairRDD<String, RowMutation>, Time, Void>() { + @Override + public Void call(JavaPairRDD<String, RowMutation> rdd, Time time) throws Exception { + + // Blur Table Details + Iface client = getBlurClient(); + TableDescriptor tableDescriptor = client.describe(getBlurTableName()); + Configuration conf = new Configuration(); + // Blur specific Configuration + conf.setClass(MAPREDUCE_PARTITIONER_CLASS, BlurPartitioner.class, Partitioner.class); + conf.set(MAPRED_OUTPUT_COMMITTER_CLASS, BlurOutputCommitter.class.getName()); + + // Partition RDD to match Blur Table Shard Count. Used Custom + // Partitioner to channel correct BlurMutate to correct Shard. + BlurSparkPartitioner blurSparkPartitioner = new BlurSparkPartitioner(tableDescriptor.getShardCount()); + JavaPairRDD<Text, BlurMutate> flatMapToPair = rdd + .flatMapToPair(new PairFlatMapFunction<Tuple2<String, RowMutation>, Text, BlurMutate>() { + @Override + public Iterable<Tuple2<Text, BlurMutate>> call(Tuple2<String, RowMutation> tuple2) throws Exception { + RowMutation rowMutation = tuple2._2; + final List<BlurMutate> result = new ArrayList<BlurMutate>(); + List<RecordMutation> recordMutations = rowMutation.getRecordMutations(); + String rowId = rowMutation.getRowId(); + for (RecordMutation recordMutation : recordMutations) { + Record record = recordMutation.getRecord(); + String family = record.getFamily(); + String recordId = record.getRecordId(); + List<BlurColumn> columns = toColumns(record.getColumns()); + + BlurRecord blurRecord = new BlurRecord(); + blurRecord.setRowId(rowId); + blurRecord.setFamily(family); + blurRecord.setRecordId(recordId); + blurRecord.setColumns(columns); + result.add(new BlurMutate(MUTATE_TYPE.REPLACE, blurRecord)); + } + return new Iterable<Tuple2<Text, BlurMutate>>() { + @Override + public Iterator<Tuple2<Text, BlurMutate>> iterator() { + final Iterator<BlurMutate> iterator = result.iterator(); + return new Iterator<Tuple2<Text, BlurMutate>>() { + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public Tuple2<Text, BlurMutate> next() { + BlurMutate blurMutate = iterator.next(); + return new Tuple2<Text, BlurMutate>(new Text(blurMutate.getRecord().getRowId()), blurMutate); + } + + @Override + public void remove() { + + } + }; + } + }; + } + + private List<BlurColumn> toColumns(List<Column> columns) { + List<BlurColumn> cols = new ArrayList<BlurColumn>(); + for (Column column : columns) { + cols.add(new BlurColumn(column.getName(), column.getValue())); + } + return cols; + } + }); + + final JavaPairRDD<Text, BlurMutate> pRdd = flatMapToPair.partitionBy(blurSparkPartitioner).persist( + getStorageLevel()); + Job job = new Job(conf); + BlurOutputFormat.setupJob(job, tableDescriptor); + Path path = new Path(getOutputPath()); + FileSystem fileSystem = path.getFileSystem(conf); + Path qualified = fileSystem.makeQualified(path); + BlurOutputFormat.setOutputPath(job, qualified); + setupBlurHadoopConfig(job.getConfiguration()); + // Write the RDD to Blur Table + if (pRdd.count() > 0) { + pRdd.saveAsNewAPIHadoopFile(tableDescriptor.getTableUri(), Text.class, BlurMutate.class, + BlurOutputFormat.class, job.getConfiguration()); + client.loadData(getBlurTableName(), qualified.toString()); + } + return null; + } + }; + } +} http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurSparkPartitioner.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurSparkPartitioner.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurSparkPartitioner.java index 728ad36..1c5c425 100644 --- a/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurSparkPartitioner.java +++ b/contrib/blur-spark/src/main/java/org/apache/blur/spark/BlurSparkPartitioner.java @@ -22,24 +22,21 @@ import org.apache.spark.HashPartitioner; public class BlurSparkPartitioner extends HashPartitioner { - private static final long serialVersionUID = 9853263327838L; - - int totalShard; - - public BlurSparkPartitioner(int partitions) { - - super(partitions); - totalShard = partitions; - } - - @Override - public int getPartition(Object key) { - - if (key instanceof Text) { - - return (key.hashCode() & Integer.MAX_VALUE) % totalShard; - } else { - return super.getPartition(key); - } - } + private static final long serialVersionUID = 9853263327838L; + + private final int _totalShard; + + public BlurSparkPartitioner(int partitions) { + super(partitions); + _totalShard = partitions; + } + + @Override + public int getPartition(Object key) { + if (key instanceof Text) { + return (key.hashCode() & Integer.MAX_VALUE) % _totalShard; + } else { + return super.getPartition(key); + } + } } http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/Consumer.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/Consumer.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/Consumer.java deleted file mode 100644 index 962faa4..0000000 --- a/contrib/blur-spark/src/main/java/org/apache/blur/spark/Consumer.java +++ /dev/null @@ -1,280 +0,0 @@ -package org.apache.blur.spark; - -/** - * 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. - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.apache.blur.manager.BlurPartitioner; -import org.apache.blur.mapreduce.lib.BlurMapReduceUtil; -import org.apache.blur.mapreduce.lib.BlurMutate; -import org.apache.blur.mapreduce.lib.BlurOutputCommitter; -import org.apache.blur.mapreduce.lib.BlurOutputFormat; -import org.apache.blur.mapreduce.lib.DefaultBlurReducer; -import org.apache.blur.thrift.generated.TableDescriptor; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.OptionBuilder; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.PosixParser; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.io.Text; -import org.apache.hadoop.mapred.JobConf; -import org.apache.hadoop.mapreduce.OutputFormat; -import org.apache.hadoop.mapreduce.Partitioner; -import org.apache.hadoop.mapreduce.Reducer; -import org.apache.spark.SparkConf; -import org.apache.spark.api.java.JavaPairRDD; -import org.apache.spark.api.java.function.Function2; -import org.apache.spark.api.java.function.PairFunction; -import org.apache.spark.storage.StorageLevel; -import org.apache.spark.streaming.Duration; -import org.apache.spark.streaming.Time; -import org.apache.spark.streaming.api.java.JavaDStream; -import org.apache.spark.streaming.api.java.JavaPairDStream; -import org.apache.spark.streaming.api.java.JavaStreamingContext; - -import scala.Tuple2; -import consumer.kafka.KafkaConfig; -import consumer.kafka.MessageAndMetadata; -import consumer.kafka.client.KafkaReceiver; - -/* - * This Consumer uses Spark RDD saveAsNewAPIHadoopFile API to index BlurMutate - */ - -public class Consumer implements Serializable { - - private static final long serialVersionUID = 4332618245650072140L; - private Properties _props; - private KafkaConfig _kafkaConfig; - - public void start() throws InstantiationException, IllegalAccessException, - ClassNotFoundException { - - _kafkaConfig = new KafkaConfig(_props); - run(); - } - - private void init(String[] args) throws Exception { - - Options options = new Options(); - this._props = new Properties(); - - options.addOption("p", true, "properties filename from the classpath"); - options.addOption("P", true, "external properties filename"); - - OptionBuilder.withArgName("property=value"); - OptionBuilder.hasArgs(2); - OptionBuilder.withValueSeparator(); - OptionBuilder.withDescription("use value for given property"); - options.addOption(OptionBuilder.create("D")); - - CommandLineParser parser = new PosixParser(); - CommandLine cmd = parser.parse(options, args); - if (cmd.hasOption('p')) { - this._props.load(ClassLoader.getSystemClassLoader() - .getResourceAsStream(cmd.getOptionValue('p'))); - } - if (cmd.hasOption('P')) { - File file = new File(cmd.getOptionValue('P')); - FileInputStream fStream = new FileInputStream(file); - this._props.load(fStream); - } - this._props.putAll(cmd.getOptionProperties("D")); - - } - - private void run() { - - String checkpointDirectory = "hdfs://10.252.5.113:9000/user/hadoop/spark"; - - // number of partition for Kafka Topic - - int _partitionCount = 5; - - List<JavaDStream<MessageAndMetadata>> streamsList = new ArrayList<JavaDStream<MessageAndMetadata>>( - _partitionCount); - JavaDStream<MessageAndMetadata> unionStreams; - - SparkConf conf = new SparkConf().setAppName("KafkaReceiver").set( - "spark.streaming.blockInterval", "200"); - - // Path to Blur Libraries . Can be copied to each Node of Spark Cluster. - - conf.set("spark.executor.extraClassPath", - "/home/apache-blur-0.2.4/lib/*"); - - // Used KryoSerializer for BlurMutate and Text. - conf.set("spark.serializer", - "org.apache.spark.serializer.KryoSerializer"); - - JavaStreamingContext ssc = new JavaStreamingContext(conf, new Duration( - 3000)); - - /* - * Receive Kafka Stream. Create individual Receivers for each Topic - * Partition - */ - - for (int i = 0; i < _partitionCount; i++) { - - streamsList.add(ssc.receiverStream(new KafkaReceiver(_props, i))); - - } - - /* - * Union all the streams if there is more than 1 stream - */ - - if (streamsList.size() > 1) { - unionStreams = ssc.union(streamsList.get(0), - streamsList.subList(1, streamsList.size())); - } else { - // Otherwise, just use the 1 stream - unionStreams = streamsList.get(0); - } - - /* - * Generate JavaPairDStream - */ - - JavaPairDStream<Text, BlurMutate> pairDStream = unionStreams - .mapToPair(new PairFunction<MessageAndMetadata, Text, BlurMutate>() { - - private static final long serialVersionUID = 443235214978L; - - public Tuple2<Text, BlurMutate> call( - MessageAndMetadata mmeta) { - - /* - * create the BlurMutate from MessageAndMetadata - */ - - String message = new String(mmeta.getPayload()); - String keyStr = DigestUtils.shaHex(message); - Text key = new Text((keyStr).getBytes()); - BlurMutate mutate = new BlurMutate( - BlurMutate.MUTATE_TYPE.REPLACE, keyStr, keyStr, - "family"); - mutate.addColumn("message", message); - - return new Tuple2<Text, BlurMutate>(key, mutate); - } - }); - - pairDStream - .foreachRDD(new Function2<JavaPairRDD<Text, BlurMutate>, Time, Void>() { - - private static final long serialVersionUID = 88875777435L; - - @Override - public Void call(JavaPairRDD<Text, BlurMutate> rdd, - Time time) throws Exception { - - /* - * Blur Table Details - */ - TableDescriptor tableDescriptor = new TableDescriptor(); - String tableUri = new Path( - "hdfs://10.252.5.113:9000/blur/tables/nrt") - .toString(); - tableDescriptor.tableUri = tableUri; - tableDescriptor.cluster = "pearson"; - tableDescriptor.name = "nrt"; - tableDescriptor.shardCount = 9; - Configuration conf = new Configuration(); - - /* - * Partition RDD to match Blur Table Shard Count. Used - * Custom Partitioner to channel correct BlurMutate to - * correct Shard. - */ - - final JavaPairRDD<Text, BlurMutate> pRdd = rdd - .partitionBy( - new BlurSparkPartitioner( - tableDescriptor.shardCount)) - .persist(StorageLevel.MEMORY_ONLY_2()); - - /* - * Blur specific Configuration - */ - - BlurOutputFormat.setIndexLocally(conf, false); - BlurOutputFormat.setOptimizeInFlight(conf, false); - conf.setClass("mapreduce.reduce.class", - DefaultBlurReducer.class, Reducer.class); - conf.setClass("mapreduce.outputformat.class", - BlurOutputFormat.class, OutputFormat.class); - conf.setClass("mapreduce.partitioner.class", - BlurPartitioner.class, Partitioner.class); - conf.set("mapred.output.committer.class", - BlurOutputCommitter.class.getName()); - conf.setInt("blur.output.max.document.buffer.size", - 10000); - - BlurOutputFormat.setTableDescriptor(conf, - tableDescriptor); - - JobConf jobConf = new JobConf(conf); - - jobConf.setNumReduceTasks(tableDescriptor.shardCount); - jobConf.setOutputKeyClass(Text.class); - jobConf.setOutputValueClass(BlurMutate.class); - - BlurMapReduceUtil.addAllJarsInBlurLib(conf); - BlurMapReduceUtil - .addDependencyJars( - conf, - org.apache.zookeeper.ZooKeeper.class, - org.apache.lucene.codecs.lucene42.Lucene42Codec.class, - jobConf.getOutputKeyClass(), - jobConf.getOutputValueClass()); - - /* - * Write the RDD to Blur Table - */ - - if (pRdd.count() > 0) - pRdd.saveAsNewAPIHadoopFile(tableUri, Text.class, - BlurMutate.class, BlurOutputFormat.class, - jobConf); - - return null; - } - }); - - // ssc.checkpoint(checkpointDirectory); - ssc.start(); - ssc.awaitTermination(); - } - - public static void main(String[] args) throws Exception { - - Consumer consumer = new Consumer(); - consumer.init(args); - consumer.start(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/ConsumerEnqueue.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/ConsumerEnqueue.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/ConsumerEnqueue.java deleted file mode 100644 index 25f2d58..0000000 --- a/contrib/blur-spark/src/main/java/org/apache/blur/spark/ConsumerEnqueue.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.apache.blur.spark; - -/** - * 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. - */ - -import java.io.File; -import java.io.FileInputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.apache.blur.thrift.BlurClient; -import org.apache.blur.thrift.generated.Blur.Iface; -import org.apache.blur.thrift.generated.Column; -import org.apache.blur.thrift.generated.Record; -import org.apache.blur.thrift.generated.RecordMutation; -import org.apache.blur.thrift.generated.RecordMutationType; -import org.apache.blur.thrift.generated.RowMutation; -import org.apache.blur.thrift.generated.RowMutationType; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.OptionBuilder; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.PosixParser; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.spark.SparkConf; -import org.apache.spark.api.java.JavaPairRDD; -import org.apache.spark.api.java.function.Function2; -import org.apache.spark.api.java.function.PairFunction; -import org.apache.spark.streaming.Duration; -import org.apache.spark.streaming.Time; -import org.apache.spark.streaming.api.java.JavaDStream; -import org.apache.spark.streaming.api.java.JavaPairDStream; -import org.apache.spark.streaming.api.java.JavaStreamingContext; - -import scala.Tuple2; -import consumer.kafka.KafkaConfig; -import consumer.kafka.MessageAndMetadata; -import consumer.kafka.client.KafkaReceiver; - - -/* - * This Consumer uses Blur Thrift Client enqueue mutate call to index Rowmutation - */ -public class ConsumerEnqueue implements Serializable { - - private static final long serialVersionUID = 4332618245650072140L; - private Properties _props; - private KafkaConfig _kafkaConfig; - - public void start() throws InstantiationException, IllegalAccessException, - ClassNotFoundException { - - _kafkaConfig = new KafkaConfig(_props); - run(); - } - - private void init(String[] args) throws Exception { - - Options options = new Options(); - this._props = new Properties(); - - options.addOption("p", true, "properties filename from the classpath"); - options.addOption("P", true, "external properties filename"); - - OptionBuilder.withArgName("property=value"); - OptionBuilder.hasArgs(2); - OptionBuilder.withValueSeparator(); - OptionBuilder.withDescription("use value for given property"); - options.addOption(OptionBuilder.create("D")); - - CommandLineParser parser = new PosixParser(); - CommandLine cmd = parser.parse(options, args); - if (cmd.hasOption('p')) { - this._props.load(ClassLoader.getSystemClassLoader() - .getResourceAsStream(cmd.getOptionValue('p'))); - } - if (cmd.hasOption('P')) { - File file = new File(cmd.getOptionValue('P')); - FileInputStream fStream = new FileInputStream(file); - this._props.load(fStream); - } - this._props.putAll(cmd.getOptionProperties("D")); - - } - - private void run() { - - String checkpointDirectory = "hdfs://10.252.5.113:9000/user/hadoop/spark"; - - // number of partition for Kafka Topic - - int _partitionCount = 5; - - List<JavaDStream<MessageAndMetadata>> streamsList = new ArrayList<JavaDStream<MessageAndMetadata>>( - _partitionCount); - JavaDStream<MessageAndMetadata> unionStreams; - - SparkConf conf = new SparkConf().setAppName("KafkaReceiver").set( - "spark.streaming.blockInterval", "200"); - - // Path to Blur Libraries . Can be copied to each Node of Spark Cluster. - - conf.set("spark.executor.extraClassPath", - "/home/apache-blur-0.2.4/lib/*"); - - // Used KryoSerializer for BlurMutate and Text. - conf.set("spark.serializer", - "org.apache.spark.serializer.KryoSerializer"); - - JavaStreamingContext ssc = new JavaStreamingContext(conf, new Duration( - 3000)); - - /* - * Receive Kafka Stream. Create individual Receivers for each Topic - * Partition - */ - - for (int i = 0; i < _partitionCount; i++) { - - streamsList.add(ssc.receiverStream(new KafkaReceiver(_props, i))); - - } - - /* - * Union all the streams if there is more than 1 stream - */ - - if (streamsList.size() > 1) { - unionStreams = ssc.union(streamsList.get(0), - streamsList.subList(1, streamsList.size())); - } else { - // Otherwise, just use the 1 stream - unionStreams = streamsList.get(0); - } - - /* - * Generate JavaPairDStream - */ - - JavaPairDStream<String, RowMutation> pairDStream = unionStreams - .mapToPair(new PairFunction<MessageAndMetadata, String, RowMutation>() { - - private static final long serialVersionUID = 443235214978L; - - public Tuple2<String, RowMutation> call( - MessageAndMetadata mmeta) { - - /* - * create the RowMutation from MessageAndMetadata - */ - - String message = new String(mmeta.getPayload()); - String keyStr = DigestUtils.shaHex(message); - - Record record = new Record(); - record.setRecordId(keyStr); - record.addToColumns(new Column("message", message)); - record.setFamily("family"); - - List recordMutations = new ArrayList(); - recordMutations.add(new RecordMutation( - RecordMutationType.REPLACE_ENTIRE_RECORD, - record)); - RowMutation mutation = new RowMutation("nrt", keyStr, - RowMutationType.REPLACE_ROW, recordMutations); - mutation.setRecordMutations(recordMutations); - - return new Tuple2<String, RowMutation>(keyStr, mutation); - } - }); - - pairDStream - .foreachRDD(new Function2<JavaPairRDD<String, RowMutation>, Time, Void>() { - - private static final long serialVersionUID = 88875777435L; - - /* - * Blur Thrift Client - */ - - Iface client = BlurClient.getClient("10.252.5.113:40010"); - - @Override - public Void call(JavaPairRDD<String, RowMutation> rdd, - Time time) throws Exception { - - for (Tuple2<String, RowMutation> tuple : rdd.collect()) { - - if (tuple != null) { - - try { - - RowMutation rm = tuple._2; - - /* - * Index using enqueue mutate call - */ - client.enqueueMutate(rm); - - } catch (Exception ex) { - - ex.printStackTrace(); - } - - } - - } - - return null; - } - }); - - // ssc.checkpoint(checkpointDirectory); - ssc.start(); - ssc.awaitTermination(); - } - - public static void main(String[] args) throws Exception { - - ConsumerEnqueue consumer = new ConsumerEnqueue(); - consumer.init(args); - consumer.start(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/example/SimpleSparkLoaderExample.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/example/SimpleSparkLoaderExample.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/example/SimpleSparkLoaderExample.java new file mode 100644 index 0000000..59b6992 --- /dev/null +++ b/contrib/blur-spark/src/main/java/org/apache/blur/spark/example/SimpleSparkLoaderExample.java @@ -0,0 +1,143 @@ +/** + * 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.blur.spark.example; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.blur.spark.BlurMRBulkLoadSparkProcessor; +import org.apache.blur.thrift.BlurClient; +import org.apache.blur.thrift.generated.Blur.Iface; +import org.apache.blur.thrift.generated.Column; +import org.apache.blur.thrift.generated.Record; +import org.apache.blur.thrift.generated.RecordMutation; +import org.apache.blur.thrift.generated.RecordMutationType; +import org.apache.blur.thrift.generated.RowMutation; +import org.apache.blur.thrift.generated.RowMutationType; +import org.apache.spark.SparkConf; +import org.apache.spark.storage.StorageLevel; +import org.apache.spark.streaming.api.java.JavaDStream; +import org.apache.spark.streaming.api.java.JavaStreamingContext; + +@SuppressWarnings("serial") +public class SimpleSparkLoaderExample extends BlurMRBulkLoadSparkProcessor<String> { + + public static void main(String[] args) throws IOException { + SimpleSparkLoaderExample loader = new SimpleSparkLoaderExample(); + loader.setConnectionStr("127.0.0.1:40010"); + // loader.setHdfsDirToMonitor("hdfs://localhost:9000/tmp/spark/input/"); + loader.setHdfsDirToMonitor("file:///tmp/spark-input/"); + loader.setOutputPath("hdfs://localhost:9000/tmp/spark/output-" + System.currentTimeMillis()); + loader.setSparkMaster("spark://amccurry:7077"); + loader.setTableName("test_hdfs"); + loader.run(); + } + + private String _tableName; + private String _connectionStr; + private String _hdfsDirToMonitor; + private String _sparkMaster; + private String _outputPath; + + @Override + protected void setupSparkConf(SparkConf conf) { + conf.set("spark.master", _sparkMaster); + } + + @Override + protected String getBlurTableName() { + return _tableName; + } + + @Override + protected Iface getBlurClient() { + return BlurClient.getClient(_connectionStr); + } + + @Override + protected String getAppName() { + return "Sample Blur Loader"; + } + + @SuppressWarnings("unchecked") + @Override + protected List<JavaDStream<String>> getStreamsList(JavaStreamingContext ssc) { + return Arrays.asList(ssc.textFileStream(_hdfsDirToMonitor)); + } + + @Override + protected RowMutation convert(String s) { + s = s.trim(); + String rowId = s; + String recordId = s; + String value = s; + + List<Column> columns = new ArrayList<Column>(); + columns.add(new Column("col", value)); + Record record = new Record(recordId, "spark-test", columns); + + RowMutation rowMutation = new RowMutation(); + rowMutation.setTable(getTableName()); + rowMutation.setRowMutationType(RowMutationType.REPLACE_ROW); + rowMutation.setRowId(rowId); + rowMutation.addToRecordMutations(new RecordMutation(RecordMutationType.REPLACE_ENTIRE_RECORD, record)); + return rowMutation; + } + + @Override + protected String getOutputPath() { + return _outputPath; + } + + public String getTableName() { + return _tableName; + } + + public String getConnectionStr() { + return _connectionStr; + } + + public String getHdfsDirToMonitor() { + return _hdfsDirToMonitor; + } + + public String getSparkMaster() { + return _sparkMaster; + } + + public void setTableName(String tableName) { + _tableName = tableName; + } + + public void setConnectionStr(String connectionStr) { + _connectionStr = connectionStr; + } + + public void setHdfsDirToMonitor(String hdfsDirToMonitor) { + _hdfsDirToMonitor = hdfsDirToMonitor; + } + + public void setSparkMaster(String sparkMaster) { + _sparkMaster = sparkMaster; + } + + public void setOutputPath(String outputPath) { + _outputPath = outputPath; + } +} http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/2db2ee80/contrib/blur-spark/src/main/java/org/apache/blur/spark/util/JavaSparkUtil.java ---------------------------------------------------------------------- diff --git a/contrib/blur-spark/src/main/java/org/apache/blur/spark/util/JavaSparkUtil.java b/contrib/blur-spark/src/main/java/org/apache/blur/spark/util/JavaSparkUtil.java new file mode 100644 index 0000000..6cea91a --- /dev/null +++ b/contrib/blur-spark/src/main/java/org/apache/blur/spark/util/JavaSparkUtil.java @@ -0,0 +1,137 @@ +package org.apache.blur.spark.util; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.spark.SparkConf; + +import com.google.common.base.Splitter; + +public class JavaSparkUtil { + + private static final String DOT = "."; + private static final String TMP_SPARK_JOB = "tmp-spark-job_"; + private static final String JAR = ".jar"; + private static final String PATH_SEPARATOR = "path.separator"; + private static final String JAVA_CLASS_PATH = "java.class.path"; + private static final String SEP = "/"; + + public static void packProjectJars(SparkConf conf) throws IOException { + String classPath = System.getProperty(JAVA_CLASS_PATH); + String pathSeparator = System.getProperty(PATH_SEPARATOR); + Splitter splitter = Splitter.on(pathSeparator); + Iterable<String> split = splitter.split(classPath); + List<String> list = toList(split); + List<String> classPathThatNeedsToBeIncluded = removeSparkLibs(list); + List<String> jars = new ArrayList<String>(); + for (String s : classPathThatNeedsToBeIncluded) { + if (isJarFile(s)) { + jars.add(s); + } else { + jars.add(createJar(s)); + } + } + conf.setJars(jars.toArray(new String[jars.size()])); + } + + private static String createJar(String s) throws IOException { + File sourceFile = new File(s); + if (sourceFile.isDirectory()) { + File file = File.createTempFile(TMP_SPARK_JOB, JAR); + OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); + JarOutputStream jarOut = new JarOutputStream(outputStream); + for (File f : sourceFile.listFiles()) { + pack(sourceFile, f, jarOut); + } + jarOut.close(); + file.deleteOnExit(); + return file.getAbsolutePath(); + } + throw new RuntimeException("File [" + s + "] is not a directory."); + } + + private static void pack(File rootPath, File source, JarOutputStream target) throws IOException { + String name = getName(rootPath, source); + if (source.isDirectory()) { + if (!SEP.equals(name)) { + JarEntry entry = new JarEntry(name); + entry.setTime(source.lastModified()); + target.putNextEntry(entry); + target.closeEntry(); + } + for (File f : source.listFiles()) { + pack(rootPath, f, target); + } + } else { + JarEntry entry = new JarEntry(name); + entry.setTime(source.lastModified()); + target.putNextEntry(entry); + BufferedInputStream in = new BufferedInputStream(new FileInputStream(source)); + IOUtils.copy(in, target); + in.close(); + target.closeEntry(); + } + } + + private static String getName(File rootPath, File source) { + String rootStr = rootPath.toURI().toString(); + String sourceStr = source.toURI().toString(); + if (sourceStr.startsWith(rootStr)) { + String result = sourceStr.substring(rootStr.length()); + if (source.isDirectory() && !result.endsWith(SEP)) { + result += SEP; + } + return result; + } else { + throw new RuntimeException("Not sure what happened."); + } + } + + private static boolean isJarFile(String s) { + if (s.endsWith(JAR) || s.endsWith(".zip")) { + return true; + } + return false; + } + + private static List<String> removeSparkLibs(List<String> list) { + String sparkJar = findSparkJar(list); + String sparkLib = sparkJar.substring(0, sparkJar.lastIndexOf(SEP) + 1); + List<String> result = new ArrayList<String>(); + for (String s : list) { + if (!s.startsWith(sparkLib)) { + result.add(s); + } + } + return result; + } + + private static String findSparkJar(List<String> list) { + String name = SparkConf.class.getName(); + String resourceName = SEP + name.replace(DOT, SEP) + ".class"; + URL url = SparkConf.class.getResource(resourceName); + String urlStr = url.toString(); + urlStr = urlStr.substring(0, urlStr.indexOf('!')); + urlStr = urlStr.substring(urlStr.lastIndexOf(':') + 1); + return urlStr; + } + + private static List<String> toList(Iterable<String> split) { + List<String> list = new ArrayList<String>(); + for (String s : split) { + list.add(s); + } + return list; + } +} \ No newline at end of file
