| 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 <errno.h> | |
| 6 #include <stdio.h> | |
| 7 #include <string.h> | |
| 8 | |
| 9 #include <deque> | |
| 10 | |
| 11 #include "base/at_exit.h" | |
| 12 #include "base/debug/trace_event.h" | 5 #include "base/debug/trace_event.h" |
| 13 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 14 #include "base/files/file_enumerator.h" | |
| 15 #include "base/files/file_path.h" | |
| 16 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 17 #include "base/memory/ref_counted.h" | |
| 18 #include "base/message_loop/message_loop.h" | |
| 19 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 20 #include "base/platform_file.h" | |
| 21 #include "base/posix/eintr_wrapper.h" | |
| 22 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 23 #include "base/synchronization/lock.h" | 10 #include "env_chromium_stdio.h" |
| 24 #include "base/sys_info.h" | |
| 25 #include "base/threading/platform_thread.h" | |
| 26 #include "base/threading/thread.h" | |
| 27 #include "chromium_logger.h" | |
| 28 #include "env_chromium.h" | |
| 29 #include "leveldb/env.h" | |
| 30 #include "leveldb/slice.h" | |
| 31 #include "port/port.h" | |
| 32 #include "third_party/re2/re2/re2.h" | 11 #include "third_party/re2/re2/re2.h" |
| 33 #include "util/logging.h" | |
| 34 | 12 |
| 35 #if defined(OS_WIN) | 13 #if defined(OS_WIN) |
| 36 #include <io.h> | 14 #include <io.h> |
| 15 #include "base/command_line.h" |
| 37 #include "base/win/win_util.h" | 16 #include "base/win/win_util.h" |
| 38 #endif | 17 #include "env_chromium_win.h" |
| 39 | |
| 40 #if defined(OS_POSIX) | |
| 41 #include <dirent.h> | |
| 42 #include <fcntl.h> | |
| 43 #include <sys/resource.h> | |
| 44 #include <sys/time.h> | |
| 45 #endif | 18 #endif |
| 46 | 19 |
| 47 using namespace leveldb; | 20 using namespace leveldb; |
| 48 | 21 |
| 49 namespace leveldb_env { | 22 namespace leveldb_env { |
| 50 | 23 |
| 51 namespace { | 24 namespace { |
| 52 | 25 |
| 53 const base::FilePath::CharType backup_table_extension[] = | 26 const base::FilePath::CharType backup_table_extension[] = |
| 54 FILE_PATH_LITERAL(".bak"); | 27 FILE_PATH_LITERAL(".bak"); |
| 55 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); | 28 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); |
| 56 | 29 |
| 57 #if (defined(OS_POSIX) && !defined(OS_LINUX)) || defined(OS_WIN) | |
| 58 // The following are glibc-specific | |
| 59 | |
| 60 size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) { | |
| 61 return fread(ptr, size, n, file); | |
| 62 } | |
| 63 | |
| 64 size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *file) { | |
| 65 return fwrite(ptr, size, n, file); | |
| 66 } | |
| 67 | |
| 68 int fflush_unlocked(FILE *file) { | |
| 69 return fflush(file); | |
| 70 } | |
| 71 | |
| 72 #if !defined(OS_ANDROID) | |
| 73 int fdatasync(int fildes) { | |
| 74 #if defined(OS_WIN) | |
| 75 return _commit(fildes); | |
| 76 #else | |
| 77 return HANDLE_EINTR(fsync(fildes)); | |
| 78 #endif | |
| 79 } | |
| 80 #endif | |
| 81 | |
| 82 #endif | |
| 83 | |
| 84 // Wide-char safe fopen wrapper. | |
| 85 FILE* fopen_internal(const char* fname, const char* mode) { | |
| 86 #if defined(OS_WIN) | |
| 87 return _wfopen(base::UTF8ToUTF16(fname).c_str(), | |
| 88 base::ASCIIToUTF16(mode).c_str()); | |
| 89 #else | |
| 90 return fopen(fname, mode); | |
| 91 #endif | |
| 92 } | |
| 93 | |
| 94 base::FilePath CreateFilePath(const std::string& file_path) { | |
| 95 #if defined(OS_WIN) | |
| 96 return base::FilePath(base::UTF8ToUTF16(file_path)); | |
| 97 #else | |
| 98 return base::FilePath(file_path); | |
| 99 #endif | |
| 100 } | |
| 101 | |
| 102 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] | 30 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] |
| 103 = FILE_PATH_LITERAL("leveldb-test-"); | 31 = FILE_PATH_LITERAL("leveldb-test-"); |
| 104 | 32 |
| 105 const char* PlatformFileErrorString(const ::base::PlatformFileError& error) { | |
| 106 switch (error) { | |
| 107 case ::base::PLATFORM_FILE_ERROR_FAILED: | |
| 108 return "No further details."; | |
| 109 case ::base::PLATFORM_FILE_ERROR_IN_USE: | |
| 110 return "File currently in use."; | |
| 111 case ::base::PLATFORM_FILE_ERROR_EXISTS: | |
| 112 return "File already exists."; | |
| 113 case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: | |
| 114 return "File not found."; | |
| 115 case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED: | |
| 116 return "Access denied."; | |
| 117 case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED: | |
| 118 return "Too many files open."; | |
| 119 case ::base::PLATFORM_FILE_ERROR_NO_MEMORY: | |
| 120 return "Out of memory."; | |
| 121 case ::base::PLATFORM_FILE_ERROR_NO_SPACE: | |
| 122 return "No space left on drive."; | |
| 123 case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: | |
| 124 return "Not a directory."; | |
| 125 case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION: | |
| 126 return "Invalid operation."; | |
| 127 case ::base::PLATFORM_FILE_ERROR_SECURITY: | |
| 128 return "Security error."; | |
| 129 case ::base::PLATFORM_FILE_ERROR_ABORT: | |
| 130 return "File operation aborted."; | |
| 131 case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE: | |
| 132 return "The supplied path was not a file."; | |
| 133 case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY: | |
| 134 return "The file was not empty."; | |
| 135 case ::base::PLATFORM_FILE_ERROR_INVALID_URL: | |
| 136 return "Invalid URL."; | |
| 137 case ::base::PLATFORM_FILE_ERROR_IO: | |
| 138 return "OS or hardware error."; | |
| 139 case ::base::PLATFORM_FILE_OK: | |
| 140 return "OK."; | |
| 141 case ::base::PLATFORM_FILE_ERROR_MAX: | |
| 142 NOTREACHED(); | |
| 143 } | |
| 144 NOTIMPLEMENTED(); | |
| 145 return "Unknown error."; | |
| 146 } | |
| 147 | |
| 148 class ChromiumSequentialFile: public SequentialFile { | |
| 149 private: | |
| 150 std::string filename_; | |
| 151 FILE* file_; | |
| 152 const UMALogger* uma_logger_; | |
| 153 | |
| 154 public: | |
| 155 ChromiumSequentialFile(const std::string& fname, FILE* f, | |
| 156 const UMALogger* uma_logger) | |
| 157 : filename_(fname), file_(f), uma_logger_(uma_logger) { } | |
| 158 virtual ~ChromiumSequentialFile() { fclose(file_); } | |
| 159 | |
| 160 virtual Status Read(size_t n, Slice* result, char* scratch) { | |
| 161 Status s; | |
| 162 size_t r = fread_unlocked(scratch, 1, n, file_); | |
| 163 *result = Slice(scratch, r); | |
| 164 if (r < n) { | |
| 165 if (feof(file_)) { | |
| 166 // We leave status as ok if we hit the end of the file | |
| 167 } else { | |
| 168 // A partial read with an error: return a non-ok status | |
| 169 s = MakeIOError(filename_, strerror(errno), kSequentialFileRead, errno); | |
| 170 uma_logger_->RecordErrorAt(kSequentialFileRead); | |
| 171 } | |
| 172 } | |
| 173 return s; | |
| 174 } | |
| 175 | |
| 176 virtual Status Skip(uint64_t n) { | |
| 177 if (fseek(file_, n, SEEK_CUR)) { | |
| 178 int saved_errno = errno; | |
| 179 uma_logger_->RecordErrorAt(kSequentialFileSkip); | |
| 180 return MakeIOError( | |
| 181 filename_, strerror(saved_errno), kSequentialFileSkip, saved_errno); | |
| 182 } | |
| 183 return Status::OK(); | |
| 184 } | |
| 185 }; | |
| 186 | |
| 187 class ChromiumRandomAccessFile: public RandomAccessFile { | |
| 188 private: | |
| 189 std::string filename_; | |
| 190 ::base::PlatformFile file_; | |
| 191 const UMALogger* uma_logger_; | |
| 192 | |
| 193 public: | |
| 194 ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file, | |
| 195 const UMALogger* uma_logger) | |
| 196 : filename_(fname), file_(file), uma_logger_(uma_logger) { } | |
| 197 virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } | |
| 198 | |
| 199 virtual Status Read(uint64_t offset, size_t n, Slice* result, | |
| 200 char* scratch) const { | |
| 201 Status s; | |
| 202 int r = ::base::ReadPlatformFile(file_, offset, scratch, n); | |
| 203 *result = Slice(scratch, (r < 0) ? 0 : r); | |
| 204 if (r < 0) { | |
| 205 // An error: return a non-ok status | |
| 206 s = MakeIOError( | |
| 207 filename_, "Could not perform read", kRandomAccessFileRead); | |
| 208 uma_logger_->RecordErrorAt(kRandomAccessFileRead); | |
| 209 } | |
| 210 return s; | |
| 211 } | |
| 212 }; | |
| 213 | |
| 214 class ChromiumFileLock : public FileLock { | 33 class ChromiumFileLock : public FileLock { |
| 215 public: | 34 public: |
| 216 ::base::PlatformFile file_; | 35 ::base::PlatformFile file_; |
| 217 std::string name_; | 36 std::string name_; |
| 218 }; | 37 }; |
| 219 | 38 |
| 220 class Retrier { | 39 class Retrier { |
| 221 public: | 40 public: |
| 222 Retrier(MethodID method, RetrierProvider* provider) | 41 Retrier(MethodID method, RetrierProvider* provider) |
| 223 : start_(base::TimeTicks::Now()), | 42 : start_(base::TimeTicks::Now()), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 254 base::TimeTicks start_; | 73 base::TimeTicks start_; |
| 255 base::TimeTicks limit_; | 74 base::TimeTicks limit_; |
| 256 base::TimeTicks last_; | 75 base::TimeTicks last_; |
| 257 base::TimeDelta time_to_sleep_; | 76 base::TimeDelta time_to_sleep_; |
| 258 bool success_; | 77 bool success_; |
| 259 MethodID method_; | 78 MethodID method_; |
| 260 base::PlatformFileError last_error_; | 79 base::PlatformFileError last_error_; |
| 261 RetrierProvider* provider_; | 80 RetrierProvider* provider_; |
| 262 }; | 81 }; |
| 263 | 82 |
| 264 class IDBEnv : public ChromiumEnv { | 83 class IDBEnvStdio : public ChromiumEnvStdio { |
| 265 public: | 84 public: |
| 266 IDBEnv() : ChromiumEnv() { | 85 IDBEnvStdio() : ChromiumEnvStdio() { |
| 267 name_ = "LevelDBEnv.IDB"; | 86 name_ = "LevelDBEnv.IDB"; |
| 268 make_backup_ = true; | 87 make_backup_ = true; |
| 269 } | 88 } |
| 270 }; | 89 }; |
| 271 | 90 |
| 272 ::base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; | 91 #if defined(OS_WIN) |
| 92 class IDBEnvWin : public ChromiumEnvWin { |
| 93 public: |
| 94 IDBEnvWin() : ChromiumEnvWin() { |
| 95 name_ = "LevelDBEnv.IDB"; |
| 96 make_backup_ = true; |
| 97 } |
| 98 }; |
| 99 #endif |
| 273 | 100 |
| 274 ::base::LazyInstance<ChromiumEnv>::Leaky default_env = | 101 #if defined(OS_WIN) |
| 102 ::base::LazyInstance<IDBEnvWin>::Leaky idb_env = |
| 103 LAZY_INSTANCE_INITIALIZER; |
| 104 #else |
| 105 ::base::LazyInstance<IDBEnvStdio>::Leaky idb_env = |
| 106 LAZY_INSTANCE_INITIALIZER; |
| 107 #endif |
| 108 |
| 109 ::base::LazyInstance<ChromiumEnvStdio>::Leaky default_env = |
| 275 LAZY_INSTANCE_INITIALIZER; | 110 LAZY_INSTANCE_INITIALIZER; |
| 276 | 111 |
| 277 } // unnamed namespace | 112 } // unnamed namespace |
| 278 | 113 |
| 279 const char* MethodIDToString(MethodID method) { | 114 const char* MethodIDToString(MethodID method) { |
| 280 switch (method) { | 115 switch (method) { |
| 281 case kSequentialFileRead: | 116 case kSequentialFileRead: |
| 282 return "SequentialFileRead"; | 117 return "SequentialFileRead"; |
| 283 case kSequentialFileSkip: | 118 case kSequentialFileSkip: |
| 284 return "SequentialFileSkip"; | 119 return "SequentialFileSkip"; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 322 } |
| 488 | 323 |
| 489 std::string FilePathToString(const base::FilePath& file_path) { | 324 std::string FilePathToString(const base::FilePath& file_path) { |
| 490 #if defined(OS_WIN) | 325 #if defined(OS_WIN) |
| 491 return base::UTF16ToUTF8(file_path.value()); | 326 return base::UTF16ToUTF8(file_path.value()); |
| 492 #else | 327 #else |
| 493 return file_path.value(); | 328 return file_path.value(); |
| 494 #endif | 329 #endif |
| 495 } | 330 } |
| 496 | 331 |
| 497 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, | 332 base::FilePath ChromiumEnv::CreateFilePath(const std::string& file_path) { |
| 498 FILE* f, | 333 #if defined(OS_WIN) |
| 499 const UMALogger* uma_logger, | 334 return base::FilePath(base::UTF8ToUTF16(file_path)); |
| 500 WriteTracker* tracker, | 335 #else |
| 501 bool make_backup) | 336 return base::FilePath(file_path); |
| 502 : filename_(fname), | 337 #endif |
| 503 file_(f), | |
| 504 uma_logger_(uma_logger), | |
| 505 tracker_(tracker), | |
| 506 file_type_(kOther), | |
| 507 make_backup_(make_backup) { | |
| 508 base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); | |
| 509 if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) | |
| 510 file_type_ = kManifest; | |
| 511 else if (path.MatchesExtension(table_extension)) | |
| 512 file_type_ = kTable; | |
| 513 if (file_type_ != kManifest) | |
| 514 tracker_->DidCreateNewFile(filename_); | |
| 515 parent_dir_ = FilePathToString(CreateFilePath(fname).DirName()); | |
| 516 } | 338 } |
| 517 | 339 |
| 518 ChromiumWritableFile::~ChromiumWritableFile() { | 340 bool ChromiumEnv::MakeBackup(const std::string& fname) { |
| 519 if (file_ != NULL) { | |
| 520 // Ignoring any potential errors | |
| 521 fclose(file_); | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 Status ChromiumWritableFile::SyncParent() { | |
| 526 Status s; | |
| 527 #if !defined(OS_WIN) | |
| 528 TRACE_EVENT0("leveldb", "SyncParent"); | |
| 529 | |
| 530 int parent_fd = | |
| 531 HANDLE_EINTR(open(parent_dir_.c_str(), O_RDONLY)); | |
| 532 if (parent_fd < 0) { | |
| 533 int saved_errno = errno; | |
| 534 return MakeIOError( | |
| 535 parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); | |
| 536 } | |
| 537 if (HANDLE_EINTR(fsync(parent_fd)) != 0) { | |
| 538 int saved_errno = errno; | |
| 539 s = MakeIOError( | |
| 540 parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); | |
| 541 }; | |
| 542 close(parent_fd); | |
| 543 #endif | |
| 544 return s; | |
| 545 } | |
| 546 | |
| 547 Status ChromiumWritableFile::Append(const Slice& data) { | |
| 548 if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { | |
| 549 Status s = SyncParent(); | |
| 550 if (!s.ok()) | |
| 551 return s; | |
| 552 tracker_->DidSyncDir(filename_); | |
| 553 } | |
| 554 | |
| 555 size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); | |
| 556 if (r != data.size()) { | |
| 557 int saved_errno = errno; | |
| 558 uma_logger_->RecordOSError(kWritableFileAppend, saved_errno); | |
| 559 return MakeIOError( | |
| 560 filename_, strerror(saved_errno), kWritableFileAppend, saved_errno); | |
| 561 } | |
| 562 return Status::OK(); | |
| 563 } | |
| 564 | |
| 565 Status ChromiumWritableFile::Close() { | |
| 566 Status result; | |
| 567 if (fclose(file_) != 0) { | |
| 568 result = MakeIOError(filename_, strerror(errno), kWritableFileClose, errno); | |
| 569 uma_logger_->RecordErrorAt(kWritableFileClose); | |
| 570 } | |
| 571 file_ = NULL; | |
| 572 return result; | |
| 573 } | |
| 574 | |
| 575 Status ChromiumWritableFile::Flush() { | |
| 576 Status result; | |
| 577 if (HANDLE_EINTR(fflush_unlocked(file_))) { | |
| 578 int saved_errno = errno; | |
| 579 result = MakeIOError( | |
| 580 filename_, strerror(saved_errno), kWritableFileFlush, saved_errno); | |
| 581 uma_logger_->RecordOSError(kWritableFileFlush, saved_errno); | |
| 582 } | |
| 583 return result; | |
| 584 } | |
| 585 | |
| 586 static bool MakeBackup(const std::string& fname) { | |
| 587 base::FilePath original_table_name = CreateFilePath(fname); | 341 base::FilePath original_table_name = CreateFilePath(fname); |
| 588 base::FilePath backup_table_name = | 342 base::FilePath backup_table_name = |
| 589 original_table_name.ReplaceExtension(backup_table_extension); | 343 original_table_name.ReplaceExtension(backup_table_extension); |
| 590 return base::CopyFile(original_table_name, backup_table_name); | 344 return base::CopyFile(original_table_name, backup_table_name); |
| 591 } | 345 } |
| 592 | 346 |
| 593 Status ChromiumWritableFile::Sync() { | 347 bool ChromiumEnv::HasTableExtension(const base::FilePath& path) |
| 594 TRACE_EVENT0("leveldb", "ChromiumEnv::Sync"); | 348 { |
| 595 Status result; | 349 return path.MatchesExtension(table_extension); |
| 596 int error = 0; | |
| 597 | |
| 598 if (HANDLE_EINTR(fflush_unlocked(file_))) | |
| 599 error = errno; | |
| 600 // Sync even if fflush gave an error; perhaps the data actually got out, | |
| 601 // even though something went wrong. | |
| 602 if (fdatasync(fileno(file_)) && !error) | |
| 603 error = errno; | |
| 604 // Report the first error we found. | |
| 605 if (error) { | |
| 606 result = MakeIOError(filename_, strerror(error), kWritableFileSync, error); | |
| 607 uma_logger_->RecordErrorAt(kWritableFileSync); | |
| 608 } else if (make_backup_ && file_type_ == kTable) { | |
| 609 bool success = MakeBackup(filename_); | |
| 610 uma_logger_->RecordBackupResult(success); | |
| 611 } | |
| 612 return result; | |
| 613 } | 350 } |
| 614 | 351 |
| 615 ChromiumEnv::ChromiumEnv() | 352 ChromiumEnv::ChromiumEnv() |
| 616 : name_("LevelDBEnv"), | 353 : name_("LevelDBEnv"), |
| 617 make_backup_(false), | 354 make_backup_(false), |
| 618 bgsignal_(&mu_), | 355 bgsignal_(&mu_), |
| 619 started_bgthread_(false), | 356 started_bgthread_(false), |
| 620 kMaxRetryTimeMillis(1000) { | 357 kMaxRetryTimeMillis(1000) { |
| 621 } | 358 } |
| 622 | 359 |
| 623 ChromiumEnv::~ChromiumEnv() { | 360 ChromiumEnv::~ChromiumEnv() { |
| 624 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to | 361 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to |
| 625 // ensure that behavior isn't accidentally changed, but there's an instance in | 362 // ensure that behavior isn't accidentally changed, but there's an instance in |
| 626 // a unit test that is deleted. | 363 // a unit test that is deleted. |
| 627 } | 364 } |
| 628 | 365 |
| 629 Status ChromiumEnv::NewSequentialFile(const std::string& fname, | |
| 630 SequentialFile** result) { | |
| 631 FILE* f = fopen_internal(fname.c_str(), "rb"); | |
| 632 if (f == NULL) { | |
| 633 *result = NULL; | |
| 634 int saved_errno = errno; | |
| 635 RecordOSError(kNewSequentialFile, saved_errno); | |
| 636 return MakeIOError( | |
| 637 fname, strerror(saved_errno), kNewSequentialFile, saved_errno); | |
| 638 } else { | |
| 639 *result = new ChromiumSequentialFile(fname, f, this); | |
| 640 return Status::OK(); | |
| 641 } | |
| 642 } | |
| 643 | |
| 644 void ChromiumEnv::RecordOpenFilesLimit(const std::string& type) { | |
| 645 #if defined(OS_POSIX) | |
| 646 struct rlimit nofile; | |
| 647 if (getrlimit(RLIMIT_NOFILE, &nofile)) | |
| 648 return; | |
| 649 GetMaxFDHistogram(type)->Add(nofile.rlim_cur); | |
| 650 #endif | |
| 651 } | |
| 652 | |
| 653 Status ChromiumEnv::NewRandomAccessFile(const std::string& fname, | |
| 654 RandomAccessFile** result) { | |
| 655 int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; | |
| 656 bool created; | |
| 657 ::base::PlatformFileError error_code; | |
| 658 ::base::PlatformFile file = ::base::CreatePlatformFile( | |
| 659 CreateFilePath(fname), flags, &created, &error_code); | |
| 660 if (error_code == ::base::PLATFORM_FILE_OK) { | |
| 661 *result = new ChromiumRandomAccessFile(fname, file, this); | |
| 662 RecordOpenFilesLimit("Success"); | |
| 663 return Status::OK(); | |
| 664 } | |
| 665 if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED) | |
| 666 RecordOpenFilesLimit("TooManyOpened"); | |
| 667 else | |
| 668 RecordOpenFilesLimit("OtherError"); | |
| 669 *result = NULL; | |
| 670 RecordOSError(kNewRandomAccessFile, error_code); | |
| 671 return MakeIOError(fname, | |
| 672 PlatformFileErrorString(error_code), | |
| 673 kNewRandomAccessFile, | |
| 674 error_code); | |
| 675 } | |
| 676 | |
| 677 Status ChromiumEnv::NewWritableFile(const std::string& fname, | |
| 678 WritableFile** result) { | |
| 679 *result = NULL; | |
| 680 FILE* f = fopen_internal(fname.c_str(), "wb"); | |
| 681 if (f == NULL) { | |
| 682 int saved_errno = errno; | |
| 683 RecordErrorAt(kNewWritableFile); | |
| 684 return MakeIOError( | |
| 685 fname, strerror(saved_errno), kNewWritableFile, saved_errno); | |
| 686 } else { | |
| 687 *result = new ChromiumWritableFile(fname, f, this, this, make_backup_); | |
| 688 return Status::OK(); | |
| 689 } | |
| 690 } | |
| 691 | |
| 692 bool ChromiumEnv::FileExists(const std::string& fname) { | 366 bool ChromiumEnv::FileExists(const std::string& fname) { |
| 693 return ::base::PathExists(CreateFilePath(fname)); | 367 return ::base::PathExists(CreateFilePath(fname)); |
| 694 } | 368 } |
| 695 | 369 |
| 370 const char* ChromiumEnv::PlatformFileErrorString(const ::base::PlatformFileError
& error) { |
| 371 switch (error) { |
| 372 case ::base::PLATFORM_FILE_ERROR_FAILED: |
| 373 return "No further details."; |
| 374 case ::base::PLATFORM_FILE_ERROR_IN_USE: |
| 375 return "File currently in use."; |
| 376 case ::base::PLATFORM_FILE_ERROR_EXISTS: |
| 377 return "File already exists."; |
| 378 case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: |
| 379 return "File not found."; |
| 380 case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED: |
| 381 return "Access denied."; |
| 382 case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED: |
| 383 return "Too many files open."; |
| 384 case ::base::PLATFORM_FILE_ERROR_NO_MEMORY: |
| 385 return "Out of memory."; |
| 386 case ::base::PLATFORM_FILE_ERROR_NO_SPACE: |
| 387 return "No space left on drive."; |
| 388 case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: |
| 389 return "Not a directory."; |
| 390 case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION: |
| 391 return "Invalid operation."; |
| 392 case ::base::PLATFORM_FILE_ERROR_SECURITY: |
| 393 return "Security error."; |
| 394 case ::base::PLATFORM_FILE_ERROR_ABORT: |
| 395 return "File operation aborted."; |
| 396 case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE: |
| 397 return "The supplied path was not a file."; |
| 398 case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY: |
| 399 return "The file was not empty."; |
| 400 case ::base::PLATFORM_FILE_ERROR_INVALID_URL: |
| 401 return "Invalid URL."; |
| 402 case ::base::PLATFORM_FILE_ERROR_IO: |
| 403 return "OS or hardware error."; |
| 404 case ::base::PLATFORM_FILE_OK: |
| 405 return "OK."; |
| 406 case ::base::PLATFORM_FILE_ERROR_MAX: |
| 407 NOTREACHED(); |
| 408 } |
| 409 NOTIMPLEMENTED(); |
| 410 return "Unknown error."; |
| 411 } |
| 412 |
| 696 base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { | 413 base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { |
| 697 base::FilePath table_name = | 414 base::FilePath table_name = |
| 698 base_name.AddExtension(table_extension); | 415 base_name.AddExtension(table_extension); |
| 699 bool result = base::CopyFile(base_name.AddExtension(backup_table_extension), | 416 bool result = base::CopyFile(base_name.AddExtension(backup_table_extension), |
| 700 table_name); | 417 table_name); |
| 701 std::string uma_name(name_); | 418 std::string uma_name(name_); |
| 702 uma_name.append(".TableRestore"); | 419 uma_name.append(".TableRestore"); |
| 703 base::BooleanHistogram::FactoryGet( | 420 base::BooleanHistogram::FactoryGet( |
| 704 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); | 421 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); |
| 705 return table_name; | 422 return table_name; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir); | 456 base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir); |
| 740 for (std::set<base::FilePath>::iterator it = backups_only.begin(); | 457 for (std::set<base::FilePath>::iterator it = backups_only.begin(); |
| 741 it != backups_only.end(); | 458 it != backups_only.end(); |
| 742 ++it) { | 459 ++it) { |
| 743 base::FilePath restored_table_name = | 460 base::FilePath restored_table_name = |
| 744 RestoreFromBackup(dir_filepath.Append(*it)); | 461 RestoreFromBackup(dir_filepath.Append(*it)); |
| 745 result->push_back(FilePathToString(restored_table_name.BaseName())); | 462 result->push_back(FilePathToString(restored_table_name.BaseName())); |
| 746 } | 463 } |
| 747 } | 464 } |
| 748 | 465 |
| 749 namespace { | |
| 750 #if defined(OS_WIN) | |
| 751 static base::PlatformFileError GetDirectoryEntries( | |
| 752 const base::FilePath& dir_param, | |
| 753 std::vector<base::FilePath>* result) { | |
| 754 result->clear(); | |
| 755 base::FilePath dir_filepath = dir_param.Append(FILE_PATH_LITERAL("*")); | |
| 756 WIN32_FIND_DATA find_data; | |
| 757 HANDLE find_handle = FindFirstFile(dir_filepath.value().c_str(), &find_data); | |
| 758 if (find_handle == INVALID_HANDLE_VALUE) { | |
| 759 DWORD last_error = GetLastError(); | |
| 760 if (last_error == ERROR_FILE_NOT_FOUND) | |
| 761 return base::PLATFORM_FILE_OK; | |
| 762 return base::LastErrorToPlatformFileError(last_error); | |
| 763 } | |
| 764 do { | |
| 765 base::FilePath filepath(find_data.cFileName); | |
| 766 base::FilePath::StringType basename = filepath.BaseName().value(); | |
| 767 if (basename == FILE_PATH_LITERAL(".") || | |
| 768 basename == FILE_PATH_LITERAL("..")) | |
| 769 continue; | |
| 770 result->push_back(filepath.BaseName()); | |
| 771 } while (FindNextFile(find_handle, &find_data)); | |
| 772 DWORD last_error = GetLastError(); | |
| 773 base::PlatformFileError return_value = base::PLATFORM_FILE_OK; | |
| 774 if (last_error != ERROR_NO_MORE_FILES) | |
| 775 return_value = base::LastErrorToPlatformFileError(last_error); | |
| 776 FindClose(find_handle); | |
| 777 return return_value; | |
| 778 } | |
| 779 #else | |
| 780 static base::PlatformFileError GetDirectoryEntries( | |
| 781 const base::FilePath& dir_filepath, | |
| 782 std::vector<base::FilePath>* result) { | |
| 783 const std::string dir_string = FilePathToString(dir_filepath); | |
| 784 result->clear(); | |
| 785 DIR* dir = opendir(dir_string.c_str()); | |
| 786 if (!dir) | |
| 787 return base::ErrnoToPlatformFileError(errno); | |
| 788 struct dirent dent_buf; | |
| 789 struct dirent* dent; | |
| 790 int readdir_result; | |
| 791 while ((readdir_result = readdir_r(dir, &dent_buf, &dent)) == 0 && dent) { | |
| 792 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) | |
| 793 continue; | |
| 794 result->push_back(CreateFilePath(dent->d_name)); | |
| 795 } | |
| 796 int saved_errno = errno; | |
| 797 closedir(dir); | |
| 798 if (readdir_result != 0) | |
| 799 return base::ErrnoToPlatformFileError(saved_errno); | |
| 800 return base::PLATFORM_FILE_OK; | |
| 801 } | |
| 802 #endif | |
| 803 } | |
| 804 | |
| 805 Status ChromiumEnv::GetChildren(const std::string& dir_string, | 466 Status ChromiumEnv::GetChildren(const std::string& dir_string, |
| 806 std::vector<std::string>* result) { | 467 std::vector<std::string>* result) { |
| 807 std::vector<base::FilePath> entries; | 468 std::vector<base::FilePath> entries; |
| 808 base::PlatformFileError error = | 469 base::PlatformFileError error = |
| 809 GetDirectoryEntries(CreateFilePath(dir_string), &entries); | 470 GetDirectoryEntries(CreateFilePath(dir_string), &entries); |
| 810 if (error != base::PLATFORM_FILE_OK) { | 471 if (error != base::PLATFORM_FILE_OK) { |
| 811 RecordOSError(kGetChildren, error); | 472 RecordOSError(kGetChildren, error); |
| 812 return MakeIOError( | 473 return MakeIOError( |
| 813 dir_string, "Could not open/read directory", kGetChildren, error); | 474 dir_string, "Could not open/read directory", kGetChildren, error); |
| 814 } | 475 } |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 RecordErrorAt(kGetTestDirectory); | 656 RecordErrorAt(kGetTestDirectory); |
| 996 return MakeIOError( | 657 return MakeIOError( |
| 997 "Could not create temp directory.", "", kGetTestDirectory); | 658 "Could not create temp directory.", "", kGetTestDirectory); |
| 998 } | 659 } |
| 999 } | 660 } |
| 1000 *path = FilePathToString(test_directory_); | 661 *path = FilePathToString(test_directory_); |
| 1001 mu_.Release(); | 662 mu_.Release(); |
| 1002 return Status::OK(); | 663 return Status::OK(); |
| 1003 } | 664 } |
| 1004 | 665 |
| 1005 Status ChromiumEnv::NewLogger(const std::string& fname, Logger** result) { | |
| 1006 FILE* f = fopen_internal(fname.c_str(), "w"); | |
| 1007 if (f == NULL) { | |
| 1008 *result = NULL; | |
| 1009 int saved_errno = errno; | |
| 1010 RecordOSError(kNewLogger, saved_errno); | |
| 1011 return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno); | |
| 1012 } else { | |
| 1013 *result = new ChromiumLogger(f); | |
| 1014 return Status::OK(); | |
| 1015 } | |
| 1016 } | |
| 1017 | |
| 1018 uint64_t ChromiumEnv::NowMicros() { | 666 uint64_t ChromiumEnv::NowMicros() { |
| 1019 return ::base::TimeTicks::Now().ToInternalValue(); | 667 return ::base::TimeTicks::Now().ToInternalValue(); |
| 1020 } | 668 } |
| 1021 | 669 |
| 1022 void ChromiumEnv::SleepForMicroseconds(int micros) { | 670 void ChromiumEnv::SleepForMicroseconds(int micros) { |
| 1023 // Round up to the next millisecond. | 671 // Round up to the next millisecond. |
| 1024 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); | 672 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); |
| 1025 } | 673 } |
| 1026 | 674 |
| 1027 void ChromiumEnv::RecordErrorAt(MethodID method) const { | 675 void ChromiumEnv::RecordErrorAt(MethodID method) const { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 Env* IDBEnv() { | 857 Env* IDBEnv() { |
| 1210 return leveldb_env::idb_env.Pointer(); | 858 return leveldb_env::idb_env.Pointer(); |
| 1211 } | 859 } |
| 1212 | 860 |
| 1213 Env* Env::Default() { | 861 Env* Env::Default() { |
| 1214 return leveldb_env::default_env.Pointer(); | 862 return leveldb_env::default_env.Pointer(); |
| 1215 } | 863 } |
| 1216 | 864 |
| 1217 } // namespace leveldb | 865 } // namespace leveldb |
| 1218 | 866 |
| OLD | NEW |