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