All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.rdf4j.federated.structures.QueryInfo Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2019 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.federated.structures;

import java.math.BigInteger;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.rdf4j.federated.FederationContext;
import org.eclipse.rdf4j.federated.algebra.PassThroughTupleExpr;
import org.eclipse.rdf4j.federated.evaluation.FederationEvalStrategy;
import org.eclipse.rdf4j.federated.evaluation.concurrent.ParallelTask;
import org.eclipse.rdf4j.federated.util.QueryStringUtil;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.Dataset;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Structure to maintain query information during evaluation, is attached to algebra nodes. Each instance is uniquely
 * attached to the query.
 * 

* The queryId can be used to abort tasks belonging to a particular evaluation. * * @author Andreas Schwarte */ public class QueryInfo { private static final Logger log = LoggerFactory.getLogger(QueryInfo.class); protected static final AtomicInteger NEXT_QUERY_ID = new AtomicInteger(1); // static id count private final BigInteger queryID; private final String query; private final String baseURI; private final QueryType queryType; private final long maxExecutionTimeMs; private final long start; private final boolean includeInferred; private final Dataset dataset; private TupleQueryResultHandler resultHandler = null; private final FederationContext federationContext; private final FederationEvalStrategy strategy; protected boolean done = false; protected Set> scheduledSubtasks = ConcurrentHashMap.newKeySet(); /** * @param query * @param queryType * @param maxExecutionTime the maximum explicit query time in seconds, if 0 use * {@link org.eclipse.rdf4j.federated.FedXConfig#getEnforceMaxQueryTime()} * @param includeInferred whether to include inferred statements * @param federationContext the {@link FederationContext} * @param dataset the {@link Dataset} */ public QueryInfo(String query, String baseURI, QueryType queryType, int maxExecutionTime, boolean includeInferred, FederationContext federationContext, FederationEvalStrategy strategy, Dataset dataset) { super(); this.queryID = federationContext.getQueryManager().getNextQueryId(); this.federationContext = federationContext; this.query = query; this.baseURI = baseURI; this.queryType = queryType; this.dataset = dataset; int _maxExecutionTime = maxExecutionTime <= 0 ? federationContext.getConfig().getEnforceMaxQueryTime() : maxExecutionTime; this.maxExecutionTimeMs = _maxExecutionTime * 1000; this.includeInferred = includeInferred; this.start = System.currentTimeMillis(); this.strategy = strategy; } public QueryInfo(Resource subj, IRI pred, Value obj, int maxExecutionTime, boolean includeInferred, FederationContext federationContext, FederationEvalStrategy strategy, Dataset dataset) { this(QueryStringUtil.toString(subj, pred, obj), null, QueryType.GET_STATEMENTS, maxExecutionTime, includeInferred, federationContext, strategy, dataset); } public BigInteger getQueryID() { return queryID; } public String getQuery() { return query; } public QueryType getQueryType() { return queryType; } public boolean getIncludeInferred() { return includeInferred; } public Dataset getDataset() { return dataset; } /** * @return the baseURI */ public String getBaseURI() { return baseURI; } /** * @return the {@link FederationEvalStrategy} active in the current query context */ public FederationEvalStrategy getStrategy() { return this.strategy; } /** * @return the {@link FederationContext} in which this query is executed */ public FederationContext getFederationContext() { return this.federationContext; } /** * @return the maximum remaining time in ms until the query runs into a timeout. If negative, timeout has been * reached */ public long getMaxRemainingTimeMS() { if (maxExecutionTimeMs <= 0) { return Long.MAX_VALUE; } // compute max remaining time // Note: return 1ms as a timeout to properly get this handled in executors long runningTime = System.currentTimeMillis() - start; long maxTime = maxExecutionTimeMs - runningTime; if (log.isTraceEnabled()) { log.trace("Applying max remaining time: " + maxTime); } return maxTime; } /** * Register a new scheduled task for this query. * * @param task * @throws QueryEvaluationException if the query has been aborted or closed */ public synchronized void registerScheduledTask(ParallelTask task) throws QueryEvaluationException { if (done) { task.cancel(); throw new QueryEvaluationException("Query is aborted or closed, cannot accept new tasks"); } scheduledSubtasks.add(task); } /** * Returns a {@link TupleQueryResultHandler} if this query is executed using. * {@link TupleQuery#evaluate(TupleQueryResultHandler)}. * * @return the {@link TupleQueryResultHandler} that can be used for pass through * @see PassThroughTupleExpr */ public Optional getResultHandler() { return Optional.ofNullable(resultHandler); } /** * Set the {@link TupleQueryResultHandler} if the query is executed using * {@link TupleQuery#evaluate(TupleQueryResultHandler)} allowing for passing through results to the handler. * * @param resultHandler the {@link TupleQueryResultHandler} */ public void setResultHandler(TupleQueryResultHandler resultHandler) { this.resultHandler = resultHandler; } /** * Mark the query as aborted and abort all scheduled (future) tasks known at this point in time. Also do not accept * any new scheduled tasks */ public synchronized void abort() { if (done) { return; } done = true; abortScheduledTasks(); } /** * Close this query. If exists, all scheduled (future) tasks known at this point in time are aborted. Also do not * accept any new scheduled tasks */ public synchronized void close() { if (done) { return; } done = true; closeScheduledTasks(); } /** * Abort any scheduled future tasks */ protected void abortScheduledTasks() { Throwable throwable = null; for (ParallelTask task : scheduledSubtasks) { try { task.cancel(); } catch (Throwable t) { if (throwable != null) { t.addSuppressed(throwable); } throwable = t; } } scheduledSubtasks.clear(); if (throwable != null) { if (throwable instanceof RuntimeException) { throw ((RuntimeException) throwable); } throw ((Error) throwable); } } private void closeScheduledTasks() { Throwable throwable = null; for (ParallelTask task : scheduledSubtasks) { try { task.close(); } catch (Throwable t) { if (throwable != null) { t.addSuppressed(throwable); } throwable = t; } } scheduledSubtasks.clear(); if (throwable != null) { if (throwable instanceof RuntimeException) { throw ((RuntimeException) throwable); } throw ((Error) throwable); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((queryID == null) ? 0 : queryID.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } QueryInfo other = (QueryInfo) obj; if (queryID == null) { return other.queryID == null; } else return queryID.equals(other.queryID); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy