Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. | 1 // Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors. | 3 // found in the LICENSE file. See the AUTHORS file for names of contributors. |
| 4 | 4 |
| 5 #include "third_party/leveldatabase/env_chromium.h" | 5 #include "third_party/leveldatabase/env_chromium.h" |
| 6 | 6 |
| 7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <dirent.h> | 8 #include <dirent.h> |
| 9 #include <sys/types.h> | 9 #include <sys/types.h> |
| 10 #endif | 10 #endif |
| 11 | 11 |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/memory/shared_memory.h" | 14 #include "base/memory/shared_memory.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/process/process_metrics.h" | 16 #include "base/process/process_metrics.h" |
| 17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "base/strings/stringprintf.h" | |
| 18 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 19 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 20 #include "third_party/leveldatabase/chromium_logger.h" | 21 #include "third_party/leveldatabase/chromium_logger.h" |
| 21 #include "third_party/re2/re2/re2.h" | 22 #include "third_party/re2/re2/re2.h" |
| 22 | 23 |
| 23 using base::FilePath; | 24 using base::FilePath; |
| 24 using leveldb::FileLock; | 25 using leveldb::FileLock; |
| 25 using leveldb::Slice; | 26 using leveldb::Slice; |
| 26 using leveldb::Status; | 27 using leveldb::Status; |
| 27 | 28 |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 319 if (make_backup_ && file_type_ == kTable) | 320 if (make_backup_ && file_type_ == kTable) |
| 320 uma_logger_->RecordBackupResult(ChromiumEnv::MakeBackup(filename_)); | 321 uma_logger_->RecordBackupResult(ChromiumEnv::MakeBackup(filename_)); |
| 321 | 322 |
| 322 return Status::OK(); | 323 return Status::OK(); |
| 323 } | 324 } |
| 324 | 325 |
| 325 class IDBEnv : public ChromiumEnv { | 326 class IDBEnv : public ChromiumEnv { |
| 326 public: | 327 public: |
| 327 IDBEnv() : ChromiumEnv() { | 328 IDBEnv() : ChromiumEnv() { |
| 328 name_ = "LevelDBEnv.IDB"; | 329 name_ = "LevelDBEnv.IDB"; |
| 330 uma_ioerror_base_name_ = name_ + ".IOError.BFE"; | |
| 329 make_backup_ = true; | 331 make_backup_ = true; |
| 330 } | 332 } |
| 331 }; | 333 }; |
| 332 | 334 |
| 333 base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; | 335 base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; |
| 334 | 336 |
| 335 base::LazyInstance<ChromiumEnv>::Leaky default_env = LAZY_INSTANCE_INITIALIZER; | 337 base::LazyInstance<ChromiumEnv>::Leaky default_env = LAZY_INSTANCE_INITIALIZER; |
| 336 | 338 |
| 337 } // unnamed namespace | 339 } // unnamed namespace |
| 338 | 340 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 389 NOTREACHED(); | 391 NOTREACHED(); |
| 390 return "Unknown"; | 392 return "Unknown"; |
| 391 } | 393 } |
| 392 | 394 |
| 393 Status MakeIOError(Slice filename, | 395 Status MakeIOError(Slice filename, |
| 394 const std::string& message, | 396 const std::string& message, |
| 395 MethodID method, | 397 MethodID method, |
| 396 base::File::Error error) { | 398 base::File::Error error) { |
| 397 DCHECK_LT(error, 0); | 399 DCHECK_LT(error, 0); |
| 398 char buf[512]; | 400 char buf[512]; |
| 399 snprintf(buf, sizeof(buf), "%s (ChromeMethodPFE: %d::%s::%d)", | 401 snprintf(buf, sizeof(buf), "%s (ChromeMethodBFE: %d::%s::%d)", |
| 400 message.c_str(), method, MethodIDToString(method), -error); | 402 message.c_str(), method, MethodIDToString(method), -error); |
| 401 return Status::IOError(filename, buf); | 403 return Status::IOError(filename, buf); |
| 402 } | 404 } |
| 403 | 405 |
| 404 Status MakeIOError(Slice filename, | 406 Status MakeIOError(Slice filename, |
| 405 const std::string& message, | 407 const std::string& message, |
| 406 MethodID method) { | 408 MethodID method) { |
| 407 char buf[512]; | 409 char buf[512]; |
| 408 snprintf(buf, sizeof(buf), "%s (ChromeMethodOnly: %d::%s)", message.c_str(), | 410 snprintf(buf, sizeof(buf), "%s (ChromeMethodOnly: %d::%s)", message.c_str(), |
| 409 method, MethodIDToString(method)); | 411 method, MethodIDToString(method)); |
| 410 return Status::IOError(filename, buf); | 412 return Status::IOError(filename, buf); |
| 411 } | 413 } |
| 412 | 414 |
| 413 ErrorParsingResult ParseMethodAndError(const leveldb::Status& status, | 415 ErrorParsingResult ParseMethodAndError(const leveldb::Status& status, |
| 414 MethodID* method_param, | 416 MethodID* method_param, |
| 415 base::File::Error* error) { | 417 base::File::Error* error) { |
| 416 const std::string status_string = status.ToString(); | 418 const std::string status_string = status.ToString(); |
| 417 int method; | 419 int method; |
| 418 if (RE2::PartialMatch(status_string.c_str(), "ChromeMethodOnly: (\\d+)", | 420 if (RE2::PartialMatch(status_string.c_str(), "ChromeMethodOnly: (\\d+)", |
| 419 &method)) { | 421 &method)) { |
| 420 *method_param = static_cast<MethodID>(method); | 422 *method_param = static_cast<MethodID>(method); |
| 421 return METHOD_ONLY; | 423 return METHOD_ONLY; |
| 422 } | 424 } |
| 423 int parsed_error; | 425 int parsed_error; |
| 424 if (RE2::PartialMatch(status_string.c_str(), | 426 if (RE2::PartialMatch(status_string.c_str(), |
| 425 "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, | 427 "ChromeMethodBFE: (\\d+)::.*::(\\d+)", &method, |
| 426 &parsed_error)) { | 428 &parsed_error)) { |
| 427 *method_param = static_cast<MethodID>(method); | 429 *method_param = static_cast<MethodID>(method); |
| 428 *error = static_cast<base::File::Error>(-parsed_error); | 430 *error = static_cast<base::File::Error>(-parsed_error); |
| 429 DCHECK_LT(*error, base::File::FILE_OK); | 431 DCHECK_LT(*error, base::File::FILE_OK); |
| 430 DCHECK_GT(*error, base::File::FILE_ERROR_MAX); | 432 DCHECK_GT(*error, base::File::FILE_ERROR_MAX); |
| 431 return METHOD_AND_PFE; | 433 return METHOD_AND_BFE; |
| 432 } | 434 } |
| 433 return NONE; | 435 return NONE; |
| 434 } | 436 } |
| 435 | 437 |
| 436 // Keep in sync with LevelDBCorruptionTypes in histograms.xml. Also, don't | 438 // Keep in sync with LevelDBCorruptionTypes in histograms.xml. Also, don't |
| 437 // change the order because indices into this array have been recorded in uma | 439 // change the order because indices into this array have been recorded in uma |
| 438 // histograms. | 440 // histograms. |
| 439 const char* patterns[] = { | 441 const char* patterns[] = { |
| 440 "missing files", | 442 "missing files", |
| 441 "log record too small", | 443 "log record too small", |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 return patterns[code - 1]; | 502 return patterns[code - 1]; |
| 501 } | 503 } |
| 502 | 504 |
| 503 bool IndicatesDiskFull(const leveldb::Status& status) { | 505 bool IndicatesDiskFull(const leveldb::Status& status) { |
| 504 if (status.ok()) | 506 if (status.ok()) |
| 505 return false; | 507 return false; |
| 506 leveldb_env::MethodID method; | 508 leveldb_env::MethodID method; |
| 507 base::File::Error error = base::File::FILE_OK; | 509 base::File::Error error = base::File::FILE_OK; |
| 508 leveldb_env::ErrorParsingResult result = | 510 leveldb_env::ErrorParsingResult result = |
| 509 leveldb_env::ParseMethodAndError(status, &method, &error); | 511 leveldb_env::ParseMethodAndError(status, &method, &error); |
| 510 return (result == leveldb_env::METHOD_AND_PFE && | 512 return (result == leveldb_env::METHOD_AND_BFE && |
| 511 static_cast<base::File::Error>(error) == | 513 static_cast<base::File::Error>(error) == |
| 512 base::File::FILE_ERROR_NO_SPACE); | 514 base::File::FILE_ERROR_NO_SPACE); |
| 513 } | 515 } |
| 514 | 516 |
| 515 bool ChromiumEnv::MakeBackup(const std::string& fname) { | 517 bool ChromiumEnv::MakeBackup(const std::string& fname) { |
| 516 FilePath original_table_name = FilePath::FromUTF8Unsafe(fname); | 518 FilePath original_table_name = FilePath::FromUTF8Unsafe(fname); |
| 517 FilePath backup_table_name = | 519 FilePath backup_table_name = |
| 518 original_table_name.ReplaceExtension(backup_table_extension); | 520 original_table_name.ReplaceExtension(backup_table_extension); |
| 519 return base::CopyFile(original_table_name, backup_table_name); | 521 return base::CopyFile(original_table_name, backup_table_name); |
| 520 } | 522 } |
| 521 | 523 |
| 522 ChromiumEnv::ChromiumEnv() | 524 ChromiumEnv::ChromiumEnv() |
| 523 : name_("LevelDBEnv"), | 525 : name_("LevelDBEnv"), |
| 524 make_backup_(false), | 526 make_backup_(false), |
| 525 bgsignal_(&mu_), | 527 bgsignal_(&mu_), |
| 526 started_bgthread_(false), | 528 started_bgthread_(false), |
| 527 kMaxRetryTimeMillis(1000) { | 529 kMaxRetryTimeMillis(1000) { |
| 530 uma_ioerror_base_name_ = name_ + ".IOError.BFE"; | |
| 528 } | 531 } |
| 529 | 532 |
| 530 ChromiumEnv::~ChromiumEnv() { | 533 ChromiumEnv::~ChromiumEnv() { |
| 531 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to | 534 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to |
| 532 // ensure that behavior isn't accidentally changed, but there's an instance in | 535 // ensure that behavior isn't accidentally changed, but there's an instance in |
| 533 // a unit test that is deleted. | 536 // a unit test that is deleted. |
| 534 } | 537 } |
| 535 | 538 |
| 536 bool ChromiumEnv::FileExists(const std::string& fname) { | 539 bool ChromiumEnv::FileExists(const std::string& fname) { |
| 537 return base::PathExists(FilePath::FromUTF8Unsafe(fname)); | 540 return base::PathExists(FilePath::FromUTF8Unsafe(fname)); |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 944 | 947 |
| 945 void ChromiumEnv::RecordBackupResult(bool result) const { | 948 void ChromiumEnv::RecordBackupResult(bool result) const { |
| 946 std::string uma_name(name_); | 949 std::string uma_name(name_); |
| 947 uma_name.append(".TableBackup"); | 950 uma_name.append(".TableBackup"); |
| 948 base::BooleanHistogram::FactoryGet( | 951 base::BooleanHistogram::FactoryGet( |
| 949 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); | 952 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); |
| 950 } | 953 } |
| 951 | 954 |
| 952 base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, | 955 base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, |
| 953 int limit) const { | 956 int limit) const { |
| 954 std::string uma_name(name_); | 957 std::string uma_name; |
| 955 // TODO(dgrogan): This is probably not the best way to concatenate strings. | 958 base::StringAppendF(&uma_name, "%s.%s", uma_ioerror_base_name_.c_str(), |
| 956 uma_name.append(".IOError.").append(MethodIDToString(method)); | 959 MethodIDToString(method)); |
| 957 return base::LinearHistogram::FactoryGet(uma_name, 1, limit, limit + 1, | 960 return base::LinearHistogram::FactoryGet(uma_name, 1, limit, limit + 1, |
| 958 base::Histogram::kUmaTargetedHistogramFlag); | 961 base::Histogram::kUmaTargetedHistogramFlag); |
| 959 } | 962 } |
| 960 | 963 |
| 961 base::HistogramBase* ChromiumEnv::GetMethodIOErrorHistogram() const { | 964 base::HistogramBase* ChromiumEnv::GetMethodIOErrorHistogram() const { |
|
dgrogan
2015/03/14 05:57:37
It looks like this one didn't need to change. It j
cmumford
2015/03/17 21:25:52
Yes, I see your point - and agree.
| |
| 962 std::string uma_name(name_); | 965 return base::LinearHistogram::FactoryGet( |
| 963 uma_name.append(".IOError"); | 966 uma_ioerror_base_name_, 1, kNumEntries, kNumEntries + 1, |
| 964 return base::LinearHistogram::FactoryGet(uma_name, 1, kNumEntries, | 967 base::Histogram::kUmaTargetedHistogramFlag); |
| 965 kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag); | |
| 966 } | 968 } |
| 967 | 969 |
| 968 base::HistogramBase* ChromiumEnv::GetMaxFDHistogram( | 970 base::HistogramBase* ChromiumEnv::GetMaxFDHistogram( |
| 969 const std::string& type) const { | 971 const std::string& type) const { |
| 970 std::string uma_name(name_); | 972 std::string uma_name(name_); |
| 971 uma_name.append(".MaxFDs.").append(type); | 973 uma_name.append(".MaxFDs.").append(type); |
| 972 // These numbers make each bucket twice as large as the previous bucket. | 974 // These numbers make each bucket twice as large as the previous bucket. |
| 973 const int kFirstEntry = 1; | 975 const int kFirstEntry = 1; |
| 974 const int kLastEntry = 65536; | 976 const int kLastEntry = 65536; |
| 975 const int kNumBuckets = 18; | 977 const int kNumBuckets = 18; |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 | 1106 |
| 1105 Env* IDBEnv() { | 1107 Env* IDBEnv() { |
| 1106 return leveldb_env::idb_env.Pointer(); | 1108 return leveldb_env::idb_env.Pointer(); |
| 1107 } | 1109 } |
| 1108 | 1110 |
| 1109 Env* Env::Default() { | 1111 Env* Env::Default() { |
| 1110 return leveldb_env::default_env.Pointer(); | 1112 return leveldb_env::default_env.Pointer(); |
| 1111 } | 1113 } |
| 1112 | 1114 |
| 1113 } // namespace leveldb | 1115 } // namespace leveldb |
| OLD | NEW |