// Copyright (c) 2013 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/tracing_cache_backend.h"

#include "net/base/net_errors.h"

namespace disk_cache {

// Proxies entry objects created by the real underlying backend. Backend users
// will only see the proxy entries. It is necessary for recording the backend
// operations since often non-trivial work is invoked directly on entries.
class EntryProxy : public Entry, public base::RefCountedThreadSafe<EntryProxy> {
 public:
  EntryProxy(Entry *entry, TracingCacheBackend* backend);
  virtual void Doom() OVERRIDE;
  virtual void Close() OVERRIDE;
  virtual std::string GetKey() const OVERRIDE;
  virtual base::Time GetLastUsed() const OVERRIDE;
  virtual base::Time GetLastModified() const OVERRIDE;
  virtual int32 GetDataSize(int index) const OVERRIDE;
  virtual int ReadData(int index, int offset, IOBuffer* buf, int buf_len,
                       const CompletionCallback& callback) OVERRIDE;
  virtual int WriteData(int index, int offset, IOBuffer* buf, int buf_len,
                        const CompletionCallback& callback,
                        bool truncate) OVERRIDE;
  virtual int ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
                             const CompletionCallback& callback) OVERRIDE;
  virtual int WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
                              const CompletionCallback& callback) OVERRIDE;
  virtual int GetAvailableRange(int64 offset, int len, int64* start,
                                const CompletionCallback& callback) OVERRIDE;
  virtual bool CouldBeSparse() const OVERRIDE;
  virtual void CancelSparseIO() OVERRIDE;
  virtual int ReadyForSparseIO(const CompletionCallback& callback) OVERRIDE;

 private:
  friend class base::RefCountedThreadSafe<EntryProxy>;
  typedef TracingCacheBackend::Operation Operation;
  virtual ~EntryProxy();

  struct RwOpExtra {
    int index;
    int offset;
    int buf_len;
    bool truncate;
  };

  void RecordEvent(base::TimeTicks start_time, Operation op, RwOpExtra extra,
                   int result_to_record);
  void EntryOpComplete(base::TimeTicks start_time, Operation op,
                       RwOpExtra extra, const CompletionCallback& cb,
                       int result);
  Entry* entry_;
  base::WeakPtr<TracingCacheBackend> backend_;

  DISALLOW_COPY_AND_ASSIGN(EntryProxy);
};

EntryProxy::EntryProxy(Entry *entry, TracingCacheBackend* backend)
  : entry_(entry),
    backend_(backend->AsWeakPtr()) {
}

void EntryProxy::Doom() {
  // TODO(pasko): Record the event.
  entry_->Doom();
}

void EntryProxy::Close() {
  // TODO(pasko): Record the event.
  entry_->Close();
  Release();
}

std::string EntryProxy::GetKey() const {
  return entry_->GetKey();
}

base::Time EntryProxy::GetLastUsed() const {
  return entry_->GetLastUsed();
}

base::Time EntryProxy::GetLastModified() const {
  return entry_->GetLastModified();
}

int32 EntryProxy::GetDataSize(int index) const {
  return entry_->GetDataSize(index);
}

int EntryProxy::ReadData(int index, int offset, IOBuffer* buf, int buf_len,
                         const CompletionCallback& callback) {
  base::TimeTicks start_time = base::TimeTicks::Now();
  RwOpExtra extra;
  extra.index = index;
  extra.offset = offset;
  extra.buf_len = buf_len;
  extra.truncate = false;
  int rv = entry_->ReadData(
      index, offset, buf, buf_len,
      base::Bind(&EntryProxy::EntryOpComplete, this, start_time,
                 TracingCacheBackend::OP_READ, extra, callback));
  if (rv != net::ERR_IO_PENDING) {
    RecordEvent(start_time, TracingCacheBackend::OP_READ, extra, rv);
  }
  return rv;
}

int EntryProxy::WriteData(int index, int offset, IOBuffer* buf, int buf_len,
                      const CompletionCallback& callback,
                      bool truncate) {
  base::TimeTicks start_time = base::TimeTicks::Now();
  RwOpExtra extra;
  extra.index = index;
  extra.offset = offset;
  extra.buf_len = buf_len;
  extra.truncate = truncate;
  int rv = entry_->WriteData(index, offset, buf, buf_len,
      base::Bind(&EntryProxy::EntryOpComplete, this, start_time,
                 TracingCacheBackend::OP_WRITE, extra, callback),
      truncate);
  if (rv != net::ERR_IO_PENDING) {
    RecordEvent(start_time, TracingCacheBackend::OP_WRITE, extra, rv);
  }
  return rv;
}

int EntryProxy::ReadSparseData(int64 offset, IOBuffer* buf, int buf_len,
                           const CompletionCallback& callback) {
  // TODO(pasko): Record the event.
  return entry_->ReadSparseData(offset, buf, buf_len, callback);
}

int EntryProxy::WriteSparseData(int64 offset, IOBuffer* buf, int buf_len,
                            const CompletionCallback& callback) {
  // TODO(pasko): Record the event.
  return entry_->WriteSparseData(offset, buf, buf_len, callback);
}

int EntryProxy::GetAvailableRange(int64 offset, int len, int64* start,
                              const CompletionCallback& callback) {
  return entry_->GetAvailableRange(offset, len, start, callback);
}

bool EntryProxy::CouldBeSparse() const {
  return entry_->CouldBeSparse();
}

void EntryProxy::CancelSparseIO() {
  return entry_->CancelSparseIO();
}

int EntryProxy::ReadyForSparseIO(const CompletionCallback& callback) {
  return entry_->ReadyForSparseIO(callback);
}

