diff --git a/exist-core/pom.xml b/exist-core/pom.xml
index 78b71881e2..a7974642c9 100644
--- a/exist-core/pom.xml
+++ b/exist-core/pom.xml
@@ -1015,12 +1015,15 @@
src/test/java/org/exist/security/internal/BackupRestoreSecurityPrincipalsTest.java
src/main/java/org/exist/security/internal/RealmImpl.java
src/main/java/org/exist/security/internal/SecurityManagerImpl.java
+ src/main/java/org/exist/security/internal/SMEvents.java
src/main/java/org/exist/security/internal/aider/UnixStylePermissionAider.java
src/main/java/org/exist/security/management/AccountsManagement.java
src/main/java/org/exist/security/management/GroupsManagement.java
src/main/java/org/exist/source/AbstractSource.java
+ src/main/java/org/exist/source/DBSource.java
src/main/java/org/exist/source/Source.java
src/main/java/org/exist/source/SourceFactory.java
+ src/test/java/org/exist/source/SourceFactoryTest.java
src/main/java/org/exist/source/URLSource.java
src/test/java/org/exist/stax/EmbeddedXMLStreamReaderTest.java
src/test/java/org/exist/storage/AbstractUpdateTest.java
@@ -1088,6 +1091,8 @@
src/test/resources-filtered/org/exist/storage/statistics/conf.xml
src/main/java/org/exist/storage/sync/SyncTask.java
src/test/java/org/exist/storage/util/PauseFunction.java
+ src/main/java/org/exist/test/ExistEmbeddedServer.java
+ src/main/java/org/exist/test/ExistWebServer.java
src/main/java/org/exist/test/ExistXmldbEmbeddedServer.java
src/main/java/org/exist/test/TransactionTestDSL.java
src/main/java/org/exist/test/XQueryAssertions.java
@@ -1232,11 +1237,15 @@
src/test/java/org/exist/xmldb/concurrent/action/ValueAppendAction.java
src/test/java/org/exist/xmldb/concurrent/action/XQueryAction.java
src/test/java/org/exist/xmldb/concurrent/action/XQueryUpdateAction.java
+ src/main/java/org/exist/xmlrpc/AbstractCachedResult.java
+ src/main/java/org/exist/xmlrpc/CachedQueryResult.java
src/main/java/org/exist/xmlrpc/ExistRpcTypeFactory.java
src/test/java/org/exist/xmlrpc/MimeTypeTest.java
+ src/main/java/org/exist/xmlrpc/QueryResultCache.java
src/test/java/org/exist/xmlrpc/QuerySessionTest.java
src/main/java/org/exist/xmlrpc/RpcAPI.java
src/main/java/org/exist/xmlrpc/RpcConnection.java
+ src/main/java/org/exist/xmlrpc/XmldbRequestProcessorFactory.java
src/test/java/org/exist/xmlrpc/XmlRpcTest.java
src/main/java/org/exist/xqj/Marshaller.java
src/test/java/org/exist/xqj/MarshallerTest.java
@@ -1248,6 +1257,7 @@
src/test/java/org/exist/xquery/CardinalityTest.java
src/test/java/org/exist/xquery/CleanupTest.java
src/main/java/org/exist/xquery/CombiningExpression.java
+ src/main/java/org/exist/xquery/CompiledXQuery.java
src/test/java/org/exist/xquery/ConstructedNodesRecoveryTest.java
src/test/java/org/exist/xquery/ConstructedNodesTest.java
src/main/java/org/exist/xquery/Context.java
@@ -1465,6 +1475,7 @@
src/test/java/org/exist/xquery/functions/util/Base64FunctionsTest.java
src/test/java/org/exist/xquery/functions/util/BaseConverterTest.java
src/main/java/org/exist/xquery/functions/util/BuiltinFunctions.java
+ src/main/java/org/exist/xquery/functions/util/CollectionName.java
src/main/java/org/exist/xquery/functions/util/DescribeFunction.java
src/test/java/org/exist/xquery/functions/util/EvalTest.java
src/test/java/org/exist/xquery/functions/util/ExpandTest.java
@@ -1841,12 +1852,18 @@
src/test/java/org/exist/security/internal/BackupRestoreSecurityPrincipalsTest.java
src/main/java/org/exist/security/internal/RealmImpl.java
src/main/java/org/exist/security/internal/SecurityManagerImpl.java
+ src/main/java/org/exist/security/internal/SMEvents.java
+ src/main/java/org/exist/security/internal/aider/ImmutableUnixStylePermissionAider.java
src/main/java/org/exist/security/internal/aider/UnixStylePermissionAider.java
src/main/java/org/exist/security/management/AccountsManagement.java
src/main/java/org/exist/security/management/GroupsManagement.java
src/main/java/org/exist/source/AbstractSource.java
+ src/main/java/org/exist/source/DBSource.java
+ src/main/java/org/exist/source/DbStoreSource.java
+ src/main/java/org/exist/source/DbUriSource.java
src/main/java/org/exist/source/Source.java
src/main/java/org/exist/source/SourceFactory.java
+ src/test/java/org/exist/source/SourceFactoryTest.java
src/main/java/org/exist/source/URLSource.java
src/test/java/org/exist/stax/EmbeddedXMLStreamReaderTest.java
src/test/java/org/exist/storage/AbstractRecoverTest.java
@@ -1966,6 +1983,8 @@
src/test/java/org/exist/storage/txn/TxnTest.java
src/test/java/org/exist/storage/util/PauseFunction.java
src/main/java/org/exist/test/DiffMatcher.java
+ src/main/java/org/exist/test/ExistEmbeddedServer.java
+ src/main/java/org/exist/test/ExistWebServer.java
src/main/java/org/exist/test/ExistXmldbEmbeddedServer.java
src/main/java/org/exist/test/TransactionTestDSL.java
src/test/java/org/exist/test/Util.java
@@ -2072,6 +2091,7 @@
src/test/java/org/exist/xmldb/IndexingTest.java
src/main/java/org/exist/xmldb/LocalBinaryResource.java
src/main/java/org/exist/xmldb/LocalCollection.java
+ src/main/java/org/exist/xmldb/LocalCompiledExpression.java
src/main/java/org/exist/xmldb/LocalResourceSet.java
src/main/java/org/exist/xmldb/LocalRestoreService.java
src/main/java/org/exist/xmldb/LocalXMLResource.java
@@ -2124,15 +2144,19 @@
src/test/java/org/exist/xmldb/concurrent/action/ValueAppendAction.java
src/test/java/org/exist/xmldb/concurrent/action/XQueryAction.java
src/test/java/org/exist/xmldb/concurrent/action/XQueryUpdateAction.java
+ src/main/java/org/exist/xmlrpc/AbstractCachedResult.java
src/main/java/org/exist/xmlrpc/ACEAiderParser.java
src/main/java/org/exist/xmlrpc/ACEAiderSerializer.java
src/main/java/org/exist/xmlrpc/ArrayWrapperParser.java
src/main/java/org/exist/xmlrpc/ArrayWrapperSerializer.java
+ src/main/java/org/exist/xmlrpc/CachedQueryResult.java
src/main/java/org/exist/xmlrpc/ExistRpcTypeFactory.java
src/test/java/org/exist/xmlrpc/MimeTypeTest.java
+ src/main/java/org/exist/xmlrpc/QueryResultCache.java
src/test/java/org/exist/xmlrpc/QuerySessionTest.java
src/main/java/org/exist/xmlrpc/RpcAPI.java
src/main/java/org/exist/xmlrpc/RpcConnection.java
+ src/main/java/org/exist/xmlrpc/XmldbRequestProcessorFactory.java
src/main/java/org/exist/xmlrpc/XmlRpcExtensionConstants.java
src/test/java/org/exist/xmlrpc/XmlRpcTest.java
src/main/java/org/exist/xqj/Marshaller.java
@@ -2148,6 +2172,7 @@
src/test/java/org/exist/xquery/CastExpressionTest.java
src/test/java/org/exist/xquery/CleanupTest.java
src/main/java/org/exist/xquery/CombiningExpression.java
+ src/main/java/org/exist/xquery/CompiledXQuery.java
src/test/java/org/exist/xquery/ConstructedNodesRecoveryTest.java
src/test/java/org/exist/xquery/ConstructedNodesTest.java
src/main/java/org/exist/xquery/Context.java
@@ -2199,6 +2224,9 @@
src/test/java/org/exist/xquery/PersistentDescendantOrSelfNodeKindTest.java
src/test/java/org/exist/xquery/QueryPoolTest.java
src/test/java/org/exist/xquery/RestBinariesTest.java
+ src/test/java/org/exist/xquery/RunningXQueryRestTest.java
+ src/test/java/org/exist/xquery/RunningXQueryTest.java
+ src/test/java/org/exist/xquery/RunningXQueryXmlDbTest.java
src/test/java/org/exist/xquery/SeqOpTest.java
src/test/java/org/exist/xquery/SpecialNamesTest.java
src/test/java/org/exist/xquery/StoredModuleTest.java
@@ -2387,6 +2415,7 @@
src/test/java/org/exist/xquery/functions/util/Base64FunctionsTest.java
src/test/java/org/exist/xquery/functions/util/BaseConverterTest.java
src/main/java/org/exist/xquery/functions/util/BuiltinFunctions.java
+ src/main/java/org/exist/xquery/functions/util/CollectionName.java
src/main/java/org/exist/xquery/functions/util/DescribeFunction.java
src/main/java/org/exist/xquery/functions/util/Eval.java
src/test/java/org/exist/xquery/functions/util/EvalTest.java
@@ -2665,6 +2694,13 @@ The original license statement is also included below.]]>
src/main/java/org/exist/mediatype/MediaTypeService.java
src/main/java/org/exist/mediatype/MediaTypeUtil.java
+ src/main/java/org/exist/security/internal/aider/ImmutableUnixStylePermissionAider.java
+ src/main/java/org/exist/source/DbStoreSource.java
+ src/main/java/org/exist/source/DbUriSource.java
+ src/main/java/org/exist/xmldb/LocalCompiledExpression.java
+ src/test/java/org/exist/xquery/RunningXQueryRestTest.java
+ src/test/java/org/exist/xquery/RunningXQueryTest.java
+ src/test/java/org/exist/xquery/RunningXQueryXmlDbTest.java
src/main/resources/xyz/elemental/mediatype/media-type-aliases.xml
src/main/resources/xyz/elemental/mediatype/media-type-mappings.xml
src/main/resources/xyz/elemental/mediatype/mime.types
@@ -2972,4 +3008,4 @@ The BaseX Team. The original license statement is also included below.]]>
-
\ No newline at end of file
+
diff --git a/exist-core/src/main/java/org/exist/collections/triggers/XQueryTrigger.java b/exist-core/src/main/java/org/exist/collections/triggers/XQueryTrigger.java
index 534e8919b8..69cf17b3c8 100644
--- a/exist-core/src/main/java/org/exist/collections/triggers/XQueryTrigger.java
+++ b/exist-core/src/main/java/org/exist/collections/triggers/XQueryTrigger.java
@@ -61,7 +61,7 @@
import org.exist.dom.persistent.DocumentImpl;
import org.exist.dom.QName;
import org.exist.security.PermissionDeniedException;
-import org.exist.source.DBSource;
+import org.exist.source.DbStoreSource;
import org.exist.source.Source;
import org.exist.source.SourceFactory;
import org.exist.source.StringSource;
@@ -364,8 +364,8 @@ private CompiledXQuery getScript(final DBBroker broker, final Txn transaction) t
context.prepareForReuse();
}
- if (query instanceof DBSource) {
- context.setModuleLoadPath(XmldbURI.EMBEDDED_SERVER_URI_PREFIX + ((DBSource)query).getDocumentPath().removeLastSegment().toString());
+ if (query instanceof DbStoreSource) {
+ context.setModuleLoadPath(XmldbURI.EMBEDDED_SERVER_URI_PREFIX + ((DbStoreSource) query).getDocumentPath().removeLastSegment().toString());
}
//compile the XQuery
diff --git a/exist-core/src/main/java/org/exist/http/AuditTrailSessionListener.java b/exist-core/src/main/java/org/exist/http/AuditTrailSessionListener.java
index 08d63fa7ef..4595a677f4 100644
--- a/exist-core/src/main/java/org/exist/http/AuditTrailSessionListener.java
+++ b/exist-core/src/main/java/org/exist/http/AuditTrailSessionListener.java
@@ -48,15 +48,13 @@
import com.evolvedbinary.j8fu.function.ConsumerE;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.exist.dom.persistent.BinaryDocument;
-import org.exist.dom.persistent.LockedDocument;
+import org.exist.EXistException;
+import org.exist.security.PermissionDeniedException;
import org.exist.security.Subject;
-import org.exist.source.DBSource;
+import org.exist.source.DbUriSource;
import org.exist.source.Source;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
-import org.exist.storage.XQueryPool;
-import org.exist.storage.lock.Lock.LockMode;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
@@ -67,7 +65,7 @@
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
-import javax.annotation.Nullable;
+import java.io.IOException;
import java.util.Optional;
import java.util.Properties;
@@ -116,50 +114,29 @@ private void executeXQuery(String xqueryResourcePath) {
if (xqueryResourcePath != null && xqueryResourcePath.length() > 0) {
xqueryResourcePath = xqueryResourcePath.trim();
- @Nullable Source source;
-
try {
final BrokerPool pool = BrokerPool.getInstance();
- final XQueryPool xqpool = pool.getXQueryPool();
-
final Subject sysSubject = pool.getSecurityManager().getSystemSubject();
- try (final DBBroker broker = pool.get(Optional.of(sysSubject))) {
- if (broker == null) {
- LOG.error("Unable to retrieve DBBroker for {}", sysSubject.getName());
- return;
- }
-
- final XmldbURI pathUri = XmldbURI.create(xqueryResourcePath);
+ final XmldbURI pathUri = XmldbURI.create(xqueryResourcePath);
+ final Source source = DbUriSource.from(pool, sysSubject, pathUri, true, false);
+
+ final ConsumerE setupXqueryContextPreCompilation = xqueryContext -> {
+ xqueryContext.setStaticallyKnownDocuments(new XmldbURI[]{pathUri});
+ xqueryContext.setBaseURI(new AnyURIValue(pathUri.toString()));
+ };
- try (final LockedDocument lockedResource = broker.getXMLResource(pathUri, LockMode.READ_LOCK)) {
+ final Properties outputProperties = new Properties();
+ try (final DBBroker broker = pool.get(Optional.of(sysSubject));
+ final XQueryUtil.QueryResult queryResult = XQueryUtil.query(broker, source, true, null, outputProperties, setupXqueryContextPreCompilation, null, null)) {
- if (lockedResource != null) {
- if (LOG.isTraceEnabled()) {
- LOG.trace("Resource [{}] exists.", xqueryResourcePath);
- }
- source = new DBSource(broker, (BinaryDocument) lockedResource.getDocument(), true);
- } else {
- LOG.error("Resource [{}] does not exist.", xqueryResourcePath);
- return;
- }
-
- final ConsumerE setupXqueryContextPreCompilation = xqueryContext -> {
- xqueryContext.setStaticallyKnownDocuments(new XmldbURI[]{pathUri});
- xqueryContext.setBaseURI(new AnyURIValue(pathUri.toString()));
- };
-
- final Properties outputProperties = new Properties();
- try (final XQueryUtil.QueryResult queryResult = XQueryUtil.query(broker, source, true, null, outputProperties, setupXqueryContextPreCompilation, null, null)) {
-
- if (LOG.isTraceEnabled()) {
- LOG.trace("XQuery execution results: {} in {}ms.", queryResult.result.toString(), queryResult.executionTime);
- }
- }
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("XQuery execution results: {} in {}ms.", queryResult.result.toString(), queryResult.executionTime);
}
}
-
- } catch (final Exception e) {
+ } catch (final DbUriSource.NoSuchDocumentException e) {
+ LOG.error("Resource [{}] does not exist.", xqueryResourcePath);
+ } catch (final EXistException | PermissionDeniedException | XPathException | IOException e) {
LOG.error("Exception while executing [{}] script", xqueryResourcePath, e);
}
}
diff --git a/exist-core/src/main/java/org/exist/http/RESTServer.java b/exist-core/src/main/java/org/exist/http/RESTServer.java
index 832026310b..964d280dd8 100644
--- a/exist-core/src/main/java/org/exist/http/RESTServer.java
+++ b/exist-core/src/main/java/org/exist/http/RESTServer.java
@@ -70,6 +70,7 @@
import org.exist.security.Subject;
import org.exist.security.internal.RealmImpl;
import org.exist.source.DBSource;
+import org.exist.source.DbStoreSource;
import org.exist.source.Source;
import org.exist.source.StringSource;
import org.exist.source.URLSource;
@@ -578,7 +579,7 @@ public void doGet(final DBBroker broker, final Txn transaction, final HttpServle
try {
if (xquery_mime_type.equals(resource.getMediaType())) {
// Execute the XQuery
- executeXQuery(broker, transaction, resource, request, response,
+ executeXQuery(broker, transaction, lockedDocument, request, response,
outputProperties, servletPath.toString(), pathInfo);
} else if (xproc_mime_type.equals(resource.getMediaType())) {
// Execute the XProc
@@ -745,7 +746,7 @@ public void doPost(final DBBroker broker, final Txn transaction, final HttpServl
try {
if (xquery_mime_type.equals(resource.getMediaType())) {
// Execute the XQuery
- executeXQuery(broker, transaction, resource, request, response,
+ executeXQuery(broker, transaction, lockedDocument, request, response,
outputProperties, servletPath.toString(), pathInfo);
} else {
// Execute the XProc
@@ -1267,7 +1268,7 @@ private boolean checkForXQueryTarget(final DBBroker broker, final Txn transactio
final Properties outputProperties = new Properties(defaultOutputKeysProperties);
try {
// Execute the XQuery
- executeXQuery(broker, transaction, resource, request, response,
+ executeXQuery(broker, transaction, lockedDocument, request, response,
outputProperties, servletPath.toString(), pathInfo);
} catch (final XPathException e) {
writeXPathExceptionHtml(response, HttpServletResponse.SC_BAD_REQUEST, UTF_8.name(), null, path.toString(), e);
@@ -1386,10 +1387,12 @@ protected void search(final DBBroker broker, final Txn transaction, final String
@Nullable final Item contextItem = extractContextItem(contextItemParam);
final Sequence contextSequence = contextItem != null ? new ValueSequence(contextItem) : null;
- try (final XQueryUtil.QueryResult queryResult = XQueryUtil.query(broker, source, true, contextSequence, outputProperties, setupXqueryContextPreCompilation, setupXqueryContextPreExecution, setupXqueryContextPostExecution)) {
+ @Nullable XQueryUtil.QueryResult queryResult = null;
+ try {
+ queryResult = XQueryUtil.query(broker, source, true, contextSequence, outputProperties, setupXqueryContextPreCompilation, setupXqueryContextPreExecution, setupXqueryContextPostExecution);
// special header to indicate that the query is not returned from cache
- response.setHeader(XQUERY_CACHED_RESPONSE_HEADER, queryResult.compilationTime == XQueryUtil.QueryResult.RETRIEVED_CACHED_COMPILED_QUERY ? "true" : "false");
+ response.setHeader(XQUERY_CACHED_RESPONSE_HEADER, queryResult.compilationTime == XQueryUtil.CompilationResult.RETRIEVED_CACHED_COMPILED_QUERY ? "true" : "false");
if (LOG.isDebugEnabled()) {
LOG.debug("Found {} in {}ms.", queryResult.result.getItemCount(), queryResult.executionTime);
@@ -1404,6 +1407,11 @@ protected void search(final DBBroker broker, final Txn transaction, final String
}
writeResults(response, broker, transaction, queryResult, howmany, start, typed, outputProperties, wrap);
+ } finally {
+ if (!cache && queryResult != null) {
+ // NOTE(AR) we can only close the query result if we are not caching it for reuse in the sessionManager, otherwise it has to be closed when it is later removed from the sessionManager
+ queryResult.close();
+ }
}
} catch (final IOException e) {
@@ -1575,41 +1583,64 @@ private void declareExternalAndXQJVariables(final XQueryContext context,
/**
* Directly execute an XQuery stored as a binary document in the database.
*
- * @throws PermissionDeniedException
+ * NOTE The document will be unlocked after query compilation (only if compilation succeeds).
+ *
+ * @param broker the database broker.
+ * @param transaction the database transaction.
+ * @param lockedQueryDocument the locked document holding the query to be executed.
+ * @param request the HTTP request.
+ * @param response the HTTP response.
+ * @param outputProperties any serialization properties.
+ * @param servletPath the path to the servlet.
+ * @param pathInfo the path.
+ *
+ * @throws XPathException if an error occurs during query compilation or execution.
+ * @throws BadRequestException if the request had a problem.
+ * @throws PermissionDeniedException if the calling user does not have sufficient permissions.
*/
- private void executeXQuery(final DBBroker broker, final Txn transaction, final DocumentImpl resource,
+ private void executeXQuery(final DBBroker broker, final Txn transaction, final LockedDocument lockedQueryDocument,
final HttpServletRequest request, final HttpServletResponse response,
final Properties outputProperties, final String servletPath, final String pathInfo)
throws XPathException, BadRequestException, PermissionDeniedException {
- final Source source = new DBSource(broker, (BinaryDocument) resource, true);
+ final DocumentImpl resource = lockedQueryDocument.getDocument();
+ final DbStoreSource source = new DBSource(broker.getBrokerPool(), (BinaryDocument) resource, true);
final ConsumerE setupXqueryContextPreCompilation = xqueryContext -> {
xqueryContext.setModuleLoadPath(XmldbURI.EMBEDDED_SERVER_URI.append(resource.getCollection().getURI()).toString());
xqueryContext.setStaticallyKnownDocuments(new XmldbURI[]{ resource.getCollection().getURI() });
};
- final ConsumerE setupXqueryContextPreExecution = xqueryContext -> {
- final HttpRequestWrapper reqw = declareVariables(xqueryContext, null, request, response);
- reqw.setServletPath(servletPath);
- reqw.setPathInfo(pathInfo);
- DebuggeeFactory.checkForDebugRequest(request, xqueryContext);
- };
+ try {
+ // NOTE(AR) compilationResult will be cleaned up by the try-with-resources wrapped XQueryUtil.execute(...); at present between here and there no exceptions can occur
+ final XQueryUtil.CompilationResult compilationResult = XQueryUtil.compile(broker, source, false, true, setupXqueryContextPreCompilation);
- final BiConsumerE setupXqueryContextPostExecution = (xqueryContext, queryResult) -> {
- // Pass last modified date to the HTTP response
- HTTPUtils.addLastModifiedHeader(queryResult.result, xqueryContext);
- };
+ // NOTE(AR) query is now compiled so we can release the LockedDocument eagerly
+ lockedQueryDocument.close();
- try (final XQueryUtil.QueryResult queryResult = XQueryUtil.query(broker, source, true, null, outputProperties, setupXqueryContextPreCompilation, setupXqueryContextPreExecution, setupXqueryContextPostExecution)) {
- // Special header to indicate whether the compiled query is returned from the cache
- response.setHeader(XQUERY_CACHED_RESPONSE_HEADER, queryResult.compilationTime == XQueryUtil.QueryResult.RETRIEVED_CACHED_COMPILED_QUERY ? "true" : "false");
+ final ConsumerE setupXqueryContextPreExecution = xqueryContext -> {
+ final HttpRequestWrapper reqw = declareVariables(xqueryContext, null, request, response);
+ reqw.setServletPath(servletPath);
+ reqw.setPathInfo(pathInfo);
+ DebuggeeFactory.checkForDebugRequest(request, xqueryContext);
+ };
+
+ final BiConsumerE setupXqueryContextPostExecution = (xqueryContext, queryResult) -> {
+ // Pass last modified date to the HTTP response
+ HTTPUtils.addLastModifiedHeader(queryResult.result, xqueryContext);
+ };
+
+ try (final XQueryUtil.QueryResult queryResult = XQueryUtil.execute(broker, compilationResult, null, outputProperties, setupXqueryContextPreExecution, setupXqueryContextPostExecution)) {
+ // Special header to indicate whether the compiled query is returned from the cache
+ response.setHeader(XQUERY_CACHED_RESPONSE_HEADER, queryResult.compilationTime == XQueryUtil.CompilationResult.RETRIEVED_CACHED_COMPILED_QUERY ? "true" : "false");
+
+ final boolean wrap = "yes".equals(outputProperties.getProperty("_wrap"));
+ writeResults(response, broker, transaction, queryResult, -1, 1, false, outputProperties, wrap);
+ }
- final boolean wrap = "yes".equals(outputProperties.getProperty("_wrap"));
- writeResults(response, broker, transaction, queryResult, -1, 1, false, outputProperties, wrap);
} catch (final IOException e) {
- throw new BadRequestException("Failed to read query from " + resource.getURI(), e);
+ throw new BadRequestException("Failed to read query from: " + source.getDocumentPath(), e);
}
}
@@ -1663,7 +1694,7 @@ private void executeXProc(final DBBroker broker, final Txn transaction, final Do
try (final XQueryUtil.QueryResult queryResult = XQueryUtil.query(broker, source, true, null, null, setupXqueryContextPreCompilation, setupXqueryContextPreExecution, setupXqueryContextPostExecution)) {
// special header to indicate that the query is not returned from cache
- response.setHeader(XQUERY_CACHED_RESPONSE_HEADER, queryResult.compilationTime == XQueryUtil.QueryResult.RETRIEVED_CACHED_COMPILED_QUERY ? "true" : "false");
+ response.setHeader(XQUERY_CACHED_RESPONSE_HEADER, queryResult.compilationTime == XQueryUtil.CompilationResult.RETRIEVED_CACHED_COMPILED_QUERY ? "true" : "false");
writeResults(response, broker, transaction, queryResult, -1, 1, false, outputProperties, false);
} catch (final IOException e) {
diff --git a/exist-core/src/main/java/org/exist/http/SessionManager.java b/exist-core/src/main/java/org/exist/http/SessionManager.java
index 9372250c4e..b4ead5748c 100644
--- a/exist-core/src/main/java/org/exist/http/SessionManager.java
+++ b/exist-core/src/main/java/org/exist/http/SessionManager.java
@@ -47,11 +47,13 @@
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.RemovalListener;
import net.jcip.annotations.ThreadSafe;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.xquery.XQueryUtil;
+import javax.annotation.Nullable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -64,6 +66,15 @@ public class SessionManager {
private static final Logger LOG = LogManager.getLogger(SessionManager.class);
private static final long TIMEOUT = 120_000; // ms (e.g. 2 minutes)
+ private static final RemovalListener REMOVAL_LISTENER = (sessionId, queryAndResult, removalCause) -> {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Removing cached query result for session: {}", sessionId);
+ }
+
+ // NOTE(AR) make sure to release any resources still held by the query result and potentially send it back to the query pool for reuse
+ queryAndResult.result.close();
+ };
+
private final AtomicInteger sessionIdCounter = new AtomicInteger();
private final Cache cache;
@@ -78,12 +89,10 @@ private QueryAndResult(final String query, final XQueryUtil.QueryResult result)
}
public SessionManager() {
- final Caffeine