Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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> |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 | 118 |
| 119 // Closes a file with CloseFile() and signals the completion. | 119 // Closes a file with CloseFile() and signals the completion. |
| 120 void CloseFileAndSignal(base::PlatformFile* file, | 120 void CloseFileAndSignal(base::PlatformFile* file, |
| 121 base::WaitableEvent* on_io_complete, | 121 base::WaitableEvent* on_io_complete, |
| 122 const net::BoundNetLog& bound_net_log) { | 122 const net::BoundNetLog& bound_net_log) { |
| 123 CloseFile(*file, bound_net_log); | 123 CloseFile(*file, bound_net_log); |
| 124 *file = base::kInvalidPlatformFileValue; | 124 *file = base::kInvalidPlatformFileValue; |
| 125 on_io_complete->Signal(); | 125 on_io_complete->Signal(); |
| 126 } | 126 } |
| 127 | 127 |
| 128 // Adjusts the position from where the data is read. | |
| 129 void SeekFile(base::PlatformFile file, | |
| 130 Whence whence, | |
| 131 int64 offset, | |
| 132 int64* result, | |
| 133 bool record_uma, | |
| 134 const net::BoundNetLog& bound_net_log) { | |
| 135 off_t res = lseek(file, static_cast<off_t>(offset), | |
| 136 static_cast<int>(whence)); | |
| 137 if (res == static_cast<off_t>(-1)) { | |
| 138 *result = RecordAndMapError(errno, | |
| 139 FILE_ERROR_SOURCE_SEEK, | |
| 140 record_uma, | |
| 141 bound_net_log); | |
| 142 return; | |
| 143 } | |
| 144 *result = res; | |
| 145 } | |
| 146 | |
| 147 // Seeks a file by calling SeekSync() and signals the completion. | |
| 148 void SeekFileAndSignal(base::PlatformFile file, | |
| 149 Whence whence, | |
| 150 int64 offset, | |
| 151 int64* result, | |
| 152 bool record_uma, | |
| 153 base::WaitableEvent* on_io_complete, | |
| 154 const net::BoundNetLog& bound_net_log) { | |
| 155 SeekFile(file, whence, offset, result, record_uma, bound_net_log); | |
| 156 on_io_complete->Signal(); | |
| 157 } | |
| 158 | |
| 128 // ReadFile() is a simple wrapper around read() that handles EINTR signals and | 159 // ReadFile() is a simple wrapper around read() that handles EINTR signals and |
| 129 // calls MapSystemError() to map errno to net error codes. | 160 // calls MapSystemError() to map errno to net error codes. |
| 130 void ReadFile(base::PlatformFile file, | 161 void ReadFile(base::PlatformFile file, |
| 131 char* buf, | 162 char* buf, |
| 132 int buf_len, | 163 int buf_len, |
| 133 bool record_uma, | 164 bool record_uma, |
| 134 int* result, | 165 int* result, |
| 135 const net::BoundNetLog& bound_net_log) { | 166 const net::BoundNetLog& bound_net_log) { |
| 136 base::ThreadRestrictions::AssertIOAllowed(); | 167 base::ThreadRestrictions::AssertIOAllowed(); |
| 137 // read(..., 0) returns 0 to indicate end-of-file. | 168 // read(..., 0) returns 0 to indicate end-of-file. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 const net::BoundNetLog& bound_net_log) { | 227 const net::BoundNetLog& bound_net_log) { |
| 197 base::ThreadRestrictions::AssertIOAllowed(); | 228 base::ThreadRestrictions::AssertIOAllowed(); |
| 198 ssize_t res = HANDLE_EINTR(fsync(file)); | 229 ssize_t res = HANDLE_EINTR(fsync(file)); |
| 199 if (res == -1) { | 230 if (res == -1) { |
| 200 res = RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma, | 231 res = RecordAndMapError(errno, FILE_ERROR_SOURCE_FLUSH, record_uma, |
| 201 bound_net_log); | 232 bound_net_log); |
| 202 } | 233 } |
| 203 return res; | 234 return res; |
| 204 } | 235 } |
| 205 | 236 |
| 237 // Called when Read(), Write() or Seek() is completed. | |
| 238 // |result| contains the result or a network error code. | |
| 239 template <typename R> | |
| 240 void OnIOComplete(const base::WeakPtr<FileStreamPosix>& stream, | |
| 241 const base::Callback<void(R)>& callback, | |
| 242 R* result) { | |
| 243 if (!stream.get()) | |
|
willchan no longer on Chromium
2012/04/05 15:12:28
You don't need this, base::Bind() will take care o
kinuko
2012/04/06 12:42:37
In this case stream is not a target object and I d
willchan no longer on Chromium
2012/04/09 12:33:57
Woops, totally misread that :)
| |
| 244 return; | |
| 245 | |
| 246 // Reset this before Run() as Run() may issue a new async operation. | |
| 247 stream->ResetOnIOComplete(); | |
| 248 callback.Run(*result); | |
| 249 } | |
| 250 | |
| 206 } // namespace | 251 } // namespace |
| 207 | 252 |
| 208 // FileStreamPosix ------------------------------------------------------------ | 253 // FileStreamPosix ------------------------------------------------------------ |
| 209 | 254 |
| 210 FileStreamPosix::FileStreamPosix(net::NetLog* net_log) | 255 FileStreamPosix::FileStreamPosix(net::NetLog* net_log) |
| 211 : file_(base::kInvalidPlatformFileValue), | 256 : file_(base::kInvalidPlatformFileValue), |
| 212 open_flags_(0), | 257 open_flags_(0), |
| 213 auto_closed_(true), | 258 auto_closed_(true), |
| 214 record_uma_(false), | 259 record_uma_(false), |
| 215 bound_net_log_(net::BoundNetLog::Make(net_log, | 260 bound_net_log_(net::BoundNetLog::Make(net_log, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 } else { | 295 } else { |
| 251 CloseSync(); | 296 CloseSync(); |
| 252 } | 297 } |
| 253 } | 298 } |
| 254 | 299 |
| 255 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); | 300 bound_net_log_.EndEvent(net::NetLog::TYPE_FILE_STREAM_ALIVE, NULL); |
| 256 } | 301 } |
| 257 | 302 |
| 258 void FileStreamPosix::Close(const CompletionCallback& callback) { | 303 void FileStreamPosix::Close(const CompletionCallback& callback) { |
| 259 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 304 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
| 260 DCHECK(callback_.is_null()); | |
|
willchan no longer on Chromium
2012/04/05 15:12:28
This DCHECK is useful. Let's keep it. It's basical
kinuko
2012/04/06 12:42:37
Done. I expect DCHECK(!on_io_complete_.get()) doe
| |
| 261 | |
| 262 callback_ = callback; | |
| 263 | 305 |
| 264 DCHECK(!on_io_complete_.get()); | 306 DCHECK(!on_io_complete_.get()); |
| 265 on_io_complete_.reset(new base::WaitableEvent( | 307 on_io_complete_.reset(new base::WaitableEvent( |
| 266 false /* manual_reset */, false /* initially_signaled */)); | 308 false /* manual_reset */, false /* initially_signaled */)); |
| 267 | 309 |
| 268 // Passing &file_ to a thread pool looks unsafe but it's safe here as the | 310 // Passing &file_ to a thread pool looks unsafe but it's safe here as the |
| 269 // destructor ensures that the close operation is complete with | 311 // destructor ensures that the close operation is complete with |
| 270 // WaitForIOCompletion(). See also the destructor. | 312 // WaitForIOCompletion(). See also the destructor. |
| 271 const bool posted = base::WorkerPool::PostTaskAndReply( | 313 const bool posted = base::WorkerPool::PostTaskAndReply( |
| 272 FROM_HERE, | 314 FROM_HERE, |
| 273 base::Bind(&CloseFileAndSignal, &file_, on_io_complete_.get(), | 315 base::Bind(&CloseFileAndSignal, &file_, on_io_complete_.get(), |
| 274 bound_net_log_), | 316 bound_net_log_), |
| 275 base::Bind(&FileStreamPosix::OnClosed, | 317 base::Bind(&FileStreamPosix::OnClosed, |
| 276 weak_ptr_factory_.GetWeakPtr()), | 318 weak_ptr_factory_.GetWeakPtr(), |
| 319 callback), | |
| 277 true /* task_is_slow */); | 320 true /* task_is_slow */); |
| 278 | 321 |
| 279 DCHECK(posted); | 322 DCHECK(posted); |
| 280 } | 323 } |
| 281 | 324 |
| 282 void FileStreamPosix::CloseSync() { | 325 void FileStreamPosix::CloseSync() { |
| 283 // TODO(satorux): Replace the following async stuff with a | 326 // TODO(satorux): Replace the following async stuff with a |
| 284 // DCHECK(open_flags & ASYNC) once once all async clients are migrated to | 327 // DCHECK(open_flags & ASYNC) once once all async clients are migrated to |
| 285 // use Close(). crbug.com/114783 | 328 // use Close(). crbug.com/114783 |
| 286 | 329 |
| 287 // Abort any existing asynchronous operations. | 330 // Abort any existing asynchronous operations. |
| 288 weak_ptr_factory_.InvalidateWeakPtrs(); | 331 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 289 // Block until the last open/read/write operation is complete. | 332 // Block until the last open/read/write operation is complete. |
| 290 // TODO(satorux): Ideally we should not block. crbug.com/115067 | 333 // TODO(satorux): Ideally we should not block. crbug.com/115067 |
| 291 WaitForIOCompletion(); | 334 WaitForIOCompletion(); |
| 292 | 335 |
| 293 CloseFile(file_, bound_net_log_); | 336 CloseFile(file_, bound_net_log_); |
| 294 file_ = base::kInvalidPlatformFileValue; | 337 file_ = base::kInvalidPlatformFileValue; |
| 295 } | 338 } |
| 296 | 339 |
| 297 int FileStreamPosix::Open(const FilePath& path, int open_flags, | 340 int FileStreamPosix::Open(const FilePath& path, int open_flags, |
| 298 const CompletionCallback& callback) { | 341 const CompletionCallback& callback) { |
| 299 if (IsOpen()) { | 342 if (IsOpen()) { |
| 300 DLOG(FATAL) << "File is already open!"; | 343 DLOG(FATAL) << "File is already open!"; |
| 301 return ERR_UNEXPECTED; | 344 return ERR_UNEXPECTED; |
| 302 } | 345 } |
| 303 | 346 |
| 304 DCHECK(callback_.is_null()); | |
| 305 callback_ = callback; | |
| 306 | |
| 307 open_flags_ = open_flags; | 347 open_flags_ = open_flags; |
| 308 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 348 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
| 309 | 349 |
| 310 DCHECK(!on_io_complete_.get()); | 350 DCHECK(!on_io_complete_.get()); |
| 311 on_io_complete_.reset(new base::WaitableEvent( | 351 on_io_complete_.reset(new base::WaitableEvent( |
| 312 false /* manual_reset */, false /* initially_signaled */)); | 352 false /* manual_reset */, false /* initially_signaled */)); |
| 313 | 353 |
| 314 // Passing &file_ to a thread pool looks unsafe but it's safe here as the | 354 // Passing &file_ to a thread pool looks unsafe but it's safe here as the |
| 315 // destructor ensures that the open operation is complete with | 355 // destructor ensures that the open operation is complete with |
| 316 // WaitForIOCompletion(). See also the destructor. | 356 // WaitForIOCompletion(). See also the destructor. |
| 317 int* result = new int(OK); | 357 int* result = new int(OK); |
| 318 const bool posted = base::WorkerPool::PostTaskAndReply( | 358 const bool posted = base::WorkerPool::PostTaskAndReply( |
| 319 FROM_HERE, | 359 FROM_HERE, |
| 320 base::Bind(&OpenFileAndSignal, | 360 base::Bind(&OpenFileAndSignal, |
| 321 path, open_flags, record_uma_, &file_, result, | 361 path, open_flags, record_uma_, &file_, result, |
| 322 on_io_complete_.get(), bound_net_log_), | 362 on_io_complete_.get(), bound_net_log_), |
| 323 base::Bind(&FileStreamPosix::OnIOComplete, | 363 base::Bind(&OnIOComplete<int>, weak_ptr_factory_.GetWeakPtr(), |
| 324 weak_ptr_factory_.GetWeakPtr(), | 364 callback, base::Owned(result)), |
| 325 base::Owned(result)), | |
| 326 true /* task_is_slow */); | 365 true /* task_is_slow */); |
| 327 DCHECK(posted); | 366 DCHECK(posted); |
| 328 return ERR_IO_PENDING; | 367 return ERR_IO_PENDING; |
| 329 } | 368 } |
| 330 | 369 |
| 331 int FileStreamPosix::OpenSync(const FilePath& path, int open_flags) { | 370 int FileStreamPosix::OpenSync(const FilePath& path, int open_flags) { |
| 332 if (IsOpen()) { | 371 if (IsOpen()) { |
| 333 DLOG(FATAL) << "File is already open!"; | 372 DLOG(FATAL) << "File is already open!"; |
| 334 return ERR_UNEXPECTED; | 373 return ERR_UNEXPECTED; |
| 335 } | 374 } |
| 336 | 375 |
| 337 open_flags_ = open_flags; | 376 open_flags_ = open_flags; |
| 338 // TODO(satorux): Put a DCHECK once once all async clients are migrated | 377 // TODO(satorux): Put a DCHECK once once all async clients are migrated |
| 339 // to use Open(). crbug.com/114783 | 378 // to use Open(). crbug.com/114783 |
| 340 // | 379 // |
| 341 // DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC)); | 380 // DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC)); |
| 342 | 381 |
| 343 int result = OK; | 382 int result = OK; |
| 344 OpenFile(path, open_flags_, record_uma_, &file_, &result, bound_net_log_); | 383 OpenFile(path, open_flags_, record_uma_, &file_, &result, bound_net_log_); |
| 345 return result; | 384 return result; |
| 346 } | 385 } |
| 347 | 386 |
| 348 bool FileStreamPosix::IsOpen() const { | 387 bool FileStreamPosix::IsOpen() const { |
| 349 return file_ != base::kInvalidPlatformFileValue; | 388 return file_ != base::kInvalidPlatformFileValue; |
| 350 } | 389 } |
| 351 | 390 |
| 352 int64 FileStreamPosix::Seek(Whence whence, int64 offset) { | 391 int FileStreamPosix::Seek(Whence whence, int64 offset, |
| 392 const Int64CompletionCallback& callback) { | |
| 393 if (!IsOpen()) | |
| 394 return ERR_UNEXPECTED; | |
| 395 | |
| 396 // Make sure we're async. | |
| 397 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | |
| 398 | |
| 399 int64* result = new int64(-1); | |
| 400 DCHECK(!on_io_complete_.get()); | |
| 401 const bool posted = base::WorkerPool::PostTaskAndReply( | |
| 402 FROM_HERE, | |
| 403 base::Bind(&SeekFileAndSignal, file_, whence, offset, result, | |
| 404 record_uma_, on_io_complete_.get(), bound_net_log_), | |
| 405 base::Bind(&OnIOComplete<int64>, | |
| 406 weak_ptr_factory_.GetWeakPtr(), | |
| 407 callback, base::Owned(result)), | |
| 408 true /* task is slow */); | |
| 409 DCHECK(posted); | |
| 410 return ERR_IO_PENDING; | |
| 411 } | |
| 412 | |
| 413 int64 FileStreamPosix::SeekSync(Whence whence, int64 offset) { | |
| 353 base::ThreadRestrictions::AssertIOAllowed(); | 414 base::ThreadRestrictions::AssertIOAllowed(); |
| 354 | 415 |
| 355 if (!IsOpen()) | 416 if (!IsOpen()) |
| 356 return ERR_UNEXPECTED; | 417 return ERR_UNEXPECTED; |
| 357 | 418 |
| 358 // If we're in async, make sure we don't have a request in flight. | 419 // If we're in async, make sure we don't have a request in flight. |
| 359 DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC) || | 420 DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC) || |
| 360 callback_.is_null()); | 421 !on_io_complete_.get()); |
| 361 | 422 |
| 362 off_t res = lseek(file_, static_cast<off_t>(offset), | 423 off_t result = -1; |
| 363 static_cast<int>(whence)); | 424 SeekFile(file_, whence, offset, &result, record_uma_, bound_net_log_); |
| 364 if (res == static_cast<off_t>(-1)) { | 425 return result; |
| 365 return RecordAndMapError(errno, | |
| 366 FILE_ERROR_SOURCE_SEEK, | |
| 367 record_uma_, | |
| 368 bound_net_log_); | |
| 369 } | |
| 370 | |
| 371 return res; | |
| 372 } | 426 } |
| 373 | 427 |
| 374 int64 FileStreamPosix::Available() { | 428 int64 FileStreamPosix::Available() { |
| 375 base::ThreadRestrictions::AssertIOAllowed(); | 429 base::ThreadRestrictions::AssertIOAllowed(); |
| 376 | 430 |
| 377 if (!IsOpen()) | 431 if (!IsOpen()) |
| 378 return ERR_UNEXPECTED; | 432 return ERR_UNEXPECTED; |
| 379 | 433 |
| 380 int64 cur_pos = Seek(FROM_CURRENT, 0); | 434 int64 cur_pos = SeekSync(FROM_CURRENT, 0); |
| 381 if (cur_pos < 0) | 435 if (cur_pos < 0) |
| 382 return cur_pos; | 436 return cur_pos; |
| 383 | 437 |
| 384 struct stat info; | 438 struct stat info; |
| 385 if (fstat(file_, &info) != 0) { | 439 if (fstat(file_, &info) != 0) { |
| 386 return RecordAndMapError(errno, | 440 return RecordAndMapError(errno, |
| 387 FILE_ERROR_SOURCE_GET_SIZE, | 441 FILE_ERROR_SOURCE_GET_SIZE, |
| 388 record_uma_, | 442 record_uma_, |
| 389 bound_net_log_); | 443 bound_net_log_); |
| 390 } | 444 } |
| 391 | 445 |
| 392 int64 size = static_cast<int64>(info.st_size); | 446 int64 size = static_cast<int64>(info.st_size); |
| 393 DCHECK_GT(size, cur_pos); | 447 DCHECK_GT(size, cur_pos); |
| 394 | 448 |
| 395 return size - cur_pos; | 449 return size - cur_pos; |
| 396 } | 450 } |
| 397 | 451 |
| 398 int FileStreamPosix::Read( | 452 int FileStreamPosix::Read( |
| 399 IOBuffer* in_buf, int buf_len, const CompletionCallback& callback) { | 453 IOBuffer* in_buf, int buf_len, const CompletionCallback& callback) { |
| 400 if (!IsOpen()) | 454 if (!IsOpen()) |
| 401 return ERR_UNEXPECTED; | 455 return ERR_UNEXPECTED; |
| 402 | 456 |
| 403 // read(..., 0) will return 0, which indicates end-of-file. | 457 // read(..., 0) will return 0, which indicates end-of-file. |
| 404 DCHECK_GT(buf_len, 0); | 458 DCHECK_GT(buf_len, 0); |
| 405 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); | 459 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); |
| 406 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 460 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
| 461 | |
| 407 // Make sure we don't have a request in flight. | 462 // Make sure we don't have a request in flight. |
| 408 DCHECK(callback_.is_null()); | |
| 409 | |
| 410 callback_ = callback; | |
| 411 int* result = new int(OK); | |
| 412 scoped_refptr<IOBuffer> buf = in_buf; | |
| 413 DCHECK(!on_io_complete_.get()); | 463 DCHECK(!on_io_complete_.get()); |
| 414 on_io_complete_.reset(new base::WaitableEvent( | 464 on_io_complete_.reset(new base::WaitableEvent( |
| 415 false /* manual_reset */, false /* initially_signaled */)); | 465 false /* manual_reset */, false /* initially_signaled */)); |
| 466 | |
| 467 int* result = new int(OK); | |
| 468 scoped_refptr<IOBuffer> buf = in_buf; | |
| 416 const bool posted = base::WorkerPool::PostTaskAndReply( | 469 const bool posted = base::WorkerPool::PostTaskAndReply( |
| 417 FROM_HERE, | 470 FROM_HERE, |
| 418 base::Bind(&ReadFileAndSignal, file_, buf, buf_len, | 471 base::Bind(&ReadFileAndSignal, file_, buf, buf_len, |
| 419 record_uma_, result, on_io_complete_.get(), bound_net_log_), | 472 record_uma_, result, on_io_complete_.get(), bound_net_log_), |
| 420 base::Bind(&FileStreamPosix::OnIOComplete, | 473 base::Bind(&OnIOComplete<int>, |
| 421 weak_ptr_factory_.GetWeakPtr(), | 474 weak_ptr_factory_.GetWeakPtr(), |
| 422 base::Owned(result)), | 475 callback, base::Owned(result)), |
| 423 true /* task is slow */); | 476 true /* task is slow */); |
| 424 DCHECK(posted); | 477 DCHECK(posted); |
| 425 return ERR_IO_PENDING; | 478 return ERR_IO_PENDING; |
| 426 } | 479 } |
| 427 | 480 |
| 428 int FileStreamPosix::ReadSync(char* buf, int buf_len) { | 481 int FileStreamPosix::ReadSync(char* buf, int buf_len) { |
| 429 if (!IsOpen()) | 482 if (!IsOpen()) |
| 430 return ERR_UNEXPECTED; | 483 return ERR_UNEXPECTED; |
| 431 | 484 |
| 432 DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC)); | 485 DCHECK(!(open_flags_ & base::PLATFORM_FILE_ASYNC)); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 462 | 515 |
| 463 int FileStreamPosix::Write( | 516 int FileStreamPosix::Write( |
| 464 IOBuffer* in_buf, int buf_len, const CompletionCallback& callback) { | 517 IOBuffer* in_buf, int buf_len, const CompletionCallback& callback) { |
| 465 if (!IsOpen()) | 518 if (!IsOpen()) |
| 466 return ERR_UNEXPECTED; | 519 return ERR_UNEXPECTED; |
| 467 | 520 |
| 468 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 521 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
| 469 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 522 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); |
| 470 // write(..., 0) will return 0, which indicates end-of-file. | 523 // write(..., 0) will return 0, which indicates end-of-file. |
| 471 DCHECK_GT(buf_len, 0); | 524 DCHECK_GT(buf_len, 0); |
| 525 | |
| 472 // Make sure we don't have a request in flight. | 526 // Make sure we don't have a request in flight. |
| 473 DCHECK(callback_.is_null()); | |
| 474 | |
| 475 callback_ = callback; | |
| 476 int* result = new int(OK); | |
| 477 scoped_refptr<IOBuffer> buf = in_buf; | |
| 478 DCHECK(!on_io_complete_.get()); | 527 DCHECK(!on_io_complete_.get()); |
| 479 on_io_complete_.reset(new base::WaitableEvent( | 528 on_io_complete_.reset(new base::WaitableEvent( |
| 480 false /* manual_reset */, false /* initially_signaled */)); | 529 false /* manual_reset */, false /* initially_signaled */)); |
| 530 | |
| 531 int* result = new int(OK); | |
| 532 scoped_refptr<IOBuffer> buf = in_buf; | |
| 481 const bool posted = base::WorkerPool::PostTaskAndReply( | 533 const bool posted = base::WorkerPool::PostTaskAndReply( |
| 482 FROM_HERE, | 534 FROM_HERE, |
| 483 base::Bind(&WriteFileAndSignal, file_, buf, buf_len, | 535 base::Bind(&WriteFileAndSignal, file_, buf, buf_len, |
| 484 record_uma_, result, on_io_complete_.get(), bound_net_log_), | 536 record_uma_, result, on_io_complete_.get(), bound_net_log_), |
| 485 base::Bind(&FileStreamPosix::OnIOComplete, | 537 base::Bind(&OnIOComplete<int>, |
| 486 weak_ptr_factory_.GetWeakPtr(), | 538 weak_ptr_factory_.GetWeakPtr(), |
| 487 base::Owned(result)), | 539 callback, base::Owned(result)), |
| 488 true /* task is slow */); | 540 true /* task is slow */); |
| 489 DCHECK(posted); | 541 DCHECK(posted); |
| 490 return ERR_IO_PENDING; | 542 return ERR_IO_PENDING; |
| 491 } | 543 } |
| 492 | 544 |
| 493 int FileStreamPosix::WriteSync( | 545 int FileStreamPosix::WriteSync( |
| 494 const char* buf, int buf_len) { | 546 const char* buf, int buf_len) { |
| 495 if (!IsOpen()) | 547 if (!IsOpen()) |
| 496 return ERR_UNEXPECTED; | 548 return ERR_UNEXPECTED; |
| 497 | 549 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 508 int64 FileStreamPosix::Truncate(int64 bytes) { | 560 int64 FileStreamPosix::Truncate(int64 bytes) { |
| 509 base::ThreadRestrictions::AssertIOAllowed(); | 561 base::ThreadRestrictions::AssertIOAllowed(); |
| 510 | 562 |
| 511 if (!IsOpen()) | 563 if (!IsOpen()) |
| 512 return ERR_UNEXPECTED; | 564 return ERR_UNEXPECTED; |
| 513 | 565 |
| 514 // We'd better be open for writing. | 566 // We'd better be open for writing. |
| 515 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 567 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); |
| 516 | 568 |
| 517 // Seek to the position to truncate from. | 569 // Seek to the position to truncate from. |
| 518 int64 seek_position = Seek(FROM_BEGIN, bytes); | 570 int64 seek_position = SeekSync(FROM_BEGIN, bytes); |
| 519 if (seek_position != bytes) | 571 if (seek_position != bytes) |
| 520 return ERR_UNEXPECTED; | 572 return ERR_UNEXPECTED; |
| 521 | 573 |
| 522 // And truncate the file. | 574 // And truncate the file. |
| 523 int result = ftruncate(file_, bytes); | 575 int result = ftruncate(file_, bytes); |
| 524 if (result == 0) | 576 if (result == 0) |
| 525 return seek_position; | 577 return seek_position; |
| 526 | 578 |
| 527 return RecordAndMapError(errno, | 579 return RecordAndMapError(errno, |
| 528 FILE_ERROR_SOURCE_SET_EOF, | 580 FILE_ERROR_SOURCE_SET_EOF, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 net::NetLog::TYPE_FILE_STREAM_SOURCE, | 614 net::NetLog::TYPE_FILE_STREAM_SOURCE, |
| 563 make_scoped_refptr( | 615 make_scoped_refptr( |
| 564 new net::NetLogSourceParameter("source_dependency", | 616 new net::NetLogSourceParameter("source_dependency", |
| 565 bound_net_log_.source()))); | 617 bound_net_log_.source()))); |
| 566 } | 618 } |
| 567 | 619 |
| 568 base::PlatformFile FileStreamPosix::GetPlatformFileForTesting() { | 620 base::PlatformFile FileStreamPosix::GetPlatformFileForTesting() { |
| 569 return file_; | 621 return file_; |
| 570 } | 622 } |
| 571 | 623 |
| 572 void FileStreamPosix::OnClosed() { | 624 void FileStreamPosix::ResetOnIOComplete() { |
|
willchan no longer on Chromium
2012/04/05 15:12:28
I'd invalidate weak pointers at the WeakPtrFactory
kinuko
2012/04/06 12:42:37
Good idea, added the invalidation and DCHECKs.
| |
| 573 file_ = base::kInvalidPlatformFileValue; | 625 on_io_complete_.reset(); |
| 574 int result = OK; | |
| 575 OnIOComplete(&result); | |
| 576 } | 626 } |
| 577 | 627 |
| 578 void FileStreamPosix::OnIOComplete(int* result) { | 628 void FileStreamPosix::OnClosed(const CompletionCallback& callback) { |
| 579 CompletionCallback temp_callback = callback_; | 629 file_ = base::kInvalidPlatformFileValue; |
| 580 callback_.Reset(); | |
| 581 | 630 |
| 582 // Reset this before Run() as Run() may issue a new async operation. | 631 // Reset this before Run() as Run() may issue a new async operation. |
| 583 on_io_complete_.reset(); | 632 on_io_complete_.reset(); |
| 584 temp_callback.Run(*result); | 633 callback.Run(OK); |
| 585 } | 634 } |
| 586 | 635 |
| 587 void FileStreamPosix::WaitForIOCompletion() { | 636 void FileStreamPosix::WaitForIOCompletion() { |
| 588 if (on_io_complete_.get()) { | 637 if (on_io_complete_.get()) { |
| 589 on_io_complete_->Wait(); | 638 on_io_complete_->Wait(); |
| 590 on_io_complete_.reset(); | 639 on_io_complete_.reset(); |
| 591 } | 640 } |
| 592 } | 641 } |
| 593 | 642 |
| 594 } // namespace net | 643 } // namespace net |
| OLD | NEW |