Skip to content
Snippets Groups Projects
Commit f912c20a authored by Grégory Mantelet's avatar Grégory Mantelet
Browse files

[TAP] Fix cancellation of a text formatting process.

Before this fix, cancelling a TAP job (async or not) which was formatting the
result in ASCII may failed, especially for large results. This was due to a
non interruptible alignment process. This process is now checking whether a
cancellation has been requested before formatting a new result line/row ; if so,
the process is immediately stopped and the job can be cleaning declared as
aborted.
parent fb4cbcfd
No related branches found
No related tags found
No related merge requests found
......@@ -16,20 +16,25 @@ package cds.util;
* 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 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
* Copyright 2012-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.util.ArrayList;
/**
* An object of this class manages an ascii table: it receives lines to add,
* An object of this class manages an ASCII table: it receives lines to add,
* made of columns separated by a given separator char. Columns can be aligned
* (RIGHT, LEFT or CENTER) before display
*
* @author Marc Wenger/CDS
* @version 1.0 May 2008 Creation<br>
* @version 1.1 May 2008 Fix a bug: lines are kept without a newline at the end<br>
* @version 1.2 Jun 2008 Add a toString method (items aligned).<br>
* @author Gr&eacute;gory Mantelet/CDS
*
* @version 1.0 May 2008 MW Creation
* @version 1.1 May 2008 MW Fix a bug: lines are kept without a newline at the
* end
* @version 1.2 Jun 2008 MW Add a toString method (items aligned) ;
* Fix a bug in align() when the last line is not full
* @version 1.3 Nov 2018 GM Make the alignment process - align() - interruptible
*/
public class AsciiTable {
public static final int LEFT = 0;
......@@ -86,8 +91,8 @@ public class AsciiTable {
/**
* Add a line to the table
* @param line string containing the line with all the columns separated by the column separator.
* The line should not end up with a newline char. If it is the case, alignement errors can be experienced
* depending on the alignement type of the last column.
* The line should not end up with a newline char. If it is the case, alignment errors can be experienced
* depending on the alignment type of the last column.
*/
public void addLine(String line){
// compute the number of columns, if we add the first line
......@@ -129,7 +134,7 @@ public class AsciiTable {
}
/**
* Get all the lines without alignement, as they were entered
* Get all the lines without alignment, as they were entered
* @return the array of the lines in the table
*/
public String[] displayRaw(){
......@@ -137,7 +142,7 @@ public class AsciiTable {
}
/**
* Get all the lines without alignement, as they were entered, with separator control
* Get all the lines without alignment, as they were entered, with separator control
* @param newsep separator to use, replacing the original one
* @return the array of the lines in the table
*/
......@@ -156,49 +161,121 @@ public class AsciiTable {
/**
* Get all the lines in the table, properly aligned.
* @param pos array of flags, indicating how each column should be justified.
* The array must have as many columns as the table has. Each column can contain
* either AsciiTable.LEFT, AsciiTable.CENTER or AsciiTable.RIGHT<br>
* if the array contains ONE item, it will be used for every column.
* @return an array of the table lines, aligned and justified
*
* <p><strong>IMPORTANT:</strong>
* The array must have as many columns as the table has. Each column can
* contain either {@link AsciiTable#LEFT}, {@link AsciiTable#CENTER} or
* {@link AsciiTable#RIGHT}. If the array contains ONE item, it will be
* used for every column.
* </p>
*
* @param pos Array of flags, indicating how each column should be
* justified.
*
* @return An array of the table lines, aligned and justified.
*
* @throws InterruptedException If the current thread has been interrupted.
* <em>This interruption is useful when this
* alignment operation becomes time and memory
* consuming.</em>
*/
public String[] displayAligned(int[] pos){
return align(pos, '\0');
public String[] displayAligned(int[] pos) throws InterruptedException{
return align(pos, '\0', null);
}
/**
* Get all the lines in the table, properly aligned.
* @param pos array of flags, indicating how each column should be justified.
* The array must have as many columns as the table has. Each column can contain
* either AsciiTable.LEFT, AsciiTable.CENTER or AsciiTable.RIGHT<br>
* if the array contains ONE item, it will be used for every column.
* @param newsep separator to use, replacing the original one
* @return an array of the table lines, aligned and justified
*
* <p><strong>IMPORTANT:</strong>
* The array must have as many columns as the table has. Each column can
* contain either {@link AsciiTable#LEFT}, {@link AsciiTable#CENTER} or
* {@link AsciiTable#RIGHT}. If the array contains ONE item, it will be
* used for every column.
* </p>
*
* @param pos Array of flags, indicating how each column should be
* justified.
* @param newsep Separator to use, replacing the original one.
*
* @return An array of the table lines, aligned and justified.
*
* @throws InterruptedException If the current thread has been interrupted.
* <em>This interruption is useful when this
* alignment operation becomes time and memory
* consuming.</em>
*/
public String[] displayAligned(int[] pos, char newsep) throws InterruptedException{
return displayAligned(pos, newsep, null);
}
/**
* Get all the lines in the table, properly aligned.
*
* <p><strong>IMPORTANT:</strong>
* The array must have as many columns as the table has. Each column can
* contain either {@link AsciiTable#LEFT}, {@link AsciiTable#CENTER} or
* {@link AsciiTable#RIGHT}. If the array contains ONE item, it will be
* used for every column.
* </p>
*
* @param pos Array of flags, indicating how each column should be
* justified.
* @param newsep Separator to use, replacing the original one.
* @param thread Thread to watch. If it is interrupted, this task should
* be as well.
*
* @return An array of the table lines, aligned and justified.
*
* @throws InterruptedException If the current thread has been interrupted.
* <em>This interruption is useful when this
* alignment operation becomes time and memory
* consuming.</em>
*/
public String[] displayAligned(int[] pos, char newsep){
public String[] displayAligned(int[] pos, char newsep, final Thread thread) throws InterruptedException{
if (newsep == csep)
newsep = '\0';
return align(pos, newsep);
return align(pos, newsep, thread);
}
/**
* Get the array of lines in which all the columns are aligned
* @param pos array of flags, indicating how each column should be justified.
* The array must have as many columns as the table has. Each column can contain
* either AsciiTable.LEFT, AsciiTable.CENTER or AsciiTable.RIGHT<br>
* if the array contains ONE item, it will be used for every column.
* @param newsep separator to use, replacing the original one (no replacement if '\0')
* @return an array of the table lines, aligned and justified
*
* <p><strong>IMPORTANT:</strong>
* The array must have as many columns as the table has. Each column can
* contain either {@link AsciiTable#LEFT}, {@link AsciiTable#CENTER} or
* {@link AsciiTable#RIGHT}. If the array contains ONE item, it will be
* used for every column.
* </p>
*
* @param pos Array of flags, indicating how each column should be
* justified.
* @param newsep Separator to use, replacing the original one.
* @param thread Thread to watch. If it is interrupted, this task should
* be as well.
*
* @return An array of the table lines, aligned and justified.
*
* @throws InterruptedException If the current thread has been interrupted.
* <em>This interruption is useful when this
* alignment operation becomes time and memory
* consuming.</em>
*/
private String[] align(int[] pos, char newsep){
private String[] align(int[] pos, char newsep, final Thread thread) throws InterruptedException{
int nblines = lines.size();
String[] result = new String[nblines];
StringBuffer buf = new StringBuffer();
int p0, p1, col, fldsize, colsize, n1, inserted;
boolean inHeader = header; // A header can contain several lines. The end is detected by a line
// beginning by the separator char
int uniqueJustif = pos.length == 1 ? pos[0] : -1;
for(int i = 0; i < nblines; i++){
/* stop everything if this thread or the given one has been
* interrupted: */
if (Thread.currentThread().isInterrupted() || (thread != null && thread.isInterrupted()))
throw new InterruptedException();
buf.delete(0, buf.length());
String line = lines.get(i);
p0 = 0;
......@@ -277,11 +354,12 @@ public class AsciiTable {
}
/**
* Display the whole table, with left alignement
* Display the whole table, with left alignment
* @return the table as a unique string
*/
@Override
public String toString(){
try{
StringBuffer buf = new StringBuffer();
String[] ids = displayAligned(new int[]{ AsciiTable.LEFT });
......@@ -292,5 +370,8 @@ public class AsciiTable {
}
return buf.toString();
}catch(InterruptedException ie){
return "!!! Operation unexpectedly interrupted !!!";
}
}
}
......@@ -41,7 +41,7 @@ import tap.backup.DefaultTAPBackupManager;
* </i></p>
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.3 (09/2018)
* @version 2.3 (11/2018)
* @since 2.0
*/
public final class TAPConfiguration {
......@@ -166,12 +166,12 @@ public final class TAPConfiguration {
* This is the fetch size for to apply for synchronous queries. */
public final static String KEY_SYNC_FETCH_SIZE = "sync_fetch_size";
/** Default value of the property {@link #KEY_SYNC_FETCH_SIZE}: {@value #DEFAULT_SYNC_FETCH_SIZE}. */
public final static int DEFAULT_SYNC_FETCH_SIZE = 10000;
public final static int DEFAULT_SYNC_FETCH_SIZE = 1000;
/** Name/Key of the property specifying by how many rows the library should fetch a query result from the database.
* This is the fetch size for to apply for asynchronous queries. */
public final static String KEY_ASYNC_FETCH_SIZE = "async_fetch_size";
/** Default value of the property {@link #KEY_ASYNC_FETCH_SIZE}: {@value #DEFAULT_ASYNC_FETCH_SIZE}. */
public final static int DEFAULT_ASYNC_FETCH_SIZE = 100000;
public final static int DEFAULT_ASYNC_FETCH_SIZE = 10000;
/** Name/Key of the property specifying the name of the DataSource into the JDNI. */
public final static String KEY_DATASOURCE_JNDI_NAME = "datasource_jndi_name";
/** Name/Key of the property specifying the full class name of the JDBC driver.
......
......@@ -193,9 +193,9 @@
too much waiting time from the TAP /sync users (and thus, avoiding some HTTP client timeouts).</p>
<p>A negative or null value means that the default value of the JDBC driver will be used. Generally,
it means that the database must wait to have collected all data before sending them to the library.</p>
<p><em>Default: <code>sync_fetch_size=10000</code></em></p>
<p><em>Default: <code>sync_fetch_size=1000</code></em></p>
</td>
<td><ul><li>10000 <em>(default)</em><li>0 <em>(wait for the the whole result)</em></li><li>100000</li></ul></td>
<td><ul><li>1000 <em>(default)</em><li>0 <em>(wait for the the whole result)</em></li><li>100000</li></ul></td>
</tr>
<tr class="optional">
<td class="done">async_fetch_size</td>
......@@ -208,9 +208,9 @@
If supported by the DBMS and the JDBC driver, this feature may help sparing memory.</p>
<p>A negative or null value means that the default value of the JDBC driver will be used. Generally,
it means that the database must wait to have collected all data before sending them to the library.</p>
<p><em>Default: <code>async_fetch_size=100000</code></em></p>
<p><em>Default: <code>async_fetch_size=10000</code></em></p>
</td>
<td><ul><li>100000 <em>(default)</em><li>0 <em>(wait for the the whole result)</em></li><li>1000000</li></ul></td>
<td><ul><li>10000 <em>(default)</em><li>0 <em>(wait for the the whole result)</em></li><li>1000000</li></ul></td>
</tr>
<tr><td colspan="5">&#10551; JNDI datasource <i>(only if database_access=jndi)</i></td></tr>
......
......@@ -2,7 +2,7 @@
# FULL TAP CONFIGURATION FILE #
# #
# TAP Version: 2.3 #
# Date: 26 Oct. 2018 #
# Date: 2 Nov. 2018 #
# Author: Gregory Mantelet (CDS;ARI) #
# #
################################################################################
......@@ -104,7 +104,7 @@ sql_translator = postgres
# data before sending them to the library.
#
# Default: sync_fetch_size=10000
sync_fetch_size = 10000
sync_fetch_size = 1000
# [OPTIONAL]
# Size of result blocks to fetch from the database when an ADQL query is
......@@ -120,7 +120,7 @@ sync_fetch_size = 10000
# data before sending them to the library.
#
# Default: async_fetch_size=100000
async_fetch_size=100000
async_fetch_size=10000
#############################
# IF DATABASE ACCESS = JNDI #
......
......@@ -16,7 +16,7 @@ package tap.formatter;
* 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 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Copyright 2012-2018 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
......@@ -37,7 +37,7 @@ import tap.data.TableIterator;
* (columns' width are adjusted so that all columns are well aligned and of the same width).
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 2.0 (04/2015)
* @version 2.3 (11/2018)
*/
public class TextFormat implements OutputFormat {
......@@ -101,10 +101,10 @@ public class TextFormat implements OutputFormat {
// Finally write the formatted ASCII table (header + data) in the output stream:
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output));
String[] lines = asciiTable.displayAligned(new int[]{AsciiTable.LEFT}, '|');
String[] lines = asciiTable.displayAligned(new int[]{ AsciiTable.LEFT }, '|', thread);
execReport.nbRows = 0;
for(String l : lines){
// stop right now the formatting if the job has been aborted/canceled/interrupted:
// stop right now the formatting if the job has been aborted/cancelled/interrupted:
if (thread.isInterrupted())
throw new InterruptedException();
// write the line:
......@@ -180,7 +180,7 @@ public class TextFormat implements OutputFormat {
StringBuffer line = new StringBuffer();
while(queryResult.nextRow()){
// Stop right now the formatting if the job has been aborted/canceled/interrupted:
// Stop right now the formatting if the job has been aborted/cancelled/interrupted:
if (thread.isInterrupted())
throw new InterruptedException();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment