Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: net/base/file_stream_posix.cc

Issue 7583049: Record UMA statistics for file_stream operations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Simplified the UMA error statistics gathering. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/file_stream_posix.cc
diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc
index 68732e3aac39fa6db4e34ffe93b96c79b3d64b7f..85808ff1807f9aa934bc10cb87d65e812047525f 100644
--- a/net/base/file_stream_posix.cc
+++ b/net/base/file_stream_posix.cc
@@ -25,6 +25,7 @@
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
#include "base/synchronization/waitable_event.h"
+#include "net/base/file_stream_metrics.h"
#include "net/base/net_errors.h"
#if defined(OS_ANDROID)
@@ -62,50 +63,64 @@ int64 MapErrorCode(int err) {
// ReadFile() is a simple wrapper around read() that handles EINTR signals and
// calls MapErrorCode() to map errno to net error codes.
-int ReadFile(base::PlatformFile file, char* buf, int buf_len) {
+int ReadFile(base::PlatformFile file, char* buf, int buf_len, bool record_uma) {
base::ThreadRestrictions::AssertIOAllowed();
// read(..., 0) returns 0 to indicate end-of-file.
// Loop in the case of getting interrupted by a signal.
ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len)));
- if (res == static_cast<ssize_t>(-1))
- return MapErrorCode(errno);
+ if (res == static_cast<ssize_t>(-1)) {
+ int error = errno;
+ if (record_uma)
+ RecordFileError(error, FILE_ERROR_SOURCE_READ);
+ return MapErrorCode(error);
+ }
return static_cast<int>(res);
}
void ReadFileTask(base::PlatformFile file,
char* buf,
int buf_len,
+ bool record_uma,
CompletionCallback* callback) {
- callback->Run(ReadFile(file, buf, buf_len));
+ callback->Run(ReadFile(file, buf, buf_len, record_uma));
}
// WriteFile() is a simple wrapper around write() that handles EINTR signals and
// calls MapErrorCode() to map errno to net error codes. It tries to write to
// completion.
-int WriteFile(base::PlatformFile file, const char* buf, int buf_len) {
+int WriteFile(base::PlatformFile file, const char* buf, int buf_len,
+ bool record_uma) {
base::ThreadRestrictions::AssertIOAllowed();
ssize_t res = HANDLE_EINTR(write(file, buf, buf_len));
- if (res == -1)
- return MapErrorCode(errno);
+ if (res == -1) {
+ int error = errno;
+ if (record_uma)
+ RecordFileError(error, FILE_ERROR_SOURCE_WRITE);
+ return MapErrorCode(error);
+ }
return res;
}
void WriteFileTask(base::PlatformFile file,
const char* buf,
- int buf_len,
+ int buf_len, bool record_uma,
CompletionCallback* callback) {
- callback->Run(WriteFile(file, buf, buf_len));
+ callback->Run(WriteFile(file, buf, buf_len, record_uma));
}
// FlushFile() is a simple wrapper around fsync() that handles EINTR signals and
// calls MapErrorCode() to map errno to net error codes. It tries to flush to
// completion.
-int FlushFile(base::PlatformFile file) {
+int FlushFile(base::PlatformFile file, bool record_uma) {
base::ThreadRestrictions::AssertIOAllowed();
ssize_t res = HANDLE_EINTR(fsync(file));
- if (res == -1)
- return MapErrorCode(errno);
+ if (res == -1) {
+ int error = errno;
+ if (record_uma)
+ RecordFileError(error, FILE_ERROR_SOURCE_FLUSH);
+ return MapErrorCode(error);
+ }
return res;
}
@@ -141,10 +156,10 @@ class FileStream::AsyncContext {
// These methods post synchronous read() and write() calls to a WorkerThread.
void InitiateAsyncRead(
- base::PlatformFile file, char* buf, int buf_len,
+ base::PlatformFile file, char* buf, int buf_len, bool record_uma,
CompletionCallback* callback);
void InitiateAsyncWrite(
- base::PlatformFile file, const char* buf, int buf_len,
+ base::PlatformFile file, const char* buf, int buf_len, bool record_uma,
CompletionCallback* callback);
CompletionCallback* callback() const { return callback_; }
@@ -211,7 +226,7 @@ FileStream::AsyncContext::~AsyncContext() {
}
void FileStream::AsyncContext::InitiateAsyncRead(
- base::PlatformFile file, char* buf, int buf_len,
+ base::PlatformFile file, char* buf, int buf_len, bool record_uma,
CompletionCallback* callback) {
DCHECK(!callback_);
callback_ = callback;
@@ -219,13 +234,13 @@ void FileStream::AsyncContext::InitiateAsyncRead(
base::WorkerPool::PostTask(FROM_HERE,
NewRunnableFunction(
&ReadFileTask,
- file, buf, buf_len,
+ file, buf, buf_len, record_uma,
&background_io_completed_callback_),
true /* task_is_slow */);
}
void FileStream::AsyncContext::InitiateAsyncWrite(
- base::PlatformFile file, const char* buf, int buf_len,
+ base::PlatformFile file, const char* buf, int buf_len, bool record_uma,
CompletionCallback* callback) {
DCHECK(!callback_);
callback_ = callback;
@@ -233,7 +248,7 @@ void FileStream::AsyncContext::InitiateAsyncWrite(
base::WorkerPool::PostTask(FROM_HERE,
NewRunnableFunction(
&WriteFileTask,
- file, buf, buf_len,
+ file, buf, buf_len, record_uma,
&background_io_completed_callback_),
true /* task_is_slow */);
}
@@ -274,14 +289,16 @@ void FileStream::AsyncContext::RunAsynchronousCallback() {
FileStream::FileStream()
: file_(base::kInvalidPlatformFileValue),
open_flags_(0),
- auto_closed_(true) {
+ auto_closed_(false),
+ record_uma_(false) {
DCHECK(!IsOpen());
}
FileStream::FileStream(base::PlatformFile file, int flags)
: file_(file),
open_flags_(flags),
- auto_closed_(false) {
+ auto_closed_(false),
+ record_uma_(false) {
// If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to
// make sure we will perform asynchronous File IO to it.
if (flags & base::PLATFORM_FILE_ASYNC) {
@@ -315,7 +332,10 @@ int FileStream::Open(const FilePath& path, int open_flags) {
open_flags_ = open_flags;
file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL);
if (file_ == base::kInvalidPlatformFileValue) {
- return MapErrorCode(errno);
+ int error = errno;
+ if (record_uma_)
+ RecordFileError(error, FILE_ERROR_SOURCE_OPEN);
+ return MapErrorCode(error);
}
if (open_flags_ & base::PLATFORM_FILE_ASYNC) {
@@ -332,16 +352,23 @@ bool FileStream::IsOpen() const {
int64 FileStream::Seek(Whence whence, int64 offset) {
base::ThreadRestrictions::AssertIOAllowed();
- if (!IsOpen())
+ if (!IsOpen()) {
+ if (record_uma_)
+ RecordFileError(EINVAL, FILE_ERROR_SOURCE_IS_NOT_OPEN);
return ERR_UNEXPECTED;
+ }
// If we're in async, make sure we don't have a request in flight.
DCHECK(!async_context_.get() || !async_context_->callback());
off_t res = lseek(file_, static_cast<off_t>(offset),
static_cast<int>(whence));
- if (res == static_cast<off_t>(-1))
- return MapErrorCode(errno);
+ if (res == static_cast<off_t>(-1)) {
+ int error = errno;
cbentzel 2011/08/16 13:36:02 Perhaps a helper function like MapAndRecordErrorC
ahendrickson 2011/08/17 20:12:04 Done.
+ if (record_uma_)
+ RecordFileError(error, FILE_ERROR_SOURCE_SEEK);
+ return MapErrorCode(error);
+ }
return res;
}
@@ -349,17 +376,23 @@ int64 FileStream::Seek(Whence whence, int64 offset) {
int64 FileStream::Available() {
base::ThreadRestrictions::AssertIOAllowed();
- if (!IsOpen())
+ if (!IsOpen()) {
+ if (record_uma_)
cbentzel 2011/08/16 13:36:02 I don't think it's worth recording these errors re
ahendrickson 2011/08/17 20:12:04 Done.
+ RecordFileError(EINVAL, FILE_ERROR_SOURCE_IS_NOT_OPEN);
return ERR_UNEXPECTED;
+ }
int64 cur_pos = Seek(FROM_CURRENT, 0);
if (cur_pos < 0)
return cur_pos;
struct stat info;
- if (fstat(file_, &info) != 0)
- return MapErrorCode(errno);
-
+ if (fstat(file_, &info) != 0) {
+ int error = errno;
+ if (record_uma_)
+ RecordFileError(error, FILE_ERROR_SOURCE_GET_SIZE);
+ return MapErrorCode(error);
+ }
int64 size = static_cast<int64>(info.st_size);
DCHECK_GT(size, cur_pos);
@@ -368,8 +401,11 @@ int64 FileStream::Available() {
int FileStream::Read(
char* buf, int buf_len, CompletionCallback* callback) {
- if (!IsOpen())
+ if (!IsOpen()) {
+ if (record_uma_)
+ RecordFileError(EINVAL, FILE_ERROR_SOURCE_IS_NOT_OPEN);
return ERR_UNEXPECTED;
+ }
// read(..., 0) will return 0, which indicates end-of-file.
DCHECK(buf_len > 0);
@@ -379,10 +415,11 @@ int FileStream::Read(
DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
// If we're in async, make sure we don't have a request in flight.
DCHECK(!async_context_->callback());
- async_context_->InitiateAsyncRead(file_, buf, buf_len, callback);
+ async_context_->InitiateAsyncRead(file_, buf, buf_len, record_uma_,
+ callback);
return ERR_IO_PENDING;
} else {
- return ReadFile(file_, buf, buf_len);
+ return ReadFile(file_, buf, buf_len, record_uma_);
}
}
@@ -412,25 +449,32 @@ int FileStream::Write(
// write(..., 0) will return 0, which indicates end-of-file.
DCHECK_GT(buf_len, 0);
- if (!IsOpen())
+ if (!IsOpen()) {
+ if (record_uma_)
+ RecordFileError(EINVAL, FILE_ERROR_SOURCE_IS_NOT_OPEN);
return ERR_UNEXPECTED;
+ }
if (async_context_.get()) {
DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
// If we're in async, make sure we don't have a request in flight.
DCHECK(!async_context_->callback());
- async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback);
+ async_context_->InitiateAsyncWrite(file_, buf, buf_len, record_uma_,
+ callback);
return ERR_IO_PENDING;
} else {
- return WriteFile(file_, buf, buf_len);
+ return WriteFile(file_, buf, buf_len, record_uma_);
}
}
int64 FileStream::Truncate(int64 bytes) {
base::ThreadRestrictions::AssertIOAllowed();
- if (!IsOpen())
+ if (!IsOpen()) {
+ if (record_uma_)
+ RecordFileError(EINVAL, FILE_ERROR_SOURCE_IS_NOT_OPEN);
return ERR_UNEXPECTED;
+ }
// We better be open for reading.
DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
@@ -442,14 +486,27 @@ int64 FileStream::Truncate(int64 bytes) {
// And truncate the file.
int result = ftruncate(file_, bytes);
cbentzel 2011/08/16 13:36:02 This existed before - but we may want to make this
ahendrickson 2011/08/17 20:12:04 What does HANDLE_EINTR do?
cbentzel 2011/08/18 13:31:27 HANDLE_EINTR re-executes the function if the errno
ahendrickson 2011/08/18 15:56:45 OK, removed.
- return result == 0 ? seek_position : MapErrorCode(errno);
+ if (result == 0)
+ return seek_position;
+
+ int error = errno;
+ if (record_uma_)
+ RecordFileError(error, FILE_ERROR_SOURCE_SET_EOF);
+ return MapErrorCode(error);
}
int FileStream::Flush() {
- if (!IsOpen())
+ if (!IsOpen()) {
+ if (record_uma_)
+ RecordFileError(EINVAL, FILE_ERROR_SOURCE_IS_NOT_OPEN);
return ERR_UNEXPECTED;
+ }
+
+ return FlushFile(file_, record_uma_);
+}
- return FlushFile(file_);
+void FileStream::EnableRecording() {
+ record_uma_ = true;
cbentzel 2011/08/16 13:36:02 Do you need to do the if (async_context_) asyn
ahendrickson 2011/08/17 20:12:04 Doing something similar now: Setting it at the ti
cbentzel 2011/08/18 13:31:27 Yup. After the fact I realized how different the t
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698