Commit 5111f73da157233df0c8ed17ec89b666aef8f30f

Authored by Wiebe Cazemier
1 parent cd429cb7

Reduce blocking of threads when saving state

mainapp.cpp
@@ -210,7 +210,7 @@ MainApp::MainApp(const std::string &configFilePath) : @@ -210,7 +210,7 @@ MainApp::MainApp(const std::string &configFilePath) :
210 subscriptionStore->loadSessionsAndSubscriptions(settings->getSessionsDBFile()); 210 subscriptionStore->loadSessionsAndSubscriptions(settings->getSessionsDBFile());
211 } 211 }
212 212
213 - auto fSaveState = std::bind(&MainApp::saveState, this); 213 + auto fSaveState = std::bind(&MainApp::saveStateInThread, this);
214 timer.addCallback(fSaveState, 900000, "Save state."); 214 timer.addCallback(fSaveState, 900000, "Save state.");
215 } 215 }
216 216
@@ -355,8 +355,31 @@ void MainApp::queuePublishStatsOnDollarTopic() @@ -355,8 +355,31 @@ void MainApp::queuePublishStatsOnDollarTopic()
355 } 355 }
356 } 356 }
357 357
  358 +/**
  359 + * @brief MainApp::saveStateInThread starts a thread for disk IO, because file IO is not async.
  360 + */
  361 +void MainApp::saveStateInThread()
  362 +{
  363 + // Prevent queueing it again when it's still running.
  364 + std::unique_lock<std::mutex> locker(saveStateMutex, std::try_to_lock);
  365 + if (!locker.owns_lock())
  366 + return;
  367 +
  368 + // Join previous instances.
  369 + if (saveStateThread.joinable())
  370 + saveStateThread.join();
  371 +
  372 + auto f = std::bind(&MainApp::saveState, this);
  373 + saveStateThread = std::thread(f);
  374 +
  375 + pthread_t native = saveStateThread.native_handle();
  376 + pthread_setname_np(native, "SaveState");
  377 +}
  378 +
358 void MainApp::saveState() 379 void MainApp::saveState()
359 { 380 {
  381 + std::lock_guard<std::mutex> lg(saveStateMutex);
  382 +
360 try 383 try
361 { 384 {
362 if (!settings->storageDir.empty()) 385 if (!settings->storageDir.empty())
@@ -366,6 +389,8 @@ void MainApp::saveState() @@ -366,6 +389,8 @@ void MainApp::saveState()
366 389
367 const std::string sessionsDBPath = settings->getSessionsDBFile(); 390 const std::string sessionsDBPath = settings->getSessionsDBFile();
368 subscriptionStore->saveSessionsAndSubscriptions(sessionsDBPath); 391 subscriptionStore->saveSessionsAndSubscriptions(sessionsDBPath);
  392 +
  393 + logger->logf(LOG_INFO, "Saving states done");
369 } 394 }
370 } 395 }
371 catch(std::exception &ex) 396 catch(std::exception &ex)
@@ -669,6 +694,9 @@ void MainApp::start() @@ -669,6 +694,9 @@ void MainApp::start()
669 } 694 }
670 695
671 saveState(); 696 saveState();
  697 +
  698 + if (saveStateThread.joinable())
  699 + saveStateThread.join();
672 } 700 }
673 701
674 void MainApp::quit() 702 void MainApp::quit()
mainapp.h
@@ -71,6 +71,9 @@ class MainApp @@ -71,6 +71,9 @@ class MainApp
71 71
72 Logger *logger = Logger::getInstance(); 72 Logger *logger = Logger::getInstance();
73 73
  74 + std::thread saveStateThread;
  75 + std::mutex saveStateMutex;
  76 +
74 void setlimits(); 77 void setlimits();
75 void loadConfig(); 78 void loadConfig();
76 void reloadConfig(); 79 void reloadConfig();
@@ -84,6 +87,7 @@ class MainApp @@ -84,6 +87,7 @@ class MainApp
84 void setFuzzFile(const std::string &fuzzFilePath); 87 void setFuzzFile(const std::string &fuzzFilePath);
85 void queuePublishStatsOnDollarTopic(); 88 void queuePublishStatsOnDollarTopic();
86 void saveState(); 89 void saveState();
  90 + void saveStateInThread();
87 91
88 MainApp(const std::string &configFilePath); 92 MainApp(const std::string &configFilePath);
89 public: 93 public:
subscriptionstore.cpp
@@ -634,7 +634,7 @@ void SubscriptionStore::saveSessionsAndSubscriptions(const std::string &amp;filePath @@ -634,7 +634,7 @@ void SubscriptionStore::saveSessionsAndSubscriptions(const std::string &amp;filePath
634 logger->logf(LOG_INFO, "Saving sessions and subscriptions to '%s'", filePath.c_str()); 634 logger->logf(LOG_INFO, "Saving sessions and subscriptions to '%s'", filePath.c_str());
635 635
636 RWLockGuard lock_guard(&subscriptionsRwlock); 636 RWLockGuard lock_guard(&subscriptionsRwlock);
637 - lock_guard.wrlock(); 637 + lock_guard.rdlock();
638 638
639 // First copy the sessions... 639 // First copy the sessions...
640 640