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_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <dirent.h> | 8 #include <dirent.h> |
| 9 #include <sys/types.h> | 9 #include <sys/types.h> |
| 10 #endif | 10 #endif |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 std::string filename_; | 209 std::string filename_; |
| 210 mutable base::File file_; | 210 mutable base::File file_; |
| 211 const UMALogger* uma_logger_; | 211 const UMALogger* uma_logger_; |
| 212 }; | 212 }; |
| 213 | 213 |
| 214 class ChromiumWritableFile : public leveldb::WritableFile { | 214 class ChromiumWritableFile : public leveldb::WritableFile { |
| 215 public: | 215 public: |
| 216 ChromiumWritableFile(const std::string& fname, | 216 ChromiumWritableFile(const std::string& fname, |
| 217 base::File* f, | 217 base::File* f, |
| 218 const UMALogger* uma_logger, | 218 const UMALogger* uma_logger, |
| 219 WriteTracker* tracker, | |
| 220 bool make_backup); | 219 bool make_backup); |
| 221 virtual ~ChromiumWritableFile() {} | 220 virtual ~ChromiumWritableFile() {} |
| 222 leveldb::Status Append(const leveldb::Slice& data) override; | 221 leveldb::Status Append(const leveldb::Slice& data) override; |
| 223 leveldb::Status Close() override; | 222 leveldb::Status Close() override; |
| 224 leveldb::Status Flush() override; | 223 leveldb::Status Flush() override; |
| 225 leveldb::Status Sync() override; | 224 leveldb::Status Sync() override; |
| 226 | 225 |
| 227 private: | 226 private: |
| 228 enum Type { kManifest, kTable, kOther }; | 227 enum Type { kManifest, kTable, kOther }; |
| 229 leveldb::Status SyncParent(); | 228 leveldb::Status SyncParent(); |
| 230 | 229 |
| 231 std::string filename_; | 230 std::string filename_; |
| 232 scoped_ptr<base::File> file_; | 231 scoped_ptr<base::File> file_; |
| 233 const UMALogger* uma_logger_; | 232 const UMALogger* uma_logger_; |
| 234 WriteTracker* tracker_; | |
| 235 Type file_type_; | 233 Type file_type_; |
| 236 std::string parent_dir_; | 234 std::string parent_dir_; |
| 237 bool make_backup_; | 235 bool make_backup_; |
| 238 }; | 236 }; |
| 239 | 237 |
| 240 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, | 238 ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, |
| 241 base::File* f, | 239 base::File* f, |
| 242 const UMALogger* uma_logger, | 240 const UMALogger* uma_logger, |
| 243 WriteTracker* tracker, | |
| 244 bool make_backup) | 241 bool make_backup) |
| 245 : filename_(fname), | 242 : filename_(fname), |
| 246 file_(f), | 243 file_(f), |
| 247 uma_logger_(uma_logger), | 244 uma_logger_(uma_logger), |
| 248 tracker_(tracker), | |
| 249 file_type_(kOther), | 245 file_type_(kOther), |
| 250 make_backup_(make_backup) { | 246 make_backup_(make_backup) { |
| 251 FilePath path = FilePath::FromUTF8Unsafe(fname); | 247 FilePath path = FilePath::FromUTF8Unsafe(fname); |
| 252 if (path.BaseName().AsUTF8Unsafe().find("MANIFEST") == 0) | 248 if (path.BaseName().AsUTF8Unsafe().find("MANIFEST") == 0) |
| 253 file_type_ = kManifest; | 249 file_type_ = kManifest; |
| 254 else if (path.MatchesExtension(table_extension)) | 250 else if (path.MatchesExtension(table_extension)) |
| 255 file_type_ = kTable; | 251 file_type_ = kTable; |
| 256 if (file_type_ != kManifest) | |
| 257 tracker_->DidCreateNewFile(filename_); | |
| 258 parent_dir_ = FilePath::FromUTF8Unsafe(fname).DirName().AsUTF8Unsafe(); | 252 parent_dir_ = FilePath::FromUTF8Unsafe(fname).DirName().AsUTF8Unsafe(); |
| 259 } | 253 } |
| 260 | 254 |
| 261 Status ChromiumWritableFile::SyncParent() { | 255 Status ChromiumWritableFile::SyncParent() { |
| 262 TRACE_EVENT0("leveldb", "SyncParent"); | 256 TRACE_EVENT0("leveldb", "SyncParent"); |
| 263 #if defined(OS_POSIX) | 257 #if defined(OS_POSIX) |
| 264 FilePath path = FilePath::FromUTF8Unsafe(parent_dir_); | 258 FilePath path = FilePath::FromUTF8Unsafe(parent_dir_); |
| 265 base::File f(path, base::File::FLAG_OPEN | base::File::FLAG_READ); | 259 base::File f(path, base::File::FLAG_OPEN | base::File::FLAG_READ); |
| 266 if (!f.IsValid()) { | 260 if (!f.IsValid()) { |
| 267 return MakeIOError(parent_dir_, "Unable to open directory", kSyncParent, | 261 return MakeIOError(parent_dir_, "Unable to open directory", kSyncParent, |
| 268 f.error_details()); | 262 f.error_details()); |
| 269 } | 263 } |
| 270 if (!f.Flush()) { | 264 if (!f.Flush()) { |
| 271 base::File::Error error = LastFileError(); | 265 base::File::Error error = LastFileError(); |
| 272 return MakeIOError(parent_dir_, base::File::ErrorToString(error), | 266 return MakeIOError(parent_dir_, base::File::ErrorToString(error), |
| 273 kSyncParent, error); | 267 kSyncParent, error); |
| 274 } | 268 } |
| 275 #endif | 269 #endif |
| 276 return Status::OK(); | 270 return Status::OK(); |
| 277 } | 271 } |
| 278 | 272 |
| 279 Status ChromiumWritableFile::Append(const Slice& data) { | 273 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()); | 274 int bytes_written = file_->WriteAtCurrentPos(data.data(), data.size()); |
| 288 if (bytes_written != data.size()) { | 275 if (bytes_written != data.size()) { |
| 289 base::File::Error error = LastFileError(); | 276 base::File::Error error = LastFileError(); |
| 290 uma_logger_->RecordOSError(kWritableFileAppend, error); | 277 uma_logger_->RecordOSError(kWritableFileAppend, error); |
| 291 return MakeIOError(filename_, base::File::ErrorToString(error), | 278 return MakeIOError(filename_, base::File::ErrorToString(error), |
| 292 kWritableFileAppend, error); | 279 kWritableFileAppend, error); |
| 293 } | 280 } |
| 294 | 281 |
| 295 return Status::OK(); | 282 return Status::OK(); |
| 296 } | 283 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 312 if (!file_->Flush()) { | 299 if (!file_->Flush()) { |
| 313 base::File::Error error = LastFileError(); | 300 base::File::Error error = LastFileError(); |
| 314 uma_logger_->RecordErrorAt(kWritableFileSync); | 301 uma_logger_->RecordErrorAt(kWritableFileSync); |
| 315 return MakeIOError(filename_, base::File::ErrorToString(error), | 302 return MakeIOError(filename_, base::File::ErrorToString(error), |
| 316 kWritableFileSync, error); | 303 kWritableFileSync, error); |
| 317 } | 304 } |
| 318 | 305 |
| 319 if (make_backup_ && file_type_ == kTable) | 306 if (make_backup_ && file_type_ == kTable) |
| 320 uma_logger_->RecordBackupResult(ChromiumEnv::MakeBackup(filename_)); | 307 uma_logger_->RecordBackupResult(ChromiumEnv::MakeBackup(filename_)); |
| 321 | 308 |
| 322 return Status::OK(); | 309 // leveldb's implicit contract for Sync() is that if this instance is for a |
| 310 // manifest file then the directory is also sync'ed. See leveldb's | |
| 311 // env_posix.cc. | |
| 312 if (file_type_ == kManifest) | |
| 313 return SyncParent(); | |
| 314 else | |
|
jsbell
2015/03/23 22:42:46
Nit: Remove else since there's an early return in
| |
| 315 return Status::OK(); | |
| 323 } | 316 } |
| 324 | 317 |
| 325 class IDBEnv : public ChromiumEnv { | 318 class IDBEnv : public ChromiumEnv { |
| 326 public: | 319 public: |
| 327 IDBEnv() : ChromiumEnv() { | 320 IDBEnv() : ChromiumEnv() { |
| 328 name_ = "LevelDBEnv.IDB"; | 321 name_ = "LevelDBEnv.IDB"; |
| 329 make_backup_ = true; | 322 make_backup_ = true; |
| 330 } | 323 } |
| 331 }; | 324 }; |
| 332 | 325 |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 881 leveldb::WritableFile** result) { | 874 leveldb::WritableFile** result) { |
| 882 *result = NULL; | 875 *result = NULL; |
| 883 FilePath path = FilePath::FromUTF8Unsafe(fname); | 876 FilePath path = FilePath::FromUTF8Unsafe(fname); |
| 884 scoped_ptr<base::File> f(new base::File( | 877 scoped_ptr<base::File> f(new base::File( |
| 885 path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)); | 878 path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE)); |
| 886 if (!f->IsValid()) { | 879 if (!f->IsValid()) { |
| 887 RecordErrorAt(kNewWritableFile); | 880 RecordErrorAt(kNewWritableFile); |
| 888 return MakeIOError(fname, "Unable to create writable file", | 881 return MakeIOError(fname, "Unable to create writable file", |
| 889 kNewWritableFile, f->error_details()); | 882 kNewWritableFile, f->error_details()); |
| 890 } else { | 883 } else { |
| 891 *result = | 884 *result = new ChromiumWritableFile(fname, f.release(), this, make_backup_); |
| 892 new ChromiumWritableFile(fname, f.release(), this, this, make_backup_); | |
| 893 return Status::OK(); | 885 return Status::OK(); |
| 894 } | 886 } |
| 895 } | 887 } |
| 896 | 888 |
| 897 Status ChromiumEnv::NewAppendableFile(const std::string& fname, | 889 Status ChromiumEnv::NewAppendableFile(const std::string& fname, |
| 898 leveldb::WritableFile** result) { | 890 leveldb::WritableFile** result) { |
| 899 *result = NULL; | 891 *result = NULL; |
| 900 FilePath path = FilePath::FromUTF8Unsafe(fname); | 892 FilePath path = FilePath::FromUTF8Unsafe(fname); |
| 901 scoped_ptr<base::File> f(new base::File( | 893 scoped_ptr<base::File> f(new base::File( |
| 902 path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND)); | 894 path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND)); |
| 903 if (!f->IsValid()) { | 895 if (!f->IsValid()) { |
| 904 RecordErrorAt(kNewAppendableFile); | 896 RecordErrorAt(kNewAppendableFile); |
| 905 return MakeIOError(fname, "Unable to create appendable file", | 897 return MakeIOError(fname, "Unable to create appendable file", |
| 906 kNewAppendableFile, f->error_details()); | 898 kNewAppendableFile, f->error_details()); |
| 907 } | 899 } |
| 908 *result = | 900 *result = new ChromiumWritableFile(fname, f.release(), this, make_backup_); |
| 909 new ChromiumWritableFile(fname, f.release(), this, this, make_backup_); | |
| 910 return Status::OK(); | 901 return Status::OK(); |
| 911 } | 902 } |
| 912 | 903 |
| 913 uint64_t ChromiumEnv::NowMicros() { | 904 uint64_t ChromiumEnv::NowMicros() { |
| 914 return base::TimeTicks::Now().ToInternalValue(); | 905 return base::TimeTicks::Now().ToInternalValue(); |
| 915 } | 906 } |
| 916 | 907 |
| 917 void ChromiumEnv::SleepForMicroseconds(int micros) { | 908 void ChromiumEnv::SleepForMicroseconds(int micros) { |
| 918 // Round up to the next millisecond. | 909 // Round up to the next millisecond. |
| 919 base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros)); | 910 base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros)); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 mu_.Release(); | 1055 mu_.Release(); |
| 1065 TRACE_EVENT0("leveldb", "ChromiumEnv::BGThread-Task"); | 1056 TRACE_EVENT0("leveldb", "ChromiumEnv::BGThread-Task"); |
| 1066 (*function)(arg); | 1057 (*function)(arg); |
| 1067 } | 1058 } |
| 1068 } | 1059 } |
| 1069 | 1060 |
| 1070 void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { | 1061 void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { |
| 1071 new Thread(function, arg); // Will self-delete. | 1062 new Thread(function, arg); // Will self-delete. |
| 1072 } | 1063 } |
| 1073 | 1064 |
| 1074 static std::string GetDirName(const std::string& filename) { | |
| 1075 return FilePath::FromUTF8Unsafe(filename).DirName().AsUTF8Unsafe(); | |
| 1076 } | |
| 1077 | |
| 1078 void ChromiumEnv::DidCreateNewFile(const std::string& filename) { | |
| 1079 base::AutoLock auto_lock(directory_sync_lock_); | |
| 1080 directories_needing_sync_.insert(GetDirName(filename)); | |
| 1081 } | |
| 1082 | |
| 1083 bool ChromiumEnv::DoesDirNeedSync(const std::string& filename) { | |
| 1084 base::AutoLock auto_lock(directory_sync_lock_); | |
| 1085 return ContainsKey(directories_needing_sync_, GetDirName(filename)); | |
| 1086 } | |
| 1087 | |
| 1088 void ChromiumEnv::DidSyncDir(const std::string& filename) { | |
| 1089 base::AutoLock auto_lock(directory_sync_lock_); | |
| 1090 directories_needing_sync_.erase(GetDirName(filename)); | |
| 1091 } | |
| 1092 | |
| 1093 } // namespace leveldb_env | 1065 } // namespace leveldb_env |
| 1094 | 1066 |
| 1095 namespace leveldb { | 1067 namespace leveldb { |
| 1096 | 1068 |
| 1097 Env* IDBEnv() { | 1069 Env* IDBEnv() { |
| 1098 return leveldb_env::idb_env.Pointer(); | 1070 return leveldb_env::idb_env.Pointer(); |
| 1099 } | 1071 } |
| 1100 | 1072 |
| 1101 Env* Env::Default() { | 1073 Env* Env::Default() { |
| 1102 return leveldb_env::default_env.Pointer(); | 1074 return leveldb_env::default_env.Pointer(); |
| 1103 } | 1075 } |
| 1104 | 1076 |
| 1105 } // namespace leveldb | 1077 } // namespace leveldb |
| OLD | NEW |