Skip to content

Commit

Permalink
Avoid lock on graph uri update (VIVO-3885) (#395)
Browse files Browse the repository at this point in the history
* Avoid lock on graph uri update

* Run in VitroBackground named thread. Avoid creating threads if a thread to update graph uris has been already created.

---------

Co-authored-by: Georgy Litvinov <georgy.litvinov@tib.eu>
  • Loading branch information
litvinovg and litvinovg authored Jun 16, 2023
1 parent 58e479a commit 0e984eb
Showing 1 changed file with 58 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,39 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.jena.query.QuerySolutionMap;
import org.apache.jena.query.ReadWrite;
import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.log4j.lf5.util.StreamUtils;

import org.apache.jena.graph.Triple;
import org.apache.jena.query.Dataset;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.QuerySolutionMap;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.query.Syntax;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.sdb.SDB;
import org.apache.jena.shared.Lock;
import org.apache.jena.sparql.core.Quad;
import org.apache.log4j.lf5.util.StreamUtils;

import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper;
Expand All @@ -49,6 +56,7 @@
import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.ResultSetIterators.ResultSetQuadsIterator;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.ResultSetIterators.ResultSetTriplesIterator;
import edu.cornell.mannlib.vitro.webapp.utils.threads.VitroBackgroundThread;

public abstract class RDFServiceJena extends RDFServiceImpl implements RDFService {

Expand All @@ -57,7 +65,8 @@ public abstract class RDFServiceJena extends RDFServiceImpl implements RDFServic
protected abstract DatasetWrapper getDatasetWrapper();

protected volatile boolean rebuildGraphURICache = true;
private final List<String> graphURIs = new ArrayList<>();
protected volatile boolean isRebuildGraphURICacheRunning = false;
protected final List<String> graphURIs = Collections.synchronizedList(new ArrayList<>());

@Override
public abstract boolean changeSetUpdate(ChangeSet changeSet) throws RDFServiceException;
Expand Down Expand Up @@ -312,27 +321,53 @@ public boolean sparqlAskQuery(String query) throws RDFServiceException {

@Override
public List<String> getGraphURIs() throws RDFServiceException {
if (rebuildGraphURICache) {
synchronized (RDFServiceJena.class) {
if (rebuildGraphURICache) {
DatasetWrapper dw = getDatasetWrapper();
try {
Dataset d = dw.getDataset();
Iterator<String> nameIt = d.listNames();
graphURIs.clear();
while (nameIt.hasNext()) {
graphURIs.add(nameIt.next());
if (rebuildGraphURICache && !isRebuildGraphURICacheRunning) {
rebuildGraphUris();
}
return graphURIs;
}

protected void rebuildGraphUris() {
Thread thread = new VitroBackgroundThread(new Runnable() {
public void run() {
synchronized (RDFServiceJena.class) {
if (rebuildGraphURICache) {
DatasetWrapper dw = getDatasetWrapper();
try {
isRebuildGraphURICacheRunning = true;
Dataset d = dw.getDataset();
Set<String> newGraphUris = new HashSet<>();
d.begin(ReadWrite.READ);
try {
Iterator<String> nameIt = d.listNames();
while (nameIt.hasNext()) {
newGraphUris.add(nameIt.next());
}
} finally {
d.end();
}
Set<String> oldGraphUris = new HashSet<String>(graphURIs);
if (newGraphUris.equals(oldGraphUris)) {
return;
}
Set<String> removedGraphUris = new HashSet<String>(oldGraphUris);
removedGraphUris.removeAll(newGraphUris);
graphURIs.removeAll(removedGraphUris);
Set<String> addedGraphUris = new HashSet<String>(newGraphUris);
addedGraphUris.removeAll(oldGraphUris);
graphURIs.addAll(addedGraphUris);
} catch (Exception e) {
log.error(e, e);
} finally {
isRebuildGraphURICacheRunning = false;
dw.close();
rebuildGraphURICache = false;
}
return graphURIs;
} finally {
dw.close();
rebuildGraphURICache = false;
}
}
}
}

return graphURIs;
}, "Rebuild graphURI cache thread");
thread.start();
}

@Override
Expand Down

0 comments on commit 0e984eb

Please sign in to comment.