Skip to content
Snippets Groups Projects
Commit 714e93fc authored by gmantele's avatar gmantele
Browse files

[TAP] Improve the abortion of queries, particularly during the UPLOAD phase.

Now, it is recommended to throw a DBCancelledException from any DBConnection
long processing. It is already done for the upload of a table, the execution
of an ADQL query and the setting of a whole TAP_SCHEMA. The flag
JDBCConnection#cancelled has now a bit different meaning: it is set even if
the Statement.cancel() fails so that any JDBCConnection function can see that
a cancellation has been requested.
parent 225c49e1
No related branches found
No related tags found
No related merge requests found
...@@ -16,7 +16,7 @@ package tap; ...@@ -16,7 +16,7 @@ package tap;
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
* *
* Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI) * Astronomisches Rechen Institut (ARI)
*/ */
...@@ -31,6 +31,7 @@ import adql.parser.ParseException; ...@@ -31,6 +31,7 @@ import adql.parser.ParseException;
import adql.query.ADQLQuery; import adql.query.ADQLQuery;
import tap.data.DataReadException; import tap.data.DataReadException;
import tap.data.TableIterator; import tap.data.TableIterator;
import tap.db.DBCancelledException;
import tap.db.DBConnection; import tap.db.DBConnection;
import tap.db.DBException; import tap.db.DBException;
import tap.formatter.OutputFormat; import tap.formatter.OutputFormat;
...@@ -104,7 +105,7 @@ import uws.service.log.UWSLog.LogLevel; ...@@ -104,7 +105,7 @@ import uws.service.log.UWSLog.LogLevel;
* </p> * </p>
* *
* @author Gr&eacute;gory Mantelet (CDS;ARI) * @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.1 (04/2016) * @version 2.1 (04/2017)
*/ */
public class ADQLExecutor { public class ADQLExecutor {
...@@ -267,7 +268,7 @@ public class ADQLExecutor { ...@@ -267,7 +268,7 @@ public class ADQLExecutor {
* @since 2.1 * @since 2.1
*/ */
public final void cancelQuery(){ public final void cancelQuery(){
if (dbConn != null && progression == ExecutionProgression.EXECUTING_ADQL) if (dbConn != null && (progression == ExecutionProgression.EXECUTING_ADQL || progression == ExecutionProgression.UPLOADING))
dbConn.cancel(true); dbConn.cancel(true);
} }
...@@ -382,6 +383,8 @@ public class ADQLExecutor { ...@@ -382,6 +383,8 @@ public class ADQLExecutor {
endStep(); endStep();
if (queryResult == null || thread.isInterrupted()) if (queryResult == null || thread.isInterrupted())
/* Note: 'queryResult == null' is for former version of the library
* ; now, a DBCancelledException should be thrown instead */
throw new InterruptedException(); throw new InterruptedException();
// 4. WRITE RESULT: // 4. WRITE RESULT:
...@@ -400,6 +403,9 @@ public class ADQLExecutor { ...@@ -400,6 +403,9 @@ public class ADQLExecutor {
logger.logTAP(LogLevel.INFO, report, "END_EXEC", "ADQL query execution finished.", null); logger.logTAP(LogLevel.INFO, report, "END_EXEC", "ADQL query execution finished.", null);
return report; return report;
}catch(DBCancelledException dce){
throw new InterruptedException();
}finally{ }finally{
// Close the result if any: // Close the result if any:
if (queryResult != null){ if (queryResult != null){
...@@ -570,15 +576,15 @@ public class ADQLExecutor { ...@@ -570,15 +576,15 @@ public class ADQLExecutor {
* *
* @param adql The object representation of the ADQL query to execute. * @param adql The object representation of the ADQL query to execute.
* *
* @return The result of the query, * @return The result of the query.
* or NULL if the query execution has failed.
* *
* @throws InterruptedException If the thread has been interrupted. * @throws InterruptedException If the thread has been interrupted.
* @throws DBCancelledException If the inner DB connection has been canceled.
* @throws TAPException If the {@link DBConnection} has failed to deal with the given ADQL query. * @throws TAPException If the {@link DBConnection} has failed to deal with the given ADQL query.
* *
* @see DBConnection#executeQuery(ADQLQuery) * @see DBConnection#executeQuery(ADQLQuery)
*/ */
protected TableIterator executeADQL(final ADQLQuery adql) throws InterruptedException, TAPException{ protected TableIterator executeADQL(final ADQLQuery adql) throws InterruptedException, DBCancelledException, TAPException{
// Log the start of execution: // Log the start of execution:
logger.logTAP(LogLevel.INFO, report, "START_DB_EXECUTION", "ADQL query: " + adql.toADQL().replaceAll("(\t|\r?\n)+", " "), null); logger.logTAP(LogLevel.INFO, report, "START_DB_EXECUTION", "ADQL query: " + adql.toADQL().replaceAll("(\t|\r?\n)+", " "), null);
...@@ -590,16 +596,22 @@ public class ADQLExecutor { ...@@ -590,16 +596,22 @@ public class ADQLExecutor {
dbConn.setFetchSize(service.getFetchSize()[0]); dbConn.setFetchSize(service.getFetchSize()[0]);
} }
// Execute the ADQL query: try{
TableIterator result = dbConn.executeQuery(adql); // Execute the ADQL query:
TableIterator result = dbConn.executeQuery(adql);
// Log the success or failure: // If NULL, in a former version of the library, it means the query execution has been aborted:
if (result == null) if (result == null)
logger.logTAP(LogLevel.INFO, report, "END_DB_EXECUTION", "Query execution aborted after " + (System.currentTimeMillis() - startStep) + "ms!", null); throw new DBCancelledException();
else
// Log the success:
logger.logTAP(LogLevel.INFO, report, "END_DB_EXECUTION", "Query successfully executed in " + (System.currentTimeMillis() - startStep) + "ms!", null); logger.logTAP(LogLevel.INFO, report, "END_DB_EXECUTION", "Query successfully executed in " + (System.currentTimeMillis() - startStep) + "ms!", null);
return result; return result;
}catch(DBCancelledException dce){
logger.logTAP(LogLevel.INFO, report, "END_DB_EXECUTION", "Query execution aborted after " + (System.currentTimeMillis() - startStep) + "ms!", null);
throw dce;
}
} }
/** /**
......
package tap.db;
/*
* This file is part of TAPLibrary.
*
* TAPLibrary is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* TAPLibrary is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2017 - Astronomisches Rechen Institut (ARI)
*/
/**
* Exception thrown when a processing of a {@link DBConnection} is cancelled.
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 2.1 (04/2017)
*/
public class DBCancelledException extends DBException {
private static final long serialVersionUID = 1L;
public DBCancelledException(){
super("DB interaction cancelled!");
}
public DBCancelledException(String message){
super(message);
}
public DBCancelledException(String message, String query){
super(message, query);
}
public DBCancelledException(Throwable cause){
super(cause);
}
public DBCancelledException(Throwable cause, String query){
super(cause, query);
}
public DBCancelledException(String message, Throwable cause){
super(message, cause);
}
public DBCancelledException(String message, Throwable cause, String query){
super(message, cause, query);
}
}
...@@ -45,7 +45,7 @@ import tap.metadata.TAPTable; ...@@ -45,7 +45,7 @@ import tap.metadata.TAPTable;
* </p> * </p>
* *
* @author Gr&eacute;gory Mantelet (CDS;ARI) * @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.1 (03/2017) * @version 2.1 (04/2017)
*/ */
public interface DBConnection { public interface DBConnection {
...@@ -172,11 +172,12 @@ public interface DBConnection { ...@@ -172,11 +172,12 @@ public interface DBConnection {
* *
* @param metadata List of all schemas, tables, columns and foreign keys to insert in the TAP_SCHEMA. * @param metadata List of all schemas, tables, columns and foreign keys to insert in the TAP_SCHEMA.
* *
* @throws DBCancelledException If {@link #cancel(boolean)} has been called during the processing.
* @throws DBException If any error occurs while updating the database. * @throws DBException If any error occurs while updating the database.
* *
* @since 2.0 * @since 2.0
*/ */
public void setTAPSchema(final TAPMetadata metadata) throws DBException; public void setTAPSchema(final TAPMetadata metadata) throws DBCancelledException, DBException;
/** /**
* Add the defined and given table inside the TAP_UPLOAD schema. * Add the defined and given table inside the TAP_UPLOAD schema.
...@@ -192,12 +193,13 @@ public interface DBConnection { ...@@ -192,12 +193,13 @@ public interface DBConnection {
* *
* @return <i>true</i> if the given table has been successfully added, <i>false</i> otherwise. * @return <i>true</i> if the given table has been successfully added, <i>false</i> otherwise.
* *
* @throws DBCancelledException If {@link #cancel(boolean)} has been called during the processing.
* @throws DBException If any error occurs while adding the table. * @throws DBException If any error occurs while adding the table.
* @throws DataReadException If any error occurs while reading the given data (particularly if any limit - in byte or row - set in the TableIterator is reached). * @throws DataReadException If any error occurs while reading the given data (particularly if any limit - in byte or row - set in the TableIterator is reached).
* *
* @since 2.0 * @since 2.0
*/ */
public boolean addUploadedTable(final TAPTable tableDef, final TableIterator data) throws DBException, DataReadException; public boolean addUploadedTable(final TAPTable tableDef, final TableIterator data) throws DBCancelledException, DBException, DataReadException;
/** /**
* <p>Drop the specified uploaded table from the database. * <p>Drop the specified uploaded table from the database.
...@@ -237,16 +239,17 @@ public interface DBConnection { ...@@ -237,16 +239,17 @@ public interface DBConnection {
* *
* @param adqlQuery ADQL query to execute. * @param adqlQuery ADQL query to execute.
* *
* @return The table result or NULL if the query has been aborted. * @return The table result.
* *
* @throws DBException If any errors occurs while executing the query. * @throws DBCancelledException If {@link #cancel(boolean)} has been called (i.e. query aborted) during the processing.
* @throws DBException If any errors occurs while executing the query.
* *
* @since 2.0 * @since 2.0
* *
* @see #endQuery() * @see #endQuery()
* @see TableIterator#close() * @see TableIterator#close()
*/ */
public TableIterator executeQuery(final ADQLQuery adqlQuery) throws DBException; public TableIterator executeQuery(final ADQLQuery adqlQuery) throws DBCancelledException, DBException;
/** /**
* <p>Set the number of rows to fetch before searching/getting the following. * <p>Set the number of rows to fetch before searching/getting the following.
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment