| 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 <deque> | 5 #include <deque> |
| 6 #include <errno.h> | 6 #include <errno.h> |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 #include "base/at_exit.h" | 8 #include "base/at_exit.h" |
| 9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 kRenamefile, | 119 kRenamefile, |
| 120 kLockFile, | 120 kLockFile, |
| 121 kUnlockFile, | 121 kUnlockFile, |
| 122 kGetTestDirectory, | 122 kGetTestDirectory, |
| 123 kNewLogger, | 123 kNewLogger, |
| 124 kNumEntries | 124 kNumEntries |
| 125 }; | 125 }; |
| 126 | 126 |
| 127 class UMALogger { | 127 class UMALogger { |
| 128 public: | 128 public: |
| 129 UMALogger(std::string uma_title); | 129 virtual void RecordErrorAt(UmaEntry entry) const = 0; |
| 130 void RecordErrorAt(UmaEntry entry) const; | 130 virtual void LogRandomAccessFileError(base::PlatformFileError error_code) |
| 131 void LogRandomAccessFileError(base::PlatformFileError error_code) const; | 131 const = 0; |
| 132 | |
| 133 private: | |
| 134 std::string uma_title_; | |
| 135 }; | 132 }; |
| 136 | 133 |
| 137 UMALogger::UMALogger(std::string uma_title) : uma_title_(uma_title) {} | |
| 138 | |
| 139 void UMALogger::RecordErrorAt(UmaEntry entry) const { | |
| 140 std::string uma_name(uma_title_); | |
| 141 uma_name.append(".IOError"); | |
| 142 UMA_HISTOGRAM_ENUMERATION(uma_name, entry, kNumEntries); | |
| 143 } | |
| 144 | |
| 145 void UMALogger::LogRandomAccessFileError(base::PlatformFileError error_code) | |
| 146 const { | |
| 147 DCHECK(error_code < 0); | |
| 148 std::string uma_name(uma_title_); | |
| 149 uma_name.append(".IOError.RandomAccessFile"); | |
| 150 UMA_HISTOGRAM_ENUMERATION(uma_name, | |
| 151 -error_code, | |
| 152 -base::PLATFORM_FILE_ERROR_MAX); | |
| 153 } | |
| 154 | |
| 155 } // namespace | 134 } // namespace |
| 156 | 135 |
| 157 namespace leveldb { | 136 namespace leveldb { |
| 158 | 137 |
| 159 namespace { | 138 namespace { |
| 160 | 139 |
| 161 class Thread; | 140 class Thread; |
| 162 | 141 |
| 163 static const ::FilePath::CharType kLevelDBTestDirectoryPrefix[] | 142 static const ::FilePath::CharType kLevelDBTestDirectoryPrefix[] |
| 164 = FILE_PATH_LITERAL("leveldb-test-"); | 143 = FILE_PATH_LITERAL("leveldb-test-"); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 } | 310 } |
| 332 return result; | 311 return result; |
| 333 } | 312 } |
| 334 }; | 313 }; |
| 335 | 314 |
| 336 class ChromiumFileLock : public FileLock { | 315 class ChromiumFileLock : public FileLock { |
| 337 public: | 316 public: |
| 338 ::base::PlatformFile file_; | 317 ::base::PlatformFile file_; |
| 339 }; | 318 }; |
| 340 | 319 |
| 341 class ChromiumEnv : public Env { | 320 class ChromiumEnv : public Env, public UMALogger { |
| 342 public: | 321 public: |
| 343 ChromiumEnv(); | 322 ChromiumEnv(); |
| 344 virtual ~ChromiumEnv() { | 323 virtual ~ChromiumEnv() { |
| 345 NOTREACHED(); | 324 NOTREACHED(); |
| 346 } | 325 } |
| 347 | 326 |
| 348 virtual Status NewSequentialFile(const std::string& fname, | 327 virtual Status NewSequentialFile(const std::string& fname, |
| 349 SequentialFile** result) { | 328 SequentialFile** result) { |
| 350 FILE* f = fopen_internal(fname.c_str(), "rb"); | 329 FILE* f = fopen_internal(fname.c_str(), "rb"); |
| 351 if (f == NULL) { | 330 if (f == NULL) { |
| 352 *result = NULL; | 331 *result = NULL; |
| 353 uma_logger_->RecordErrorAt(kNewSequentialFile); | 332 RecordErrorAt(kNewSequentialFile); |
| 354 return Status::IOError(fname, strerror(errno)); | 333 return Status::IOError(fname, strerror(errno)); |
| 355 } else { | 334 } else { |
| 356 *result = new ChromiumSequentialFile(fname, f, uma_logger_.get()); | 335 *result = new ChromiumSequentialFile(fname, f, this); |
| 357 return Status::OK(); | 336 return Status::OK(); |
| 358 } | 337 } |
| 359 } | 338 } |
| 360 | 339 |
| 361 virtual Status NewRandomAccessFile(const std::string& fname, | 340 virtual Status NewRandomAccessFile(const std::string& fname, |
| 362 RandomAccessFile** result) { | 341 RandomAccessFile** result) { |
| 363 int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; | 342 int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; |
| 364 bool created; | 343 bool created; |
| 365 ::base::PlatformFileError error_code; | 344 ::base::PlatformFileError error_code; |
| 366 ::base::PlatformFile file = ::base::CreatePlatformFile( | 345 ::base::PlatformFile file = ::base::CreatePlatformFile( |
| 367 CreateFilePath(fname), flags, &created, &error_code); | 346 CreateFilePath(fname), flags, &created, &error_code); |
| 368 if (error_code != ::base::PLATFORM_FILE_OK) { | 347 if (error_code != ::base::PLATFORM_FILE_OK) { |
| 369 *result = NULL; | 348 *result = NULL; |
| 370 uma_logger_->RecordErrorAt(kNewRandomAccessFile); | 349 RecordErrorAt(kNewRandomAccessFile); |
| 371 uma_logger_->LogRandomAccessFileError(error_code); | 350 LogRandomAccessFileError(error_code); |
| 372 return Status::IOError(fname, PlatformFileErrorString(error_code)); | 351 return Status::IOError(fname, PlatformFileErrorString(error_code)); |
| 373 } | 352 } |
| 374 *result = new ChromiumRandomAccessFile(fname, file, uma_logger_.get()); | 353 *result = new ChromiumRandomAccessFile(fname, file, this); |
| 375 return Status::OK(); | 354 return Status::OK(); |
| 376 } | 355 } |
| 377 | 356 |
| 378 virtual Status NewWritableFile(const std::string& fname, | 357 virtual Status NewWritableFile(const std::string& fname, |
| 379 WritableFile** result) { | 358 WritableFile** result) { |
| 380 *result = NULL; | 359 *result = NULL; |
| 381 FILE* f = fopen_internal(fname.c_str(), "wb"); | 360 FILE* f = fopen_internal(fname.c_str(), "wb"); |
| 382 if (f == NULL) { | 361 if (f == NULL) { |
| 383 uma_logger_->RecordErrorAt(kNewWritableFile); | 362 RecordErrorAt(kNewWritableFile); |
| 384 return Status::IOError(fname, strerror(errno)); | 363 return Status::IOError(fname, strerror(errno)); |
| 385 } else { | 364 } else { |
| 386 if (!sync_parent(fname)) { | 365 if (!sync_parent(fname)) { |
| 387 fclose(f); | 366 fclose(f); |
| 388 return Status::IOError(fname, strerror(errno)); | 367 return Status::IOError(fname, strerror(errno)); |
| 389 } | 368 } |
| 390 *result = new ChromiumWritableFile(fname, f, uma_logger_.get()); | 369 *result = new ChromiumWritableFile(fname, f, this); |
| 391 return Status::OK(); | 370 return Status::OK(); |
| 392 } | 371 } |
| 393 } | 372 } |
| 394 | 373 |
| 395 virtual bool FileExists(const std::string& fname) { | 374 virtual bool FileExists(const std::string& fname) { |
| 396 return ::file_util::PathExists(CreateFilePath(fname)); | 375 return ::file_util::PathExists(CreateFilePath(fname)); |
| 397 } | 376 } |
| 398 | 377 |
| 399 virtual Status GetChildren(const std::string& dir, | 378 virtual Status GetChildren(const std::string& dir, |
| 400 std::vector<std::string>* result) { | 379 std::vector<std::string>* result) { |
| 401 result->clear(); | 380 result->clear(); |
| 402 ::file_util::FileEnumerator iter( | 381 ::file_util::FileEnumerator iter( |
| 403 CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES); | 382 CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES); |
| 404 ::FilePath current = iter.Next(); | 383 ::FilePath current = iter.Next(); |
| 405 while (!current.empty()) { | 384 while (!current.empty()) { |
| 406 result->push_back(FilePathToString(current.BaseName())); | 385 result->push_back(FilePathToString(current.BaseName())); |
| 407 current = iter.Next(); | 386 current = iter.Next(); |
| 408 } | 387 } |
| 409 // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so | 388 // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so |
| 410 // we'll always return OK. Maybe manually check for error | 389 // we'll always return OK. Maybe manually check for error |
| 411 // conditions like the file not existing? | 390 // conditions like the file not existing? |
| 412 return Status::OK(); | 391 return Status::OK(); |
| 413 } | 392 } |
| 414 | 393 |
| 415 virtual Status DeleteFile(const std::string& fname) { | 394 virtual Status DeleteFile(const std::string& fname) { |
| 416 Status result; | 395 Status result; |
| 417 // TODO(jorlow): Should we assert this is a file? | 396 // TODO(jorlow): Should we assert this is a file? |
| 418 if (!::file_util::Delete(CreateFilePath(fname), false)) { | 397 if (!::file_util::Delete(CreateFilePath(fname), false)) { |
| 419 result = Status::IOError(fname, "Could not delete file."); | 398 result = Status::IOError(fname, "Could not delete file."); |
| 420 uma_logger_->RecordErrorAt(kDeleteFile); | 399 RecordErrorAt(kDeleteFile); |
| 421 } | 400 } |
| 422 return result; | 401 return result; |
| 423 }; | 402 }; |
| 424 | 403 |
| 425 virtual Status CreateDir(const std::string& name) { | 404 virtual Status CreateDir(const std::string& name) { |
| 426 Status result; | 405 Status result; |
| 427 if (!::file_util::CreateDirectory(CreateFilePath(name))) { | 406 if (!::file_util::CreateDirectory(CreateFilePath(name))) { |
| 428 result = Status::IOError(name, "Could not create directory."); | 407 result = Status::IOError(name, "Could not create directory."); |
| 429 uma_logger_->RecordErrorAt(kCreateDir); | 408 RecordErrorAt(kCreateDir); |
| 430 } | 409 } |
| 431 return result; | 410 return result; |
| 432 }; | 411 }; |
| 433 | 412 |
| 434 virtual Status DeleteDir(const std::string& name) { | 413 virtual Status DeleteDir(const std::string& name) { |
| 435 Status result; | 414 Status result; |
| 436 // TODO(jorlow): Should we assert this is a directory? | 415 // TODO(jorlow): Should we assert this is a directory? |
| 437 if (!::file_util::Delete(CreateFilePath(name), false)) { | 416 if (!::file_util::Delete(CreateFilePath(name), false)) { |
| 438 result = Status::IOError(name, "Could not delete directory."); | 417 result = Status::IOError(name, "Could not delete directory."); |
| 439 uma_logger_->RecordErrorAt(kDeleteDir); | 418 RecordErrorAt(kDeleteDir); |
| 440 } | 419 } |
| 441 return result; | 420 return result; |
| 442 }; | 421 }; |
| 443 | 422 |
| 444 virtual Status GetFileSize(const std::string& fname, uint64_t* size) { | 423 virtual Status GetFileSize(const std::string& fname, uint64_t* size) { |
| 445 Status s; | 424 Status s; |
| 446 int64_t signed_size; | 425 int64_t signed_size; |
| 447 if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) { | 426 if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) { |
| 448 *size = 0; | 427 *size = 0; |
| 449 s = Status::IOError(fname, "Could not determine file size."); | 428 s = Status::IOError(fname, "Could not determine file size."); |
| 450 uma_logger_->RecordErrorAt(kGetFileSize); | 429 RecordErrorAt(kGetFileSize); |
| 451 } else { | 430 } else { |
| 452 *size = static_cast<uint64_t>(signed_size); | 431 *size = static_cast<uint64_t>(signed_size); |
| 453 } | 432 } |
| 454 return s; | 433 return s; |
| 455 } | 434 } |
| 456 | 435 |
| 457 virtual Status RenameFile(const std::string& src, const std::string& dst) { | 436 virtual Status RenameFile(const std::string& src, const std::string& dst) { |
| 458 Status result; | 437 Status result; |
| 459 if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) { | 438 if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) { |
| 460 result = Status::IOError(src, "Could not rename file."); | 439 result = Status::IOError(src, "Could not rename file."); |
| 461 uma_logger_->RecordErrorAt(kRenamefile); | 440 RecordErrorAt(kRenamefile); |
| 462 } else { | 441 } else { |
| 463 sync_parent(dst); | 442 sync_parent(dst); |
| 464 if (src != dst) | 443 if (src != dst) |
| 465 sync_parent(src); | 444 sync_parent(src); |
| 466 } | 445 } |
| 467 return result; | 446 return result; |
| 468 } | 447 } |
| 469 | 448 |
| 470 virtual Status LockFile(const std::string& fname, FileLock** lock) { | 449 virtual Status LockFile(const std::string& fname, FileLock** lock) { |
| 471 *lock = NULL; | 450 *lock = NULL; |
| 472 Status result; | 451 Status result; |
| 473 int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | | 452 int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | |
| 474 ::base::PLATFORM_FILE_READ | | 453 ::base::PLATFORM_FILE_READ | |
| 475 ::base::PLATFORM_FILE_WRITE | | 454 ::base::PLATFORM_FILE_WRITE | |
| 476 ::base::PLATFORM_FILE_EXCLUSIVE_READ | | 455 ::base::PLATFORM_FILE_EXCLUSIVE_READ | |
| 477 ::base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 456 ::base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
| 478 bool created; | 457 bool created; |
| 479 ::base::PlatformFileError error_code; | 458 ::base::PlatformFileError error_code; |
| 480 ::base::PlatformFile file = ::base::CreatePlatformFile( | 459 ::base::PlatformFile file = ::base::CreatePlatformFile( |
| 481 CreateFilePath(fname), flags, &created, &error_code); | 460 CreateFilePath(fname), flags, &created, &error_code); |
| 482 if (error_code != ::base::PLATFORM_FILE_OK) { | 461 if (error_code != ::base::PLATFORM_FILE_OK) { |
| 483 result = Status::IOError(fname, PlatformFileErrorString(error_code)); | 462 result = Status::IOError(fname, PlatformFileErrorString(error_code)); |
| 484 uma_logger_->RecordErrorAt(kLockFile); | 463 RecordErrorAt(kLockFile); |
| 485 } else { | 464 } else { |
| 486 ChromiumFileLock* my_lock = new ChromiumFileLock; | 465 ChromiumFileLock* my_lock = new ChromiumFileLock; |
| 487 my_lock->file_ = file; | 466 my_lock->file_ = file; |
| 488 *lock = my_lock; | 467 *lock = my_lock; |
| 489 } | 468 } |
| 490 return result; | 469 return result; |
| 491 } | 470 } |
| 492 | 471 |
| 493 virtual Status UnlockFile(FileLock* lock) { | 472 virtual Status UnlockFile(FileLock* lock) { |
| 494 ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock); | 473 ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock); |
| 495 Status result; | 474 Status result; |
| 496 if (!::base::ClosePlatformFile(my_lock->file_)) { | 475 if (!::base::ClosePlatformFile(my_lock->file_)) { |
| 497 result = Status::IOError("Could not close lock file."); | 476 result = Status::IOError("Could not close lock file."); |
| 498 uma_logger_->RecordErrorAt(kUnlockFile); | 477 RecordErrorAt(kUnlockFile); |
| 499 } | 478 } |
| 500 delete my_lock; | 479 delete my_lock; |
| 501 return result; | 480 return result; |
| 502 } | 481 } |
| 503 | 482 |
| 504 virtual void Schedule(void (*function)(void*), void* arg); | 483 virtual void Schedule(void (*function)(void*), void* arg); |
| 505 | 484 |
| 506 virtual void StartThread(void (*function)(void* arg), void* arg); | 485 virtual void StartThread(void (*function)(void* arg), void* arg); |
| 507 | 486 |
| 508 virtual std::string UserIdentifier() { | 487 virtual std::string UserIdentifier() { |
| 509 #if defined(OS_WIN) | 488 #if defined(OS_WIN) |
| 510 std::wstring user_sid; | 489 std::wstring user_sid; |
| 511 bool ret = ::base::win::GetUserSidString(&user_sid); | 490 bool ret = ::base::win::GetUserSidString(&user_sid); |
| 512 DCHECK(ret); | 491 DCHECK(ret); |
| 513 return UTF16ToUTF8(user_sid); | 492 return UTF16ToUTF8(user_sid); |
| 514 #else | 493 #else |
| 515 char buf[100]; | 494 char buf[100]; |
| 516 snprintf(buf, sizeof(buf), "%d", int(geteuid())); | 495 snprintf(buf, sizeof(buf), "%d", int(geteuid())); |
| 517 return buf; | 496 return buf; |
| 518 #endif | 497 #endif |
| 519 } | 498 } |
| 520 | 499 |
| 521 virtual Status GetTestDirectory(std::string* path) { | 500 virtual Status GetTestDirectory(std::string* path) { |
| 522 mu_.Acquire(); | 501 mu_.Acquire(); |
| 523 if (test_directory_.empty()) { | 502 if (test_directory_.empty()) { |
| 524 if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix, | 503 if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix, |
| 525 &test_directory_)) { | 504 &test_directory_)) { |
| 526 mu_.Release(); | 505 mu_.Release(); |
| 527 uma_logger_->RecordErrorAt(kGetTestDirectory); | 506 RecordErrorAt(kGetTestDirectory); |
| 528 return Status::IOError("Could not create temp directory."); | 507 return Status::IOError("Could not create temp directory."); |
| 529 } | 508 } |
| 530 } | 509 } |
| 531 *path = FilePathToString(test_directory_); | 510 *path = FilePathToString(test_directory_); |
| 532 mu_.Release(); | 511 mu_.Release(); |
| 533 return Status::OK(); | 512 return Status::OK(); |
| 534 } | 513 } |
| 535 | 514 |
| 536 virtual Status NewLogger(const std::string& fname, Logger** result) { | 515 virtual Status NewLogger(const std::string& fname, Logger** result) { |
| 537 FILE* f = fopen_internal(fname.c_str(), "w"); | 516 FILE* f = fopen_internal(fname.c_str(), "w"); |
| 538 if (f == NULL) { | 517 if (f == NULL) { |
| 539 *result = NULL; | 518 *result = NULL; |
| 540 uma_logger_->RecordErrorAt(kNewLogger); | 519 RecordErrorAt(kNewLogger); |
| 541 return Status::IOError(fname, strerror(errno)); | 520 return Status::IOError(fname, strerror(errno)); |
| 542 } else { | 521 } else { |
| 543 if (!sync_parent(fname)) { | 522 if (!sync_parent(fname)) { |
| 544 fclose(f); | 523 fclose(f); |
| 545 return Status::IOError(fname, strerror(errno)); | 524 return Status::IOError(fname, strerror(errno)); |
| 546 } | 525 } |
| 547 *result = new ChromiumLogger(f); | 526 *result = new ChromiumLogger(f); |
| 548 return Status::OK(); | 527 return Status::OK(); |
| 549 } | 528 } |
| 550 } | 529 } |
| 551 | 530 |
| 552 virtual uint64_t NowMicros() { | 531 virtual uint64_t NowMicros() { |
| 553 return ::base::TimeTicks::Now().ToInternalValue(); | 532 return ::base::TimeTicks::Now().ToInternalValue(); |
| 554 } | 533 } |
| 555 | 534 |
| 556 virtual void SleepForMicroseconds(int micros) { | 535 virtual void SleepForMicroseconds(int micros) { |
| 557 // Round up to the next millisecond. | 536 // Round up to the next millisecond. |
| 558 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); | 537 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); |
| 559 } | 538 } |
| 560 | 539 |
| 540 void RecordErrorAt(UmaEntry entry) const { |
| 541 io_error_histogram_->Add(entry); |
| 542 } |
| 543 |
| 544 void LogRandomAccessFileError(base::PlatformFileError error_code) const { |
| 545 DCHECK(error_code < 0); |
| 546 random_access_file_histogram_->Add(-error_code); |
| 547 } |
| 548 |
| 561 protected: | 549 protected: |
| 562 scoped_ptr<UMALogger> uma_logger_; | 550 void InitHistograms(const std::string& uma_title); |
| 563 | 551 |
| 564 private: | 552 private: |
| 565 // BGThread() is the body of the background thread | 553 // BGThread() is the body of the background thread |
| 566 void BGThread(); | 554 void BGThread(); |
| 567 static void BGThreadWrapper(void* arg) { | 555 static void BGThreadWrapper(void* arg) { |
| 568 reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); | 556 reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); |
| 569 } | 557 } |
| 570 | 558 |
| 571 FilePath test_directory_; | 559 FilePath test_directory_; |
| 572 | 560 |
| 573 size_t page_size_; | 561 size_t page_size_; |
| 574 ::base::Lock mu_; | 562 ::base::Lock mu_; |
| 575 ::base::ConditionVariable bgsignal_; | 563 ::base::ConditionVariable bgsignal_; |
| 576 bool started_bgthread_; | 564 bool started_bgthread_; |
| 577 | 565 |
| 578 // Entry per Schedule() call | 566 // Entry per Schedule() call |
| 579 struct BGItem { void* arg; void (*function)(void*); }; | 567 struct BGItem { void* arg; void (*function)(void*); }; |
| 580 typedef std::deque<BGItem> BGQueue; | 568 typedef std::deque<BGItem> BGQueue; |
| 581 BGQueue queue_; | 569 BGQueue queue_; |
| 570 |
| 571 base::Histogram* io_error_histogram_; |
| 572 base::Histogram* random_access_file_histogram_; |
| 582 }; | 573 }; |
| 583 | 574 |
| 584 ChromiumEnv::ChromiumEnv() | 575 ChromiumEnv::ChromiumEnv() |
| 585 : page_size_(::base::SysInfo::VMAllocationGranularity()), | 576 : page_size_(::base::SysInfo::VMAllocationGranularity()), |
| 586 bgsignal_(&mu_), | 577 bgsignal_(&mu_), |
| 587 started_bgthread_(false), | 578 started_bgthread_(false) { |
| 588 uma_logger_(new UMALogger("LevelDBEnv")) { | 579 InitHistograms("LevelDBEnv"); |
| 580 } |
| 581 |
| 582 void ChromiumEnv::InitHistograms(const std::string& uma_title) { |
| 583 std::string uma_name(uma_title); |
| 584 uma_name.append(".IOError"); |
| 585 // Note: The calls to FactoryGet aren't thread-safe. It's ok to call them here |
| 586 // because this method is only called from LazyInstance, which provides |
| 587 // thread-safety. |
| 588 io_error_histogram_ = base::LinearHistogram::FactoryGet(uma_name, 1, |
| 589 kNumEntries, kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag); |
| 590 |
| 591 uma_name.append(".RandomAccessFile"); |
| 592 random_access_file_histogram_ = base::LinearHistogram::FactoryGet(uma_name, 1, |
| 593 -base::PLATFORM_FILE_ERROR_MAX, -base::PLATFORM_FILE_ERROR_MAX + 1, |
| 594 base::Histogram::kUmaTargetedHistogramFlag); |
| 589 } | 595 } |
| 590 | 596 |
| 591 class Thread : public ::base::PlatformThread::Delegate { | 597 class Thread : public ::base::PlatformThread::Delegate { |
| 592 public: | 598 public: |
| 593 Thread(void (*function)(void* arg), void* arg) | 599 Thread(void (*function)(void* arg), void* arg) |
| 594 : function_(function), arg_(arg) { | 600 : function_(function), arg_(arg) { |
| 595 ::base::PlatformThreadHandle handle; | 601 ::base::PlatformThreadHandle handle; |
| 596 bool success = ::base::PlatformThread::Create(0, this, &handle); | 602 bool success = ::base::PlatformThread::Create(0, this, &handle); |
| 597 DCHECK(success); | 603 DCHECK(success); |
| 598 } | 604 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 } | 653 } |
| 648 } | 654 } |
| 649 | 655 |
| 650 void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { | 656 void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { |
| 651 new Thread(function, arg); // Will self-delete. | 657 new Thread(function, arg); // Will self-delete. |
| 652 } | 658 } |
| 653 | 659 |
| 654 class IDBEnv : public ChromiumEnv { | 660 class IDBEnv : public ChromiumEnv { |
| 655 public: | 661 public: |
| 656 IDBEnv() : ChromiumEnv() { | 662 IDBEnv() : ChromiumEnv() { |
| 657 uma_logger_.reset(new UMALogger("LevelDBEnv.IDB")); | 663 InitHistograms("LevelDBEnv.IDB"); |
| 658 } | 664 } |
| 659 }; | 665 }; |
| 660 | 666 |
| 661 ::base::LazyInstance<IDBEnv>::Leaky | 667 ::base::LazyInstance<IDBEnv>::Leaky |
| 662 idb_env = LAZY_INSTANCE_INITIALIZER; | 668 idb_env = LAZY_INSTANCE_INITIALIZER; |
| 663 | 669 |
| 664 ::base::LazyInstance<ChromiumEnv>::Leaky | 670 ::base::LazyInstance<ChromiumEnv>::Leaky |
| 665 default_env = LAZY_INSTANCE_INITIALIZER; | 671 default_env = LAZY_INSTANCE_INITIALIZER; |
| 666 | 672 |
| 667 } | 673 } |
| 668 | 674 |
| 669 Env* IDBEnv() { | 675 Env* IDBEnv() { |
| 670 return idb_env.Pointer(); | 676 return idb_env.Pointer(); |
| 671 } | 677 } |
| 672 | 678 |
| 673 Env* Env::Default() { | 679 Env* Env::Default() { |
| 674 return default_env.Pointer(); | 680 return default_env.Pointer(); |
| 675 } | 681 } |
| 676 | 682 |
| 677 } | 683 } |
| OLD | NEW |