OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/browser/value_store/leveldb_value_store.h" | 5 #include "extensions/browser/value_store/leveldb_value_store.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 leveldb::DB* db_; | 41 leveldb::DB* db_; |
42 const leveldb::Snapshot* snapshot_; | 42 const leveldb::Snapshot* snapshot_; |
43 | 43 |
44 DISALLOW_COPY_AND_ASSIGN(ScopedSnapshot); | 44 DISALLOW_COPY_AND_ASSIGN(ScopedSnapshot); |
45 }; | 45 }; |
46 | 46 |
47 } // namespace | 47 } // namespace |
48 | 48 |
49 LeveldbValueStore::LeveldbValueStore(const base::FilePath& db_path) | 49 LeveldbValueStore::LeveldbValueStore(const base::FilePath& db_path) |
50 : db_path_(db_path) { | 50 : db_path_(db_path) { |
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 51 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
52 | 52 |
53 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 53 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
54 if (open_error) | 54 if (open_error) |
55 LOG(WARNING) << open_error->message; | 55 LOG(WARNING) << open_error->message; |
56 } | 56 } |
57 | 57 |
58 LeveldbValueStore::~LeveldbValueStore() { | 58 LeveldbValueStore::~LeveldbValueStore() { |
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 59 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
60 | 60 |
61 // Delete the database from disk if it's empty (but only if we managed to | 61 // Delete the database from disk if it's empty (but only if we managed to |
62 // open it!). This is safe on destruction, assuming that we have exclusive | 62 // open it!). This is safe on destruction, assuming that we have exclusive |
63 // access to the database. | 63 // access to the database. |
64 if (db_ && IsEmpty()) | 64 if (db_ && IsEmpty()) |
65 DeleteDbFile(); | 65 DeleteDbFile(); |
66 } | 66 } |
67 | 67 |
68 size_t LeveldbValueStore::GetBytesInUse(const std::string& key) { | 68 size_t LeveldbValueStore::GetBytesInUse(const std::string& key) { |
69 // Let SettingsStorageQuotaEnforcer implement this. | 69 // Let SettingsStorageQuotaEnforcer implement this. |
70 NOTREACHED() << "Not implemented"; | 70 NOTREACHED() << "Not implemented"; |
71 return 0; | 71 return 0; |
72 } | 72 } |
73 | 73 |
74 size_t LeveldbValueStore::GetBytesInUse( | 74 size_t LeveldbValueStore::GetBytesInUse( |
75 const std::vector<std::string>& keys) { | 75 const std::vector<std::string>& keys) { |
76 // Let SettingsStorageQuotaEnforcer implement this. | 76 // Let SettingsStorageQuotaEnforcer implement this. |
77 NOTREACHED() << "Not implemented"; | 77 NOTREACHED() << "Not implemented"; |
78 return 0; | 78 return 0; |
79 } | 79 } |
80 | 80 |
81 size_t LeveldbValueStore::GetBytesInUse() { | 81 size_t LeveldbValueStore::GetBytesInUse() { |
82 // Let SettingsStorageQuotaEnforcer implement this. | 82 // Let SettingsStorageQuotaEnforcer implement this. |
83 NOTREACHED() << "Not implemented"; | 83 NOTREACHED() << "Not implemented"; |
84 return 0; | 84 return 0; |
85 } | 85 } |
86 | 86 |
87 ValueStore::ReadResult LeveldbValueStore::Get(const std::string& key) { | 87 ValueStore::ReadResult LeveldbValueStore::Get(const std::string& key) { |
88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 88 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
89 | 89 |
90 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 90 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
91 if (open_error) | 91 if (open_error) |
92 return MakeReadResult(open_error.Pass()); | 92 return MakeReadResult(open_error.Pass()); |
93 | 93 |
94 scoped_ptr<base::Value> setting; | 94 scoped_ptr<base::Value> setting; |
95 scoped_ptr<Error> error = ReadFromDb(leveldb::ReadOptions(), key, &setting); | 95 scoped_ptr<Error> error = ReadFromDb(leveldb::ReadOptions(), key, &setting); |
96 if (error) | 96 if (error) |
97 return MakeReadResult(error.Pass()); | 97 return MakeReadResult(error.Pass()); |
98 | 98 |
99 base::DictionaryValue* settings = new base::DictionaryValue(); | 99 base::DictionaryValue* settings = new base::DictionaryValue(); |
100 if (setting) | 100 if (setting) |
101 settings->SetWithoutPathExpansion(key, setting.release()); | 101 settings->SetWithoutPathExpansion(key, setting.release()); |
102 return MakeReadResult(make_scoped_ptr(settings)); | 102 return MakeReadResult(make_scoped_ptr(settings)); |
103 } | 103 } |
104 | 104 |
105 ValueStore::ReadResult LeveldbValueStore::Get( | 105 ValueStore::ReadResult LeveldbValueStore::Get( |
106 const std::vector<std::string>& keys) { | 106 const std::vector<std::string>& keys) { |
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 107 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
108 | 108 |
109 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 109 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
110 if (open_error) | 110 if (open_error) |
111 return MakeReadResult(open_error.Pass()); | 111 return MakeReadResult(open_error.Pass()); |
112 | 112 |
113 leveldb::ReadOptions options; | 113 leveldb::ReadOptions options; |
114 scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue()); | 114 scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue()); |
115 | 115 |
116 // All interaction with the db is done on the same thread, so snapshotting | 116 // All interaction with the db is done on the same thread, so snapshotting |
117 // isn't strictly necessary. This is just defensive. | 117 // isn't strictly necessary. This is just defensive. |
118 ScopedSnapshot snapshot(db_.get()); | 118 ScopedSnapshot snapshot(db_.get()); |
119 options.snapshot = snapshot.get(); | 119 options.snapshot = snapshot.get(); |
120 for (std::vector<std::string>::const_iterator it = keys.begin(); | 120 for (std::vector<std::string>::const_iterator it = keys.begin(); |
121 it != keys.end(); ++it) { | 121 it != keys.end(); ++it) { |
122 scoped_ptr<base::Value> setting; | 122 scoped_ptr<base::Value> setting; |
123 scoped_ptr<Error> error = ReadFromDb(options, *it, &setting); | 123 scoped_ptr<Error> error = ReadFromDb(options, *it, &setting); |
124 if (error) | 124 if (error) |
125 return MakeReadResult(error.Pass()); | 125 return MakeReadResult(error.Pass()); |
126 if (setting) | 126 if (setting) |
127 settings->SetWithoutPathExpansion(*it, setting.release()); | 127 settings->SetWithoutPathExpansion(*it, setting.release()); |
128 } | 128 } |
129 | 129 |
130 return MakeReadResult(settings.Pass()); | 130 return MakeReadResult(settings.Pass()); |
131 } | 131 } |
132 | 132 |
133 ValueStore::ReadResult LeveldbValueStore::Get() { | 133 ValueStore::ReadResult LeveldbValueStore::Get() { |
134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 134 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
135 | 135 |
136 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 136 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
137 if (open_error) | 137 if (open_error) |
138 return MakeReadResult(open_error.Pass()); | 138 return MakeReadResult(open_error.Pass()); |
139 | 139 |
140 base::JSONReader json_reader; | 140 base::JSONReader json_reader; |
141 leveldb::ReadOptions options = leveldb::ReadOptions(); | 141 leveldb::ReadOptions options = leveldb::ReadOptions(); |
142 // All interaction with the db is done on the same thread, so snapshotting | 142 // All interaction with the db is done on the same thread, so snapshotting |
143 // isn't strictly necessary. This is just defensive. | 143 // isn't strictly necessary. This is just defensive. |
144 scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue()); | 144 scoped_ptr<base::DictionaryValue> settings(new base::DictionaryValue()); |
(...skipping 17 matching lines...) Expand all Loading... |
162 } | 162 } |
163 | 163 |
164 if (!it->status().ok()) | 164 if (!it->status().ok()) |
165 return MakeReadResult(ToValueStoreError(it->status(), util::NoKey())); | 165 return MakeReadResult(ToValueStoreError(it->status(), util::NoKey())); |
166 | 166 |
167 return MakeReadResult(settings.Pass()); | 167 return MakeReadResult(settings.Pass()); |
168 } | 168 } |
169 | 169 |
170 ValueStore::WriteResult LeveldbValueStore::Set( | 170 ValueStore::WriteResult LeveldbValueStore::Set( |
171 WriteOptions options, const std::string& key, const base::Value& value) { | 171 WriteOptions options, const std::string& key, const base::Value& value) { |
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 172 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
173 | 173 |
174 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 174 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
175 if (open_error) | 175 if (open_error) |
176 return MakeWriteResult(open_error.Pass()); | 176 return MakeWriteResult(open_error.Pass()); |
177 | 177 |
178 leveldb::WriteBatch batch; | 178 leveldb::WriteBatch batch; |
179 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); | 179 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); |
180 scoped_ptr<Error> batch_error = | 180 scoped_ptr<Error> batch_error = |
181 AddToBatch(options, key, value, &batch, changes.get()); | 181 AddToBatch(options, key, value, &batch, changes.get()); |
182 if (batch_error) | 182 if (batch_error) |
183 return MakeWriteResult(batch_error.Pass()); | 183 return MakeWriteResult(batch_error.Pass()); |
184 | 184 |
185 scoped_ptr<Error> write_error = WriteToDb(&batch); | 185 scoped_ptr<Error> write_error = WriteToDb(&batch); |
186 return write_error ? MakeWriteResult(write_error.Pass()) | 186 return write_error ? MakeWriteResult(write_error.Pass()) |
187 : MakeWriteResult(changes.Pass()); | 187 : MakeWriteResult(changes.Pass()); |
188 } | 188 } |
189 | 189 |
190 ValueStore::WriteResult LeveldbValueStore::Set( | 190 ValueStore::WriteResult LeveldbValueStore::Set( |
191 WriteOptions options, const base::DictionaryValue& settings) { | 191 WriteOptions options, const base::DictionaryValue& settings) { |
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 192 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
193 | 193 |
194 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 194 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
195 if (open_error) | 195 if (open_error) |
196 return MakeWriteResult(open_error.Pass()); | 196 return MakeWriteResult(open_error.Pass()); |
197 | 197 |
198 leveldb::WriteBatch batch; | 198 leveldb::WriteBatch batch; |
199 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); | 199 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); |
200 | 200 |
201 for (base::DictionaryValue::Iterator it(settings); | 201 for (base::DictionaryValue::Iterator it(settings); |
202 !it.IsAtEnd(); it.Advance()) { | 202 !it.IsAtEnd(); it.Advance()) { |
203 scoped_ptr<Error> batch_error = | 203 scoped_ptr<Error> batch_error = |
204 AddToBatch(options, it.key(), it.value(), &batch, changes.get()); | 204 AddToBatch(options, it.key(), it.value(), &batch, changes.get()); |
205 if (batch_error) | 205 if (batch_error) |
206 return MakeWriteResult(batch_error.Pass()); | 206 return MakeWriteResult(batch_error.Pass()); |
207 } | 207 } |
208 | 208 |
209 scoped_ptr<Error> write_error = WriteToDb(&batch); | 209 scoped_ptr<Error> write_error = WriteToDb(&batch); |
210 return write_error ? MakeWriteResult(write_error.Pass()) | 210 return write_error ? MakeWriteResult(write_error.Pass()) |
211 : MakeWriteResult(changes.Pass()); | 211 : MakeWriteResult(changes.Pass()); |
212 } | 212 } |
213 | 213 |
214 ValueStore::WriteResult LeveldbValueStore::Remove(const std::string& key) { | 214 ValueStore::WriteResult LeveldbValueStore::Remove(const std::string& key) { |
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 215 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
216 return Remove(std::vector<std::string>(1, key)); | 216 return Remove(std::vector<std::string>(1, key)); |
217 } | 217 } |
218 | 218 |
219 ValueStore::WriteResult LeveldbValueStore::Remove( | 219 ValueStore::WriteResult LeveldbValueStore::Remove( |
220 const std::vector<std::string>& keys) { | 220 const std::vector<std::string>& keys) { |
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 221 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
222 | 222 |
223 scoped_ptr<Error> open_error = EnsureDbIsOpen(); | 223 scoped_ptr<Error> open_error = EnsureDbIsOpen(); |
224 if (open_error) | 224 if (open_error) |
225 return MakeWriteResult(open_error.Pass()); | 225 return MakeWriteResult(open_error.Pass()); |
226 | 226 |
227 leveldb::WriteBatch batch; | 227 leveldb::WriteBatch batch; |
228 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); | 228 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); |
229 | 229 |
230 for (std::vector<std::string>::const_iterator it = keys.begin(); | 230 for (std::vector<std::string>::const_iterator it = keys.begin(); |
231 it != keys.end(); ++it) { | 231 it != keys.end(); ++it) { |
232 scoped_ptr<base::Value> old_value; | 232 scoped_ptr<base::Value> old_value; |
233 scoped_ptr<Error> read_error = | 233 scoped_ptr<Error> read_error = |
234 ReadFromDb(leveldb::ReadOptions(), *it, &old_value); | 234 ReadFromDb(leveldb::ReadOptions(), *it, &old_value); |
235 if (read_error) | 235 if (read_error) |
236 return MakeWriteResult(read_error.Pass()); | 236 return MakeWriteResult(read_error.Pass()); |
237 | 237 |
238 if (old_value) { | 238 if (old_value) { |
239 changes->push_back(ValueStoreChange(*it, old_value.release(), NULL)); | 239 changes->push_back(ValueStoreChange(*it, old_value.release(), NULL)); |
240 batch.Delete(*it); | 240 batch.Delete(*it); |
241 } | 241 } |
242 } | 242 } |
243 | 243 |
244 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 244 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
245 if (!status.ok() && !status.IsNotFound()) | 245 if (!status.ok() && !status.IsNotFound()) |
246 return MakeWriteResult(ToValueStoreError(status, util::NoKey())); | 246 return MakeWriteResult(ToValueStoreError(status, util::NoKey())); |
247 return MakeWriteResult(changes.Pass()); | 247 return MakeWriteResult(changes.Pass()); |
248 } | 248 } |
249 | 249 |
250 ValueStore::WriteResult LeveldbValueStore::Clear() { | 250 ValueStore::WriteResult LeveldbValueStore::Clear() { |
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 251 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
252 | 252 |
253 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); | 253 scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); |
254 | 254 |
255 ReadResult read_result = Get(); | 255 ReadResult read_result = Get(); |
256 if (read_result->HasError()) | 256 if (read_result->HasError()) |
257 return MakeWriteResult(read_result->PassError()); | 257 return MakeWriteResult(read_result->PassError()); |
258 | 258 |
259 base::DictionaryValue& whole_db = read_result->settings(); | 259 base::DictionaryValue& whole_db = read_result->settings(); |
260 while (!whole_db.empty()) { | 260 while (!whole_db.empty()) { |
261 std::string next_key = base::DictionaryValue::Iterator(whole_db).key(); | 261 std::string next_key = base::DictionaryValue::Iterator(whole_db).key(); |
262 scoped_ptr<base::Value> next_value; | 262 scoped_ptr<base::Value> next_value; |
263 whole_db.RemoveWithoutPathExpansion(next_key, &next_value); | 263 whole_db.RemoveWithoutPathExpansion(next_key, &next_value); |
264 changes->push_back( | 264 changes->push_back( |
265 ValueStoreChange(next_key, next_value.release(), NULL)); | 265 ValueStoreChange(next_key, next_value.release(), NULL)); |
266 } | 266 } |
267 | 267 |
268 DeleteDbFile(); | 268 DeleteDbFile(); |
269 return MakeWriteResult(changes.Pass()); | 269 return MakeWriteResult(changes.Pass()); |
270 } | 270 } |
271 | 271 |
272 bool LeveldbValueStore::Restore() { | 272 bool LeveldbValueStore::Restore() { |
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 273 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
274 | 274 |
275 ReadResult result = Get(); | 275 ReadResult result = Get(); |
276 std::string previous_key; | 276 std::string previous_key; |
277 while (result->IsCorrupted()) { | 277 while (result->IsCorrupted()) { |
278 // If we don't have a specific corrupted key, or we've tried and failed to | 278 // If we don't have a specific corrupted key, or we've tried and failed to |
279 // clear this specific key, or we fail to restore the key, then wipe the | 279 // clear this specific key, or we fail to restore the key, then wipe the |
280 // whole database. | 280 // whole database. |
281 if (!result->error().key.get() || *result->error().key == previous_key || | 281 if (!result->error().key.get() || *result->error().key == previous_key || |
282 !RestoreKey(*result->error().key)) { | 282 !RestoreKey(*result->error().key)) { |
283 DeleteDbFile(); | 283 DeleteDbFile(); |
284 result = Get(); | 284 result = Get(); |
285 break; | 285 break; |
286 } | 286 } |
287 | 287 |
288 // Otherwise, re-Get() the database to check if there is still any | 288 // Otherwise, re-Get() the database to check if there is still any |
289 // corruption. | 289 // corruption. |
290 previous_key = *result->error().key; | 290 previous_key = *result->error().key; |
291 result = Get(); | 291 result = Get(); |
292 } | 292 } |
293 | 293 |
294 // If we still have an error, it means we've tried deleting the database file, | 294 // If we still have an error, it means we've tried deleting the database file, |
295 // and failed. There's nothing more we can do. | 295 // and failed. There's nothing more we can do. |
296 return !result->IsCorrupted(); | 296 return !result->IsCorrupted(); |
297 } | 297 } |
298 | 298 |
299 bool LeveldbValueStore::RestoreKey(const std::string& key) { | 299 bool LeveldbValueStore::RestoreKey(const std::string& key) { |
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 300 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
301 | 301 |
302 ReadResult result = Get(key); | 302 ReadResult result = Get(key); |
303 if (result->IsCorrupted()) { | 303 if (result->IsCorrupted()) { |
304 leveldb::WriteBatch batch; | 304 leveldb::WriteBatch batch; |
305 batch.Delete(key); | 305 batch.Delete(key); |
306 scoped_ptr<ValueStore::Error> error = WriteToDb(&batch); | 306 scoped_ptr<ValueStore::Error> error = WriteToDb(&batch); |
307 // If we can't delete the key, the restore failed. | 307 // If we can't delete the key, the restore failed. |
308 if (error.get()) | 308 if (error.get()) |
309 return false; | 309 return false; |
310 result = Get(key); | 310 result = Get(key); |
311 } | 311 } |
312 | 312 |
313 // The restore succeeded if there is no corruption error. | 313 // The restore succeeded if there is no corruption error. |
314 return !result->IsCorrupted(); | 314 return !result->IsCorrupted(); |
315 } | 315 } |
316 | 316 |
317 bool LeveldbValueStore::WriteToDbForTest(leveldb::WriteBatch* batch) { | 317 bool LeveldbValueStore::WriteToDbForTest(leveldb::WriteBatch* batch) { |
318 return !WriteToDb(batch).get(); | 318 return !WriteToDb(batch).get(); |
319 } | 319 } |
320 | 320 |
321 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { | 321 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { |
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 322 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
323 | 323 |
324 if (db_) | 324 if (db_) |
325 return util::NoError(); | 325 return util::NoError(); |
326 | 326 |
327 leveldb::Options options; | 327 leveldb::Options options; |
328 options.max_open_files = 0; // Use minimum. | 328 options.max_open_files = 0; // Use minimum. |
329 options.create_if_missing = true; | 329 options.create_if_missing = true; |
330 | 330 |
331 leveldb::DB* db = NULL; | 331 leveldb::DB* db = NULL; |
332 leveldb::Status status = | 332 leveldb::Status status = |
333 leveldb::DB::Open(options, db_path_.AsUTF8Unsafe(), &db); | 333 leveldb::DB::Open(options, db_path_.AsUTF8Unsafe(), &db); |
334 if (!status.ok()) | 334 if (!status.ok()) |
335 return ToValueStoreError(status, util::NoKey()); | 335 return ToValueStoreError(status, util::NoKey()); |
336 | 336 |
337 CHECK(db); | 337 CHECK(db); |
338 db_.reset(db); | 338 db_.reset(db); |
339 return util::NoError(); | 339 return util::NoError(); |
340 } | 340 } |
341 | 341 |
342 scoped_ptr<ValueStore::Error> LeveldbValueStore::ReadFromDb( | 342 scoped_ptr<ValueStore::Error> LeveldbValueStore::ReadFromDb( |
343 leveldb::ReadOptions options, | 343 leveldb::ReadOptions options, |
344 const std::string& key, | 344 const std::string& key, |
345 scoped_ptr<base::Value>* setting) { | 345 scoped_ptr<base::Value>* setting) { |
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 346 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
347 DCHECK(setting); | 347 DCHECK(setting); |
348 | 348 |
349 std::string value_as_json; | 349 std::string value_as_json; |
350 leveldb::Status s = db_->Get(options, key, &value_as_json); | 350 leveldb::Status s = db_->Get(options, key, &value_as_json); |
351 | 351 |
352 if (s.IsNotFound()) { | 352 if (s.IsNotFound()) { |
353 // Despite there being no value, it was still a success. Check this first | 353 // Despite there being no value, it was still a success. Check this first |
354 // because ok() is false on IsNotFound. | 354 // because ok() is false on IsNotFound. |
355 return util::NoError(); | 355 return util::NoError(); |
356 } | 356 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 } | 398 } |
399 | 399 |
400 scoped_ptr<ValueStore::Error> LeveldbValueStore::WriteToDb( | 400 scoped_ptr<ValueStore::Error> LeveldbValueStore::WriteToDb( |
401 leveldb::WriteBatch* batch) { | 401 leveldb::WriteBatch* batch) { |
402 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch); | 402 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch); |
403 return status.ok() ? util::NoError() | 403 return status.ok() ? util::NoError() |
404 : ToValueStoreError(status, util::NoKey()); | 404 : ToValueStoreError(status, util::NoKey()); |
405 } | 405 } |
406 | 406 |
407 bool LeveldbValueStore::IsEmpty() { | 407 bool LeveldbValueStore::IsEmpty() { |
408 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 408 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
409 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions())); | 409 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions())); |
410 | 410 |
411 it->SeekToFirst(); | 411 it->SeekToFirst(); |
412 bool is_empty = !it->Valid(); | 412 bool is_empty = !it->Valid(); |
413 if (!it->status().ok()) { | 413 if (!it->status().ok()) { |
414 LOG(ERROR) << "Checking DB emptiness failed: " << it->status().ToString(); | 414 LOG(ERROR) << "Checking DB emptiness failed: " << it->status().ToString(); |
415 return false; | 415 return false; |
416 } | 416 } |
417 return is_empty; | 417 return is_empty; |
418 } | 418 } |
(...skipping 12 matching lines...) Expand all Loading... |
431 CHECK(!status.ok()); | 431 CHECK(!status.ok()); |
432 CHECK(!status.IsNotFound()); // not an error | 432 CHECK(!status.IsNotFound()); // not an error |
433 | 433 |
434 std::string message = status.ToString(); | 434 std::string message = status.ToString(); |
435 // The message may contain |db_path_|, which may be considered sensitive | 435 // The message may contain |db_path_|, which may be considered sensitive |
436 // data, and those strings are passed to the extension, so strip it out. | 436 // data, and those strings are passed to the extension, so strip it out. |
437 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); | 437 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); |
438 | 438 |
439 return Error::Create(CORRUPTION, message, key.Pass()); | 439 return Error::Create(CORRUPTION, message, key.Pass()); |
440 } | 440 } |
OLD | NEW |