Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/prefs/leveldb_pref_store.h" | |
| 6 | |
| 7 #include <algorithm> | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
| |
| 8 #include <set> | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
| |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/callback.h" | |
| 12 #include "base/file_util.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
dgrogan
2014/02/25 03:32:08
Needed, but the rest were not.
| |
| 13 #include "base/json/json_file_value_serializer.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
| |
| 14 #include "base/json/json_string_value_serializer.h" | |
| 15 #include "base/location.h" | |
| 16 #include "base/memory/ref_counted.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
| |
| 17 #include "base/message_loop/message_loop_proxy.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
Unused?
| |
| 18 #include "base/prefs/pref_filter.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
| |
| 19 #include "base/sequenced_task_runner.h" | |
| 20 #include "base/threading/sequenced_worker_pool.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
unused?
| |
| 21 #include "base/values.h" | |
| 22 #include "third_party/leveldatabase/src/include/leveldb/db.h" | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
Also in .h, but that might be able to use a forwar
| |
| 23 | |
| 24 LevelDBPrefStore::LevelDBPrefStore( | |
| 25 const base::FilePath& filename, | |
| 26 base::SequencedTaskRunner* sequenced_task_runner) | |
| 27 : path_(filename), | |
| 28 sequenced_task_runner_(sequenced_task_runner), | |
| 29 read_only_(false), | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
What's the use case for this?
| |
| 30 initialized_(false), | |
| 31 read_error_(PREF_READ_ERROR_OTHER) {} | |
| 32 | |
| 33 bool LevelDBPrefStore::GetValue(const std::string& key, | |
| 34 const base::Value** result) const { | |
| 35 const base::Value* tmp = NULL; | |
| 36 if (!prefs_.GetValue(key, &tmp)) { | |
| 37 return false; | |
| 38 } | |
| 39 | |
| 40 if (result) | |
| 41 *result = tmp; | |
| 42 return true; | |
| 43 } | |
| 44 | |
| 45 // Callers of GetMutableValue have to call ReportValueChanged in order for the | |
| 46 // new value to be persisted. | |
| 47 bool LevelDBPrefStore::GetMutableValue(const std::string& key, | |
| 48 base::Value** result) { | |
| 49 return prefs_.GetValue(key, result); | |
| 50 } | |
| 51 | |
| 52 void LevelDBPrefStore::AddObserver(PrefStore::Observer* observer) { | |
| 53 observers_.AddObserver(observer); | |
| 54 } | |
| 55 | |
| 56 void LevelDBPrefStore::RemoveObserver(PrefStore::Observer* observer) { | |
| 57 observers_.RemoveObserver(observer); | |
| 58 } | |
| 59 | |
| 60 bool LevelDBPrefStore::HasObservers() const { | |
| 61 return observers_.might_have_observers(); | |
| 62 } | |
| 63 | |
| 64 bool LevelDBPrefStore::IsInitializationComplete() const { return initialized_; } | |
| 65 | |
| 66 void LevelDBPrefStore::PersistOnFileThread(const std::string& key, | |
| 67 const std::string& value) { | |
| 68 DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); | |
| 69 | |
| 70 leveldb::Status status = db_->Put(leveldb::WriteOptions(), key, value); | |
| 71 DCHECK(status.ok()); | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
Is this OK? What kind of errors can happen here? E
dgrogan
2014/02/25 03:32:08
The corresponding error in JSONPrefStore is ignore
| |
| 72 } | |
| 73 | |
| 74 void LevelDBPrefStore::PersistFromUIThread(const std::string& key, | |
| 75 base::Value* value) { | |
| 76 if (read_only_) | |
| 77 return; | |
| 78 std::string value_string; | |
| 79 JSONStringValueSerializer serializer(&value_string); | |
| 80 DCHECK(serializer.Serialize(*value)); | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
Please no production code in DCHECK, it won't get
dgrogan
2014/02/25 03:32:08
Done.
| |
| 81 | |
| 82 sequenced_task_runner_->PostTask( | |
| 83 FROM_HERE, | |
| 84 base::Bind( | |
| 85 &LevelDBPrefStore::PersistOnFileThread, this, key, value_string)); | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
How do you make sure |this| is still alive when Pe
dgrogan
2014/02/25 03:32:08
If I'm reading https://code.google.com/p/chromium/
Mattias Nissler (ping if slow)
2014/02/25 10:51:44
Note that PrefStore inherits from base::RefCounted
dgrogan
2014/02/26 07:10:47
Wouldn't this just move the problem to the interna
Mattias Nissler (ping if slow)
2014/02/26 08:35:00
The difference is that you can destroy that object
| |
| 86 } | |
| 87 | |
| 88 void LevelDBPrefStore::SetValue(const std::string& key, base::Value* value) { | |
| 89 DCHECK(value); | |
| 90 scoped_ptr<base::Value> new_value(value); | |
| 91 base::Value* old_value = NULL; | |
| 92 bool found = prefs_.GetValue(key, &old_value); | |
| 93 if (!found || !value->Equals(old_value)) { | |
| 94 PersistFromUIThread(key, new_value.get()); | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
JSONPrefStore batches writes and hits the file onl
dgrogan
2014/02/25 03:32:08
LevelDB does not do this internally. I thought one
Mattias Nissler (ping if slow)
2014/02/25 10:51:44
OK, are you planning to run performance tests on t
dgrogan
2014/03/05 03:06:57
Yes. Note that I don't yet know how, but it's on m
| |
| 95 prefs_.SetValue(key, new_value.release()); | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 void LevelDBPrefStore::SetValueSilently(const std::string& key, | |
| 100 base::Value* value) { | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
implement?
| |
| 101 } | |
| 102 | |
| 103 void LevelDBPrefStore::RemoveValue(const std::string& key) { | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
implement?
| |
| 104 } | |
| 105 | |
| 106 bool LevelDBPrefStore::ReadOnly() const { return read_only_; } | |
| 107 | |
| 108 PersistentPrefStore::PrefReadError LevelDBPrefStore::GetReadError() const { | |
| 109 return read_error_; | |
| 110 } | |
| 111 | |
| 112 PersistentPrefStore::PrefReadError LevelDBPrefStore::ReadPrefs() { | |
| 113 DCHECK(!db_); | |
| 114 if (path_.empty()) { | |
| 115 OnStorageRead(PREF_READ_ERROR_FILE_NOT_SPECIFIED, false); | |
| 116 return PREF_READ_ERROR_FILE_NOT_SPECIFIED; | |
| 117 } | |
| 118 | |
| 119 bool no_dir = !base::PathExists(path_.DirName()); | |
| 120 | |
| 121 leveldb::DB* db; | |
| 122 leveldb::Options options; | |
| 123 options.create_if_missing = true; | |
| 124 leveldb::Status status = | |
| 125 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); | |
| 126 if (!status.ok()) { | |
| 127 // TODO(dgrogan): Add error histogram and call RepairDB. | |
| 128 OnStorageRead(PREF_READ_ERROR_FILE_OTHER, no_dir); | |
| 129 return PREF_READ_ERROR_FILE_OTHER; | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
Is it possible to get some more information about
dgrogan
2014/03/05 03:06:57
Done.
| |
| 130 } | |
| 131 db_.reset(db); | |
| 132 | |
| 133 scoped_ptr<leveldb::Iterator> it(db->NewIterator(leveldb::ReadOptions())); | |
| 134 for (it->SeekToFirst(); it->Valid(); it->Next()) { | |
| 135 const std::string value_string = it->value().ToString(); | |
| 136 JSONStringValueSerializer deserializer(value_string); | |
| 137 std::string error_message; | |
| 138 int error_code; | |
| 139 base::Value* json_value = | |
| 140 deserializer.Deserialize(&error_code, &error_message); | |
| 141 DCHECK(json_value) << error_message; | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
This should probably not be a DCHECK (unless level
dgrogan
2014/02/25 03:32:08
Done.
| |
| 142 prefs_.SetValue(it->key().ToString(), json_value); | |
| 143 } | |
| 144 | |
| 145 PersistentPrefStore::PrefReadError error = PREF_READ_ERROR_NONE; | |
| 146 if (!it->status().ok()) { | |
| 147 // TODO(dgrogan): Add error histogram? | |
| 148 error = PREF_READ_ERROR_FILE_OTHER; | |
| 149 } | |
| 150 OnStorageRead(error, no_dir); | |
| 151 return error; | |
| 152 } | |
| 153 | |
| 154 void LevelDBPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) { | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
implement?
| |
| 155 } | |
| 156 | |
| 157 void LevelDBPrefStore::CommitPendingWrite() { | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
If this is not needed, please add a comment explai
dgrogan
2014/02/25 03:32:08
Done.
| |
| 158 } | |
| 159 | |
| 160 void LevelDBPrefStore::ReportValueChanged(const std::string& key) { | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
implement?
| |
| 161 } | |
| 162 | |
| 163 void LevelDBPrefStore::OnStorageRead(PersistentPrefStore::PrefReadError error, | |
| 164 bool no_dir) { | |
|
Mattias Nissler (ping if slow)
2014/02/24 09:00:40
implement?
| |
| 165 } | |
| 166 | |
| 167 LevelDBPrefStore::~LevelDBPrefStore() {} | |
| OLD | NEW |