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 |