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