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

Side by Side Diff: services/url_response_disk_cache/url_response_disk_cache_db.cc

Issue 1276073004: Offline By Default (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Fix command line. Created 5 years, 3 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
(Empty)
1 // Copyright 2015 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 "services/url_response_disk_cache/url_response_disk_cache_db.h"
6
7 #include "base/logging.h"
8 #include "base/time/time.h"
9 #include "leveldb/comparator.h"
10 #include "leveldb/db.h"
11 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
12 #include "services/url_response_disk_cache/url_response_disk_cache_entry.mojom.h "
13
14 namespace mojo {
15 namespace {
16
17 const char kVersionKey[] = "/version";
18
19 union VersionData {
20 uint64_t version;
21 char data[sizeof(uint64_t)];
22 };
23
24 // TODO(darin): These Serialize / Deserialize methods should not live here.
25 // They use private details of the bindings system. Instead, we should provide
26 // these as helper functions under mojo/public/cpp/bindings/.
27
28 template <typename T>
29 void Serialize(T input, std::string* output) {
30 typedef typename mojo::internal::WrapperTraits<T>::DataType DataType;
31 size_t size = GetSerializedSize_(input);
32
33 output->clear();
34 output->resize(size);
35
36 mojo::internal::FixedBuffer buf;
37 buf.Initialize(&output->at(0), size);
38
39 DataType data_type;
40 Serialize_(input.Pass(), &buf, &data_type);
41 std::vector<Handle> handles;
42 data_type->EncodePointersAndHandles(&handles);
43 }
44
45 template <typename T>
46 bool Deserialize(void* data, size_t size, T* output) {
47 typedef typename mojo::internal::WrapperTraits<T>::DataType DataType;
48 mojo::internal::BoundsChecker bounds_checker(data, size, 0);
49 if (!std::remove_pointer<DataType>::type::Validate(data, &bounds_checker)) {
50 return false;
51 }
52 DataType data_type = reinterpret_cast<DataType>(data);
53 std::vector<Handle> handles;
54 data_type->DecodePointersAndHandles(&handles);
55 Deserialize_(data_type, output);
56 return true;
57 }
58
59 template <typename T>
60 bool Deserialize(std::string s, T* output) {
61 return Deserialize(&s.at(0), s.size(), output);
62 }
63
64 template <typename T>
65 bool Deserialize(const leveldb::Slice& s, T* output) {
66 return Deserialize(s.ToString(), output);
67 }
68
69 bool IsMetaDataKey(const leveldb::Slice& s) {
ppi 2015/09/08 11:56:24 Please describe what meta data key is, maybe give
qsr 2015/09/08 13:35:22 Comment added.
70 return s.size() != 0 && s[0] == '/';
71 }
72
73 class KeyComparator : public leveldb::Comparator {
74 public:
75 int Compare(const leveldb::Slice& s1,
76 const leveldb::Slice& s2) const override {
77 if (IsMetaDataKey(s1) != IsMetaDataKey(s2)) {
78 if (IsMetaDataKey(s1))
79 return -1;
80 return 1;
81 }
82
83 if (IsMetaDataKey(s1))
84 return leveldb::BytewiseComparator()->Compare(s1, s2);
85
86 mojo::LevelDBKeyPtr k1, k2;
87 bool result = Deserialize(s1, &k1) && Deserialize(s2, &k2);
88 DCHECK(result);
89 if (k1->request_origin.get() < k2->request_origin.get())
90 return -1;
91 if (k1->request_origin.get() > k2->request_origin.get())
92 return +1;
93 if (k1->url.get() < k2->url.get())
94 return -1;
95 if (k1->url.get() > k2->url.get())
96 return +1;
97 if (k1->timestamp < k2->timestamp)
98 return 1;
99 if (k1->timestamp > k2->timestamp)
100 return -1;
101 return 0;
102 }
103
104 const char* Name() const override { return "KeyComparator"; }
105 void FindShortestSeparator(std::string*,
106 const leveldb::Slice&) const override {}
107 void FindShortSuccessor(std::string*) const override {}
108 };
109
110 class DBIterator : public DBReader::Iterator {
111 public:
112 DBIterator(linked_ptr<leveldb::DB> db, const leveldb::ReadOptions& options);
113
114 private:
115 // Implementation of DBReader::Iterator:
116 bool HasNext() override;
117 void GetNext(LevelDBKeyPtr* key, CacheEntryPtr* entry) override;
118
119 linked_ptr<leveldb::DB> db_;
120 scoped_ptr<leveldb::Iterator> it_;
121 };
122
123 class DBReaderImpl : public DBReader {
124 public:
125 DBReaderImpl(linked_ptr<leveldb::DB> db, const leveldb::ReadOptions& options);
126 ~DBReaderImpl() override;
127
128 private:
129 // Implementation of DBReader:
130 scoped_ptr<Iterator> Iterate() override;
131 CacheEntryPtr Get(const std::string& request_origin,
132 const std::string& url) override;
133
134 linked_ptr<leveldb::DB> db_;
135 leveldb::ReadOptions options_;
136 };
137
138 class DBSnapshot : public DBReader {
139 public:
140 DBSnapshot(linked_ptr<leveldb::DB> db);
141 ~DBSnapshot() override;
142
143 private:
144 // Implementation of DBReader:
145 scoped_ptr<Iterator> Iterate() override;
146 CacheEntryPtr Get(const std::string& request_origin,
147 const std::string& url) override;
148
149 linked_ptr<leveldb::DB> db_;
150 leveldb::ReadOptions options_;
151 scoped_ptr<DBReader> db_reader_;
152 };
153
154 DBIterator::DBIterator(linked_ptr<leveldb::DB> db,
155 const leveldb::ReadOptions& options)
156 : db_(db) {
157 it_.reset(db_->NewIterator(options));
158 it_->SeekToFirst();
159 }
160
161 bool DBIterator::HasNext() {
162 while (it_->Valid() && IsMetaDataKey(it_->key())) {
163 it_->Next();
164 }
165 return it_->Valid();
166 }
167
168 void DBIterator::GetNext(LevelDBKeyPtr* key, CacheEntryPtr* entry) {
169 DCHECK(it_->Valid());
170 if (key)
171 Deserialize(it_->key(), key);
172 if (entry)
173 Deserialize(it_->value(), entry);
174 it_->Next();
175 }
176
177 DBReaderImpl::DBReaderImpl(linked_ptr<leveldb::DB> db,
178 const leveldb::ReadOptions& options)
179 : db_(db), options_(options) {}
180
181 // virtual
182 DBReaderImpl::~DBReaderImpl() {}
183
184 scoped_ptr<DBReader::Iterator> DBReaderImpl::Iterate() {
185 return make_scoped_ptr(new DBIterator(db_, options_));
186 }
187
188 CacheEntryPtr DBReaderImpl::Get(const std::string& request_origin,
189 const std::string& url) {
190 LevelDBKeyPtr key = LevelDBKey::New();
191 key->request_origin = request_origin;
192 key->url = url;
193 key->timestamp = std::numeric_limits<int64>::max();
194 std::string key_string;
195 Serialize(key.Pass(), &key_string);
196 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options_));
197 it->Seek(key_string);
198 CacheEntryPtr result;
199 if (it->Valid()) {
200 Deserialize(it->key(), &key);
201 if (key->request_origin == request_origin && key->url == url) {
202 Deserialize(it->value(), &result);
203 }
204 }
205 return result.Pass();
206 }
207
208 DBSnapshot::DBSnapshot(linked_ptr<leveldb::DB> db) : db_(db) {
209 options_.snapshot = db_->GetSnapshot();
210 db_reader_.reset(new DBReaderImpl(db, options_));
211 }
212
213 // virtual
214 DBSnapshot::~DBSnapshot() {
215 db_->ReleaseSnapshot(options_.snapshot);
216 }
217
218 scoped_ptr<DBReader::Iterator> DBSnapshot::Iterate() {
219 return db_reader_->Iterate();
220 }
221
222 CacheEntryPtr DBSnapshot::Get(const std::string& request_origin,
223 const std::string& url) {
224 return db_reader_->Get(request_origin, url);
225 }
226
227 } // namespace
228
229 URLResponseDiskCacheDB::URLResponseDiskCacheDB(const base::FilePath& db_path)
230 : comparator_(new KeyComparator) {
231 leveldb::DB* db;
232 leveldb::Options options;
233 options.create_if_missing = true;
234 options.comparator = comparator_.get();
235 leveldb::Status status = leveldb::DB::Open(options, db_path.value(), &db);
236 DCHECK(status.ok()) << status.ToString();
237 db_.reset(db);
238 db_reader_.reset(new DBReaderImpl(db_, leveldb::ReadOptions()));
239 }
240
241 // virtual
242 URLResponseDiskCacheDB::~URLResponseDiskCacheDB() {}
243
244 scoped_ptr<DBReader::Iterator> URLResponseDiskCacheDB::Iterate() {
245 return db_reader_->Iterate();
246 }
247
248 CacheEntryPtr URLResponseDiskCacheDB::Get(const std::string& request_origin,
249 const std::string& url) {
250 return db_reader_->Get(request_origin, url);
251 }
252
253 uint64_t URLResponseDiskCacheDB::GetVersion() {
254 std::string value;
255 leveldb::Status status =
256 db_->Get(leveldb::ReadOptions(), kVersionKey, &value);
257 if (status.IsNotFound())
258 return 0u;
259 DCHECK(status.ok());
260 const VersionData* version_data =
261 reinterpret_cast<const VersionData*>(value.data());
262 return version_data->version;
263 }
264
265 void URLResponseDiskCacheDB::SetVersion(uint64_t version) {
266 VersionData version_data;
267 version_data.version = version;
268 leveldb::Status status =
269 db_->Put(leveldb::WriteOptions(), kVersionKey,
270 leveldb::Slice(version_data.data, sizeof(version)));
271 DCHECK(status.ok());
272 }
273
274 void URLResponseDiskCacheDB::Put(const std::string& request_origin,
275 const std::string& url,
276 CacheEntryPtr entry) {
277 LevelDBKeyPtr key = LevelDBKey::New();
278 key->request_origin = request_origin;
279 key->url = url;
280 key->timestamp = base::Time::Now().ToInternalValue();
281 std::string key_string;
282 Serialize(key.Pass(), &key_string);
283 std::string entry_string;
284 Serialize(entry.Pass(), &entry_string);
285 leveldb::Status s =
286 db_->Put(leveldb::WriteOptions(), key_string, entry_string);
287 DCHECK(s.ok());
288 }
289
290 void URLResponseDiskCacheDB::Delete(LevelDBKeyPtr key) {
291 std::string key_string;
292 Serialize(key.Pass(), &key_string);
293 leveldb::Status s = db_->Delete(leveldb::WriteOptions(), key_string);
294 DCHECK(s.ok());
295 }
296
297 scoped_ptr<DBReader> URLResponseDiskCacheDB::GetSnapshot() {
298 return make_scoped_ptr(new DBSnapshot(db_));
299 }
300
301 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698