void EntryProxy::RecordEvent(base::TimeTicks start_time, Operation op,
                             RwOpExtra extra, int result_to_record) {
  // TODO(pasko): Implement.
}

void EntryProxy::EntryOpComplete(base::TimeTicks start_time, Operation op,
                                 RwOpExtra extra, const CompletionCallback& cb,
                                 int result) {
  RecordEvent(start_time, op, extra, result);
  if (!cb.is_null()) {
    cb.Run(result);
  }
}

EntryProxy::~EntryProxy() {
  if (backend_.get()) {
    backend_->OnDeleteEntry(entry_);
  }
}

TracingCacheBackend::TracingCacheBackend(scoped_ptr<Backend> backend)
  : backend_(backend.Pass()) {
}

TracingCacheBackend::~TracingCacheBackend() {
}

net::CacheType TracingCacheBackend::GetCacheType() const {
  return backend_->GetCacheType();
}

int32 TracingCacheBackend::GetEntryCount() const {
  return backend_->GetEntryCount();
}

void TracingCacheBackend::RecordEvent(base::TimeTicks start_time, Operation op,
                                      std::string key, Entry* entry, int rv) {
  // TODO(pasko): Implement.
}

EntryProxy* TracingCacheBackend::FindOrCreateEntryProxy(Entry* entry) {
  EntryProxy* entry_proxy;
  EntryToProxyMap::iterator it = open_entries_.find(entry);
  if (it != open_entries_.end()) {
    entry_proxy = it->second;
    entry_proxy->AddRef();
    return entry_proxy;
  }
  entry_proxy = new EntryProxy(entry, this);
  entry_proxy->AddRef();
  open_entries_[entry] = entry_proxy;
  return entry_proxy;
}

void TracingCacheBackend::OnDeleteEntry(Entry* entry) {
  EntryToProxyMap::iterator it = open_entries_.find(entry);
  if (it != open_entries_.end()) {
    open_entries_.erase(it);
  }
}

void TracingCacheBackend::BackendOpComplete(base::TimeTicks start_time,
                                            Operation op,
                                            std::string key,
                                            Entry** entry,
                                            const CompletionCallback& callback,
                                            int result) {
  RecordEvent(start_time, op, key, *entry, result);
  if (*entry) {
    *entry = FindOrCreateEntryProxy(*entry);
  }
  if (!callback.is_null()) {
    callback.Run(result);
  }
}

net::CompletionCallback TracingCacheBackend::BindCompletion(
    Operation op, base::TimeTicks start_time, const std::string& key,
    Entry **entry, const net::CompletionCallback& cb) {
  return base::Bind(&TracingCacheBackend::BackendOpComplete,
                    AsWeakPtr(), start_time, op, key, entry, cb);
}

int TracingCacheBackend::OpenEntry(const std::string& key, Entry** entry,
                                   const CompletionCallback& callback) {
  DCHECK(*entry == NULL);
  base::TimeTicks start_time = base::TimeTicks::Now();
  int rv = backend_->OpenEntry(key, entry,
                               BindCompletion(OP_OPEN, start_time, key, entry,
                                              callback));
  if (rv != net::ERR_IO_PENDING) {
    RecordEvent(start_time, OP_OPEN, key, *entry, rv);
    if (*entry) {
      *entry = FindOrCreateEntryProxy(*entry);
    }
  }
  return rv;
}

int TracingCacheBackend::CreateEntry(const std::string& key, Entry** entry,
                                     const CompletionCallback& callback) {
  base::TimeTicks start_time = base::TimeTicks::Now();
  int rv = backend_->CreateEntry(key, entry,
                                 BindCompletion(OP_CREATE, start_time, key,
                                                entry, callback));
  if (rv != net::ERR_IO_PENDING) {
    RecordEvent(start_time, OP_CREATE, key, *entry, rv);
    if (*entry) {
      *entry = FindOrCreateEntryProxy(*entry);
    }
  }
  return rv;
}

int TracingCacheBackend::DoomEntry(const std::string& key,
                                   const CompletionCallback& callback) {
  base::TimeTicks start_time = base::TimeTicks::Now();
  int rv = backend_->DoomEntry(key, BindCompletion(OP_DOOM_ENTRY,
                                                   start_time, key, NULL,
                                                   callback));
  if (rv != net::ERR_IO_PENDING) {
    RecordEvent(start_time, OP_DOOM_ENTRY, key, NULL, rv);
  }
  return rv;
}

int TracingCacheBackend::DoomAllEntries(const CompletionCallback& callback) {
  return backend_->DoomAllEntries(callback);
}

int TracingCacheBackend::DoomEntriesBetween(base::Time initial_time,
                                            base::Time end_time,
                                            const CompletionCallback& cb) {
  return backend_->DoomEntriesBetween(initial_time, end_time, cb);
}

int TracingCacheBackend::DoomEntriesSince(base::Time initial_time,
                                          const CompletionCallback& callback) {
  return backend_->DoomEntriesSince(initial_time, callback);
}

int TracingCacheBackend::OpenNextEntry(void** iter, Entry** next_entry,
                                       const CompletionCallback& callback) {
  return backend_->OpenNextEntry(iter, next_entry, callback);
}

void TracingCacheBackend::EndEnumeration(void** iter) {
  return backend_->EndEnumeration(iter);
}

void TracingCacheBackend::GetStats(StatsItems* stats) {
  return backend_->GetStats(stats);
}

void TracingCacheBackend::OnExternalCacheHit(const std::string& key) {
  return backend_->OnExternalCacheHit(key);
}

}  // namespace disk_cache
