Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / net / disk_cache / simple / simple_synchronous_entry.cc
blobe6f1eaa4f21c7c3f5da2a978f38069ea712cbb5c
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
3 // found in the LICENSE file.
5 #include "net/disk_cache/simple/simple_synchronous_entry.h"
7 #include <algorithm>
8 #include <cstring>
9 #include <functional>
10 #include <limits>
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/hash.h"
16 #include "base/location.h"
17 #include "base/metrics/histogram.h"
18 #include "base/sha1.h"
19 #include "base/strings/stringprintf.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/net_errors.h"
22 #include "net/disk_cache/simple/simple_util.h"
23 #include "third_party/zlib/zlib.h"
25 using base::kInvalidPlatformFileValue;
26 using base::ClosePlatformFile;
27 using base::FilePath;
28 using base::GetPlatformFileInfo;
29 using base::PlatformFileError;
30 using base::PlatformFileInfo;
31 using base::PLATFORM_FILE_CREATE;
32 using base::PLATFORM_FILE_ERROR_EXISTS;
33 using base::PLATFORM_FILE_OK;
34 using base::PLATFORM_FILE_OPEN;
35 using base::PLATFORM_FILE_READ;
36 using base::PLATFORM_FILE_WRITE;
37 using base::ReadPlatformFile;
38 using base::Time;
39 using base::TruncatePlatformFile;
40 using base::WritePlatformFile;
42 namespace {
44 // Used in histograms, please only add entries at the end.
45 enum OpenEntryResult {
46 OPEN_ENTRY_SUCCESS = 0,
47 OPEN_ENTRY_PLATFORM_FILE_ERROR = 1,
48 OPEN_ENTRY_CANT_READ_HEADER = 2,
49 OPEN_ENTRY_BAD_MAGIC_NUMBER = 3,
50 OPEN_ENTRY_BAD_VERSION = 4,
51 OPEN_ENTRY_CANT_READ_KEY = 5,
52 // OPEN_ENTRY_KEY_MISMATCH = 6, Deprecated.
53 OPEN_ENTRY_KEY_HASH_MISMATCH = 7,
54 OPEN_ENTRY_MAX = 8,
57 // Used in histograms, please only add entries at the end.
58 enum CreateEntryResult {
59 CREATE_ENTRY_SUCCESS = 0,
60 CREATE_ENTRY_PLATFORM_FILE_ERROR = 1,
61 CREATE_ENTRY_CANT_WRITE_HEADER = 2,
62 CREATE_ENTRY_CANT_WRITE_KEY = 3,
63 CREATE_ENTRY_MAX = 4,
66 // Used in histograms, please only add entries at the end.
67 enum WriteResult {
68 WRITE_RESULT_SUCCESS = 0,
69 WRITE_RESULT_PRETRUNCATE_FAILURE,
70 WRITE_RESULT_WRITE_FAILURE,
71 WRITE_RESULT_TRUNCATE_FAILURE,
72 WRITE_RESULT_MAX,
75 // Used in histograms, please only add entries at the end.
76 enum CheckEOFResult {
77 CHECK_EOF_RESULT_SUCCESS,
78 CHECK_EOF_RESULT_READ_FAILURE,
79 CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH,
80 CHECK_EOF_RESULT_CRC_MISMATCH,
81 CHECK_EOF_RESULT_MAX,
84 // Used in histograms, please only add entries at the end.
85 enum CloseResult {
86 CLOSE_RESULT_SUCCESS,
87 CLOSE_RESULT_WRITE_FAILURE,
90 void RecordSyncOpenResult(OpenEntryResult result, bool had_index) {
91 DCHECK_GT(OPEN_ENTRY_MAX, result);
92 UMA_HISTOGRAM_ENUMERATION(
93 "SimpleCache.SyncOpenResult", result, OPEN_ENTRY_MAX);
94 if (had_index) {
95 UMA_HISTOGRAM_ENUMERATION(
96 "SimpleCache.SyncOpenResult_WithIndex", result, OPEN_ENTRY_MAX);
97 } else {
98 UMA_HISTOGRAM_ENUMERATION(
99 "SimpleCache.SyncOpenResult_WithoutIndex", result, OPEN_ENTRY_MAX);
103 void RecordSyncCreateResult(CreateEntryResult result, bool had_index) {
104 DCHECK_GT(CREATE_ENTRY_MAX, result);
105 UMA_HISTOGRAM_ENUMERATION(
106 "SimpleCache.SyncCreateResult", result, CREATE_ENTRY_MAX);
107 if (had_index) {
108 UMA_HISTOGRAM_ENUMERATION(
109 "SimpleCache.SyncCreateResult_WithIndex", result, CREATE_ENTRY_MAX);
110 } else {
111 UMA_HISTOGRAM_ENUMERATION(
112 "SimpleCache.SyncCreateResult_WithoutIndex", result, CREATE_ENTRY_MAX);
116 void RecordWriteResult(WriteResult result) {
117 UMA_HISTOGRAM_ENUMERATION(
118 "SimpleCache.SyncWriteResult", result, WRITE_RESULT_MAX);
121 void RecordCheckEOFResult(CheckEOFResult result) {
122 UMA_HISTOGRAM_ENUMERATION(
123 "SimpleCache.SyncCheckEOFResult", result, CHECK_EOF_RESULT_MAX);
126 void RecordCloseResult(CloseResult result) {
127 UMA_HISTOGRAM_ENUMERATION(
128 "SimpleCache.SyncCloseResult", result, WRITE_RESULT_MAX);
131 } // namespace
133 namespace disk_cache {
135 using simple_util::ConvertEntryHashKeyToHexString;
136 using simple_util::GetEntryHashKey;
137 using simple_util::GetFilenameFromEntryHashAndIndex;
138 using simple_util::GetDataSizeFromKeyAndFileSize;
139 using simple_util::GetFileSizeFromKeyAndDataSize;
140 using simple_util::GetFileOffsetFromKeyAndDataOffset;
142 SimpleEntryStat::SimpleEntryStat() {}
144 SimpleEntryStat::SimpleEntryStat(base::Time last_used_p,
145 base::Time last_modified_p,
146 const int32 data_size_p[])
147 : last_used(last_used_p),
148 last_modified(last_modified_p) {
149 memcpy(data_size, data_size_p, sizeof(data_size));
152 SimpleEntryCreationResults::SimpleEntryCreationResults(
153 SimpleEntryStat entry_stat)
154 : sync_entry(NULL),
155 entry_stat(entry_stat),
156 result(net::OK) {
159 SimpleEntryCreationResults::~SimpleEntryCreationResults() {
162 SimpleSynchronousEntry::CRCRecord::CRCRecord() : index(-1),
163 has_crc32(false),
164 data_crc32(0) {
167 SimpleSynchronousEntry::CRCRecord::CRCRecord(int index_p,
168 bool has_crc32_p,
169 uint32 data_crc32_p)
170 : index(index_p),
171 has_crc32(has_crc32_p),
172 data_crc32(data_crc32_p) {}
174 SimpleSynchronousEntry::EntryOperationData::EntryOperationData(int index_p,
175 int offset_p,
176 int buf_len_p)
177 : index(index_p),
178 offset(offset_p),
179 buf_len(buf_len_p) {}
181 SimpleSynchronousEntry::EntryOperationData::EntryOperationData(int index_p,
182 int offset_p,
183 int buf_len_p,
184 bool truncate_p)
185 : index(index_p),
186 offset(offset_p),
187 buf_len(buf_len_p),
188 truncate(truncate_p) {}
190 // static
191 void SimpleSynchronousEntry::OpenEntry(
192 const FilePath& path,
193 const uint64 entry_hash,
194 bool had_index,
195 SimpleEntryCreationResults *out_results) {
196 SimpleSynchronousEntry* sync_entry = new SimpleSynchronousEntry(path, "",
197 entry_hash);
198 out_results->result = sync_entry->InitializeForOpen(
199 had_index, &out_results->entry_stat);
200 if (out_results->result != net::OK) {
201 sync_entry->Doom();
202 delete sync_entry;
203 out_results->sync_entry = NULL;
204 return;
206 out_results->sync_entry = sync_entry;
209 // static
210 void SimpleSynchronousEntry::CreateEntry(
211 const FilePath& path,
212 const std::string& key,
213 const uint64 entry_hash,
214 bool had_index,
215 SimpleEntryCreationResults *out_results) {
216 DCHECK_EQ(entry_hash, GetEntryHashKey(key));
217 SimpleSynchronousEntry* sync_entry = new SimpleSynchronousEntry(path, key,
218 entry_hash);
219 out_results->result = sync_entry->InitializeForCreate(
220 had_index, &out_results->entry_stat);
221 if (out_results->result != net::OK) {
222 if (out_results->result != net::ERR_FILE_EXISTS)
223 sync_entry->Doom();
224 delete sync_entry;
225 out_results->sync_entry = NULL;
226 return;
228 out_results->sync_entry = sync_entry;
231 // TODO(gavinp): Move this function to its correct location in this .cc file.
232 // static
233 bool SimpleSynchronousEntry::DeleteFilesForEntryHash(
234 const FilePath& path,
235 const uint64 entry_hash) {
236 bool result = true;
237 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
238 FilePath to_delete = path.AppendASCII(
239 GetFilenameFromEntryHashAndIndex(entry_hash, i));
240 if (!base::DeleteFile(to_delete, false)) {
241 result = false;
242 DLOG(ERROR) << "Could not delete " << to_delete.MaybeAsASCII();
245 return result;
248 // static
249 void SimpleSynchronousEntry::DoomEntry(
250 const FilePath& path,
251 const std::string& key,
252 uint64 entry_hash,
253 int* out_result) {
254 DCHECK_EQ(entry_hash, GetEntryHashKey(key));
255 bool deleted_well = DeleteFilesForEntryHash(path, entry_hash);
256 *out_result = deleted_well ? net::OK : net::ERR_FAILED;
259 // static
260 int SimpleSynchronousEntry::DoomEntrySet(
261 scoped_ptr<std::vector<uint64> > key_hashes,
262 const FilePath& path) {
263 const size_t did_delete_count = std::count_if(
264 key_hashes->begin(), key_hashes->end(), std::bind1st(
265 std::ptr_fun(SimpleSynchronousEntry::DeleteFilesForEntryHash), path));
266 return (did_delete_count == key_hashes->size()) ? net::OK : net::ERR_FAILED;
269 void SimpleSynchronousEntry::ReadData(const EntryOperationData& in_entry_op,
270 net::IOBuffer* out_buf,
271 uint32* out_crc32,
272 base::Time* out_last_used,
273 int* out_result) const {
274 DCHECK(initialized_);
275 int64 file_offset =
276 GetFileOffsetFromKeyAndDataOffset(key_, in_entry_op.offset);
277 int bytes_read = ReadPlatformFile(files_[in_entry_op.index],
278 file_offset,
279 out_buf->data(),
280 in_entry_op.buf_len);
281 if (bytes_read > 0) {
282 *out_last_used = Time::Now();
283 *out_crc32 = crc32(crc32(0L, Z_NULL, 0),
284 reinterpret_cast<const Bytef*>(out_buf->data()),
285 bytes_read);
287 if (bytes_read >= 0) {
288 *out_result = bytes_read;
289 } else {
290 *out_result = net::ERR_CACHE_READ_FAILURE;
291 Doom();
295 void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
296 net::IOBuffer* in_buf,
297 SimpleEntryStat* out_entry_stat,
298 int* out_result) const {
299 DCHECK(initialized_);
300 int index = in_entry_op.index;
301 int offset = in_entry_op.offset;
302 int buf_len = in_entry_op.buf_len;
303 int truncate = in_entry_op.truncate;
305 bool extending_by_write = offset + buf_len > out_entry_stat->data_size[index];
306 if (extending_by_write) {
307 // We are extending the file, and need to insure the EOF record is zeroed.
308 const int64 file_eof_offset = GetFileOffsetFromKeyAndDataOffset(
309 key_, out_entry_stat->data_size[index]);
310 if (!TruncatePlatformFile(files_[index], file_eof_offset)) {
311 RecordWriteResult(WRITE_RESULT_PRETRUNCATE_FAILURE);
312 Doom();
313 *out_result = net::ERR_CACHE_WRITE_FAILURE;
314 return;
317 const int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, offset);
318 if (buf_len > 0) {
319 if (WritePlatformFile(
320 files_[index], file_offset, in_buf->data(), buf_len) != buf_len) {
321 RecordWriteResult(WRITE_RESULT_WRITE_FAILURE);
322 Doom();
323 *out_result = net::ERR_CACHE_WRITE_FAILURE;
324 return;
327 if (!truncate && (buf_len > 0 || !extending_by_write)) {
328 out_entry_stat->data_size[index] =
329 std::max(out_entry_stat->data_size[index], offset + buf_len);
330 } else {
331 if (!TruncatePlatformFile(files_[index], file_offset + buf_len)) {
332 RecordWriteResult(WRITE_RESULT_TRUNCATE_FAILURE);
333 Doom();
334 *out_result = net::ERR_CACHE_WRITE_FAILURE;
335 return;
337 out_entry_stat->data_size[index] = offset + buf_len;
340 RecordWriteResult(WRITE_RESULT_SUCCESS);
341 out_entry_stat->last_used = out_entry_stat->last_modified = Time::Now();
342 *out_result = buf_len;
345 void SimpleSynchronousEntry::CheckEOFRecord(int index,
346 int32 data_size,
347 uint32 expected_crc32,
348 int* out_result) const {
349 DCHECK(initialized_);
351 SimpleFileEOF eof_record;
352 int64 file_offset = GetFileOffsetFromKeyAndDataOffset(key_, data_size);
353 if (ReadPlatformFile(files_[index],
354 file_offset,
355 reinterpret_cast<char*>(&eof_record),
356 sizeof(eof_record)) != sizeof(eof_record)) {
357 RecordCheckEOFResult(CHECK_EOF_RESULT_READ_FAILURE);
358 Doom();
359 *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE;
360 return;
363 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) {
364 RecordCheckEOFResult(CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH);
365 DLOG(INFO) << "eof record had bad magic number.";
366 Doom();
367 *out_result = net::ERR_CACHE_CHECKSUM_READ_FAILURE;
368 return;
371 const bool has_crc = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) ==
372 SimpleFileEOF::FLAG_HAS_CRC32;
373 UMA_HISTOGRAM_BOOLEAN("SimpleCache.SyncCheckEOFHasCrc", has_crc);
374 if (has_crc && eof_record.data_crc32 != expected_crc32) {
375 RecordCheckEOFResult(CHECK_EOF_RESULT_CRC_MISMATCH);
376 DLOG(INFO) << "eof record had bad crc.";
377 Doom();
378 *out_result = net::ERR_CACHE_CHECKSUM_MISMATCH;
379 return;
382 RecordCheckEOFResult(CHECK_EOF_RESULT_SUCCESS);
383 *out_result = net::OK;
386 void SimpleSynchronousEntry::Close(
387 const SimpleEntryStat& entry_stat,
388 scoped_ptr<std::vector<CRCRecord> > crc32s_to_write) {
389 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin();
390 it != crc32s_to_write->end(); ++it) {
391 SimpleFileEOF eof_record;
392 eof_record.final_magic_number = kSimpleFinalMagicNumber;
393 eof_record.flags = 0;
394 if (it->has_crc32)
395 eof_record.flags |= SimpleFileEOF::FLAG_HAS_CRC32;
396 eof_record.data_crc32 = it->data_crc32;
397 int64 file_offset = GetFileOffsetFromKeyAndDataOffset(
398 key_, entry_stat.data_size[it->index]);
399 if (WritePlatformFile(files_[it->index],
400 file_offset,
401 reinterpret_cast<const char*>(&eof_record),
402 sizeof(eof_record)) != sizeof(eof_record)) {
403 RecordCloseResult(CLOSE_RESULT_WRITE_FAILURE);
404 DLOG(INFO) << "Could not write eof record.";
405 Doom();
406 break;
408 const int64 file_size = file_offset + sizeof(eof_record);
409 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.LastClusterSize",
410 file_size % 4096, 0, 4097, 50);
411 const int64 cluster_loss = file_size % 4096 ? 4096 - file_size % 4096 : 0;
412 UMA_HISTOGRAM_PERCENTAGE("SimpleCache.LastClusterLossPercent",
413 cluster_loss * 100 / (cluster_loss + file_size));
416 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
417 bool did_close_file = ClosePlatformFile(files_[i]);
418 CHECK(did_close_file);
420 RecordCloseResult(CLOSE_RESULT_SUCCESS);
421 have_open_files_ = false;
422 delete this;
425 SimpleSynchronousEntry::SimpleSynchronousEntry(const FilePath& path,
426 const std::string& key,
427 const uint64 entry_hash)
428 : path_(path),
429 entry_hash_(entry_hash),
430 key_(key),
431 have_open_files_(false),
432 initialized_(false) {
433 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
434 files_[i] = kInvalidPlatformFileValue;
438 SimpleSynchronousEntry::~SimpleSynchronousEntry() {
439 DCHECK(!(have_open_files_ && initialized_));
440 if (have_open_files_)
441 CloseFiles();
444 bool SimpleSynchronousEntry::OpenOrCreateFiles(
445 bool create,
446 bool had_index,
447 SimpleEntryStat* out_entry_stat) {
448 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
449 FilePath filename = path_.AppendASCII(
450 GetFilenameFromEntryHashAndIndex(entry_hash_, i));
451 int flags = PLATFORM_FILE_READ | PLATFORM_FILE_WRITE;
452 if (create)
453 flags |= PLATFORM_FILE_CREATE;
454 else
455 flags |= PLATFORM_FILE_OPEN;
456 PlatformFileError error;
457 files_[i] = CreatePlatformFile(filename, flags, NULL, &error);
458 if (error != PLATFORM_FILE_OK) {
459 // TODO(ttuttle,gavinp): Remove one each of these triplets of histograms.
460 // We can calculate the third as the sum or difference of the other two.
461 if (create) {
462 RecordSyncCreateResult(CREATE_ENTRY_PLATFORM_FILE_ERROR, had_index);
463 UMA_HISTOGRAM_ENUMERATION("SimpleCache.SyncCreatePlatformFileError",
464 -error, -base::PLATFORM_FILE_ERROR_MAX);
465 if (had_index) {
466 UMA_HISTOGRAM_ENUMERATION(
467 "SimpleCache.SyncCreatePlatformFileError_WithIndex",
468 -error, -base::PLATFORM_FILE_ERROR_MAX);
469 } else {
470 UMA_HISTOGRAM_ENUMERATION(
471 "SimpleCache.SyncCreatePlatformFileError_WithoutIndex",
472 -error, -base::PLATFORM_FILE_ERROR_MAX);
474 } else {
475 RecordSyncOpenResult(OPEN_ENTRY_PLATFORM_FILE_ERROR, had_index);
476 UMA_HISTOGRAM_ENUMERATION("SimpleCache.SyncOpenPlatformFileError",
477 -error, -base::PLATFORM_FILE_ERROR_MAX);
478 if (had_index) {
479 UMA_HISTOGRAM_ENUMERATION(
480 "SimpleCache.SyncOpenPlatformFileError_WithIndex",
481 -error, -base::PLATFORM_FILE_ERROR_MAX);
482 } else {
483 UMA_HISTOGRAM_ENUMERATION(
484 "SimpleCache.SyncOpenPlatformFileError_WithoutIndex",
485 -error, -base::PLATFORM_FILE_ERROR_MAX);
488 while (--i >= 0) {
489 bool ALLOW_UNUSED did_close = ClosePlatformFile(files_[i]);
490 DLOG_IF(INFO, !did_close) << "Could not close file "
491 << filename.MaybeAsASCII();
493 return false;
497 have_open_files_ = true;
498 if (create) {
499 out_entry_stat->last_modified = out_entry_stat->last_used = Time::Now();
500 for (int i = 0; i < kSimpleEntryFileCount; ++i)
501 out_entry_stat->data_size[i] = 0;
502 } else {
503 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
504 PlatformFileInfo file_info;
505 bool success = GetPlatformFileInfo(files_[i], &file_info);
506 base::Time file_last_modified;
507 if (!success) {
508 DLOG(WARNING) << "Could not get platform file info.";
509 continue;
511 out_entry_stat->last_used = file_info.last_accessed;
512 if (simple_util::GetMTime(path_, &file_last_modified))
513 out_entry_stat->last_modified = file_last_modified;
514 else
515 out_entry_stat->last_modified = file_info.last_modified;
517 // Keep the file size in |data size_| briefly until the key is initialized
518 // properly.
519 out_entry_stat->data_size[i] = file_info.size;
523 return true;
526 void SimpleSynchronousEntry::CloseFiles() {
527 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
528 DCHECK_NE(kInvalidPlatformFileValue, files_[i]);
529 bool did_close = ClosePlatformFile(files_[i]);
530 DCHECK(did_close);
534 int SimpleSynchronousEntry::InitializeForOpen(bool had_index,
535 SimpleEntryStat* out_entry_stat) {
536 DCHECK(!initialized_);
537 if (!OpenOrCreateFiles(false, had_index, out_entry_stat))
538 return net::ERR_FAILED;
540 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
541 SimpleFileHeader header;
542 int header_read_result =
543 ReadPlatformFile(files_[i], 0, reinterpret_cast<char*>(&header),
544 sizeof(header));
545 if (header_read_result != sizeof(header)) {
546 DLOG(WARNING) << "Cannot read header from entry.";
547 RecordSyncOpenResult(OPEN_ENTRY_CANT_READ_HEADER, had_index);
548 return net::ERR_FAILED;
551 if (header.initial_magic_number != kSimpleInitialMagicNumber) {
552 // TODO(gavinp): This seems very bad; for now we log at WARNING, but we
553 // should give consideration to not saturating the log with these if that
554 // becomes a problem.
555 DLOG(WARNING) << "Magic number did not match.";
556 RecordSyncOpenResult(OPEN_ENTRY_BAD_MAGIC_NUMBER, had_index);
557 return net::ERR_FAILED;
560 if (header.version != kSimpleVersion) {
561 DLOG(WARNING) << "Unreadable version.";
562 RecordSyncOpenResult(OPEN_ENTRY_BAD_VERSION, had_index);
563 return net::ERR_FAILED;
566 scoped_ptr<char[]> key(new char[header.key_length]);
567 int key_read_result = ReadPlatformFile(files_[i], sizeof(header),
568 key.get(), header.key_length);
569 if (key_read_result != implicit_cast<int>(header.key_length)) {
570 DLOG(WARNING) << "Cannot read key from entry.";
571 RecordSyncOpenResult(OPEN_ENTRY_CANT_READ_KEY, had_index);
572 return net::ERR_FAILED;
575 key_ = std::string(key.get(), header.key_length);
576 out_entry_stat->data_size[i] =
577 GetDataSizeFromKeyAndFileSize(key_, out_entry_stat->data_size[i]);
578 if (out_entry_stat->data_size[i] < 0) {
579 // This entry can't possibly be valid, as it does not have enough space to
580 // store a valid SimpleFileEOF record.
581 return net::ERR_FAILED;
584 if (base::Hash(key.get(), header.key_length) != header.key_hash) {
585 DLOG(WARNING) << "Hash mismatch on key.";
586 RecordSyncOpenResult(OPEN_ENTRY_KEY_HASH_MISMATCH, had_index);
587 return net::ERR_FAILED;
590 RecordSyncOpenResult(OPEN_ENTRY_SUCCESS, had_index);
591 initialized_ = true;
592 return net::OK;
595 int SimpleSynchronousEntry::InitializeForCreate(
596 bool had_index,
597 SimpleEntryStat* out_entry_stat) {
598 DCHECK(!initialized_);
599 if (!OpenOrCreateFiles(true, had_index, out_entry_stat)) {
600 DLOG(WARNING) << "Could not create platform files.";
601 return net::ERR_FILE_EXISTS;
603 for (int i = 0; i < kSimpleEntryFileCount; ++i) {
604 SimpleFileHeader header;
605 header.initial_magic_number = kSimpleInitialMagicNumber;
606 header.version = kSimpleVersion;
608 header.key_length = key_.size();
609 header.key_hash = base::Hash(key_);
611 if (WritePlatformFile(files_[i], 0, reinterpret_cast<char*>(&header),
612 sizeof(header)) != sizeof(header)) {
613 DLOG(WARNING) << "Could not write headers to new cache entry.";
614 RecordSyncCreateResult(CREATE_ENTRY_CANT_WRITE_HEADER, had_index);
615 return net::ERR_FAILED;
618 if (WritePlatformFile(files_[i], sizeof(header), key_.data(),
619 key_.size()) != implicit_cast<int>(key_.size())) {
620 DLOG(WARNING) << "Could not write keys to new cache entry.";
621 RecordSyncCreateResult(CREATE_ENTRY_CANT_WRITE_KEY, had_index);
622 return net::ERR_FAILED;
625 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index);
626 initialized_ = true;
627 return net::OK;
630 void SimpleSynchronousEntry::Doom() const {
631 // TODO(gavinp): Consider if we should guard against redundant Doom() calls.
632 DeleteFilesForEntryHash(path_, entry_hash_);
635 } // namespace disk_cache