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 |