entry_impl.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/entry_impl.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/backend_impl.h"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/bitmap.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/cache_util.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/histogram_macros.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/sparse_control.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time;
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta;
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks;
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Index for the file used to store the key, if any (files_[kKeyFileIndex]).
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kKeyFileIndex = 3;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class implements FileIOCallback to buffer the callback from a file IO
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// operation from the actual net class.
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SyncCallback: public disk_cache::FileIOCallback {
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SyncCallback(disk_cache::EntryImpl* entry, net::IOBuffer* buffer,
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               net::CompletionCallback* callback )
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : entry_(entry), callback_(callback), buf_(buffer),
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        start_(TimeTicks::Now()) {
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->AddRef();
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry->IncrementIoCount();
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~SyncCallback() {}
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void OnFileIOComplete(int bytes_copied);
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Discard();
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::EntryImpl* entry_;
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::CompletionCallback* callback_;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<net::IOBuffer> buf_;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start_;
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(SyncCallback);
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncCallback::OnFileIOComplete(int bytes_copied) {
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_->DecrementIoCount();
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (callback_) {
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry_->ReportIOTime(disk_cache::EntryImpl::kAsyncIO, start_);
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    callback_->Run(bytes_copied);
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_->Release();
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delete this;
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncCallback::Discard() {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  callback_ = NULL;
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  buf_ = NULL;
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  OnFileIOComplete(0);
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kMaxBufferSize = 1024 * 1024;  // 1 MB.
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This class handles individual memory buffers that store data before it is
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// sent to disk. The buffer can start at any offset, but if we try to write to
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// anywhere in the first 16KB of the file (kMaxBlockSize), we set the offset to
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// zero. The buffer grows up to a size determined by the backend, to keep the
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// total memory used under control.
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass EntryImpl::UserBuffer {
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit UserBuffer(BackendImpl* backend)
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      : backend_(backend->GetWeakPtr()), offset_(0), grow_allowed_(true) {
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_.reserve(kMaxBlockSize);
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ~UserBuffer() {
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (backend_)
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      backend_->BufferDeleted(capacity() - kMaxBlockSize);
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Returns true if we can handle writing |len| bytes to |offset|.
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool PreWrite(int offset, int len);
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Truncates the buffer to |offset| bytes.
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Truncate(int offset);
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Writes |len| bytes from |buf| at the given |offset|.
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Write(int offset, net::IOBuffer* buf, int len);
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Returns true if we can read |len| bytes from |offset|, given that the
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // actual file has |eof| bytes stored. Note that the number of bytes to read
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // may be modified by this method even though it returns false: that means we
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // should do a smaller read from disk.
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool PreRead(int eof, int offset, int* len);
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Read |len| bytes from |buf| at the given |offset|.
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int Read(int offset, net::IOBuffer* buf, int len);
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Prepare this buffer for reuse.
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Reset();
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char* Data() { return buffer_.size() ? &buffer_[0] : NULL; }
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int Size() { return static_cast<int>(buffer_.size()); }
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int Start() { return offset_; }
1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int End() { return offset_ + Size(); }
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int capacity() { return static_cast<int>(buffer_.capacity()); }
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool GrowBuffer(int required, int limit);
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::WeakPtr<BackendImpl> backend_;
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int offset_;
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::vector<char> buffer_;
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool grow_allowed_;
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(UserBuffer);
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::UserBuffer::PreWrite(int offset, int len) {
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, 0);
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(len, 0);
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset + len, 0);
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We don't want to write before our current start.
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (offset < offset_)
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Lets get the common case out of the way.
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (offset + len <= capacity())
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // If we are writing to the first 16K (kMaxBlockSize), we want to keep the
1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // buffer offset_ at 0.
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Size() && offset > kMaxBlockSize)
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return GrowBuffer(len, kMaxBufferSize);
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int required = offset - offset_ + len;
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return GrowBuffer(required, kMaxBufferSize * 6 / 5);
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UserBuffer::Truncate(int offset) {
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, 0);
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, offset_);
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  offset -= offset_;
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (Size() >= offset)
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_.resize(offset);
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UserBuffer::Write(int offset, net::IOBuffer* buf, int len) {
1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, 0);
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(len, 0);
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset + len, 0);
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, offset_);
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Size() && offset > kMaxBlockSize)
1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    offset_ = offset;
1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  offset -= offset_;
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (offset > Size())
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_.resize(offset);
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!len)
1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  char* buffer = buf->data();
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int valid_len = Size() - offset;
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int copy_len = std::min(valid_len, len);
1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (copy_len) {
1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    memcpy(&buffer_[offset], buffer, copy_len);
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    len -= copy_len;
1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer += copy_len;
1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!len)
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_.insert(buffer_.end(), buffer, buffer + len);
1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::UserBuffer::PreRead(int eof, int offset, int* len) {
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, 0);
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GT(*len, 0);
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (offset < offset_) {
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We are reading before this buffer.
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (offset >= eof)
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return true;
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // If the read overlaps with the buffer, change its length so that there is
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // no overlap.
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *len = std::min(*len, offset_ - offset);
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    *len = std::min(*len, eof - offset);
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We should read from disk.
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!Size())
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See if we can fulfill the first part of the operation.
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return (offset - offset_ < Size());
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint EntryImpl::UserBuffer::Read(int offset, net::IOBuffer* buf, int len) {
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(offset, 0);
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GT(len, 0);
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(Size() || offset < offset_);
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int clean_bytes = 0;
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (offset < offset_) {
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We don't have a file so lets fill the first part with 0.
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    clean_bytes = std::min(offset_ - offset, len);
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    memset(buf->data(), 0, clean_bytes);
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (len == clean_bytes)
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return len;
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    offset = offset_;
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    len -= clean_bytes;
2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int start = offset - offset_;
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int available = Size() - start;
2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(start, 0);
2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(available, 0);
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  len = std::min(len, available);
2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  memcpy(buf->data() + clean_bytes, &buffer_[start], len);
2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return len + clean_bytes;
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UserBuffer::Reset() {
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!grow_allowed_) {
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (backend_)
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      backend_->BufferDeleted(capacity() - kMaxBlockSize);
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    grow_allowed_ = true;
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    std::vector<char> tmp;
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_.swap(tmp);
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buffer_.reserve(kMaxBlockSize);
2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  offset_ = 0;
2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_.clear();
2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::UserBuffer::GrowBuffer(int required, int limit) {
2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GE(required, 0);
2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int current_size = capacity();
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (required <= current_size)
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (required > limit)
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!backend_)
2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int to_add = std::max(required - current_size, kMaxBlockSize * 4);
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  to_add = std::max(current_size, to_add);
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  required = std::min(current_size + to_add, limit);
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  grow_allowed_ = backend_->IsAllocAllowed(current_size, required);
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!grow_allowed_)
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  buffer_.reserve(required);
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ------------------------------------------------------------------------
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickEntryImpl::EntryImpl(BackendImpl* backend, Addr address, bool read_only)
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : entry_(NULL, Addr(0)), node_(NULL, Addr(0)), read_only_(read_only) {
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.LazyInit(backend->File(address), address);
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  doomed_ = false;
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_ = backend;
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < kNumStreams; i++) {
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    unreported_size_[i] = 0;
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When an entry is deleted from the cache, we clean up all the data associated
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// with it for two reasons: to simplify the reuse of the block (we know that any
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// unused block is filled with zeros), and to simplify the handling of write /
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// read partial information from an entry (don't have to worry about returning
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// data related to a previous cache entry because the range was not fully
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// written before).
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEntryImpl::~EntryImpl() {
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Log("~EntryImpl in");
2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  backend_->OnEntryDestroyBegin(entry_.address());
2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Save the sparse info to disk before deleting this entry.
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  sparse_.reset();
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (doomed_) {
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DeleteEntryData(true);
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool ret = true;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int index = 0; index < kNumStreams; index++) {
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (user_buffers_[index].get()) {
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        if (!(ret = Flush(index, 0)))
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          LOG(ERROR) << "Failed to save user data";
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (unreported_size_[index]) {
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        backend_->ModifyStorageSize(
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            entry_.Data()->data_size[index] - unreported_size_[index],
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            entry_.Data()->data_size[index]);
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!ret) {
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // There was a failure writing the actual data. Mark the entry as dirty.
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int current_id = backend_->GetCurrentEntryId();
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      node_.Data()->dirty = current_id == 1 ? -1 : current_id - 1;
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      node_.Store();
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else if (node_.HasData() && node_.Data()->dirty) {
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      node_.Data()->dirty = 0;
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      node_.Store();
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("~EntryImpl out 0x%p", reinterpret_cast<void*>(this));
3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  backend_->OnEntryDestroyEnd();
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::Doom() {
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->DoomEntryImpl(this);
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::Close() {
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->CloseEntryImpl(this);
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string EntryImpl::GetKey() const {
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_);
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (entry->Data()->key_len <= kMaxInternalKeyLength)
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return std::string(entry->Data()->key);
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We keep a copy of the key so that we can always return it, even if the
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // backend is disabled.
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!key_.empty())
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return key_;
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry->Data()->long_key);
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(address.is_initialized());
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t offset = 0;
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (address.is_block_file())
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    offset = address.start_block() * address.BlockSize() + kBlockHeaderSize;
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  COMPILE_ASSERT(kNumStreams == kKeyFileIndex, invalid_key_index);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  File* key_file = const_cast<EntryImpl*>(this)->GetBackingFile(address,
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                                kKeyFileIndex);
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!key_file ||
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !key_file->Read(WriteInto(&key_, entry->Data()->key_len + 1),
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      entry->Data()->key_len + 1, offset))
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    key_.clear();
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return key_;
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime EntryImpl::GetLastUsed() const {
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_);
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return Time::FromInternalValue(node->Data()->last_used);
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime EntryImpl::GetLastModified() const {
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_);
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return Time::FromInternalValue(node->Data()->last_modified);
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint32 EntryImpl::GetDataSize(int index) const {
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (index < 0 || index >= kNumStreams)
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_);
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return entry->Data()->data_size[index];
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint EntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        net::CompletionCallback* callback) {
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!callback)
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ReadDataImpl(index, offset, buf, buf_len, callback);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(node_.Data()->dirty || read_only_);
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index < 0 || index >= kNumStreams)
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_INVALID_ARGUMENT;
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int entry_size = entry_.Data()->data_size[index];
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (offset >= entry_size || offset < 0 || !buf_len)
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (buf_len < 0)
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_INVALID_ARGUMENT;
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->ReadData(this, index, offset, buf, buf_len,
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         callback);
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len,
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         CompletionCallback* callback, bool truncate) {
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!callback)
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WriteDataImpl(index, offset, buf, buf_len, callback, truncate);
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(node_.Data()->dirty || read_only_);
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (index < 0 || index >= kNumStreams)
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_INVALID_ARGUMENT;
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (offset < 0 || buf_len < 0)
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::ERR_INVALID_ARGUMENT;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->WriteData(this, index, offset, buf, buf_len,
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          truncate, callback);
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              net::CompletionCallback* callback) {
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!callback)
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ReadSparseDataImpl(offset, buf, buf_len, callback);
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->ReadSparseData(this, offset, buf, buf_len,
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               callback);
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               net::CompletionCallback* callback) {
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!callback)
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WriteSparseDataImpl(offset, buf, buf_len, callback);
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->WriteSparseData(this, offset, buf, buf_len,
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                callback);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 CompletionCallback* callback) {
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->GetAvailableRange(this, offset, len, start,
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                  callback);
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool EntryImpl::CouldBeSparse() const {
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (sparse_.get())
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<SparseControl> sparse;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  sparse.reset(new SparseControl(const_cast<EntryImpl*>(this)));
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sparse->CouldBeSparse();
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EntryImpl::CancelSparseIO() {
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->CancelSparseIO(this);
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::ReadyForSparseIO(net::CompletionCallback* callback) {
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!sparse_.get())
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return net::OK;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->background_queue()->ReadyForSparseIO(this, callback);
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return net::ERR_IO_PENDING;
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ------------------------------------------------------------------------
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EntryImpl::DoomImpl() {
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (doomed_)
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetPointerForInvalidEntry(backend_->GetCurrentEntryId());
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->InternalDoomEntry(this);
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf,
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            int buf_len, CompletionCallback* callback) {
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(node_.Data()->dirty || read_only_);
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (index < 0 || index >= kNumStreams)
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_INVALID_ARGUMENT;
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int entry_size = entry_.Data()->data_size[index];
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (offset >= entry_size || offset < 0 || !buf_len)
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buf_len < 0)
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_INVALID_ARGUMENT;
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (offset + buf_len > entry_size)
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    buf_len = entry_size - offset;
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UpdateRank(false);
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->OnEvent(Stats::READ_DATA);
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->OnRead(buf_len);
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We need the current size in disk.
5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int eof = entry_size - unreported_size_[index];
5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (user_buffers_[index].get() &&
5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_buffers_[index]->PreRead(eof, offset, &buf_len)) {
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Complete the operation locally.
5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    buf_len = user_buffers_[index]->Read(offset, buf, buf_len);
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportIOTime(kRead, start);
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return buf_len;
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->data_addr[index]);
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(address.is_initialized());
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!address.is_initialized())
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  File* file = GetBackingFile(address, index);
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file)
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t file_offset = offset;
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (address.is_block_file()) {
5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_LE(offset + buf_len, kMaxBlockSize);
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    file_offset += address.start_block() * address.BlockSize() +
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   kBlockHeaderSize;
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SyncCallback* io_callback = NULL;
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (callback)
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    io_callback = new SyncCallback(this, buf, callback);
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool completed;
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file->Read(buf->data(), buf_len, file_offset, io_callback, &completed)) {
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (io_callback)
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      io_callback->Discard();
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (io_callback && completed)
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    io_callback->Discard();
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReportIOTime(kRead, start);
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (completed || !callback) ? buf_len : net::ERR_IO_PENDING;
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::WriteDataImpl(int index, int offset, net::IOBuffer* buf,
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             int buf_len, CompletionCallback* callback,
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             bool truncate) {
5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(node_.Data()->dirty || read_only_);
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (index < 0 || index >= kNumStreams)
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_INVALID_ARGUMENT;
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (offset < 0 || buf_len < 0)
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_INVALID_ARGUMENT;
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int max_file_size = backend_->MaxFileSize();
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // offset or buf_len could be negative numbers.
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (offset > max_file_size || buf_len > max_file_size ||
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      offset + buf_len > max_file_size) {
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int size = offset + buf_len;
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (size <= max_file_size)
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      size = kint32max;
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    backend_->TooMuchStorageRequested(size);
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Read the size at this point (it may change inside prepare).
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int entry_size = entry_.Data()->data_size[index];
5733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool extending = entry_size < offset + buf_len;
5743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  truncate = truncate && entry_size > offset + buf_len;
5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("To PrepareTarget 0x%x", entry_.address().value());
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!PrepareTarget(index, offset, buf_len, truncate))
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Trace("From PrepareTarget 0x%x", entry_.address().value());
5803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (extending || truncate)
5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UpdateSize(index, entry_size, offset + buf_len);
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UpdateRank(true);
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->OnEvent(Stats::WRITE_DATA);
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  backend_->OnWrite(buf_len);
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (user_buffers_[index].get()) {
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Complete the operation locally.
5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    user_buffers_[index]->Write(offset, buf, buf_len);
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ReportIOTime(kWrite, start);
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return buf_len;
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->data_addr[index]);
596731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (offset + buf_len == 0) {
597731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (truncate) {
598731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      DCHECK(!address.is_initialized());
599731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return 0;
6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
6023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  File* file = GetBackingFile(address, index);
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file)
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t file_offset = offset;
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (address.is_block_file()) {
6093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_LE(offset + buf_len, kMaxBlockSize);
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    file_offset += address.start_block() * address.BlockSize() +
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   kBlockHeaderSize;
6123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else if (truncate || (extending && !buf_len)) {
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!file->SetLength(offset + buf_len))
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return net::ERR_FAILED;
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!buf_len)
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SyncCallback* io_callback = NULL;
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (callback)
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    io_callback = new SyncCallback(this, buf, callback);
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool completed;
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file->Write(buf->data(), buf_len, file_offset, io_callback,
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   &completed)) {
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (io_callback)
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      io_callback->Discard();
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::ERR_FAILED;
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (io_callback && completed)
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    io_callback->Discard();
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReportIOTime(kWrite, start);
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return (completed || !callback) ? buf_len : net::ERR_IO_PENDING;
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::ReadSparseDataImpl(int64 offset, net::IOBuffer* buf, int buf_len,
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  CompletionCallback* callback) {
6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(node_.Data()->dirty || read_only_);
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result = InitSparseData();
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (net::OK != result)
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result = sparse_->StartIO(SparseControl::kReadOperation, offset, buf, buf_len,
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            callback);
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReportIOTime(kSparseRead, start);
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::WriteSparseDataImpl(int64 offset, net::IOBuffer* buf,
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   int buf_len, CompletionCallback* callback) {
6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(node_.Data()->dirty || read_only_);
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result = InitSparseData();
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (net::OK != result)
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TimeTicks start = TimeTicks::Now();
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  result = sparse_->StartIO(SparseControl::kWriteOperation, offset, buf,
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            buf_len, callback);
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ReportIOTime(kSparseWrite, start);
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::GetAvailableRangeImpl(int64 offset, int len, int64* start) {
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int result = InitSparseData();
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (net::OK != result)
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result;
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return sparse_->GetAvailableRange(offset, len, start);
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EntryImpl::CancelSparseIOImpl() {
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!sparse_.get())
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  sparse_->CancelIO();
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint EntryImpl::ReadyForSparseIOImpl(CompletionCallback* callback) {
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(sparse_.get());
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return sparse_->ReadyToUse(callback);
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint32 EntryImpl::GetHash() {
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return entry_.Data()->hash;
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::CreateEntry(Addr node_address, const std::string& key,
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            uint32 hash) {
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("Create entry In");
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EntryStore* entry_store = entry_.Data();
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RankingsNode* node = node_.Data();
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks());
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(node, 0, sizeof(RankingsNode));
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!node_.LazyInit(backend_->File(node_address), node_address))
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_store->rankings_node = node_address.value();
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node->contents = entry_.address().value();
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_store->hash = hash;
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_store->creation_time = Time::Now().ToInternalValue();
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_store->key_len = static_cast<int32>(key.size());
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (entry_store->key_len > kMaxInternalKeyLength) {
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Addr address(0);
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!CreateBlock(entry_store->key_len + 1, &address))
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry_store->long_key = address.value();
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    File* key_file = GetBackingFile(address, kKeyFileIndex);
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    key_ = key;
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    size_t offset = 0;
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (address.is_block_file())
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      offset = address.start_block() * address.BlockSize() + kBlockHeaderSize;
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!key_file || !key_file->Write(key.data(), key.size(), offset)) {
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DeleteData(address, kKeyFileIndex);
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (address.is_separate_file())
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      key_file->SetLength(key.size() + 1);
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memcpy(entry_store->key, key.data(), key.size());
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry_store->key[key.size()] = '\0';
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->ModifyStorageSize(0, static_cast<int32>(key.size()));
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CACHE_UMA(COUNTS, "KeySize", 0, static_cast<int32>(key.size()));
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node->dirty = backend_->GetCurrentEntryId();
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Log("Create Entry ");
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::IsSameEntry(const std::string& key, uint32 hash) {
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (entry_.Data()->hash != hash ||
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      static_cast<size_t>(entry_.Data()->key_len) != key.size())
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string my_key = GetKey();
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return key.compare(my_key) ? false : true;
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::InternalDoom() {
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(node_.HasData());
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!node_.Data()->dirty) {
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    node_.Data()->dirty = backend_->GetCurrentEntryId();
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    node_.Store();
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  doomed_ = true;
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::DeleteEntryData(bool everything) {
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(doomed_ || !everything);
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (GetEntryFlags() & PARENT_ENTRY) {
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We have some child entries that must go away.
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SparseControl::DeleteChildren(this);
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (GetDataSize(0))
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(COUNTS, "DeleteHeader", 0, GetDataSize(0));
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (GetDataSize(1))
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(COUNTS, "DeleteData", 0, GetDataSize(1));
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int index = 0; index < kNumStreams; index++) {
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Addr address(entry_.Data()->data_addr[index]);
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (address.is_initialized()) {
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      backend_->ModifyStorageSize(entry_.Data()->data_size[index] -
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      unreported_size_[index], 0);
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entry_.Data()->data_addr[index] = 0;
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      entry_.Data()->data_size[index] = 0;
7773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      entry_.Store();
7783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DeleteData(address, index);
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!everything)
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Remove all traces of this entry.
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->RemoveEntry(this);
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->long_key);
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeleteData(address, kKeyFileIndex);
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->ModifyStorageSize(entry_.Data()->key_len, 0);
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(node_.buffer(), 0, node_.size());
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(entry_.buffer(), 0, entry_.size());
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Store();
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Store();
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->DeleteBlock(node_.address(), false);
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->DeleteBlock(entry_.address(), false);
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCacheAddr EntryImpl::GetNextAddress() {
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return entry_.Data()->next;
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::SetNextAddress(Addr address) {
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Data()->next = address.value();
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool success = entry_.Store();
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(success);
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::LoadNodeAddress() {
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->rankings_node);
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!node_.LazyInit(backend_->File(address), address))
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return node_.Load();
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::Update() {
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(node_.HasData());
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
8213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (read_only_)
8223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
8233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RankingsNode* rankings = node_.Data();
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!rankings->dirty) {
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rankings->dirty = backend_->GetCurrentEntryId();
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!node_.Store())
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::IsDirty(int32 current_id) {
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(node_.HasData());
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We are checking if the entry is valid or not. If there is a pointer here,
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we should not be checking the entry.
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (node_.Data()->dummy)
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return node_.Data()->dirty && current_id != node_.Data()->dirty;
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::ClearDirtyFlag() {
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Data()->dirty = 0;
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::SetPointerForInvalidEntry(int32 new_id) {
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Data()->dirty = new_id;
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Data()->dummy = 0;
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Store();
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::SanityCheck() {
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!entry_.Data()->rankings_node || !entry_.Data()->key_len)
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr rankings_addr(entry_.Data()->rankings_node);
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!rankings_addr.is_initialized() || rankings_addr.is_separate_file() ||
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rankings_addr.file_type() != RANKINGS)
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr next_addr(entry_.Data()->next);
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (next_addr.is_initialized() &&
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      (next_addr.is_separate_file() || next_addr.file_type() != BLOCK_256))
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::IncrementIoCount() {
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->IncrementIoCount();
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::DecrementIoCount() {
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  backend_->DecrementIoCount();
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::SetTimes(base::Time last_used, base::Time last_modified) {
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Data()->last_used = last_used.ToInternalValue();
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Data()->last_modified = last_modified.ToInternalValue();
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.set_modified();
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid EntryImpl::ReportIOTime(Operation op, const base::TimeTicks& start) {
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int group = backend_->GetSizeGroup();
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (op) {
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case kRead:
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CACHE_UMA(AGE_MS, "ReadTime", group, start);
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case kWrite:
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CACHE_UMA(AGE_MS, "WriteTime", group, start);
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case kSparseRead:
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CACHE_UMA(AGE_MS, "SparseReadTime", 0, start);
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case kSparseWrite:
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CACHE_UMA(AGE_MS, "SparseWriteTime", 0, start);
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case kAsyncIO:
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CACHE_UMA(AGE_MS, "AsyncIOTime", group, start);
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      NOTREACHED();
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::CreateDataBlock(int index, int size) {
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(index >= 0 && index < kNumStreams);
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->data_addr[index]);
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!CreateBlock(size, &address))
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Data()->data_addr[index] = address.value();
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Store();
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::CreateBlock(int size, Addr* address) {
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!address->is_initialized());
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FileType file_type = Addr::RequiredFileType(size);
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (EXTERNAL == file_type) {
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (size > backend_->MaxFileSize())
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!backend_->CreateExternalFile(address))
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int num_blocks = (size + Addr::BlockSizeForFileType(file_type) - 1) /
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                     Addr::BlockSizeForFileType(file_type);
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!backend_->CreateBlock(file_type, num_blocks, address))
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Note that this method may end up modifying a block file so upon return the
9413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// involved block will be free, and could be reused for something else. If there
9423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// is a crash after that point (and maybe before returning to the caller), the
9433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// entry will be left dirty... and at some point it will be discarded; it is
9443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// important that the entry doesn't keep a reference to this address, or we'll
9453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// end up deleting the contents of |address| once again.
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::DeleteData(Addr address, int index) {
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!address.is_initialized())
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (address.is_separate_file()) {
9503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int failure = !DeleteCacheFile(backend_->GetFileName(address));
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CACHE_UMA(COUNTS, "DeleteFailed", 0, failure);
9523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (failure) {
953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(ERROR) << "Failed to delete " <<
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          backend_->GetFileName(address).value() << " from the cache.";
9553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
9563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (files_[index])
9573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      files_[index] = NULL;  // Releases the object.
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    backend_->DeleteBlock(address, true);
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::UpdateRank(bool modified) {
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!doomed_) {
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Everything is handled by the backend.
9663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    backend_->UpdateRank(this, modified);
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Time current = Time::Now();
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  node_.Data()->last_used = current.ToInternalValue();
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (modified)
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    node_.Data()->last_modified = current.ToInternalValue();
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile* EntryImpl::GetBackingFile(Addr address, int index) {
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  File* file;
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (address.is_separate_file())
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    file = GetExternalFile(address, index);
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    file = backend_->File(address);
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return file;
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile* EntryImpl::GetExternalFile(Addr address, int index) {
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(index >= 0 && index <= kKeyFileIndex);
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!files_[index].get()) {
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // For a key file, use mixed mode IO.
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_refptr<File> file(new File(kKeyFileIndex == index));
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (file->Init(backend_->GetFileName(address)))
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      files_[index].swap(file);
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return files_[index].get();
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// We keep a memory buffer for everything that ends up stored on a block file
9983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// (because we don't know yet the final data size), and for some of the data
9993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// that end up on external files. This function will initialize that memory
10003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// buffer and / or the files needed to store the data.
10013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick//
10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// In general, a buffer may overlap data already stored on disk, and in that
10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// case, the contents of the buffer are the most accurate. It may also extend
10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the file, but we don't want to read from disk just to keep the buffer up to
10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// date. This means that as soon as there is a chance to get confused about what
10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// is the most recent version of some part of a file, we'll flush the buffer and
10073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// reuse it for the new data. Keep in mind that the normal use pattern is quite
10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// simple (write sequentially from the beginning), so we optimize for handling
10093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// that case.
1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::PrepareTarget(int index, int offset, int buf_len,
1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              bool truncate) {
10123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (truncate)
10133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return HandleTruncation(index, offset, buf_len);
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1015731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!offset && !buf_len)
1016731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return true;
1017731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
10183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Addr address(entry_.Data()->data_addr[index]);
10193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (address.is_initialized()) {
10203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (address.is_block_file() && !MoveToLocalBuffer(index))
10213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!user_buffers_[index].get() && offset < kMaxBlockSize) {
10243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // We are about to create a buffer for the first 16KB, make sure that we
10253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // preserve existing data.
10263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (!CopyToLocalBuffer(index))
10273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return false;
10283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
10293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!user_buffers_[index].get())
10323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    user_buffers_[index].reset(new UserBuffer(backend_));
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return PrepareBuffer(index, offset, buf_len);
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We get to this function with some data already stored. If there is a
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// truncation that results on data stored internally, we'll explicitly
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// handle the case here.
10403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::HandleTruncation(int index, int offset, int buf_len) {
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->data_addr[index]);
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int current_size = entry_.Data()->data_size[index];
10443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int new_size = offset + buf_len;
10453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!new_size) {
10473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // This is by far the most common scenario.
10483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    backend_->ModifyStorageSize(current_size - unreported_size_[index], 0);
10493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    entry_.Data()->data_addr[index] = 0;
10503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    entry_.Data()->data_size[index] = 0;
10513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    unreported_size_[index] = 0;
10523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    entry_.Store();
10533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DeleteData(address, index);
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    user_buffers_[index].reset();
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We never postpone truncating a file, if there is one, but we may postpone
10603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // telling the backend about the size reduction.
10613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (user_buffers_[index].get()) {
10623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_GE(current_size, user_buffers_[index]->Start());
10633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!address.is_initialized()) {
10643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // There is no overlap between the buffer and disk.
10653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (new_size > user_buffers_[index]->Start()) {
10663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        // Just truncate our buffer.
10673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        DCHECK_LT(new_size, user_buffers_[index]->End());
10683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        user_buffers_[index]->Truncate(new_size);
10693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return true;
10703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Just discard our buffer.
10733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_buffers_[index]->Reset();
10743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return PrepareBuffer(index, offset, buf_len);
10753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // There is some overlap or we need to extend the file before the
10783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // truncation.
10793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (offset > user_buffers_[index]->Start())
10803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_buffers_[index]->Truncate(new_size);
10813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UpdateSize(index, current_size, new_size);
10823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!Flush(index, 0))
10833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
10843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    user_buffers_[index].reset();
10853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We have data somewhere, and it is not in a buffer.
10883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!user_buffers_[index].get());
10893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(address.is_initialized());
10903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (new_size > kMaxBlockSize)
10923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;  // Let the operation go directly to disk.
10933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
10943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ImportSeparateFile(index, offset + buf_len);
1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::CopyToLocalBuffer(int index) {
1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->data_addr[index]);
1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!user_buffers_[index].get());
1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(address.is_initialized());
11013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int len = std::min(entry_.Data()->data_size[index], kMaxBlockSize);
11033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  user_buffers_[index].reset(new UserBuffer(backend_));
11043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  user_buffers_[index]->Write(len, NULL, 0);
1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  File* file = GetBackingFile(address, index);
11073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int offset = 0;
1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (address.is_block_file())
1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    offset = address.start_block() * address.BlockSize() + kBlockHeaderSize;
1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!file ||
11133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      !file->Read(user_buffers_[index]->Data(), len, offset, NULL, NULL)) {
11143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    user_buffers_[index].reset();
11153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
11163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
11173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
11183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::MoveToLocalBuffer(int index) {
11213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!CopyToLocalBuffer(index))
1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Addr address(entry_.Data()->data_addr[index]);
1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Data()->data_addr[index] = 0;
1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Store();
11273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DeleteData(address, index);
1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If we lose this entry we'll see it as zero sized.
11303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int len = entry_.Data()->data_size[index];
11313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  backend_->ModifyStorageSize(len - unreported_size_[index], 0);
11323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  unreported_size_[index] = len;
1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::ImportSeparateFile(int index, int new_size) {
11373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (entry_.Data()->data_size[index] > new_size)
11383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UpdateSize(index, entry_.Data()->data_size[index], new_size);
11393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return MoveToLocalBuffer(index);
11413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
11423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
11433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::PrepareBuffer(int index, int offset, int buf_len) {
11443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(user_buffers_[index].get());
11453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (offset > user_buffers_[index]->End()) {
11463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // We are about to extend the buffer (with zeros), so make sure that we are
11473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // not overwriting anything.
11483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    Addr address(entry_.Data()->data_addr[index]);
11493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (address.is_initialized() && address.is_separate_file()) {
11503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int eof = entry_.Data()->data_size[index];
11513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (eof > user_buffers_[index]->Start() && !Flush(index, 0))
11523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return false;
11533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!user_buffers_[index]->PreWrite(offset, buf_len)) {
11573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!Flush(index, offset + buf_len))
11583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Lets try again.
11613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!user_buffers_[index]->PreWrite(offset, buf_len)) {
11623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // We cannot complete the operation with a buffer.
11633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!user_buffers_[index]->Size());
11643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!user_buffers_[index]->Start());
11653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      user_buffers_[index].reset();
11663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
11673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::Flush(int index, int min_len) {
1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Addr address(entry_.Data()->data_addr[index]);
1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(user_buffers_[index].get());
11743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(!address.is_initialized() || address.is_separate_file());
1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int size = std::max(entry_.Data()->data_size[index], min_len);
1177731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (size && !address.is_initialized() && !CreateDataBlock(index, size))
1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!entry_.Data()->data_size[index]) {
11813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(!user_buffers_[index]->Size());
11823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
11833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
11843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  address.set_value(entry_.Data()->data_addr[index]);
1186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int len = user_buffers_[index]->Size();
11883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int offset = user_buffers_[index]->Start();
11893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!len && !offset)
11903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return true;
1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (address.is_block_file()) {
11933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK_EQ(len, entry_.Data()->data_size[index]);
11943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(!offset);
11953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    offset = address.start_block() * address.BlockSize() + kBlockHeaderSize;
11963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  File* file = GetBackingFile(address, index);
1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!file)
1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!file->Write(user_buffers_[index]->Data(), len, offset, NULL, NULL))
12033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;
12043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  user_buffers_[index]->Reset();
1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UpdateSize(int index, int old_size, int new_size) {
12103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (entry_.Data()->data_size[index] == new_size)
12113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
12123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
12133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  unreported_size_[index] += new_size - old_size;
12143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  entry_.Data()->data_size[index] = new_size;
12153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  entry_.set_modified();
12163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
12173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint EntryImpl::InitSparseData() {
1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (sparse_.get())
1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return net::OK;
1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Use a local variable so that sparse_ never goes from 'valid' to NULL.
1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<SparseControl> sparse(new SparseControl(this));
1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int result = sparse->Init();
1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (net::OK == result)
1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sparse_.swap(sparse);
1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::SetEntryFlags(uint32 flags) {
1232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.Data()->flags |= flags;
1233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  entry_.set_modified();
1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint32 EntryImpl::GetEntryFlags() {
1237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return entry_.Data()->flags;
1238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::GetData(int index, char** buffer, Addr* address) {
12413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (user_buffers_[index].get() && user_buffers_[index]->Size() &&
12423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      !user_buffers_[index]->Start()) {
1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The data is already in memory, just copy it and we're done.
1244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int data_len = entry_.Data()->data_size[index];
12453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (data_len <= user_buffers_[index]->Size()) {
12463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(!user_buffers_[index]->Start());
12473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      *buffer = new char[data_len];
12483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      memcpy(*buffer, user_buffers_[index]->Data(), data_len);
12493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return;
12503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
1251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Bad news: we'd have to read the info from disk so instead we'll just tell
1254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the caller where to read from.
1255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *buffer = NULL;
1256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  address->set_value(entry_.Data()->data_addr[index]);
1257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (address->is_initialized()) {
1258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Prevent us from deleting the block from the backing store.
1259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    backend_->ModifyStorageSize(entry_.Data()->data_size[index] -
1260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    unreported_size_[index], 0);
1261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry_.Data()->data_addr[index] = 0;
1262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    entry_.Data()->data_size[index] = 0;
1263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::Log(const char* msg) {
1267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int dirty = 0;
1268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (node_.HasData()) {
1269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    dirty = node_.Data()->dirty;
1270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this),
1273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        entry_.address().value(), node_.address().value());
1274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("  data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0],
1276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        entry_.Data()->data_addr[1], entry_.Data()->long_key);
1277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Trace("  doomed: %d 0x%x", doomed_, dirty);
1279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace disk_cache
1282