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 "third_party/leveldatabase/env_chromium.h" | 5 #include "third_party/leveldatabase/env_chromium.h" |
6 | 6 |
7 #if defined(OS_WIN) | 7 #if defined(OS_POSIX) |
8 #include <io.h> | 8 #include <dirent.h> |
9 #include <sys/types.h> | |
9 #endif | 10 #endif |
10 | 11 |
11 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
13 #include "base/files/file_enumerator.h" | |
jsbell
2014/11/14 00:12:33
No longer needed?
cmumford
2014/11/14 22:43:57
Done.
| |
12 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
13 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/memory/shared_memory.h" | |
14 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
18 #include "base/process/process_metrics.h" | |
15 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
16 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
17 #include "third_party/leveldatabase/env_chromium_stdio.h" | 21 #include "third_party/leveldatabase/chromium_logger.h" |
18 #include "third_party/re2/re2/re2.h" | 22 #include "third_party/re2/re2/re2.h" |
19 | 23 |
20 #if defined(OS_WIN) | |
21 #include "base/command_line.h" | |
22 #include "base/win/win_util.h" | |
23 #include "third_party/leveldatabase/env_chromium_win.h" | |
24 #endif | |
25 | |
26 using leveldb::FileLock; | 24 using leveldb::FileLock; |
27 using leveldb::Slice; | 25 using leveldb::Slice; |
28 using leveldb::Status; | 26 using leveldb::Status; |
29 | 27 |
30 namespace leveldb_env { | 28 namespace leveldb_env { |
31 | 29 |
32 namespace { | 30 namespace { |
33 | 31 |
34 const base::FilePath::CharType backup_table_extension[] = | 32 const base::FilePath::CharType backup_table_extension[] = |
35 FILE_PATH_LITERAL(".bak"); | 33 FILE_PATH_LITERAL(".bak"); |
36 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); | 34 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); |
37 | 35 |
38 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] | 36 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] |
39 = FILE_PATH_LITERAL("leveldb-test-"); | 37 = FILE_PATH_LITERAL("leveldb-test-"); |
40 | 38 |
39 static base::File::Error LastFileError() { | |
40 #if defined(OS_WIN) | |
41 return base::File::OSErrorToFileError(GetLastError()); | |
42 #else | |
43 return base::File::OSErrorToFileError(errno); | |
44 #endif | |
45 } | |
46 | |
47 static base::File::Error GetDirectoryEntries( | |
jsbell
2014/11/14 00:12:34
Add a comment with the rationale for using this in
cmumford
2014/11/14 22:43:57
Done.
| |
48 const base::FilePath& dir_param, | |
49 std::vector<base::FilePath>* result) { | |
50 result->clear(); | |
51 #if defined(OS_WIN) | |
52 base::FilePath dir_filepath = dir_param.Append(FILE_PATH_LITERAL("*")); | |
53 WIN32_FIND_DATA find_data; | |
54 HANDLE find_handle = FindFirstFile(dir_filepath.value().c_str(), &find_data); | |
55 if (find_handle == INVALID_HANDLE_VALUE) { | |
56 DWORD last_error = GetLastError(); | |
57 if (last_error == ERROR_FILE_NOT_FOUND) | |
58 return base::File::FILE_OK; | |
59 return base::File::OSErrorToFileError(last_error); | |
60 } | |
61 do { | |
62 base::FilePath filepath(find_data.cFileName); | |
63 base::FilePath::StringType basename = filepath.BaseName().value(); | |
64 if (basename == FILE_PATH_LITERAL(".") || | |
65 basename == FILE_PATH_LITERAL("..")) | |
66 continue; | |
67 result->push_back(filepath.BaseName()); | |
68 } while (FindNextFile(find_handle, &find_data)); | |
69 DWORD last_error = GetLastError(); | |
70 base::File::Error return_value = base::File::FILE_OK; | |
71 if (last_error != ERROR_NO_MORE_FILES) | |
72 return_value = base::File::OSErrorToFileError(last_error); | |
73 FindClose(find_handle); | |
74 return return_value; | |
75 #else | |
76 const std::string dir_string = FilePathToString(dir_param); | |
77 DIR* dir = opendir(dir_string.c_str()); | |
78 if (!dir) | |
79 return base::File::OSErrorToFileError(errno); | |
80 struct dirent dent_buf; | |
81 struct dirent* dent; | |
82 int readdir_result; | |
83 while ((readdir_result = readdir_r(dir, &dent_buf, &dent)) == 0 && dent) { | |
84 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) | |
85 continue; | |
86 result->push_back(ChromiumEnv::CreateFilePath(dent->d_name)); | |
87 } | |
88 int saved_errno = errno; | |
89 closedir(dir); | |
90 if (readdir_result != 0) | |
91 return base::File::OSErrorToFileError(saved_errno); | |
92 return base::File::FILE_OK; | |
93 #endif | |
94 } | |
95 | |
41 class ChromiumFileLock : public FileLock { | 96 class ChromiumFileLock : public FileLock { |
42 public: | 97 public: |
43 ::base::File file_; | 98 ::base::File file_; |
jsbell
2014/11/14 00:12:33
Bit of a tangent but... what's up with ::base vs.
cmumford
2014/11/14 22:43:57
I have another CL that will follow up this one wit
| |
44 std::string name_; | 99 std::string name_; |
45 }; | 100 }; |
46 | 101 |
47 class Retrier { | 102 class Retrier { |
48 public: | 103 public: |
49 Retrier(MethodID method, RetrierProvider* provider) | 104 Retrier(MethodID method, RetrierProvider* provider) |
50 : start_(base::TimeTicks::Now()), | 105 : start_(base::TimeTicks::Now()), |
51 limit_(start_ + base::TimeDelta::FromMilliseconds( | 106 limit_(start_ + base::TimeDelta::FromMilliseconds( |
52 provider->MaxRetryTimeMillis())), | 107 provider->MaxRetryTimeMillis())), |
53 last_(start_), | 108 last_(start_), |
(...skipping 27 matching lines...) Expand all Loading... | |
81 base::TimeTicks start_; | 136 base::TimeTicks start_; |
82 base::TimeTicks limit_; | 137 base::TimeTicks limit_; |
83 base::TimeTicks last_; | 138 base::TimeTicks last_; |
84 base::TimeDelta time_to_sleep_; | 139 base::TimeDelta time_to_sleep_; |
85 bool success_; | 140 bool success_; |
86 MethodID method_; | 141 MethodID method_; |
87 base::File::Error last_error_; | 142 base::File::Error last_error_; |
88 RetrierProvider* provider_; | 143 RetrierProvider* provider_; |
89 }; | 144 }; |
90 | 145 |
91 class IDBEnvStdio : public ChromiumEnvStdio { | 146 class ChromiumSequentialFile : public leveldb::SequentialFile { |
92 public: | 147 public: |
93 IDBEnvStdio() : ChromiumEnvStdio() { | 148 ChromiumSequentialFile(const std::string& fname, |
149 base::File* f, | |
150 const UMALogger* uma_logger) | |
151 : filename_(fname), file_(f), uma_logger_(uma_logger) {} | |
152 virtual ~ChromiumSequentialFile() {} | |
153 | |
154 Status Read(size_t n, Slice* result, char* scratch) override { | |
155 int bytes_read = file_->ReadAtCurrentPos(scratch, n); | |
156 if (bytes_read == -1) { | |
157 base::File::Error error = LastFileError(); | |
158 uma_logger_->RecordErrorAt(kSequentialFileRead); | |
159 return MakeIOError(filename_, base::File::ErrorToString(error), | |
160 kSequentialFileRead, error); | |
161 } else { | |
162 *result = Slice(scratch, bytes_read); | |
163 return Status::OK(); | |
164 } | |
165 } | |
166 | |
167 Status Skip(uint64_t n) override { | |
168 if (file_->Seek(base::File::FROM_CURRENT, n) == -1) { | |
169 base::File::Error error = LastFileError(); | |
170 uma_logger_->RecordErrorAt(kSequentialFileSkip); | |
171 return MakeIOError(filename_, base::File::ErrorToString(error), | |
172 kSequentialFileSkip, error); | |
173 } else { | |
174 return Status::OK(); | |
175 } | |
176 } | |
177 | |
178 private: | |
179 std::string filename_; | |
180 scoped_ptr<base::File> file_; | |
181 const UMALogger* uma_logger_; | |
182 }; | |
183 | |
184 class ChromiumRandomAccessFile : public leveldb::RandomAccessFile { | |
185 public: | |
186 ChromiumRandomAccessFile(const std::string& fname, | |
187 ::base::File file, | |
188 const UMALogger* uma_logger) | |
189 : filename_(fname), file_(file.Pass()), uma_logger_(uma_logger) {} | |
190 virtual ~ChromiumRandomAccessFile() {} | |
191 | |
192 Status Read(uint64_t offset, | |
193 size_t n, | |
194 Slice* result, | |
195 char* scratch) const override { | |
196 Status s; | |
197 int r = file_.Read(offset, scratch, n); | |
198 *result = Slice(scratch, (r < 0) ? 0 : r); | |
199 if (r < 0) { | |
200 // An error: return a non-ok status | |
201 s = MakeIOError(filename_, "Could not perform read", | |
202 kRandomAccessFileRead); | |
203 uma_logger_->RecordErrorAt(kRandomAccessFileRead); | |
204 } | |
205 return s; | |
206 } | |
207 | |
208 private: | |
209 std::string filename_; | |
210 mutable ::base::File file_; | |
211 const UMALogger* uma_logger_; | |
212 }; | |
213 | |
214 class ChromiumWritableFile : public leveldb::WritableFile { | |
215 public: | |
216 ChromiumWritableFile(const std::string& fname, | |
217 base::File* f, | |
218 const UMALogger* uma_logger, | |
219 WriteTracker* tracker, | |
220 bool make_backup); | |
221 virtual ~ChromiumWritableFile() {} | |
222 leveldb::Status Append(const leveldb::Slice& data) override; | |
223 leveldb::Status Close() override; | |
224 leveldb::Status Flush() override; | |
225 leveldb::Status Sync() override; | |
226 | |
227 private: | |
228 enum Type { kManifest, kTable, kOther }; | |
229 leveldb::Status SyncParent(); | |
230 | |
231 std::string filename_; | |
232 scoped_ptr<base::File> file_; | |
233 const UMALogger* uma_logger_; | |
234 WriteTracker* tracker_; | |
235 Type file_type_; | |
236 std::string parent_dir_; | |
237 bool make_backup_; | |
238 }; | |
239 | |
240 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, | |
241 base::File* f, | |
242 const UMALogger* uma_logger, | |
243 WriteTracker* tracker, | |
244 bool make_backup) | |
245 : filename_(fname), | |
246 file_(f), | |
247 uma_logger_(uma_logger), | |
248 tracker_(tracker), | |
249 file_type_(kOther), | |
250 make_backup_(make_backup) { | |
251 base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); | |
252 if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) | |
253 file_type_ = kManifest; | |
254 else if (ChromiumEnv::HasTableExtension(path)) | |
255 file_type_ = kTable; | |
256 if (file_type_ != kManifest) | |
257 tracker_->DidCreateNewFile(filename_); | |
258 parent_dir_ = FilePathToString(ChromiumEnv::CreateFilePath(fname).DirName()); | |
259 } | |
260 | |
261 Status ChromiumWritableFile::SyncParent() { | |
262 TRACE_EVENT0("leveldb", "SyncParent"); | |
263 #if defined(OS_POSIX) | |
264 base::FilePath path = base::FilePath::FromUTF8Unsafe(parent_dir_); | |
265 base::File f(path, base::File::FLAG_OPEN | base::File::FLAG_READ); | |
266 if (!f.IsValid()) { | |
267 return MakeIOError(parent_dir_, "Unable to open directory", kSyncParent, | |
268 f.error_details()); | |
269 } | |
270 if (!f.Flush()) { | |
271 base::File::Error error = LastFileError(); | |
272 return MakeIOError(parent_dir_, base::File::ErrorToString(error), | |
273 kSyncParent, error); | |
274 } | |
275 #endif | |
276 return Status::OK(); | |
277 } | |
278 | |
279 Status ChromiumWritableFile::Append(const Slice& data) { | |
280 if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { | |
281 Status s = SyncParent(); | |
282 if (!s.ok()) | |
283 return s; | |
284 tracker_->DidSyncDir(filename_); | |
285 } | |
286 | |
287 int bytes_written = file_->WriteAtCurrentPos(data.data(), data.size()); | |
288 if (bytes_written != data.size()) { | |
289 base::File::Error error = LastFileError(); | |
290 uma_logger_->RecordOSError(kWritableFileAppend, error); | |
291 return MakeIOError(filename_, base::File::ErrorToString(error), | |
292 kWritableFileAppend, error); | |
293 } | |
294 | |
295 return Status::OK(); | |
296 } | |
297 | |
298 Status ChromiumWritableFile::Close() { | |
299 file_->Close(); | |
300 return Status::OK(); | |
301 } | |
302 | |
303 Status ChromiumWritableFile::Flush() { | |
304 // base::File doesn't do buffered I/O (i.e. POSIX FILE streams) so nothing to | |
305 // flush. | |
306 return Status::OK(); | |
307 } | |
308 | |
309 Status ChromiumWritableFile::Sync() { | |
310 TRACE_EVENT0("leveldb", "WritableFile::Sync"); | |
311 | |
312 if (!file_->Flush()) { | |
313 base::File::Error error = LastFileError(); | |
314 uma_logger_->RecordErrorAt(kWritableFileSync); | |
315 return MakeIOError(filename_, base::File::ErrorToString(error), | |
316 kWritableFileSync, error); | |
317 } | |
318 | |
319 if (make_backup_ && file_type_ == kTable) | |
320 uma_logger_->RecordBackupResult(ChromiumEnv::MakeBackup(filename_)); | |
321 | |
322 return Status::OK(); | |
323 } | |
324 | |
325 class IDBEnv : public ChromiumEnv { | |
326 public: | |
327 IDBEnv() : ChromiumEnv() { | |
94 name_ = "LevelDBEnv.IDB"; | 328 name_ = "LevelDBEnv.IDB"; |
95 make_backup_ = true; | 329 make_backup_ = true; |
96 } | 330 } |
97 }; | 331 }; |
98 | 332 |
99 #if defined(OS_WIN) | 333 ::base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; |
100 class IDBEnvWin : public ChromiumEnvWin { | |
101 public: | |
102 IDBEnvWin() : ChromiumEnvWin() { | |
103 name_ = "LevelDBEnv.IDB"; | |
104 make_backup_ = true; | |
105 } | |
106 }; | |
107 #endif | |
108 | 334 |
109 #if defined(OS_WIN) | 335 ::base::LazyInstance<ChromiumEnv>::Leaky default_env = |
110 ::base::LazyInstance<IDBEnvWin>::Leaky idb_env = | |
111 LAZY_INSTANCE_INITIALIZER; | |
112 #else | |
113 ::base::LazyInstance<IDBEnvStdio>::Leaky idb_env = | |
114 LAZY_INSTANCE_INITIALIZER; | |
115 #endif | |
116 | |
117 ::base::LazyInstance<ChromiumEnvStdio>::Leaky default_env = | |
118 LAZY_INSTANCE_INITIALIZER; | 336 LAZY_INSTANCE_INITIALIZER; |
119 | 337 |
120 } // unnamed namespace | 338 } // unnamed namespace |
121 | 339 |
122 const char* MethodIDToString(MethodID method) { | 340 const char* MethodIDToString(MethodID method) { |
123 switch (method) { | 341 switch (method) { |
124 case kSequentialFileRead: | 342 case kSequentialFileRead: |
125 return "SequentialFileRead"; | 343 return "SequentialFileRead"; |
126 case kSequentialFileSkip: | 344 case kSequentialFileSkip: |
127 return "SequentialFileSkip"; | 345 return "SequentialFileSkip"; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
165 return "GetChildren"; | 383 return "GetChildren"; |
166 case kNumEntries: | 384 case kNumEntries: |
167 NOTREACHED(); | 385 NOTREACHED(); |
168 return "kNumEntries"; | 386 return "kNumEntries"; |
169 } | 387 } |
170 NOTREACHED(); | 388 NOTREACHED(); |
171 return "Unknown"; | 389 return "Unknown"; |
172 } | 390 } |
173 | 391 |
174 Status MakeIOError(Slice filename, | 392 Status MakeIOError(Slice filename, |
175 const char* message, | 393 const std::string& message, |
176 MethodID method, | 394 MethodID method, |
177 int saved_errno) { | 395 base::File::Error error) { |
396 DCHECK_LT(error, 0); | |
178 char buf[512]; | 397 char buf[512]; |
179 snprintf(buf, | 398 snprintf(buf, sizeof(buf), "%s (ChromeMethodPFE: %d::%s::%d)", |
180 sizeof(buf), | 399 message.c_str(), method, MethodIDToString(method), -error); |
181 "%s (ChromeMethodErrno: %d::%s::%d)", | |
182 message, | |
183 method, | |
184 MethodIDToString(method), | |
185 saved_errno); | |
186 return Status::IOError(filename, buf); | 400 return Status::IOError(filename, buf); |
187 } | 401 } |
188 | 402 |
189 Status MakeIOError(Slice filename, | 403 Status MakeIOError(Slice filename, |
190 const char* message, | 404 const std::string& message, |
191 MethodID method, | 405 MethodID method) { |
192 base::File::Error error) { | |
193 DCHECK_LT(error, 0); | |
194 char buf[512]; | 406 char buf[512]; |
195 snprintf(buf, | 407 snprintf(buf, sizeof(buf), "%s (ChromeMethodOnly: %d::%s)", message.c_str(), |
196 sizeof(buf), | 408 method, MethodIDToString(method)); |
197 "%s (ChromeMethodPFE: %d::%s::%d)", | |
198 message, | |
199 method, | |
200 MethodIDToString(method), | |
201 -error); | |
202 return Status::IOError(filename, buf); | 409 return Status::IOError(filename, buf); |
203 } | 410 } |
204 | 411 |
205 Status MakeIOError(Slice filename, const char* message, MethodID method) { | |
206 char buf[512]; | |
207 snprintf(buf, | |
208 sizeof(buf), | |
209 "%s (ChromeMethodOnly: %d::%s)", | |
210 message, | |
211 method, | |
212 MethodIDToString(method)); | |
213 return Status::IOError(filename, buf); | |
214 } | |
215 | |
216 ErrorParsingResult ParseMethodAndError(const char* string, | 412 ErrorParsingResult ParseMethodAndError(const char* string, |
217 MethodID* method_param, | 413 MethodID* method_param, |
218 int* error) { | 414 int* error) { |
219 int method; | 415 int method; |
220 if (RE2::PartialMatch(string, "ChromeMethodOnly: (\\d+)", &method)) { | 416 if (RE2::PartialMatch(string, "ChromeMethodOnly: (\\d+)", &method)) { |
221 *method_param = static_cast<MethodID>(method); | 417 *method_param = static_cast<MethodID>(method); |
222 return METHOD_ONLY; | 418 return METHOD_ONLY; |
223 } | 419 } |
224 if (RE2::PartialMatch( | 420 if (RE2::PartialMatch( |
225 string, "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, error)) { | 421 string, "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, error)) { |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 Status ChromiumEnv::GetChildren(const std::string& dir_string, | 663 Status ChromiumEnv::GetChildren(const std::string& dir_string, |
468 std::vector<std::string>* result) { | 664 std::vector<std::string>* result) { |
469 std::vector<base::FilePath> entries; | 665 std::vector<base::FilePath> entries; |
470 base::File::Error error = | 666 base::File::Error error = |
471 GetDirectoryEntries(CreateFilePath(dir_string), &entries); | 667 GetDirectoryEntries(CreateFilePath(dir_string), &entries); |
472 if (error != base::File::FILE_OK) { | 668 if (error != base::File::FILE_OK) { |
473 RecordOSError(kGetChildren, error); | 669 RecordOSError(kGetChildren, error); |
474 return MakeIOError( | 670 return MakeIOError( |
475 dir_string, "Could not open/read directory", kGetChildren, error); | 671 dir_string, "Could not open/read directory", kGetChildren, error); |
476 } | 672 } |
673 | |
477 result->clear(); | 674 result->clear(); |
478 for (std::vector<base::FilePath>::iterator it = entries.begin(); | 675 for (const auto& entry : entries) |
479 it != entries.end(); | 676 result->push_back(FilePathToString(entry)); |
480 ++it) { | |
481 result->push_back(FilePathToString(*it)); | |
482 } | |
483 | 677 |
484 if (make_backup_) | 678 if (make_backup_) |
485 RestoreIfNecessary(dir_string, result); | 679 RestoreIfNecessary(dir_string, result); |
680 | |
486 return Status::OK(); | 681 return Status::OK(); |
487 } | 682 } |
488 | 683 |
489 Status ChromiumEnv::DeleteFile(const std::string& fname) { | 684 Status ChromiumEnv::DeleteFile(const std::string& fname) { |
490 Status result; | 685 Status result; |
491 base::FilePath fname_filepath = CreateFilePath(fname); | 686 base::FilePath fname_filepath = CreateFilePath(fname); |
492 // TODO(jorlow): Should we assert this is a file? | 687 // TODO(jorlow): Should we assert this is a file? |
493 if (!::base::DeleteFile(fname_filepath, false)) { | 688 if (!::base::DeleteFile(fname_filepath, false)) { |
494 result = MakeIOError(fname, "Could not delete file.", kDeleteFile); | 689 result = MakeIOError(fname, "Could not delete file.", kDeleteFile); |
495 RecordErrorAt(kDeleteFile); | 690 RecordErrorAt(kDeleteFile); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
648 RecordErrorAt(kGetTestDirectory); | 843 RecordErrorAt(kGetTestDirectory); |
649 return MakeIOError( | 844 return MakeIOError( |
650 "Could not create temp directory.", "", kGetTestDirectory); | 845 "Could not create temp directory.", "", kGetTestDirectory); |
651 } | 846 } |
652 } | 847 } |
653 *path = FilePathToString(test_directory_); | 848 *path = FilePathToString(test_directory_); |
654 mu_.Release(); | 849 mu_.Release(); |
655 return Status::OK(); | 850 return Status::OK(); |
656 } | 851 } |
657 | 852 |
853 Status ChromiumEnv::NewLogger(const std::string& fname, | |
854 leveldb::Logger** result) { | |
855 base::FilePath path = CreateFilePath(fname); | |
856 scoped_ptr<base::File> f(new base::File( | |
857 path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)); | |
858 if (!f->IsValid()) { | |
859 *result = NULL; | |
860 RecordOSError(kNewLogger, f->error_details()); | |
861 return MakeIOError(fname, "Unable to create log file", kNewLogger, | |
862 f->error_details()); | |
863 } else { | |
864 *result = new leveldb::ChromiumLogger(f.release()); | |
865 return Status::OK(); | |
866 } | |
867 } | |
868 | |
869 Status ChromiumEnv::NewSequentialFile(const std::string& fname, | |
870 leveldb::SequentialFile** result) { | |
871 base::FilePath path = CreateFilePath(fname); | |
872 scoped_ptr<base::File> f( | |
873 new base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ)); | |
874 if (!f->IsValid()) { | |
875 *result = NULL; | |
876 RecordOSError(kNewSequentialFile, f->error_details()); | |
877 return MakeIOError(fname, "Unable to create sequential file", | |
878 kNewSequentialFile, f->error_details()); | |
879 } else { | |
880 *result = new ChromiumSequentialFile(fname, f.release(), this); | |
881 return Status::OK(); | |
882 } | |
883 } | |
884 | |
885 void ChromiumEnv::RecordOpenFilesLimit(const std::string& type) { | |
886 #if defined(OS_POSIX) | |
887 GetMaxFDHistogram(type)->Add(base::GetMaxFds()); | |
888 #elif defined(OS_WIN) | |
889 // Windows is only limited by available memory | |
890 #else | |
891 #error "Need to determine limit to open files for this OS" | |
892 #endif | |
893 } | |
894 | |
895 Status ChromiumEnv::NewRandomAccessFile(const std::string& fname, | |
896 leveldb::RandomAccessFile** result) { | |
897 int flags = ::base::File::FLAG_READ | ::base::File::FLAG_OPEN; | |
898 ::base::File file(ChromiumEnv::CreateFilePath(fname), flags); | |
899 if (file.IsValid()) { | |
900 *result = new ChromiumRandomAccessFile(fname, file.Pass(), this); | |
901 RecordOpenFilesLimit("Success"); | |
902 return Status::OK(); | |
903 } | |
904 ::base::File::Error error_code = file.error_details(); | |
905 if (error_code == ::base::File::FILE_ERROR_TOO_MANY_OPENED) | |
906 RecordOpenFilesLimit("TooManyOpened"); | |
907 else | |
908 RecordOpenFilesLimit("OtherError"); | |
909 *result = NULL; | |
910 RecordOSError(kNewRandomAccessFile, error_code); | |
911 return MakeIOError(fname, FileErrorString(error_code), kNewRandomAccessFile, | |
912 error_code); | |
913 } | |
914 | |
915 Status ChromiumEnv::NewWritableFile(const std::string& fname, | |
916 leveldb::WritableFile** result) { | |
917 *result = NULL; | |
918 base::FilePath path = CreateFilePath(fname); | |
919 scoped_ptr<base::File> f(new base::File( | |
920 path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)); | |
921 if (!f->IsValid()) { | |
922 RecordErrorAt(kNewWritableFile); | |
923 return MakeIOError(fname, "Unable to create writable file", | |
924 kNewWritableFile, f->error_details()); | |
925 } else { | |
926 *result = | |
927 new ChromiumWritableFile(fname, f.release(), this, this, make_backup_); | |
928 return Status::OK(); | |
929 } | |
930 } | |
931 | |
658 uint64_t ChromiumEnv::NowMicros() { | 932 uint64_t ChromiumEnv::NowMicros() { |
659 return ::base::TimeTicks::Now().ToInternalValue(); | 933 return ::base::TimeTicks::Now().ToInternalValue(); |
660 } | 934 } |
661 | 935 |
662 void ChromiumEnv::SleepForMicroseconds(int micros) { | 936 void ChromiumEnv::SleepForMicroseconds(int micros) { |
663 // Round up to the next millisecond. | 937 // Round up to the next millisecond. |
664 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); | 938 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); |
665 } | 939 } |
666 | 940 |
667 void ChromiumEnv::RecordErrorAt(MethodID method) const { | 941 void ChromiumEnv::RecordErrorAt(MethodID method) const { |
668 GetMethodIOErrorHistogram()->Add(method); | 942 GetMethodIOErrorHistogram()->Add(method); |
669 } | 943 } |
670 | 944 |
671 void ChromiumEnv::RecordLockFileAncestors(int num_missing_ancestors) const { | 945 void ChromiumEnv::RecordLockFileAncestors(int num_missing_ancestors) const { |
672 GetLockFileAncestorHistogram()->Add(num_missing_ancestors); | 946 GetLockFileAncestorHistogram()->Add(num_missing_ancestors); |
673 } | 947 } |
674 | 948 |
675 void ChromiumEnv::RecordOSError(MethodID method, | 949 void ChromiumEnv::RecordOSError(MethodID method, |
676 base::File::Error error) const { | 950 base::File::Error error) const { |
677 DCHECK_LT(error, 0); | 951 DCHECK_LT(error, 0); |
678 RecordErrorAt(method); | 952 RecordErrorAt(method); |
679 GetOSErrorHistogram(method, -base::File::FILE_ERROR_MAX)->Add(-error); | 953 GetOSErrorHistogram(method, -base::File::FILE_ERROR_MAX)->Add(-error); |
680 } | 954 } |
681 | 955 |
682 void ChromiumEnv::RecordOSError(MethodID method, int error) const { | |
683 DCHECK_GT(error, 0); | |
684 RecordErrorAt(method); | |
685 GetOSErrorHistogram(method, ERANGE + 1)->Add(error); | |
686 } | |
687 | |
688 void ChromiumEnv::RecordBackupResult(bool result) const { | 956 void ChromiumEnv::RecordBackupResult(bool result) const { |
689 std::string uma_name(name_); | 957 std::string uma_name(name_); |
690 uma_name.append(".TableBackup"); | 958 uma_name.append(".TableBackup"); |
691 base::BooleanHistogram::FactoryGet( | 959 base::BooleanHistogram::FactoryGet( |
692 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); | 960 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); |
693 } | 961 } |
694 | 962 |
695 base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, | 963 base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, |
696 int limit) const { | 964 int limit) const { |
697 std::string uma_name(name_); | 965 std::string uma_name(name_); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
758 | 1026 |
759 class Thread : public ::base::PlatformThread::Delegate { | 1027 class Thread : public ::base::PlatformThread::Delegate { |
760 public: | 1028 public: |
761 Thread(void (*function)(void* arg), void* arg) | 1029 Thread(void (*function)(void* arg), void* arg) |
762 : function_(function), arg_(arg) { | 1030 : function_(function), arg_(arg) { |
763 ::base::PlatformThreadHandle handle; | 1031 ::base::PlatformThreadHandle handle; |
764 bool success = ::base::PlatformThread::Create(0, this, &handle); | 1032 bool success = ::base::PlatformThread::Create(0, this, &handle); |
765 DCHECK(success); | 1033 DCHECK(success); |
766 } | 1034 } |
767 virtual ~Thread() {} | 1035 virtual ~Thread() {} |
768 virtual void ThreadMain() { | 1036 void ThreadMain() override { |
769 (*function_)(arg_); | 1037 (*function_)(arg_); |
770 delete this; | 1038 delete this; |
771 } | 1039 } |
772 | 1040 |
773 private: | 1041 private: |
774 void (*function_)(void* arg); | 1042 void (*function_)(void* arg); |
775 void* arg_; | 1043 void* arg_; |
776 }; | 1044 }; |
777 | 1045 |
778 void ChromiumEnv::Schedule(ScheduleFunc* function, void* arg) { | 1046 void ChromiumEnv::Schedule(ScheduleFunc* function, void* arg) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
848 | 1116 |
849 Env* IDBEnv() { | 1117 Env* IDBEnv() { |
850 return leveldb_env::idb_env.Pointer(); | 1118 return leveldb_env::idb_env.Pointer(); |
851 } | 1119 } |
852 | 1120 |
853 Env* Env::Default() { | 1121 Env* Env::Default() { |
854 return leveldb_env::default_env.Pointer(); | 1122 return leveldb_env::default_env.Pointer(); |
855 } | 1123 } |
856 | 1124 |
857 } // namespace leveldb | 1125 } // namespace leveldb |
OLD | NEW |