Index: components/leveldb/env_mojo.cc |
diff --git a/components/leveldb/env_mojo.cc b/components/leveldb/env_mojo.cc |
index 6e6980292efae589589855fe6e556d896b633957..54667a3d3314406299874fa60c7c45157416d22f 100644 |
--- a/components/leveldb/env_mojo.cc |
+++ b/components/leveldb/env_mojo.cc |
@@ -8,13 +8,17 @@ |
#include <memory> |
+#include "base/metrics/histogram_functions.h" |
+#include "base/metrics/histogram_macros.h" |
#include "base/strings/string_util.h" |
#include "base/task_scheduler/post_task.h" |
#include "base/trace_event/trace_event.h" |
#include "third_party/leveldatabase/chromium_logger.h" |
-#include "third_party/leveldatabase/env_chromium.h" |
#include "third_party/leveldatabase/src/include/leveldb/status.h" |
+using filesystem::mojom::FileError; |
+using leveldb_env::UMALogger; |
+ |
namespace leveldb { |
namespace { |
@@ -29,10 +33,10 @@ base::File::Error LastFileError() { |
#endif |
} |
-Status FilesystemErrorToStatus(filesystem::mojom::FileError error, |
+Status FilesystemErrorToStatus(FileError error, |
const std::string& filename, |
leveldb_env::MethodID method) { |
- if (error == filesystem::mojom::FileError::OK) |
+ if (error == FileError::OK) |
return Status::OK(); |
std::string err_str = |
@@ -65,8 +69,10 @@ class MojoFileLock : public FileLock { |
class MojoSequentialFile : public leveldb::SequentialFile { |
public: |
- MojoSequentialFile(const std::string& fname, base::File f) |
- : filename_(fname), file_(std::move(f)) {} |
+ MojoSequentialFile(const std::string& fname, |
+ base::File f, |
+ const UMALogger* uma_logger) |
+ : filename_(fname), file_(std::move(f)), uma_logger_(uma_logger) {} |
~MojoSequentialFile() override {} |
Status Read(size_t n, Slice* result, char* scratch) override { |
@@ -75,6 +81,7 @@ class MojoSequentialFile : public leveldb::SequentialFile { |
static_cast<int>(n)); |
if (bytes_read == -1) { |
base::File::Error error = LastFileError(); |
+ uma_logger_->RecordOSError(leveldb_env::kSequentialFileRead, error); |
return MakeIOError(filename_, base::File::ErrorToString(error), |
leveldb_env::kSequentialFileRead, error); |
} else { |
@@ -86,6 +93,7 @@ class MojoSequentialFile : public leveldb::SequentialFile { |
Status Skip(uint64_t n) override { |
if (file_.Seek(base::File::FROM_CURRENT, n) == -1) { |
base::File::Error error = LastFileError(); |
+ uma_logger_->RecordOSError(leveldb_env::kSequentialFileSkip, error); |
return MakeIOError(filename_, base::File::ErrorToString(error), |
leveldb_env::kSequentialFileSkip, error); |
} else { |
@@ -96,14 +104,17 @@ class MojoSequentialFile : public leveldb::SequentialFile { |
private: |
std::string filename_; |
base::File file_; |
+ const UMALogger* uma_logger_; |
DISALLOW_COPY_AND_ASSIGN(MojoSequentialFile); |
}; |
class MojoRandomAccessFile : public leveldb::RandomAccessFile { |
public: |
- MojoRandomAccessFile(const std::string& fname, base::File file) |
- : filename_(fname), file_(std::move(file)) {} |
+ MojoRandomAccessFile(const std::string& fname, |
+ base::File file, |
+ const UMALogger* uma_logger) |
+ : filename_(fname), file_(std::move(file)), uma_logger_(uma_logger) {} |
~MojoRandomAccessFile() override {} |
Status Read(uint64_t offset, |
@@ -117,6 +128,8 @@ class MojoRandomAccessFile : public leveldb::RandomAccessFile { |
// An error: return a non-ok status |
s = MakeIOError(filename_, "Could not perform read", |
leveldb_env::kRandomAccessFileRead); |
+ uma_logger_->RecordOSError(leveldb_env::kRandomAccessFileRead, |
+ LastFileError()); |
} |
return s; |
} |
@@ -124,6 +137,7 @@ class MojoRandomAccessFile : public leveldb::RandomAccessFile { |
private: |
std::string filename_; |
mutable base::File file_; |
+ const UMALogger* uma_logger_; |
DISALLOW_COPY_AND_ASSIGN(MojoRandomAccessFile); |
}; |
@@ -133,12 +147,14 @@ class MojoWritableFile : public leveldb::WritableFile { |
MojoWritableFile(LevelDBMojoProxy::OpaqueDir* dir, |
const std::string& fname, |
base::File f, |
- scoped_refptr<LevelDBMojoProxy> thread) |
+ scoped_refptr<LevelDBMojoProxy> thread, |
+ const UMALogger* uma_logger) |
: filename_(fname), |
file_(std::move(f)), |
file_type_(kOther), |
dir_(dir), |
- thread_(thread) { |
+ thread_(thread), |
+ uma_logger_(uma_logger) { |
base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); |
if (base::StartsWith(path.BaseName().AsUTF8Unsafe(), "MANIFEST", |
base::CompareCase::SENSITIVE)) { |
@@ -157,6 +173,7 @@ class MojoWritableFile : public leveldb::WritableFile { |
data.data(), static_cast<int>(data.size())); |
if (bytes_written != data.size()) { |
base::File::Error error = LastFileError(); |
+ uma_logger_->RecordOSError(leveldb_env::kWritableFileAppend, error); |
return MakeIOError(filename_, base::File::ErrorToString(error), |
leveldb_env::kWritableFileAppend, error); |
} |
@@ -181,6 +198,7 @@ class MojoWritableFile : public leveldb::WritableFile { |
if (!file_.Flush()) { |
base::File::Error error = LastFileError(); |
+ uma_logger_->RecordOSError(leveldb_env::kWritableFileSync, error); |
return MakeIOError(filename_, base::File::ErrorToString(error), |
leveldb_env::kWritableFileSync, error); |
} |
@@ -198,9 +216,8 @@ class MojoWritableFile : public leveldb::WritableFile { |
enum Type { kManifest, kTable, kOther }; |
leveldb::Status SyncParent() { |
- filesystem::mojom::FileError error = |
- thread_->SyncDirectory(dir_, parent_dir_); |
- return error == filesystem::mojom::FileError::OK |
+ FileError error = thread_->SyncDirectory(dir_, parent_dir_); |
+ return error == FileError::OK |
? Status::OK() |
: Status::IOError(filename_, |
base::File::ErrorToString(base::File::Error( |
@@ -213,6 +230,7 @@ class MojoWritableFile : public leveldb::WritableFile { |
LevelDBMojoProxy::OpaqueDir* dir_; |
std::string parent_dir_; |
scoped_refptr<LevelDBMojoProxy> thread_; |
+ const UMALogger* uma_logger_; |
DISALLOW_COPY_AND_ASSIGN(MojoWritableFile); |
}; |
@@ -255,11 +273,12 @@ Status MojoEnv::NewSequentialFile(const std::string& fname, |
dir_, fname, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead); |
if (!f.IsValid()) { |
*result = nullptr; |
+ RecordOSError(leveldb_env::kNewSequentialFile, f.error_details()); |
return MakeIOError(fname, "Unable to create sequential file", |
leveldb_env::kNewSequentialFile, f.error_details()); |
} |
- *result = new MojoSequentialFile(fname, std::move(f)); |
+ *result = new MojoSequentialFile(fname, std::move(f), this); |
return Status::OK(); |
} |
@@ -271,11 +290,12 @@ Status MojoEnv::NewRandomAccessFile(const std::string& fname, |
if (!f.IsValid()) { |
*result = nullptr; |
base::File::Error error_code = f.error_details(); |
+ RecordOSError(leveldb_env::kNewRandomAccessFile, error_code); |
return MakeIOError(fname, base::File::ErrorToString(error_code), |
leveldb_env::kNewRandomAccessFile, error_code); |
} |
- *result = new MojoRandomAccessFile(fname, std::move(f)); |
+ *result = new MojoRandomAccessFile(fname, std::move(f), this); |
return Status::OK(); |
} |
@@ -287,11 +307,12 @@ Status MojoEnv::NewWritableFile(const std::string& fname, |
filesystem::mojom::kFlagWrite); |
if (!f.IsValid()) { |
*result = nullptr; |
+ RecordOSError(leveldb_env::kNewWritableFile, f.error_details()); |
return MakeIOError(fname, "Unable to create writable file", |
leveldb_env::kNewWritableFile, f.error_details()); |
} |
- *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); |
+ *result = new MojoWritableFile(dir_, fname, std::move(f), thread_, this); |
return Status::OK(); |
} |
@@ -303,11 +324,12 @@ Status MojoEnv::NewAppendableFile(const std::string& fname, |
filesystem::mojom::kFlagAppend); |
if (!f.IsValid()) { |
*result = nullptr; |
+ RecordOSError(leveldb_env::kNewAppendableFile, f.error_details()); |
return MakeIOError(fname, "Unable to create appendable file", |
leveldb_env::kNewAppendableFile, f.error_details()); |
} |
- *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); |
+ *result = new MojoWritableFile(dir_, fname, std::move(f), thread_, this); |
return Status::OK(); |
} |
@@ -319,48 +341,62 @@ bool MojoEnv::FileExists(const std::string& fname) { |
Status MojoEnv::GetChildren(const std::string& path, |
std::vector<std::string>* result) { |
TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "path", path); |
- return FilesystemErrorToStatus(thread_->GetChildren(dir_, path, result), path, |
- leveldb_env::kGetChildren); |
+ FileError error = thread_->GetChildren(dir_, path, result); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kGetChildren, error); |
+ return FilesystemErrorToStatus(error, path, leveldb_env::kGetChildren); |
} |
Status MojoEnv::DeleteFile(const std::string& fname) { |
TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname); |
- return FilesystemErrorToStatus(thread_->Delete(dir_, fname, 0), fname, |
- leveldb_env::kDeleteFile); |
+ FileError error = thread_->Delete(dir_, fname, 0); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kDeleteFile, error); |
+ return FilesystemErrorToStatus(error, fname, leveldb_env::kDeleteFile); |
} |
Status MojoEnv::CreateDir(const std::string& dirname) { |
TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname); |
- return FilesystemErrorToStatus(thread_->CreateDir(dir_, dirname), dirname, |
- leveldb_env::kCreateDir); |
+ FileError error = thread_->CreateDir(dir_, dirname); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kCreateDir, error); |
+ return FilesystemErrorToStatus(error, dirname, leveldb_env::kCreateDir); |
} |
Status MojoEnv::DeleteDir(const std::string& dirname) { |
TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname); |
- return FilesystemErrorToStatus( |
- thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive), |
- dirname, leveldb_env::kDeleteDir); |
+ FileError error = |
+ thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kDeleteDir, error); |
+ return FilesystemErrorToStatus(error, dirname, leveldb_env::kDeleteDir); |
} |
Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) { |
TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname); |
- return FilesystemErrorToStatus(thread_->GetFileSize(dir_, fname, file_size), |
- fname, |
- leveldb_env::kGetFileSize); |
+ FileError error = thread_->GetFileSize(dir_, fname, file_size); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kGetFileSize, error); |
+ return FilesystemErrorToStatus(error, fname, leveldb_env::kGetFileSize); |
} |
Status MojoEnv::RenameFile(const std::string& src, const std::string& target) { |
TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target); |
- return FilesystemErrorToStatus(thread_->RenameFile(dir_, src, target), src, |
- leveldb_env::kRenameFile); |
+ FileError error = thread_->RenameFile(dir_, src, target); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kRenameFile, error); |
+ return FilesystemErrorToStatus(error, src, leveldb_env::kRenameFile); |
} |
Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) { |
TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname); |
- std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*> p = |
+ std::pair<FileError, LevelDBMojoProxy::OpaqueLock*> p = |
thread_->LockFile(dir_, fname); |
+ if (p.first != FileError::OK) |
+ RecordFileError(leveldb_env::kLockFile, p.first); |
+ |
if (p.second) |
*lock = new MojoFileLock(p.second, fname); |
@@ -373,9 +409,11 @@ Status MojoEnv::UnlockFile(FileLock* lock) { |
std::string fname = my_lock ? my_lock->name() : "(invalid)"; |
TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname); |
- filesystem::mojom::FileError err = thread_->UnlockFile(my_lock->TakeLock()); |
+ FileError error = thread_->UnlockFile(my_lock->TakeLock()); |
+ if (error != FileError::OK) |
+ RecordFileError(leveldb_env::kUnlockFile, error); |
delete my_lock; |
- return FilesystemErrorToStatus(err, fname, leveldb_env::kUnlockFile); |
+ return FilesystemErrorToStatus(error, fname, leveldb_env::kUnlockFile); |
} |
Status MojoEnv::GetTestDirectory(std::string* path) { |
@@ -395,6 +433,7 @@ Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { |
filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite)); |
if (!f.IsValid()) { |
*result = NULL; |
+ RecordOSError(leveldb_env::kNewLogger, f.error_details()); |
return MakeIOError(fname, "Unable to create log file", |
leveldb_env::kNewLogger, f.error_details()); |
} else { |
@@ -403,6 +442,24 @@ Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { |
} |
} |
+void MojoEnv::RecordErrorAt(leveldb_env::MethodID method) const { |
+ UMA_HISTOGRAM_ENUMERATION("MojoLevelDBEnv.IOError", method, |
+ leveldb_env::kNumEntries); |
+} |
+ |
+void MojoEnv::RecordOSError(leveldb_env::MethodID method, |
+ base::File::Error error) const { |
+ RecordErrorAt(method); |
+ std::string uma_name = |
+ std::string("MojoLevelDBEnv.IOError.BFE.") + MethodIDToString(method); |
+ base::UmaHistogramExactLinear(uma_name, -error, -base::File::FILE_ERROR_MAX); |
+} |
+ |
+void MojoEnv::RecordFileError(leveldb_env::MethodID method, |
+ FileError error) const { |
+ RecordOSError(method, static_cast<base::File::Error>(error)); |
+} |
+ |
uint64_t MojoEnv::NowMicros() { |
return base::TimeTicks::Now().ToInternalValue(); |
} |