Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: net/disk_cache/simple/simple_synchronous_entry.cc

Issue 1977863003: SimpleCache: open with fewer seeks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@open-speeder-macbetter
Patch Set: actually fix test Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/disk_cache/simple/simple_synchronous_entry.h" 5 #include "net/disk_cache/simple/simple_synchronous_entry.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring> 8 #include <cstring>
9 #include <functional> 9 #include <functional>
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
14 #include "base/hash.h" 14 #include "base/hash.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
17 #include "base/numerics/safe_conversions.h" 17 #include "base/numerics/safe_conversions.h"
18 #include "base/sha1.h" 18 #include "base/sha1.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/timer/elapsed_timer.h" 20 #include "base/timer/elapsed_timer.h"
21 #include "crypto/secure_hash.h"
22 #include "net/base/hash_value.h"
21 #include "net/base/io_buffer.h" 23 #include "net/base/io_buffer.h"
22 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
23 #include "net/disk_cache/simple/simple_backend_version.h" 25 #include "net/disk_cache/simple/simple_backend_version.h"
24 #include "net/disk_cache/simple/simple_histogram_macros.h" 26 #include "net/disk_cache/simple/simple_histogram_macros.h"
25 #include "net/disk_cache/simple/simple_util.h" 27 #include "net/disk_cache/simple/simple_util.h"
26 #include "third_party/zlib/zlib.h" 28 #include "third_party/zlib/zlib.h"
27 29
28 using base::File; 30 using base::File;
29 using base::FilePath; 31 using base::FilePath;
30 using base::Time; 32 using base::Time;
31 33
32 namespace { 34 namespace {
33 35
34 // Used in histograms, please only add entries at the end. 36 // Used in histograms, please only add entries at the end.
35 enum OpenEntryResult { 37 enum OpenEntryResult {
36 OPEN_ENTRY_SUCCESS = 0, 38 OPEN_ENTRY_SUCCESS = 0,
37 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1, 39 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1,
38 OPEN_ENTRY_CANT_READ_HEADER = 2, 40 OPEN_ENTRY_CANT_READ_HEADER = 2,
39 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3, 41 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3,
40 OPEN_ENTRY_BAD_VERSION = 4, 42 OPEN_ENTRY_BAD_VERSION = 4,
41 OPEN_ENTRY_CANT_READ_KEY = 5, 43 OPEN_ENTRY_CANT_READ_KEY = 5,
42 // OPEN_ENTRY_KEY_MISMATCH = 6, Deprecated. 44 OPEN_ENTRY_KEY_MISMATCH = 6,
43 OPEN_ENTRY_KEY_HASH_MISMATCH = 7, 45 OPEN_ENTRY_KEY_HASH_MISMATCH = 7,
44 OPEN_ENTRY_SPARSE_OPEN_FAILED = 8, 46 OPEN_ENTRY_SPARSE_OPEN_FAILED = 8,
45 OPEN_ENTRY_MAX = 9, 47 OPEN_ENTRY_MAX = 9,
46 }; 48 };
47 49
48 // Used in histograms, please only add entries at the end. 50 // Used in histograms, please only add entries at the end.
49 enum WriteResult { 51 enum WriteResult {
50 WRITE_RESULT_SUCCESS = 0, 52 WRITE_RESULT_SUCCESS = 0,
51 WRITE_RESULT_PRETRUNCATE_FAILURE, 53 WRITE_RESULT_PRETRUNCATE_FAILURE,
52 WRITE_RESULT_WRITE_FAILURE, 54 WRITE_RESULT_WRITE_FAILURE,
53 WRITE_RESULT_TRUNCATE_FAILURE, 55 WRITE_RESULT_TRUNCATE_FAILURE,
54 WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED, 56 WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED,
55 WRITE_RESULT_LAZY_CREATE_FAILURE, 57 WRITE_RESULT_LAZY_CREATE_FAILURE,
56 WRITE_RESULT_LAZY_INITIALIZE_FAILURE, 58 WRITE_RESULT_LAZY_INITIALIZE_FAILURE,
57 WRITE_RESULT_MAX, 59 WRITE_RESULT_MAX,
58 }; 60 };
59 61
60 // Used in histograms, please only add entries at the end. 62 // Used in histograms, please only add entries at the end.
61 enum CheckEOFResult { 63 enum CheckEOFResult {
62 CHECK_EOF_RESULT_SUCCESS, 64 CHECK_EOF_RESULT_SUCCESS,
63 CHECK_EOF_RESULT_READ_FAILURE, 65 CHECK_EOF_RESULT_READ_FAILURE,
64 CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH, 66 CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH,
65 CHECK_EOF_RESULT_CRC_MISMATCH, 67 CHECK_EOF_RESULT_CRC_MISMATCH,
68 CHECK_EOF_RESULT_KEY_SHA256_MISMATCH,
66 CHECK_EOF_RESULT_MAX, 69 CHECK_EOF_RESULT_MAX,
67 }; 70 };
68 71
69 // Used in histograms, please only add entries at the end. 72 // Used in histograms, please only add entries at the end.
70 enum CloseResult { 73 enum CloseResult {
71 CLOSE_RESULT_SUCCESS, 74 CLOSE_RESULT_SUCCESS,
72 CLOSE_RESULT_WRITE_FAILURE, 75 CLOSE_RESULT_WRITE_FAILURE,
73 }; 76 };
74 77
78 // Used in histograms, please only add entries at the end.
79 enum class KeySHA256Result { NOT_PRESENT, MATCHED, NO_MATCH, MAX };
80
75 void RecordSyncOpenResult(net::CacheType cache_type, 81 void RecordSyncOpenResult(net::CacheType cache_type,
76 OpenEntryResult result, 82 OpenEntryResult result,
77 bool had_index) { 83 bool had_index) {
78 DCHECK_LT(result, OPEN_ENTRY_MAX); 84 DCHECK_LT(result, OPEN_ENTRY_MAX);
79 SIMPLE_CACHE_UMA(ENUMERATION, 85 SIMPLE_CACHE_UMA(ENUMERATION,
80 "SyncOpenResult", cache_type, result, OPEN_ENTRY_MAX); 86 "SyncOpenResult", cache_type, result, OPEN_ENTRY_MAX);
81 if (had_index) { 87 if (had_index) {
82 SIMPLE_CACHE_UMA(ENUMERATION, 88 SIMPLE_CACHE_UMA(ENUMERATION,
83 "SyncOpenResult_WithIndex", cache_type, 89 "SyncOpenResult_WithIndex", cache_type,
84 result, OPEN_ENTRY_MAX); 90 result, OPEN_ENTRY_MAX);
(...skipping 13 matching lines...) Expand all
98 SIMPLE_CACHE_UMA(ENUMERATION, 104 SIMPLE_CACHE_UMA(ENUMERATION,
99 "SyncCheckEOFResult", cache_type, 105 "SyncCheckEOFResult", cache_type,
100 result, CHECK_EOF_RESULT_MAX); 106 result, CHECK_EOF_RESULT_MAX);
101 } 107 }
102 108
103 void RecordCloseResult(net::CacheType cache_type, CloseResult result) { 109 void RecordCloseResult(net::CacheType cache_type, CloseResult result) {
104 SIMPLE_CACHE_UMA(ENUMERATION, 110 SIMPLE_CACHE_UMA(ENUMERATION,
105 "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX); 111 "SyncCloseResult", cache_type, result, WRITE_RESULT_MAX);
106 } 112 }
107 113
114 void RecordKeySHA256Result(net::CacheType cache_type, KeySHA256Result result) {
115 SIMPLE_CACHE_UMA(ENUMERATION, "SyncKeySHA256Result", cache_type,
116 static_cast<int>(result),
117 static_cast<int>(KeySHA256Result::MAX));
118 }
119
108 bool CanOmitEmptyFile(int file_index) { 120 bool CanOmitEmptyFile(int file_index) {
109 DCHECK_GE(file_index, 0); 121 DCHECK_GE(file_index, 0);
110 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount); 122 DCHECK_LT(file_index, disk_cache::kSimpleEntryFileCount);
111 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2); 123 return file_index == disk_cache::simple_util::GetFileIndexFromStreamIndex(2);
112 } 124 }
113 125
114 bool TruncatePath(const FilePath& filename_to_truncate) { 126 bool TruncatePath(const FilePath& filename_to_truncate) {
115 File file_to_truncate; 127 File file_to_truncate;
116 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE | 128 int flags = File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE |
117 File::FLAG_SHARE_DELETE; 129 File::FLAG_SHARE_DELETE;
118 file_to_truncate.Initialize(filename_to_truncate, flags); 130 file_to_truncate.Initialize(filename_to_truncate, flags);
119 if (!file_to_truncate.IsValid()) 131 if (!file_to_truncate.IsValid())
120 return false; 132 return false;
121 if (!file_to_truncate.SetLength(0)) 133 if (!file_to_truncate.SetLength(0))
122 return false; 134 return false;
123 return true; 135 return true;
124 } 136 }
125 137
138 void CalculateSHA256OfKey(const std::string& key,
139 net::SHA256HashValue* out_hash_value) {
140 std::unique_ptr<crypto::SecureHash> hash(
141 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
142 hash->Update(key.data(), key.size());
143 hash->Finish(out_hash_value, sizeof(*out_hash_value));
144 }
145
126 } // namespace 146 } // namespace
127 147
128 namespace disk_cache { 148 namespace disk_cache {
129 149
130 using simple_util::GetEntryHashKey; 150 using simple_util::GetEntryHashKey;
131 using simple_util::GetFilenameFromEntryHashAndFileIndex; 151 using simple_util::GetFilenameFromEntryHashAndFileIndex;
132 using simple_util::GetSparseFilenameFromEntryHash; 152 using simple_util::GetSparseFilenameFromEntryHash;
133 using simple_util::GetDataSizeFromKeyAndFileSize; 153 using simple_util::GetHeaderSize;
134 using simple_util::GetFileSizeFromKeyAndDataSize; 154 using simple_util::GetDataSizeFromFileSize;
155 using simple_util::GetFileSizeFromDataSize;
135 using simple_util::GetFileIndexFromStreamIndex; 156 using simple_util::GetFileIndexFromStreamIndex;
136 157
137 SimpleEntryStat::SimpleEntryStat(base::Time last_used, 158 SimpleEntryStat::SimpleEntryStat(base::Time last_used,
138 base::Time last_modified, 159 base::Time last_modified,
139 const int32_t data_size[], 160 const int32_t data_size[],
140 const int32_t sparse_data_size) 161 const int32_t sparse_data_size)
141 : last_used_(last_used), 162 : last_used_(last_used),
142 last_modified_(last_modified), 163 last_modified_(last_modified),
143 sparse_data_size_(sparse_data_size) { 164 sparse_data_size_(sparse_data_size) {
144 memcpy(data_size_, data_size, sizeof(data_size_)); 165 memcpy(data_size_, data_size, sizeof(data_size_));
145 } 166 }
146 167
147 int SimpleEntryStat::GetOffsetInFile(const std::string& key, 168 // These size methods all assume the presence of the SHA256 on stream zero,
169 // since this version of the cache always writes it. In the read case, it may
170 // not be present and these methods can't be relied upon.
171
172 int SimpleEntryStat::GetOffsetInFile(size_t key_length,
148 int offset, 173 int offset,
149 int stream_index) const { 174 int stream_index) const {
150 const size_t headers_size = sizeof(SimpleFileHeader) + key.size(); 175 const size_t headers_size = sizeof(SimpleFileHeader) + key_length;
151 const size_t additional_offset = 176 const size_t additional_offset =
152 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0; 177 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0;
153 return headers_size + offset + additional_offset; 178 return headers_size + offset + additional_offset;
154 } 179 }
155 180
156 int SimpleEntryStat::GetEOFOffsetInFile(const std::string& key, 181 int SimpleEntryStat::GetEOFOffsetInFile(size_t key_length,
157 int stream_index) const { 182 int stream_index) const {
158 return GetOffsetInFile(key, data_size_[stream_index], stream_index); 183 size_t additional_offset;
184 if (stream_index != 0)
185 additional_offset = 0;
186 else
187 additional_offset = sizeof(net::SHA256HashValue);
188 return additional_offset +
189 GetOffsetInFile(key_length, data_size_[stream_index], stream_index);
159 } 190 }
160 191
161 int SimpleEntryStat::GetLastEOFOffsetInFile(const std::string& key, 192 int SimpleEntryStat::GetLastEOFOffsetInFile(size_t key_length,
162 int stream_index) const { 193 int stream_index) const {
163 const int file_index = GetFileIndexFromStreamIndex(stream_index); 194 if (stream_index == 1)
164 const int eof_data_offset = 195 return GetEOFOffsetInFile(key_length, 0);
165 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF) 196 return GetEOFOffsetInFile(key_length, stream_index);
166 : data_size_[2];
167 return GetOffsetInFile(key, eof_data_offset, stream_index);
168 } 197 }
169 198
170 int64_t SimpleEntryStat::GetFileSize(const std::string& key, 199 int64_t SimpleEntryStat::GetFileSize(size_t key_length, int file_index) const {
171 int file_index) const { 200 int32_t total_data_size;
172 const int32_t total_data_size = 201 if (file_index == 0) {
173 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF) 202 total_data_size = data_size_[0] + data_size_[1] +
174 : data_size_[2]; 203 sizeof(net::SHA256HashValue) + sizeof(SimpleFileEOF);
175 return GetFileSizeFromKeyAndDataSize(key, total_data_size); 204 } else {
205 total_data_size = data_size_[2];
206 }
207 return GetFileSizeFromDataSize(key_length, total_data_size);
176 } 208 }
177 209
178 SimpleEntryCreationResults::SimpleEntryCreationResults( 210 SimpleEntryCreationResults::SimpleEntryCreationResults(
179 SimpleEntryStat entry_stat) 211 SimpleEntryStat entry_stat)
180 : sync_entry(NULL), 212 : sync_entry(NULL),
181 entry_stat(entry_stat), 213 entry_stat(entry_stat),
182 stream_0_crc32(crc32(0, Z_NULL, 0)), 214 stream_0_crc32(crc32(0, Z_NULL, 0)),
183 result(net::OK) { 215 result(net::OK) {
184 } 216 }
185 217
(...skipping 30 matching lines...) Expand all
216 248
217 SimpleSynchronousEntry::EntryOperationData::EntryOperationData( 249 SimpleSynchronousEntry::EntryOperationData::EntryOperationData(
218 int64_t sparse_offset_p, 250 int64_t sparse_offset_p,
219 int buf_len_p) 251 int buf_len_p)
220 : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {} 252 : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {}
221 253
222 // static 254 // static
223 void SimpleSynchronousEntry::OpenEntry( 255 void SimpleSynchronousEntry::OpenEntry(
224 net::CacheType cache_type, 256 net::CacheType cache_type,
225 const FilePath& path, 257 const FilePath& path,
258 const std::string& key,
226 const uint64_t entry_hash, 259 const uint64_t entry_hash,
227 bool had_index, 260 const bool had_index,
228 SimpleEntryCreationResults* out_results) { 261 SimpleEntryCreationResults* out_results) {
229 base::ElapsedTimer open_time; 262 base::ElapsedTimer open_time;
230 SimpleSynchronousEntry* sync_entry = 263 SimpleSynchronousEntry* sync_entry =
231 new SimpleSynchronousEntry(cache_type, path, "", entry_hash); 264 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index);
232 out_results->result = 265 out_results->result = sync_entry->InitializeForOpen(
233 sync_entry->InitializeForOpen(had_index, 266 &out_results->entry_stat, &out_results->stream_0_data,
234 &out_results->entry_stat, 267 &out_results->stream_0_crc32);
235 &out_results->stream_0_data,
236 &out_results->stream_0_crc32);
237 if (out_results->result != net::OK) { 268 if (out_results->result != net::OK) {
238 sync_entry->Doom(); 269 sync_entry->Doom();
239 delete sync_entry; 270 delete sync_entry;
240 out_results->sync_entry = NULL; 271 out_results->sync_entry = NULL;
241 out_results->stream_0_data = NULL; 272 out_results->stream_0_data = NULL;
242 return; 273 return;
243 } 274 }
244 UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed()); 275 UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed());
245 out_results->sync_entry = sync_entry; 276 out_results->sync_entry = sync_entry;
246 } 277 }
247 278
248 // static 279 // static
249 void SimpleSynchronousEntry::CreateEntry( 280 void SimpleSynchronousEntry::CreateEntry(
250 net::CacheType cache_type, 281 net::CacheType cache_type,
251 const FilePath& path, 282 const FilePath& path,
252 const std::string& key, 283 const std::string& key,
253 const uint64_t entry_hash, 284 const uint64_t entry_hash,
254 bool had_index, 285 const bool had_index,
255 SimpleEntryCreationResults* out_results) { 286 SimpleEntryCreationResults* out_results) {
256 DCHECK_EQ(entry_hash, GetEntryHashKey(key)); 287 DCHECK_EQ(entry_hash, GetEntryHashKey(key));
257 SimpleSynchronousEntry* sync_entry = 288 SimpleSynchronousEntry* sync_entry =
258 new SimpleSynchronousEntry(cache_type, path, key, entry_hash); 289 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index);
259 out_results->result = sync_entry->InitializeForCreate( 290 out_results->result =
260 had_index, &out_results->entry_stat); 291 sync_entry->InitializeForCreate(&out_results->entry_stat);
261 if (out_results->result != net::OK) { 292 if (out_results->result != net::OK) {
262 if (out_results->result != net::ERR_FILE_EXISTS) 293 if (out_results->result != net::ERR_FILE_EXISTS)
263 sync_entry->Doom(); 294 sync_entry->Doom();
264 delete sync_entry; 295 delete sync_entry;
265 out_results->sync_entry = NULL; 296 out_results->sync_entry = NULL;
266 return; 297 return;
267 } 298 }
268 out_results->sync_entry = sync_entry; 299 out_results->sync_entry = sync_entry;
269 } 300 }
270 301
(...skipping 20 matching lines...) Expand all
291 [&path](const uint64_t& key_hash) { 322 [&path](const uint64_t& key_hash) {
292 return SimpleSynchronousEntry::DeleteFilesForEntryHash(path, key_hash); 323 return SimpleSynchronousEntry::DeleteFilesForEntryHash(path, key_hash);
293 }); 324 });
294 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; 325 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED;
295 } 326 }
296 327
297 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, 328 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op,
298 net::IOBuffer* out_buf, 329 net::IOBuffer* out_buf,
299 uint32_t* out_crc32, 330 uint32_t* out_crc32,
300 SimpleEntryStat* entry_stat, 331 SimpleEntryStat* entry_stat,
301 int* out_result) const { 332 int* out_result) {
302 DCHECK(initialized_); 333 DCHECK(initialized_);
303 DCHECK_NE(0, in_entry_op.index); 334 DCHECK_NE(0, in_entry_op.index);
304 const int64_t file_offset =
305 entry_stat->GetOffsetInFile(key_, in_entry_op.offset, in_entry_op.index);
306 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index); 335 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index);
336 if (header_and_key_check_needed_[file_index] &&
337 !CheckHeaderAndKey(file_index)) {
338 *out_result = net::ERR_FAILED;
339 Doom();
340 return;
341 }
342 const int64_t file_offset = entry_stat->GetOffsetInFile(
343 key_.size(), in_entry_op.offset, in_entry_op.index);
307 // Zero-length reads and reads to the empty streams of omitted files should 344 // Zero-length reads and reads to the empty streams of omitted files should
308 // be handled in the SimpleEntryImpl. 345 // be handled in the SimpleEntryImpl.
309 DCHECK_GT(in_entry_op.buf_len, 0); 346 DCHECK_GT(in_entry_op.buf_len, 0);
310 DCHECK(!empty_file_omitted_[file_index]); 347 DCHECK(!empty_file_omitted_[file_index]);
311 File* file = const_cast<File*>(&files_[file_index]); 348 int bytes_read = files_[file_index].Read(file_offset, out_buf->data(),
312 int bytes_read = 349 in_entry_op.buf_len);
313 file->Read(file_offset, out_buf->data(), in_entry_op.buf_len);
314 if (bytes_read > 0) { 350 if (bytes_read > 0) {
315 entry_stat->set_last_used(Time::Now()); 351 entry_stat->set_last_used(Time::Now());
316 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), 352 *out_crc32 = crc32(crc32(0L, Z_NULL, 0),
317 reinterpret_cast<const Bytef*>(out_buf->data()), 353 reinterpret_cast<const Bytef*>(out_buf->data()),
318 bytes_read); 354 bytes_read);
319 } 355 }
320 if (bytes_read >= 0) { 356 if (bytes_read >= 0) {
321 *out_result = bytes_read; 357 *out_result = bytes_read;
322 } else { 358 } else {
323 *out_result = net::ERR_CACHE_READ_FAILURE; 359 *out_result = net::ERR_CACHE_READ_FAILURE;
324 Doom(); 360 Doom();
325 } 361 }
326 } 362 }
327 363
328 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, 364 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
329 net::IOBuffer* in_buf, 365 net::IOBuffer* in_buf,
330 SimpleEntryStat* out_entry_stat, 366 SimpleEntryStat* out_entry_stat,
331 int* out_result) { 367 int* out_result) {
332 DCHECK(initialized_); 368 DCHECK(initialized_);
333 DCHECK_NE(0, in_entry_op.index); 369 DCHECK_NE(0, in_entry_op.index);
334 int index = in_entry_op.index; 370 int index = in_entry_op.index;
335 int file_index = GetFileIndexFromStreamIndex(index); 371 int file_index = GetFileIndexFromStreamIndex(index);
372 if (header_and_key_check_needed_[file_index] &&
373 !empty_file_omitted_[file_index] && !CheckHeaderAndKey(file_index)) {
374 *out_result = net::ERR_FAILED;
375 Doom();
376 return;
377 }
336 int offset = in_entry_op.offset; 378 int offset = in_entry_op.offset;
337 int buf_len = in_entry_op.buf_len; 379 int buf_len = in_entry_op.buf_len;
338 bool truncate = in_entry_op.truncate; 380 bool truncate = in_entry_op.truncate;
339 bool doomed = in_entry_op.doomed; 381 bool doomed = in_entry_op.doomed;
340 const int64_t file_offset = out_entry_stat->GetOffsetInFile( 382 const int64_t file_offset = out_entry_stat->GetOffsetInFile(
341 key_, in_entry_op.offset, in_entry_op.index); 383 key_.size(), in_entry_op.offset, in_entry_op.index);
342 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index); 384 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index);
343 385
344 if (empty_file_omitted_[file_index]) { 386 if (empty_file_omitted_[file_index]) {
345 // Don't create a new file if the entry has been doomed, to avoid it being 387 // Don't create a new file if the entry has been doomed, to avoid it being
346 // mixed up with a newly-created entry with the same key. 388 // mixed up with a newly-created entry with the same key.
347 if (doomed) { 389 if (doomed) {
348 DLOG(WARNING) << "Rejecting write to lazily omitted stream " 390 DLOG(WARNING) << "Rejecting write to lazily omitted stream "
349 << in_entry_op.index << " of doomed cache entry."; 391 << in_entry_op.index << " of doomed cache entry.";
350 RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED); 392 RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED);
351 *out_result = net::ERR_CACHE_WRITE_FAILURE; 393 *out_result = net::ERR_CACHE_WRITE_FAILURE;
(...skipping 12 matching lines...) Expand all
364 Doom(); 406 Doom();
365 *out_result = net::ERR_CACHE_WRITE_FAILURE; 407 *out_result = net::ERR_CACHE_WRITE_FAILURE;
366 return; 408 return;
367 } 409 }
368 } 410 }
369 DCHECK(!empty_file_omitted_[file_index]); 411 DCHECK(!empty_file_omitted_[file_index]);
370 412
371 if (extending_by_write) { 413 if (extending_by_write) {
372 // The EOF record and the eventual stream afterward need to be zeroed out. 414 // The EOF record and the eventual stream afterward need to be zeroed out.
373 const int64_t file_eof_offset = 415 const int64_t file_eof_offset =
374 out_entry_stat->GetEOFOffsetInFile(key_, index); 416 out_entry_stat->GetEOFOffsetInFile(key_.size(), index);
375 if (!files_[file_index].SetLength(file_eof_offset)) { 417 if (!files_[file_index].SetLength(file_eof_offset)) {
376 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); 418 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE);
377 Doom(); 419 Doom();
378 *out_result = net::ERR_CACHE_WRITE_FAILURE; 420 *out_result = net::ERR_CACHE_WRITE_FAILURE;
379 return; 421 return;
380 } 422 }
381 } 423 }
382 if (buf_len > 0) { 424 if (buf_len > 0) {
383 if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) != 425 if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) !=
384 buf_len) { 426 buf_len) {
385 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); 427 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE);
386 Doom(); 428 Doom();
387 *out_result = net::ERR_CACHE_WRITE_FAILURE; 429 *out_result = net::ERR_CACHE_WRITE_FAILURE;
388 return; 430 return;
389 } 431 }
390 } 432 }
391 if (!truncate && (buf_len > 0 || !extending_by_write)) { 433 if (!truncate && (buf_len > 0 || !extending_by_write)) {
392 out_entry_stat->set_data_size( 434 out_entry_stat->set_data_size(
393 index, std::max(out_entry_stat->data_size(index), offset + buf_len)); 435 index, std::max(out_entry_stat->data_size(index), offset + buf_len));
394 } else { 436 } else {
395 out_entry_stat->set_data_size(index, offset + buf_len); 437 out_entry_stat->set_data_size(index, offset + buf_len);
396 int file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_, index); 438 int file_eof_offset =
439 out_entry_stat->GetLastEOFOffsetInFile(key_.size(), index);
397 if (!files_[file_index].SetLength(file_eof_offset)) { 440 if (!files_[file_index].SetLength(file_eof_offset)) {
398 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); 441 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE);
399 Doom(); 442 Doom();
400 *out_result = net::ERR_CACHE_WRITE_FAILURE; 443 *out_result = net::ERR_CACHE_WRITE_FAILURE;
401 return; 444 return;
402 } 445 }
403 } 446 }
404 447
405 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); 448 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS);
406 base::Time modification_time = Time::Now(); 449 base::Time modification_time = Time::Now();
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); 657 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start));
615 } 658 }
616 659
617 void SimpleSynchronousEntry::CheckEOFRecord(int index, 660 void SimpleSynchronousEntry::CheckEOFRecord(int index,
618 const SimpleEntryStat& entry_stat, 661 const SimpleEntryStat& entry_stat,
619 uint32_t expected_crc32, 662 uint32_t expected_crc32,
620 int* out_result) const { 663 int* out_result) const {
621 DCHECK(initialized_); 664 DCHECK(initialized_);
622 uint32_t crc32; 665 uint32_t crc32;
623 bool has_crc32; 666 bool has_crc32;
667 bool has_key_sha256;
624 int stream_size; 668 int stream_size;
625 *out_result = 669 *out_result = GetEOFRecordData(index, entry_stat, &has_crc32, &has_key_sha256,
626 GetEOFRecordData(index, entry_stat, &has_crc32, &crc32, &stream_size); 670 &crc32, &stream_size);
627 if (*out_result != net::OK) { 671 if (*out_result != net::OK) {
628 Doom(); 672 Doom();
629 return; 673 return;
630 } 674 }
631 if (has_crc32 && crc32 != expected_crc32) { 675 if (has_crc32 && crc32 != expected_crc32) {
632 DVLOG(1) << "EOF record had bad crc."; 676 DVLOG(1) << "EOF record had bad crc.";
633 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH; 677 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH;
634 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); 678 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
635 Doom(); 679 Doom();
636 return; 680 return;
637 } 681 }
638 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); 682 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
639 } 683 }
640 684
641 void SimpleSynchronousEntry::Close( 685 void SimpleSynchronousEntry::Close(
642 const SimpleEntryStat& entry_stat, 686 const SimpleEntryStat& entry_stat,
643 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, 687 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write,
644 net::GrowableIOBuffer* stream_0_data) { 688 net::GrowableIOBuffer* stream_0_data) {
645 DCHECK(stream_0_data); 689 DCHECK(stream_0_data);
646 // Write stream 0 data. 690 // Write stream 0 data.
647 int stream_0_offset = entry_stat.GetOffsetInFile(key_, 0, 0); 691 int stream_0_offset = entry_stat.GetOffsetInFile(key_.size(), 0, 0);
648 if (files_[0].Write(stream_0_offset, stream_0_data->data(), 692 if (files_[0].Write(stream_0_offset, stream_0_data->data(),
649 entry_stat.data_size(0)) != 693 entry_stat.data_size(0)) !=
650 entry_stat.data_size(0)) { 694 entry_stat.data_size(0)) {
651 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 695 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
652 DVLOG(1) << "Could not write stream 0 data."; 696 DVLOG(1) << "Could not write stream 0 data.";
653 Doom(); 697 Doom();
654 } 698 }
699 net::SHA256HashValue hash_value;
700 CalculateSHA256OfKey(key_, &hash_value);
701 if (files_[0].Write(stream_0_offset + entry_stat.data_size(0),
702 reinterpret_cast<char*>(hash_value.data),
703 sizeof(hash_value)) != sizeof(hash_value)) {
704 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
705 DVLOG(1) << "Could not write stream 0 data.";
706 Doom();
707 }
655 708
656 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); 709 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
657 it != crc32s_to_write->end(); ++it) { 710 it != crc32s_to_write->end(); ++it) {
658 const int stream_index = it->index; 711 const int stream_index = it->index;
659 const int file_index = GetFileIndexFromStreamIndex(stream_index); 712 const int file_index = GetFileIndexFromStreamIndex(stream_index);
660 if (empty_file_omitted_[file_index]) 713 if (empty_file_omitted_[file_index])
661 continue; 714 continue;
662 715
663 SimpleFileEOF eof_record; 716 SimpleFileEOF eof_record;
664 eof_record.stream_size = entry_stat.data_size(stream_index); 717 eof_record.stream_size = entry_stat.data_size(stream_index);
665 eof_record.final_magic_number = kSimpleFinalMagicNumber; 718 eof_record.final_magic_number = kSimpleFinalMagicNumber;
666 eof_record.flags = 0; 719 eof_record.flags = 0;
667 if (it->has_crc32) 720 if (it->has_crc32)
668 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; 721 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32;
722 if (stream_index == 0)
723 eof_record.flags |= SimpleFileEOF::FLAG_HAS_KEY_SHA256;
669 eof_record.data_crc32 = it->data_crc32; 724 eof_record.data_crc32 = it->data_crc32;
670 int eof_offset = entry_stat.GetEOFOffsetInFile(key_, stream_index); 725 int eof_offset = entry_stat.GetEOFOffsetInFile(key_.size(), stream_index);
671 // If stream 0 changed size, the file needs to be resized, otherwise the 726 // If stream 0 changed size, the file needs to be resized, otherwise the
672 // next open will yield wrong stream sizes. On stream 1 and stream 2 proper 727 // next open will yield wrong stream sizes. On stream 1 and stream 2 proper
673 // resizing of the file is handled in SimpleSynchronousEntry::WriteData(). 728 // resizing of the file is handled in SimpleSynchronousEntry::WriteData().
674 if (stream_index == 0 && 729 if (stream_index == 0 &&
675 !files_[file_index].SetLength(eof_offset)) { 730 !files_[file_index].SetLength(eof_offset)) {
676 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 731 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
677 DVLOG(1) << "Could not truncate stream 0 file."; 732 DVLOG(1) << "Could not truncate stream 0 file.";
678 Doom(); 733 Doom();
679 break; 734 break;
680 } 735 }
681 if (files_[file_index].Write(eof_offset, 736 if (files_[file_index].Write(eof_offset,
682 reinterpret_cast<const char*>(&eof_record), 737 reinterpret_cast<const char*>(&eof_record),
683 sizeof(eof_record)) != 738 sizeof(eof_record)) !=
684 sizeof(eof_record)) { 739 sizeof(eof_record)) {
685 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 740 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
686 DVLOG(1) << "Could not write eof record."; 741 DVLOG(1) << "Could not write eof record.";
687 Doom(); 742 Doom();
688 break; 743 break;
689 } 744 }
690 } 745 }
691 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 746 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
692 if (empty_file_omitted_[i]) 747 if (empty_file_omitted_[i])
693 continue; 748 continue;
694 749
750 if (header_and_key_check_needed_[i] && !CheckHeaderAndKey(i)) {
751 Doom();
752 }
695 files_[i].Close(); 753 files_[i].Close();
696 const int64_t file_size = entry_stat.GetFileSize(key_, i); 754 const int64_t file_size = entry_stat.GetFileSize(key_.size(), i);
697 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 755 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
698 "LastClusterSize", cache_type_, 756 "LastClusterSize", cache_type_,
699 file_size % 4096, 0, 4097, 50); 757 file_size % 4096, 0, 4097, 50);
700 const int64_t cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; 758 const int64_t cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0;
701 SIMPLE_CACHE_UMA(PERCENTAGE, 759 SIMPLE_CACHE_UMA(PERCENTAGE,
702 "LastClusterLossPercent", cache_type_, 760 "LastClusterLossPercent", cache_type_,
703 static_cast<base::HistogramBase::Sample>( 761 static_cast<base::HistogramBase::Sample>(
704 cluster_loss * 100 / (cluster_loss + file_size))); 762 cluster_loss * 100 / (cluster_loss + file_size)));
705 } 763 }
706 764
707 if (sparse_file_open()) 765 if (sparse_file_open())
708 sparse_file_.Close(); 766 sparse_file_.Close();
709 767
710 if (files_created_) { 768 if (files_created_) {
711 const int stream2_file_index = GetFileIndexFromStreamIndex(2); 769 const int stream2_file_index = GetFileIndexFromStreamIndex(2);
712 SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_, 770 SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_,
713 empty_file_omitted_[stream2_file_index]); 771 empty_file_omitted_[stream2_file_index]);
714 } 772 }
715 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS); 773 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS);
716 have_open_files_ = false; 774 have_open_files_ = false;
717 delete this; 775 delete this;
718 } 776 }
719 777
720 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, 778 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type,
721 const FilePath& path, 779 const FilePath& path,
722 const std::string& key, 780 const std::string& key,
723 const uint64_t entry_hash) 781 const uint64_t entry_hash,
782 const bool had_index)
724 : cache_type_(cache_type), 783 : cache_type_(cache_type),
725 path_(path), 784 path_(path),
726 entry_hash_(entry_hash), 785 entry_hash_(entry_hash),
786 had_index_(had_index),
727 key_(key), 787 key_(key),
728 have_open_files_(false), 788 have_open_files_(false),
729 initialized_(false) { 789 initialized_(false) {
730 for (int i = 0; i < kSimpleEntryFileCount; ++i) 790 for (int i = 0; i < kSimpleEntryFileCount; ++i)
731 empty_file_omitted_[i] = false; 791 empty_file_omitted_[i] = false;
732 } 792 }
733 793
734 SimpleSynchronousEntry::~SimpleSynchronousEntry() { 794 SimpleSynchronousEntry::~SimpleSynchronousEntry() {
735 DCHECK(!(have_open_files_ && initialized_)); 795 DCHECK(!(have_open_files_ && initialized_));
736 if (have_open_files_) 796 if (have_open_files_)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE | 832 int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE |
773 File::FLAG_SHARE_DELETE; 833 File::FLAG_SHARE_DELETE;
774 files_[file_index].Initialize(filename, flags); 834 files_[file_index].Initialize(filename, flags);
775 *out_error = files_[file_index].error_details(); 835 *out_error = files_[file_index].error_details();
776 836
777 empty_file_omitted_[file_index] = false; 837 empty_file_omitted_[file_index] = false;
778 838
779 return files_[file_index].IsValid(); 839 return files_[file_index].IsValid();
780 } 840 }
781 841
782 bool SimpleSynchronousEntry::OpenFiles( 842 bool SimpleSynchronousEntry::OpenFiles(SimpleEntryStat* out_entry_stat) {
783 bool had_index,
784 SimpleEntryStat* out_entry_stat) {
785 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 843 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
786 File::Error error; 844 File::Error error;
787 if (!MaybeOpenFile(i, &error)) { 845 if (!MaybeOpenFile(i, &error)) {
788 // TODO(juliatuttle,gavinp): Remove one each of these triplets of 846 // TODO(juliatuttle,gavinp): Remove one each of these triplets of
789 // histograms. We can calculate the third as the sum or difference of the 847 // histograms. We can calculate the third as the sum or difference of the
790 // other two. 848 // other two.
791 RecordSyncOpenResult( 849 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR,
792 cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR, had_index); 850 had_index_);
793 SIMPLE_CACHE_UMA(ENUMERATION, 851 SIMPLE_CACHE_UMA(ENUMERATION,
794 "SyncOpenPlatformFileError", cache_type_, 852 "SyncOpenPlatformFileError", cache_type_,
795 -error, -base::File::FILE_ERROR_MAX); 853 -error, -base::File::FILE_ERROR_MAX);
796 if (had_index) { 854 if (had_index_) {
797 SIMPLE_CACHE_UMA(ENUMERATION, 855 SIMPLE_CACHE_UMA(ENUMERATION,
798 "SyncOpenPlatformFileError_WithIndex", cache_type_, 856 "SyncOpenPlatformFileError_WithIndex", cache_type_,
799 -error, -base::File::FILE_ERROR_MAX); 857 -error, -base::File::FILE_ERROR_MAX);
800 } else { 858 } else {
801 SIMPLE_CACHE_UMA(ENUMERATION, 859 SIMPLE_CACHE_UMA(ENUMERATION,
802 "SyncOpenPlatformFileError_WithoutIndex", 860 "SyncOpenPlatformFileError_WithoutIndex",
803 cache_type_, 861 cache_type_,
804 -error, -base::File::FILE_ERROR_MAX); 862 -error, -base::File::FILE_ERROR_MAX);
805 } 863 }
806 while (--i >= 0) 864 while (--i >= 0)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 } 911 }
854 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 912 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
855 "SyncOpenEntryAge", cache_type_, 913 "SyncOpenEntryAge", cache_type_,
856 entry_age.InHours(), 1, 1000, 50); 914 entry_age.InHours(), 1, 1000, 50);
857 915
858 files_created_ = false; 916 files_created_ = false;
859 917
860 return true; 918 return true;
861 } 919 }
862 920
863 bool SimpleSynchronousEntry::CreateFiles( 921 bool SimpleSynchronousEntry::CreateFiles(SimpleEntryStat* out_entry_stat) {
864 bool had_index,
865 SimpleEntryStat* out_entry_stat) {
866 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 922 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
867 File::Error error; 923 File::Error error;
868 if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) { 924 if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) {
869 // TODO(juliatuttle,gavinp): Remove one each of these triplets of 925 // TODO(juliatuttle,gavinp): Remove one each of these triplets of
870 // histograms. We can calculate the third as the sum or difference of the 926 // histograms. We can calculate the third as the sum or difference of the
871 // other two. 927 // other two.
872 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index); 928 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index_);
873 SIMPLE_CACHE_UMA(ENUMERATION, 929 SIMPLE_CACHE_UMA(ENUMERATION,
874 "SyncCreatePlatformFileError", cache_type_, 930 "SyncCreatePlatformFileError", cache_type_,
875 -error, -base::File::FILE_ERROR_MAX); 931 -error, -base::File::FILE_ERROR_MAX);
876 if (had_index) { 932 if (had_index_) {
877 SIMPLE_CACHE_UMA(ENUMERATION, 933 SIMPLE_CACHE_UMA(ENUMERATION,
878 "SyncCreatePlatformFileError_WithIndex", cache_type_, 934 "SyncCreatePlatformFileError_WithIndex", cache_type_,
879 -error, -base::File::FILE_ERROR_MAX); 935 -error, -base::File::FILE_ERROR_MAX);
880 } else { 936 } else {
881 SIMPLE_CACHE_UMA(ENUMERATION, 937 SIMPLE_CACHE_UMA(ENUMERATION,
882 "SyncCreatePlatformFileError_WithoutIndex", 938 "SyncCreatePlatformFileError_WithoutIndex",
883 cache_type_, 939 cache_type_,
884 -error, -base::File::FILE_ERROR_MAX); 940 -error, -base::File::FILE_ERROR_MAX);
885 } 941 }
886 while (--i >= 0) 942 while (--i >= 0)
(...skipping 25 matching lines...) Expand all
912 968
913 if (sparse_file_open()) 969 if (sparse_file_open())
914 CloseSparseFile(); 970 CloseSparseFile();
915 } 971 }
916 972
917 void SimpleSynchronousEntry::CloseFiles() { 973 void SimpleSynchronousEntry::CloseFiles() {
918 for (int i = 0; i < kSimpleEntryFileCount; ++i) 974 for (int i = 0; i < kSimpleEntryFileCount; ++i)
919 CloseFile(i); 975 CloseFile(i);
920 } 976 }
921 977
978 bool SimpleSynchronousEntry::CheckHeaderAndKey(int file_index) {
979 // TODO(gavinp): Frequently we are doing this at the same time as we read from
980 // the beginning of an entry. It might improve performance to make a single
981 // read(2) call rather than two separate reads. On the other hand, it would
982 // mean an extra memory to memory copy. In the case where we are opening an
983 // entry without a key, the kInitialHeaderRead setting means that we are
984 // actually already reading stream 1 data here, and tossing it out.
985 std::vector<char> header_data(key_.empty() ? kInitialHeaderRead
986 : GetHeaderSize(key_.size()));
987 int bytes_read =
988 files_[file_index].Read(0, header_data.data(), header_data.size());
989 const SimpleFileHeader* header =
990 reinterpret_cast<const SimpleFileHeader*>(header_data.data());
991
992 if (bytes_read == -1 || static_cast<size_t>(bytes_read) < sizeof(*header)) {
993 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index_);
994 return false;
995 }
996 // This resize will not invalidate iterators since it does not enlarge the
997 // header_data.
998 DCHECK_LE(static_cast<size_t>(bytes_read), header_data.size());
999 header_data.resize(bytes_read);
1000
1001 if (header->initial_magic_number != kSimpleInitialMagicNumber) {
1002 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index_);
1003 return false;
1004 }
1005
1006 if (header->version != kSimpleEntryVersionOnDisk) {
1007 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_VERSION, had_index_);
1008 return false;
1009 }
1010
1011 size_t expected_header_size = GetHeaderSize(header->key_length);
1012 if (header_data.size() < expected_header_size) {
1013 size_t old_size = header_data.size();
1014 int bytes_to_read = expected_header_size - old_size;
1015 // This resize will invalidate iterators, since it is enlarging header_data.
1016 header_data.resize(expected_header_size);
1017 int bytes_read = files_[file_index].Read(
1018 old_size, header_data.data() + old_size, bytes_to_read);
1019 if (bytes_read != bytes_to_read) {
1020 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index_);
1021 return false;
1022 }
1023 header = reinterpret_cast<const SimpleFileHeader*>(header_data.data());
1024 }
1025
1026 char* key_data = header_data.data() + sizeof(*header);
1027 if (base::Hash(key_data, header->key_length) != header->key_hash) {
1028 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index_);
1029 return false;
1030 }
1031
1032 std::string key_from_header(key_data, header->key_length);
1033 if (key_.empty()) {
1034 key_.swap(key_from_header);
1035 } else {
1036 if (key_ != key_from_header) {
1037 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_MISMATCH, had_index_);
1038 return false;
1039 }
1040 }
1041
1042 header_and_key_check_needed_[file_index] = false;
1043 return true;
1044 }
1045
922 int SimpleSynchronousEntry::InitializeForOpen( 1046 int SimpleSynchronousEntry::InitializeForOpen(
923 bool had_index,
924 SimpleEntryStat* out_entry_stat, 1047 SimpleEntryStat* out_entry_stat,
925 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1048 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
926 uint32_t* out_stream_0_crc32) { 1049 uint32_t* out_stream_0_crc32) {
927 DCHECK(!initialized_); 1050 DCHECK(!initialized_);
928 if (!OpenFiles(had_index, out_entry_stat)) { 1051 if (!OpenFiles(out_entry_stat)) {
929 DLOG(WARNING) << "Could not open platform files for entry."; 1052 DLOG(WARNING) << "Could not open platform files for entry.";
930 return net::ERR_FAILED; 1053 return net::ERR_FAILED;
931 } 1054 }
932 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 1055 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
933 if (empty_file_omitted_[i]) 1056 if (empty_file_omitted_[i])
934 continue; 1057 continue;
935 1058
936 SimpleFileHeader header; 1059 if (!key_.empty()) {
937 int header_read_result = 1060 header_and_key_check_needed_[i] = true;
938 files_[i].Read(0, reinterpret_cast<char*>(&header), sizeof(header)); 1061 } else {
939 if (header_read_result != sizeof(header)) { 1062 if (!CheckHeaderAndKey(i))
940 DLOG(WARNING) << "Cannot read header from entry."; 1063 return net::ERR_FAILED;
941 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index);
942 return net::ERR_FAILED;
943 } 1064 }
944 1065
945 if (header.initial_magic_number != kSimpleInitialMagicNumber) {
946 // TODO(gavinp): This seems very bad; for now we log at WARNING, but we
947 // should give consideration to not saturating the log with these if that
948 // becomes a problem.
949 DLOG(WARNING) << "Magic number did not match.";
950 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index);
951 return net::ERR_FAILED;
952 }
953
954 if (header.version != kSimpleEntryVersionOnDisk) {
955 DLOG(WARNING) << "Unreadable version.";
956 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_VERSION, had_index);
957 return net::ERR_FAILED;
958 }
959
960 std::unique_ptr<char[]> key(new char[header.key_length]);
961 int key_read_result = files_[i].Read(sizeof(header), key.get(),
962 header.key_length);
963 if (key_read_result != base::checked_cast<int>(header.key_length)) {
964 DLOG(WARNING) << "Cannot read key from entry.";
965 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index);
966 return net::ERR_FAILED;
967 }
968
969 key_ = std::string(key.get(), header.key_length);
970 if (i == 0) { 1066 if (i == 0) {
971 // File size for stream 0 has been stored temporarily in data_size[1]. 1067 // File size for stream 0 has been stored temporarily in data_size[1].
972 int total_data_size = 1068 int ret_value_stream_0 =
973 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(1)); 1069 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat,
974 int ret_value_stream_0 = ReadAndValidateStream0( 1070 stream_0_data, out_stream_0_crc32);
975 total_data_size, out_entry_stat, stream_0_data, out_stream_0_crc32);
976 if (ret_value_stream_0 != net::OK) 1071 if (ret_value_stream_0 != net::OK)
977 return ret_value_stream_0; 1072 return ret_value_stream_0;
978 } else { 1073 } else {
979 out_entry_stat->set_data_size( 1074 out_entry_stat->set_data_size(
980 2, GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(2))); 1075 2,
1076 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2)));
981 if (out_entry_stat->data_size(2) < 0) { 1077 if (out_entry_stat->data_size(2) < 0) {
982 DLOG(WARNING) << "Stream 2 file is too small."; 1078 DLOG(WARNING) << "Stream 2 file is too small.";
983 return net::ERR_FAILED; 1079 return net::ERR_FAILED;
984 } 1080 }
985 } 1081 }
986
987 if (base::Hash(key.get(), header.key_length) != header.key_hash) {
988 DLOG(WARNING) << "Hash mismatch on key.";
989 RecordSyncOpenResult(
990 cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index);
991 return net::ERR_FAILED;
992 }
993 } 1082 }
994 1083
995 int32_t sparse_data_size = 0; 1084 int32_t sparse_data_size = 0;
996 if (!OpenSparseFileIfExists(&sparse_data_size)) { 1085 if (!OpenSparseFileIfExists(&sparse_data_size)) {
997 RecordSyncOpenResult( 1086 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED,
998 cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED, had_index); 1087 had_index_);
999 return net::ERR_FAILED; 1088 return net::ERR_FAILED;
1000 } 1089 }
1001 out_entry_stat->set_sparse_data_size(sparse_data_size); 1090 out_entry_stat->set_sparse_data_size(sparse_data_size);
1002 1091
1003 bool removed_stream2 = false; 1092 bool removed_stream2 = false;
1004 const int stream2_file_index = GetFileIndexFromStreamIndex(2); 1093 const int stream2_file_index = GetFileIndexFromStreamIndex(2);
1005 DCHECK(CanOmitEmptyFile(stream2_file_index)); 1094 DCHECK(CanOmitEmptyFile(stream2_file_index));
1006 if (!empty_file_omitted_[stream2_file_index] && 1095 if (!empty_file_omitted_[stream2_file_index] &&
1007 out_entry_stat->data_size(2) == 0) { 1096 out_entry_stat->data_size(2) == 0) {
1008 DVLOG(1) << "Removing empty stream 2 file."; 1097 DVLOG(1) << "Removing empty stream 2 file.";
1009 CloseFile(stream2_file_index); 1098 CloseFile(stream2_file_index);
1010 DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index); 1099 DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index);
1011 empty_file_omitted_[stream2_file_index] = true; 1100 empty_file_omitted_[stream2_file_index] = true;
1012 removed_stream2 = true; 1101 removed_stream2 = true;
1013 } 1102 }
1014 1103
1015 SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_, 1104 SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_,
1016 removed_stream2); 1105 removed_stream2);
1017 1106
1018 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index); 1107 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index_);
1019 initialized_ = true; 1108 initialized_ = true;
1020 return net::OK; 1109 return net::OK;
1021 } 1110 }
1022 1111
1023 bool SimpleSynchronousEntry::InitializeCreatedFile( 1112 bool SimpleSynchronousEntry::InitializeCreatedFile(
1024 int file_index, 1113 int file_index,
1025 CreateEntryResult* out_result) { 1114 CreateEntryResult* out_result) {
1026 SimpleFileHeader header; 1115 SimpleFileHeader header;
1027 header.initial_magic_number = kSimpleInitialMagicNumber; 1116 header.initial_magic_number = kSimpleInitialMagicNumber;
1028 header.version = kSimpleEntryVersionOnDisk; 1117 header.version = kSimpleEntryVersionOnDisk;
(...skipping 12 matching lines...) Expand all
1041 key_.size()); 1130 key_.size());
1042 if (bytes_written != base::checked_cast<int>(key_.size())) { 1131 if (bytes_written != base::checked_cast<int>(key_.size())) {
1043 *out_result = CREATE_ENTRY_CANT_WRITE_KEY; 1132 *out_result = CREATE_ENTRY_CANT_WRITE_KEY;
1044 return false; 1133 return false;
1045 } 1134 }
1046 1135
1047 return true; 1136 return true;
1048 } 1137 }
1049 1138
1050 int SimpleSynchronousEntry::InitializeForCreate( 1139 int SimpleSynchronousEntry::InitializeForCreate(
1051 bool had_index,
1052 SimpleEntryStat* out_entry_stat) { 1140 SimpleEntryStat* out_entry_stat) {
1053 DCHECK(!initialized_); 1141 DCHECK(!initialized_);
1054 if (!CreateFiles(had_index, out_entry_stat)) { 1142 if (!CreateFiles(out_entry_stat)) {
1055 DLOG(WARNING) << "Could not create platform files."; 1143 DLOG(WARNING) << "Could not create platform files.";
1056 return net::ERR_FILE_EXISTS; 1144 return net::ERR_FILE_EXISTS;
1057 } 1145 }
1058 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 1146 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
1059 if (empty_file_omitted_[i]) 1147 if (empty_file_omitted_[i])
1060 continue; 1148 continue;
1061 1149
1062 CreateEntryResult result; 1150 CreateEntryResult result;
1063 if (!InitializeCreatedFile(i, &result)) { 1151 if (!InitializeCreatedFile(i, &result)) {
1064 RecordSyncCreateResult(result, had_index); 1152 RecordSyncCreateResult(result, had_index_);
1065 return net::ERR_FAILED; 1153 return net::ERR_FAILED;
1066 } 1154 }
1067 } 1155 }
1068 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index); 1156 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_);
1069 initialized_ = true; 1157 initialized_ = true;
1070 return net::OK; 1158 return net::OK;
1071 } 1159 }
1072 1160
1073 int SimpleSynchronousEntry::ReadAndValidateStream0( 1161 int SimpleSynchronousEntry::ReadAndValidateStream0(
1074 int total_data_size, 1162 int file_size,
1075 SimpleEntryStat* out_entry_stat, 1163 SimpleEntryStat* out_entry_stat,
1076 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1164 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
1077 uint32_t* out_stream_0_crc32) const { 1165 uint32_t* out_stream_0_crc32) {
1078 // Temporarily assign all the data size to stream 1 in order to read the 1166 // Pretend this file has a null stream zero, and contains the optional key
1079 // EOF record for stream 0, which contains the size of stream 0. 1167 // SHA256. This is good enough to read the EOF record on the file, which gives
1168 // the actual size of stream 0.
1169 int total_data_size = GetDataSizeFromFileSize(key_.size(), file_size);
1080 out_entry_stat->set_data_size(0, 0); 1170 out_entry_stat->set_data_size(0, 0);
1081 out_entry_stat->set_data_size(1, total_data_size - sizeof(SimpleFileEOF)); 1171 out_entry_stat->set_data_size(
1172 1,
1173 total_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF));
1082 1174
1083 bool has_crc32; 1175 bool has_crc32;
1176 bool has_key_sha256;
1084 uint32_t read_crc32; 1177 uint32_t read_crc32;
1085 int stream_0_size; 1178 int stream_0_size;
1086 int ret_value_crc32 = GetEOFRecordData( 1179 int ret_value_crc32 =
1087 0, *out_entry_stat, &has_crc32, &read_crc32, &stream_0_size); 1180 GetEOFRecordData(0, *out_entry_stat, &has_crc32, &has_key_sha256,
1181 &read_crc32, &stream_0_size);
1088 if (ret_value_crc32 != net::OK) 1182 if (ret_value_crc32 != net::OK)
1089 return ret_value_crc32; 1183 return ret_value_crc32;
1090 1184 // Calculate and set the real values for data size.
1091 if (stream_0_size > out_entry_stat->data_size(1)) 1185 int stream_1_size = out_entry_stat->data_size(1) - stream_0_size;
1186 if (!has_key_sha256)
1187 stream_1_size += sizeof(net::SHA256HashValue);
1188 if (stream_1_size < 0)
1092 return net::ERR_FAILED; 1189 return net::ERR_FAILED;
1093
1094 // These are the real values of data size.
1095 out_entry_stat->set_data_size(0, stream_0_size); 1190 out_entry_stat->set_data_size(0, stream_0_size);
1096 out_entry_stat->set_data_size( 1191 out_entry_stat->set_data_size(1, stream_1_size);
1097 1, out_entry_stat->data_size(1) - stream_0_size);
1098 1192
1099 // Put stream 0 data in memory. 1193 // Put stream 0 data in memory.
1100 *stream_0_data = new net::GrowableIOBuffer(); 1194 *stream_0_data = new net::GrowableIOBuffer();
1101 (*stream_0_data)->SetCapacity(stream_0_size); 1195 (*stream_0_data)->SetCapacity(stream_0_size + sizeof(net::SHA256HashValue));
1102 int file_offset = out_entry_stat->GetOffsetInFile(key_, 0, 0); 1196 int file_offset = out_entry_stat->GetOffsetInFile(key_.size(), 0, 0);
1103 File* file = const_cast<File*>(&files_[0]); 1197 int read_size = stream_0_size;
1104 int bytes_read = 1198 if (has_key_sha256)
1105 file->Read(file_offset, (*stream_0_data)->data(), stream_0_size); 1199 read_size += sizeof(net::SHA256HashValue);
1106 if (bytes_read != stream_0_size) 1200 if (files_[0].Read(file_offset, (*stream_0_data)->data(), read_size) !=
1201 read_size)
1107 return net::ERR_FAILED; 1202 return net::ERR_FAILED;
1108 1203
1109 // Check the CRC32. 1204 // Check the CRC32.
1110 uint32_t expected_crc32 = 1205 uint32_t expected_crc32 =
1111 stream_0_size == 0 1206 stream_0_size == 0
1112 ? crc32(0, Z_NULL, 0) 1207 ? crc32(0, Z_NULL, 0)
1113 : crc32(crc32(0, Z_NULL, 0), 1208 : crc32(crc32(0, Z_NULL, 0),
1114 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), 1209 reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
1115 stream_0_size); 1210 stream_0_size);
1116 if (has_crc32 && read_crc32 != expected_crc32) { 1211 if (has_crc32 && read_crc32 != expected_crc32) {
1117 DVLOG(1) << "EOF record had bad crc."; 1212 DVLOG(1) << "EOF record had bad crc.";
1118 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); 1213 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
1119 return net::ERR_FAILED; 1214 return net::ERR_FAILED;
1120 } 1215 }
1121 *out_stream_0_crc32 = expected_crc32; 1216 *out_stream_0_crc32 = expected_crc32;
1217
1218 // If present, check the key SHA256.
1219 if (has_key_sha256) {
1220 net::SHA256HashValue hash_value;
1221 CalculateSHA256OfKey(key_, &hash_value);
1222 bool matched =
1223 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size,
1224 sizeof(hash_value)) == 0;
1225 if (!matched) {
1226 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH);
1227 return net::ERR_FAILED;
1228 }
1229 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED);
1230 } else {
1231 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT);
1232 }
1233
1234 // Ensure the key is validated before completion.
1235 if (!has_key_sha256 && header_and_key_check_needed_[0])
1236 CheckHeaderAndKey(0);
1237
1122 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); 1238 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
1123 return net::OK; 1239 return net::OK;
1124 } 1240 }
1125 1241
1126 int SimpleSynchronousEntry::GetEOFRecordData(int index, 1242 int SimpleSynchronousEntry::GetEOFRecordData(int index,
1127 const SimpleEntryStat& entry_stat, 1243 const SimpleEntryStat& entry_stat,
1128 bool* out_has_crc32, 1244 bool* out_has_crc32,
1245 bool* out_has_key_sha256,
1129 uint32_t* out_crc32, 1246 uint32_t* out_crc32,
1130 int* out_data_size) const { 1247 int* out_data_size) const {
1131 SimpleFileEOF eof_record; 1248 SimpleFileEOF eof_record;
1132 int file_offset = entry_stat.GetEOFOffsetInFile(key_, index); 1249 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), index);
1133 int file_index = GetFileIndexFromStreamIndex(index); 1250 int file_index = GetFileIndexFromStreamIndex(index);
1134 File* file = const_cast<File*>(&files_[file_index]); 1251 File* file = const_cast<File*>(&files_[file_index]);
1135 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record), 1252 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record),
1136 sizeof(eof_record)) != 1253 sizeof(eof_record)) !=
1137 sizeof(eof_record)) { 1254 sizeof(eof_record)) {
1138 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); 1255 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
1139 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; 1256 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
1140 } 1257 }
1141 1258
1142 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { 1259 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
1143 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); 1260 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
1144 DVLOG(1) << "EOF record had bad magic number."; 1261 DVLOG(1) << "EOF record had bad magic number.";
1145 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; 1262 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
1146 } 1263 }
1147 1264
1148 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == 1265 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
1149 SimpleFileEOF::FLAG_HAS_CRC32; 1266 SimpleFileEOF::FLAG_HAS_CRC32;
1267 *out_has_key_sha256 =
1268 (eof_record.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) ==
1269 SimpleFileEOF::FLAG_HAS_KEY_SHA256;
1150 *out_crc32 = eof_record.data_crc32; 1270 *out_crc32 = eof_record.data_crc32;
1151 *out_data_size = eof_record.stream_size; 1271 *out_data_size = eof_record.stream_size;
1152 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32); 1272 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32);
1153 return net::OK; 1273 return net::OK;
1154 } 1274 }
1155 1275
1156 void SimpleSynchronousEntry::Doom() const { 1276 void SimpleSynchronousEntry::Doom() const {
1157 DeleteFilesForEntryHash(path_, entry_hash_); 1277 DeleteFilesForEntryHash(path_, entry_hash_);
1158 } 1278 }
1159 1279
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 range.offset = offset; 1587 range.offset = offset;
1468 range.length = len; 1588 range.length = len;
1469 range.data_crc32 = data_crc32; 1589 range.data_crc32 = data_crc32;
1470 range.file_offset = data_file_offset; 1590 range.file_offset = data_file_offset;
1471 sparse_ranges_.insert(std::make_pair(offset, range)); 1591 sparse_ranges_.insert(std::make_pair(offset, range));
1472 1592
1473 return true; 1593 return true;
1474 } 1594 }
1475 1595
1476 } // namespace disk_cache 1596 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/simple/simple_synchronous_entry.h ('k') | net/disk_cache/simple/simple_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698