15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/disk_cache/blockfile/file.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/lazy_instance.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/run_loop.h"
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/task_runner_util.h"
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/disk_cache/disk_cache.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The maximum number of threads for this pool.
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMaxThreads = 5;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class FileWorkerPool : public base::SequencedWorkerPool {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  FileWorkerPool() : base::SequencedWorkerPool(kMaxThreads, "CachePool") {}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual ~FileWorkerPool() {}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)base::LazyInstance<FileWorkerPool>::Leaky s_worker_pool =
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace disk_cache {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochFile::File(base::File file)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : init_(true),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixed_(true),
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base_file_(file.Pass()) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool File::Init(const base::FilePath& name) {
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (base_file_.IsValid())
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              base::File::FLAG_WRITE;
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  base_file_.Initialize(name, flags);
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.IsValid();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool File::IsValid() const {
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.IsValid();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_len > static_cast<size_t>(kint32max) ||
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      offset > static_cast<size_t>(kint32max)) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int ret = base_file_.Read(offset, static_cast<char*>(buffer), buffer_len);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (static_cast<size_t>(ret) == buffer_len);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_len > static_cast<size_t>(kint32max) ||
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      offset > static_cast<size_t>(kint32max)) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int ret = base_file_.Write(offset, static_cast<const char*>(buffer),
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                             buffer_len);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (static_cast<size_t>(ret) == buffer_len);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool File::Read(void* buffer, size_t buffer_len, size_t offset,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                FileIOCallback* callback, bool* completed) {
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (completed)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *completed = true;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Read(buffer, buffer_len, offset);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (buffer_len > static_cast<size_t>(kint32max) ||
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      offset > static_cast<size_t>(kint32max)) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      s_worker_pool.Pointer(), FROM_HERE,
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Bind(&File::DoRead, this, buffer, buffer_len, offset),
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Bind(&File::OnOperationComplete, this, callback));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *completed = false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 FileIOCallback* callback, bool* completed) {
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!callback) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (completed)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *completed = true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Write(buffer, buffer_len, offset);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (buffer_len > static_cast<size_t>(kint32max) ||
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      offset > static_cast<size_t>(kint32max)) {
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      s_worker_pool.Pointer(), FROM_HERE,
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Bind(&File::DoWrite, this, buffer, buffer_len, offset),
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::Bind(&File::OnOperationComplete, this, callback));
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  *completed = false;
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return true;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool File::SetLength(size_t length) {
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (length > kuint32max)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.SetLength(length);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t File::GetLength() {
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(base_file_.IsValid());
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  int64 len = base_file_.GetLength();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (len > static_cast<int64>(kuint32max))
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return kuint32max;
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return static_cast<size_t>(len);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static.
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void File::WaitForPendingIO(int* num_pending_io) {
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We are running unit tests so we should wait for all callbacks. Sadly, the
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // worker pool only waits for tasks on the worker pool, not the "Reply" tasks
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // so we have to let the current message loop to run.
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  s_worker_pool.Get().FlushForTesting();
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Static.
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void File::DropPendingIO() {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)File::~File() {
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
161c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbase::PlatformFile File::platform_file() const {
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return base_file_.GetPlatformFile();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Runs on a worker thread.
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int File::DoRead(void* buffer, size_t buffer_len, size_t offset) {
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Read(const_cast<void*>(buffer), buffer_len, offset))
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return static_cast<int>(buffer_len);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return net::ERR_CACHE_READ_FAILURE;
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Runs on a worker thread.
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int File::DoWrite(const void* buffer, size_t buffer_len, size_t offset) {
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (Write(const_cast<void*>(buffer), buffer_len, offset))
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return static_cast<int>(buffer_len);
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return net::ERR_CACHE_WRITE_FAILURE;
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// This method actually makes sure that the last reference to the file doesn't
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// go away on the worker pool.
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void File::OnOperationComplete(FileIOCallback* callback, int result) {
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  callback->OnFileIOComplete(result);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace disk_cache
188