Chromium Code Reviews| 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) | |
| 8 #include <io.h> | |
| 9 #endif | |
| 10 | |
| 11 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
| 8 #include "base/files/file_enumerator.h" | |
| 12 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 13 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/memory/shared_memory.h" | |
| 14 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/process/process_metrics.h" | |
| 15 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 17 #include "third_party/leveldatabase/env_chromium_stdio.h" | 16 #include "third_party/leveldatabase/chromium_logger.h" |
| 18 #include "third_party/re2/re2/re2.h" | 17 #include "third_party/re2/re2/re2.h" |
| 19 | 18 |
| 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; | 19 using leveldb::FileLock; |
| 27 using leveldb::Slice; | 20 using leveldb::Slice; |
| 28 using leveldb::Status; | 21 using leveldb::Status; |
| 29 | 22 |
| 30 namespace leveldb_env { | 23 namespace leveldb_env { |
| 31 | 24 |
| 32 namespace { | 25 namespace { |
| 33 | 26 |
| 34 const base::FilePath::CharType backup_table_extension[] = | 27 const base::FilePath::CharType backup_table_extension[] = |
| 35 FILE_PATH_LITERAL(".bak"); | 28 FILE_PATH_LITERAL(".bak"); |
| 36 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); | 29 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); |
| 37 | 30 |
| 38 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] | 31 static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] |
| 39 = FILE_PATH_LITERAL("leveldb-test-"); | 32 = FILE_PATH_LITERAL("leveldb-test-"); |
| 40 | 33 |
| 34 static base::File::Error LastFileError() { | |
| 35 #if defined(OS_WIN) | |
| 36 return base::File::OSErrorToFileError(GetLastError()); | |
| 37 #else | |
| 38 return base::File::OSErrorToFileError(errno); | |
| 39 #endif | |
| 40 } | |
| 41 | |
| 41 class ChromiumFileLock : public FileLock { | 42 class ChromiumFileLock : public FileLock { |
| 42 public: | 43 public: |
| 43 ::base::File file_; | 44 ::base::File file_; |
| 44 std::string name_; | 45 std::string name_; |
| 45 }; | 46 }; |
| 46 | 47 |
| 47 class Retrier { | 48 class Retrier { |
| 48 public: | 49 public: |
| 49 Retrier(MethodID method, RetrierProvider* provider) | 50 Retrier(MethodID method, RetrierProvider* provider) |
| 50 : start_(base::TimeTicks::Now()), | 51 : start_(base::TimeTicks::Now()), |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 81 base::TimeTicks start_; | 82 base::TimeTicks start_; |
| 82 base::TimeTicks limit_; | 83 base::TimeTicks limit_; |
| 83 base::TimeTicks last_; | 84 base::TimeTicks last_; |
| 84 base::TimeDelta time_to_sleep_; | 85 base::TimeDelta time_to_sleep_; |
| 85 bool success_; | 86 bool success_; |
| 86 MethodID method_; | 87 MethodID method_; |
| 87 base::File::Error last_error_; | 88 base::File::Error last_error_; |
| 88 RetrierProvider* provider_; | 89 RetrierProvider* provider_; |
| 89 }; | 90 }; |
| 90 | 91 |
| 91 class IDBEnvStdio : public ChromiumEnvStdio { | 92 class ChromiumSequentialFile : public leveldb::SequentialFile { |
| 92 public: | 93 public: |
| 93 IDBEnvStdio() : ChromiumEnvStdio() { | 94 ChromiumSequentialFile(const std::string& fname, |
| 95 base::File* f, | |
| 96 const UMALogger* uma_logger) | |
| 97 : filename_(fname), file_(f), uma_logger_(uma_logger) {} | |
| 98 virtual ~ChromiumSequentialFile() {} | |
| 99 | |
| 100 Status Read(size_t n, Slice* result, char* scratch) override { | |
| 101 int bytes_read = file_->ReadAtCurrentPos(scratch, n); | |
| 102 if (bytes_read == -1) { | |
| 103 base::File::Error error = LastFileError(); | |
| 104 uma_logger_->RecordErrorAt(kSequentialFileRead); | |
| 105 return MakeIOError(filename_, base::File::ErrorToString(error), | |
| 106 kSequentialFileRead, error); | |
| 107 } else { | |
| 108 *result = Slice(scratch, bytes_read); | |
| 109 return Status::OK(); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 Status Skip(uint64_t n) override { | |
| 114 if (file_->Seek(base::File::FROM_CURRENT, n) == -1) { | |
| 115 base::File::Error error = LastFileError(); | |
| 116 uma_logger_->RecordErrorAt(kSequentialFileSkip); | |
| 117 return MakeIOError(filename_, base::File::ErrorToString(error), | |
| 118 kSequentialFileSkip, error); | |
| 119 } else { | |
| 120 return Status::OK(); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 private: | |
| 125 std::string filename_; | |
| 126 scoped_ptr<base::File> file_; | |
| 127 const UMALogger* uma_logger_; | |
| 128 }; | |
| 129 | |
| 130 class ChromiumRandomAccessFile : public leveldb::RandomAccessFile { | |
| 131 public: | |
| 132 ChromiumRandomAccessFile(const std::string& fname, | |
| 133 ::base::File file, | |
| 134 const UMALogger* uma_logger) | |
| 135 : filename_(fname), file_(file.Pass()), uma_logger_(uma_logger) {} | |
| 136 virtual ~ChromiumRandomAccessFile() {} | |
| 137 | |
| 138 Status Read(uint64_t offset, | |
| 139 size_t n, | |
| 140 Slice* result, | |
| 141 char* scratch) const override { | |
| 142 Status s; | |
| 143 int r = file_.Read(offset, scratch, n); | |
| 144 *result = Slice(scratch, (r < 0) ? 0 : r); | |
| 145 if (r < 0) { | |
| 146 // An error: return a non-ok status | |
| 147 s = MakeIOError(filename_, "Could not perform read", | |
| 148 kRandomAccessFileRead); | |
| 149 uma_logger_->RecordErrorAt(kRandomAccessFileRead); | |
| 150 } | |
| 151 return s; | |
| 152 } | |
| 153 | |
| 154 private: | |
| 155 std::string filename_; | |
| 156 mutable ::base::File file_; | |
| 157 const UMALogger* uma_logger_; | |
| 158 }; | |
| 159 | |
| 160 class ChromiumWritableFile : public leveldb::WritableFile { | |
| 161 public: | |
| 162 ChromiumWritableFile(const std::string& fname, | |
| 163 base::File* f, | |
| 164 const UMALogger* uma_logger, | |
| 165 WriteTracker* tracker, | |
| 166 bool make_backup); | |
| 167 virtual ~ChromiumWritableFile() {} | |
| 168 leveldb::Status Append(const leveldb::Slice& data) override; | |
| 169 leveldb::Status Close() override; | |
| 170 leveldb::Status Flush() override; | |
| 171 leveldb::Status Sync() override; | |
| 172 | |
| 173 private: | |
| 174 enum Type { kManifest, kTable, kOther }; | |
| 175 leveldb::Status SyncParent(); | |
| 176 | |
| 177 std::string filename_; | |
| 178 scoped_ptr<base::File> file_; | |
| 179 const UMALogger* uma_logger_; | |
| 180 WriteTracker* tracker_; | |
| 181 Type file_type_; | |
| 182 std::string parent_dir_; | |
| 183 bool make_backup_; | |
| 184 }; | |
| 185 | |
| 186 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, | |
| 187 base::File* f, | |
| 188 const UMALogger* uma_logger, | |
| 189 WriteTracker* tracker, | |
| 190 bool make_backup) | |
| 191 : filename_(fname), | |
| 192 file_(f), | |
| 193 uma_logger_(uma_logger), | |
| 194 tracker_(tracker), | |
| 195 file_type_(kOther), | |
| 196 make_backup_(make_backup) { | |
| 197 base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); | |
| 198 if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) | |
| 199 file_type_ = kManifest; | |
| 200 else if (ChromiumEnv::HasTableExtension(path)) | |
| 201 file_type_ = kTable; | |
| 202 if (file_type_ != kManifest) | |
| 203 tracker_->DidCreateNewFile(filename_); | |
| 204 parent_dir_ = FilePathToString(ChromiumEnv::CreateFilePath(fname).DirName()); | |
| 205 } | |
| 206 | |
| 207 Status ChromiumWritableFile::SyncParent() { | |
| 208 TRACE_EVENT0("leveldb", "SyncParent"); | |
| 209 #if defined(OS_POSIX) | |
| 210 base::FilePath path = base::FilePath::FromUTF8Unsafe(parent_dir_); | |
| 211 base::File f(path, base::File::FLAG_OPEN | base::File::FLAG_READ); | |
| 212 if (!f.IsValid()) { | |
| 213 return MakeIOError(parent_dir_, "Unable to open directory", kSyncParent, | |
| 214 f.error_details()); | |
| 215 } | |
| 216 if (!f.Flush()) { | |
| 217 base::File::Error error = LastFileError(); | |
| 218 return MakeIOError(parent_dir_, base::File::ErrorToString(error), | |
| 219 kSyncParent, error); | |
| 220 } | |
| 221 #endif | |
| 222 return Status::OK(); | |
| 223 } | |
| 224 | |
| 225 Status ChromiumWritableFile::Append(const Slice& data) { | |
| 226 if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { | |
| 227 Status s = SyncParent(); | |
| 228 if (!s.ok()) | |
| 229 return s; | |
| 230 tracker_->DidSyncDir(filename_); | |
| 231 } | |
| 232 | |
| 233 int bytes_written = file_->WriteAtCurrentPos(data.data(), data.size()); | |
| 234 if (bytes_written != data.size()) { | |
| 235 base::File::Error error = LastFileError(); | |
| 236 uma_logger_->RecordOSError(kWritableFileAppend, error); | |
| 237 return MakeIOError(filename_, base::File::ErrorToString(error), | |
| 238 kWritableFileAppend, error); | |
| 239 } | |
| 240 | |
| 241 return Status::OK(); | |
| 242 } | |
| 243 | |
| 244 Status ChromiumWritableFile::Close() { | |
| 245 file_->Close(); | |
| 246 return Status::OK(); | |
| 247 } | |
| 248 | |
| 249 Status ChromiumWritableFile::Flush() { | |
| 250 // base::File doesn't do buffered I/O (i.e. POSIX FILE streams) so nothing to | |
| 251 // flush. | |
| 252 return Status::OK(); | |
| 253 } | |
| 254 | |
| 255 Status ChromiumWritableFile::Sync() { | |
| 256 TRACE_EVENT0("leveldb", "WritableFile::Sync"); | |
| 257 | |
| 258 if (!file_->Flush()) { | |
| 259 base::File::Error error = LastFileError(); | |
| 260 uma_logger_->RecordErrorAt(kWritableFileSync); | |
| 261 return MakeIOError(filename_, base::File::ErrorToString(error), | |
| 262 kWritableFileSync, error); | |
| 263 } | |
| 264 | |
| 265 if (make_backup_ && file_type_ == kTable) | |
| 266 uma_logger_->RecordBackupResult(ChromiumEnv::MakeBackup(filename_)); | |
| 267 | |
| 268 return Status::OK(); | |
| 269 } | |
| 270 | |
| 271 class IDBEnv : public ChromiumEnv { | |
| 272 public: | |
| 273 IDBEnv() : ChromiumEnv() { | |
| 94 name_ = "LevelDBEnv.IDB"; | 274 name_ = "LevelDBEnv.IDB"; |
| 95 make_backup_ = true; | 275 make_backup_ = true; |
| 96 } | 276 } |
| 97 }; | 277 }; |
| 98 | 278 |
| 99 #if defined(OS_WIN) | 279 ::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 | 280 |
| 109 #if defined(OS_WIN) | 281 ::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; | 282 LAZY_INSTANCE_INITIALIZER; |
| 119 | 283 |
| 120 } // unnamed namespace | 284 } // unnamed namespace |
| 121 | 285 |
| 122 const char* MethodIDToString(MethodID method) { | 286 const char* MethodIDToString(MethodID method) { |
| 123 switch (method) { | 287 switch (method) { |
| 124 case kSequentialFileRead: | 288 case kSequentialFileRead: |
| 125 return "SequentialFileRead"; | 289 return "SequentialFileRead"; |
| 126 case kSequentialFileSkip: | 290 case kSequentialFileSkip: |
| 127 return "SequentialFileSkip"; | 291 return "SequentialFileSkip"; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 return "GetChildren"; | 329 return "GetChildren"; |
| 166 case kNumEntries: | 330 case kNumEntries: |
| 167 NOTREACHED(); | 331 NOTREACHED(); |
| 168 return "kNumEntries"; | 332 return "kNumEntries"; |
| 169 } | 333 } |
| 170 NOTREACHED(); | 334 NOTREACHED(); |
| 171 return "Unknown"; | 335 return "Unknown"; |
| 172 } | 336 } |
| 173 | 337 |
| 174 Status MakeIOError(Slice filename, | 338 Status MakeIOError(Slice filename, |
| 175 const char* message, | 339 const std::string& message, |
| 176 MethodID method, | 340 MethodID method, |
| 177 int saved_errno) { | 341 base::File::Error error) { |
| 342 DCHECK_LT(error, 0); | |
| 178 char buf[512]; | 343 char buf[512]; |
| 179 snprintf(buf, | 344 snprintf(buf, sizeof(buf), "%s (ChromeMethodPFE: %d::%s::%d)", |
| 180 sizeof(buf), | 345 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); | 346 return Status::IOError(filename, buf); |
| 187 } | 347 } |
| 188 | 348 |
| 189 Status MakeIOError(Slice filename, | 349 Status MakeIOError(Slice filename, |
| 190 const char* message, | 350 const std::string& message, |
| 191 MethodID method, | 351 MethodID method) { |
| 192 base::File::Error error) { | |
| 193 DCHECK_LT(error, 0); | |
| 194 char buf[512]; | 352 char buf[512]; |
| 195 snprintf(buf, | 353 snprintf(buf, sizeof(buf), "%s (ChromeMethodOnly: %d::%s)", message.c_str(), |
| 196 sizeof(buf), | 354 method, MethodIDToString(method)); |
| 197 "%s (ChromeMethodPFE: %d::%s::%d)", | |
| 198 message, | |
| 199 method, | |
| 200 MethodIDToString(method), | |
| 201 -error); | |
| 202 return Status::IOError(filename, buf); | 355 return Status::IOError(filename, buf); |
| 203 } | 356 } |
| 204 | 357 |
| 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, | 358 ErrorParsingResult ParseMethodAndError(const char* string, |
| 217 MethodID* method_param, | 359 MethodID* method_param, |
| 218 int* error) { | 360 int* error) { |
| 219 int method; | 361 int method; |
| 220 if (RE2::PartialMatch(string, "ChromeMethodOnly: (\\d+)", &method)) { | 362 if (RE2::PartialMatch(string, "ChromeMethodOnly: (\\d+)", &method)) { |
| 221 *method_param = static_cast<MethodID>(method); | 363 *method_param = static_cast<MethodID>(method); |
| 222 return METHOD_ONLY; | 364 return METHOD_ONLY; |
| 223 } | 365 } |
| 224 if (RE2::PartialMatch( | 366 if (RE2::PartialMatch( |
| 225 string, "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, error)) { | 367 string, "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, error)) { |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 it != backups_only.end(); | 601 it != backups_only.end(); |
| 460 ++it) { | 602 ++it) { |
| 461 base::FilePath restored_table_name = | 603 base::FilePath restored_table_name = |
| 462 RestoreFromBackup(dir_filepath.Append(*it)); | 604 RestoreFromBackup(dir_filepath.Append(*it)); |
| 463 result->push_back(FilePathToString(restored_table_name.BaseName())); | 605 result->push_back(FilePathToString(restored_table_name.BaseName())); |
| 464 } | 606 } |
| 465 } | 607 } |
| 466 | 608 |
| 467 Status ChromiumEnv::GetChildren(const std::string& dir_string, | 609 Status ChromiumEnv::GetChildren(const std::string& dir_string, |
| 468 std::vector<std::string>* result) { | 610 std::vector<std::string>* result) { |
| 469 std::vector<base::FilePath> entries; | 611 result->clear(); |
| 470 base::File::Error error = | 612 base::FilePath dir_path = CreateFilePath(dir_string); |
| 471 GetDirectoryEntries(CreateFilePath(dir_string), &entries); | 613 if (!DirectoryExists(dir_path)) { |
| 472 if (error != base::File::FILE_OK) { | 614 RecordErrorAt(kGetChildren); |
| 473 RecordOSError(kGetChildren, error); | 615 return MakeIOError(dir_string, "Could not open/read directory", |
| 474 return MakeIOError( | 616 kGetChildren); |
| 475 dir_string, "Could not open/read directory", kGetChildren, error); | |
| 476 } | 617 } |
| 477 result->clear(); | 618 base::FileEnumerator enumerator(dir_path, |
|
dgrogan
2014/11/12 22:45:11
As Josh hinted, moving back to FileEnumerator will
cmumford
2014/11/12 23:52:41
So right now LevelDB calls GetChildren in four pla
| |
| 478 for (std::vector<base::FilePath>::iterator it = entries.begin(); | 619 false, // not recursive |
| 479 it != entries.end(); | 620 base::FileEnumerator::FILES); |
| 480 ++it) { | 621 for (base::FilePath current = enumerator.Next(); !current.empty(); |
| 481 result->push_back(FilePathToString(*it)); | 622 current = enumerator.Next()) { |
| 623 result->push_back(FilePathToString(current.BaseName())); | |
| 482 } | 624 } |
| 483 | 625 |
| 484 if (make_backup_) | 626 if (make_backup_) |
| 485 RestoreIfNecessary(dir_string, result); | 627 RestoreIfNecessary(dir_string, result); |
| 486 return Status::OK(); | 628 return Status::OK(); |
| 487 } | 629 } |
| 488 | 630 |
| 489 Status ChromiumEnv::DeleteFile(const std::string& fname) { | 631 Status ChromiumEnv::DeleteFile(const std::string& fname) { |
| 490 Status result; | 632 Status result; |
| 491 base::FilePath fname_filepath = CreateFilePath(fname); | 633 base::FilePath fname_filepath = CreateFilePath(fname); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 RecordErrorAt(kGetTestDirectory); | 790 RecordErrorAt(kGetTestDirectory); |
| 649 return MakeIOError( | 791 return MakeIOError( |
| 650 "Could not create temp directory.", "", kGetTestDirectory); | 792 "Could not create temp directory.", "", kGetTestDirectory); |
| 651 } | 793 } |
| 652 } | 794 } |
| 653 *path = FilePathToString(test_directory_); | 795 *path = FilePathToString(test_directory_); |
| 654 mu_.Release(); | 796 mu_.Release(); |
| 655 return Status::OK(); | 797 return Status::OK(); |
| 656 } | 798 } |
| 657 | 799 |
| 800 Status ChromiumEnv::NewLogger(const std::string& fname, | |
| 801 leveldb::Logger** result) { | |
| 802 base::FilePath path = CreateFilePath(fname); | |
| 803 scoped_ptr<base::File> f(new base::File( | |
| 804 path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)); | |
| 805 if (!f->IsValid()) { | |
| 806 *result = NULL; | |
| 807 RecordOSError(kNewLogger, f->error_details()); | |
| 808 return MakeIOError(fname, "Unable to create log file", kNewLogger, | |
| 809 f->error_details()); | |
| 810 } else { | |
| 811 *result = new leveldb::ChromiumLogger(f.release()); | |
| 812 return Status::OK(); | |
| 813 } | |
| 814 } | |
| 815 | |
| 816 Status ChromiumEnv::NewSequentialFile(const std::string& fname, | |
| 817 leveldb::SequentialFile** result) { | |
| 818 base::FilePath path = CreateFilePath(fname); | |
| 819 scoped_ptr<base::File> f( | |
| 820 new base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ)); | |
| 821 if (!f->IsValid()) { | |
| 822 *result = NULL; | |
| 823 RecordOSError(kNewSequentialFile, f->error_details()); | |
| 824 return MakeIOError(fname, "Unable to create sequential file", | |
| 825 kNewSequentialFile, f->error_details()); | |
| 826 } else { | |
| 827 *result = new ChromiumSequentialFile(fname, f.release(), this); | |
| 828 return Status::OK(); | |
| 829 } | |
| 830 } | |
| 831 | |
| 832 void ChromiumEnv::RecordOpenFilesLimit(const std::string& type) { | |
| 833 #if defined(OS_POSIX) | |
| 834 GetMaxFDHistogram(type)->Add(base::GetMaxFds()); | |
| 835 #elif defined(OS_WIN) | |
| 836 // Windows is only limited by available memory | |
| 837 #else | |
| 838 #error "Need to determine limit to open files for this OS" | |
| 839 #endif | |
| 840 } | |
| 841 | |
| 842 Status ChromiumEnv::NewRandomAccessFile(const std::string& fname, | |
| 843 leveldb::RandomAccessFile** result) { | |
| 844 int flags = ::base::File::FLAG_READ | ::base::File::FLAG_OPEN; | |
| 845 ::base::File file(ChromiumEnv::CreateFilePath(fname), flags); | |
| 846 if (file.IsValid()) { | |
| 847 *result = new ChromiumRandomAccessFile(fname, file.Pass(), this); | |
| 848 RecordOpenFilesLimit("Success"); | |
| 849 return Status::OK(); | |
| 850 } | |
| 851 ::base::File::Error error_code = file.error_details(); | |
| 852 if (error_code == ::base::File::FILE_ERROR_TOO_MANY_OPENED) | |
| 853 RecordOpenFilesLimit("TooManyOpened"); | |
| 854 else | |
| 855 RecordOpenFilesLimit("OtherError"); | |
| 856 *result = NULL; | |
| 857 RecordOSError(kNewRandomAccessFile, error_code); | |
| 858 return MakeIOError(fname, FileErrorString(error_code), kNewRandomAccessFile, | |
| 859 error_code); | |
| 860 } | |
| 861 | |
| 862 Status ChromiumEnv::NewWritableFile(const std::string& fname, | |
| 863 leveldb::WritableFile** result) { | |
| 864 *result = NULL; | |
| 865 base::FilePath path = CreateFilePath(fname); | |
| 866 scoped_ptr<base::File> f(new base::File( | |
| 867 path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)); | |
| 868 if (!f->IsValid()) { | |
| 869 RecordErrorAt(kNewWritableFile); | |
| 870 return MakeIOError(fname, "Unable to create writable file", | |
| 871 kNewWritableFile, f->error_details()); | |
| 872 } else { | |
| 873 *result = | |
| 874 new ChromiumWritableFile(fname, f.release(), this, this, make_backup_); | |
| 875 return Status::OK(); | |
| 876 } | |
| 877 } | |
| 878 | |
| 658 uint64_t ChromiumEnv::NowMicros() { | 879 uint64_t ChromiumEnv::NowMicros() { |
| 659 return ::base::TimeTicks::Now().ToInternalValue(); | 880 return ::base::TimeTicks::Now().ToInternalValue(); |
| 660 } | 881 } |
| 661 | 882 |
| 662 void ChromiumEnv::SleepForMicroseconds(int micros) { | 883 void ChromiumEnv::SleepForMicroseconds(int micros) { |
| 663 // Round up to the next millisecond. | 884 // Round up to the next millisecond. |
| 664 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); | 885 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); |
| 665 } | 886 } |
| 666 | 887 |
| 667 void ChromiumEnv::RecordErrorAt(MethodID method) const { | 888 void ChromiumEnv::RecordErrorAt(MethodID method) const { |
| 668 GetMethodIOErrorHistogram()->Add(method); | 889 GetMethodIOErrorHistogram()->Add(method); |
| 669 } | 890 } |
| 670 | 891 |
| 671 void ChromiumEnv::RecordLockFileAncestors(int num_missing_ancestors) const { | 892 void ChromiumEnv::RecordLockFileAncestors(int num_missing_ancestors) const { |
| 672 GetLockFileAncestorHistogram()->Add(num_missing_ancestors); | 893 GetLockFileAncestorHistogram()->Add(num_missing_ancestors); |
| 673 } | 894 } |
| 674 | 895 |
| 675 void ChromiumEnv::RecordOSError(MethodID method, | 896 void ChromiumEnv::RecordOSError(MethodID method, |
| 676 base::File::Error error) const { | 897 base::File::Error error) const { |
| 677 DCHECK_LT(error, 0); | 898 DCHECK_LT(error, 0); |
| 678 RecordErrorAt(method); | 899 RecordErrorAt(method); |
| 679 GetOSErrorHistogram(method, -base::File::FILE_ERROR_MAX)->Add(-error); | 900 GetOSErrorHistogram(method, -base::File::FILE_ERROR_MAX)->Add(-error); |
| 680 } | 901 } |
| 681 | 902 |
| 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 { | 903 void ChromiumEnv::RecordBackupResult(bool result) const { |
| 689 std::string uma_name(name_); | 904 std::string uma_name(name_); |
| 690 uma_name.append(".TableBackup"); | 905 uma_name.append(".TableBackup"); |
| 691 base::BooleanHistogram::FactoryGet( | 906 base::BooleanHistogram::FactoryGet( |
| 692 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); | 907 uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); |
| 693 } | 908 } |
| 694 | 909 |
| 695 base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, | 910 base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, |
| 696 int limit) const { | 911 int limit) const { |
| 697 std::string uma_name(name_); | 912 std::string uma_name(name_); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 | 973 |
| 759 class Thread : public ::base::PlatformThread::Delegate { | 974 class Thread : public ::base::PlatformThread::Delegate { |
| 760 public: | 975 public: |
| 761 Thread(void (*function)(void* arg), void* arg) | 976 Thread(void (*function)(void* arg), void* arg) |
| 762 : function_(function), arg_(arg) { | 977 : function_(function), arg_(arg) { |
| 763 ::base::PlatformThreadHandle handle; | 978 ::base::PlatformThreadHandle handle; |
| 764 bool success = ::base::PlatformThread::Create(0, this, &handle); | 979 bool success = ::base::PlatformThread::Create(0, this, &handle); |
| 765 DCHECK(success); | 980 DCHECK(success); |
| 766 } | 981 } |
| 767 virtual ~Thread() {} | 982 virtual ~Thread() {} |
| 768 virtual void ThreadMain() { | 983 void ThreadMain() override { |
| 769 (*function_)(arg_); | 984 (*function_)(arg_); |
| 770 delete this; | 985 delete this; |
| 771 } | 986 } |
| 772 | 987 |
| 773 private: | 988 private: |
| 774 void (*function_)(void* arg); | 989 void (*function_)(void* arg); |
| 775 void* arg_; | 990 void* arg_; |
| 776 }; | 991 }; |
| 777 | 992 |
| 778 void ChromiumEnv::Schedule(ScheduleFunc* function, void* arg) { | 993 void ChromiumEnv::Schedule(ScheduleFunc* function, void* arg) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 848 | 1063 |
| 849 Env* IDBEnv() { | 1064 Env* IDBEnv() { |
| 850 return leveldb_env::idb_env.Pointer(); | 1065 return leveldb_env::idb_env.Pointer(); |
| 851 } | 1066 } |
| 852 | 1067 |
| 853 Env* Env::Default() { | 1068 Env* Env::Default() { |
| 854 return leveldb_env::default_env.Pointer(); | 1069 return leveldb_env::default_env.Pointer(); |
| 855 } | 1070 } |
| 856 | 1071 |
| 857 } // namespace leveldb | 1072 } // namespace leveldb |
| OLD | NEW |