Implement a memory-based Prefs class.
When the /data storage is not available, we need to store the required
prefs in memory to keep all the code working. This patch splits the
Prefs class functionality and implements a MemoryPrefs class which
stores all the values in memory.
Bug: 27178350
TEST=Added unittest for the MemoryPrefs.
Change-Id: I11f871ddb73e2f33db4101705efb293e1cbe0023
diff --git a/common/prefs.cc b/common/prefs.cc
index a4b97d0..12d06c0 100644
--- a/common/prefs.cc
+++ b/common/prefs.cc
@@ -29,31 +29,12 @@
namespace chromeos_update_engine {
-bool Prefs::Init(const base::FilePath& prefs_dir) {
- prefs_dir_ = prefs_dir;
- return true;
+bool PrefsBase::GetString(const string& key, string* value) const {
+ return storage_->GetKey(key, 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)) {
- LOG(INFO) << key << " not present in " << prefs_dir_.value();
- return false;
- }
- return true;
-}
-
-bool Prefs::SetString(const string& key, const string& value) {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- if (!base::DirectoryExists(filename.DirName())) {
- // Only attempt to create the directory if it doesn't exist to avoid calls
- // to parent directories where we might not have permission to write to.
- TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
- }
- TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
- static_cast<int>(value.size()));
+bool PrefsBase::SetString(const string& key, const string& value) {
+ TEST_AND_RETURN_FALSE(storage_->SetKey(key, value));
const auto observers_for_key = observers_.find(key);
if (observers_for_key != observers_.end()) {
std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
@@ -63,7 +44,7 @@
return true;
}
-bool Prefs::GetInt64(const string& key, int64_t* value) const {
+bool PrefsBase::GetInt64(const string& key, int64_t* value) const {
string str_value;
if (!GetString(key, &str_value))
return false;
@@ -72,11 +53,11 @@
return true;
}
-bool Prefs::SetInt64(const string& key, const int64_t value) {
+bool PrefsBase::SetInt64(const string& key, const int64_t value) {
return SetString(key, base::Int64ToString(value));
}
-bool Prefs::GetBoolean(const string& key, bool* value) const {
+bool PrefsBase::GetBoolean(const string& key, bool* value) const {
string str_value;
if (!GetString(key, &str_value))
return false;
@@ -92,20 +73,16 @@
return false;
}
-bool Prefs::SetBoolean(const string& key, const bool value) {
+bool PrefsBase::SetBoolean(const string& key, const bool value) {
return SetString(key, value ? "true" : "false");
}
-bool Prefs::Exists(const string& key) const {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- return base::PathExists(filename);
+bool PrefsBase::Exists(const string& key) const {
+ return storage_->KeyExists(key);
}
-bool Prefs::Delete(const string& key) {
- base::FilePath filename;
- TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
- TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+bool PrefsBase::Delete(const string& key) {
+ TEST_AND_RETURN_FALSE(storage_->DeleteKey(key));
const auto observers_for_key = observers_.find(key);
if (observers_for_key != observers_.end()) {
std::vector<ObserverInterface*> copy_observers(observers_for_key->second);
@@ -115,11 +92,11 @@
return true;
}
-void Prefs::AddObserver(const string& key, ObserverInterface* observer) {
+void PrefsBase::AddObserver(const string& key, ObserverInterface* observer) {
observers_[key].push_back(observer);
}
-void Prefs::RemoveObserver(const string& key, ObserverInterface* observer) {
+void PrefsBase::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);
@@ -127,8 +104,55 @@
observers_for_key.erase(observer_it);
}
-bool Prefs::GetFileNameForKey(const string& key,
- base::FilePath* filename) const {
+// Prefs
+
+bool Prefs::Init(const base::FilePath& prefs_dir) {
+ return file_storage_.Init(prefs_dir);
+}
+
+bool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) {
+ prefs_dir_ = prefs_dir;
+ return true;
+}
+
+bool Prefs::FileStorage::GetKey(const string& key, string* value) const {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ if (!base::ReadFileToString(filename, value)) {
+ LOG(INFO) << key << " not present in " << prefs_dir_.value();
+ return false;
+ }
+ return true;
+}
+
+bool Prefs::FileStorage::SetKey(const string& key, const string& value) {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ if (!base::DirectoryExists(filename.DirName())) {
+ // Only attempt to create the directory if it doesn't exist to avoid calls
+ // to parent directories where we might not have permission to write to.
+ TEST_AND_RETURN_FALSE(base::CreateDirectory(filename.DirName()));
+ }
+ TEST_AND_RETURN_FALSE(base::WriteFile(filename, value.data(), value.size()) ==
+ static_cast<int>(value.size()));
+ return true;
+}
+
+bool Prefs::FileStorage::KeyExists(const string& key) const {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ return base::PathExists(filename);
+}
+
+bool Prefs::FileStorage::DeleteKey(const string& key) {
+ base::FilePath filename;
+ TEST_AND_RETURN_FALSE(GetFileNameForKey(key, &filename));
+ TEST_AND_RETURN_FALSE(base::DeleteFile(filename, false));
+ return true;
+}
+
+bool Prefs::FileStorage::GetFileNameForKey(const string& key,
+ 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) {
@@ -140,4 +164,33 @@
return true;
}
+// MemoryPrefs
+
+bool MemoryPrefs::MemoryStorage::GetKey(const string& key,
+ string* value) const {
+ auto it = values_.find(key);
+ if (it == values_.end())
+ return false;
+ *value = it->second;
+ return true;
+}
+
+bool MemoryPrefs::MemoryStorage::SetKey(const string& key,
+ const string& value) {
+ values_[key] = value;
+ return true;
+}
+
+bool MemoryPrefs::MemoryStorage::KeyExists(const string& key) const {
+ return values_.find(key) != values_.end();
+}
+
+bool MemoryPrefs::MemoryStorage::DeleteKey(const string& key) {
+ auto it = values_.find(key);
+ if (it == values_.end())
+ return false;
+ values_.erase(it);
+ return true;
+}
+
} // namespace chromeos_update_engine