Commit 6c6d959a authored by Nick Draper's avatar Nick Draper
Browse files

Add a 5 second delay after completion of the algorithm before deletion

This is all handled through a isReadyForGarbageCollection() method on Algorithm.
This can be overloaded in specific algorithms if needed.
parent 146181c5
......@@ -11,6 +11,7 @@
#include "MantidAPI/DllConfig.h"
#include "MantidAPI/IAlgorithm.h"
#include "MantidAPI/IndexTypeProperty.h"
#include "MantidKernel/DateAndTime.h"
#include "MantidKernel/IValidator.h"
#include "MantidKernel/PropertyManagerOwner.h"
......@@ -226,6 +227,7 @@ public:
bool isInitialized() const override;
bool isExecuted() const override;
bool isRunning() const override;
bool isReadyForGarbageCollection() const override;
using Kernel::PropertyManagerOwner::getProperty;
......@@ -504,6 +506,9 @@ private:
/// (MPI) communicator used when executing the algorithm.
std::unique_ptr<Parallel::Communicator> m_communicator;
/// The earliest this class should be considered for garbage collection
Mantid::Types::Core::DateAndTime m_gcTime;
};
/// Typedef for a shared pointer to an Algorithm
......
......@@ -132,6 +132,9 @@ public:
/// True if the algorithm is running.
virtual bool isRunning() const = 0;
/// True if the algorithm is ready for garbage collection.
virtual bool isReadyForGarbageCollection() const = 0;
/// To query whether algorithm is a child. Default to false
virtual bool isChild() const = 0;
......
......@@ -16,7 +16,6 @@
#include "MantidKernel/CompositeValidator.h"
#include "MantidKernel/ConfigService.h"
#include "MantidKernel/DateAndTime.h"
#include "MantidKernel/EmptyValues.h"
#include "MantidKernel/MultiThreaded.h"
#include "MantidKernel/PropertyWithValue.h"
......@@ -51,6 +50,10 @@ namespace {
/// Separator for workspace types in workspaceMethodOnTypes member
const std::string WORKSPACE_TYPES_SEPARATOR = ";";
/// The minimum number of seconds after execution that the algorithm should be kept alive
/// before garbage collection
const size_t DELAY_BEFORE_GC = 5;
class WorkspacePropertyValueIs {
public:
explicit WorkspacePropertyValueIs(const std::string &value)
......@@ -108,7 +111,7 @@ Algorithm::Algorithm()
m_communicator(std::make_unique<Parallel::Communicator>()) {}
/// Virtual destructor
Algorithm::~Algorithm() {}
Algorithm::~Algorithm() {}
//=============================================================================================
//================================== Simple Getters/Setters
......@@ -196,6 +199,15 @@ bool Algorithm::isRunning() const {
return (executionState() == ExecutionState::Running);
}
/// True if the algorithm is ready for garbage collection.
bool Algorithm::isReadyForGarbageCollection() const {
if ((executionState() == ExecutionState::Finished) &&
(Mantid::Types::Core::DateAndTime::getCurrentTime() > m_gcTime)) {
return true;
}
return false;
}
//---------------------------------------------------------------------------------------------
/** Add an observer to a notification
@param observer :: Reference to the observer to add
......@@ -671,10 +683,12 @@ bool Algorithm::executeInternal() {
" seconds\n");
reportCompleted(duration);
} catch (std::runtime_error &ex) {
m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
(Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
setResultState(ResultState::Failed);
notificationCenter().postNotification(
new ErrorNotification(this, ex.what()));
this->unlockWorkspaces();
setResultState(ResultState::Failed);
if (m_isChildAlgorithm || m_runningAsync || m_rethrow)
throw;
else {
......@@ -686,8 +700,10 @@ bool Algorithm::executeInternal() {
} catch (std::logic_error &ex) {
notificationCenter().postNotification(
new ErrorNotification(this, ex.what()));
this->unlockWorkspaces();
setResultState(ResultState::Failed);
this->unlockWorkspaces();
m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
(Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
if (m_isChildAlgorithm || m_runningAsync || m_rethrow)
throw;
else {
......@@ -698,15 +714,20 @@ bool Algorithm::executeInternal() {
}
} catch (CancelException &ex) {
m_runningAsync = false;
m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
(Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
setResultState(ResultState::Failed);
getLogger().warning() << this->name() << ": Execution cancelled by user.\n";
notificationCenter().postNotification(
new ErrorNotification(this, ex.what()));
this->unlockWorkspaces();
setResultState(ResultState::Failed);
throw;
}
// Gaudi also specifically catches GaudiException & std:exception.
catch (std::exception &ex) {
m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
(Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
setResultState(ResultState::Failed);
m_runningAsync = false;
......@@ -723,22 +744,26 @@ bool Algorithm::executeInternal() {
// Execution failed with an unknown exception object
m_runningAsync = false;
m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
(Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
setResultState(ResultState::Failed);
notificationCenter().postNotification(
new ErrorNotification(this, "UNKNOWN Exception is caught in exec()"));
getLogger().error() << this->name()
<< ": UNKNOWN Exception is caught in exec()\n";
this->unlockWorkspaces();
setResultState(ResultState::Failed);
throw;
}
// Unlock the locked workspaces
this->unlockWorkspaces();
// Only gets to here if algorithm ended normally
notificationCenter().postNotification(
new FinishedNotification(this, true));
m_gcTime = Mantid::Types::Core::DateAndTime::getCurrentTime() +=
(Mantid::Types::Core::DateAndTime::ONE_SECOND * DELAY_BEFORE_GC);
setResultState(ResultState::Success);
// Only gets to here if algorithm ended normally
notificationCenter().postNotification(new FinishedNotification(this, true));
return true;
}
......
......@@ -193,7 +193,7 @@ size_t AlgorithmManagerImpl::removeFinishedAlgorithms() {
std::copy_if(
m_managed_algs.cbegin(), m_managed_algs.cend(),
std::back_inserter(theCompletedInstances), [](const auto &algorithm) {
return (algorithm->executionState() == ExecutionState::Finished);
return (algorithm->isReadyForGarbageCollection());
});
for (auto completedAlg : theCompletedInstances) {
auto itend = m_managed_algs.end();
......
......@@ -1083,6 +1083,7 @@ add_subdirectory(test)
# Auto-generate exports header
target_include_directories(Algorithms PUBLIC ${CMAKE_BINARY_DIR}/Framework/Algorithms)
target_include_directories(Algorithms PUBLIC ${CMAKE_BINARY_DIR}/Framework/Types)
generate_mantid_export_header(Algorithms FALSE)
# Installation settings
......
......@@ -24,6 +24,8 @@ if(CXXTEST_FOUND)
set_target_properties(${_pythoninterface_test_target_name}
PROPERTIES COMPILE_FLAGS "/w44244")
endif()
target_include_directories(${_pythoninterface_test_target_name} PUBLIC ${CMAKE_BINARY_DIR}/Framework/Types)
target_link_libraries(${_pythoninterface_test_target_name}
LINK_PRIVATE
${TCMALLOC_LIBRARIES_LINKTIME}
......
......@@ -4,6 +4,7 @@ if(CXXTEST_FOUND)
)
cxxtest_add_test(RemoteAlgorithmsTest ${TEST_FILES})
target_include_directories(RemoteAlgorithmsTest PUBLIC ${CMAKE_BINARY_DIR}/Framework/Types)
target_link_libraries(RemoteAlgorithmsTest
LINK_PRIVATE
${TCMALLOC_LIBRARIES_LINKTIME}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment