From dc726d2600de22027c0de63aaf5d056da02695dc Mon Sep 17 00:00:00 2001 From: Jim Blake Date: Mon, 13 Apr 2015 10:25:58 -0400 Subject: [PATCH] VIVO-1016 Avoid crashing on ABox.isEmpty() 1) Don't ask whether the ABox is empty, if you don't need to 2) If you must ask, ask the graph of the base model, to avoid SDB layers 3) change contains() to use SELECT instead of ASK, because SDB implements ASK very poorly. --- webapp/config/log4j.properties | 2 +- .../vitro/webapp/dao/jena/RDFServiceGraph.java | 14 ++++++++------ .../mannlib/vitro/webapp/dao/jena/SparqlGraph.java | 6 ++++-- .../filestorage/serving/FileServingServlet.java | 2 ++ .../rdfservice/impl/jena/ListeningGraph.java | 2 +- .../webapp/servlet/setup/ContentModelSetup.java | 13 ++++++++++--- .../impl/tdb/ContentTripleSourceTDB.java | 2 +- 7 files changed, 27 insertions(+), 14 deletions(-) diff --git a/webapp/config/log4j.properties b/webapp/config/log4j.properties index eab5f48e9..afb5b3a11 100644 --- a/webapp/config/log4j.properties +++ b/webapp/config/log4j.properties @@ -36,7 +36,7 @@ log4j.rootLogger=INFO, AllAppender # These classes are too chatty to display INFO messages. log4j.logger.edu.cornell.mannlib.vitro.webapp.startup.StartupStatus=WARN log4j.logger.edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase=WARN -log4j.logger.org.semanticweb.owlapi.rdf.rdfxml.parser.OWLRDFConsumer=WARN +log4j.logger.org.semanticweb.owlapi.rdf.rdfxml.parser=WARN # Spring as a whole is too chatty to display INFO messages. log4j.logger.org.springframework=WARN diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java index 61afe6091..81ca7c240 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/RDFServiceGraph.java @@ -145,10 +145,12 @@ public class RDFServiceGraph implements GraphWithPerform { @Override public boolean contains(Node subject, Node predicate, Node object) { - if (subject.isBlank() || predicate.isBlank() || object.isBlank()) { + if ((subject != null && subject.isBlank()) + || (predicate != null && predicate.isBlank()) + || (object != null && object.isBlank())) { return false; } - StringBuffer containsQuery = new StringBuffer("ASK { \n"); + StringBuffer containsQuery = new StringBuffer("SELECT * WHERE { \n"); if (graphURI != null) { containsQuery.append(" GRAPH <" + graphURI + "> { "); } @@ -160,9 +162,9 @@ public class RDFServiceGraph implements GraphWithPerform { if (graphURI != null) { containsQuery.append(" } \n"); } - containsQuery.append("\n}"); - boolean result = execAsk(containsQuery.toString()); - return result; + containsQuery.append("} \nLIMIT 1 "); + ResultSet result = execSelect(containsQuery.toString()); + return result.hasNext(); } @Override @@ -319,7 +321,7 @@ public class RDFServiceGraph implements GraphWithPerform { @Override public boolean isEmpty() { - return (size() == 0); + return !contains(null, null, null); } @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java index c64b5c444..506860482 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/SparqlGraph.java @@ -170,7 +170,9 @@ public class SparqlGraph implements GraphWithPerform { @Override public boolean contains(Node subject, Node predicate, Node object) { - if (subject.isBlank() || predicate.isBlank() || object.isBlank()) { + if ((subject != null && subject.isBlank()) + || (predicate != null && predicate.isBlank()) + || (object != null && object.isBlank())) { return false; } StringBuffer containsQuery = new StringBuffer("ASK { \n"); @@ -357,7 +359,7 @@ public class SparqlGraph implements GraphWithPerform { @Override public boolean isEmpty() { - return (size() == 0); + return !contains(null, null, null); } @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/serving/FileServingServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/serving/FileServingServlet.java index 76927409e..8ee917595 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/serving/FileServingServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/serving/FileServingServlet.java @@ -113,6 +113,8 @@ public class FileServingServlet extends VitroHttpServlet { while (-1 != (howMany = in.read(buffer))) { out.write(buffer, 0, howMany); } + } catch (IOException e) { + log.warn("Failed to serve the file", e); } finally { try { in.close(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/ListeningGraph.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/ListeningGraph.java index 690fcf02f..8fb2752e4 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/ListeningGraph.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/ListeningGraph.java @@ -163,7 +163,7 @@ public class ListeningGraph implements GraphWithPerform { @Override public boolean isEmpty() { - return (size() == 0); + return !contains(null, null, null); } @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ContentModelSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ContentModelSetup.java index c22fbbc48..5b9b45579 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ContentModelSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/ContentModelSetup.java @@ -32,6 +32,11 @@ import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; /** * Sets up the content models, OntModelSelectors and webapp DAO factories. + * + * Why the firstTimeStartup flag? Because you can't ask a large SDB model + * whether it is empty. SDB translates this into a call to size(), which + * in turn becomes find(null, null, null) and a count, and this gives an + * OutOfMemoryError because it tries to read the entire model into memory. */ public class ContentModelSetup extends JenaDataSourceSetupBase implements javax.servlet.ServletContextListener { @@ -50,22 +55,24 @@ public class ContentModelSetup extends JenaDataSourceSetupBase private void setUpJenaDataSource(ServletContext ctx) { ContextModelAccess models = ModelAccess.on(ctx); + boolean firstTimeStartup = false; Model applicationMetadataModel = models.getOntModel(APPLICATION_METADATA); - if (applicationMetadataModel.size()== 0) { + if (applicationMetadataModel.isEmpty()) { + firstTimeStartup = true; initializeApplicationMetadata(ctx, applicationMetadataModel); } else { checkForNamespaceMismatch( applicationMetadataModel, ctx ); } OntModel baseABoxModel = models.getOntModel(ABOX_ASSERTIONS); - if (baseABoxModel.size() == 0) { + if (firstTimeStartup) { RDFFilesLoader.loadFirstTimeFiles("abox", baseABoxModel, true); } RDFFilesLoader.loadEveryTimeFiles("abox", baseABoxModel); OntModel baseTBoxModel = models.getOntModel(TBOX_ASSERTIONS); - if (baseTBoxModel.size() == 0) { + if (firstTimeStartup) { RDFFilesLoader.loadFirstTimeFiles("tbox", baseTBoxModel, true); } RDFFilesLoader.loadEveryTimeFiles("tbox", baseTBoxModel); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/triplesource/impl/tdb/ContentTripleSourceTDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/triplesource/impl/tdb/ContentTripleSourceTDB.java index 5ac40e591..4591559b0 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/triplesource/impl/tdb/ContentTripleSourceTDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/triplesource/impl/tdb/ContentTripleSourceTDB.java @@ -106,7 +106,7 @@ public class ContentTripleSourceTDB extends ContentTripleSource { } private void checkForFirstTimeStartup() { - if (this.dataset.getNamedModel(ModelNames.TBOX_ASSERTIONS).size() == 0) { + if (this.dataset.getNamedModel(ModelNames.TBOX_ASSERTIONS).getGraph().isEmpty()) { JenaDataSourceSetupBase.thisIsFirstStartup(); } }