15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/file.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/worker_pool.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/net_errors.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/in_flight_io.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/disk_cache/disk_cache.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class represents a single asynchronous IO operation while it is being
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// bounced between threads.
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class FileBackgroundIO : public disk_cache::BackgroundIO {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Other than the actual parameters for the IO operation (including the
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |callback| that must be notified at the end), we need the controller that
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is keeping track of all operations. When done, we notify the controller
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (we do NOT invoke the callback), in the worker thead that completed the
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // operation.
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len,
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   size_t offset, disk_cache::FileIOCallback* callback,
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   disk_cache::InFlightIO* controller)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : disk_cache::BackgroundIO(controller), callback_(callback), file_(file),
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        buf_(buf), buf_len_(buf_len), offset_(offset) {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  disk_cache::FileIOCallback* callback() {
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return callback_;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  disk_cache::File* file() {
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return file_;
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Read and Write are the operations that can be performed asynchronously.
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The actual parameters for the operation are setup in the constructor of
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the object. Both methods should be called from a worker thread, by posting
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a task to the WorkerPool (they are RunnableMethods). When finished,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // controller->OnIOComplete() is called.
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Read();
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Write();
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~FileBackgroundIO() {}
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  disk_cache::FileIOCallback* callback_;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  disk_cache::File* file_;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const void* buf_;
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t buf_len_;
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t offset_;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO);
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The specialized controller that keeps track of current operations.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class FileInFlightIO : public disk_cache::InFlightIO {
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileInFlightIO() {}
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~FileInFlightIO() {}
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // These methods start an asynchronous operation. The arguments have the same
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // semantics of the File asynchronous operations, with the exception that the
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // operation never finishes synchronously.
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void PostRead(disk_cache::File* file, void* buf, size_t buf_len,
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                size_t offset, disk_cache::FileIOCallback* callback);
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len,
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 size_t offset, disk_cache::FileIOCallback* callback);
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Invokes the users' completion callback at the end of the IO operation.
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |cancel| is true if the actual task posted to the thread is still
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // queued (because we are inside WaitForPendingIO), and false if said task is
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // the one performing the call.
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnOperationComplete(disk_cache::BackgroundIO* operation,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   bool cancel) OVERRIDE;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FileInFlightIO);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ---------------------------------------------------------------------------
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Runs on a worker thread.
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileBackgroundIO::Read() {
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (file_->Read(const_cast<void*>(buf_), buf_len_, offset_)) {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result_ = static_cast<int>(buf_len_);
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    result_ = net::ERR_CACHE_READ_FAILURE;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyController();
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Runs on a worker thread.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileBackgroundIO::Write() {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool rv = file_->Write(buf_, buf_len_, offset_);
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  result_ = rv ? static_cast<int>(buf_len_) : net::ERR_CACHE_WRITE_FAILURE;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NotifyController();
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ---------------------------------------------------------------------------
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          size_t offset, disk_cache::FileIOCallback *callback) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<FileBackgroundIO> operation(
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file->AddRef();  // Balanced on OnOperationComplete()
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WorkerPool::PostTask(FROM_HERE,
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&FileBackgroundIO::Read, operation.get()), true);
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OnOperationPosted(operation.get());
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf,
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           size_t buf_len, size_t offset,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           disk_cache::FileIOCallback* callback) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<FileBackgroundIO> operation(
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file->AddRef();  // Balanced on OnOperationComplete()
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WorkerPool::PostTask(FROM_HERE,
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&FileBackgroundIO::Write, operation.get()), true);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OnOperationPosted(operation.get());
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Runs on the IO thread.
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation,
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         bool cancel) {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation);
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  disk_cache::FileIOCallback* callback = op->callback();
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int bytes = operation->result();
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Release the references acquired in PostRead / PostWrite.
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  op->file()->Release();
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback->OnFileIOComplete(bytes);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// A static object that will broker all async operations.
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileInFlightIO* s_file_operations = NULL;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns the current FileInFlightIO.
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileInFlightIO* GetFileInFlightIO() {
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!s_file_operations) {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    s_file_operations = new FileInFlightIO;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return s_file_operations;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Deletes the current FileInFlightIO.
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DeleteFileInFlightIO() {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(s_file_operations);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete s_file_operations;
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s_file_operations = NULL;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace disk_cache {
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochFile::File(base::File file)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : init_(true),
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      mixed_(true),
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base_file_(file.Pass()) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::Init(const base::FilePath& name) {
176c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (base_file_.IsValid())
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
179c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
180c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              base::File::FLAG_WRITE;
181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base_file_.Initialize(name, flags);
182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.IsValid();
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::IsValid() const {
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.IsValid();
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (buffer_len > static_cast<size_t>(kint32max) ||
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      offset > static_cast<size_t>(kint32max)) {
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
196c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int ret = base_file_.Read(offset, static_cast<char*>(buffer), buffer_len);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (static_cast<size_t>(ret) == buffer_len);
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
201c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (buffer_len > static_cast<size_t>(kint32max) ||
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      offset > static_cast<size_t>(kint32max)) {
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int ret = base_file_.Write(offset, static_cast<const char*>(buffer),
208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                             buffer_len);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return (static_cast<size_t>(ret) == buffer_len);
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// We have to increase the ref counter of the file before performing the IO to
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// prevent the completion to happen with an invalid handle (if the file is
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// closed while the IO is in flight).
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::Read(void* buffer, size_t buffer_len, size_t offset,
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                FileIOCallback* callback, bool* completed) {
217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!callback) {
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (completed)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *completed = true;
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Read(buffer, buffer_len, offset);
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback);
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *completed = false;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 FileIOCallback* callback, bool* completed) {
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!callback) {
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (completed)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *completed = true;
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Write(buffer, buffer_len, offset);
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return AsyncWrite(buffer, buffer_len, offset, callback, completed);
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::SetLength(size_t length) {
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (length > kuint32max)
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.SetLength(length);
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t File::GetLength() {
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int64 len = base_file_.GetLength();
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (len > static_cast<int64>(kuint32max))
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return kuint32max;
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return static_cast<size_t>(len);
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Static.
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void File::WaitForPendingIO(int* num_pending_io) {
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We may be running unit tests so we should allow be able to reset the
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // message loop.
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetFileInFlightIO()->WaitForPendingIO();
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeleteFileInFlightIO();
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Static.
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void File::DropPendingIO() {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetFileInFlightIO()->DropPendingIO();
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeleteFileInFlightIO();
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)File::~File() {
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbase::PlatformFile File::platform_file() const {
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.GetPlatformFile();
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      FileIOCallback* callback, bool* completed) {
286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback);
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (completed)
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *completed = false;
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace disk_cache
298