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