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

Side by Side 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: Removed extra logging. Created 9 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/file_stream_metrics_win.cc ('k') | net/base/file_stream_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // For 64-bit file access (off_t = off64_t, lseek64, etc). 5 // For 64-bit file access (off_t = off64_t, lseek64, etc).
6 #define _FILE_OFFSET_BITS 64 6 #define _FILE_OFFSET_BITS 64
7 7
8 #include "net/base/file_stream.h" 8 #include "net/base/file_stream.h"
9 9
10 #include <sys/types.h> 10 #include <sys/types.h>
11 #include <sys/stat.h> 11 #include <sys/stat.h>
12 #include <fcntl.h> 12 #include <fcntl.h>
13 #include <unistd.h> 13 #include <unistd.h>
14 #include <errno.h> 14 #include <errno.h>
15 15
16 #include "base/basictypes.h" 16 #include "base/basictypes.h"
17 #include "base/callback.h" 17 #include "base/callback.h"
18 #include "base/eintr_wrapper.h" 18 #include "base/eintr_wrapper.h"
19 #include "base/file_path.h" 19 #include "base/file_path.h"
20 #include "base/logging.h" 20 #include "base/logging.h"
21 #include "base/message_loop.h" 21 #include "base/message_loop.h"
22 #include "base/metrics/histogram.h" 22 #include "base/metrics/histogram.h"
23 #include "base/string_util.h" 23 #include "base/string_util.h"
24 #include "base/task.h" 24 #include "base/task.h"
25 #include "base/threading/thread_restrictions.h" 25 #include "base/threading/thread_restrictions.h"
26 #include "base/threading/worker_pool.h" 26 #include "base/threading/worker_pool.h"
27 #include "base/synchronization/waitable_event.h" 27 #include "base/synchronization/waitable_event.h"
28 #include "net/base/file_stream_metrics.h"
28 #include "net/base/net_errors.h" 29 #include "net/base/net_errors.h"
29 30
30 #if defined(OS_ANDROID) 31 #if defined(OS_ANDROID)
31 // Android's bionic libc only supports the LFS transitional API. 32 // Android's bionic libc only supports the LFS transitional API.
32 #define off_t off64_t 33 #define off_t off64_t
33 #define lseek lseek64 34 #define lseek lseek64
34 #define stat stat64 35 #define stat stat64
35 #define fstat fstat64 36 #define fstat fstat64
36 #endif 37 #endif
37 38
38 namespace net { 39 namespace net {
39 40
40 // We cast back and forth, so make sure it's the size we're expecting. 41 // We cast back and forth, so make sure it's the size we're expecting.
41 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); 42 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit);
42 43
43 // Make sure our Whence mappings match the system headers. 44 // Make sure our Whence mappings match the system headers.
44 COMPILE_ASSERT(FROM_BEGIN == SEEK_SET && 45 COMPILE_ASSERT(FROM_BEGIN == SEEK_SET &&
45 FROM_CURRENT == SEEK_CUR && 46 FROM_CURRENT == SEEK_CUR &&
46 FROM_END == SEEK_END, whence_matches_system); 47 FROM_END == SEEK_END, whence_matches_system);
47 48
48 namespace { 49 namespace {
49 50
51 int RecordAndMapError(int error, FileErrorSource source, bool record_uma) {
52 RecordFileError(error, source, record_uma);
53 return MapSystemError(error);
54 }
55
50 // ReadFile() is a simple wrapper around read() that handles EINTR signals and 56 // ReadFile() is a simple wrapper around read() that handles EINTR signals and
51 // calls MapSystemError() to map errno to net error codes. 57 // calls MapSystemError() to map errno to net error codes.
52 int ReadFile(base::PlatformFile file, char* buf, int buf_len) { 58 int ReadFile(base::PlatformFile file, char* buf, int buf_len, bool record_uma) {
53 base::ThreadRestrictions::AssertIOAllowed(); 59 base::ThreadRestrictions::AssertIOAllowed();
54 // read(..., 0) returns 0 to indicate end-of-file. 60 // read(..., 0) returns 0 to indicate end-of-file.
55 61
56 // Loop in the case of getting interrupted by a signal. 62 // Loop in the case of getting interrupted by a signal.
57 ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len))); 63 ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len)));
58 if (res == static_cast<ssize_t>(-1)) 64 if (res == static_cast<ssize_t>(-1))
59 return MapSystemError(errno); 65 RecordAndMapError(errno, FILE_ERROR_SOURCE_READ, record_uma);
60 return static_cast<int>(res); 66 return static_cast<int>(res);
61 } 67 }
62 68
63 void ReadFileTask(base::PlatformFile file, 69 void ReadFileTask(base::PlatformFile file,
64 char* buf, 70 char* buf,
65 int buf_len, 71 int buf_len,
72 bool record_uma,
66 CompletionCallback* callback) { 73 CompletionCallback* callback) {
67 callback->Run(ReadFile(file, buf, buf_len)); 74 callback->Run(ReadFile(file, buf, buf_len, record_uma));
68 } 75 }
69 76
70 // WriteFile() is a simple wrapper around write() that handles EINTR signals and 77 // WriteFile() is a simple wrapper around write() that handles EINTR signals and
71 // calls MapSystemError() to map errno to net error codes. It tries to write to 78 // calls MapSystemError() to map errno to net error codes. It tries to write to
72 // completion. 79 // completion.
73 int WriteFile(base::PlatformFile file, const char* buf, int buf_len) { 80 int WriteFile(base::PlatformFile file, const char* buf, int buf_len,
81 bool record_uma) {
74 base::ThreadRestrictions::AssertIOAllowed(); 82 base::ThreadRestrictions::AssertIOAllowed();
75 ssize_t res = HANDLE_EINTR(write(file, buf, buf_len)); 83 ssize_t res = HANDLE_EINTR(write(file, buf, buf_len));
76 if (res == -1) 84 if (res == -1)
77 return MapSystemError(errno); 85 RecordAndMapError(errno, FILE_ERROR_SOURCE_WRITE, record_uma);
78 return res; 86 return res;
79 } 87 }
80 88
81 void WriteFileTask(base::PlatformFile file, 89 void WriteFileTask(base::PlatformFile file,
82 const char* buf, 90 const char* buf,
83 int buf_len, 91 int buf_len, bool record_uma,
84 CompletionCallback* callback) { 92 CompletionCallback* callback) {
85 callback->Run(WriteFile(file, buf, buf_len)); 93 callback->Run(WriteFile(file, buf, buf_len, record_uma));
86 } 94 }
87 95
88 // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and 96 // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and
89 // calls MapSystemError() to map errno to net error codes. It tries to flush to 97 // calls MapSystemError() to map errno to net error codes. It tries to flush to
90 // completion. 98 // completion.
91 int FlushFile(base::PlatformFile file) { 99 int FlushFile(base::PlatformFile file, bool record_uma) {
92 base::ThreadRestrictions::AssertIOAllowed(); 100 base::ThreadRestrictions::AssertIOAllowed();
93 ssize_t res = HANDLE_EINTR(fsync(file)); 101 ssize_t res = HANDLE_EINTR(fsync(file));
94 if (res == -1) 102 if (res == -1)
95 return MapSystemError(errno); 103 RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma);
96 return res; 104 return res;
97 } 105 }
98 106
99 } // namespace 107 } // namespace
100 108
101 // CancelableCallbackTask takes ownership of the Callback. This task gets 109 // CancelableCallbackTask takes ownership of the Callback. This task gets
102 // posted to the MessageLoopForIO instance. 110 // posted to the MessageLoopForIO instance.
103 class CancelableCallbackTask : public CancelableTask { 111 class CancelableCallbackTask : public CancelableTask {
104 public: 112 public:
105 explicit CancelableCallbackTask(Callback0::Type* callback) 113 explicit CancelableCallbackTask(Callback0::Type* callback)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 CompletionCallback* callback() const { return callback_; } 145 CompletionCallback* callback() const { return callback_; }
138 146
139 // Called by the WorkerPool thread executing the IO after the IO completes. 147 // Called by the WorkerPool thread executing the IO after the IO completes.
140 // This method queues RunAsynchronousCallback() on the MessageLoop and signals 148 // This method queues RunAsynchronousCallback() on the MessageLoop and signals
141 // |background_io_completed_callback_|, in case the destructor is waiting. In 149 // |background_io_completed_callback_|, in case the destructor is waiting. In
142 // that case, the destructor will call RunAsynchronousCallback() instead, and 150 // that case, the destructor will call RunAsynchronousCallback() instead, and
143 // cancel |message_loop_task_|. 151 // cancel |message_loop_task_|.
144 // |result| is the result of the Read/Write task. 152 // |result| is the result of the Read/Write task.
145 void OnBackgroundIOCompleted(int result); 153 void OnBackgroundIOCompleted(int result);
146 154
155 void EnableErrorStatistics() {
156 record_uma_ = true;
157 }
158
147 private: 159 private:
148 // Always called on the IO thread, either directly by a task on the 160 // Always called on the IO thread, either directly by a task on the
149 // MessageLoop or by ~AsyncContext(). 161 // MessageLoop or by ~AsyncContext().
150 void RunAsynchronousCallback(); 162 void RunAsynchronousCallback();
151 163
152 // The MessageLoopForIO that this AsyncContext is running on. 164 // The MessageLoopForIO that this AsyncContext is running on.
153 MessageLoopForIO* const message_loop_; 165 MessageLoopForIO* const message_loop_;
154 CompletionCallback* callback_; // The user provided callback. 166 CompletionCallback* callback_; // The user provided callback.
155 167
156 // A callback wrapper around OnBackgroundIOCompleted(). Run by the WorkerPool 168 // A callback wrapper around OnBackgroundIOCompleted(). Run by the WorkerPool
157 // thread doing the background IO on our behalf. 169 // thread doing the background IO on our behalf.
158 CompletionCallbackImpl<AsyncContext> background_io_completed_callback_; 170 CompletionCallbackImpl<AsyncContext> background_io_completed_callback_;
159 171
160 // This is used to synchronize between the AsyncContext destructor (which runs 172 // This is used to synchronize between the AsyncContext destructor (which runs
161 // on the IO thread and OnBackgroundIOCompleted() which runs on the WorkerPool 173 // on the IO thread and OnBackgroundIOCompleted() which runs on the WorkerPool
162 // thread. 174 // thread.
163 base::WaitableEvent background_io_completed_; 175 base::WaitableEvent background_io_completed_;
164 176
165 // These variables are only valid when background_io_completed is signaled. 177 // These variables are only valid when background_io_completed is signaled.
166 int result_; 178 int result_;
167 CancelableCallbackTask* message_loop_task_; 179 CancelableCallbackTask* message_loop_task_;
168 180
169 bool is_closing_; 181 bool is_closing_;
182 bool record_uma_;
170 183
171 DISALLOW_COPY_AND_ASSIGN(AsyncContext); 184 DISALLOW_COPY_AND_ASSIGN(AsyncContext);
172 }; 185 };
173 186
174 FileStream::AsyncContext::AsyncContext() 187 FileStream::AsyncContext::AsyncContext()
175 : message_loop_(MessageLoopForIO::current()), 188 : message_loop_(MessageLoopForIO::current()),
176 callback_(NULL), 189 callback_(NULL),
177 background_io_completed_callback_( 190 background_io_completed_callback_(
178 this, &AsyncContext::OnBackgroundIOCompleted), 191 this, &AsyncContext::OnBackgroundIOCompleted),
179 background_io_completed_(true, false), 192 background_io_completed_(true, false),
180 message_loop_task_(NULL), 193 message_loop_task_(NULL),
181 is_closing_(false) {} 194 is_closing_(false),
195 record_uma_(false) {}
182 196
183 FileStream::AsyncContext::~AsyncContext() { 197 FileStream::AsyncContext::~AsyncContext() {
184 is_closing_ = true; 198 is_closing_ = true;
185 if (callback_) { 199 if (callback_) {
186 // If |callback_| is non-NULL, that implies either the worker thread is 200 // If |callback_| is non-NULL, that implies either the worker thread is
187 // still running the IO task, or the completion callback is queued up on the 201 // still running the IO task, or the completion callback is queued up on the
188 // MessageLoopForIO, but AsyncContext() got deleted before then. 202 // MessageLoopForIO, but AsyncContext() got deleted before then.
189 const bool need_to_wait = !background_io_completed_.IsSignaled(); 203 const bool need_to_wait = !background_io_completed_.IsSignaled();
190 base::TimeTicks start = base::TimeTicks::Now(); 204 base::TimeTicks start = base::TimeTicks::Now();
191 RunAsynchronousCallback(); 205 RunAsynchronousCallback();
192 if (need_to_wait) { 206 if (need_to_wait) {
193 // We want to see if we block the message loop for too long. 207 // We want to see if we block the message loop for too long.
194 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose", 208 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose",
195 base::TimeTicks::Now() - start); 209 base::TimeTicks::Now() - start);
196 } 210 }
197 } 211 }
198 } 212 }
199 213
200 void FileStream::AsyncContext::InitiateAsyncRead( 214 void FileStream::AsyncContext::InitiateAsyncRead(
201 base::PlatformFile file, char* buf, int buf_len, 215 base::PlatformFile file, char* buf, int buf_len,
202 CompletionCallback* callback) { 216 CompletionCallback* callback) {
203 DCHECK(!callback_); 217 DCHECK(!callback_);
204 callback_ = callback; 218 callback_ = callback;
205 219
206 base::WorkerPool::PostTask(FROM_HERE, 220 base::WorkerPool::PostTask(FROM_HERE,
207 NewRunnableFunction( 221 NewRunnableFunction(
208 &ReadFileTask, 222 &ReadFileTask,
209 file, buf, buf_len, 223 file, buf, buf_len,
224 record_uma_,
210 &background_io_completed_callback_), 225 &background_io_completed_callback_),
211 true /* task_is_slow */); 226 true /* task_is_slow */);
212 } 227 }
213 228
214 void FileStream::AsyncContext::InitiateAsyncWrite( 229 void FileStream::AsyncContext::InitiateAsyncWrite(
215 base::PlatformFile file, const char* buf, int buf_len, 230 base::PlatformFile file, const char* buf, int buf_len,
216 CompletionCallback* callback) { 231 CompletionCallback* callback) {
217 DCHECK(!callback_); 232 DCHECK(!callback_);
218 callback_ = callback; 233 callback_ = callback;
219 234
220 base::WorkerPool::PostTask(FROM_HERE, 235 base::WorkerPool::PostTask(FROM_HERE,
221 NewRunnableFunction( 236 NewRunnableFunction(
222 &WriteFileTask, 237 &WriteFileTask,
223 file, buf, buf_len, 238 file, buf, buf_len,
239 record_uma_,
224 &background_io_completed_callback_), 240 &background_io_completed_callback_),
225 true /* task_is_slow */); 241 true /* task_is_slow */);
226 } 242 }
227 243
228 void FileStream::AsyncContext::OnBackgroundIOCompleted(int result) { 244 void FileStream::AsyncContext::OnBackgroundIOCompleted(int result) {
229 result_ = result; 245 result_ = result;
230 message_loop_task_ = new CancelableCallbackTask( 246 message_loop_task_ = new CancelableCallbackTask(
231 NewCallback(this, &AsyncContext::RunAsynchronousCallback)); 247 NewCallback(this, &AsyncContext::RunAsynchronousCallback));
232 message_loop_->PostTask(FROM_HERE, message_loop_task_); 248 message_loop_->PostTask(FROM_HERE, message_loop_task_);
233 background_io_completed_.Signal(); 249 background_io_completed_.Signal();
(...skipping 20 matching lines...) Expand all
254 std::swap(temp, callback_); 270 std::swap(temp, callback_);
255 background_io_completed_.Reset(); 271 background_io_completed_.Reset();
256 temp->Run(result_); 272 temp->Run(result_);
257 } 273 }
258 274
259 // FileStream ------------------------------------------------------------ 275 // FileStream ------------------------------------------------------------
260 276
261 FileStream::FileStream() 277 FileStream::FileStream()
262 : file_(base::kInvalidPlatformFileValue), 278 : file_(base::kInvalidPlatformFileValue),
263 open_flags_(0), 279 open_flags_(0),
264 auto_closed_(true) { 280 auto_closed_(true),
281 record_uma_(false) {
265 DCHECK(!IsOpen()); 282 DCHECK(!IsOpen());
266 } 283 }
267 284
268 FileStream::FileStream(base::PlatformFile file, int flags) 285 FileStream::FileStream(base::PlatformFile file, int flags)
269 : file_(file), 286 : file_(file),
270 open_flags_(flags), 287 open_flags_(flags),
271 auto_closed_(false) { 288 auto_closed_(false),
289 record_uma_(false) {
272 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to 290 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to
273 // make sure we will perform asynchronous File IO to it. 291 // make sure we will perform asynchronous File IO to it.
274 if (flags & base::PLATFORM_FILE_ASYNC) { 292 if (flags & base::PLATFORM_FILE_ASYNC) {
275 async_context_.reset(new AsyncContext()); 293 async_context_.reset(new AsyncContext());
276 } 294 }
277 } 295 }
278 296
279 FileStream::~FileStream() { 297 FileStream::~FileStream() {
280 if (auto_closed_) 298 if (auto_closed_)
281 Close(); 299 Close();
(...skipping 12 matching lines...) Expand all
294 } 312 }
295 313
296 int FileStream::Open(const FilePath& path, int open_flags) { 314 int FileStream::Open(const FilePath& path, int open_flags) {
297 if (IsOpen()) { 315 if (IsOpen()) {
298 DLOG(FATAL) << "File is already open!"; 316 DLOG(FATAL) << "File is already open!";
299 return ERR_UNEXPECTED; 317 return ERR_UNEXPECTED;
300 } 318 }
301 319
302 open_flags_ = open_flags; 320 open_flags_ = open_flags;
303 file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); 321 file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL);
304 if (file_ == base::kInvalidPlatformFileValue) { 322 if (file_ == base::kInvalidPlatformFileValue)
305 return MapSystemError(errno); 323 return RecordAndMapError(errno, FILE_ERROR_SOURCE_OPEN, record_uma_);
306 }
307 324
308 if (open_flags_ & base::PLATFORM_FILE_ASYNC) { 325 if (open_flags_ & base::PLATFORM_FILE_ASYNC)
309 async_context_.reset(new AsyncContext()); 326 async_context_.reset(new AsyncContext());
310 }
311 327
312 return OK; 328 return OK;
313 } 329 }
314 330
315 bool FileStream::IsOpen() const { 331 bool FileStream::IsOpen() const {
316 return file_ != base::kInvalidPlatformFileValue; 332 return file_ != base::kInvalidPlatformFileValue;
317 } 333 }
318 334
319 int64 FileStream::Seek(Whence whence, int64 offset) { 335 int64 FileStream::Seek(Whence whence, int64 offset) {
320 base::ThreadRestrictions::AssertIOAllowed(); 336 base::ThreadRestrictions::AssertIOAllowed();
321 337
322 if (!IsOpen()) 338 if (!IsOpen())
323 return ERR_UNEXPECTED; 339 return ERR_UNEXPECTED;
324 340
325 // If we're in async, make sure we don't have a request in flight. 341 // If we're in async, make sure we don't have a request in flight.
326 DCHECK(!async_context_.get() || !async_context_->callback()); 342 DCHECK(!async_context_.get() || !async_context_->callback());
327 343
328 off_t res = lseek(file_, static_cast<off_t>(offset), 344 off_t res = lseek(file_, static_cast<off_t>(offset),
329 static_cast<int>(whence)); 345 static_cast<int>(whence));
330 if (res == static_cast<off_t>(-1)) 346 if (res == static_cast<off_t>(-1))
331 return MapSystemError(errno); 347 return RecordAndMapError(errno, FILE_ERROR_SOURCE_SEEK, record_uma_);
332 348
333 return res; 349 return res;
334 } 350 }
335 351
336 int64 FileStream::Available() { 352 int64 FileStream::Available() {
337 base::ThreadRestrictions::AssertIOAllowed(); 353 base::ThreadRestrictions::AssertIOAllowed();
338 354
339 if (!IsOpen()) 355 if (!IsOpen())
340 return ERR_UNEXPECTED; 356 return ERR_UNEXPECTED;
341 357
342 int64 cur_pos = Seek(FROM_CURRENT, 0); 358 int64 cur_pos = Seek(FROM_CURRENT, 0);
343 if (cur_pos < 0) 359 if (cur_pos < 0)
344 return cur_pos; 360 return cur_pos;
345 361
346 struct stat info; 362 struct stat info;
347 if (fstat(file_, &info) != 0) 363 if (fstat(file_, &info) != 0)
348 return MapSystemError(errno); 364 return RecordAndMapError(errno, FILE_ERROR_SOURCE_GET_SIZE, record_uma_);
349 365
350 int64 size = static_cast<int64>(info.st_size); 366 int64 size = static_cast<int64>(info.st_size);
351 DCHECK_GT(size, cur_pos); 367 DCHECK_GT(size, cur_pos);
352 368
353 return size - cur_pos; 369 return size - cur_pos;
354 } 370 }
355 371
356 int FileStream::Read( 372 int FileStream::Read(
357 char* buf, int buf_len, CompletionCallback* callback) { 373 char* buf, int buf_len, CompletionCallback* callback) {
358 if (!IsOpen()) 374 if (!IsOpen())
359 return ERR_UNEXPECTED; 375 return ERR_UNEXPECTED;
360 376
361 // read(..., 0) will return 0, which indicates end-of-file. 377 // read(..., 0) will return 0, which indicates end-of-file.
362 DCHECK(buf_len > 0); 378 DCHECK(buf_len > 0);
363 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); 379 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
364 380
365 if (async_context_.get()) { 381 if (async_context_.get()) {
366 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); 382 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
367 // If we're in async, make sure we don't have a request in flight. 383 // If we're in async, make sure we don't have a request in flight.
368 DCHECK(!async_context_->callback()); 384 DCHECK(!async_context_->callback());
385 if (record_uma_)
386 async_context_->EnableErrorStatistics();
369 async_context_->InitiateAsyncRead(file_, buf, buf_len, callback); 387 async_context_->InitiateAsyncRead(file_, buf, buf_len, callback);
370 return ERR_IO_PENDING; 388 return ERR_IO_PENDING;
371 } else { 389 } else {
372 return ReadFile(file_, buf, buf_len); 390 return ReadFile(file_, buf, buf_len, record_uma_);
373 } 391 }
374 } 392 }
375 393
376 int FileStream::ReadUntilComplete(char *buf, int buf_len) { 394 int FileStream::ReadUntilComplete(char *buf, int buf_len) {
377 int to_read = buf_len; 395 int to_read = buf_len;
378 int bytes_total = 0; 396 int bytes_total = 0;
379 397
380 do { 398 do {
381 int bytes_read = Read(buf, to_read, NULL); 399 int bytes_read = Read(buf, to_read, NULL);
382 if (bytes_read <= 0) { 400 if (bytes_read <= 0) {
(...skipping 16 matching lines...) Expand all
399 // write(..., 0) will return 0, which indicates end-of-file. 417 // write(..., 0) will return 0, which indicates end-of-file.
400 DCHECK_GT(buf_len, 0); 418 DCHECK_GT(buf_len, 0);
401 419
402 if (!IsOpen()) 420 if (!IsOpen())
403 return ERR_UNEXPECTED; 421 return ERR_UNEXPECTED;
404 422
405 if (async_context_.get()) { 423 if (async_context_.get()) {
406 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); 424 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
407 // If we're in async, make sure we don't have a request in flight. 425 // If we're in async, make sure we don't have a request in flight.
408 DCHECK(!async_context_->callback()); 426 DCHECK(!async_context_->callback());
427 if (record_uma_)
428 async_context_->EnableErrorStatistics();
409 async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback); 429 async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback);
410 return ERR_IO_PENDING; 430 return ERR_IO_PENDING;
411 } else { 431 } else {
412 return WriteFile(file_, buf, buf_len); 432 return WriteFile(file_, buf, buf_len, record_uma_);
413 } 433 }
414 } 434 }
415 435
416 int64 FileStream::Truncate(int64 bytes) { 436 int64 FileStream::Truncate(int64 bytes) {
417 base::ThreadRestrictions::AssertIOAllowed(); 437 base::ThreadRestrictions::AssertIOAllowed();
418 438
419 if (!IsOpen()) 439 if (!IsOpen())
420 return ERR_UNEXPECTED; 440 return ERR_UNEXPECTED;
421 441
422 // We better be open for reading. 442 // We better be open for reading.
423 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 443 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
424 444
425 // Seek to the position to truncate from. 445 // Seek to the position to truncate from.
426 int64 seek_position = Seek(FROM_BEGIN, bytes); 446 int64 seek_position = Seek(FROM_BEGIN, bytes);
427 if (seek_position != bytes) 447 if (seek_position != bytes)
428 return ERR_UNEXPECTED; 448 return ERR_UNEXPECTED;
429 449
430 // And truncate the file. 450 // And truncate the file.
431 int result = ftruncate(file_, bytes); 451 int result = ftruncate(file_, bytes);
432 return result == 0 ? seek_position : 452 if (result == 0)
433 static_cast<int64>(MapSystemError(errno)); 453 return seek_position;
454
455 return RecordAndMapError(errno, FILE_ERROR_SOURCE_SET_EOF, record_uma_);
434 } 456 }
435 457
436 int FileStream::Flush() { 458 int FileStream::Flush() {
437 if (!IsOpen()) 459 if (!IsOpen())
438 return ERR_UNEXPECTED; 460 return ERR_UNEXPECTED;
439 461
440 return FlushFile(file_); 462 return FlushFile(file_, record_uma_);
463 }
464
465 void FileStream::EnableErrorStatistics() {
466 record_uma_ = true;
441 } 467 }
442 468
443 } // namespace net 469 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_metrics_win.cc ('k') | net/base/file_stream_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698