summaryrefslogtreecommitdiff
path: root/util/background.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'util/background.cpp')
-rw-r--r--util/background.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/util/background.cpp b/util/background.cpp
index 746d14c..215b271 100644
--- a/util/background.cpp
+++ b/util/background.cpp
@@ -18,8 +18,11 @@
#include "pch.h"
#include "concurrency/mutex.h"
+#include "concurrency/spin_lock.h"
#include "background.h"
+#include "time_support.h"
+#include "timer.h"
#include "mongoutils/str.h"
@@ -80,6 +83,7 @@ namespace mongo {
}
bool BackgroundJob::wait( unsigned msTimeOut ) {
+ assert( !_status->deleteSelf ); // you cannot call wait on a self-deleting job
scoped_lock l( _status->m );
while ( _status->state != Done ) {
if ( msTimeOut ) {
@@ -117,4 +121,70 @@ namespace mongo {
return _status->state == Running;
}
+ // -------------------------
+
+ PeriodicTask::PeriodicTask() {
+ if ( ! theRunner )
+ theRunner = new Runner();
+ theRunner->add( this );
+ }
+
+ PeriodicTask::~PeriodicTask() {
+ theRunner->remove( this );
+ }
+
+ void PeriodicTask::Runner::add( PeriodicTask* task ) {
+ scoped_spinlock lk( _lock );
+ _tasks.push_back( task );
+ }
+
+ void PeriodicTask::Runner::remove( PeriodicTask* task ) {
+ scoped_spinlock lk( _lock );
+ for ( size_t i=0; i<_tasks.size(); i++ ) {
+ if ( _tasks[i] == task ) {
+ _tasks[i] = 0;
+ break;
+ }
+ }
+ }
+
+ void PeriodicTask::Runner::run() {
+ int sleeptime = 60;
+ DEV sleeptime = 5; // to catch race conditions
+
+ while ( ! inShutdown() ) {
+
+ sleepsecs( sleeptime );
+
+ scoped_spinlock lk( _lock );
+
+ size_t size = _tasks.size();
+
+ for ( size_t i=0; i<size; i++ ) {
+ PeriodicTask * t = _tasks[i];
+ if ( ! t )
+ continue;
+
+ if ( inShutdown() )
+ break;
+
+ Timer timer;
+ try {
+ t->taskDoWork();
+ }
+ catch ( std::exception& e ) {
+ error() << "task: " << t->taskName() << " failed: " << e.what() << endl;
+ }
+ catch ( ... ) {
+ error() << "task: " << t->taskName() << " failed with unknown error" << endl;
+ }
+
+ int ms = timer.millis();
+ LOG( ms <= 3 ? 1 : 0 ) << "task: " << t->taskName() << " took: " << ms << "ms" << endl;
+ }
+ }
+ }
+
+ PeriodicTask::Runner* PeriodicTask::theRunner = 0;
+
} // namespace mongo