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" |
5 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
6 #include "base/file_util.h" | 13 #include "base/file_util.h" |
| 14 #include "base/files/file_enumerator.h" |
| 15 #include "base/files/file_path.h" |
7 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
| 17 #include "base/memory/ref_counted.h" |
| 18 #include "base/message_loop/message_loop.h" |
8 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
| 20 #include "base/platform_file.h" |
| 21 #include "base/posix/eintr_wrapper.h" |
9 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
10 #include "env_chromium_stdio.h" | 23 #include "base/synchronization/lock.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" |
11 #include "third_party/re2/re2/re2.h" | 32 #include "third_party/re2/re2/re2.h" |
| 33 #include "util/logging.h" |
12 | 34 |
13 #if defined(OS_WIN) | 35 #if defined(OS_WIN) |
14 #include <io.h> | 36 #include <io.h> |
15 #include "base/command_line.h" | |
16 #include "base/win/win_util.h" | 37 #include "base/win/win_util.h" |
17 #include "env_chromium_win.h" | 38 #endif |
| 39 |
| 40 #if defined(OS_POSIX) |
| 41 #include <dirent.h> |
| 42 #include <fcntl.h> |
| 43 #include <sys/resource.h> |
| 44 #include <sys/time.h> |
18 #endif | 45 #endif |
19 | 46 |
20 using namespace leveldb; | 47 using namespace leveldb; |
21 | 48 |
22 namespace leveldb_env { | 49 namespace leveldb_env { |
23 | 50 |
24 namespace { | 51 namespace { |
25 | 52 |
26 const base::FilePath::CharType backup_table_extension[] = | 53 const base::FilePath::CharType backup_table_extension[] = |
27 FILE_PATH_LITERAL(".bak"); | 54 FILE_PATH_LITERAL(".bak"); |
28 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); | 55 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); |
29 | 56 |
| 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 |
30 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] | 102 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] |
31 = FILE_PATH_LITERAL("leveldb-test-"); | 103 = FILE_PATH_LITERAL("leveldb-test-"); |
32 | 104 |
| 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 |
33 class ChromiumFileLock : public FileLock { | 214 class ChromiumFileLock : public FileLock { |
34 public: | 215 public: |
35 ::base::PlatformFile file_; | 216 ::base::PlatformFile file_; |
36 std::string name_; | 217 std::string name_; |
37 }; | 218 }; |
38 | 219 |
39 class Retrier { | 220 class Retrier { |
40 public: | 221 public: |
41 Retrier(MethodID method, RetrierProvider* provider) | 222 Retrier(MethodID method, RetrierProvider* provider) |
42 : start_(base::TimeTicks::Now()), | 223 : start_(base::TimeTicks::Now()), |
(...skipping 30 matching lines...) Expand all Loading... |
73 base::TimeTicks start_; | 254 base::TimeTicks start_; |
74 base::TimeTicks limit_; | 255 base::TimeTicks limit_; |
75 base::TimeTicks last_; | 256 base::TimeTicks last_; |
76 base::TimeDelta time_to_sleep_; | 257 base::TimeDelta time_to_sleep_; |
77 bool success_; | 258 bool success_; |
78 MethodID method_; | 259 MethodID method_; |
79 base::PlatformFileError last_error_; | 260 base::PlatformFileError last_error_; |
80 RetrierProvider* provider_; | 261 RetrierProvider* provider_; |
81 }; | 262 }; |
82 | 263 |
83 class IDBEnvStdio : public ChromiumEnvStdio { | 264 class IDBEnv : public ChromiumEnv { |
84 public: | 265 public: |
85 IDBEnvStdio() : ChromiumEnvStdio() { | 266 IDBEnv() : ChromiumEnv() { |
86 name_ = "LevelDBEnv.IDB"; | 267 name_ = "LevelDBEnv.IDB"; |
87 make_backup_ = true; | 268 make_backup_ = true; |
88 } | 269 } |
89 }; | 270 }; |
90 | 271 |
91 #if defined(OS_WIN) | 272 ::base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; |
92 class IDBEnvWin : public ChromiumEnvWin { | |
93 public: | |
94 IDBEnvWin() : ChromiumEnvWin() { | |
95 name_ = "LevelDBEnv.IDB"; | |
96 make_backup_ = true; | |
97 } | |
98 }; | |
99 #endif | |
100 | 273 |
101 #if defined(OS_WIN) | 274 ::base::LazyInstance<ChromiumEnv>::Leaky default_env = |
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 = | |
110 LAZY_INSTANCE_INITIALIZER; | 275 LAZY_INSTANCE_INITIALIZER; |
111 | 276 |
112 } // unnamed namespace | 277 } // unnamed namespace |
113 | 278 |
114 const char* MethodIDToString(MethodID method) { | 279 const char* MethodIDToString(MethodID method) { |
115 switch (method) { | 280 switch (method) { |
116 case kSequentialFileRead: | 281 case kSequentialFileRead: |
117 return "SequentialFileRead"; | 282 return "SequentialFileRead"; |
118 case kSequentialFileSkip: | 283 case kSequentialFileSkip: |
119 return "SequentialFileSkip"; | 284 return "SequentialFileSkip"; |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 } | 487 } |
323 | 488 |
324 std::string FilePathToString(const base::FilePath& file_path) { | 489 std::string FilePathToString(const base::FilePath& file_path) { |
325 #if defined(OS_WIN) | 490 #if defined(OS_WIN) |
326 return base::UTF16ToUTF8(file_path.value()); | 491 return base::UTF16ToUTF8(file_path.value()); |
327 #else | 492 #else |
328 return file_path.value(); | 493 return file_path.value(); |
329 #endif | 494 #endif |
330 } | 495 } |
331 | 496 |
332 base::FilePath ChromiumEnv::CreateFilePath(const std::string& file_path) { | 497 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, |
333 #if defined(OS_WIN) | 498 FILE* f, |
334 return base::FilePath(base::UTF8ToUTF16(file_path)); | 499 const UMALogger* uma_logger, |
335 #else | 500 WriteTracker* tracker, |
336 return base::FilePath(file_path); | 501 bool make_backup) |
337 #endif | 502 : filename_(fname), |
| 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()); |
338 } | 516 } |
339 | 517 |
340 bool ChromiumEnv::MakeBackup(const std::string& fname) { | 518 ChromiumWritableFile::~ChromiumWritableFile() { |
| 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) { |
341 base::FilePath original_table_name = CreateFilePath(fname); | 587 base::FilePath original_table_name = CreateFilePath(fname); |
342 base::FilePath backup_table_name = | 588 base::FilePath backup_table_name = |
343 original_table_name.ReplaceExtension(backup_table_extension); | 589 original_table_name.ReplaceExtension(backup_table_extension); |
344 return base::CopyFile(original_table_name, backup_table_name); | 590 return base::CopyFile(original_table_name, backup_table_name); |
345 } | 591 } |
346 | 592 |
347 bool ChromiumEnv::HasTableExtension(const base::FilePath& path) | 593 Status ChromiumWritableFile::Sync() { |
348 { | 594 TRACE_EVENT0("leveldb", "ChromiumEnv::Sync"); |
349 return path.MatchesExtension(table_extension); | 595 Status result; |
| 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; |
350 } | 613 } |
351 | 614 |
352 ChromiumEnv::ChromiumEnv() | 615 ChromiumEnv::ChromiumEnv() |
353 : name_("LevelDBEnv"), | 616 : name_("LevelDBEnv"), |
354 make_backup_(false), | 617 make_backup_(false), |
355 bgsignal_(&mu_), | 618 bgsignal_(&mu_), |
356 started_bgthread_(false), | 619 started_bgthread_(false), |
357 kMaxRetryTimeMillis(1000) { | 620 kMaxRetryTimeMillis(1000) { |
358 } | 621 } |
359 | 622 |
360 ChromiumEnv::~ChromiumEnv() { | 623 ChromiumEnv::~ChromiumEnv() { |
361 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to | 624 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to |
362 // ensure that behavior isn't accidentally changed, but there's an instance in | 625 // ensure that behavior isn't accidentally changed, but there's an instance in |
363 // a unit test that is deleted. | 626 // a unit test that is deleted. |
364 } | 627 } |
365 | 628 |
| 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 |
366 bool ChromiumEnv::FileExists(const std::string& fname) { | 692 bool ChromiumEnv::FileExists(const std::string& fname) { |
367 return ::base::PathExists(CreateFilePath(fname)); | 693 return ::base::PathExists(CreateFilePath(fname)); |
368 } | 694 } |
369 | 695 |
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 | |
413 base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { | 696 base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { |
414 base::FilePath table_name = | 697 base::FilePath table_name = |
415 base_name.AddExtension(table_extension); | 698 base_name.AddExtension(table_extension); |
416 bool result = base::CopyFile(base_name.AddExtension(backup_table_extension), | 699 bool result = base::CopyFile(base_name.AddExtension(backup_table_extension), |
417 table_name); | 700 table_name); |
418 std::string uma_name(name_); | 701 std::string uma_name(name_); |
419 uma_name.append(".TableRestore"); | 702 uma_name.append(".TableRestore"); |
420 base::BooleanHistogram::FactoryGet( | 703 base::BooleanHistogram::FactoryGet( |
421 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); | 704 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); |
422 return table_name; | 705 return table_name; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir); | 739 base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir); |
457 for (std::set<base::FilePath>::iterator it = backups_only.begin(); | 740 for (std::set<base::FilePath>::iterator it = backups_only.begin(); |
458 it != backups_only.end(); | 741 it != backups_only.end(); |
459 ++it) { | 742 ++it) { |
460 base::FilePath restored_table_name = | 743 base::FilePath restored_table_name = |
461 RestoreFromBackup(dir_filepath.Append(*it)); | 744 RestoreFromBackup(dir_filepath.Append(*it)); |
462 result->push_back(FilePathToString(restored_table_name.BaseName())); | 745 result->push_back(FilePathToString(restored_table_name.BaseName())); |
463 } | 746 } |
464 } | 747 } |
465 | 748 |
| 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 |
466 Status ChromiumEnv::GetChildren(const std::string& dir_string, | 805 Status ChromiumEnv::GetChildren(const std::string& dir_string, |
467 std::vector<std::string>* result) { | 806 std::vector<std::string>* result) { |
468 std::vector<base::FilePath> entries; | 807 std::vector<base::FilePath> entries; |
469 base::PlatformFileError error = | 808 base::PlatformFileError error = |
470 GetDirectoryEntries(CreateFilePath(dir_string), &entries); | 809 GetDirectoryEntries(CreateFilePath(dir_string), &entries); |
471 if (error != base::PLATFORM_FILE_OK) { | 810 if (error != base::PLATFORM_FILE_OK) { |
472 RecordOSError(kGetChildren, error); | 811 RecordOSError(kGetChildren, error); |
473 return MakeIOError( | 812 return MakeIOError( |
474 dir_string, "Could not open/read directory", kGetChildren, error); | 813 dir_string, "Could not open/read directory", kGetChildren, error); |
475 } | 814 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 RecordErrorAt(kGetTestDirectory); | 1002 RecordErrorAt(kGetTestDirectory); |
664 return MakeIOError( | 1003 return MakeIOError( |
665 "Could not create temp directory.", "", kGetTestDirectory); | 1004 "Could not create temp directory.", "", kGetTestDirectory); |
666 } | 1005 } |
667 } | 1006 } |
668 *path = FilePathToString(test_directory_); | 1007 *path = FilePathToString(test_directory_); |
669 mu_.Release(); | 1008 mu_.Release(); |
670 return Status::OK(); | 1009 return Status::OK(); |
671 } | 1010 } |
672 | 1011 |
| 1012 Status ChromiumEnv::NewLogger(const std::string& fname, Logger** result) { |
| 1013 FILE* f = fopen_internal(fname.c_str(), "w"); |
| 1014 if (f == NULL) { |
| 1015 *result = NULL; |
| 1016 int saved_errno = errno; |
| 1017 RecordOSError(kNewLogger, saved_errno); |
| 1018 return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno); |
| 1019 } else { |
| 1020 *result = new ChromiumLogger(f); |
| 1021 return Status::OK(); |
| 1022 } |
| 1023 } |
| 1024 |
673 uint64_t ChromiumEnv::NowMicros() { | 1025 uint64_t ChromiumEnv::NowMicros() { |
674 return ::base::TimeTicks::Now().ToInternalValue(); | 1026 return ::base::TimeTicks::Now().ToInternalValue(); |
675 } | 1027 } |
676 | 1028 |
677 void ChromiumEnv::SleepForMicroseconds(int micros) { | 1029 void ChromiumEnv::SleepForMicroseconds(int micros) { |
678 // Round up to the next millisecond. | 1030 // Round up to the next millisecond. |
679 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); | 1031 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); |
680 } | 1032 } |
681 | 1033 |
682 void ChromiumEnv::RecordErrorAt(MethodID method) const { | 1034 void ChromiumEnv::RecordErrorAt(MethodID method) const { |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
864 Env* IDBEnv() { | 1216 Env* IDBEnv() { |
865 return leveldb_env::idb_env.Pointer(); | 1217 return leveldb_env::idb_env.Pointer(); |
866 } | 1218 } |
867 | 1219 |
868 Env* Env::Default() { | 1220 Env* Env::Default() { |
869 return leveldb_env::default_env.Pointer(); | 1221 return leveldb_env::default_env.Pointer(); |
870 } | 1222 } |
871 | 1223 |
872 } // namespace leveldb | 1224 } // namespace leveldb |
873 | 1225 |
OLD | NEW |