Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "content/browser/indexed_db/leveldb/leveldb_database.h" | 5 #include "content/browser/indexed_db/leveldb/leveldb_database.h" |
| 6 | 6 |
| 7 #include <cerrno> | 7 #include <cerrno> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/files/file.h" | 10 #include "base/files/file.h" |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 if (s.IsIOError()) | 257 if (s.IsIOError()) |
| 258 ParseAndHistogramIOErrorDetails(histogram_name, s); | 258 ParseAndHistogramIOErrorDetails(histogram_name, s); |
| 259 else | 259 else |
| 260 ParseAndHistogramCorruptionDetails(histogram_name, s); | 260 ParseAndHistogramCorruptionDetails(histogram_name, s); |
| 261 } | 261 } |
| 262 | 262 |
| 263 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, | 263 leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name, |
| 264 const LevelDBComparator* comparator, | 264 const LevelDBComparator* comparator, |
| 265 scoped_ptr<LevelDBDatabase>* result, | 265 scoped_ptr<LevelDBDatabase>* result, |
| 266 bool* is_disk_full) { | 266 bool* is_disk_full) { |
| 267 base::TimeTicks begin_time = base::TimeTicks::Now(); | |
| 268 | |
| 267 scoped_ptr<ComparatorAdapter> comparator_adapter( | 269 scoped_ptr<ComparatorAdapter> comparator_adapter( |
| 268 new ComparatorAdapter(comparator)); | 270 new ComparatorAdapter(comparator)); |
| 269 | 271 |
| 270 leveldb::DB* db; | 272 leveldb::DB* db; |
| 271 const leveldb::Status s = | 273 const leveldb::Status s = |
| 272 OpenDB(comparator_adapter.get(), leveldb::IDBEnv(), file_name, &db); | 274 OpenDB(comparator_adapter.get(), leveldb::IDBEnv(), file_name, &db); |
| 273 | 275 |
| 274 if (!s.ok()) { | 276 if (!s.ok()) { |
| 275 HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); | 277 HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s); |
| 276 int free_space_k_bytes = CheckFreeSpace("Failure", file_name); | 278 int free_space_k_bytes = CheckFreeSpace("Failure", file_name); |
| 277 // Disks with <100k of free space almost never succeed in opening a | 279 // Disks with <100k of free space almost never succeed in opening a |
| 278 // leveldb database. | 280 // leveldb database. |
| 279 if (is_disk_full) | 281 if (is_disk_full) |
| 280 *is_disk_full = free_space_k_bytes >= 0 && free_space_k_bytes < 100; | 282 *is_disk_full = free_space_k_bytes >= 0 && free_space_k_bytes < 100; |
| 281 | 283 |
| 282 LOG(ERROR) << "Failed to open LevelDB database from " | 284 LOG(ERROR) << "Failed to open LevelDB database from " |
| 283 << file_name.AsUTF8Unsafe() << "," << s.ToString(); | 285 << file_name.AsUTF8Unsafe() << "," << s.ToString(); |
| 284 return s; | 286 return s; |
| 285 } | 287 } |
| 286 | 288 |
| 289 UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime.Disk", | |
|
jsbell
2014/08/13 22:49:11
Assumes anything < 10 seconds is "fast enough" and
cmumford
2014/08/13 23:53:02
If I'm reading the code correctly then UMA_HISTOGR
dgrogan
2014/08/13 23:55:18
They'll show up in the 0 bucket.
| |
| 290 base::TimeTicks::Now() - begin_time); | |
| 291 | |
| 287 CheckFreeSpace("Success", file_name); | 292 CheckFreeSpace("Success", file_name); |
| 288 | 293 |
| 289 (*result).reset(new LevelDBDatabase); | 294 (*result).reset(new LevelDBDatabase); |
| 290 (*result)->db_ = make_scoped_ptr(db); | 295 (*result)->db_ = make_scoped_ptr(db); |
| 291 (*result)->comparator_adapter_ = comparator_adapter.Pass(); | 296 (*result)->comparator_adapter_ = comparator_adapter.Pass(); |
| 292 (*result)->comparator_ = comparator; | 297 (*result)->comparator_ = comparator; |
| 293 | 298 |
| 294 return s; | 299 return s; |
| 295 } | 300 } |
| 296 | 301 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 313 result->env_ = in_memory_env.Pass(); | 318 result->env_ = in_memory_env.Pass(); |
| 314 result->db_ = make_scoped_ptr(db); | 319 result->db_ = make_scoped_ptr(db); |
| 315 result->comparator_adapter_ = comparator_adapter.Pass(); | 320 result->comparator_adapter_ = comparator_adapter.Pass(); |
| 316 result->comparator_ = comparator; | 321 result->comparator_ = comparator; |
| 317 | 322 |
| 318 return result.Pass(); | 323 return result.Pass(); |
| 319 } | 324 } |
| 320 | 325 |
| 321 leveldb::Status LevelDBDatabase::Put(const StringPiece& key, | 326 leveldb::Status LevelDBDatabase::Put(const StringPiece& key, |
| 322 std::string* value) { | 327 std::string* value) { |
| 328 base::TimeTicks begin_time = base::TimeTicks::Now(); | |
| 329 | |
| 323 leveldb::WriteOptions write_options; | 330 leveldb::WriteOptions write_options; |
| 324 write_options.sync = kSyncWrites; | 331 write_options.sync = kSyncWrites; |
| 325 | 332 |
| 326 const leveldb::Status s = | 333 const leveldb::Status s = |
| 327 db_->Put(write_options, MakeSlice(key), MakeSlice(*value)); | 334 db_->Put(write_options, MakeSlice(key), MakeSlice(*value)); |
| 328 if (!s.ok()) | 335 if (!s.ok()) |
| 329 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); | 336 LOG(ERROR) << "LevelDB put failed: " << s.ToString(); |
| 337 else | |
| 338 UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.PutTime", | |
| 339 base::TimeTicks::Now() - begin_time); | |
| 330 return s; | 340 return s; |
| 331 } | 341 } |
| 332 | 342 |
| 333 leveldb::Status LevelDBDatabase::Remove(const StringPiece& key) { | 343 leveldb::Status LevelDBDatabase::Remove(const StringPiece& key) { |
|
jsbell
2014/08/13 22:49:11
Why no histogram here?
cmumford
2014/08/13 23:53:02
No reason. Your bug only mentioned open & commit s
| |
| 334 leveldb::WriteOptions write_options; | 344 leveldb::WriteOptions write_options; |
| 335 write_options.sync = kSyncWrites; | 345 write_options.sync = kSyncWrites; |
| 336 | 346 |
| 337 const leveldb::Status s = db_->Delete(write_options, MakeSlice(key)); | 347 const leveldb::Status s = db_->Delete(write_options, MakeSlice(key)); |
| 338 if (!s.IsNotFound()) | 348 if (!s.IsNotFound()) |
| 339 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); | 349 LOG(ERROR) << "LevelDB remove failed: " << s.ToString(); |
| 340 return s; | 350 return s; |
| 341 } | 351 } |
| 342 | 352 |
| 343 leveldb::Status LevelDBDatabase::Get(const StringPiece& key, | 353 leveldb::Status LevelDBDatabase::Get(const StringPiece& key, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 356 return s; | 366 return s; |
| 357 } | 367 } |
| 358 if (s.IsNotFound()) | 368 if (s.IsNotFound()) |
| 359 return leveldb::Status::OK(); | 369 return leveldb::Status::OK(); |
| 360 HistogramLevelDBError("WebCore.IndexedDB.LevelDBReadErrors", s); | 370 HistogramLevelDBError("WebCore.IndexedDB.LevelDBReadErrors", s); |
| 361 LOG(ERROR) << "LevelDB get failed: " << s.ToString(); | 371 LOG(ERROR) << "LevelDB get failed: " << s.ToString(); |
| 362 return s; | 372 return s; |
| 363 } | 373 } |
| 364 | 374 |
| 365 leveldb::Status LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) { | 375 leveldb::Status LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) { |
| 376 base::TimeTicks begin_time = base::TimeTicks::Now(); | |
| 366 leveldb::WriteOptions write_options; | 377 leveldb::WriteOptions write_options; |
| 367 write_options.sync = kSyncWrites; | 378 write_options.sync = kSyncWrites; |
| 368 | 379 |
| 369 const leveldb::Status s = | 380 const leveldb::Status s = |
| 370 db_->Write(write_options, write_batch.write_batch_.get()); | 381 db_->Write(write_options, write_batch.write_batch_.get()); |
| 371 if (!s.ok()) { | 382 if (!s.ok()) { |
| 372 HistogramLevelDBError("WebCore.IndexedDB.LevelDBWriteErrors", s); | 383 HistogramLevelDBError("WebCore.IndexedDB.LevelDBWriteErrors", s); |
| 373 LOG(ERROR) << "LevelDB write failed: " << s.ToString(); | 384 LOG(ERROR) << "LevelDB write failed: " << s.ToString(); |
| 385 } else { | |
| 386 UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.WriteTime", | |
| 387 base::TimeTicks::Now() - begin_time); | |
| 374 } | 388 } |
| 375 return s; | 389 return s; |
| 376 } | 390 } |
| 377 | 391 |
| 378 scoped_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( | 392 scoped_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator( |
| 379 const LevelDBSnapshot* snapshot) { | 393 const LevelDBSnapshot* snapshot) { |
| 380 leveldb::ReadOptions read_options; | 394 leveldb::ReadOptions read_options; |
| 381 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the | 395 read_options.verify_checksums = true; // TODO(jsbell): Disable this if the |
| 382 // performance impact is too great. | 396 // performance impact is too great. |
| 383 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; | 397 read_options.snapshot = snapshot ? snapshot->snapshot_ : 0; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 396 const leveldb::Slice start_slice = MakeSlice(start); | 410 const leveldb::Slice start_slice = MakeSlice(start); |
| 397 const leveldb::Slice stop_slice = MakeSlice(stop); | 411 const leveldb::Slice stop_slice = MakeSlice(stop); |
| 398 // NULL batch means just wait for earlier writes to be done | 412 // NULL batch means just wait for earlier writes to be done |
| 399 db_->Write(leveldb::WriteOptions(), NULL); | 413 db_->Write(leveldb::WriteOptions(), NULL); |
| 400 db_->CompactRange(&start_slice, &stop_slice); | 414 db_->CompactRange(&start_slice, &stop_slice); |
| 401 } | 415 } |
| 402 | 416 |
| 403 void LevelDBDatabase::CompactAll() { db_->CompactRange(NULL, NULL); } | 417 void LevelDBDatabase::CompactAll() { db_->CompactRange(NULL, NULL); } |
| 404 | 418 |
| 405 } // namespace content | 419 } // namespace content |
| OLD | NEW |