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 |