update_manager: Make Prefs Variable async.
The update_engine prefs, while stored in disk, are private daemon
values changed by the daemon only. There was a 5 minutes delay between
changing this value and the update policy checking it again, and there
was a log spam every 5 minutes due to policy re-evaluations.
This patch makes these Prefs-based variables async by implementing an
observer pattern in the PrefsInterface and makes these variables async.
Bug: chromium:367333
Test: Added uniittest. No more log spam every 5 minutes.
Change-Id: I8b3f7072cc87515972c9f5b1ddcc54b865ffe238
diff --git a/prefs.cc b/prefs.cc
index dea21e2..89da8bf 100644
--- a/prefs.cc
+++ b/prefs.cc
@@ -16,6 +16,8 @@
#include "update_engine/prefs.h"
+#include <algorithm>
+
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
@@ -32,7 +34,7 @@
return true;
}
-bool Prefs::GetString(const string& key, string* value) {
+bool Prefs::GetString(const string& key, string* value) const {
base::FilePath filename;
TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
if (!base::ReadFileToString(filename, value)) {
@@ -48,10 +50,16 @@
TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
static_cast<int>(value.size()));
+ const auto observers_for_key = observers_.find(key);
+ if (observers_for_key != observers_.end()) {
+ std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
+ for (ObserverInterface* observer : copy_observers)
+ observer->OnPrefSet(key);
+ }
return true;
}
-bool Prefs::GetInt64(const string& key, int64_t* value) {
+bool Prefs::GetInt64(const string& key, int64_t* value) const {
string str_value;
if (!GetString(key, &str_value))
return false;
@@ -64,7 +72,7 @@
return SetString(key, base::Int64ToString(value));
}
-bool Prefs::GetBoolean(const string& key, bool* value) {
+bool Prefs::GetBoolean(const string& key, bool* value) const {
string str_value;
if (!GetString(key, &str_value))
return false;
@@ -84,7 +92,7 @@
return SetString(key, value ? "true" : "false");
}
-bool Prefs::Exists(const string& key) {
+bool Prefs::Exists(const string& key) const {
base::FilePath filename;
TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
return base::PathExists(filename);
@@ -93,11 +101,30 @@
bool Prefs::Delete(const string& key) {
base::FilePath filename;
TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- return base::DeleteFile(filename, false);
+ TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+ const auto observers_for_key = observers_.find(key);
+ if (observers_for_key != observers_.end()) {
+ std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
+ for (ObserverInterface* observer : copy_observers)
+ observer->OnPrefDeleted(key);
+ }
+ return true;
+}
+
+void Prefs::AddObserver(const string& key, ObserverInterface* observer) {
+ observers_[key].push_back(observer);
+}
+
+void Prefs::RemoveObserver(const string& key, ObserverInterface* observer) {
+ std::vector<ObserverInterface*>& observers_for_key = observers_[key];
+ auto observer_it =
+ std::find(observers_for_key.begin(), observers_for_key.end(), observer);
+ if (observer_it != observers_for_key.end())
+ observers_for_key.erase(observer_it);
}
bool Prefs::GetFileNameForKey(const string& key,
- base::FilePath* filename) {
+ base::FilePath* filename) const {
// Allows only non-empty keys containing [A-Za-z0-9_-].
TEST_AND_RETURN_FALSE(!key.empty());
for (size_t i = 0; i < key.size(); ++i) {