summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrii Kalinich <AKalinich@luxoft.com>2019-10-22 13:33:27 -0400
committerAndrii Kalinich <AKalinich@luxoft.com>2019-10-22 13:33:27 -0400
commit06e58a92960d7590657df599be554bf94eda39db (patch)
tree588ecb4a0c7fb0db135d50bdf704dc17131f6845
parentb67c088ea29cd0d7b29f4809a7964b11af80745e (diff)
downloadsdl_core-06e58a92960d7590657df599be554bf94eda39db.tar.gz
Synchronize backup and reset policy functions
This is an issue specific for EXTERNAL_PROPRIETARY flow only. This issue is exposed by PolicyHandlerTest unit test: ResetPolicyTable_WithPreloadedFile_ExpectPolicyTableReset which sometimes is failing. The main problem was that database reset(drop) and backup can be done simultaneously in different threads which were not synchronized. In that case, database drop often may be failed because another thread is trying to write something into the DB table which is going to be dropped. This causes above unit test to fail sometimes. To make that unit test and policy component more stable, these two threads were synchronized by additing a waiting function, so one thread will be able to wait for another thread to finish its own staff.
-rw-r--r--src/components/policy/policy_external/include/policy/cache_manager.h17
-rw-r--r--src/components/policy/policy_external/src/cache_manager.cc25
2 files changed, 42 insertions, 0 deletions
diff --git a/src/components/policy/policy_external/include/policy/cache_manager.h b/src/components/policy/policy_external/include/policy/cache_manager.h
index acc7a7da51..5873d31781 100644
--- a/src/components/policy/policy_external/include/policy/cache_manager.h
+++ b/src/components/policy/policy_external/include/policy/cache_manager.h
@@ -33,6 +33,7 @@
#ifndef SRC_COMPONENTS_POLICY_POLICY_EXTERNAL_INCLUDE_POLICY_CACHE_MANAGER_H_
#define SRC_COMPONENTS_POLICY_POLICY_EXTERNAL_INCLUDE_POLICY_CACHE_MANAGER_H_
+#include <atomic>
#include <map>
#include "boost/optional.hpp"
@@ -1107,12 +1108,28 @@ class CacheManager : public CacheManagerInterface {
~BackgroundBackuper();
virtual void threadMain();
virtual void exitThreadMain();
+
+ /**
+ * @brief Notifies BackgroundBackuper thread that new data is available and
+ * new backup iteration should be scheduled
+ */
void DoBackup();
+ /**
+ * @brief Waits for BackgroundBackuper thread finish its own backup
+ * iteration. If currently no backup iteration in progress - function just
+ * returns the control back
+ */
+ void WaitForBackupIsDone();
+
private:
void InternalBackup();
CacheManager* cache_manager_;
sync_primitives::ConditionalVariable backup_notifier_;
+ sync_primitives::ConditionalVariable backup_done_;
+ sync_primitives::Lock backup_done_lock_;
+
+ std::atomic_bool backup_is_in_progress_;
volatile bool stop_flag_;
volatile bool new_data_available_;
diff --git a/src/components/policy/policy_external/src/cache_manager.cc b/src/components/policy/policy_external/src/cache_manager.cc
index 3e1538ab04..1c5b5bff6c 100644
--- a/src/components/policy/policy_external/src/cache_manager.cc
+++ b/src/components/policy/policy_external/src/cache_manager.cc
@@ -2682,10 +2682,14 @@ bool CacheManager::LoadFromFile(const std::string& file_name,
bool CacheManager::ResetPT(const std::string& file_name) {
LOG4CXX_AUTO_TRACE(logger_);
is_unpaired_.clear();
+
+ backuper_->WaitForBackupIsDone();
+
if (!backup_->RefreshDB()) {
LOG4CXX_ERROR(logger_, "Can't re-create policy database. Reset failed.");
return false;
}
+
sync_primitives::AutoLock lock(cache_lock_);
pt_.reset(new policy_table::Table());
const bool result = LoadFromFile(file_name, *pt_);
@@ -3097,6 +3101,7 @@ void CacheManager::OnDeviceSwitching(const std::string& device_id_from,
CacheManager::BackgroundBackuper::BackgroundBackuper(
CacheManager* cache_manager)
: cache_manager_(cache_manager)
+ , backup_is_in_progress_(false)
, stop_flag_(false)
, new_data_available_(false) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -3121,13 +3126,23 @@ void CacheManager::BackgroundBackuper::threadMain() {
LOG4CXX_AUTO_TRACE(logger_);
sync_primitives::AutoLock lock(need_backup_lock_);
while (!stop_flag_) {
+ backup_is_in_progress_.exchange(true);
{
sync_primitives::AutoUnlock need_backup_lock(need_backup_lock_);
InternalBackup();
}
+
if (new_data_available_ || stop_flag_) {
continue;
}
+
+ {
+ LOG4CXX_DEBUG(logger_, "Backup is done");
+ sync_primitives::AutoLock auto_lock(backup_done_lock_);
+ backup_is_in_progress_.exchange(false);
+ backup_done_.Broadcast();
+ }
+
LOG4CXX_DEBUG(logger_, "Wait for a next backup");
backup_notifier_.Wait(need_backup_lock_);
}
@@ -3147,6 +3162,16 @@ void CacheManager::BackgroundBackuper::DoBackup() {
backup_notifier_.NotifyOne();
}
+void CacheManager::BackgroundBackuper::WaitForBackupIsDone() {
+ LOG4CXX_AUTO_TRACE(logger_);
+ sync_primitives::AutoLock auto_lock(backup_done_lock_);
+ if (!backup_is_in_progress_) {
+ return;
+ }
+
+ backup_done_.Wait(auto_lock);
+}
+
EncryptionRequired CacheManager::GetAppEncryptionRequiredFlag(
const std::string& application) const {
LOG4CXX_AUTO_TRACE(logger_);