Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1458)

Side by Side Diff: third_party/leveldatabase/env_chromium.cc

Issue 113373002: Unrevert r245135 "Created new Windows LevelDB environment." (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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> 5 #include <stdio.h>
7 #include <string.h>
8 6
9 #include <deque> 7 #include <deque>
10 8
11 #include "base/at_exit.h" 9 #include "base/at_exit.h"
12 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
13 #include "base/file_util.h" 11 #include "base/file_util.h"
14 #include "base/files/file_enumerator.h" 12 #include "base/files/file_enumerator.h"
15 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
16 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
17 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
18 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
19 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
20 #include "base/platform_file.h" 18 #include "base/platform_file.h"
21 #include "base/posix/eintr_wrapper.h" 19 #include "base/posix/eintr_wrapper.h"
22 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
23 #include "base/synchronization/lock.h" 21 #include "base/synchronization/lock.h"
24 #include "base/sys_info.h" 22 #include "base/sys_info.h"
25 #include "base/threading/platform_thread.h" 23 #include "base/threading/platform_thread.h"
26 #include "base/threading/thread.h" 24 #include "base/threading/thread.h"
27 #include "chromium_logger.h" 25 #include "chromium_logger.h"
28 #include "env_chromium.h" 26 #include "env_chromium.h"
27 #include "env_chromium_posix.h"
28 #if defined(OS_WIN)
29 #include "env_chromium_win32.h"
30 #endif
29 #include "leveldb/env.h" 31 #include "leveldb/env.h"
30 #include "leveldb/slice.h" 32 #include "leveldb/slice.h"
31 #include "port/port.h" 33 #include "port/port.h"
32 #include "third_party/re2/re2/re2.h" 34 #include "third_party/re2/re2/re2.h"
33 #include "util/logging.h" 35 #include "util/logging.h"
34 36
35 #if defined(OS_WIN) 37 #if defined(OS_WIN)
36 #include <io.h> 38 #include <io.h>
39 #include "base/command_line.h"
40 #include "base/metrics/field_trial.h"
37 #include "base/win/win_util.h" 41 #include "base/win/win_util.h"
42 #include "leveldb_switches.h"
38 #endif 43 #endif
39 44
40 #if defined(OS_POSIX) 45 #if defined(OS_POSIX)
41 #include <dirent.h> 46 #include <dirent.h>
42 #include <fcntl.h> 47 #include <fcntl.h>
43 #include <sys/resource.h> 48 #include <sys/resource.h>
44 #include <sys/time.h> 49 #include <sys/time.h>
45 #endif 50 #endif
46 51
47 using namespace leveldb; 52 using namespace leveldb;
48 53
49 namespace leveldb_env { 54 namespace leveldb_env {
50 55
56 enum ChromiumEnvType {
57 CHROMIUM_ENV_UNSET
58 ,CHROMIUM_ENV_POSIX
59 #if defined(OS_WIN)
60 ,CHROMIUM_ENV_WIN32
61 #endif
62 };
63
64 static ChromiumEnvType g_active_chromium_env_type = CHROMIUM_ENV_UNSET;
65
51 namespace { 66 namespace {
52 67
53 const base::FilePath::CharType backup_table_extension[] = 68 const base::FilePath::CharType backup_table_extension[] =
54 FILE_PATH_LITERAL(".bak"); 69 FILE_PATH_LITERAL(".bak");
55 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); 70 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb");
56 71
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(UTF8ToUTF16(fname).c_str(), ASCIIToUTF16(mode).c_str());
88 #else
89 return fopen(fname, mode);
90 #endif
91 }
92
93 base::FilePath CreateFilePath(const std::string& file_path) {
94 #if defined(OS_WIN)
95 return base::FilePath(UTF8ToUTF16(file_path));
96 #else
97 return base::FilePath(file_path);
98 #endif
99 }
100
101 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] 72 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[]
102 = FILE_PATH_LITERAL("leveldb-test-"); 73 = FILE_PATH_LITERAL("leveldb-test-");
103 74
104 const char* PlatformFileErrorString(const ::base::PlatformFileError& error) {
105 switch (error) {
106 case ::base::PLATFORM_FILE_ERROR_FAILED:
107 return "No further details.";
108 case ::base::PLATFORM_FILE_ERROR_IN_USE:
109 return "File currently in use.";
110 case ::base::PLATFORM_FILE_ERROR_EXISTS:
111 return "File already exists.";
112 case ::base::PLATFORM_FILE_ERROR_NOT_FOUND:
113 return "File not found.";
114 case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
115 return "Access denied.";
116 case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
117 return "Too many files open.";
118 case ::base::PLATFORM_FILE_ERROR_NO_MEMORY:
119 return "Out of memory.";
120 case ::base::PLATFORM_FILE_ERROR_NO_SPACE:
121 return "No space left on drive.";
122 case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
123 return "Not a directory.";
124 case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION:
125 return "Invalid operation.";
126 case ::base::PLATFORM_FILE_ERROR_SECURITY:
127 return "Security error.";
128 case ::base::PLATFORM_FILE_ERROR_ABORT:
129 return "File operation aborted.";
130 case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE:
131 return "The supplied path was not a file.";
132 case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY:
133 return "The file was not empty.";
134 case ::base::PLATFORM_FILE_ERROR_INVALID_URL:
135 return "Invalid URL.";
136 case ::base::PLATFORM_FILE_ERROR_IO:
137 return "OS or hardware error.";
138 case ::base::PLATFORM_FILE_OK:
139 return "OK.";
140 case ::base::PLATFORM_FILE_ERROR_MAX:
141 NOTREACHED();
142 }
143 NOTIMPLEMENTED();
144 return "Unknown error.";
145 }
146
147 class ChromiumSequentialFile: public SequentialFile {
148 private:
149 std::string filename_;
150 FILE* file_;
151 const UMALogger* uma_logger_;
152
153 public:
154 ChromiumSequentialFile(const std::string& fname, FILE* f,
155 const UMALogger* uma_logger)
156 : filename_(fname), file_(f), uma_logger_(uma_logger) { }
157 virtual ~ChromiumSequentialFile() { fclose(file_); }
158
159 virtual Status Read(size_t n, Slice* result, char* scratch) {
160 Status s;
161 size_t r = fread_unlocked(scratch, 1, n, file_);
162 *result = Slice(scratch, r);
163 if (r < n) {
164 if (feof(file_)) {
165 // We leave status as ok if we hit the end of the file
166 } else {
167 // A partial read with an error: return a non-ok status
168 s = MakeIOError(filename_, strerror(errno), kSequentialFileRead, errno);
169 uma_logger_->RecordErrorAt(kSequentialFileRead);
170 }
171 }
172 return s;
173 }
174
175 virtual Status Skip(uint64_t n) {
176 if (fseek(file_, n, SEEK_CUR)) {
177 int saved_errno = errno;
178 uma_logger_->RecordErrorAt(kSequentialFileSkip);
179 return MakeIOError(
180 filename_, strerror(saved_errno), kSequentialFileSkip, saved_errno);
181 }
182 return Status::OK();
183 }
184 };
185
186 class ChromiumRandomAccessFile: public RandomAccessFile {
187 private:
188 std::string filename_;
189 ::base::PlatformFile file_;
190 const UMALogger* uma_logger_;
191
192 public:
193 ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file,
194 const UMALogger* uma_logger)
195 : filename_(fname), file_(file), uma_logger_(uma_logger) { }
196 virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); }
197
198 virtual Status Read(uint64_t offset, size_t n, Slice* result,
199 char* scratch) const {
200 Status s;
201 int r = ::base::ReadPlatformFile(file_, offset, scratch, n);
202 *result = Slice(scratch, (r < 0) ? 0 : r);
203 if (r < 0) {
204 // An error: return a non-ok status
205 s = MakeIOError(
206 filename_, "Could not perform read", kRandomAccessFileRead);
207 uma_logger_->RecordErrorAt(kRandomAccessFileRead);
208 }
209 return s;
210 }
211 };
212
213 class ChromiumFileLock : public FileLock { 75 class ChromiumFileLock : public FileLock {
214 public: 76 public:
215 ::base::PlatformFile file_; 77 ::base::PlatformFile file_;
216 std::string name_; 78 std::string name_;
217 }; 79 };
218 80
219 class Retrier { 81 class Retrier {
220 public: 82 public:
221 Retrier(MethodID method, RetrierProvider* provider) 83 Retrier(MethodID method, RetrierProvider* provider)
222 : start_(base::TimeTicks::Now()), 84 : start_(base::TimeTicks::Now()),
(...skipping 30 matching lines...) Expand all
253 base::TimeTicks start_; 115 base::TimeTicks start_;
254 base::TimeTicks limit_; 116 base::TimeTicks limit_;
255 base::TimeTicks last_; 117 base::TimeTicks last_;
256 base::TimeDelta time_to_sleep_; 118 base::TimeDelta time_to_sleep_;
257 bool success_; 119 bool success_;
258 MethodID method_; 120 MethodID method_;
259 base::PlatformFileError last_error_; 121 base::PlatformFileError last_error_;
260 RetrierProvider* provider_; 122 RetrierProvider* provider_;
261 }; 123 };
262 124
263 class IDBEnv : public ChromiumEnv { 125 class IDBEnvPosix : public ChromiumEnvPosix {
264 public: 126 public:
265 IDBEnv() : ChromiumEnv() { 127 IDBEnvPosix() : ChromiumEnvPosix() {
266 name_ = "LevelDBEnv.IDB"; 128 name_ = "LevelDBEnv.IDB";
267 make_backup_ = true; 129 make_backup_ = true;
268 } 130 }
269 }; 131 };
270 132
271 ::base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; 133 #if defined(OS_WIN)
134 class IDBEnvWin32 : public ChromiumEnvWin32 {
135 public:
136 IDBEnvWin32() : ChromiumEnvWin32() {
137 name_ = "LevelDBEnv.IDB";
138 make_backup_ = true;
139 }
140 };
141 #endif
272 142
273 ::base::LazyInstance<ChromiumEnv>::Leaky default_env = 143 ::base::LazyInstance<IDBEnvPosix>::Leaky idb_env_posix =
274 LAZY_INSTANCE_INITIALIZER; 144 LAZY_INSTANCE_INITIALIZER;
275 145
146 ::base::LazyInstance<ChromiumEnvPosix>::Leaky default_env_posix =
147 LAZY_INSTANCE_INITIALIZER;
148
149 #if defined(OS_WIN)
150 ::base::LazyInstance<IDBEnvWin32>::Leaky idb_env_win32 =
151 LAZY_INSTANCE_INITIALIZER;
152
153 ::base::LazyInstance<ChromiumEnvWin32>::Leaky default_env_win32 =
154 LAZY_INSTANCE_INITIALIZER;
155 #endif
156
276 } // unnamed namespace 157 } // unnamed namespace
277 158
278 const char* MethodIDToString(MethodID method) { 159 const char* MethodIDToString(MethodID method) {
279 switch (method) { 160 switch (method) {
280 case kSequentialFileRead: 161 case kSequentialFileRead:
281 return "SequentialFileRead"; 162 return "SequentialFileRead";
282 case kSequentialFileSkip: 163 case kSequentialFileSkip:
283 return "SequentialFileSkip"; 164 return "SequentialFileSkip";
284 case kRandomAccessFileRead: 165 case kRandomAccessFileRead:
285 return "RandomAccessFileRead"; 166 return "RandomAccessFileRead";
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 NOTREACHED(); 204 NOTREACHED();
324 return "kNumEntries"; 205 return "kNumEntries";
325 } 206 }
326 NOTREACHED(); 207 NOTREACHED();
327 return "Unknown"; 208 return "Unknown";
328 } 209 }
329 210
330 Status MakeIOError(Slice filename, 211 Status MakeIOError(Slice filename,
331 const char* message, 212 const char* message,
332 MethodID method, 213 MethodID method,
333 int saved_errno) {
334 char buf[512];
335 snprintf(buf,
336 sizeof(buf),
337 "%s (ChromeMethodErrno: %d::%s::%d)",
338 message,
339 method,
340 MethodIDToString(method),
341 saved_errno);
342 return Status::IOError(filename, buf);
343 }
344
345 Status MakeIOError(Slice filename,
346 const char* message,
347 MethodID method,
348 base::PlatformFileError error) { 214 base::PlatformFileError error) {
349 DCHECK(error < 0); 215 DCHECK(error < 0);
350 char buf[512]; 216 char buf[512];
351 snprintf(buf, 217 snprintf(buf,
352 sizeof(buf), 218 sizeof(buf),
353 "%s (ChromeMethodPFE: %d::%s::%d)", 219 "%s (ChromeMethodPFE: %d::%s::%d)",
354 message, 220 message,
355 method, 221 method,
356 MethodIDToString(method), 222 MethodIDToString(method),
357 -error); 223 -error);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 } 352 }
487 353
488 std::string FilePathToString(const base::FilePath& file_path) { 354 std::string FilePathToString(const base::FilePath& file_path) {
489 #if defined(OS_WIN) 355 #if defined(OS_WIN)
490 return UTF16ToUTF8(file_path.value()); 356 return UTF16ToUTF8(file_path.value());
491 #else 357 #else
492 return file_path.value(); 358 return file_path.value();
493 #endif 359 #endif
494 } 360 }
495 361
496 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, 362 base::FilePath ChromiumEnv::CreateFilePath(const std::string& file_path) {
497 FILE* f, 363 #if defined(OS_WIN)
498 const UMALogger* uma_logger, 364 return base::FilePath(UTF8ToUTF16(file_path));
499 WriteTracker* tracker, 365 #else
500 bool make_backup) 366 return base::FilePath(file_path);
501 : filename_(fname), 367 #endif
502 file_(f),
503 uma_logger_(uma_logger),
504 tracker_(tracker),
505 file_type_(kOther),
506 make_backup_(make_backup) {
507 base::FilePath path = base::FilePath::FromUTF8Unsafe(fname);
508 if (FilePathToString(path.BaseName()).find("MANIFEST") == 0)
509 file_type_ = kManifest;
510 else if (path.MatchesExtension(table_extension))
511 file_type_ = kTable;
512 if (file_type_ != kManifest)
513 tracker_->DidCreateNewFile(filename_);
514 parent_dir_ = FilePathToString(CreateFilePath(fname).DirName());
515 } 368 }
516 369
517 ChromiumWritableFile::~ChromiumWritableFile() { 370 bool ChromiumEnv::MakeBackup(const std::string& fname) {
518 if (file_ != NULL) {
519 // Ignoring any potential errors
520 fclose(file_);
521 }
522 }
523
524 Status ChromiumWritableFile::SyncParent() {
525 Status s;
526 #if !defined(OS_WIN)
527 TRACE_EVENT0("leveldb", "SyncParent");
528
529 int parent_fd =
530 HANDLE_EINTR(open(parent_dir_.c_str(), O_RDONLY));
531 if (parent_fd < 0) {
532 int saved_errno = errno;
533 return MakeIOError(
534 parent_dir_, strerror(saved_errno), kSyncParent, saved_errno);
535 }
536 if (HANDLE_EINTR(fsync(parent_fd)) != 0) {
537 int saved_errno = errno;
538 s = MakeIOError(
539 parent_dir_, strerror(saved_errno), kSyncParent, saved_errno);
540 };
541 close(parent_fd);
542 #endif
543 return s;
544 }
545
546 Status ChromiumWritableFile::Append(const Slice& data) {
547 if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) {
548 Status s = SyncParent();
549 if (!s.ok())
550 return s;
551 tracker_->DidSyncDir(filename_);
552 }
553
554 size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_);
555 if (r != data.size()) {
556 int saved_errno = errno;
557 uma_logger_->RecordOSError(kWritableFileAppend, saved_errno);
558 return MakeIOError(
559 filename_, strerror(saved_errno), kWritableFileAppend, saved_errno);
560 }
561 return Status::OK();
562 }
563
564 Status ChromiumWritableFile::Close() {
565 Status result;
566 if (fclose(file_) != 0) {
567 result = MakeIOError(filename_, strerror(errno), kWritableFileClose, errno);
568 uma_logger_->RecordErrorAt(kWritableFileClose);
569 }
570 file_ = NULL;
571 return result;
572 }
573
574 Status ChromiumWritableFile::Flush() {
575 Status result;
576 if (HANDLE_EINTR(fflush_unlocked(file_))) {
577 int saved_errno = errno;
578 result = MakeIOError(
579 filename_, strerror(saved_errno), kWritableFileFlush, saved_errno);
580 uma_logger_->RecordOSError(kWritableFileFlush, saved_errno);
581 }
582 return result;
583 }
584
585 static bool MakeBackup(const std::string& fname) {
586 base::FilePath original_table_name = CreateFilePath(fname); 371 base::FilePath original_table_name = CreateFilePath(fname);
587 base::FilePath backup_table_name = 372 base::FilePath backup_table_name =
588 original_table_name.ReplaceExtension(backup_table_extension); 373 original_table_name.ReplaceExtension(backup_table_extension);
589 return base::CopyFile(original_table_name, backup_table_name); 374 return base::CopyFile(original_table_name, backup_table_name);
590 } 375 }
591 376
592 Status ChromiumWritableFile::Sync() { 377 bool ChromiumEnv::HasTableExtension(const base::FilePath& path)
593 TRACE_EVENT0("leveldb", "ChromiumEnv::Sync"); 378 {
594 Status result; 379 return path.MatchesExtension(table_extension);
595 int error = 0;
596
597 if (HANDLE_EINTR(fflush_unlocked(file_)))
598 error = errno;
599 // Sync even if fflush gave an error; perhaps the data actually got out,
600 // even though something went wrong.
601 if (fdatasync(fileno(file_)) && !error)
602 error = errno;
603 // Report the first error we found.
604 if (error) {
605 result = MakeIOError(filename_, strerror(error), kWritableFileSync, error);
606 uma_logger_->RecordErrorAt(kWritableFileSync);
607 } else if (make_backup_ && file_type_ == kTable) {
608 bool success = MakeBackup(filename_);
609 uma_logger_->RecordBackupResult(success);
610 }
611 return result;
612 } 380 }
613 381
614 ChromiumEnv::ChromiumEnv() 382 ChromiumEnv::ChromiumEnv()
615 : name_("LevelDBEnv"), 383 : name_("LevelDBEnv"),
616 make_backup_(false), 384 make_backup_(false),
617 bgsignal_(&mu_), 385 bgsignal_(&mu_),
618 started_bgthread_(false), 386 started_bgthread_(false),
619 kMaxRetryTimeMillis(1000) { 387 kMaxRetryTimeMillis(1000) {
620 } 388 }
621 389
622 ChromiumEnv::~ChromiumEnv() { 390 ChromiumEnv::~ChromiumEnv() {
623 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to 391 // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to
624 // ensure that behavior isn't accidentally changed, but there's an instance in 392 // ensure that behavior isn't accidentally changed, but there's an instance in
625 // a unit test that is deleted. 393 // a unit test that is deleted.
626 } 394 }
627 395
628 Status ChromiumEnv::NewSequentialFile(const std::string& fname, 396 void ChromiumEnv::SetDelegate(ChromiumEnvDelegate* delegate) {
629 SequentialFile** result) { 397 env_delegate_.reset(delegate);
630 FILE* f = fopen_internal(fname.c_str(), "rb");
631 if (f == NULL) {
632 *result = NULL;
633 int saved_errno = errno;
634 RecordOSError(kNewSequentialFile, saved_errno);
635 return MakeIOError(
636 fname, strerror(saved_errno), kNewSequentialFile, saved_errno);
637 } else {
638 *result = new ChromiumSequentialFile(fname, f, this);
639 return Status::OK();
640 }
641 }
642
643 void ChromiumEnv::RecordOpenFilesLimit(const std::string& type) {
644 #if defined(OS_POSIX)
645 struct rlimit nofile;
646 if (getrlimit(RLIMIT_NOFILE, &nofile))
647 return;
648 GetMaxFDHistogram(type)->Add(nofile.rlim_cur);
649 #endif
650 }
651
652 Status ChromiumEnv::NewRandomAccessFile(const std::string& fname,
653 RandomAccessFile** result) {
654 int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN;
655 bool created;
656 ::base::PlatformFileError error_code;
657 ::base::PlatformFile file = ::base::CreatePlatformFile(
658 CreateFilePath(fname), flags, &created, &error_code);
659 if (error_code == ::base::PLATFORM_FILE_OK) {
660 *result = new ChromiumRandomAccessFile(fname, file, this);
661 RecordOpenFilesLimit("Success");
662 return Status::OK();
663 }
664 if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED)
665 RecordOpenFilesLimit("TooManyOpened");
666 else
667 RecordOpenFilesLimit("OtherError");
668 *result = NULL;
669 RecordOSError(kNewRandomAccessFile, error_code);
670 return MakeIOError(fname,
671 PlatformFileErrorString(error_code),
672 kNewRandomAccessFile,
673 error_code);
674 }
675
676 Status ChromiumEnv::NewWritableFile(const std::string& fname,
677 WritableFile** result) {
678 *result = NULL;
679 FILE* f = fopen_internal(fname.c_str(), "wb");
680 if (f == NULL) {
681 int saved_errno = errno;
682 RecordErrorAt(kNewWritableFile);
683 return MakeIOError(
684 fname, strerror(saved_errno), kNewWritableFile, saved_errno);
685 } else {
686 *result = new ChromiumWritableFile(fname, f, this, this, make_backup_);
687 return Status::OK();
688 }
689 } 398 }
690 399
691 bool ChromiumEnv::FileExists(const std::string& fname) { 400 bool ChromiumEnv::FileExists(const std::string& fname) {
692 return ::base::PathExists(CreateFilePath(fname)); 401 return ::base::PathExists(CreateFilePath(fname));
693 } 402 }
694 403
404 const char* ChromiumEnv::PlatformFileErrorString(const ::base::PlatformFileError & error) {
405 switch (error) {
406 case ::base::PLATFORM_FILE_ERROR_FAILED:
407 return "No further details.";
408 case ::base::PLATFORM_FILE_ERROR_IN_USE:
409 return "File currently in use.";
410 case ::base::PLATFORM_FILE_ERROR_EXISTS:
411 return "File already exists.";
412 case ::base::PLATFORM_FILE_ERROR_NOT_FOUND:
413 return "File not found.";
414 case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
415 return "Access denied.";
416 case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
417 return "Too many files open.";
418 case ::base::PLATFORM_FILE_ERROR_NO_MEMORY:
419 return "Out of memory.";
420 case ::base::PLATFORM_FILE_ERROR_NO_SPACE:
421 return "No space left on drive.";
422 case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
423 return "Not a directory.";
424 case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION:
425 return "Invalid operation.";
426 case ::base::PLATFORM_FILE_ERROR_SECURITY:
427 return "Security error.";
428 case ::base::PLATFORM_FILE_ERROR_ABORT:
429 return "File operation aborted.";
430 case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE:
431 return "The supplied path was not a file.";
432 case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY:
433 return "The file was not empty.";
434 case ::base::PLATFORM_FILE_ERROR_INVALID_URL:
435 return "Invalid URL.";
436 case ::base::PLATFORM_FILE_ERROR_IO:
437 return "OS or hardware error.";
438 case ::base::PLATFORM_FILE_OK:
439 return "OK.";
440 case ::base::PLATFORM_FILE_ERROR_MAX:
441 NOTREACHED();
442 }
443 NOTIMPLEMENTED();
444 return "Unknown error.";
445 }
446
695 base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { 447 base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) {
696 base::FilePath table_name = 448 base::FilePath table_name =
697 base_name.AddExtension(table_extension); 449 base_name.AddExtension(table_extension);
698 bool result = base::CopyFile(base_name.AddExtension(backup_table_extension), 450 bool result = base::CopyFile(base_name.AddExtension(backup_table_extension),
699 table_name); 451 table_name);
700 std::string uma_name(name_); 452 std::string uma_name(name_);
701 uma_name.append(".TableRestore"); 453 uma_name.append(".TableRestore");
702 base::BooleanHistogram::FactoryGet( 454 base::BooleanHistogram::FactoryGet(
703 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); 455 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result);
704 return table_name; 456 return table_name;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir); 490 base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir);
739 for (std::set<base::FilePath>::iterator it = backups_only.begin(); 491 for (std::set<base::FilePath>::iterator it = backups_only.begin();
740 it != backups_only.end(); 492 it != backups_only.end();
741 ++it) { 493 ++it) {
742 base::FilePath restored_table_name = 494 base::FilePath restored_table_name =
743 RestoreFromBackup(dir_filepath.Append(*it)); 495 RestoreFromBackup(dir_filepath.Append(*it));
744 result->push_back(FilePathToString(restored_table_name.BaseName())); 496 result->push_back(FilePathToString(restored_table_name.BaseName()));
745 } 497 }
746 } 498 }
747 499
748 namespace {
749 #if defined(OS_WIN)
750 static base::PlatformFileError GetDirectoryEntries(
751 const base::FilePath& dir_param,
752 std::vector<base::FilePath>* result) {
753 result->clear();
754 base::FilePath dir_filepath = dir_param.Append(FILE_PATH_LITERAL("*"));
755 WIN32_FIND_DATA find_data;
756 HANDLE find_handle = FindFirstFile(dir_filepath.value().c_str(), &find_data);
757 if (find_handle == INVALID_HANDLE_VALUE) {
758 DWORD last_error = GetLastError();
759 if (last_error == ERROR_FILE_NOT_FOUND)
760 return base::PLATFORM_FILE_OK;
761 return base::LastErrorToPlatformFileError(last_error);
762 }
763 do {
764 base::FilePath filepath(find_data.cFileName);
765 base::FilePath::StringType basename = filepath.BaseName().value();
766 if (basename == FILE_PATH_LITERAL(".") ||
767 basename == FILE_PATH_LITERAL(".."))
768 continue;
769 result->push_back(filepath.BaseName());
770 } while (FindNextFile(find_handle, &find_data));
771 DWORD last_error = GetLastError();
772 base::PlatformFileError return_value = base::PLATFORM_FILE_OK;
773 if (last_error != ERROR_NO_MORE_FILES)
774 return_value = base::LastErrorToPlatformFileError(last_error);
775 FindClose(find_handle);
776 return return_value;
777 }
778 #else
779 static base::PlatformFileError GetDirectoryEntries(
780 const base::FilePath& dir_filepath,
781 std::vector<base::FilePath>* result) {
782 const std::string dir_string = FilePathToString(dir_filepath);
783 result->clear();
784 DIR* dir = opendir(dir_string.c_str());
785 if (!dir)
786 return base::ErrnoToPlatformFileError(errno);
787 struct dirent dent_buf;
788 struct dirent* dent;
789 int readdir_result;
790 while ((readdir_result = readdir_r(dir, &dent_buf, &dent)) == 0 && dent) {
791 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
792 continue;
793 result->push_back(CreateFilePath(dent->d_name));
794 }
795 int saved_errno = errno;
796 closedir(dir);
797 if (readdir_result != 0)
798 return base::ErrnoToPlatformFileError(saved_errno);
799 return base::PLATFORM_FILE_OK;
800 }
801 #endif
802 }
803
804 Status ChromiumEnv::GetChildren(const std::string& dir_string, 500 Status ChromiumEnv::GetChildren(const std::string& dir_string,
805 std::vector<std::string>* result) { 501 std::vector<std::string>* result) {
806 std::vector<base::FilePath> entries; 502 std::vector<base::FilePath> entries;
807 base::PlatformFileError error = 503 base::PlatformFileError error =
808 GetDirectoryEntries(CreateFilePath(dir_string), &entries); 504 GetDirectoryEntries(CreateFilePath(dir_string), &entries);
809 if (error != base::PLATFORM_FILE_OK) { 505 if (error != base::PLATFORM_FILE_OK) {
810 RecordOSError(kGetChildren, error); 506 RecordOSError(kGetChildren, error);
811 return MakeIOError( 507 return MakeIOError(
812 dir_string, "Could not open/read directory", kGetChildren, error); 508 dir_string, "Could not open/read directory", kGetChildren, error);
813 } 509 }
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 RecordErrorAt(kGetTestDirectory); 690 RecordErrorAt(kGetTestDirectory);
995 return MakeIOError( 691 return MakeIOError(
996 "Could not create temp directory.", "", kGetTestDirectory); 692 "Could not create temp directory.", "", kGetTestDirectory);
997 } 693 }
998 } 694 }
999 *path = FilePathToString(test_directory_); 695 *path = FilePathToString(test_directory_);
1000 mu_.Release(); 696 mu_.Release();
1001 return Status::OK(); 697 return Status::OK();
1002 } 698 }
1003 699
1004 Status ChromiumEnv::NewLogger(const std::string& fname, Logger** result) {
1005 FILE* f = fopen_internal(fname.c_str(), "w");
1006 if (f == NULL) {
1007 *result = NULL;
1008 int saved_errno = errno;
1009 RecordOSError(kNewLogger, saved_errno);
1010 return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno);
1011 } else {
1012 *result = new ChromiumLogger(f);
1013 return Status::OK();
1014 }
1015 }
1016
1017 uint64_t ChromiumEnv::NowMicros() { 700 uint64_t ChromiumEnv::NowMicros() {
1018 return ::base::TimeTicks::Now().ToInternalValue(); 701 return ::base::TimeTicks::Now().ToInternalValue();
1019 } 702 }
1020 703
1021 void ChromiumEnv::SleepForMicroseconds(int micros) { 704 void ChromiumEnv::SleepForMicroseconds(int micros) {
1022 // Round up to the next millisecond. 705 // Round up to the next millisecond.
1023 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); 706 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros));
1024 } 707 }
1025 708
1026 void ChromiumEnv::RecordErrorAt(MethodID method) const { 709 void ChromiumEnv::RecordErrorAt(MethodID method) const {
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 } 875 }
1193 876
1194 bool ChromiumEnv::DoesDirNeedSync(const std::string& filename) { 877 bool ChromiumEnv::DoesDirNeedSync(const std::string& filename) {
1195 base::AutoLock auto_lock(map_lock_); 878 base::AutoLock auto_lock(map_lock_);
1196 return needs_sync_map_.find(GetDirName(filename)) != needs_sync_map_.end(); 879 return needs_sync_map_.find(GetDirName(filename)) != needs_sync_map_.end();
1197 } 880 }
1198 881
1199 void ChromiumEnv::DidSyncDir(const std::string& filename) { 882 void ChromiumEnv::DidSyncDir(const std::string& filename) {
1200 base::AutoLock auto_lock(map_lock_); 883 base::AutoLock auto_lock(map_lock_);
1201 needs_sync_map_.erase(GetDirName(filename)); 884 needs_sync_map_.erase(GetDirName(filename));
885 if (env_delegate_)
886 env_delegate_->DidSyncDir(filename);
1202 } 887 }
1203 888
1204 } // namespace leveldb_env 889 } // namespace leveldb_env
1205 890
1206 namespace leveldb { 891 namespace leveldb {
1207 892
893 #if defined(OS_WIN)
894 static std::string GetFieldTrialDbEnvType() {
895 static const char kFieldTrialName[] = "LevelDbEnvWin32";
896 return base::FieldTrialList::FindFullName(kFieldTrialName);
897 }
898 #endif
899
900 static void SetEnvType() {
901 DCHECK(leveldb_env::g_active_chromium_env_type ==
902 leveldb_env::CHROMIUM_ENV_UNSET);
903 #if defined(OS_WIN)
904 const CommandLine* command_line = CommandLine::ForCurrentProcess();
905 const std::string env_type_switch =
906 command_line->HasSwitch(switches::kLevelDbEnv) ?
907 command_line->GetSwitchValueASCII(switches::kLevelDbEnv) :
908 switches::kLevelDbEnvDefault;
909 if (env_type_switch == switches::kLevelDbEnvWin32) {
910 leveldb_env::g_active_chromium_env_type = leveldb_env::CHROMIUM_ENV_WIN32;
911 }
912 else if (env_type_switch == switches::kLevelDbEnvPosix) {
913 leveldb_env::g_active_chromium_env_type = leveldb_env::CHROMIUM_ENV_POSIX;
914 }
915 else {
916 if (GetFieldTrialDbEnvType() == switches::kLevelDbEnvWin32)
917 leveldb_env::g_active_chromium_env_type = leveldb_env::CHROMIUM_ENV_WIN32;
918 else
919 leveldb_env::g_active_chromium_env_type = leveldb_env::CHROMIUM_ENV_POSIX;
920 }
921 #else
922 leveldb_env::g_active_chromium_env_type = leveldb_env::CHROMIUM_ENV_POSIX;
923 #endif
924 }
925
1208 Env* IDBEnv() { 926 Env* IDBEnv() {
1209 return leveldb_env::idb_env.Pointer(); 927
928 if (leveldb_env::g_active_chromium_env_type ==
929 leveldb_env::CHROMIUM_ENV_UNSET)
930 SetEnvType();
931
932 switch (leveldb_env::g_active_chromium_env_type) {
933 case leveldb_env::CHROMIUM_ENV_POSIX:
934 return leveldb_env::idb_env_posix.Pointer();
935 #if defined(OS_WIN)
936 case leveldb_env::CHROMIUM_ENV_WIN32:
937 return leveldb_env::idb_env_win32.Pointer();
938 #endif
939 default:
940 DCHECK(false);
941 return NULL;
942 }
1210 } 943 }
1211 944
1212 Env* Env::Default() { 945 Env* Env::Default() {
1213 return leveldb_env::default_env.Pointer(); 946
947 if (leveldb_env::g_active_chromium_env_type ==
948 leveldb_env::CHROMIUM_ENV_UNSET)
949 SetEnvType();
950
951 switch (leveldb_env::g_active_chromium_env_type) {
952 case leveldb_env::CHROMIUM_ENV_POSIX:
953 return leveldb_env::default_env_posix.Pointer();
954 #if defined(OS_WIN)
955 case leveldb_env::CHROMIUM_ENV_WIN32:
956 return leveldb_env::default_env_win32.Pointer();
957 #endif
958 default:
959 DCHECK(false);
960 return NULL;
961 }
1214 } 962 }
1215 963
1216 } // namespace leveldb 964 } // namespace leveldb
1217 965
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698