Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium 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. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/leveldb/env_mojo.h" | 5 #include "components/leveldb/env_mojo.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/metrics/histogram_macros.h" | |
| 11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 12 #include "base/task_scheduler/post_task.h" | 13 #include "base/task_scheduler/post_task.h" |
| 13 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 14 #include "third_party/leveldatabase/chromium_logger.h" | 15 #include "third_party/leveldatabase/chromium_logger.h" |
| 15 #include "third_party/leveldatabase/env_chromium.h" | |
| 16 #include "third_party/leveldatabase/src/include/leveldb/status.h" | 16 #include "third_party/leveldatabase/src/include/leveldb/status.h" |
| 17 | 17 |
| 18 using filesystem::mojom::FileError; | |
| 19 using leveldb_env::UMALogger; | |
| 20 | |
| 18 namespace leveldb { | 21 namespace leveldb { |
| 19 | 22 |
| 20 namespace { | 23 namespace { |
| 21 | 24 |
| 22 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); | 25 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); |
| 23 | 26 |
| 24 base::File::Error LastFileError() { | 27 base::File::Error LastFileError() { |
| 25 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
| 26 return base::File::OSErrorToFileError(GetLastError()); | 29 return base::File::OSErrorToFileError(GetLastError()); |
| 27 #else | 30 #else |
| 28 return base::File::OSErrorToFileError(errno); | 31 return base::File::OSErrorToFileError(errno); |
| 29 #endif | 32 #endif |
| 30 } | 33 } |
| 31 | 34 |
| 32 Status FilesystemErrorToStatus(filesystem::mojom::FileError error, | 35 Status FilesystemErrorToStatus(FileError error, |
| 33 const std::string& filename, | 36 const std::string& filename, |
| 34 leveldb_env::MethodID method) { | 37 leveldb_env::MethodID method) { |
| 35 if (error == filesystem::mojom::FileError::OK) | 38 if (error == FileError::OK) |
| 36 return Status::OK(); | 39 return Status::OK(); |
| 37 | 40 |
| 38 std::string err_str = | 41 std::string err_str = |
| 39 base::File::ErrorToString(base::File::Error(static_cast<int>(error))); | 42 base::File::ErrorToString(base::File::Error(static_cast<int>(error))); |
| 40 | 43 |
| 41 char buf[512]; | 44 char buf[512]; |
| 42 snprintf(buf, sizeof(buf), "%s (MojoFSError: %d::%s)", err_str.c_str(), | 45 snprintf(buf, sizeof(buf), "%s (MojoFSError: %d::%s)", err_str.c_str(), |
| 43 method, MethodIDToString(method)); | 46 method, MethodIDToString(method)); |
| 44 return Status::IOError(filename, buf); | 47 return Status::IOError(filename, buf); |
| 45 } | 48 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 58 return to_return; | 61 return to_return; |
| 59 } | 62 } |
| 60 | 63 |
| 61 private: | 64 private: |
| 62 std::string fname_; | 65 std::string fname_; |
| 63 LevelDBMojoProxy::OpaqueLock* lock_; | 66 LevelDBMojoProxy::OpaqueLock* lock_; |
| 64 }; | 67 }; |
| 65 | 68 |
| 66 class MojoSequentialFile : public leveldb::SequentialFile { | 69 class MojoSequentialFile : public leveldb::SequentialFile { |
| 67 public: | 70 public: |
| 68 MojoSequentialFile(const std::string& fname, base::File f) | 71 MojoSequentialFile(const std::string& fname, |
| 69 : filename_(fname), file_(std::move(f)) {} | 72 base::File f, |
| 73 const UMALogger* uma_logger) | |
| 74 : filename_(fname), file_(std::move(f)), uma_logger_(uma_logger) {} | |
| 70 ~MojoSequentialFile() override {} | 75 ~MojoSequentialFile() override {} |
| 71 | 76 |
| 72 Status Read(size_t n, Slice* result, char* scratch) override { | 77 Status Read(size_t n, Slice* result, char* scratch) override { |
| 73 int bytes_read = file_.ReadAtCurrentPosNoBestEffort( | 78 int bytes_read = file_.ReadAtCurrentPosNoBestEffort( |
| 74 scratch, | 79 scratch, |
| 75 static_cast<int>(n)); | 80 static_cast<int>(n)); |
| 76 if (bytes_read == -1) { | 81 if (bytes_read == -1) { |
| 77 base::File::Error error = LastFileError(); | 82 base::File::Error error = LastFileError(); |
| 83 uma_logger_->RecordOSError(leveldb_env::kSequentialFileRead, error); | |
| 78 return MakeIOError(filename_, base::File::ErrorToString(error), | 84 return MakeIOError(filename_, base::File::ErrorToString(error), |
| 79 leveldb_env::kSequentialFileRead, error); | 85 leveldb_env::kSequentialFileRead, error); |
| 80 } else { | 86 } else { |
| 81 *result = Slice(scratch, bytes_read); | 87 *result = Slice(scratch, bytes_read); |
| 82 return Status::OK(); | 88 return Status::OK(); |
| 83 } | 89 } |
| 84 } | 90 } |
| 85 | 91 |
| 86 Status Skip(uint64_t n) override { | 92 Status Skip(uint64_t n) override { |
| 87 if (file_.Seek(base::File::FROM_CURRENT, n) == -1) { | 93 if (file_.Seek(base::File::FROM_CURRENT, n) == -1) { |
| 88 base::File::Error error = LastFileError(); | 94 base::File::Error error = LastFileError(); |
| 95 uma_logger_->RecordOSError(leveldb_env::kSequentialFileSkip, error); | |
| 89 return MakeIOError(filename_, base::File::ErrorToString(error), | 96 return MakeIOError(filename_, base::File::ErrorToString(error), |
| 90 leveldb_env::kSequentialFileSkip, error); | 97 leveldb_env::kSequentialFileSkip, error); |
| 91 } else { | 98 } else { |
| 92 return Status::OK(); | 99 return Status::OK(); |
| 93 } | 100 } |
| 94 } | 101 } |
| 95 | 102 |
| 96 private: | 103 private: |
| 97 std::string filename_; | 104 std::string filename_; |
| 98 base::File file_; | 105 base::File file_; |
| 106 const UMALogger* uma_logger_; | |
| 99 | 107 |
| 100 DISALLOW_COPY_AND_ASSIGN(MojoSequentialFile); | 108 DISALLOW_COPY_AND_ASSIGN(MojoSequentialFile); |
| 101 }; | 109 }; |
| 102 | 110 |
| 103 class MojoRandomAccessFile : public leveldb::RandomAccessFile { | 111 class MojoRandomAccessFile : public leveldb::RandomAccessFile { |
| 104 public: | 112 public: |
| 105 MojoRandomAccessFile(const std::string& fname, base::File file) | 113 MojoRandomAccessFile(const std::string& fname, |
| 106 : filename_(fname), file_(std::move(file)) {} | 114 base::File file, |
| 115 const UMALogger* uma_logger) | |
| 116 : filename_(fname), file_(std::move(file)), uma_logger_(uma_logger) {} | |
| 107 ~MojoRandomAccessFile() override {} | 117 ~MojoRandomAccessFile() override {} |
| 108 | 118 |
| 109 Status Read(uint64_t offset, | 119 Status Read(uint64_t offset, |
| 110 size_t n, | 120 size_t n, |
| 111 Slice* result, | 121 Slice* result, |
| 112 char* scratch) const override { | 122 char* scratch) const override { |
| 113 Status s; | 123 Status s; |
| 114 int r = file_.Read(offset, scratch, static_cast<int>(n)); | 124 int r = file_.Read(offset, scratch, static_cast<int>(n)); |
| 115 *result = Slice(scratch, (r < 0) ? 0 : r); | 125 *result = Slice(scratch, (r < 0) ? 0 : r); |
| 116 if (r < 0) { | 126 if (r < 0) { |
| 117 // An error: return a non-ok status | 127 // An error: return a non-ok status |
| 118 s = MakeIOError(filename_, "Could not perform read", | 128 s = MakeIOError(filename_, "Could not perform read", |
| 119 leveldb_env::kRandomAccessFileRead); | 129 leveldb_env::kRandomAccessFileRead); |
| 130 uma_logger_->RecordOSError(leveldb_env::kRandomAccessFileRead, | |
| 131 LastFileError()); | |
| 120 } | 132 } |
| 121 return s; | 133 return s; |
| 122 } | 134 } |
| 123 | 135 |
| 124 private: | 136 private: |
| 125 std::string filename_; | 137 std::string filename_; |
| 126 mutable base::File file_; | 138 mutable base::File file_; |
| 139 const UMALogger* uma_logger_; | |
| 127 | 140 |
| 128 DISALLOW_COPY_AND_ASSIGN(MojoRandomAccessFile); | 141 DISALLOW_COPY_AND_ASSIGN(MojoRandomAccessFile); |
| 129 }; | 142 }; |
| 130 | 143 |
| 131 class MojoWritableFile : public leveldb::WritableFile { | 144 class MojoWritableFile : public leveldb::WritableFile { |
| 132 public: | 145 public: |
| 133 MojoWritableFile(LevelDBMojoProxy::OpaqueDir* dir, | 146 MojoWritableFile(LevelDBMojoProxy::OpaqueDir* dir, |
| 134 const std::string& fname, | 147 const std::string& fname, |
| 135 base::File f, | 148 base::File f, |
| 136 scoped_refptr<LevelDBMojoProxy> thread) | 149 scoped_refptr<LevelDBMojoProxy> thread, |
| 150 const UMALogger* uma_logger) | |
| 137 : filename_(fname), | 151 : filename_(fname), |
| 138 file_(std::move(f)), | 152 file_(std::move(f)), |
| 139 file_type_(kOther), | 153 file_type_(kOther), |
| 140 dir_(dir), | 154 dir_(dir), |
| 141 thread_(thread) { | 155 thread_(thread), |
| 156 uma_logger_(uma_logger) { | |
| 142 base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); | 157 base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); |
| 143 if (base::StartsWith(path.BaseName().AsUTF8Unsafe(), "MANIFEST", | 158 if (base::StartsWith(path.BaseName().AsUTF8Unsafe(), "MANIFEST", |
| 144 base::CompareCase::SENSITIVE)) { | 159 base::CompareCase::SENSITIVE)) { |
| 145 file_type_ = kManifest; | 160 file_type_ = kManifest; |
| 146 } else if (path.MatchesExtension(table_extension)) { | 161 } else if (path.MatchesExtension(table_extension)) { |
| 147 file_type_ = kTable; | 162 file_type_ = kTable; |
| 148 } | 163 } |
| 149 parent_dir_ = | 164 parent_dir_ = |
| 150 base::FilePath::FromUTF8Unsafe(fname).DirName().AsUTF8Unsafe(); | 165 base::FilePath::FromUTF8Unsafe(fname).DirName().AsUTF8Unsafe(); |
| 151 } | 166 } |
| 152 | 167 |
| 153 ~MojoWritableFile() override {} | 168 ~MojoWritableFile() override {} |
| 154 | 169 |
| 155 leveldb::Status Append(const leveldb::Slice& data) override { | 170 leveldb::Status Append(const leveldb::Slice& data) override { |
| 156 size_t bytes_written = file_.WriteAtCurrentPos( | 171 size_t bytes_written = file_.WriteAtCurrentPos( |
| 157 data.data(), static_cast<int>(data.size())); | 172 data.data(), static_cast<int>(data.size())); |
| 158 if (bytes_written != data.size()) { | 173 if (bytes_written != data.size()) { |
| 159 base::File::Error error = LastFileError(); | 174 base::File::Error error = LastFileError(); |
| 175 uma_logger_->RecordOSError(leveldb_env::kWritableFileAppend, error); | |
| 160 return MakeIOError(filename_, base::File::ErrorToString(error), | 176 return MakeIOError(filename_, base::File::ErrorToString(error), |
| 161 leveldb_env::kWritableFileAppend, error); | 177 leveldb_env::kWritableFileAppend, error); |
| 162 } | 178 } |
| 163 | 179 |
| 164 return Status::OK(); | 180 return Status::OK(); |
| 165 } | 181 } |
| 166 | 182 |
| 167 leveldb::Status Close() override { | 183 leveldb::Status Close() override { |
| 168 file_.Close(); | 184 file_.Close(); |
| 169 return Status::OK(); | 185 return Status::OK(); |
| 170 } | 186 } |
| 171 | 187 |
| 172 leveldb::Status Flush() override { | 188 leveldb::Status Flush() override { |
| 173 // base::File doesn't do buffered I/O (i.e. POSIX FILE streams) so nothing | 189 // base::File doesn't do buffered I/O (i.e. POSIX FILE streams) so nothing |
| 174 // to | 190 // to |
| 175 // flush. | 191 // flush. |
| 176 return Status::OK(); | 192 return Status::OK(); |
| 177 } | 193 } |
| 178 | 194 |
| 179 leveldb::Status Sync() override { | 195 leveldb::Status Sync() override { |
| 180 TRACE_EVENT0("leveldb", "MojoWritableFile::Sync"); | 196 TRACE_EVENT0("leveldb", "MojoWritableFile::Sync"); |
| 181 | 197 |
| 182 if (!file_.Flush()) { | 198 if (!file_.Flush()) { |
| 183 base::File::Error error = LastFileError(); | 199 base::File::Error error = LastFileError(); |
| 200 uma_logger_->RecordOSError(leveldb_env::kWritableFileSync, error); | |
| 184 return MakeIOError(filename_, base::File::ErrorToString(error), | 201 return MakeIOError(filename_, base::File::ErrorToString(error), |
| 185 leveldb_env::kWritableFileSync, error); | 202 leveldb_env::kWritableFileSync, error); |
| 186 } | 203 } |
| 187 | 204 |
| 188 // leveldb's implicit contract for Sync() is that if this instance is for a | 205 // leveldb's implicit contract for Sync() is that if this instance is for a |
| 189 // manifest file then the directory is also sync'ed. See leveldb's | 206 // manifest file then the directory is also sync'ed. See leveldb's |
| 190 // env_posix.cc. | 207 // env_posix.cc. |
| 191 if (file_type_ == kManifest) | 208 if (file_type_ == kManifest) |
| 192 return SyncParent(); | 209 return SyncParent(); |
| 193 | 210 |
| 194 return Status::OK(); | 211 return Status::OK(); |
| 195 } | 212 } |
| 196 | 213 |
| 197 private: | 214 private: |
| 198 enum Type { kManifest, kTable, kOther }; | 215 enum Type { kManifest, kTable, kOther }; |
| 199 | 216 |
| 200 leveldb::Status SyncParent() { | 217 leveldb::Status SyncParent() { |
| 201 filesystem::mojom::FileError error = | 218 FileError error = thread_->SyncDirectory(dir_, parent_dir_); |
| 202 thread_->SyncDirectory(dir_, parent_dir_); | 219 return error == FileError::OK |
| 203 return error == filesystem::mojom::FileError::OK | |
| 204 ? Status::OK() | 220 ? Status::OK() |
| 205 : Status::IOError(filename_, | 221 : Status::IOError(filename_, |
| 206 base::File::ErrorToString(base::File::Error( | 222 base::File::ErrorToString(base::File::Error( |
| 207 static_cast<int>(error)))); | 223 static_cast<int>(error)))); |
| 208 } | 224 } |
| 209 | 225 |
| 210 std::string filename_; | 226 std::string filename_; |
| 211 base::File file_; | 227 base::File file_; |
| 212 Type file_type_; | 228 Type file_type_; |
| 213 LevelDBMojoProxy::OpaqueDir* dir_; | 229 LevelDBMojoProxy::OpaqueDir* dir_; |
| 214 std::string parent_dir_; | 230 std::string parent_dir_; |
| 215 scoped_refptr<LevelDBMojoProxy> thread_; | 231 scoped_refptr<LevelDBMojoProxy> thread_; |
| 232 const UMALogger* uma_logger_; | |
| 216 | 233 |
| 217 DISALLOW_COPY_AND_ASSIGN(MojoWritableFile); | 234 DISALLOW_COPY_AND_ASSIGN(MojoWritableFile); |
| 218 }; | 235 }; |
| 219 | 236 |
| 220 class Thread : public base::PlatformThread::Delegate { | 237 class Thread : public base::PlatformThread::Delegate { |
| 221 public: | 238 public: |
| 222 Thread(void (*function)(void* arg), void* arg) | 239 Thread(void (*function)(void* arg), void* arg) |
| 223 : function_(function), arg_(arg) { | 240 : function_(function), arg_(arg) { |
| 224 base::PlatformThreadHandle handle; | 241 base::PlatformThreadHandle handle; |
| 225 bool success = base::PlatformThread::Create(0, this, &handle); | 242 bool success = base::PlatformThread::Create(0, this, &handle); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 248 thread_->UnregisterDirectory(dir_); | 265 thread_->UnregisterDirectory(dir_); |
| 249 } | 266 } |
| 250 | 267 |
| 251 Status MojoEnv::NewSequentialFile(const std::string& fname, | 268 Status MojoEnv::NewSequentialFile(const std::string& fname, |
| 252 SequentialFile** result) { | 269 SequentialFile** result) { |
| 253 TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname); | 270 TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname); |
| 254 base::File f = thread_->OpenFileHandle( | 271 base::File f = thread_->OpenFileHandle( |
| 255 dir_, fname, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead); | 272 dir_, fname, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead); |
| 256 if (!f.IsValid()) { | 273 if (!f.IsValid()) { |
| 257 *result = nullptr; | 274 *result = nullptr; |
| 275 RecordOSError(leveldb_env::kNewSequentialFile, f.error_details()); | |
| 258 return MakeIOError(fname, "Unable to create sequential file", | 276 return MakeIOError(fname, "Unable to create sequential file", |
| 259 leveldb_env::kNewSequentialFile, f.error_details()); | 277 leveldb_env::kNewSequentialFile, f.error_details()); |
| 260 } | 278 } |
| 261 | 279 |
| 262 *result = new MojoSequentialFile(fname, std::move(f)); | 280 *result = new MojoSequentialFile(fname, std::move(f), this); |
| 263 return Status::OK(); | 281 return Status::OK(); |
| 264 } | 282 } |
| 265 | 283 |
| 266 Status MojoEnv::NewRandomAccessFile(const std::string& fname, | 284 Status MojoEnv::NewRandomAccessFile(const std::string& fname, |
| 267 RandomAccessFile** result) { | 285 RandomAccessFile** result) { |
| 268 TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname); | 286 TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname); |
| 269 base::File f = thread_->OpenFileHandle( | 287 base::File f = thread_->OpenFileHandle( |
| 270 dir_, fname, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen); | 288 dir_, fname, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen); |
| 271 if (!f.IsValid()) { | 289 if (!f.IsValid()) { |
| 272 *result = nullptr; | 290 *result = nullptr; |
| 273 base::File::Error error_code = f.error_details(); | 291 base::File::Error error_code = f.error_details(); |
| 292 RecordOSError(leveldb_env::kNewRandomAccessFile, error_code); | |
| 274 return MakeIOError(fname, base::File::ErrorToString(error_code), | 293 return MakeIOError(fname, base::File::ErrorToString(error_code), |
| 275 leveldb_env::kNewRandomAccessFile, error_code); | 294 leveldb_env::kNewRandomAccessFile, error_code); |
| 276 } | 295 } |
| 277 | 296 |
| 278 *result = new MojoRandomAccessFile(fname, std::move(f)); | 297 *result = new MojoRandomAccessFile(fname, std::move(f), this); |
| 279 return Status::OK(); | 298 return Status::OK(); |
| 280 } | 299 } |
| 281 | 300 |
| 282 Status MojoEnv::NewWritableFile(const std::string& fname, | 301 Status MojoEnv::NewWritableFile(const std::string& fname, |
| 283 WritableFile** result) { | 302 WritableFile** result) { |
| 284 TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname); | 303 TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname); |
| 285 base::File f = | 304 base::File f = |
| 286 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways | | 305 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways | |
| 287 filesystem::mojom::kFlagWrite); | 306 filesystem::mojom::kFlagWrite); |
| 288 if (!f.IsValid()) { | 307 if (!f.IsValid()) { |
| 289 *result = nullptr; | 308 *result = nullptr; |
| 309 RecordOSError(leveldb_env::kNewWritableFile, f.error_details()); | |
| 290 return MakeIOError(fname, "Unable to create writable file", | 310 return MakeIOError(fname, "Unable to create writable file", |
| 291 leveldb_env::kNewWritableFile, f.error_details()); | 311 leveldb_env::kNewWritableFile, f.error_details()); |
| 292 } | 312 } |
| 293 | 313 |
| 294 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); | 314 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_, this); |
| 295 return Status::OK(); | 315 return Status::OK(); |
| 296 } | 316 } |
| 297 | 317 |
| 298 Status MojoEnv::NewAppendableFile(const std::string& fname, | 318 Status MojoEnv::NewAppendableFile(const std::string& fname, |
| 299 WritableFile** result) { | 319 WritableFile** result) { |
| 300 TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname); | 320 TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname); |
| 301 base::File f = | 321 base::File f = |
| 302 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways | | 322 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways | |
| 303 filesystem::mojom::kFlagAppend); | 323 filesystem::mojom::kFlagAppend); |
| 304 if (!f.IsValid()) { | 324 if (!f.IsValid()) { |
| 305 *result = nullptr; | 325 *result = nullptr; |
| 326 RecordOSError(leveldb_env::kNewAppendableFile, f.error_details()); | |
| 306 return MakeIOError(fname, "Unable to create appendable file", | 327 return MakeIOError(fname, "Unable to create appendable file", |
| 307 leveldb_env::kNewAppendableFile, f.error_details()); | 328 leveldb_env::kNewAppendableFile, f.error_details()); |
| 308 } | 329 } |
| 309 | 330 |
| 310 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); | 331 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_, this); |
| 311 return Status::OK(); | 332 return Status::OK(); |
| 312 } | 333 } |
| 313 | 334 |
| 314 bool MojoEnv::FileExists(const std::string& fname) { | 335 bool MojoEnv::FileExists(const std::string& fname) { |
| 315 TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname); | 336 TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname); |
| 316 return thread_->FileExists(dir_, fname); | 337 return thread_->FileExists(dir_, fname); |
| 317 } | 338 } |
| 318 | 339 |
| 319 Status MojoEnv::GetChildren(const std::string& path, | 340 Status MojoEnv::GetChildren(const std::string& path, |
| 320 std::vector<std::string>* result) { | 341 std::vector<std::string>* result) { |
| 321 TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "path", path); | 342 TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "path", path); |
| 322 return FilesystemErrorToStatus(thread_->GetChildren(dir_, path, result), path, | 343 FileError error = thread_->GetChildren(dir_, path, result); |
| 323 leveldb_env::kGetChildren); | 344 if (error != FileError::OK) |
| 345 RecordFileError(leveldb_env::kGetChildren, error); | |
| 346 return FilesystemErrorToStatus(error, path, leveldb_env::kGetChildren); | |
| 324 } | 347 } |
| 325 | 348 |
| 326 Status MojoEnv::DeleteFile(const std::string& fname) { | 349 Status MojoEnv::DeleteFile(const std::string& fname) { |
| 327 TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname); | 350 TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname); |
| 328 return FilesystemErrorToStatus(thread_->Delete(dir_, fname, 0), fname, | 351 FileError error = thread_->Delete(dir_, fname, 0); |
| 329 leveldb_env::kDeleteFile); | 352 if (error != FileError::OK) |
| 353 RecordFileError(leveldb_env::kDeleteFile, error); | |
| 354 return FilesystemErrorToStatus(error, fname, leveldb_env::kDeleteFile); | |
| 330 } | 355 } |
| 331 | 356 |
| 332 Status MojoEnv::CreateDir(const std::string& dirname) { | 357 Status MojoEnv::CreateDir(const std::string& dirname) { |
| 333 TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname); | 358 TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname); |
| 334 return FilesystemErrorToStatus(thread_->CreateDir(dir_, dirname), dirname, | 359 FileError error = thread_->CreateDir(dir_, dirname); |
| 335 leveldb_env::kCreateDir); | 360 if (error != FileError::OK) |
| 361 RecordFileError(leveldb_env::kCreateDir, error); | |
| 362 return FilesystemErrorToStatus(error, dirname, leveldb_env::kCreateDir); | |
| 336 } | 363 } |
| 337 | 364 |
| 338 Status MojoEnv::DeleteDir(const std::string& dirname) { | 365 Status MojoEnv::DeleteDir(const std::string& dirname) { |
| 339 TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname); | 366 TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname); |
| 340 return FilesystemErrorToStatus( | 367 FileError error = |
| 341 thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive), | 368 thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive); |
| 342 dirname, leveldb_env::kDeleteDir); | 369 if (error != FileError::OK) |
| 370 RecordFileError(leveldb_env::kDeleteDir, error); | |
| 371 return FilesystemErrorToStatus(error, dirname, leveldb_env::kDeleteDir); | |
| 343 } | 372 } |
| 344 | 373 |
| 345 Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) { | 374 Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) { |
| 346 TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname); | 375 TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname); |
| 347 return FilesystemErrorToStatus(thread_->GetFileSize(dir_, fname, file_size), | 376 FileError error = thread_->GetFileSize(dir_, fname, file_size); |
| 348 fname, | 377 if (error != FileError::OK) |
| 349 leveldb_env::kGetFileSize); | 378 RecordFileError(leveldb_env::kGetFileSize, error); |
| 379 return FilesystemErrorToStatus(error, fname, leveldb_env::kGetFileSize); | |
| 350 } | 380 } |
| 351 | 381 |
| 352 Status MojoEnv::RenameFile(const std::string& src, const std::string& target) { | 382 Status MojoEnv::RenameFile(const std::string& src, const std::string& target) { |
| 353 TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target); | 383 TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target); |
| 354 return FilesystemErrorToStatus(thread_->RenameFile(dir_, src, target), src, | 384 FileError error = thread_->RenameFile(dir_, src, target); |
| 355 leveldb_env::kRenameFile); | 385 if (error != FileError::OK) |
| 386 RecordFileError(leveldb_env::kRenameFile, error); | |
| 387 return FilesystemErrorToStatus(error, src, leveldb_env::kRenameFile); | |
| 356 } | 388 } |
| 357 | 389 |
| 358 Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) { | 390 Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) { |
| 359 TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname); | 391 TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname); |
| 360 | 392 |
| 361 std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*> p = | 393 std::pair<FileError, LevelDBMojoProxy::OpaqueLock*> p = |
| 362 thread_->LockFile(dir_, fname); | 394 thread_->LockFile(dir_, fname); |
| 363 | 395 |
| 396 if (p.first != FileError::OK) | |
| 397 RecordFileError(leveldb_env::kLockFile, p.first); | |
| 398 | |
| 364 if (p.second) | 399 if (p.second) |
| 365 *lock = new MojoFileLock(p.second, fname); | 400 *lock = new MojoFileLock(p.second, fname); |
| 366 | 401 |
| 367 return FilesystemErrorToStatus(p.first, fname, leveldb_env::kLockFile); | 402 return FilesystemErrorToStatus(p.first, fname, leveldb_env::kLockFile); |
| 368 } | 403 } |
| 369 | 404 |
| 370 Status MojoEnv::UnlockFile(FileLock* lock) { | 405 Status MojoEnv::UnlockFile(FileLock* lock) { |
| 371 MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock); | 406 MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock); |
| 372 | 407 |
| 373 std::string fname = my_lock ? my_lock->name() : "(invalid)"; | 408 std::string fname = my_lock ? my_lock->name() : "(invalid)"; |
| 374 TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname); | 409 TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname); |
| 375 | 410 |
| 376 filesystem::mojom::FileError err = thread_->UnlockFile(my_lock->TakeLock()); | 411 FileError error = thread_->UnlockFile(my_lock->TakeLock()); |
| 412 if (error != FileError::OK) | |
| 413 RecordFileError(leveldb_env::kUnlockFile, error); | |
| 377 delete my_lock; | 414 delete my_lock; |
| 378 return FilesystemErrorToStatus(err, fname, leveldb_env::kUnlockFile); | 415 return FilesystemErrorToStatus(error, fname, leveldb_env::kUnlockFile); |
| 379 } | 416 } |
| 380 | 417 |
| 381 Status MojoEnv::GetTestDirectory(std::string* path) { | 418 Status MojoEnv::GetTestDirectory(std::string* path) { |
| 382 // TODO(erg): This method is actually only used from the test harness in | 419 // TODO(erg): This method is actually only used from the test harness in |
| 383 // leveldb. And when we go and port that test stuff to a | 420 // leveldb. And when we go and port that test stuff to a |
| 384 // service_manager::ServiceTest, | 421 // service_manager::ServiceTest, |
| 385 // we probably won't use it since the mojo filesystem actually handles | 422 // we probably won't use it since the mojo filesystem actually handles |
| 386 // temporary filesystems just fine. | 423 // temporary filesystems just fine. |
| 387 NOTREACHED(); | 424 NOTREACHED(); |
| 388 return Status::OK(); | 425 return Status::OK(); |
| 389 } | 426 } |
| 390 | 427 |
| 391 Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { | 428 Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { |
| 392 TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname); | 429 TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname); |
| 393 base::File f(thread_->OpenFileHandle( | 430 base::File f(thread_->OpenFileHandle( |
| 394 dir_, fname, | 431 dir_, fname, |
| 395 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite)); | 432 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite)); |
| 396 if (!f.IsValid()) { | 433 if (!f.IsValid()) { |
| 397 *result = NULL; | 434 *result = NULL; |
| 435 RecordOSError(leveldb_env::kNewLogger, f.error_details()); | |
| 398 return MakeIOError(fname, "Unable to create log file", | 436 return MakeIOError(fname, "Unable to create log file", |
| 399 leveldb_env::kNewLogger, f.error_details()); | 437 leveldb_env::kNewLogger, f.error_details()); |
| 400 } else { | 438 } else { |
| 401 *result = new leveldb::ChromiumLogger(std::move(f)); | 439 *result = new leveldb::ChromiumLogger(std::move(f)); |
| 402 return Status::OK(); | 440 return Status::OK(); |
| 403 } | 441 } |
| 404 } | 442 } |
| 405 | 443 |
| 444 void MojoEnv::RecordErrorAt(leveldb_env::MethodID method) const { | |
| 445 UMA_HISTOGRAM_ENUMERATION("MojoLevelDBEnv.IOError", method, | |
| 446 leveldb_env::kNumEntries); | |
| 447 } | |
| 448 | |
| 449 void MojoEnv::RecordOSError(leveldb_env::MethodID method, | |
| 450 base::File::Error error) const { | |
| 451 RecordErrorAt(method); | |
| 452 std::string uma_name = | |
| 453 std::string("MojoLevelDBEnv.IOError.BFE.") + MethodIDToString(method); | |
| 454 base::LinearHistogram::FactoryGet(uma_name, 1, -base::File::FILE_ERROR_MAX, | |
| 455 -base::File::FILE_ERROR_MAX + 1, | |
| 456 base::Histogram::kUmaTargetedHistogramFlag) | |
| 457 ->Add(-error); | |
|
Ilya Sherman
2017/05/17 19:06:32
nit: Please use the convenience wrapper base::UmaH
| |
| 458 } | |
| 459 | |
| 460 void MojoEnv::RecordFileError(leveldb_env::MethodID method, | |
| 461 FileError error) const { | |
| 462 RecordOSError(method, static_cast<base::File::Error>(error)); | |
| 463 } | |
| 464 | |
| 406 uint64_t MojoEnv::NowMicros() { | 465 uint64_t MojoEnv::NowMicros() { |
| 407 return base::TimeTicks::Now().ToInternalValue(); | 466 return base::TimeTicks::Now().ToInternalValue(); |
| 408 } | 467 } |
| 409 | 468 |
| 410 void MojoEnv::SleepForMicroseconds(int micros) { | 469 void MojoEnv::SleepForMicroseconds(int micros) { |
| 411 // Round up to the next millisecond. | 470 // Round up to the next millisecond. |
| 412 base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros)); | 471 base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(micros)); |
| 413 } | 472 } |
| 414 | 473 |
| 415 void MojoEnv::Schedule(void (*function)(void* arg), void* arg) { | 474 void MojoEnv::Schedule(void (*function)(void* arg), void* arg) { |
| 416 base::PostTaskWithTraits(FROM_HERE, | 475 base::PostTaskWithTraits(FROM_HERE, |
| 417 {base::MayBlock(), base::WithBaseSyncPrimitives(), | 476 {base::MayBlock(), base::WithBaseSyncPrimitives(), |
| 418 base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, | 477 base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, |
| 419 base::Bind(function, arg)); | 478 base::Bind(function, arg)); |
| 420 } | 479 } |
| 421 | 480 |
| 422 void MojoEnv::StartThread(void (*function)(void* arg), void* arg) { | 481 void MojoEnv::StartThread(void (*function)(void* arg), void* arg) { |
| 423 new Thread(function, arg); // Will self-delete. | 482 new Thread(function, arg); // Will self-delete. |
| 424 } | 483 } |
| 425 | 484 |
| 426 } // namespace leveldb | 485 } // namespace leveldb |
| OLD | NEW |