| 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 |