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 |