package mil.nga.giat.geowave.core.store.index;
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import mil.nga.giat.geowave.core.index.ByteArrayId;
import mil.nga.giat.geowave.core.store.DataStoreOperations;
import mil.nga.giat.geowave.core.store.DataStoreOptions;
import mil.nga.giat.geowave.core.store.IndexWriter;
import mil.nga.giat.geowave.core.store.adapter.DataAdapter;
import mil.nga.giat.geowave.core.store.base.DataStoreEntryInfo;
import mil.nga.giat.geowave.core.store.base.Writer;
import mil.nga.giat.geowave.core.store.callback.IngestCallback;
import mil.nga.giat.geowave.core.store.data.VisibilityWriter;
import mil.nga.giat.geowave.core.store.util.DataStoreUtils;
/**
* This class can write many entries for a single index by retaining a single
* open writer. The first entry that is written will open a writer and it is the
* responsibility of the caller to close this writer when complete.
*
*/
public abstract class DataStoreIndexWriter<T, MutationType> implements
IndexWriter<T>
{
private final static Logger LOGGER = LoggerFactory.getLogger(DataStoreIndexWriter.class);
protected final PrimaryIndex index;
protected final DataStoreOperations operations;
protected final DataStoreOptions options;
protected final IngestCallback<T> callback;
protected Writer<MutationType> writer;
protected final DataAdapter<T> adapter;
protected final byte[] adapterId;
final Closeable closable;
public DataStoreIndexWriter(
final DataAdapter<T> adapter,
final PrimaryIndex index,
final DataStoreOperations operations,
final DataStoreOptions options,
final IngestCallback<T> callback,
final Closeable closable ) {
this.index = index;
this.operations = operations;
this.options = options;
this.callback = callback;
this.adapter = adapter;
this.adapterId = adapter.getAdapterId().getBytes();
this.closable = closable;
}
protected synchronized void closeInternal() {
if (writer != null) {
try {
writer.close();
writer = null;
}
catch (IOException e) {
LOGGER.warn(
"Unable to close writer",
e);
}
}
}
@Override
public PrimaryIndex[] getIndices() {
return new PrimaryIndex[] {
index
};
}
@Override
public List<ByteArrayId> write(
final T entry )
throws IOException {
return write(
entry,
DataStoreUtils.UNCONSTRAINED_VISIBILITY);
}
@Override
public List<ByteArrayId> write(
final T entry,
final VisibilityWriter<T> fieldVisibilityWriter )
throws IOException {
DataStoreEntryInfo entryInfo;
synchronized (this) {
ensureOpen();
if (writer == null) {
LOGGER.error("Null writer - empty list returned");
return Collections.emptyList();
}
entryInfo = getEntryInfo(
entry,
fieldVisibilityWriter);
if (entryInfo == null) {
LOGGER.error("Null EntryInfo - empty list returned");
return Collections.emptyList();
}
callback.entryIngested(
entryInfo,
entry);
}
return entryInfo.getRowIds();
}
protected abstract void ensureOpen()
throws IOException;
protected abstract DataStoreEntryInfo getEntryInfo(
final T entry,
final VisibilityWriter<T> visibilityWriter );
@Override
public void close() {
try {
closable.close();
}
catch (final IOException e) {
LOGGER.error(
"Cannot close callbacks",
e);
}
// thread safe close
closeInternal();
}
@Override
public synchronized void flush() {
// thread safe flush of the writers
if (writer != null) {
writer.flush();
}
if (this.callback instanceof Flushable) {
try {
((Flushable) callback).flush();
}
catch (final IOException e) {
LOGGER.error(
"Cannot flush callbacks",
e);
}
}
}
}