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