package mil.nga.giat.geowave.examples.ingest;
import java.io.IOException;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import mil.nga.giat.geowave.adapter.vector.GeotoolsFeatureDataAdapter;
import mil.nga.giat.geowave.core.store.DataStore;
import mil.nga.giat.geowave.core.store.IndexWriter;
import mil.nga.giat.geowave.core.store.index.PrimaryIndex;
import mil.nga.giat.geowave.datastore.accumulo.BasicAccumuloOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleIngestProducerConsumer extends
SimpleIngest
{
private static Logger log = LoggerFactory.getLogger(SimpleIngestProducerConsumer.class);
private final FeatureCollection features = new FeatureCollection();
public static void main(
final String[] args ) {
if ((args == null) || (args.length == 0)) {
log.error("Invalid arguments, expected: dataStoreOptions");
System.exit(1);
}
final SimpleIngestProducerConsumer si = new SimpleIngestProducerConsumer();
DataStore geowaveDataStore = null;
String namespace = null;
String instance = null;
if (args.length != 5) {
log
.error("Invalid arguments, expected: zookeepers, accumuloInstance, accumuloUser, accumuloPass, geowaveNamespace");
System.exit(1);
}
namespace = args[5];
instance = args[2];
try {
final BasicAccumuloOperations bao = si.getAccumuloOperationsInstance(
args[1],
args[2],
args[3],
args[4],
args[5]);
geowaveDataStore = si.getAccumuloGeowaveDataStore(bao);
}
catch (final Exception e) {
log.error(
"Error creating BasicAccumuloOperations",
e);
System.exit(1);
}
si.generateGrid(geowaveDataStore);
System.out
.println("Finished ingesting data to namespace: " + namespace + " at datastore instance: " + instance);
}
/***
* Here we will change the ingest mechanism to use a producer/consumer
* pattern
*/
protected void generateGrid(
final DataStore geowaveDataStore ) {
// In order to store data we need to determine the type of data store
final SimpleFeatureType point = createPointFeatureType();
// This a factory class that builds simple feature objects based on the
// type passed
final SimpleFeatureBuilder pointBuilder = new SimpleFeatureBuilder(
point);
// This is an adapter, that is needed to describe how to persist the
// data type passed
final GeotoolsFeatureDataAdapter adapter = createDataAdapter(point);
// This describes how to index the data
final PrimaryIndex index = createSpatialIndex();
final Thread ingestThread = new Thread(
new Runnable() {
@Override
public void run() {
try (IndexWriter writer = geowaveDataStore.createWriter(
adapter,
index)) {
while (features.hasNext()) {
final SimpleFeature sft = features.next();
writer.write(sft);
}
}
catch (final IOException e) {
log.error(
"Unable to create writer",
e);
}
}
},
"Ingestion Thread");
ingestThread.start();
// build a grid of points across the globe at each whole
// latitude/longitude intersection
for (final SimpleFeature sft : getGriddedFeatures(
pointBuilder,
-10000)) {
features.add(sft);
}
features.ingestCompleted = true;
try {
ingestThread.join();
}
catch (final InterruptedException e) {
log.error(
"Error joining ingest thread",
e);
}
}
protected static class FeatureCollection implements
Iterator<SimpleFeature>
{
private final BlockingQueue<SimpleFeature> queue = new LinkedBlockingQueue<>(
10000);
public boolean ingestCompleted = false;
public void add(
final SimpleFeature sft ) {
try {
queue.put(sft);
}
catch (final InterruptedException e) {
log.error(
"Error inserting next item into queue",
e);
}
}
@Override
public boolean hasNext() {
return !(ingestCompleted && queue.isEmpty());
}
@Override
public SimpleFeature next() {
try {
return queue.take();
}
catch (final InterruptedException e) {
log.error(
"Error getting next item from queue",
e);
}
return null;
}
@Override
public void remove() {
log.error("Remove called, method not implemented");
}
}
}