diff --git a/include/api/CBackgroundPersister.h b/include/api/CBackgroundPersister.h index c5d910a8ed..fa4fc3bda0 100644 --- a/include/api/CBackgroundPersister.h +++ b/include/api/CBackgroundPersister.h @@ -38,6 +38,13 @@ namespace api //! are that a lot of memory is being used by the temporary //! copy of the data to be persisted. //! +//! Persistence happens in a background thread and further +//! persistence requests via the startBackgroundPersist*() methods +//! will be rejected if the background thread is executing. +//! However, calls to startBackgroundPersist() and +//! startBackgroundPersistIfAppropriate() are not thread safe and +//! must not be made concurrently. +//! //! IMPLEMENTATION DECISIONS:\n //! This class expects to call a persistence function taking //! just the data adder as an argument. It's easy to wrap up @@ -98,9 +105,15 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable //! called. bool firstProcessorPeriodicPersistFunc(const TFirstProcessorPeriodicPersistFunc &firstProcessorPeriodicPersistFunc); - //! Check whether a background persist is appropriate now, and if it is - //! then start it by calling the first processor periodic persist - //! function. + //! Start a background persist is one is not running. + //! Calls the first processor periodic persist function first. + //! Concurrent calls to this method are not threadsafe. + bool startBackgroundPersist(void); + + //! If the periodic persist interval has passed since the last persist + //! then it is appropriate to persist now. Start it by calling the + //! first processor periodic persist function. + //! Concurrent calls to this method are not threadsafe. bool startBackgroundPersistIfAppropriate(void); private: @@ -121,6 +134,10 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable }; private: + //! Persist in the background setting the last persist time + //! to timeOfPersistence + bool startBackgroundPersist(core_t::TTime timeOfPersistence); + //! When this function is called a background persistence will be //! triggered unless there is already one in progress. bool startPersist(void); diff --git a/lib/api/CAnomalyJob.cc b/lib/api/CAnomalyJob.cc index a636ab0e2d..847a878903 100644 --- a/lib/api/CAnomalyJob.cc +++ b/lib/api/CAnomalyJob.cc @@ -388,6 +388,14 @@ bool CAnomalyJob::handleControlMessage(const std::string &controlMessage) case 'p': this->doForecast(controlMessage); break; + case 'w': + { + if (m_PeriodicPersister != nullptr) + { + m_PeriodicPersister->startBackgroundPersist(); + } + } + break; default: LOG_WARN("Ignoring unknown control message of length " << controlMessage.length() << " beginning with '" << diff --git a/lib/api/CBackgroundPersister.cc b/lib/api/CBackgroundPersister.cc index 5ea1ac00fd..8a4788c14e 100644 --- a/lib/api/CBackgroundPersister.cc +++ b/lib/api/CBackgroundPersister.cc @@ -169,6 +169,17 @@ bool CBackgroundPersister::firstProcessorPeriodicPersistFunc(const TFirstProcess return true; } +bool CBackgroundPersister::startBackgroundPersist(void) +{ + if (this->isBusy()) + { + LOG_WARN("Cannot start background persist as a previous " + "persist is still in progress"); + return false; + } + return this->startBackgroundPersist(core::CTimeUtils::now()); +} + bool CBackgroundPersister::startBackgroundPersistIfAppropriate(void) { core_t::TTime due(m_LastPeriodicPersistTime + m_PeriodicPersistInterval); @@ -192,6 +203,11 @@ bool CBackgroundPersister::startBackgroundPersistIfAppropriate(void) return false; } + return this->startBackgroundPersist(now); +} + +bool CBackgroundPersister::startBackgroundPersist(core_t::TTime timeOfPersistence) +{ bool backgroundPersistSetupOk = m_FirstProcessorPeriodicPersistFunc(*this); if (!backgroundPersistSetupOk) { @@ -202,7 +218,7 @@ bool CBackgroundPersister::startBackgroundPersistIfAppropriate(void) return false; } - m_LastPeriodicPersistTime = now; + m_LastPeriodicPersistTime = timeOfPersistence; LOG_INFO("Background persist starting background thread");