1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/disk_cache/hash.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/histogram_macros.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/disk_cache/net_log_parameters.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/sparse_control.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time; 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeTicks; 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Index for the file used to store the key, if any (files_[kKeyFileIndex]). 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kKeyFileIndex = 3; 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class implements FileIOCallback to buffer the callback from a file IO 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// operation from the actual net class. 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass SyncCallback: public disk_cache::FileIOCallback { 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // |end_event_type| is the event type to log on completion. Logs nothing on 343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // discard, or when the NetLog is not set to log all events. 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SyncCallback(disk_cache::EntryImpl* entry, net::IOBuffer* buffer, 363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net::CompletionCallback* callback, 373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net::NetLog::EventType end_event_type) 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : entry_(entry), callback_(callback), buf_(buffer), 393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen start_(TimeTicks::Now()), end_event_type_(end_event_type) { 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry->AddRef(); 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry->IncrementIoCount(); 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~SyncCallback() {} 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnFileIOComplete(int bytes_copied); 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void Discard(); 473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott disk_cache::EntryImpl* entry_; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::CompletionCallback* callback_; 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<net::IOBuffer> buf_; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeTicks start_; 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const net::NetLog::EventType end_event_type_; 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(SyncCallback); 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncCallback::OnFileIOComplete(int bytes_copied) { 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->DecrementIoCount(); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (callback_) { 613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (entry_->net_log().IsLoggingAllEvents()) { 623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_->net_log().EndEvent( 633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen end_event_type_, 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr( 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new disk_cache::ReadWriteCompleteParameters(bytes_copied))); 663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->ReportIOTime(disk_cache::EntryImpl::kAsyncIO, start_); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_->Run(bytes_copied); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_->Release(); 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete this; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SyncCallback::Discard() { 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_ = NULL; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf_ = NULL; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnFileIOComplete(0); 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int kMaxBufferSize = 1024 * 1024; // 1 MB. 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This class handles individual memory buffers that store data before it is 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// sent to disk. The buffer can start at any offset, but if we try to write to 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// anywhere in the first 16KB of the file (kMaxBlockSize), we set the offset to 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// zero. The buffer grows up to a size determined by the backend, to keep the 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// total memory used under control. 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass EntryImpl::UserBuffer { 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public: 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick explicit UserBuffer(BackendImpl* backend) 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick : backend_(backend->GetWeakPtr()), offset_(0), grow_allowed_(true) { 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.reserve(kMaxBlockSize); 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ~UserBuffer() { 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (backend_) 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick backend_->BufferDeleted(capacity() - kMaxBlockSize); 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Returns true if we can handle writing |len| bytes to |offset|. 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool PreWrite(int offset, int len); 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Truncates the buffer to |offset| bytes. 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void Truncate(int offset); 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Writes |len| bytes from |buf| at the given |offset|. 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void Write(int offset, net::IOBuffer* buf, int len); 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Returns true if we can read |len| bytes from |offset|, given that the 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // actual file has |eof| bytes stored. Note that the number of bytes to read 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // may be modified by this method even though it returns false: that means we 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // should do a smaller read from disk. 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool PreRead(int eof, int offset, int* len); 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Read |len| bytes from |buf| at the given |offset|. 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int Read(int offset, net::IOBuffer* buf, int len); 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Prepare this buffer for reuse. 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void Reset(); 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick char* Data() { return buffer_.size() ? &buffer_[0] : NULL; } 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int Size() { return static_cast<int>(buffer_.size()); } 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int Start() { return offset_; } 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int End() { return offset_ + Size(); } 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private: 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int capacity() { return static_cast<int>(buffer_.capacity()); } 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool GrowBuffer(int required, int limit); 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::WeakPtr<BackendImpl> backend_; 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int offset_; 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<char> buffer_; 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool grow_allowed_; 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DISALLOW_COPY_AND_ASSIGN(UserBuffer); 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::UserBuffer::PreWrite(int offset, int len) { 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, 0); 1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(len, 0); 1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset + len, 0); 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We don't want to write before our current start. 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset < offset_) 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Lets get the common case out of the way. 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset + len <= capacity()) 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If we are writing to the first 16K (kMaxBlockSize), we want to keep the 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // buffer offset_ at 0. 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!Size() && offset > kMaxBlockSize) 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return GrowBuffer(len, kMaxBufferSize); 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int required = offset - offset_ + len; 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return GrowBuffer(required, kMaxBufferSize * 6 / 5); 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UserBuffer::Truncate(int offset) { 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, 0); 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, offset_); 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(3) << "Buffer truncate at " << offset << " current " << offset_; 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset -= offset_; 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (Size() >= offset) 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.resize(offset); 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UserBuffer::Write(int offset, net::IOBuffer* buf, int len) { 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, 0); 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(len, 0); 1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset + len, 0); 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, offset_); 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(3) << "Buffer write at " << offset << " current " << offset_; 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!Size() && offset > kMaxBlockSize) 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset_ = offset; 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset -= offset_; 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset > Size()) 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.resize(offset); 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!len) 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick char* buffer = buf->data(); 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int valid_len = Size() - offset; 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int copy_len = std::min(valid_len, len); 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (copy_len) { 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick memcpy(&buffer_[offset], buffer, copy_len); 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick len -= copy_len; 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer += copy_len; 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!len) 1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.insert(buffer_.end(), buffer, buffer + len); 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::UserBuffer::PreRead(int eof, int offset, int* len) { 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, 0); 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GT(*len, 0); 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset < offset_) { 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are reading before this buffer. 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset >= eof) 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If the read overlaps with the buffer, change its length so that there is 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // no overlap. 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *len = std::min(*len, offset_ - offset); 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *len = std::min(*len, eof - offset); 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We should read from disk. 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!Size()) 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // See if we can fulfill the first part of the operation. 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return (offset - offset_ < Size()); 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint EntryImpl::UserBuffer::Read(int offset, net::IOBuffer* buf, int len) { 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(offset, 0); 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GT(len, 0); 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(Size() || offset < offset_); 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int clean_bytes = 0; 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset < offset_) { 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We don't have a file so lets fill the first part with 0. 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick clean_bytes = std::min(offset_ - offset, len); 2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick memset(buf->data(), 0, clean_bytes); 2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (len == clean_bytes) 2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return len; 2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset = offset_; 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick len -= clean_bytes; 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int start = offset - offset_; 2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int available = Size() - start; 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(start, 0); 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(available, 0); 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick len = std::min(len, available); 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick memcpy(buf->data() + clean_bytes, &buffer_[start], len); 2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return len + clean_bytes; 2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UserBuffer::Reset() { 2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!grow_allowed_) { 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (backend_) 2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick backend_->BufferDeleted(capacity() - kMaxBlockSize); 2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick grow_allowed_ = true; 2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<char> tmp; 2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.swap(tmp); 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.reserve(kMaxBlockSize); 2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset_ = 0; 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.clear(); 2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::UserBuffer::GrowBuffer(int required, int limit) { 2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(required, 0); 2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int current_size = capacity(); 2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (required <= current_size) 2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (required > limit) 2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!backend_) 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int to_add = std::max(required - current_size, kMaxBlockSize * 4); 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick to_add = std::max(current_size, to_add); 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick required = std::min(current_size + to_add, limit); 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick grow_allowed_ = backend_->IsAllocAllowed(current_size, required); 2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!grow_allowed_) 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(3) << "Buffer grow to " << required; 287513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer_.reserve(required); 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// ------------------------------------------------------------------------ 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickEntryImpl::EntryImpl(BackendImpl* backend, Addr address, bool read_only) 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : entry_(NULL, Addr(0)), node_(NULL, Addr(0)), backend_(backend), 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen doomed_(false), read_only_(read_only), dirty_(false) { 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.LazyInit(backend->File(address), address); 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < kNumStreams; i++) { 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unreported_size_[i] = 0; 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::DoomImpl() { 3043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (doomed_) 3053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return; 30621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SetPointerForInvalidEntry(backend_->GetCurrentEntryId()); 3083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->InternalDoomEntry(this); 3093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::ReadDataImpl(int index, int offset, net::IOBuffer* buf, 3123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int buf_len, CompletionCallback* callback) { 3133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (net_log_.IsLoggingAllEvents()) { 3143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log_.BeginEvent( 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_READ_DATA, 3163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen make_scoped_refptr( 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new ReadWriteDataParameters(index, offset, buf_len, false))); 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int result = InternalReadData(index, offset, buf, buf_len, callback); 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (result != net::ERR_IO_PENDING && net_log_.IsLoggingAllEvents()) { 3233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log_.EndEvent( 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_READ_DATA, 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new ReadWriteCompleteParameters(result))); 3263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 3273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::WriteDataImpl(int index, int offset, net::IOBuffer* buf, 3313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int buf_len, CompletionCallback* callback, 3323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool truncate) { 3333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (net_log_.IsLoggingAllEvents()) { 3343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log_.BeginEvent( 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_WRITE_DATA, 3363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen make_scoped_refptr( 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new ReadWriteDataParameters(index, offset, buf_len, truncate))); 3383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int result = InternalWriteData(index, offset, buf, buf_len, callback, 3413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen truncate); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (result != net::ERR_IO_PENDING && net_log_.IsLoggingAllEvents()) { 3443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log_.EndEvent( 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_WRITE_DATA, 346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen make_scoped_refptr(new ReadWriteCompleteParameters(result))); 3473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 3483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 3493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::ReadSparseDataImpl(int64 offset, net::IOBuffer* buf, int buf_len, 3523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CompletionCallback* callback) { 3533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.Data()->dirty || read_only_); 3543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int result = InitSparseData(); 3553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (net::OK != result) 3563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TimeTicks start = TimeTicks::Now(); 3593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen result = sparse_->StartIO(SparseControl::kReadOperation, offset, buf, buf_len, 3603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen callback); 3613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ReportIOTime(kSparseRead, start); 3623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::WriteSparseDataImpl(int64 offset, net::IOBuffer* buf, 3663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int buf_len, CompletionCallback* callback) { 3673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.Data()->dirty || read_only_); 3683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int result = InitSparseData(); 3693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (net::OK != result) 3703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TimeTicks start = TimeTicks::Now(); 3733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen result = sparse_->StartIO(SparseControl::kWriteOperation, offset, buf, 3743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen buf_len, callback); 3753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ReportIOTime(kSparseWrite, start); 3763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::GetAvailableRangeImpl(int64 offset, int len, int64* start) { 3803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int result = InitSparseData(); 3813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (net::OK != result) 3823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return result; 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return sparse_->GetAvailableRange(offset, len, start); 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::CancelSparseIOImpl() { 3883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!sparse_.get()) 3893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return; 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sparse_->CancelIO(); 3923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::ReadyForSparseIOImpl(CompletionCallback* callback) { 3953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(sparse_.get()); 3963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return sparse_->ReadyToUse(callback); 3973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenuint32 EntryImpl::GetHash() { 4003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return entry_.Data()->hash; 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool EntryImpl::CreateEntry(Addr node_address, const std::string& key, 4043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen uint32 hash) { 4053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Trace("Create entry In"); 4063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen EntryStore* entry_store = entry_.Data(); 4073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen RankingsNode* node = node_.Data(); 4083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen memset(entry_store, 0, sizeof(EntryStore) * entry_.address().num_blocks()); 4093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen memset(node, 0, sizeof(RankingsNode)); 4103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!node_.LazyInit(backend_->File(node_address), node_address)) 4113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_store->rankings_node = node_address.value(); 4143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node->contents = entry_.address().value(); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_store->hash = hash; 4173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_store->creation_time = Time::Now().ToInternalValue(); 4183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_store->key_len = static_cast<int32>(key.size()); 4193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (entry_store->key_len > kMaxInternalKeyLength) { 4203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(0); 4213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!CreateBlock(entry_store->key_len + 1, &address)) 4223f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_store->long_key = address.value(); 4253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen File* key_file = GetBackingFile(address, kKeyFileIndex); 4263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen key_ = key; 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen size_t offset = 0; 4293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (address.is_block_file()) 4303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!key_file || !key_file->Write(key.data(), key.size(), offset)) { 4333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DeleteData(address, kKeyFileIndex); 4343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 4353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 4363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 4373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (address.is_separate_file()) 4383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen key_file->SetLength(key.size() + 1); 4393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } else { 4403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen memcpy(entry_store->key, key.data(), key.size()); 4413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_store->key[key.size()] = '\0'; 4423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 4433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->ModifyStorageSize(0, static_cast<int32>(key.size())); 4443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(COUNTS, "KeySize", 0, static_cast<int32>(key.size())); 4453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node->dirty = backend_->GetCurrentEntryId(); 4463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Log("Create Entry "); 4473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool EntryImpl::IsSameEntry(const std::string& key, uint32 hash) { 4513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (entry_.Data()->hash != hash || 4523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static_cast<size_t>(entry_.Data()->key_len) != key.size()) 4533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen std::string my_key = GetKey(); 4563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return key.compare(my_key) ? false : true; 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::InternalDoom() { 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.AddEvent(net::NetLog::TYPE_ENTRY_DOOM, NULL); 4613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.HasData()); 4623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!node_.Data()->dirty) { 4633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->dirty = backend_->GetCurrentEntryId(); 4643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Store(); 4653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 4663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen doomed_ = true; 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::DeleteEntryData(bool everything) { 4703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(doomed_ || !everything); 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (GetEntryFlags() & PARENT_ENTRY) { 4733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // We have some child entries that must go away. 4743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SparseControl::DeleteChildren(this); 4753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (GetDataSize(0)) 4783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(COUNTS, "DeleteHeader", 0, GetDataSize(0)); 4793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (GetDataSize(1)) 4803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(COUNTS, "DeleteData", 0, GetDataSize(1)); 4813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen for (int index = 0; index < kNumStreams; index++) { 4823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(entry_.Data()->data_addr[index]); 4833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (address.is_initialized()) { 4843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->ModifyStorageSize(entry_.Data()->data_size[index] - 4853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen unreported_size_[index], 0); 4863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_.Data()->data_addr[index] = 0; 4873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_.Data()->data_size[index] = 0; 4883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_.Store(); 4893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DeleteData(address, index); 4903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 4913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!everything) 4943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return; 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Remove all traces of this entry. 4973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->RemoveEntry(this); 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 499ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen // Note that at this point node_ and entry_ are just two blocks of data, and 500ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen // even if they reference each other, nobody should be referencing them. 501ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 5023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(entry_.Data()->long_key); 5033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DeleteData(address, kKeyFileIndex); 5043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->ModifyStorageSize(entry_.Data()->key_len, 0); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 506ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen backend_->DeleteBlock(entry_.address(), true); 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 508ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen if (!LeaveRankingsBehind()) 509ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen backend_->DeleteBlock(node_.address(), true); 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5123f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenCacheAddr EntryImpl::GetNextAddress() { 5133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return entry_.Data()->next; 5143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::SetNextAddress(Addr address) { 51772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_NE(address.value(), entry_.address().value()); 5183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_.Data()->next = address.value(); 5193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool success = entry_.Store(); 5203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(success); 5213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool EntryImpl::LoadNodeAddress() { 5243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(entry_.Data()->rankings_node); 5253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!node_.LazyInit(backend_->File(address), address)) 5263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 5273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return node_.Load(); 5283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool EntryImpl::Update() { 5313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.HasData()); 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (read_only_) 5343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen RankingsNode* rankings = node_.Data(); 5373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!rankings->dirty) { 5383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen rankings->dirty = backend_->GetCurrentEntryId(); 5393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!node_.Store()) 5403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 5423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 5433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid EntryImpl::SetDirtyFlag(int32 current_id) { 5463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.HasData()); 5473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // We are checking if the entry is valid or not. If there is a pointer here, 5483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // we should not be checking the entry. 5493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (node_.Data()->dummy) 550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dirty_ = true; 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (node_.Data()->dirty && current_id != node_.Data()->dirty) 553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dirty_ = true; 554ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 555ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen if (!current_id) 556ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen dirty_ = true; 5573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::SetPointerForInvalidEntry(int32 new_id) { 5603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->dirty = new_id; 5613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->dummy = 0; 5623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Store(); 5633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 565ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsenbool EntryImpl::LeaveRankingsBehind() { 566ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen return !node_.Data()->contents; 567ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen} 568ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 569ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen// This only includes checks that relate to the first block of the entry (the 570ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen// first 256 bytes), and values that should be set from the entry creation. 571ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen// Basically, even if there is something wrong with this entry, we want to see 572ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen// if it is possible to load the rankings node and delete them together. 5733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool EntryImpl::SanityCheck() { 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EntryStore* stored = entry_.Data(); 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!stored->rankings_node || stored->key_len <= 0) 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (stored->reuse_count < 0 || stored->refetch_count < 0) 5793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 581ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Addr rankings_addr(stored->rankings_node); 5823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!rankings_addr.is_initialized() || rankings_addr.is_separate_file() || 583ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen rankings_addr.file_type() != RANKINGS || rankings_addr.num_blocks() != 1) 5843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 586ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Addr next_addr(stored->next); 5873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (next_addr.is_initialized() && 5883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen (next_addr.is_separate_file() || next_addr.file_type() != BLOCK_256)) 5893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return false; 5903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!rankings_addr.SanityCheck() || !next_addr.SanityCheck()) 592ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 593ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (stored->state > ENTRY_DOOMED || stored->state < ENTRY_NORMAL) 595ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 596ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Addr key_addr(stored->long_key); 598ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if ((stored->key_len <= kMaxInternalKeyLength && key_addr.is_initialized()) || 599ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen (stored->key_len > kMaxInternalKeyLength && !key_addr.is_initialized())) 600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 602ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!key_addr.SanityCheck()) 603ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 604ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 605ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if (key_addr.is_initialized() && 606ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen ((stored->key_len <= kMaxBlockSize && key_addr.is_separate_file()) || 607ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen (stored->key_len > kMaxBlockSize && key_addr.is_block_file()))) 608ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen return false; 609ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 610ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen int num_blocks = NumBlocksForEntry(stored->key_len); 611ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if (entry_.address().num_blocks() != num_blocks) 612ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen return false; 613ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 614ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen return true; 615ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen} 616ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 617ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsenbool EntryImpl::DataSanityCheck() { 618ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen EntryStore* stored = entry_.Data(); 619ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen Addr key_addr(stored->long_key); 620ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 621ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen // The key must be NULL terminated. 622ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if (!key_addr.is_initialized() && stored->key[stored->key_len]) 623ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen return false; 624ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (stored->hash != Hash(GetKey())) 626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < kNumStreams; i++) { 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Addr data_addr(stored->data_addr[i]); 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int data_size = stored->data_size[i]; 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (data_size < 0) 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 633ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!data_size && data_addr.is_initialized()) 634ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 635ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!data_addr.SanityCheck()) 636ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 637ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!data_size) 638ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (data_size <= kMaxBlockSize && data_addr.is_separate_file()) 640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (data_size > kMaxBlockSize && data_addr.is_block_file()) 642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 6443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 647ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsenvoid EntryImpl::FixForDelete() { 648ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen EntryStore* stored = entry_.Data(); 649ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen Addr key_addr(stored->long_key); 650ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 651ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen if (!key_addr.is_initialized()) 652ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen stored->key[stored->key_len] = '\0'; 653ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 654ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen for (int i = 0; i < kNumStreams; i++) { 655ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen Addr data_addr(stored->data_addr[i]); 656ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen int data_size = stored->data_size[i]; 657ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen if (data_addr.is_initialized()) { 658ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen if ((data_size <= kMaxBlockSize && data_addr.is_separate_file()) || 659ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen (data_size > kMaxBlockSize && data_addr.is_block_file()) || 660ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen !data_addr.SanityCheck()) { 661ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen // The address is weird so don't attempt to delete it. 662ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen stored->data_addr[i] = 0; 663ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen // In general, trust the stored size as it should be in sync with the 664ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen // total size tracked by the backend. 665ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen } 666ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen } 667ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen if (data_size < 0) 668ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen stored->data_size[i] = 0; 669ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen } 670ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen entry_.Store(); 671ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen} 672ae2796cabb52f6a27c50818b78107d3ebc858e0cKristian Monsen 6733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::IncrementIoCount() { 6743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->IncrementIoCount(); 6753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::DecrementIoCount() { 6783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->DecrementIoCount(); 6793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::SetTimes(base::Time last_used, base::Time last_modified) { 6823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->last_used = last_used.ToInternalValue(); 6833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->last_modified = last_modified.ToInternalValue(); 6843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.set_modified(); 6853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::ReportIOTime(Operation op, const base::TimeTicks& start) { 6883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int group = backend_->GetSizeGroup(); 6893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen switch (op) { 6903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case kRead: 6913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(AGE_MS, "ReadTime", group, start); 6923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 6933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case kWrite: 6943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(AGE_MS, "WriteTime", group, start); 6953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 6963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case kSparseRead: 6973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(AGE_MS, "SparseReadTime", 0, start); 6983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 6993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case kSparseWrite: 7003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(AGE_MS, "SparseWriteTime", 0, start); 7013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 7023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case kAsyncIO: 7033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CACHE_UMA(AGE_MS, "AsyncIOTime", group, start); 7043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 7053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen default: 7063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen NOTREACHED(); 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 7083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::BeginLogging(net::NetLog* net_log, bool created) { 7113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(!net_log_.net_log()); 7123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log_ = net::BoundNetLog::Make( 7133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log, net::NetLog::SOURCE_DISK_CACHE_ENTRY); 7143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net_log_.BeginEvent( 715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_DISK_CACHE_ENTRY_IMPL, 7163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen make_scoped_refptr(new EntryCreationParameters(GetKey(), created))); 7173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenconst net::BoundNetLog& EntryImpl::net_log() const { 7203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net_log_; 7213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 723ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen// static 724ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsenint EntryImpl::NumBlocksForEntry(int key_size) { 725ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen // The longest key that can be stored using one block. 726ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen int key1_len = 727ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen static_cast<int>(sizeof(EntryStore) - offsetof(EntryStore, key)); 728ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 729ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if (key_size < key1_len || key_size > kMaxInternalKeyLength) 730ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen return 1; 731ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 732ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen return ((key_size - key1_len) / 256 + 2); 733ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen} 734ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 735ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen// ------------------------------------------------------------------------ 736ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 7373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::Doom() { 7383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->DoomEntryImpl(this); 7393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::Close() { 7423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->CloseEntryImpl(this); 7433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenstd::string EntryImpl::GetKey() const { 7463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_); 747ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen int key_len = entry->Data()->key_len; 748ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if (key_len <= kMaxInternalKeyLength) 7493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return std::string(entry->Data()->key); 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // We keep a copy of the key so that we can always return it, even if the 7523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // backend is disabled. 7533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!key_.empty()) 7543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return key_; 7553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(entry->Data()->long_key); 7573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(address.is_initialized()); 7583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen size_t offset = 0; 7593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (address.is_block_file()) 7603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen COMPILE_ASSERT(kNumStreams == kKeyFileIndex, invalid_key_index); 7633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen File* key_file = const_cast<EntryImpl*>(this)->GetBackingFile(address, 7643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen kKeyFileIndex); 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 766ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen if (!offset && key_file->GetLength() != static_cast<size_t>(key_len + 1)) 767ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen return std::string(); 768ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen 7693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!key_file || 770ea380985f4dd3c72953f7df161674e1644d6de90Kristian Monsen !key_file->Read(WriteInto(&key_, key_len + 1), key_len + 1, offset)) 7713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen key_.clear(); 7723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return key_; 7733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7753f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenTime EntryImpl::GetLastUsed() const { 7763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_); 7773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return Time::FromInternalValue(node->Data()->last_used); 7783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7803f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenTime EntryImpl::GetLastModified() const { 7813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CacheRankingsBlock* node = const_cast<CacheRankingsBlock*>(&node_); 7823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return Time::FromInternalValue(node->Data()->last_modified); 7833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint32 EntryImpl::GetDataSize(int index) const { 7863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (index < 0 || index >= kNumStreams) 7873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return 0; 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CacheEntryBlock* entry = const_cast<CacheEntryBlock*>(&entry_); 7903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return entry->Data()->data_size[index]; 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, int buf_len, 7943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net::CompletionCallback* callback) { 7953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!callback) 7963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return ReadDataImpl(index, offset, buf, buf_len, callback); 7973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 7983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(node_.Data()->dirty || read_only_); 7993f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (index < 0 || index >= kNumStreams) 8003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int entry_size = entry_.Data()->data_size[index]; 8033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset >= entry_size || offset < 0 || !buf_len) 8043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return 0; 8053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 8063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (buf_len < 0) 8073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 8083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 8093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->ReadData(this, index, offset, buf, buf_len, 8103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen callback); 8113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_IO_PENDING; 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::WriteData(int index, int offset, net::IOBuffer* buf, int buf_len, 8153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CompletionCallback* callback, bool truncate) { 8163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!callback) 8173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return WriteDataImpl(index, offset, buf, buf_len, callback, truncate); 8183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 8193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(node_.Data()->dirty || read_only_); 8203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (index < 0 || index >= kNumStreams) 8213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset < 0 || buf_len < 0) 8243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 8253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 8263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->WriteData(this, index, offset, buf, buf_len, 8273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen truncate, callback); 8283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_IO_PENDING; 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 8323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net::CompletionCallback* callback) { 8333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!callback) 8343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return ReadSparseDataImpl(offset, buf, buf_len, callback); 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->ReadSparseData(this, offset, buf, buf_len, 8373f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen callback); 8383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_IO_PENDING; 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, 8423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen net::CompletionCallback* callback) { 8433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!callback) 8443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return WriteSparseDataImpl(offset, buf, buf_len, callback); 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->WriteSparseData(this, offset, buf, buf_len, 8473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen callback); 8483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_IO_PENDING; 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::GetAvailableRange(int64 offset, int len, int64* start, 8523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen CompletionCallback* callback) { 8533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->GetAvailableRange(this, offset, len, start, 8543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen callback); 8553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_IO_PENDING; 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbool EntryImpl::CouldBeSparse() const { 8593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (sparse_.get()) 8603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return true; 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen scoped_ptr<SparseControl> sparse; 8633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sparse.reset(new SparseControl(const_cast<EntryImpl*>(this))); 8643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return sparse->CouldBeSparse(); 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid EntryImpl::CancelSparseIO() { 8683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->CancelSparseIO(this); 8693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::ReadyForSparseIO(net::CompletionCallback* callback) { 8723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!sparse_.get()) 8733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::OK; 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->background_queue()->ReadyForSparseIO(this, callback); 8763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_IO_PENDING; 8773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// When an entry is deleted from the cache, we clean up all the data associated 8803f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// with it for two reasons: to simplify the reuse of the block (we know that any 8813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// unused block is filled with zeros), and to simplify the handling of write / 8823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// read partial information from an entry (don't have to worry about returning 8833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// data related to a previous cache entry because the range was not fully 8843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// written before). 8853f50c38dc070f4bb515c1b64450dae14f316474eKristian MonsenEntryImpl::~EntryImpl() { 8863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Log("~EntryImpl in"); 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Save the sparse info to disk. This will generate IO for this entry and 8893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // maybe for a child entry, so it is important to do it before deleting this 8903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // entry. 8913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen sparse_.reset(); 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Remove this entry from the list of open entries. 8943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->OnEntryDestroyBegin(entry_.address()); 895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8963f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (doomed_) { 8973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DeleteEntryData(true); 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 899ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.AddEvent(net::NetLog::TYPE_ENTRY_CLOSE, NULL); 9003f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool ret = true; 9013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen for (int index = 0; index < kNumStreams; index++) { 9023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (user_buffers_[index].get()) { 9033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!(ret = Flush(index, 0))) 9043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen LOG(ERROR) << "Failed to save user data"; 9053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 9063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (unreported_size_[index]) { 9073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->ModifyStorageSize( 9083f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_.Data()->data_size[index] - unreported_size_[index], 9093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen entry_.Data()->data_size[index]); 9103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 9113f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 9123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!ret) { 9143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // There was a failure writing the actual data. Mark the entry as dirty. 9153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int current_id = backend_->GetCurrentEntryId(); 9163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->dirty = current_id == 1 ? -1 : current_id - 1; 9173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Store(); 918dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (node_.HasData() && !dirty_) { 9193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Data()->dirty = 0; 9203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen node_.Store(); 9213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 9233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Trace("~EntryImpl out 0x%p", reinterpret_cast<void*>(this)); 925ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net_log_.EndEvent(net::NetLog::TYPE_DISK_CACHE_ENTRY_IMPL, NULL); 9263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->OnEntryDestroyEnd(); 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// ------------------------------------------------------------------------ 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::InternalReadData(int index, int offset, net::IOBuffer* buf, 9323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int buf_len, CompletionCallback* callback) { 9333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.Data()->dirty || read_only_); 9343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DVLOG(2) << "Read from " << index << " at " << offset << " : " << buf_len; 9353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (index < 0 || index >= kNumStreams) 9363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int entry_size = entry_.Data()->data_size[index]; 9393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset >= entry_size || offset < 0 || !buf_len) 9403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return 0; 941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9423f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (buf_len < 0) 9433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TimeTicks start = TimeTicks::Now(); 946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset + buf_len > entry_size) 9483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen buf_len = entry_size - offset; 9493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen UpdateRank(false); 9513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->OnEvent(Stats::READ_DATA); 9533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->OnRead(buf_len); 9543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 9553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(entry_.Data()->data_addr[index]); 9563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int eof = address.is_initialized() ? entry_size : 0; 9573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (user_buffers_[index].get() && 9583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen user_buffers_[index]->PreRead(eof, offset, &buf_len)) { 9593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Complete the operation locally. 9603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen buf_len = user_buffers_[index]->Read(offset, buf, buf_len); 9613f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ReportIOTime(kRead, start); 9623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return buf_len; 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen address.set_value(entry_.Data()->data_addr[index]); 9663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(address.is_initialized()); 9673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!address.is_initialized()) 9683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen File* file = GetBackingFile(address, index); 9713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!file) 9723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen size_t file_offset = offset; 9753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (address.is_block_file()) { 9763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK_LE(offset + buf_len, kMaxBlockSize); 9773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen file_offset += address.start_block() * address.BlockSize() + 9783f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen kBlockHeaderSize; 9793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SyncCallback* io_callback = NULL; 9823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (callback) { 9833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen io_callback = new SyncCallback(this, buf, callback, 984ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_READ_DATA); 9853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9873f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool completed; 9883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!file->Read(buf->data(), buf_len, file_offset, io_callback, &completed)) { 9893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (io_callback) 9903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen io_callback->Discard(); 9913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 9923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9943f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (io_callback && completed) 9953f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen io_callback->Discard(); 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9973f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ReportIOTime(kRead, start); 9983f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return (completed || !callback) ? buf_len : net::ERR_IO_PENDING; 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10013f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint EntryImpl::InternalWriteData(int index, int offset, net::IOBuffer* buf, 10023f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int buf_len, CompletionCallback* callback, 10033f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool truncate) { 10043f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(node_.Data()->dirty || read_only_); 10053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DVLOG(2) << "Write to " << index << " at " << offset << " : " << buf_len; 10063f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (index < 0 || index >= kNumStreams) 10073f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 1008c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset < 0 || buf_len < 0) 10103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_INVALID_ARGUMENT; 1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10123f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int max_file_size = backend_->MaxFileSize(); 10133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 10143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // offset or buf_len could be negative numbers. 10153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset > max_file_size || buf_len > max_file_size || 10163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen offset + buf_len > max_file_size) { 10173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int size = offset + buf_len; 10183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (size <= max_file_size) 10193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen size = kint32max; 10203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->TooMuchStorageRequested(size); 10213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen TimeTicks start = TimeTicks::Now(); 1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Read the size at this point (it may change inside prepare). 10273f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen int entry_size = entry_.Data()->data_size[index]; 10283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool extending = entry_size < offset + buf_len; 10293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen truncate = truncate && entry_size > offset + buf_len; 10303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Trace("To PrepareTarget 0x%x", entry_.address().value()); 10313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!PrepareTarget(index, offset, buf_len, truncate)) 10323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Trace("From PrepareTarget 0x%x", entry_.address().value()); 10353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (extending || truncate) 10363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen UpdateSize(index, entry_size, offset + buf_len); 1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen UpdateRank(true); 1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->OnEvent(Stats::WRITE_DATA); 10413f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen backend_->OnWrite(buf_len); 1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (user_buffers_[index].get()) { 10443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen // Complete the operation locally. 10453f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen user_buffers_[index]->Write(offset, buf, buf_len); 10463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ReportIOTime(kWrite, start); 10473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return buf_len; 10483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen Addr address(entry_.Data()->data_addr[index]); 10513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (offset + buf_len == 0) { 10523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (truncate) { 10533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK(!address.is_initialized()); 10543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 10553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return 0; 10563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen File* file = GetBackingFile(address, index); 10593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!file) 10603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen size_t file_offset = offset; 10633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (address.is_block_file()) { 10643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen DCHECK_LE(offset + buf_len, kMaxBlockSize); 10653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen file_offset += address.start_block() * address.BlockSize() + 10663f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen kBlockHeaderSize; 10673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } else if (truncate || (extending && !buf_len)) { 10683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!file->SetLength(offset + buf_len)) 10693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 10703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!buf_len) 10733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return 0; 1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen SyncCallback* io_callback = NULL; 10763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (callback) { 10773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen io_callback = new SyncCallback(this, buf, callback, 1078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::NetLog::TYPE_ENTRY_WRITE_DATA); 10793f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10813f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen bool completed; 10823f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (!file->Write(buf->data(), buf_len, file_offset, io_callback, 10833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen &completed)) { 10843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (io_callback) 10853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen io_callback->Discard(); 10863f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return net::ERR_FAILED; 1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 10883f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 10893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen if (io_callback && completed) 10903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen io_callback->Discard(); 10913f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 10923f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ReportIOTime(kWrite, start); 10933f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return (completed || !callback) ? buf_len : net::ERR_IO_PENDING; 1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ------------------------------------------------------------------------ 1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::CreateDataBlock(int index, int size) { 1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(index >= 0 && index < kNumStreams); 1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Addr address(entry_.Data()->data_addr[index]); 1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!CreateBlock(size, &address)) 1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Data()->data_addr[index] = address.value(); 1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Store(); 1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::CreateBlock(int size, Addr* address) { 1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!address->is_initialized()); 1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileType file_type = Addr::RequiredFileType(size); 1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (EXTERNAL == file_type) { 1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (size > backend_->MaxFileSize()) 1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!backend_->CreateExternalFile(address)) 1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int num_blocks = (size + Addr::BlockSizeForFileType(file_type) - 1) / 1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Addr::BlockSizeForFileType(file_type); 1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!backend_->CreateBlock(file_type, num_blocks, address)) 1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Note that this method may end up modifying a block file so upon return the 11303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// involved block will be free, and could be reused for something else. If there 11313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// is a crash after that point (and maybe before returning to the caller), the 11323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// entry will be left dirty... and at some point it will be discarded; it is 11333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// important that the entry doesn't keep a reference to this address, or we'll 11343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// end up deleting the contents of |address| once again. 1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::DeleteData(Addr address, int index) { 1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!address.is_initialized()) 1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (address.is_separate_file()) { 11393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int failure = !DeleteCacheFile(backend_->GetFileName(address)); 1140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CACHE_UMA(COUNTS, "DeleteFailed", 0, failure); 11413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (failure) { 1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Failed to delete " << 1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->GetFileName(address).value() << " from the cache."; 11443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 11453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (files_[index]) 11463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick files_[index] = NULL; // Releases the object. 1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->DeleteBlock(address, true); 1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::UpdateRank(bool modified) { 1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!doomed_) { 1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Everything is handled by the backend. 11553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick backend_->UpdateRank(this, modified); 1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time current = Time::Now(); 1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott node_.Data()->last_used = current.ToInternalValue(); 1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (modified) 1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott node_.Data()->last_modified = current.ToInternalValue(); 1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile* EntryImpl::GetBackingFile(Addr address, int index) { 1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott File* file; 1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (address.is_separate_file()) 1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file = GetExternalFile(address, index); 1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file = backend_->File(address); 1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return file; 1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile* EntryImpl::GetExternalFile(Addr address, int index) { 1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(index >= 0 && index <= kKeyFileIndex); 1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!files_[index].get()) { 1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For a key file, use mixed mode IO. 1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_refptr<File> file(new File(kKeyFileIndex == index)); 1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (file->Init(backend_->GetFileName(address))) 1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott files_[index].swap(file); 1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return files_[index].get(); 1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// We keep a memory buffer for everything that ends up stored on a block file 11873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// (because we don't know yet the final data size), and for some of the data 11883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// that end up on external files. This function will initialize that memory 11893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// buffer and / or the files needed to store the data. 11903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// 11913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// In general, a buffer may overlap data already stored on disk, and in that 11923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// case, the contents of the buffer are the most accurate. It may also extend 11933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// the file, but we don't want to read from disk just to keep the buffer up to 11943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// date. This means that as soon as there is a chance to get confused about what 11953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// is the most recent version of some part of a file, we'll flush the buffer and 11963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// reuse it for the new data. Keep in mind that the normal use pattern is quite 11973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// simple (write sequentially from the beginning), so we optimize for handling 11983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// that case. 1199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EntryImpl::PrepareTarget(int index, int offset, int buf_len, 1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool truncate) { 12013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (truncate) 12023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return HandleTruncation(index, offset, buf_len); 1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!offset && !buf_len) 1205731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 1206731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 12073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Addr address(entry_.Data()->data_addr[index]); 12083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (address.is_initialized()) { 12093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (address.is_block_file() && !MoveToLocalBuffer(index)) 12103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!user_buffers_[index].get() && offset < kMaxBlockSize) { 12133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are about to create a buffer for the first 16KB, make sure that we 12143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // preserve existing data. 12153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!CopyToLocalBuffer(index)) 12163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 12173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 12183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!user_buffers_[index].get()) 12213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index].reset(new UserBuffer(backend_)); 1222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return PrepareBuffer(index, offset, buf_len); 1224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We get to this function with some data already stored. If there is a 1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// truncation that results on data stored internally, we'll explicitly 1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// handle the case here. 12293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::HandleTruncation(int index, int offset, int buf_len) { 1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Addr address(entry_.Data()->data_addr[index]); 1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int current_size = entry_.Data()->data_size[index]; 12333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int new_size = offset + buf_len; 12343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!new_size) { 12363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This is by far the most common scenario. 12373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick backend_->ModifyStorageSize(current_size - unreported_size_[index], 0); 12383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entry_.Data()->data_addr[index] = 0; 12393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entry_.Data()->data_size[index] = 0; 12403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick unreported_size_[index] = 0; 12413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entry_.Store(); 12423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DeleteData(address, index); 1243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index].reset(); 1245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We never postpone truncating a file, if there is one, but we may postpone 12493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // telling the backend about the size reduction. 12503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (user_buffers_[index].get()) { 12513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_GE(current_size, user_buffers_[index]->Start()); 12523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!address.is_initialized()) { 12533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // There is no overlap between the buffer and disk. 12543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (new_size > user_buffers_[index]->Start()) { 12553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Just truncate our buffer. 12563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_LT(new_size, user_buffers_[index]->End()); 12573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index]->Truncate(new_size); 12583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 12593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Just discard our buffer. 12623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index]->Reset(); 12633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return PrepareBuffer(index, offset, buf_len); 12643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // There is some overlap or we need to extend the file before the 12673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // truncation. 12683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (offset > user_buffers_[index]->Start()) 12693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index]->Truncate(new_size); 12703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UpdateSize(index, current_size, new_size); 12713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!Flush(index, 0)) 12723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 12733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index].reset(); 12743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We have data somewhere, and it is not in a buffer. 12773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!user_buffers_[index].get()); 12783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(address.is_initialized()); 12793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (new_size > kMaxBlockSize) 12813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; // Let the operation go directly to disk. 12823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ImportSeparateFile(index, offset + buf_len); 1284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::CopyToLocalBuffer(int index) { 1287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Addr address(entry_.Data()->data_addr[index]); 1288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_buffers_[index].get()); 1289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(address.is_initialized()); 12903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int len = std::min(entry_.Data()->data_size[index], kMaxBlockSize); 12923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index].reset(new UserBuffer(backend_)); 12933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index]->Write(len, NULL, 0); 1294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott File* file = GetBackingFile(address, index); 12963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int offset = 0; 1297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (address.is_block_file()) 1299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; 1300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!file || 13023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !file->Read(user_buffers_[index]->Data(), len, offset, NULL, NULL)) { 13033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index].reset(); 13043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 13053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 13063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 13073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 13083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 13093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::MoveToLocalBuffer(int index) { 13103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!CopyToLocalBuffer(index)) 1311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Addr address(entry_.Data()->data_addr[index]); 1314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Data()->data_addr[index] = 0; 1315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Store(); 13163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DeleteData(address, index); 1317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we lose this entry we'll see it as zero sized. 13193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int len = entry_.Data()->data_size[index]; 13203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick backend_->ModifyStorageSize(len - unreported_size_[index], 0); 13213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick unreported_size_[index] = len; 1322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::ImportSeparateFile(int index, int new_size) { 13263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (entry_.Data()->data_size[index] > new_size) 13273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UpdateSize(index, entry_.Data()->data_size[index], new_size); 13283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 13293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return MoveToLocalBuffer(index); 13303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 13313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 13323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::PrepareBuffer(int index, int offset, int buf_len) { 13333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(user_buffers_[index].get()); 1334513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if ((user_buffers_[index]->End() && offset > user_buffers_[index]->End()) || 1335513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch offset > entry_.Data()->data_size[index]) { 1336513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // We are about to extend the buffer or the file (with zeros), so make sure 1337513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // that we are not overwriting anything. 13383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Addr address(entry_.Data()->data_addr[index]); 13393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (address.is_initialized() && address.is_separate_file()) { 1340513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!Flush(index, 0)) 13413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1342513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // There is an actual file already, and we don't want to keep track of 1343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // its length so we let this operation go straight to disk. 1344513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // The only case when a buffer is allowed to extend the file (as in fill 1345513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // with zeros before the start) is when there is no file yet to extend. 1346513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch user_buffers_[index].reset(); 1347513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 13483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!user_buffers_[index]->PreWrite(offset, buf_len)) { 13523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!Flush(index, offset + buf_len)) 13533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Lets try again. 1356513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (offset > user_buffers_[index]->End() || 1357513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch !user_buffers_[index]->PreWrite(offset, buf_len)) { 13583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We cannot complete the operation with a buffer. 13593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!user_buffers_[index]->Size()); 13603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!user_buffers_[index]->Start()); 13613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index].reset(); 13623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 13633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool EntryImpl::Flush(int index, int min_len) { 1368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Addr address(entry_.Data()->data_addr[index]); 1369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_buffers_[index].get()); 13703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!address.is_initialized() || address.is_separate_file()); 1371513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DVLOG(3) << "Flush"; 1372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int size = std::max(entry_.Data()->data_size[index], min_len); 1374731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (size && !address.is_initialized() && !CreateDataBlock(index, size)) 1375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!entry_.Data()->data_size[index]) { 13783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!user_buffers_[index]->Size()); 13793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 13803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 13813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott address.set_value(entry_.Data()->data_addr[index]); 1383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int len = user_buffers_[index]->Size(); 13853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int offset = user_buffers_[index]->Start(); 13863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!len && !offset) 13873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 1388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (address.is_block_file()) { 13903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(len, entry_.Data()->data_size[index]); 13913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!offset); 13923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick offset = address.start_block() * address.BlockSize() + kBlockHeaderSize; 13933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick File* file = GetBackingFile(address, index); 1396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!file) 1397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!file->Write(user_buffers_[index]->Data(), len, offset, NULL, NULL)) 14003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 14013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick user_buffers_[index]->Reset(); 1402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid EntryImpl::UpdateSize(int index, int old_size, int new_size) { 14073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (entry_.Data()->data_size[index] == new_size) 14083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 14093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 14103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick unreported_size_[index] += new_size - old_size; 14113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entry_.Data()->data_size[index] = new_size; 14123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entry_.set_modified(); 14133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 14143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint EntryImpl::InitSparseData() { 1416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (sparse_.get()) 1417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return net::OK; 1418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Use a local variable so that sparse_ never goes from 'valid' to NULL. 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SparseControl> sparse(new SparseControl(this)); 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int result = sparse->Init(); 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (net::OK == result) 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sparse_.swap(sparse); 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 1426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::SetEntryFlags(uint32 flags) { 1429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Data()->flags |= flags; 1430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.set_modified(); 1431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint32 EntryImpl::GetEntryFlags() { 1434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return entry_.Data()->flags; 1435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::GetData(int index, char** buffer, Addr* address) { 14383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (user_buffers_[index].get() && user_buffers_[index]->Size() && 14393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !user_buffers_[index]->Start()) { 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The data is already in memory, just copy it and we're done. 1441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_len = entry_.Data()->data_size[index]; 14423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (data_len <= user_buffers_[index]->Size()) { 14433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!user_buffers_[index]->Start()); 14443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *buffer = new char[data_len]; 14453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick memcpy(*buffer, user_buffers_[index]->Data(), data_len); 14463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 14473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Bad news: we'd have to read the info from disk so instead we'll just tell 1451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the caller where to read from. 1452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *buffer = NULL; 1453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott address->set_value(entry_.Data()->data_addr[index]); 1454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (address->is_initialized()) { 1455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Prevent us from deleting the block from the backing store. 1456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott backend_->ModifyStorageSize(entry_.Data()->data_size[index] - 1457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unreported_size_[index], 0); 1458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Data()->data_addr[index] = 0; 1459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Data()->data_size[index] = 0; 1460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EntryImpl::Log(const char* msg) { 1464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int dirty = 0; 1465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (node_.HasData()) { 1466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dirty = node_.Data()->dirty; 1467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Trace("%s 0x%p 0x%x 0x%x", msg, reinterpret_cast<void*>(this), 1470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.address().value(), node_.address().value()); 1471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Trace(" data: 0x%x 0x%x 0x%x", entry_.Data()->data_addr[0], 1473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott entry_.Data()->data_addr[1], entry_.Data()->long_key); 1474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Trace(" doomed: %d 0x%x", doomed_, dirty); 1476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace disk_cache 1479