OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "net/disk_cache/simple/simple_index_file.h" | |
6 | |
7 #include "base/file_util.h" | |
8 #include "base/hash.h" | |
9 #include "base/logging.h" | |
10 #include "base/pickle.h" | |
11 #include "net/disk_cache/simple/simple_disk_format.h" | |
12 #include "net/disk_cache/simple/simple_index_util.h" | |
13 #include "third_party/zlib/zlib.h" | |
14 | |
15 namespace { | |
16 | |
17 const uint64 kMaxEntiresInIndex = 100000000; | |
18 | |
19 uint32 CalculatePickleCRC(const Pickle& pickle) { | |
20 return crc32(crc32(0, Z_NULL, 0), | |
21 reinterpret_cast<const Bytef*>(pickle.payload()), | |
22 pickle.payload_size()); | |
23 } | |
24 | |
25 } // namespace | |
26 | |
27 namespace disk_cache { | |
28 | |
29 SimpleIndexFile::IndexMetadata::IndexMetadata() : | |
30 magic_number_(kSimpleIndexMagicNumber), | |
31 version_(kSimpleVersion), | |
32 number_of_entries_(0), | |
33 cache_size_(0) {} | |
34 | |
35 SimpleIndexFile::IndexMetadata::IndexMetadata( | |
36 uint64 number_of_entries, uint64 cache_size) : | |
37 magic_number_(kSimpleIndexMagicNumber), | |
38 version_(kSimpleVersion), | |
39 number_of_entries_(number_of_entries), | |
40 cache_size_(cache_size) {} | |
41 | |
42 void SimpleIndexFile::IndexMetadata::Serialize(Pickle* pickle) const { | |
43 DCHECK(pickle); | |
44 pickle->WriteUInt64(magic_number_); | |
45 pickle->WriteUInt32(version_); | |
46 pickle->WriteUInt64(number_of_entries_); | |
47 pickle->WriteUInt64(cache_size_); | |
48 } | |
49 | |
50 bool SimpleIndexFile::IndexMetadata::Deserialize(PickleIterator* it) { | |
51 DCHECK(it); | |
52 return it->ReadUInt64(&magic_number_) && | |
53 it->ReadUInt32(&version_) && | |
54 it->ReadUInt64(&number_of_entries_)&& | |
55 it->ReadUInt64(&cache_size_); | |
56 } | |
57 | |
58 bool SimpleIndexFile::IndexMetadata::CheckIndexMetadata() { | |
59 return number_of_entries_ <= kMaxEntiresInIndex && | |
60 magic_number_ == disk_cache::kSimpleIndexMagicNumber && | |
61 version_ == disk_cache::kSimpleVersion; | |
62 } | |
63 | |
64 // static | |
65 scoped_ptr<EntrySet> SimpleIndexFile::LoadFromDisk( | |
66 const base::FilePath& index_filename) { | |
67 std::string contents; | |
68 if(!file_util::ReadFileToString(index_filename, &contents)) { | |
69 LOG(WARNING) << "Could not read Simple Index file."; | |
70 return scoped_ptr<EntrySet>(NULL); | |
71 } | |
72 | |
73 return SimpleIndexFile::Deserialize(contents.data(), contents.size()); | |
74 } | |
75 | |
76 // static | |
77 scoped_ptr<EntrySet> SimpleIndexFile::Deserialize(const char* data, | |
gavinp
2013/04/15 19:27:46
Method ordering: methods in .cc should be in the s
| |
78 int data_len) { | |
79 Pickle pickle(data, data_len); | |
80 PickleIterator pickle_it(pickle); | |
81 | |
82 SimpleIndexFile::PickleHeader* header_p = | |
83 pickle.headerT<SimpleIndexFile::PickleHeader>(); | |
84 const uint32 crc_read = header_p->crc; | |
85 const uint32 crc_calculated = CalculatePickleCRC(pickle); | |
86 | |
87 if (crc_read != crc_calculated) { | |
88 LOG(WARNING) << "Invalid CRC in Simple Index file."; | |
89 return scoped_ptr<EntrySet>(NULL); | |
90 } | |
91 | |
92 SimpleIndexFile::IndexMetadata index_metadata; | |
93 if (!index_metadata.Deserialize(&pickle_it)) { | |
94 LOG(ERROR) << "Invalid index_metadata on Simple Cache Index."; | |
95 return scoped_ptr<EntrySet>(NULL); | |
96 } | |
97 | |
98 if (!index_metadata.CheckIndexMetadata()) { | |
99 LOG(ERROR) << "Invalid index_metadata on Simple Cache Index."; | |
100 return scoped_ptr<EntrySet>(NULL); | |
101 } | |
102 | |
103 scoped_ptr<EntrySet> index_file_entries(new EntrySet()); | |
104 while (index_file_entries->size() < index_metadata.GetNumberOfEntries()) { | |
105 EntryMetadata entry_metadata; | |
106 if (!entry_metadata.Deserialize(&pickle_it)) { | |
107 LOG(WARNING) << "Invalid EntryMetadata in Simple Index file."; | |
108 return scoped_ptr<EntrySet>(NULL); | |
109 } | |
110 InsertInEntrySet(entry_metadata, | |
111 index_file_entries.get()); | |
112 } | |
113 | |
114 return index_file_entries.Pass(); | |
115 } | |
116 | |
117 // static | |
118 scoped_ptr<Pickle> SimpleIndexFile::Serialize( | |
119 const SimpleIndexFile::IndexMetadata& index_metadata, | |
120 const EntrySet& entries) { | |
121 scoped_ptr<Pickle> pickle(new Pickle(sizeof(SimpleIndexFile::PickleHeader))); | |
122 | |
123 index_metadata.Serialize(pickle.get()); | |
124 for (EntrySet::const_iterator it = entries.begin(); | |
125 it != entries.end(); ++it) { | |
126 it->second.Serialize(pickle.get()); | |
127 } | |
128 SimpleIndexFile::PickleHeader* header_p = | |
129 pickle->headerT<SimpleIndexFile::PickleHeader>(); | |
130 header_p->crc = CalculatePickleCRC(*pickle); | |
131 return pickle.Pass(); | |
132 } | |
133 | |
134 // static | |
135 void SimpleIndexFile::WriteToDisk(const base::FilePath& index_filename, | |
136 const Pickle& pickle) { | |
137 const base::FilePath temp_filename = | |
138 index_filename.DirName().AppendASCII("index_temp"); | |
139 int bytes_written = file_util::WriteFile( | |
140 temp_filename, | |
141 reinterpret_cast<const char*>(pickle.data()), | |
142 pickle.size()); | |
143 DCHECK_EQ(bytes_written, implicit_cast<int>(pickle.size())); | |
144 if (bytes_written != static_cast<int>(pickle.size())) { | |
145 // TODO(felipeg): Add better error handling. | |
146 LOG(ERROR) << "Could not write Simple Cache index to temporary file: " | |
147 << temp_filename.value(); | |
148 file_util::Delete(temp_filename, /* recursive = */ false); | |
149 return; | |
150 } | |
151 // Swap temp and index_file. | |
152 bool result = file_util::ReplaceFile(temp_filename, index_filename); | |
153 DCHECK(result); | |
154 } | |
155 | |
156 } // namespace disk_cache | |
OLD | NEW |