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

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: move obsolete section 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/command_line.h"
12 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
13 #include "base/files/file_util.h" 14 #include "base/files/file_util.h"
14 #include "base/hash.h" 15 #include "base/hash.h"
15 #include "base/location.h" 16 #include "base/location.h"
16 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.h"
17 #include "base/numerics/safe_conversions.h" 18 #include "base/numerics/safe_conversions.h"
18 #include "base/sha1.h" 19 #include "base/sha1.h"
19 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
20 #include "base/timer/elapsed_timer.h" 21 #include "base/timer/elapsed_timer.h"
21 #include "net/base/io_buffer.h" 22 #include "net/base/io_buffer.h"
(...skipping 10 matching lines...) Expand all
32 namespace { 33 namespace {
33 34
34 // Used in histograms, please only add entries at the end. 35 // Used in histograms, please only add entries at the end.
35 enum OpenEntryResult { 36 enum OpenEntryResult {
36 OPEN_ENTRY_SUCCESS = 0, 37 OPEN_ENTRY_SUCCESS = 0,
37 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1, 38 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1,
38 OPEN_ENTRY_CANT_READ_HEADER = 2, 39 OPEN_ENTRY_CANT_READ_HEADER = 2,
39 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3, 40 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3,
40 OPEN_ENTRY_BAD_VERSION = 4, 41 OPEN_ENTRY_BAD_VERSION = 4,
41 OPEN_ENTRY_CANT_READ_KEY = 5, 42 OPEN_ENTRY_CANT_READ_KEY = 5,
42 // OPEN_ENTRY_KEY_MISMATCH = 6, Deprecated. 43 OPEN_ENTRY_KEY_MISMATCH = 6,
43 OPEN_ENTRY_KEY_HASH_MISMATCH = 7, 44 OPEN_ENTRY_KEY_HASH_MISMATCH = 7,
44 OPEN_ENTRY_SPARSE_OPEN_FAILED = 8, 45 OPEN_ENTRY_SPARSE_OPEN_FAILED = 8,
45 OPEN_ENTRY_MAX = 9, 46 OPEN_ENTRY_MAX = 9,
46 }; 47 };
47 48
48 // Used in histograms, please only add entries at the end. 49 // Used in histograms, please only add entries at the end.
49 enum WriteResult { 50 enum WriteResult {
50 WRITE_RESULT_SUCCESS = 0, 51 WRITE_RESULT_SUCCESS = 0,
51 WRITE_RESULT_PRETRUNCATE_FAILURE, 52 WRITE_RESULT_PRETRUNCATE_FAILURE,
52 WRITE_RESULT_WRITE_FAILURE, 53 WRITE_RESULT_WRITE_FAILURE,
(...skipping 12 matching lines...) Expand all
65 CHECK_EOF_RESULT_CRC_MISMATCH, 66 CHECK_EOF_RESULT_CRC_MISMATCH,
66 CHECK_EOF_RESULT_MAX, 67 CHECK_EOF_RESULT_MAX,
67 }; 68 };
68 69
69 // Used in histograms, please only add entries at the end. 70 // Used in histograms, please only add entries at the end.
70 enum CloseResult { 71 enum CloseResult {
71 CLOSE_RESULT_SUCCESS, 72 CLOSE_RESULT_SUCCESS,
72 CLOSE_RESULT_WRITE_FAILURE, 73 CLOSE_RESULT_WRITE_FAILURE,
73 }; 74 };
74 75
76 // When opening an entry without knowing the key, the header must be read
77 // without knowing the size of the key. This is how much to read initially, to
78 // make it likely the entire key is read.
79 const size_t kInitialHeaderRead = 64 * 1024;
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 return true; 129 return true;
124 } 130 }
125 131
126 } // namespace 132 } // namespace
127 133
128 namespace disk_cache { 134 namespace disk_cache {
129 135
130 using simple_util::GetEntryHashKey; 136 using simple_util::GetEntryHashKey;
131 using simple_util::GetFilenameFromEntryHashAndFileIndex; 137 using simple_util::GetFilenameFromEntryHashAndFileIndex;
132 using simple_util::GetSparseFilenameFromEntryHash; 138 using simple_util::GetSparseFilenameFromEntryHash;
133 using simple_util::GetDataSizeFromKeyAndFileSize; 139 using simple_util::GetHeaderSize;
134 using simple_util::GetFileSizeFromKeyAndDataSize; 140 using simple_util::GetDataSizeFromFileSize;
141 using simple_util::GetFileSizeFromDataSize;
135 using simple_util::GetFileIndexFromStreamIndex; 142 using simple_util::GetFileIndexFromStreamIndex;
136 143
137 SimpleEntryStat::SimpleEntryStat(base::Time last_used, 144 SimpleEntryStat::SimpleEntryStat(base::Time last_used,
138 base::Time last_modified, 145 base::Time last_modified,
139 const int32_t data_size[], 146 const int32_t data_size[],
140 const int32_t sparse_data_size) 147 const int32_t sparse_data_size)
141 : last_used_(last_used), 148 : last_used_(last_used),
142 last_modified_(last_modified), 149 last_modified_(last_modified),
143 sparse_data_size_(sparse_data_size) { 150 sparse_data_size_(sparse_data_size) {
144 memcpy(data_size_, data_size, sizeof(data_size_)); 151 memcpy(data_size_, data_size, sizeof(data_size_));
145 } 152 }
146 153
147 int SimpleEntryStat::GetOffsetInFile(const std::string& key, 154 int SimpleEntryStat::GetOffsetInFile(size_t key_length,
148 int offset, 155 int offset,
149 int stream_index) const { 156 int stream_index) const {
150 const size_t headers_size = sizeof(SimpleFileHeader) + key.size(); 157 const size_t headers_size = sizeof(SimpleFileHeader) + key_length;
151 const size_t additional_offset = 158 const size_t additional_offset =
152 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0; 159 stream_index == 0 ? data_size_[1] + sizeof(SimpleFileEOF) : 0;
153 return headers_size + offset + additional_offset; 160 return headers_size + offset + additional_offset;
154 } 161 }
155 162
156 int SimpleEntryStat::GetEOFOffsetInFile(const std::string& key, 163 int SimpleEntryStat::GetEOFOffsetInFile(size_t key_length,
157 int stream_index) const { 164 int stream_index) const {
158 return GetOffsetInFile(key, data_size_[stream_index], stream_index); 165 return GetOffsetInFile(key_length, data_size_[stream_index], stream_index);
159 } 166 }
160 167
161 int SimpleEntryStat::GetLastEOFOffsetInFile(const std::string& key, 168 int SimpleEntryStat::GetLastEOFOffsetInFile(size_t key_length,
162 int stream_index) const { 169 int stream_index) const {
163 const int file_index = GetFileIndexFromStreamIndex(stream_index); 170 const int file_index = GetFileIndexFromStreamIndex(stream_index);
164 const int eof_data_offset = 171 const int eof_data_offset =
165 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF) 172 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF)
166 : data_size_[2]; 173 : data_size_[2];
167 return GetOffsetInFile(key, eof_data_offset, stream_index); 174 return GetOffsetInFile(key_length, eof_data_offset, stream_index);
168 } 175 }
169 176
170 int64_t SimpleEntryStat::GetFileSize(const std::string& key, 177 int64_t SimpleEntryStat::GetFileSize(size_t key_length, int file_index) const {
171 int file_index) const {
172 const int32_t total_data_size = 178 const int32_t total_data_size =
173 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF) 179 file_index == 0 ? data_size_[0] + data_size_[1] + sizeof(SimpleFileEOF)
174 : data_size_[2]; 180 : data_size_[2];
175 return GetFileSizeFromKeyAndDataSize(key, total_data_size); 181 return GetFileSizeFromDataSize(key_length, total_data_size);
176 } 182 }
177 183
178 SimpleEntryCreationResults::SimpleEntryCreationResults( 184 SimpleEntryCreationResults::SimpleEntryCreationResults(
179 SimpleEntryStat entry_stat) 185 SimpleEntryStat entry_stat)
180 : sync_entry(NULL), 186 : sync_entry(NULL),
181 entry_stat(entry_stat), 187 entry_stat(entry_stat),
182 stream_0_crc32(crc32(0, Z_NULL, 0)), 188 stream_0_crc32(crc32(0, Z_NULL, 0)),
183 result(net::OK) { 189 result(net::OK) {
184 } 190 }
185 191
(...skipping 30 matching lines...) Expand all
216 222
217 SimpleSynchronousEntry::EntryOperationData::EntryOperationData( 223 SimpleSynchronousEntry::EntryOperationData::EntryOperationData(
218 int64_t sparse_offset_p, 224 int64_t sparse_offset_p,
219 int buf_len_p) 225 int buf_len_p)
220 : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {} 226 : sparse_offset(sparse_offset_p), buf_len(buf_len_p) {}
221 227
222 // static 228 // static
223 void SimpleSynchronousEntry::OpenEntry( 229 void SimpleSynchronousEntry::OpenEntry(
224 net::CacheType cache_type, 230 net::CacheType cache_type,
225 const FilePath& path, 231 const FilePath& path,
232 const std::string& key,
226 const uint64_t entry_hash, 233 const uint64_t entry_hash,
227 bool had_index, 234 const bool had_index,
228 SimpleEntryCreationResults* out_results) { 235 SimpleEntryCreationResults* out_results) {
229 base::ElapsedTimer open_time; 236 base::ElapsedTimer open_time;
230 SimpleSynchronousEntry* sync_entry = 237 SimpleSynchronousEntry* sync_entry =
231 new SimpleSynchronousEntry(cache_type, path, "", entry_hash); 238 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index);
232 out_results->result = 239 out_results->result = sync_entry->InitializeForOpen(
233 sync_entry->InitializeForOpen(had_index, 240 &out_results->entry_stat, &out_results->stream_0_data,
234 &out_results->entry_stat, 241 &out_results->stream_0_crc32);
235 &out_results->stream_0_data,
236 &out_results->stream_0_crc32);
237 if (out_results->result != net::OK) { 242 if (out_results->result != net::OK) {
238 sync_entry->Doom(); 243 sync_entry->Doom();
239 delete sync_entry; 244 delete sync_entry;
240 out_results->sync_entry = NULL; 245 out_results->sync_entry = NULL;
241 out_results->stream_0_data = NULL; 246 out_results->stream_0_data = NULL;
242 return; 247 return;
243 } 248 }
244 UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed()); 249 UMA_HISTOGRAM_TIMES("SimpleCache.DiskOpenLatency", open_time.Elapsed());
245 out_results->sync_entry = sync_entry; 250 out_results->sync_entry = sync_entry;
246 } 251 }
247 252
248 // static 253 // static
249 void SimpleSynchronousEntry::CreateEntry( 254 void SimpleSynchronousEntry::CreateEntry(
250 net::CacheType cache_type, 255 net::CacheType cache_type,
251 const FilePath& path, 256 const FilePath& path,
252 const std::string& key, 257 const std::string& key,
253 const uint64_t entry_hash, 258 const uint64_t entry_hash,
254 bool had_index, 259 const bool had_index,
255 SimpleEntryCreationResults* out_results) { 260 SimpleEntryCreationResults* out_results) {
256 DCHECK_EQ(entry_hash, GetEntryHashKey(key)); 261 DCHECK_EQ(entry_hash, GetEntryHashKey(key));
257 SimpleSynchronousEntry* sync_entry = 262 SimpleSynchronousEntry* sync_entry =
258 new SimpleSynchronousEntry(cache_type, path, key, entry_hash); 263 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index);
259 out_results->result = sync_entry->InitializeForCreate( 264 out_results->result =
260 had_index, &out_results->entry_stat); 265 sync_entry->InitializeForCreate(&out_results->entry_stat);
261 if (out_results->result != net::OK) { 266 if (out_results->result != net::OK) {
262 if (out_results->result != net::ERR_FILE_EXISTS) 267 if (out_results->result != net::ERR_FILE_EXISTS)
263 sync_entry->Doom(); 268 sync_entry->Doom();
264 delete sync_entry; 269 delete sync_entry;
265 out_results->sync_entry = NULL; 270 out_results->sync_entry = NULL;
266 return; 271 return;
267 } 272 }
268 out_results->sync_entry = sync_entry; 273 out_results->sync_entry = sync_entry;
269 } 274 }
270 275
(...skipping 20 matching lines...) Expand all
291 [&path](const uint64_t& key_hash) { 296 [&path](const uint64_t& key_hash) {
292 return SimpleSynchronousEntry::DeleteFilesForEntryHash(path, key_hash); 297 return SimpleSynchronousEntry::DeleteFilesForEntryHash(path, key_hash);
293 }); 298 });
294 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED; 299 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED;
295 } 300 }
296 301
297 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op, 302 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op,
298 net::IOBuffer* out_buf, 303 net::IOBuffer* out_buf,
299 uint32_t* out_crc32, 304 uint32_t* out_crc32,
300 SimpleEntryStat* entry_stat, 305 SimpleEntryStat* entry_stat,
301 int* out_result) const { 306 int* out_result) {
302 DCHECK(initialized_); 307 DCHECK(initialized_);
303 DCHECK_NE(0, in_entry_op.index); 308 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); 309 int file_index = GetFileIndexFromStreamIndex(in_entry_op.index);
310 if (header_and_key_check_needed_ && !CheckHeaderAndKeyForOpen(file_index)) {
311 *out_result = net::ERR_FAILED;
312 Doom();
313 return;
314 }
315 const int64_t file_offset = entry_stat->GetOffsetInFile(
316 key_.size(), in_entry_op.offset, in_entry_op.index);
307 // Zero-length reads and reads to the empty streams of omitted files should 317 // Zero-length reads and reads to the empty streams of omitted files should
308 // be handled in the SimpleEntryImpl. 318 // be handled in the SimpleEntryImpl.
309 DCHECK_GT(in_entry_op.buf_len, 0); 319 DCHECK_GT(in_entry_op.buf_len, 0);
310 DCHECK(!empty_file_omitted_[file_index]); 320 DCHECK(!empty_file_omitted_[file_index]);
311 File* file = const_cast<File*>(&files_[file_index]); 321 int bytes_read = files_[file_index].Read(file_offset, out_buf->data(),
312 int bytes_read = 322 in_entry_op.buf_len);
313 file->Read(file_offset, out_buf->data(), in_entry_op.buf_len);
314 if (bytes_read > 0) { 323 if (bytes_read > 0) {
315 entry_stat->set_last_used(Time::Now()); 324 entry_stat->set_last_used(Time::Now());
316 *out_crc32 = crc32(crc32(0L, Z_NULL, 0), 325 *out_crc32 = crc32(crc32(0L, Z_NULL, 0),
317 reinterpret_cast<const Bytef*>(out_buf->data()), 326 reinterpret_cast<const Bytef*>(out_buf->data()),
318 bytes_read); 327 bytes_read);
319 } 328 }
320 if (bytes_read >= 0) { 329 if (bytes_read >= 0) {
321 *out_result = bytes_read; 330 *out_result = bytes_read;
322 } else { 331 } else {
323 *out_result = net::ERR_CACHE_READ_FAILURE; 332 *out_result = net::ERR_CACHE_READ_FAILURE;
324 Doom(); 333 Doom();
325 } 334 }
326 } 335 }
327 336
328 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op, 337 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
329 net::IOBuffer* in_buf, 338 net::IOBuffer* in_buf,
330 SimpleEntryStat* out_entry_stat, 339 SimpleEntryStat* out_entry_stat,
331 int* out_result) { 340 int* out_result) {
332 DCHECK(initialized_); 341 DCHECK(initialized_);
333 DCHECK_NE(0, in_entry_op.index); 342 DCHECK_NE(0, in_entry_op.index);
334 int index = in_entry_op.index; 343 int index = in_entry_op.index;
335 int file_index = GetFileIndexFromStreamIndex(index); 344 int file_index = GetFileIndexFromStreamIndex(index);
336 int offset = in_entry_op.offset; 345 int offset = in_entry_op.offset;
337 int buf_len = in_entry_op.buf_len; 346 int buf_len = in_entry_op.buf_len;
338 bool truncate = in_entry_op.truncate; 347 bool truncate = in_entry_op.truncate;
339 bool doomed = in_entry_op.doomed; 348 bool doomed = in_entry_op.doomed;
340 const int64_t file_offset = out_entry_stat->GetOffsetInFile( 349 const int64_t file_offset = out_entry_stat->GetOffsetInFile(
341 key_, in_entry_op.offset, in_entry_op.index); 350 key_.size(), in_entry_op.offset, in_entry_op.index);
342 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index); 351 bool extending_by_write = offset + buf_len > out_entry_stat->data_size(index);
343 352
344 if (empty_file_omitted_[file_index]) { 353 if (empty_file_omitted_[file_index]) {
345 // Don't create a new file if the entry has been doomed, to avoid it being 354 // 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. 355 // mixed up with a newly-created entry with the same key.
347 if (doomed) { 356 if (doomed) {
348 DLOG(WARNING) << "Rejecting write to lazily omitted stream " 357 DLOG(WARNING) << "Rejecting write to lazily omitted stream "
349 << in_entry_op.index << " of doomed cache entry."; 358 << in_entry_op.index << " of doomed cache entry.";
350 RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED); 359 RecordWriteResult(cache_type_, WRITE_RESULT_LAZY_STREAM_ENTRY_DOOMED);
351 *out_result = net::ERR_CACHE_WRITE_FAILURE; 360 *out_result = net::ERR_CACHE_WRITE_FAILURE;
(...skipping 12 matching lines...) Expand all
364 Doom(); 373 Doom();
365 *out_result = net::ERR_CACHE_WRITE_FAILURE; 374 *out_result = net::ERR_CACHE_WRITE_FAILURE;
366 return; 375 return;
367 } 376 }
368 } 377 }
369 DCHECK(!empty_file_omitted_[file_index]); 378 DCHECK(!empty_file_omitted_[file_index]);
370 379
371 if (extending_by_write) { 380 if (extending_by_write) {
372 // The EOF record and the eventual stream afterward need to be zeroed out. 381 // The EOF record and the eventual stream afterward need to be zeroed out.
373 const int64_t file_eof_offset = 382 const int64_t file_eof_offset =
374 out_entry_stat->GetEOFOffsetInFile(key_, index); 383 out_entry_stat->GetEOFOffsetInFile(key_.size(), index);
375 if (!files_[file_index].SetLength(file_eof_offset)) { 384 if (!files_[file_index].SetLength(file_eof_offset)) {
376 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE); 385 RecordWriteResult(cache_type_, WRITE_RESULT_PRETRUNCATE_FAILURE);
377 Doom(); 386 Doom();
378 *out_result = net::ERR_CACHE_WRITE_FAILURE; 387 *out_result = net::ERR_CACHE_WRITE_FAILURE;
379 return; 388 return;
380 } 389 }
381 } 390 }
382 if (buf_len > 0) { 391 if (buf_len > 0) {
383 if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) != 392 if (files_[file_index].Write(file_offset, in_buf->data(), buf_len) !=
384 buf_len) { 393 buf_len) {
385 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE); 394 RecordWriteResult(cache_type_, WRITE_RESULT_WRITE_FAILURE);
386 Doom(); 395 Doom();
387 *out_result = net::ERR_CACHE_WRITE_FAILURE; 396 *out_result = net::ERR_CACHE_WRITE_FAILURE;
388 return; 397 return;
389 } 398 }
390 } 399 }
391 if (!truncate && (buf_len > 0 || !extending_by_write)) { 400 if (!truncate && (buf_len > 0 || !extending_by_write)) {
392 out_entry_stat->set_data_size( 401 out_entry_stat->set_data_size(
393 index, std::max(out_entry_stat->data_size(index), offset + buf_len)); 402 index, std::max(out_entry_stat->data_size(index), offset + buf_len));
394 } else { 403 } else {
395 out_entry_stat->set_data_size(index, offset + buf_len); 404 out_entry_stat->set_data_size(index, offset + buf_len);
396 int file_eof_offset = out_entry_stat->GetLastEOFOffsetInFile(key_, index); 405 int file_eof_offset =
406 out_entry_stat->GetLastEOFOffsetInFile(key_.size(), index);
397 if (!files_[file_index].SetLength(file_eof_offset)) { 407 if (!files_[file_index].SetLength(file_eof_offset)) {
398 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE); 408 RecordWriteResult(cache_type_, WRITE_RESULT_TRUNCATE_FAILURE);
399 Doom(); 409 Doom();
400 *out_result = net::ERR_CACHE_WRITE_FAILURE; 410 *out_result = net::ERR_CACHE_WRITE_FAILURE;
401 return; 411 return;
402 } 412 }
403 } 413 }
404 414
405 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS); 415 RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS);
406 base::Time modification_time = Time::Now(); 416 base::Time modification_time = Time::Now();
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 } 647 }
638 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); 648 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
639 } 649 }
640 650
641 void SimpleSynchronousEntry::Close( 651 void SimpleSynchronousEntry::Close(
642 const SimpleEntryStat& entry_stat, 652 const SimpleEntryStat& entry_stat,
643 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, 653 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write,
644 net::GrowableIOBuffer* stream_0_data) { 654 net::GrowableIOBuffer* stream_0_data) {
645 DCHECK(stream_0_data); 655 DCHECK(stream_0_data);
646 // Write stream 0 data. 656 // Write stream 0 data.
647 int stream_0_offset = entry_stat.GetOffsetInFile(key_, 0, 0); 657 int stream_0_offset = entry_stat.GetOffsetInFile(key_.size(), 0, 0);
648 if (files_[0].Write(stream_0_offset, stream_0_data->data(), 658 if (files_[0].Write(stream_0_offset, stream_0_data->data(),
649 entry_stat.data_size(0)) != 659 entry_stat.data_size(0)) !=
650 entry_stat.data_size(0)) { 660 entry_stat.data_size(0)) {
651 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 661 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
652 DVLOG(1) << "Could not write stream 0 data."; 662 DVLOG(1) << "Could not write stream 0 data.";
653 Doom(); 663 Doom();
654 } 664 }
655 665
656 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); 666 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
657 it != crc32s_to_write->end(); ++it) { 667 it != crc32s_to_write->end(); ++it) {
658 const int stream_index = it->index; 668 const int stream_index = it->index;
659 const int file_index = GetFileIndexFromStreamIndex(stream_index); 669 const int file_index = GetFileIndexFromStreamIndex(stream_index);
660 if (empty_file_omitted_[file_index]) 670 if (empty_file_omitted_[file_index])
661 continue; 671 continue;
662 672
663 SimpleFileEOF eof_record; 673 SimpleFileEOF eof_record;
664 eof_record.stream_size = entry_stat.data_size(stream_index); 674 eof_record.stream_size = entry_stat.data_size(stream_index);
665 eof_record.final_magic_number = kSimpleFinalMagicNumber; 675 eof_record.final_magic_number = kSimpleFinalMagicNumber;
666 eof_record.flags = 0; 676 eof_record.flags = 0;
667 if (it->has_crc32) 677 if (it->has_crc32)
668 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32; 678 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32;
669 eof_record.data_crc32 = it->data_crc32; 679 eof_record.data_crc32 = it->data_crc32;
670 int eof_offset = entry_stat.GetEOFOffsetInFile(key_, stream_index); 680 int eof_offset = entry_stat.GetEOFOffsetInFile(key_.size(), stream_index);
671 // If stream 0 changed size, the file needs to be resized, otherwise the 681 // 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 682 // next open will yield wrong stream sizes. On stream 1 and stream 2 proper
673 // resizing of the file is handled in SimpleSynchronousEntry::WriteData(). 683 // resizing of the file is handled in SimpleSynchronousEntry::WriteData().
674 if (stream_index == 0 && 684 if (stream_index == 0 &&
675 !files_[file_index].SetLength(eof_offset)) { 685 !files_[file_index].SetLength(eof_offset)) {
676 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 686 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
677 DVLOG(1) << "Could not truncate stream 0 file."; 687 DVLOG(1) << "Could not truncate stream 0 file.";
678 Doom(); 688 Doom();
679 break; 689 break;
680 } 690 }
681 if (files_[file_index].Write(eof_offset, 691 if (files_[file_index].Write(eof_offset,
682 reinterpret_cast<const char*>(&eof_record), 692 reinterpret_cast<const char*>(&eof_record),
683 sizeof(eof_record)) != 693 sizeof(eof_record)) !=
684 sizeof(eof_record)) { 694 sizeof(eof_record)) {
685 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE); 695 RecordCloseResult(cache_type_, CLOSE_RESULT_WRITE_FAILURE);
686 DVLOG(1) << "Could not write eof record."; 696 DVLOG(1) << "Could not write eof record.";
687 Doom(); 697 Doom();
688 break; 698 break;
689 } 699 }
690 } 700 }
691 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 701 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
692 if (empty_file_omitted_[i]) 702 if (empty_file_omitted_[i])
693 continue; 703 continue;
694 704
695 files_[i].Close(); 705 files_[i].Close();
696 const int64_t file_size = entry_stat.GetFileSize(key_, i); 706 const int64_t file_size = entry_stat.GetFileSize(key_.size(), i);
697 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 707 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
698 "LastClusterSize", cache_type_, 708 "LastClusterSize", cache_type_,
699 file_size % 4096, 0, 4097, 50); 709 file_size % 4096, 0, 4097, 50);
700 const int64_t cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0; 710 const int64_t cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0;
701 SIMPLE_CACHE_UMA(PERCENTAGE, 711 SIMPLE_CACHE_UMA(PERCENTAGE,
702 "LastClusterLossPercent", cache_type_, 712 "LastClusterLossPercent", cache_type_,
703 static_cast<base::HistogramBase::Sample>( 713 static_cast<base::HistogramBase::Sample>(
704 cluster_loss * 100 / (cluster_loss + file_size))); 714 cluster_loss * 100 / (cluster_loss + file_size)));
705 } 715 }
706 716
707 if (sparse_file_open()) 717 if (sparse_file_open())
708 sparse_file_.Close(); 718 sparse_file_.Close();
709 719
710 if (files_created_) { 720 if (files_created_) {
711 const int stream2_file_index = GetFileIndexFromStreamIndex(2); 721 const int stream2_file_index = GetFileIndexFromStreamIndex(2);
712 SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_, 722 SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_,
713 empty_file_omitted_[stream2_file_index]); 723 empty_file_omitted_[stream2_file_index]);
714 } 724 }
715 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS); 725 RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS);
716 have_open_files_ = false; 726 have_open_files_ = false;
717 delete this; 727 delete this;
718 } 728 }
719 729
720 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type, 730 SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type,
721 const FilePath& path, 731 const FilePath& path,
722 const std::string& key, 732 const std::string& key,
723 const uint64_t entry_hash) 733 const uint64_t entry_hash,
734 const bool had_index)
724 : cache_type_(cache_type), 735 : cache_type_(cache_type),
725 path_(path), 736 path_(path),
726 entry_hash_(entry_hash), 737 entry_hash_(entry_hash),
738 had_index_(had_index),
727 key_(key), 739 key_(key),
728 have_open_files_(false), 740 have_open_files_(false),
729 initialized_(false) { 741 initialized_(false),
742 header_and_key_check_needed_(false) {
730 for (int i = 0; i < kSimpleEntryFileCount; ++i) 743 for (int i = 0; i < kSimpleEntryFileCount; ++i)
731 empty_file_omitted_[i] = false; 744 empty_file_omitted_[i] = false;
732 } 745 }
733 746
734 SimpleSynchronousEntry::~SimpleSynchronousEntry() { 747 SimpleSynchronousEntry::~SimpleSynchronousEntry() {
735 DCHECK(!(have_open_files_ && initialized_)); 748 DCHECK(!(have_open_files_ && initialized_));
736 if (have_open_files_) 749 if (have_open_files_)
737 CloseFiles(); 750 CloseFiles();
738 } 751 }
739 752
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE | 785 int flags = File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE |
773 File::FLAG_SHARE_DELETE; 786 File::FLAG_SHARE_DELETE;
774 files_[file_index].Initialize(filename, flags); 787 files_[file_index].Initialize(filename, flags);
775 *out_error = files_[file_index].error_details(); 788 *out_error = files_[file_index].error_details();
776 789
777 empty_file_omitted_[file_index] = false; 790 empty_file_omitted_[file_index] = false;
778 791
779 return files_[file_index].IsValid(); 792 return files_[file_index].IsValid();
780 } 793 }
781 794
782 bool SimpleSynchronousEntry::OpenFiles( 795 bool SimpleSynchronousEntry::OpenFiles(SimpleEntryStat* out_entry_stat) {
783 bool had_index,
784 SimpleEntryStat* out_entry_stat) {
785 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 796 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
786 File::Error error; 797 File::Error error;
787 if (!MaybeOpenFile(i, &error)) { 798 if (!MaybeOpenFile(i, &error)) {
788 // TODO(juliatuttle,gavinp): Remove one each of these triplets of 799 // TODO(juliatuttle,gavinp): Remove one each of these triplets of
789 // histograms. We can calculate the third as the sum or difference of the 800 // histograms. We can calculate the third as the sum or difference of the
790 // other two. 801 // other two.
791 RecordSyncOpenResult( 802 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR,
792 cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR, had_index); 803 had_index_);
793 SIMPLE_CACHE_UMA(ENUMERATION, 804 SIMPLE_CACHE_UMA(ENUMERATION,
794 "SyncOpenPlatformFileError", cache_type_, 805 "SyncOpenPlatformFileError", cache_type_,
795 -error, -base::File::FILE_ERROR_MAX); 806 -error, -base::File::FILE_ERROR_MAX);
796 if (had_index) { 807 if (had_index_) {
797 SIMPLE_CACHE_UMA(ENUMERATION, 808 SIMPLE_CACHE_UMA(ENUMERATION,
798 "SyncOpenPlatformFileError_WithIndex", cache_type_, 809 "SyncOpenPlatformFileError_WithIndex", cache_type_,
799 -error, -base::File::FILE_ERROR_MAX); 810 -error, -base::File::FILE_ERROR_MAX);
800 } else { 811 } else {
801 SIMPLE_CACHE_UMA(ENUMERATION, 812 SIMPLE_CACHE_UMA(ENUMERATION,
802 "SyncOpenPlatformFileError_WithoutIndex", 813 "SyncOpenPlatformFileError_WithoutIndex",
803 cache_type_, 814 cache_type_,
804 -error, -base::File::FILE_ERROR_MAX); 815 -error, -base::File::FILE_ERROR_MAX);
805 } 816 }
806 while (--i >= 0) 817 while (--i >= 0)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 } 864 }
854 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, 865 SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
855 "SyncOpenEntryAge", cache_type_, 866 "SyncOpenEntryAge", cache_type_,
856 entry_age.InHours(), 1, 1000, 50); 867 entry_age.InHours(), 1, 1000, 50);
857 868
858 files_created_ = false; 869 files_created_ = false;
859 870
860 return true; 871 return true;
861 } 872 }
862 873
863 bool SimpleSynchronousEntry::CreateFiles( 874 bool SimpleSynchronousEntry::CreateFiles(SimpleEntryStat* out_entry_stat) {
864 bool had_index,
865 SimpleEntryStat* out_entry_stat) {
866 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 875 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
867 File::Error error; 876 File::Error error;
868 if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) { 877 if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) {
869 // TODO(juliatuttle,gavinp): Remove one each of these triplets of 878 // TODO(juliatuttle,gavinp): Remove one each of these triplets of
870 // histograms. We can calculate the third as the sum or difference of the 879 // histograms. We can calculate the third as the sum or difference of the
871 // other two. 880 // other two.
872 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index); 881 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index_);
873 SIMPLE_CACHE_UMA(ENUMERATION, 882 SIMPLE_CACHE_UMA(ENUMERATION,
874 "SyncCreatePlatformFileError", cache_type_, 883 "SyncCreatePlatformFileError", cache_type_,
875 -error, -base::File::FILE_ERROR_MAX); 884 -error, -base::File::FILE_ERROR_MAX);
876 if (had_index) { 885 if (had_index_) {
877 SIMPLE_CACHE_UMA(ENUMERATION, 886 SIMPLE_CACHE_UMA(ENUMERATION,
878 "SyncCreatePlatformFileError_WithIndex", cache_type_, 887 "SyncCreatePlatformFileError_WithIndex", cache_type_,
879 -error, -base::File::FILE_ERROR_MAX); 888 -error, -base::File::FILE_ERROR_MAX);
880 } else { 889 } else {
881 SIMPLE_CACHE_UMA(ENUMERATION, 890 SIMPLE_CACHE_UMA(ENUMERATION,
882 "SyncCreatePlatformFileError_WithoutIndex", 891 "SyncCreatePlatformFileError_WithoutIndex",
883 cache_type_, 892 cache_type_,
884 -error, -base::File::FILE_ERROR_MAX); 893 -error, -base::File::FILE_ERROR_MAX);
885 } 894 }
886 while (--i >= 0) 895 while (--i >= 0)
(...skipping 25 matching lines...) Expand all
912 921
913 if (sparse_file_open()) 922 if (sparse_file_open())
914 CloseSparseFile(); 923 CloseSparseFile();
915 } 924 }
916 925
917 void SimpleSynchronousEntry::CloseFiles() { 926 void SimpleSynchronousEntry::CloseFiles() {
918 for (int i = 0; i < kSimpleEntryFileCount; ++i) 927 for (int i = 0; i < kSimpleEntryFileCount; ++i)
919 CloseFile(i); 928 CloseFile(i);
920 } 929 }
921 930
931 bool SimpleSynchronousEntry::CheckHeaderAndKeyForOpen(int file_index) {
Randy Smith (Not in Mondays) 2016/05/18 16:41:30 Given that this function is no longer being called
gavinp 2016/05/18 19:05:02 Well, it's still only for open... It's just that o
932 // TODO(gavinp): Frequently we are doing this at the same time as we read from
933 // the beginning of an entry. It might improve performance to make a single
934 // read(2) call rather than two separate reads. On the other hand, it would
935 // mean an extra memory to memory copy.
Randy Smith (Not in Mondays) 2016/05/17 20:04:07 Hmmm. The other issue I'd add to this comment (pr
gavinp 2016/05/18 15:46:00 Yeah, the key is almost always present. And in ite
Randy Smith (Not in Mondays) 2016/05/18 16:41:29 Ah, good point; I hadn't kept in mind no key -> it
936 std::vector<char> header_data(key_.empty() ? kInitialHeaderRead
937 : GetHeaderSize(key_.size()));
938 int bytes_read =
939 files_[file_index].Read(0, header_data.data(), header_data.size());
940 const SimpleFileHeader* header;
941
942 if (bytes_read == -1 || static_cast<size_t>(bytes_read) < sizeof(*header)) {
943 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index_);
944 return false;
945 }
946 header_data.resize(bytes_read);
947 header = reinterpret_cast<const SimpleFileHeader*>(header_data.data());
Randy Smith (Not in Mondays) 2016/05/17 20:04:07 Maybe comment here about dodging the resize() repo
gavinp 2016/05/18 15:46:00 Actually, I checked, and resizes down in size (whi
948
949 if (header->initial_magic_number != kSimpleInitialMagicNumber) {
950 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index_);
951 return false;
952 }
953
954 if (header->version != kSimpleEntryVersionOnDisk) {
955 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_BAD_VERSION, had_index_);
956 return false;
957 }
958
959 size_t expected_header_size = GetHeaderSize(header->key_length);
gavinp 2016/05/16 23:19:28 I think this needs a unit test; just something wit
Randy Smith (Not in Mondays) 2016/05/17 20:04:07 Agreed.
gavinp 2016/05/18 15:46:00 Done.
960 if (header_data.size() < expected_header_size) {
961 size_t old_size = header_data.size();
962 header_data.resize(expected_header_size);
963 int bytes_read =
964 files_[file_index].Read(old_size, header_data.data() + old_size,
965 expected_header_size - old_size);
966 if (bytes_read == -1)
967 header_data.resize(old_size);
Randy Smith (Not in Mondays) 2016/05/17 20:04:07 Call out that this is an error path?
gavinp 2016/05/18 15:46:00 Done.
968 else
969 header_data.resize(old_size + bytes_read);
970 // The resize calls invalidated |*header|, so it must be reset.
Randy Smith (Not in Mondays) 2016/05/18 16:41:30 Why delete the comment? This was an expansion, so
gavinp 2016/05/18 19:05:02 This was not an expansion, because of the resize a
971 header = reinterpret_cast<const SimpleFileHeader*>(header_data.data());
972 }
973
974 if (header_data.size() < sizeof(*header) + header->key_length) {
975 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_KEY, had_index_);
976 return false;
977 }
978 char* key_data = header_data.data() + sizeof(*header);
979 if (base::Hash(key_data, header->key_length) != header->key_hash) {
980 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH, had_index_);
981 return false;
982 }
983
984 std::string key_from_header(key_data, header->key_length);
985 if (key_.empty()) {
986 key_.swap(key_from_header);
987 } else {
988 if (key_ != key_from_header) {
989 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_MISMATCH, had_index_);
990 return false;
991 }
992 }
993
994 header_and_key_check_needed_ = false;
995 return true;
996 }
997
922 int SimpleSynchronousEntry::InitializeForOpen( 998 int SimpleSynchronousEntry::InitializeForOpen(
923 bool had_index,
924 SimpleEntryStat* out_entry_stat, 999 SimpleEntryStat* out_entry_stat,
925 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1000 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
926 uint32_t* out_stream_0_crc32) { 1001 uint32_t* out_stream_0_crc32) {
927 DCHECK(!initialized_); 1002 DCHECK(!initialized_);
928 if (!OpenFiles(had_index, out_entry_stat)) { 1003 if (!OpenFiles(out_entry_stat)) {
929 DLOG(WARNING) << "Could not open platform files for entry."; 1004 DLOG(WARNING) << "Could not open platform files for entry.";
930 return net::ERR_FAILED; 1005 return net::ERR_FAILED;
931 } 1006 }
932 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 1007 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
933 if (empty_file_omitted_[i]) 1008 if (empty_file_omitted_[i])
934 continue; 1009 continue;
935 1010
936 SimpleFileHeader header; 1011 if (!key_.empty() &&
937 int header_read_result = 1012 base::CommandLine::ForCurrentProcess()->HasSwitch(
938 files_[i].Read(0, reinterpret_cast<char*>(&header), sizeof(header)); 1013 "simple-cache-dont-read-initial-header")) {
gavinp 2016/05/16 23:19:28 Oh, yes, this must be removed for landing. I was u
Randy Smith (Not in Mondays) 2016/05/17 20:04:07 Acknowledged.
Randy Smith (Not in Mondays) 2016/05/18 16:41:29 I'd feel better about it being gone in the PS I st
gavinp 2016/05/18 19:05:02 Nothing, done. It was just convenient for me to us
939 if (header_read_result != sizeof(header)) { 1014 header_and_key_check_needed_ = true;
940 DLOG(WARNING) << "Cannot read header from entry."; 1015 } else {
941 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_CANT_READ_HEADER, had_index); 1016 if (!CheckHeaderAndKeyForOpen(i))
942 return net::ERR_FAILED; 1017 return net::ERR_FAILED;
943 } 1018 }
944 1019
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) { 1020 if (i == 0) {
971 // File size for stream 0 has been stored temporarily in data_size[1]. 1021 // File size for stream 0 has been stored temporarily in data_size[1].
972 int total_data_size = 1022 int total_data_size =
973 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(1)); 1023 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(1));
974 int ret_value_stream_0 = ReadAndValidateStream0( 1024 int ret_value_stream_0 = ReadAndValidateStream0(
975 total_data_size, out_entry_stat, stream_0_data, out_stream_0_crc32); 1025 total_data_size, out_entry_stat, stream_0_data, out_stream_0_crc32);
976 if (ret_value_stream_0 != net::OK) 1026 if (ret_value_stream_0 != net::OK)
977 return ret_value_stream_0; 1027 return ret_value_stream_0;
978 } else { 1028 } else {
979 out_entry_stat->set_data_size( 1029 out_entry_stat->set_data_size(
980 2, GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size(2))); 1030 2,
1031 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2)));
981 if (out_entry_stat->data_size(2) < 0) { 1032 if (out_entry_stat->data_size(2) < 0) {
982 DLOG(WARNING) << "Stream 2 file is too small."; 1033 DLOG(WARNING) << "Stream 2 file is too small.";
983 return net::ERR_FAILED; 1034 return net::ERR_FAILED;
984 } 1035 }
985 } 1036 }
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 } 1037 }
994 1038
995 int32_t sparse_data_size = 0; 1039 int32_t sparse_data_size = 0;
996 if (!OpenSparseFileIfExists(&sparse_data_size)) { 1040 if (!OpenSparseFileIfExists(&sparse_data_size)) {
997 RecordSyncOpenResult( 1041 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED,
998 cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED, had_index); 1042 had_index_);
999 return net::ERR_FAILED; 1043 return net::ERR_FAILED;
1000 } 1044 }
1001 out_entry_stat->set_sparse_data_size(sparse_data_size); 1045 out_entry_stat->set_sparse_data_size(sparse_data_size);
1002 1046
1003 bool removed_stream2 = false; 1047 bool removed_stream2 = false;
1004 const int stream2_file_index = GetFileIndexFromStreamIndex(2); 1048 const int stream2_file_index = GetFileIndexFromStreamIndex(2);
1005 DCHECK(CanOmitEmptyFile(stream2_file_index)); 1049 DCHECK(CanOmitEmptyFile(stream2_file_index));
1006 if (!empty_file_omitted_[stream2_file_index] && 1050 if (!empty_file_omitted_[stream2_file_index] &&
1007 out_entry_stat->data_size(2) == 0) { 1051 out_entry_stat->data_size(2) == 0) {
1008 DVLOG(1) << "Removing empty stream 2 file."; 1052 DVLOG(1) << "Removing empty stream 2 file.";
1009 CloseFile(stream2_file_index); 1053 CloseFile(stream2_file_index);
1010 DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index); 1054 DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index);
1011 empty_file_omitted_[stream2_file_index] = true; 1055 empty_file_omitted_[stream2_file_index] = true;
1012 removed_stream2 = true; 1056 removed_stream2 = true;
1013 } 1057 }
1014 1058
1015 SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_, 1059 SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_,
1016 removed_stream2); 1060 removed_stream2);
1017 1061
1018 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index); 1062 RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index_);
1019 initialized_ = true; 1063 initialized_ = true;
1020 return net::OK; 1064 return net::OK;
1021 } 1065 }
1022 1066
1023 bool SimpleSynchronousEntry::InitializeCreatedFile( 1067 bool SimpleSynchronousEntry::InitializeCreatedFile(
1024 int file_index, 1068 int file_index,
1025 CreateEntryResult* out_result) { 1069 CreateEntryResult* out_result) {
1026 SimpleFileHeader header; 1070 SimpleFileHeader header;
1027 header.initial_magic_number = kSimpleInitialMagicNumber; 1071 header.initial_magic_number = kSimpleInitialMagicNumber;
1028 header.version = kSimpleEntryVersionOnDisk; 1072 header.version = kSimpleEntryVersionOnDisk;
(...skipping 12 matching lines...) Expand all
1041 key_.size()); 1085 key_.size());
1042 if (bytes_written != base::checked_cast<int>(key_.size())) { 1086 if (bytes_written != base::checked_cast<int>(key_.size())) {
1043 *out_result = CREATE_ENTRY_CANT_WRITE_KEY; 1087 *out_result = CREATE_ENTRY_CANT_WRITE_KEY;
1044 return false; 1088 return false;
1045 } 1089 }
1046 1090
1047 return true; 1091 return true;
1048 } 1092 }
1049 1093
1050 int SimpleSynchronousEntry::InitializeForCreate( 1094 int SimpleSynchronousEntry::InitializeForCreate(
1051 bool had_index,
1052 SimpleEntryStat* out_entry_stat) { 1095 SimpleEntryStat* out_entry_stat) {
1053 DCHECK(!initialized_); 1096 DCHECK(!initialized_);
1054 if (!CreateFiles(had_index, out_entry_stat)) { 1097 if (!CreateFiles(out_entry_stat)) {
1055 DLOG(WARNING) << "Could not create platform files."; 1098 DLOG(WARNING) << "Could not create platform files.";
1056 return net::ERR_FILE_EXISTS; 1099 return net::ERR_FILE_EXISTS;
1057 } 1100 }
1058 for (int i = 0; i < kSimpleEntryFileCount; ++i) { 1101 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
1059 if (empty_file_omitted_[i]) 1102 if (empty_file_omitted_[i])
1060 continue; 1103 continue;
1061 1104
1062 CreateEntryResult result; 1105 CreateEntryResult result;
1063 if (!InitializeCreatedFile(i, &result)) { 1106 if (!InitializeCreatedFile(i, &result)) {
1064 RecordSyncCreateResult(result, had_index); 1107 RecordSyncCreateResult(result, had_index_);
1065 return net::ERR_FAILED; 1108 return net::ERR_FAILED;
1066 } 1109 }
1067 } 1110 }
1068 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index); 1111 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_);
1069 initialized_ = true; 1112 initialized_ = true;
1070 return net::OK; 1113 return net::OK;
1071 } 1114 }
1072 1115
1073 int SimpleSynchronousEntry::ReadAndValidateStream0( 1116 int SimpleSynchronousEntry::ReadAndValidateStream0(
1074 int total_data_size, 1117 int total_data_size,
1075 SimpleEntryStat* out_entry_stat, 1118 SimpleEntryStat* out_entry_stat,
1076 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, 1119 scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
1077 uint32_t* out_stream_0_crc32) const { 1120 uint32_t* out_stream_0_crc32) const {
1078 // Temporarily assign all the data size to stream 1 in order to read the 1121 // Temporarily assign all the data size to stream 1 in order to read the
(...skipping 13 matching lines...) Expand all
1092 return net::ERR_FAILED; 1135 return net::ERR_FAILED;
1093 1136
1094 // These are the real values of data size. 1137 // These are the real values of data size.
1095 out_entry_stat->set_data_size(0, stream_0_size); 1138 out_entry_stat->set_data_size(0, stream_0_size);
1096 out_entry_stat->set_data_size( 1139 out_entry_stat->set_data_size(
1097 1, out_entry_stat->data_size(1) - stream_0_size); 1140 1, out_entry_stat->data_size(1) - stream_0_size);
1098 1141
1099 // Put stream 0 data in memory. 1142 // Put stream 0 data in memory.
1100 *stream_0_data = new net::GrowableIOBuffer(); 1143 *stream_0_data = new net::GrowableIOBuffer();
1101 (*stream_0_data)->SetCapacity(stream_0_size); 1144 (*stream_0_data)->SetCapacity(stream_0_size);
1102 int file_offset = out_entry_stat->GetOffsetInFile(key_, 0, 0); 1145 int file_offset = out_entry_stat->GetOffsetInFile(key_.size(), 0, 0);
1103 File* file = const_cast<File*>(&files_[0]); 1146 File* file = const_cast<File*>(&files_[0]);
1104 int bytes_read = 1147 int bytes_read =
1105 file->Read(file_offset, (*stream_0_data)->data(), stream_0_size); 1148 file->Read(file_offset, (*stream_0_data)->data(), stream_0_size);
1106 if (bytes_read != stream_0_size) 1149 if (bytes_read != stream_0_size)
1107 return net::ERR_FAILED; 1150 return net::ERR_FAILED;
1108 1151
1109 // Check the CRC32. 1152 // Check the CRC32.
1110 uint32_t expected_crc32 = 1153 uint32_t expected_crc32 =
1111 stream_0_size == 0 1154 stream_0_size == 0
1112 ? crc32(0, Z_NULL, 0) 1155 ? crc32(0, Z_NULL, 0)
1113 : crc32(crc32(0, Z_NULL, 0), 1156 : crc32(crc32(0, Z_NULL, 0),
1114 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), 1157 reinterpret_cast<const Bytef*>((*stream_0_data)->data()),
1115 stream_0_size); 1158 stream_0_size);
1116 if (has_crc32 && read_crc32 != expected_crc32) { 1159 if (has_crc32 && read_crc32 != expected_crc32) {
1117 DVLOG(1) << "EOF record had bad crc."; 1160 DVLOG(1) << "EOF record had bad crc.";
1118 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); 1161 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH);
1119 return net::ERR_FAILED; 1162 return net::ERR_FAILED;
1120 } 1163 }
1121 *out_stream_0_crc32 = expected_crc32; 1164 *out_stream_0_crc32 = expected_crc32;
1122 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); 1165 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS);
1123 return net::OK; 1166 return net::OK;
1124 } 1167 }
1125 1168
1126 int SimpleSynchronousEntry::GetEOFRecordData(int index, 1169 int SimpleSynchronousEntry::GetEOFRecordData(int index,
1127 const SimpleEntryStat& entry_stat, 1170 const SimpleEntryStat& entry_stat,
1128 bool* out_has_crc32, 1171 bool* out_has_crc32,
1129 uint32_t* out_crc32, 1172 uint32_t* out_crc32,
1130 int* out_data_size) const { 1173 int* out_data_size) const {
1131 SimpleFileEOF eof_record; 1174 SimpleFileEOF eof_record;
1132 int file_offset = entry_stat.GetEOFOffsetInFile(key_, index); 1175 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), index);
1133 int file_index = GetFileIndexFromStreamIndex(index); 1176 int file_index = GetFileIndexFromStreamIndex(index);
1134 File* file = const_cast<File*>(&files_[file_index]); 1177 File* file = const_cast<File*>(&files_[file_index]);
1135 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record), 1178 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record),
1136 sizeof(eof_record)) != 1179 sizeof(eof_record)) !=
1137 sizeof(eof_record)) { 1180 sizeof(eof_record)) {
1138 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); 1181 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE);
1139 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; 1182 return net::ERR_CACHE_CHECKSUM_READ_FAILURE;
1140 } 1183 }
1141 1184
1142 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { 1185 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 range.offset = offset; 1510 range.offset = offset;
1468 range.length = len; 1511 range.length = len;
1469 range.data_crc32 = data_crc32; 1512 range.data_crc32 = data_crc32;
1470 range.file_offset = data_file_offset; 1513 range.file_offset = data_file_offset;
1471 sparse_ranges_.insert(std::make_pair(offset, range)); 1514 sparse_ranges_.insert(std::make_pair(offset, range));
1472 1515
1473 return true; 1516 return true;
1474 } 1517 }
1475 1518
1476 } // namespace disk_cache 1519 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698