diff --git a/src/tap/AbstractTAPFactory.java b/src/tap/AbstractTAPFactory.java index 359b3cbde1ce780131d4e098f6299a4393388574..cc364a31b01345868c936a88eedbd50f6cf063d0 100644 --- a/src/tap/AbstractTAPFactory.java +++ b/src/tap/AbstractTAPFactory.java @@ -215,6 +215,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { public UWSService createUWS() throws TAPException{ try{ UWSService uws = new UWSService(this, this.service.getFileManager(), this.service.getLogger()); + uws.setName("TAP/async"); uws.setErrorWriter(errorWriter); return uws; }catch(UWSException ue){ diff --git a/src/tap/ServiceConnection.java b/src/tap/ServiceConnection.java index 444df9d8a6edf73a1b01bf2f7ad95c69de2c4614..37eddb236cb70bb548e67893afb4b8bebd28b264 100644 --- a/src/tap/ServiceConnection.java +++ b/src/tap/ServiceConnection.java @@ -91,7 +91,8 @@ public interface ServiceConnection { /** * <i><b>[MANDATORY]</b></i> - * <p>This function controls the state of the whole TAP service.</p> + * <p>This function tells whether the TAP service is available + * (that's to say, "able to execute requests" ; resources like /availability, /capabilities and /tables may still work).</p> * * <p> * A message explaining the current state of the TAP service could be provided thanks to {@link #getAvailability()}. @@ -111,6 +112,21 @@ public interface ServiceConnection { */ public String getAvailability(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>This function sets the state of the whole TAP service. + * If true, all TAP resources will be able to execute resources. + * If false, /sync and /async won't answer any more to requests and a HTTP-503 (Service unavailable) + * error will be returned. + * </p> + * + * @param isAvailable <i>true</i> to enable all resources, <i>false</i> to forbid /sync and /async (all other resources will still be available). + * @param message A message describing the current state of the service. If NULL, a default message may be set by the library. + * + * @since 2.0 + */ + public void setAvailable(final boolean isAvailable, final String message); + /** * <i>[OPTIONAL]</i> * <p>Get the limit of the retention period.</p> diff --git a/src/tap/TAPFactory.java b/src/tap/TAPFactory.java index 49d3421ec3b963411faacbfd5d2bfaf1b0fe09fd..580e232831db6aebb92c5bc738dd0b7dd749c435 100644 --- a/src/tap/TAPFactory.java +++ b/src/tap/TAPFactory.java @@ -61,7 +61,7 @@ import adql.query.ADQLQuery; * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (11/2014) + * @version 2.0 (12/2014) */ public abstract class TAPFactory implements UWSFactory { @@ -90,7 +90,7 @@ public abstract class TAPFactory implements UWSFactory { * * @return The error writer to use. * - * @since 4.1 + * @since 2.0 */ public abstract ServiceErrorWriter getErrorWriter(); @@ -125,6 +125,8 @@ public abstract class TAPFactory implements UWSFactory { * @return A new and free connection to the database. <b>MUST BE NOT NULL, or otherwise a TAPException should be returned.</b> * * @throws TAPException If there is any error while getting a free connection. + * + * @since 2.0 */ public abstract DBConnection getConnection(final String jobID) throws TAPException; @@ -142,6 +144,8 @@ public abstract class TAPFactory implements UWSFactory { * </i></p> * * @param conn The connection to close. + * + * @since 2.0 */ public abstract void freeConnection(final DBConnection conn); @@ -163,9 +167,23 @@ public abstract class TAPFactory implements UWSFactory { * * @return The number of connections still available, * or <=0 in case of problem (<i>note: in this case, the error must be logged in the implementation of this function</i>). + * + * @since 2.0 */ public abstract int countFreeConnections(); + /** + * <p>Destroy all resources (and particularly DB connections and JDBC driver) allocated in this factory.</p> + * + * <p><i>Note: + * This function is called when the TAP service is shutting down. + * After this call, the factory may not be able to provide any closed resources ; its behavior may be unpredictable. + * </i></p> + * + * @since 2.0 + */ + public abstract void destroy(); + /* *************** */ /* ADQL MANAGEMENT */ /* *************** */ diff --git a/src/tap/resource/ASync.java b/src/tap/resource/ASync.java index fd0e7cdf5ae4d9ec43369f6104475dbb9349fe39..ccd94df703d6420efad34a6121f91e054fc40e92 100644 --- a/src/tap/resource/ASync.java +++ b/src/tap/resource/ASync.java @@ -175,7 +175,8 @@ public class ASync implements TAPResource { @Override public void destroy(){ - ; + if (uws != null) + uws.destroy(); } @Override diff --git a/src/tap/resource/TAP.java b/src/tap/resource/TAP.java index 918f2116ce1e7582f693b0978814a2c23a4a2a8f..65ec8b0d06c3e52f8a3dc11f5cffc704e5affcbe 100644 --- a/src/tap/resource/TAP.java +++ b/src/tap/resource/TAP.java @@ -154,8 +154,18 @@ public class TAP implements VOSIResource { * @see TAPResource#destroy() */ public void destroy(){ + // Set the availability to "false" and the reason to "The application server is stopping!": + service.setAvailable(false, "The application server is stopping!"); + + // Destroy all web resources: for(TAPResource res : resources.values()) res.destroy(); + + // Destroy also all resources allocated in the factory: + service.getFactory().destroy(); + + // Log the end: + getLogger().logTAP(LogLevel.INFO, this, "STOP", "TAP Service stopped!", null); } /** diff --git a/src/uws/job/manager/AbstractQueuedExecutionManager.java b/src/uws/job/manager/AbstractQueuedExecutionManager.java index 49a1d0be3b1f67a92a0987f0dff3f3857f6a046d..3fa56c22afc45f4f6c1e792fa6a3a7d5e750e177 100644 --- a/src/uws/job/manager/AbstractQueuedExecutionManager.java +++ b/src/uws/job/manager/AbstractQueuedExecutionManager.java @@ -34,17 +34,25 @@ import uws.service.log.UWSLog.LogLevel; /** * <p>Abstract implementation of the interface {@link ExecutionManager} which lets managing an execution queue.</p> + * * <p> * When calling {@link #execute(UWSJob)}, ALL jobs are put into the list of queued jobs (so their phase is changed * to {@link ExecutionPhase#QUEUED}). A call to {@link #refresh()}, reads this list and tries to execute the first job of the list. * The function {@link #isReadyForExecution(UWSJob)} decides whether the first job of the queue can be executed NOW or not. * </p> + * * <p><i>Note: * The order of queued jobs is preserved: it is implemented by a FIFO queue. * </i></p> * + * <p><i>Note: + * After a call to {@link #stopAll()}, this manager is still able to execute new jobs. + * Except if it was not possible to stop them properly, stopped jobs could be executed again by calling + * afterwards {@link #execute(UWSJob)} with these jobs in parameter. + * </i></p> + * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (08/2014) + * @version 4.1 (12/2014) */ public abstract class AbstractQueuedExecutionManager implements ExecutionManager { @@ -237,4 +245,36 @@ public abstract class AbstractQueuedExecutionManager implements ExecutionManager refresh(); } } + + @Override + public final synchronized void stopAll(){ + // Set back all queued jobs to the PENDING phase: + for(UWSJob qj : queuedJobs){ + try{ + qj.setPhase(ExecutionPhase.PENDING, true); + }catch(UWSException ue){ + if (logger != null) + logger.logJob(LogLevel.WARNING, qj, "ABORT", "Can not set back the job to the PENDING phase.", ue); + } + } + + // Empty the queue: + queuedJobs.clear(); + + // Stop all running jobs and set them back to the PENDING phase: + for(UWSJob rj : runningJobs.values()){ + try{ + // Stop the job: + rj.abort(); + // Set its phase back to PENDING: + rj.setPhase(ExecutionPhase.PENDING, true); + }catch(UWSException ue){ + if (logger != null) + logger.logJob(LogLevel.WARNING, rj, "ABORT", "Can not stop the job nicely. The thread may continue to run until its end.", ue); + } + } + + // Empty the list of running jobs: + runningJobs.clear(); + } } diff --git a/src/uws/job/manager/DefaultDestructionManager.java b/src/uws/job/manager/DefaultDestructionManager.java index 24bff3e6e1ae765a08ef33f8f9a65b50e0056d34..8a0314c2129b75a7edafabd0d100c61f457b8544 100644 --- a/src/uws/job/manager/DefaultDestructionManager.java +++ b/src/uws/job/manager/DefaultDestructionManager.java @@ -16,11 +16,11 @@ package uws.job.manager; * You should have received a copy of the GNU Lesser General Public License * along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>. * - * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.io.Serializable; - import java.util.Comparator; import java.util.Date; import java.util.Timer; @@ -34,19 +34,27 @@ import uws.job.UWSJob; * The default implementation of the {@link DestructionManager} interface. * Its goal is to manage the automatic destruction any given jobs. * </p> + * * <p> * Jobs can be added thanks to {@link #update(UWSJob)} and removed with {@link #remove(UWSJob)}. * All added jobs are stored in a {@link TreeSet} which sorts them by ascending destruction time. * The job which must be destroyed in first is used to start a timer. * This one will destroyed the job once its destruction time is reached. * </p> + * * <p> * The list of jobs to destroy is supposed to be updated each time the destruction time of a job is changed. This update works only if * the job knows its jobs list ({@link UWSJob#getJobList()} != null) and its jobs list has a destruction manager. * </p> * - * @author Grégory Mantelet (CDS) - * @version 05/2012 + * <p><i>Note: + * The {@link #stop()} function lets stop this manager to watch for destructions of job until {@link #refresh()} or + * {@link #update(UWSJob)} or {@link #remove(UWSJob)} is called. When stopped, the inner timer is canceled and set + * to NULL ; no more thread resources is used. + * </i></p> + * + * @author Grégory Mantelet (CDS;ARI) + * @version 4.1 (12/2014) */ public class DefaultDestructionManager implements DestructionManager { private static final long serialVersionUID = 1L; @@ -83,7 +91,8 @@ public class DefaultDestructionManager implements DestructionManager { /** * Stops the timer if running and set to <i>null</i> {@link #timDestruction}, {@link #currentDate} and {@link #currentJob}. */ - protected synchronized final void stop(){ + @Override + public synchronized final void stop(){ if (timDestruction != null) timDestruction.cancel(); timDestruction = null; @@ -111,18 +120,22 @@ public class DefaultDestructionManager implements DestructionManager { /** * <p>Returns <i>true</i> if {@link #currentDate} is different from <i>null</i>.</p> */ + @Override public final boolean isRunning(){ return currentDate != null; } + @Override public final Date getNextDestruction(){ return currentDate; } + @Override public final String getNextJobToDestroy(){ return (currentJob == null) ? null : currentJob.getJobId(); } + @Override public final int getNbJobsToDestroy(){ return jobsToDestroy.size() + (isRunning() ? 1 : 0); } @@ -147,6 +160,7 @@ public class DefaultDestructionManager implements DestructionManager { * @see #stop() * @see #destroyJob(UWSJob) */ + @Override public synchronized void refresh(){ // Finish the current timer if... if (isRunning()){ @@ -196,6 +210,7 @@ public class DefaultDestructionManager implements DestructionManager { * @see #destroyJob(UWSJob) * @see #refresh() */ + @Override public synchronized void update(UWSJob job){ if (job != null && job.getJobList() != null && job.getDestructionTime() != null){ if (job.getDestructionTime().before(new Date())) @@ -217,6 +232,7 @@ public class DefaultDestructionManager implements DestructionManager { * @see #stop() * @see #refresh() */ + @Override public synchronized void remove(UWSJob job){ if (job == null) return; diff --git a/src/uws/job/manager/DefaultExecutionManager.java b/src/uws/job/manager/DefaultExecutionManager.java index 333cbca0294adc0c4549dc754df0355c57d78091..7049aaf6a76690c24a2babd1db7c2905c79b6ff2 100644 --- a/src/uws/job/manager/DefaultExecutionManager.java +++ b/src/uws/job/manager/DefaultExecutionManager.java @@ -36,9 +36,15 @@ import uws.service.log.UWSLog.LogLevel; * * <p>This manager does not have a queue. That is to say that all jobs are always immediately starting. * Consequently this manager is just used to gather all running jobs.</p> + * + * <p><i>Note: + * After a call to {@link #stopAll()}, this manager is still able to execute new jobs. + * Except if it was not possible to stop them properly, stopped jobs could be executed again by calling + * afterwards {@link #execute(UWSJob)} with these jobs in parameter. + * </i></p> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (08/2014) + * @version 4.1 (12/2014) */ public class DefaultExecutionManager implements ExecutionManager { @@ -147,4 +153,22 @@ public class DefaultExecutionManager implements ExecutionManager { if (jobToRemove != null) runningJobs.remove(jobToRemove.getJobId()); } + + @Override + public synchronized void stopAll(){ + // Stop all running jobs: + for(UWSJob rj : runningJobs.values()){ + try{ + // Stop the job: + rj.abort(); + // Set its phase back to PENDING: + rj.setPhase(ExecutionPhase.PENDING, true); + }catch(UWSException ue){ + if (logger != null) + logger.logJob(LogLevel.WARNING, rj, "ABORT", "Can not stop the job nicely. The thread may continue to run until its end.", ue); + } + } + // Empty the list of running jobs: + runningJobs.clear(); + } } diff --git a/src/uws/job/manager/DestructionManager.java b/src/uws/job/manager/DestructionManager.java index 5bb89066a3b998da8e23cb787638b2ff97c61e77..022ecbc41717fe988a3c5ef7f53e1477b68cb97f 100644 --- a/src/uws/job/manager/DestructionManager.java +++ b/src/uws/job/manager/DestructionManager.java @@ -16,16 +16,15 @@ package uws.job.manager; * You should have received a copy of the GNU Lesser General Public License * along with UWSLibrary. If not, see <http://www.gnu.org/licenses/>. * - * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.io.Serializable; - import java.util.Date; import uws.job.JobList; import uws.job.UWSJob; - import uws.service.UWS; /** @@ -50,8 +49,8 @@ import uws.service.UWS; * </i> * </p> * - * @author Grégory Mantelet (CDS) - * @version 05/2012 + * @author Grégory Mantelet (CDS;ARI) + * @version 4.1 (12/2014) * * @see DefaultDestructionManager */ @@ -114,4 +113,15 @@ public interface DestructionManager extends Serializable { * @param job The job to remove. */ public void remove(UWSJob job); + + /** + * <p>Stop watching the destruction of jobs.</p> + * + * <p><i>Note: + * A subsequent call to {@link #update(UWSJob)} may enable again this manager. + * </i></p> + * + * @since 4.1 + */ + public void stop(); } diff --git a/src/uws/job/manager/ExecutionManager.java b/src/uws/job/manager/ExecutionManager.java index f95bd620161e1b87b77309406215bd033073245a..e50d86d9b0a23e771e17d7293bf5102ecf9c0e2e 100644 --- a/src/uws/job/manager/ExecutionManager.java +++ b/src/uws/job/manager/ExecutionManager.java @@ -36,7 +36,7 @@ import uws.job.UWSJob; * </p> * * @author Grégory Mantelet (CDS;ARI) - * @version 4.1 (08/2014) + * @version 4.1 (12/2014) */ public interface ExecutionManager { @@ -102,4 +102,17 @@ public interface ExecutionManager { * @param jobToRemove The job to remove. */ public void remove(final UWSJob jobToRemove); + + /** + * <p>Stop all running jobs. No more job, even the queued ones, must be executed after a call to this function. + * All stopped or aborted queued jobs should be set forcedly back to the PENDING status.</p> + * + * <p><i>Note: + * A call to {@link #execute(UWSJob)} would re-activate this manager. However jobs stopped or + * aborted using this function might not be starting again. These behaviors at implementation-dependent. + * </i></p> + * + * @since 4.1 + */ + public void stopAll(); } diff --git a/src/uws/service/UWS.java b/src/uws/service/UWS.java index ebd0689add0a0a40e423e4c89c892d80039ae1f1..9c545b259a2ae171b5e984083483448d07a702ac 100644 --- a/src/uws/service/UWS.java +++ b/src/uws/service/UWS.java @@ -58,6 +58,11 @@ import uws.service.request.UWSRequestParser; * the UWS and the servlet. * </p> * + * <p><b>IMPORTANT: + * All implementations of this interface should implement properly the function {@link #closeService()} and should call it + * when the JVM or the HTTP server application is closing. + * </b></p> + * * @author Grégory Mantelet (CDS;ARI) * @version 4.1 (12/2014) */ @@ -85,6 +90,28 @@ public interface UWS extends Iterable<JobList> { */ public String getDescription(); + /* ***************** */ + /* RESOURCES RELEASE */ + /* ***************** */ + + /** + * <p> + * End properly this UWS: jobs should be backuped (if this feature is enable), timers and threads should be stopped, + * open files and database connections should be closed, etc... + * In brief, this function should release all used resources. + * </p> + * + * <p><b>IMPORTANT: This function should be called only when the JVM or the Web Application Server is stopping.</b></p> + * + * <p><i>Note: + * A call to this function may prevent this instance of {@link UWS} to execute any subsequent HTTP request, or the behavior + * would be unpredictable. + * </i></p> + * + * @since 4.1 + */ + public void destroy(); + /* ******************* */ /* JOB LIST MANAGEMENT */ /* ******************* */ diff --git a/src/uws/service/UWSService.java b/src/uws/service/UWSService.java index a2b1e74b174a964fd9608241e47619e17d93360c..9867ef694fc5ae1ec80ffcb7eb8ed9ecfcd09c1f 100644 --- a/src/uws/service/UWSService.java +++ b/src/uws/service/UWSService.java @@ -37,6 +37,7 @@ import uws.UWSException; import uws.UWSToolBox; import uws.job.ExecutionPhase; import uws.job.JobList; +import uws.job.JobThread; import uws.job.UWSJob; import uws.job.manager.DefaultExecutionManager; import uws.job.serializer.JSONSerializer; @@ -414,6 +415,35 @@ public class UWSService implements UWS { logger.logUWS(LogLevel.INFO, this, "INIT", "UWS successfully initialized.", null); } + @Override + public void destroy(){ + // Backup all jobs: + /* Jobs are backuped now so that running jobs are set back to the PENDING phase in the backup. + * Indeed, the "stopAll" operation of the ExecutionManager may fail and would set the phase to ERROR + * for the wrong reason. */ + if (backupManager != null){ + // save all jobs: + backupManager.setEnabled(true); + backupManager.saveAll(); + // stop the automatic backup, if there is one: + backupManager.setEnabled(false); + } + + // Stop all jobs and stop watching for the jobs' destruction: + for(JobList jl : mapJobLists.values()){ + jl.getExecutionManager().stopAll(); + jl.getDestructionManager().stop(); + } + + // Just in case that previous clean "stop"s did not work, try again an interruption for all running threads: + /* note: timers are not part of this ThreadGroup and so, they won't be affected by this function call. */ + JobThread.tg.interrupt(); + + // Log the service is stopped: + if (logger != null) + logger.logUWS(LogLevel.INFO, this, "STOP", "UWS Service \"" + getName() + "\" stopped!", null); + } + /* ************** */ /* LOG MANAGEMENT */ /* ************** */ diff --git a/src/uws/service/UWSServlet.java b/src/uws/service/UWSServlet.java index da9b7f5b1ec1f371e4c34c9f11208db6024e84a8..e755f4e2633db2ba1482fce40e57caefa350f246 100644 --- a/src/uws/service/UWSServlet.java +++ b/src/uws/service/UWSServlet.java @@ -47,6 +47,7 @@ import uws.UWSExceptionFactory; import uws.UWSToolBox; import uws.job.ErrorSummary; import uws.job.JobList; +import uws.job.JobThread; import uws.job.Result; import uws.job.UWSJob; import uws.job.parameters.DestructionTimeController; @@ -240,6 +241,38 @@ public abstract class UWSServlet extends HttpServlet implements UWS, UWSFactory public abstract void initUWS() throws UWSException; + @Override + public void destroy(){ + // Backup all jobs: + /* Jobs are backuped now so that running jobs are set back to the PENDING phase in the backup. + * Indeed, the "stopAll" operation of the ExecutionManager may fail and would set the phase to ERROR + * for the wrong reason. */ + if (backupManager != null){ + // save all jobs: + backupManager.setEnabled(true); + backupManager.saveAll(); + // stop the automatic backup, if there is one: + backupManager.setEnabled(false); + } + + // Stop all jobs and stop watching for the jobs' destruction: + for(JobList jl : mapJobLists.values()){ + jl.getExecutionManager().stopAll(); + jl.getDestructionManager().stop(); + } + + // Just in case that previous clean "stop"s did not work, try again an interruption for all running threads: + /* note: timers are not part of this ThreadGroup and so, they won't be affected by this function call. */ + JobThread.tg.interrupt(); + + // Log the service is stopped: + if (logger != null) + logger.logUWS(LogLevel.INFO, this, "STOP", "UWS Service \"" + getName() + "\" stopped!", null); + + // Default destroy function: + super.destroy(); + } + public UWSFileManager createFileManager() throws UWSException{ UWSFileManager fm = null; String rootPath = getServletConfig().getInitParameter("rootDirectory"); diff --git a/src/uws/service/backup/DefaultUWSBackupManager.java b/src/uws/service/backup/DefaultUWSBackupManager.java index 6b198bdc4cb4c1f3323178b9ea9fef8ceae1b679..3081bedc59c2db9ca170b4bbaad8e7c32a1b780f 100644 --- a/src/uws/service/backup/DefaultUWSBackupManager.java +++ b/src/uws/service/backup/DefaultUWSBackupManager.java @@ -401,7 +401,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { // Build the report and log it: int[] report = new int[]{nbSavedJobs,nbJobs,nbSavedOwners,nbOwners}; - getLogger().logUWS(LogLevel.INFO, report, "BACKUPED", "UWS backuped! (" + nbSavedJobs + "/" + nbJobs + " jobs backuped ; " + nbSavedOwners + "/" + nbOwners + " users backuped)", null); + getLogger().logUWS(LogLevel.INFO, report, "BACKUPED", "UWS Service \"" + uws.getName() + "\" backuped!", null); lastBackup = new Date(); @@ -465,7 +465,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { out.endObject(); // Log the "save" report: - getLogger().logUWS(LogLevel.INFO, saveReport, "BACKUPED", "UWS backuped! (" + saveReport[0] + "/" + saveReport[1] + " users backuped)", null); + getLogger().logUWS(LogLevel.INFO, saveReport, "BACKUPED", "UWS backuped!", null); lastBackup = new Date(); @@ -756,7 +756,7 @@ public class DefaultUWSBackupManager implements UWSBackupManager { // Build the restoration report and log it: int[] report = new int[]{nbRestoredJobs,nbJobs,nbRestoredUsers,nbUsers}; - getLogger().logUWS(LogLevel.INFO, report, "RESTORED", "UWS restored! (" + nbRestoredJobs + "/" + nbJobs + " jobs restored ; " + nbRestoredUsers + "/" + nbUsers + " users restored)", null); + getLogger().logUWS(LogLevel.INFO, report, "RESTORED", "UWS restored!", null); return report; } diff --git a/src/uws/service/log/DefaultUWSLog.java b/src/uws/service/log/DefaultUWSLog.java index a1ef8b70f2dd977353a558655b3ec1fe795ed523..cfaadb47430a31511e131ec141376f6ff2593e17 100644 --- a/src/uws/service/log/DefaultUWSLog.java +++ b/src/uws/service/log/DefaultUWSLog.java @@ -390,6 +390,16 @@ public class DefaultUWSLog implements UWSLog { @Override public void logUWS(LogLevel level, Object obj, String event, String message, Throwable error){ + // CASE "BACKUPED": Append to the message the backup report: + if (event != null && event.equalsIgnoreCase("BACKUPED") && obj != null && obj.getClass().getName().equals("[I")){ + int[] backupReport = (int[])obj; + message += "\t(" + backupReport[0] + "/" + backupReport[1] + " jobs backuped ; " + backupReport[2] + "/" + backupReport[3] + " users backuped)"; + }else if (event != null && event.equalsIgnoreCase("RESTORED") && obj != null && obj.getClass().getName().equals("[I")){ + int[] restoreReport = (int[])obj; + message += "\t(" + restoreReport[0] + "/" + restoreReport[1] + " jobs restored ; " + restoreReport[2] + "/" + restoreReport[3] + " users restored)"; + } + + // Log the message log(level, "UWS", event, null, message, error); } diff --git a/src/uws/service/log/UWSLog.java b/src/uws/service/log/UWSLog.java index c0771f624d0613eb8dd0fac6bbdbbe49c024b7cd..94a901b23e506c363206f5676494036cea30089d 100644 --- a/src/uws/service/log/UWSLog.java +++ b/src/uws/service/log/UWSLog.java @@ -191,6 +191,7 @@ public interface UWSLog { * <li>RESTORED (with "obj" as an integer array of 4 items: nb of restored jobs, total nb of jobs, nb of restored users, total nb of users)</li> * <li>BACKUPED (with "obj" as an integer array of 4 items: nb of saved jobs, total nb of jobs, nb of saved users, total nb of users or with just 2 items (the two last ones))</li> * <li>FORMAT_ERROR (with a NULL "obj")</li> + * <li>STOP (with "obj" as an instance of {@link UWS})</li> * </ul> * * @param level Level of the log (info, warning, error, ...). <i>SHOULD NOT be NULL, but if NULL anyway, the level SHOULD be considered as INFO</i> diff --git a/test/tap/formatter/JSONFormatTest.java b/test/tap/formatter/JSONFormatTest.java index fee9143f1473a5416cda1065c621f515a5228561..c7cb39361c02e63296eb7d583d3586183e68b7eb 100644 --- a/test/tap/formatter/JSONFormatTest.java +++ b/test/tap/formatter/JSONFormatTest.java @@ -264,6 +264,9 @@ public class JSONFormatTest { return -1; } + @Override + public void setAvailable(boolean isAvailable, String message){} + } } diff --git a/test/tap/formatter/SVFormatTest.java b/test/tap/formatter/SVFormatTest.java index d32b3dc09a662828e3b6c3a84c1035082a72c2e9..d523abfdb1c544a601b43229d4f3e34eef258e70 100644 --- a/test/tap/formatter/SVFormatTest.java +++ b/test/tap/formatter/SVFormatTest.java @@ -258,6 +258,9 @@ public class SVFormatTest { return -1; } + @Override + public void setAvailable(boolean isAvailable, String message){} + } } diff --git a/test/tap/formatter/TextFormatTest.java b/test/tap/formatter/TextFormatTest.java index 97145b23e947ea4b5c2e8fddb72fd5b0fec60cd2..d6632da5a0d245398c0cfb10723b6cdee943e4d3 100644 --- a/test/tap/formatter/TextFormatTest.java +++ b/test/tap/formatter/TextFormatTest.java @@ -258,6 +258,9 @@ public class TextFormatTest { return -1; } + @Override + public void setAvailable(boolean isAvailable, String message){} + } } diff --git a/test/tap/formatter/VOTableFormatTest.java b/test/tap/formatter/VOTableFormatTest.java index dca3751b977ae07ced1f388d74e97e9f24b03bdb..d55200a8820abcd614a482995d34788873500b7a 100644 --- a/test/tap/formatter/VOTableFormatTest.java +++ b/test/tap/formatter/VOTableFormatTest.java @@ -263,6 +263,9 @@ public class VOTableFormatTest { return -1; } + @Override + public void setAvailable(boolean isAvailable, String message){} + } } diff --git a/test/tap/parameters/ServiceConnectionOfTest.java b/test/tap/parameters/ServiceConnectionOfTest.java index 1d390ce84cf933eb737a3cb4966757a7eaf91d4d..cb0d79360556b13dadbd0ce576898ed608171e98 100644 --- a/test/tap/parameters/ServiceConnectionOfTest.java +++ b/test/tap/parameters/ServiceConnectionOfTest.java @@ -20,6 +20,8 @@ import adql.db.FunctionDef; public class ServiceConnectionOfTest implements ServiceConnection { + private boolean available = true; + private String availability = "TAP Service available!"; private int[] retentionPeriod = new int[]{-1,-1}; private int[] executionDuration = new int[]{(int)TAPJob.UNLIMITED_DURATION,(int)TAPJob.UNLIMITED_DURATION}; private int[] outputLimit = new int[]{TAPJob.UNLIMITED_MAX_REC,TAPJob.UNLIMITED_MAX_REC}; @@ -37,12 +39,21 @@ public class ServiceConnectionOfTest implements ServiceConnection { @Override public boolean isAvailable(){ - return true; + return available; + } + + @Override + public void setAvailable(boolean isAvailable, String message){ + available = isAvailable; + if (message != null) + availability = message; + else + availability = (isAvailable ? "TAP Service available!" : "TAP Service momentarily UNavailable!"); } @Override public String getAvailability(){ - return null; + return availability; } @Override