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

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

Powered by Google App Engine
This is Rietveld 408576698