org.eclipse.rdf4j.lucene.spin.LuceneSpinSailConnection Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2017 Eclipse RDF4J contributors, Aduna, and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*******************************************************************************/
package org.eclipse.rdf4j.lucene.spin;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.rdf4j.common.annotation.Experimental;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.sail.NotifyingSailConnection;
import org.eclipse.rdf4j.sail.SailConnectionListener;
import org.eclipse.rdf4j.sail.SailException;
import org.eclipse.rdf4j.sail.helpers.NotifyingSailConnectionWrapper;
import org.eclipse.rdf4j.sail.lucene.LuceneSailBuffer;
import org.eclipse.rdf4j.sail.lucene.LuceneSailBuffer.AddRemoveOperation;
import org.eclipse.rdf4j.sail.lucene.LuceneSailBuffer.ClearContextOperation;
import org.eclipse.rdf4j.sail.lucene.LuceneSailBuffer.Operation;
import org.eclipse.rdf4j.sail.lucene.LuceneSailConnection;
import org.eclipse.rdf4j.sail.lucene.SearchIndex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This connection inherits Lucene index supporting methods from {@link LuceneSailConnection}.
*
* @author sauermann
* @author christian.huetter
* @author jacek grzebyta
*
* @deprecated since 3.0. The experimental LuceneSpinSail is scheduled to be removed by the next major release.
*/
@Deprecated
@Experimental
public class LuceneSpinSailConnection extends NotifyingSailConnectionWrapper {
private static final Logger logger = LoggerFactory.getLogger(LuceneSpinSailConnection.class);
private final SearchIndex luceneIndex;
private final LuceneSpinSail sail;
/**
* the buffer that collects operations
*/
private final LuceneSailBuffer buffer = new LuceneSailBuffer();
/**
* The listener that listens to the underlying connection. It is disabled during clearContext operations.
*/
protected final SailConnectionListener connectionListener = new SailConnectionListener() {
@Override
public void statementAdded(Statement statement) {
// we only consider statements that contain literals
if (statement.getObject() instanceof Literal) {
statement = sail.mapStatement(statement);
// process only mapped/indexable statements
if (statement == null) {
return;
}
// we further only index statements where the Literal's datatype is
// accepted
Literal literal = (Literal) statement.getObject();
if (luceneIndex.accept(literal)) {
buffer.add(statement);
}
}
}
@Override
public void statementRemoved(Statement statement) {
// we only consider statements that contain literals
if (statement.getObject() instanceof Literal) {
// process oly mapped/indexable statements
statement = sail.mapStatement(statement);
if (statement == null) {
return;
}
// we further only indexed statements where the Literal's datatype
// is accepted
Literal literal = (Literal) statement.getObject();
if (luceneIndex.accept(literal)) {
buffer.remove(statement);
}
}
}
};
/**
* To remember if the iterator was already closed and only free resources once
*/
private final AtomicBoolean closed = new AtomicBoolean(false);
public LuceneSpinSailConnection(NotifyingSailConnection wrappedConnection, SearchIndex luceneIndex,
LuceneSpinSail sail) {
super(wrappedConnection);
this.luceneIndex = luceneIndex;
this.sail = sail;
/*
* Using SailConnectionListener, see above
*/
wrappedConnection.addConnectionListener(connectionListener);
}
@Override
public synchronized void addStatement(Resource subj, IRI pred, Value obj, Resource... contexts)
throws SailException {
super.addStatement(subj, pred, obj, contexts);
}
@Override
public void close() throws SailException {
if (closed.compareAndSet(false, true)) {
super.close();
}
}
// //////////////////////////////// Methods related to indexing
@Override
public synchronized void clear(Resource... resources) throws SailException {
// remove the connection listener, this is safe as the changing methods
// are synchronized
// during the clear(), no other operation can be invoked
getWrappedConnection().removeConnectionListener(connectionListener);
try {
super.clear(resources);
buffer.clear(resources);
} finally {
getWrappedConnection().addConnectionListener(connectionListener);
}
}
@Override
public void begin() throws SailException {
super.begin();
buffer.reset();
try {
luceneIndex.begin();
} catch (IOException e) {
throw new SailException(e);
}
}
@Override
public void commit() throws SailException {
super.commit();
logger.debug("Committing Lucene transaction with {} operations.", buffer.operations().size());
try {
// preprocess buffer
buffer.optimize();
// run operations and remove them from buffer
for (Iterator i = buffer.operations().iterator(); i.hasNext();) {
Operation op = i.next();
if (op instanceof LuceneSailBuffer.AddRemoveOperation) {
AddRemoveOperation addremove = (AddRemoveOperation) op;
// add/remove in one call
addRemoveStatements(addremove.getAdded(), addremove.getRemoved());
} else if (op instanceof LuceneSailBuffer.ClearContextOperation) {
// clear context
clearContexts(((ClearContextOperation) op).getContexts());
} else if (op instanceof LuceneSailBuffer.ClearOperation) {
logger.debug("clearing index...");
luceneIndex.clear();
} else {
throw new SailException("Cannot interpret operation " + op + " of type " + op.getClass().getName());
}
i.remove();
}
} catch (Exception e) {
logger.error("Committing operations in lucenesail, encountered exception " + e
+ ". Only some operations were stored, " + buffer.operations().size()
+ " operations are discarded. Lucene Index is now corrupt.", e);
throw new SailException(e);
} finally {
buffer.reset();
}
}
private void addRemoveStatements(Set toAdd, Set toRemove) throws IOException {
logger.debug("indexing {}/removing {} statements...", toAdd.size(), toRemove.size());
luceneIndex.begin();
try {
luceneIndex.addRemoveStatements(toAdd, toRemove);
luceneIndex.commit();
} catch (IOException e) {
logger.error("Rolling back", e);
luceneIndex.rollback();
throw e;
}
}
private void clearContexts(Resource... contexts) throws IOException {
logger.debug("clearing contexts...");
luceneIndex.begin();
try {
luceneIndex.clearContexts(contexts);
luceneIndex.commit();
} catch (IOException e) {
logger.error("Rolling back", e);
luceneIndex.rollback();
throw e;
}
}
/**
* {@inheritDoc }
*/
@Override
public synchronized void removeStatements(Resource subj, IRI pred, Value obj, Resource... contexts)
throws SailException {
super.removeStatements(subj, pred, obj, contexts);
}
@Override
public void rollback() throws SailException {
super.rollback();
buffer.reset();
try {
luceneIndex.rollback();
} catch (IOException e) {
throw new SailException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy