CachingRepositoryConnection.java
/*******************************************************************************
* Copyright (c) 2021 Eclipse RDF4J contributors.
*
* 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.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.spring.resultcache;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.GraphQuery;
import org.eclipse.rdf4j.query.MalformedQueryException;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.Update;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.repository.base.RepositoryConnectionWrapper;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.RDFParseException;
/**
* @author Florian Kleedorfer
* @since 4.0.0
*/
public class CachingRepositoryConnection extends RepositoryConnectionWrapper implements Clearable {
private final LRUResultCache<ReusableTupleQueryResult> localTupleQueryResultCache;
private final LRUResultCache<ReusableGraphQueryResult> localGraphQueryResultCache;
private final LRUResultCache<ReusableTupleQueryResult> globalTupleQueryResultCache;
private final LRUResultCache<ReusableGraphQueryResult> globalGraphQueryResultCache;
private final ResultCacheProperties properties;
private boolean clearGlobalResultCacheOnClose = false;
public CachingRepositoryConnection(
RepositoryConnection delegate,
LRUResultCache<ReusableTupleQueryResult> globalTupleQueryResultCache,
LRUResultCache<ReusableGraphQueryResult> globalGraphQueryResultCache,
ResultCacheProperties properties) {
super(delegate.getRepository(), delegate);
this.globalGraphQueryResultCache = globalGraphQueryResultCache;
this.globalTupleQueryResultCache = globalTupleQueryResultCache;
this.localGraphQueryResultCache = new LRUResultCache<>(properties);
this.localTupleQueryResultCache = new LRUResultCache<>(properties);
this.properties = properties;
}
private Integer makeCacheKey(QueryLanguage ql, String query, String baseURI) {
return (ql.toString() + query + baseURI).hashCode();
}
public void renewLocalResultCache(ResultCachingTupleQuery resultCachingTupleQuery) {
resultCachingTupleQuery.renewLocalResultCache(this.localTupleQueryResultCache);
}
public void renewLocalResultCache(ResultCachingGraphQuery resultCachingGraphQuery) {
resultCachingGraphQuery.renewLocalResultCache(this.localGraphQueryResultCache);
}
public void renewClearable(ClearableAwareUpdate update) {
update.renewClearable(this);
}
@Override
public TupleQuery prepareTupleQuery(QueryLanguage ql, String queryString, String baseURI)
throws MalformedQueryException, RepositoryException {
return new ResultCachingTupleQuery(
getDelegate().prepareTupleQuery(ql, queryString, baseURI),
this.localTupleQueryResultCache,
this.globalTupleQueryResultCache,
properties);
}
@Override
public GraphQuery prepareGraphQuery(QueryLanguage ql, String queryString, String baseURI)
throws MalformedQueryException, RepositoryException {
return new ResultCachingGraphQuery(
getDelegate().prepareGraphQuery(ql, queryString, baseURI),
this.localGraphQueryResultCache,
this.globalGraphQueryResultCache,
this.properties);
}
@Override
public Update prepareUpdate(QueryLanguage ql, String updateString, String baseURI)
throws MalformedQueryException, RepositoryException {
return new ClearableAwareUpdate(
getDelegate().prepareUpdate(ql, updateString, baseURI), this);
}
@Override
public void close() throws RepositoryException {
this.localGraphQueryResultCache.markDirty();
this.localTupleQueryResultCache.markDirty();
if (this.clearGlobalResultCacheOnClose) {
this.globalGraphQueryResultCache.markDirty();
this.globalTupleQueryResultCache.markDirty();
}
super.close();
}
/**
* As we are changing the repository's content, we have to reset all caches (even though it
*/
@Override
public void markDirty() {
this.localGraphQueryResultCache.markDirty();
this.localTupleQueryResultCache.markDirty();
this.globalTupleQueryResultCache.bypassForCurrentThread();
this.globalGraphQueryResultCache.bypassForCurrentThread();
this.clearGlobalResultCacheOnClose = true;
}
@Override
public void clearCachedResults() {
this.localGraphQueryResultCache.clearCachedResults();
this.localTupleQueryResultCache.clearCachedResults();
}
@Override
public void add(File file, String baseURI, RDFFormat dataFormat, Resource... contexts)
throws IOException, RDFParseException, RepositoryException {
super.add(file, baseURI, dataFormat, contexts);
markDirty();
}
@Override
public void add(InputStream in, String baseURI, RDFFormat dataFormat, Resource... contexts)
throws IOException, RDFParseException, RepositoryException {
super.add(in, baseURI, dataFormat, contexts);
markDirty();
}
@Override
public void add(Iterable<? extends Statement> statements, Resource... contexts)
throws RepositoryException {
super.add(statements, contexts);
markDirty();
}
@Override
public void add(
CloseableIteration<? extends Statement> statementIter, Resource... contexts)
throws RepositoryException {
super.add(statementIter, contexts);
markDirty();
}
@Override
public void add(Reader reader, String baseURI, RDFFormat dataFormat, Resource... contexts)
throws IOException, RDFParseException, RepositoryException {
super.add(reader, baseURI, dataFormat, contexts);
markDirty();
}
@Override
public void add(Resource subject, IRI predicate, Value object, Resource... contexts)
throws RepositoryException {
super.add(subject, predicate, object, contexts);
markDirty();
}
@Override
public void add(Statement st, Resource... contexts) throws RepositoryException {
super.add(st, contexts);
markDirty();
}
@Override
public void add(URL url, String baseURI, RDFFormat dataFormat, Resource... contexts)
throws IOException, RDFParseException, RepositoryException {
super.add(url, baseURI, dataFormat, contexts);
markDirty();
}
@Override
public void clear(Resource... contexts) throws RepositoryException {
super.clear(contexts);
markDirty();
}
@Override
public void remove(Iterable<? extends Statement> statements, Resource... contexts)
throws RepositoryException {
super.remove(statements, contexts);
markDirty();
}
@Override
public void remove(
CloseableIteration<? extends Statement> statementIter, Resource... contexts)
throws RepositoryException {
super.remove(statementIter, contexts);
markDirty();
}
@Override
public void remove(Resource subject, IRI predicate, Value object, Resource... contexts)
throws RepositoryException {
super.remove(subject, predicate, object, contexts);
markDirty();
}
@Override
public void remove(Statement st, Resource... contexts) throws RepositoryException {
super.remove(st, contexts);
markDirty();
}
@Override
public void removeNamespace(String prefix) throws RepositoryException {
super.removeNamespace(prefix);
markDirty();
}
}