// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/disk_cache/blockfile/file.h"

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "net/base/net_errors.h"
#include "net/disk_cache/disk_cache.h"

namespace {

// The maximum number of threads for this pool.
const int kMaxThreads = 5;

class FileWorkerPool : public base::SequencedWorkerPool {
 public:
  FileWorkerPool() : base::SequencedWorkerPool(kMaxThreads, "CachePool") {}

 protected:
  ~FileWorkerPool() override {}
};

base::LazyInstance<FileWorkerPool>::Leaky s_worker_pool =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace

namespace disk_cache {

File::File(base::File file)
    : init_(true),
      mixed_(true),
      base_file_(file.Pass()) {
}

bool File::Init(const base::FilePath& name) {
  if (base_file_.IsValid())
    return false;

  int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
              base::File::FLAG_WRITE;
  base_file_.Initialize(name, flags);
  return base_file_.IsValid();
}

bool File::IsValid() const {
  return base_file_.IsValid();
}

bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
  DCHECK(base_file_.IsValid());
  if (buffer_len > static_cast<size_t>(kint32max) ||
      offset > static_cast<size_t>(kint32max)) {
    return false;
  }

  int ret = base_file_.Read(offset, static_cast<char*>(buffer), buffer_len);
  return (static_cast<size_t>(ret) == buffer_len);
}

bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
  DCHECK(base_file_.IsValid());
  if (buffer_len > static_cast<size_t>(kint32max) ||
      offset > static_cast<size_t>(kint32max)) {
    return false;
  }

  int ret = base_file_.Write(offset, static_cast<const char*>(buffer),
                             buffer_len);
  return (static_cast<size_t>(ret) == buffer_len);
}

bool File::Read(void* buffer, size_t buffer_len, size_t offset,
                FileIOCallback* callback, bool* completed) {
  DCHECK(base_file_.IsValid());
  if (!callback) {
    if (completed)
      *completed = true;
    return Read(buffer, buffer_len, offset);
  }

  if (buffer_len > static_cast<size_t>(kint32max) ||
      offset > static_cast<size_t>(kint32max)) {
    return false;
  }

  base::PostTaskAndReplyWithResult(
      s_worker_pool.Pointer(), FROM_HERE,
      base::Bind(&File::DoRead, this, buffer, buffer_len, offset),
      base::Bind(&File::OnOperationComplete, this, callback));

  *completed = false;
  return true;
}

bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
                 FileIOCallback* callback, bool* completed) {
  DCHECK(base_file_.IsValid());
  if (!callback) {
    if (completed)
      *completed = true;
    return Write(buffer, buffer_len, offset);
  }

  if (buffer_len > static_cast<size_t>(kint32max) ||
      offset > static_cast<size_t>(kint32max)) {
    return false;
  }

  base::PostTaskAndReplyWithResult(
      s_worker_pool.Pointer(), FROM_HERE,
      base::Bind(&File::DoWrite, this, buffer, buffer_len, offset),
      base::Bind(&File::OnOperationComplete, this, callback));

  *completed = false;
  return true;
}

bool File::SetLength(size_t length) {
  DCHECK(base_file_.IsValid());
  if (length > kuint32max)
    return false;

  return base_file_.SetLength(length);
}

size_t File::GetLength() {
  DCHECK(base_file_.IsValid());
  int64 len = base_file_.GetLength();

  if (len > static_cast<int64>(kuint32max))
    return kuint32max;

  return static_cast<size_t>(len);
}

// Static.
void File::WaitForPendingIO(int* num_pending_io) {
  // We are running unit tests so we should wait for all callbacks. Sadly, the
  // worker pool only waits for tasks on the worker pool, not the "Reply" tasks
  // so we have to let the current message loop to run.
  s_worker_pool.Get().FlushForTesting();
  base::RunLoop().RunUntilIdle();
}

// Static.
void File::DropPendingIO() {
}


File::~File() {
}

base::PlatformFile File::platform_file() const {
  return base_file_.GetPlatformFile();
}

// Runs on a worker thread.
int File::DoRead(void* buffer, size_t buffer_len, size_t offset) {
  if (Read(const_cast<void*>(buffer), buffer_len, offset))
    return static_cast<int>(buffer_len);

  return net::ERR_CACHE_READ_FAILURE;
}

// Runs on a worker thread.
int File::DoWrite(const void* buffer, size_t buffer_len, size_t offset) {
  if (Write(const_cast<void*>(buffer), buffer_len, offset))
    return static_cast<int>(buffer_len);

  return net::ERR_CACHE_WRITE_FAILURE;
}

// This method actually makes sure that the last reference to the file doesn't
// go away on the worker pool.
void File::OnOperationComplete(FileIOCallback* callback, int result) {
  callback->OnFileIOComplete(result);
}

}  // namespace disk_cache
