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

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: Add missing explicits. 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 <string.h>
8
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/time/time.h"
12 #include "leveldb/comparator.h"
13 #include "leveldb/db.h"
14 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
15 #include "services/url_response_disk_cache/url_response_disk_cache_entry.mojom.h "
16
17 namespace mojo {
18 namespace {
19
20 // List of keys for metadata. All metadata keys must start with a '\1'
21 // character.
22 const char kVersionKey[] = "\1version";
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 // Returns whether the key is for a metadata entry. Metadata entries are
70 // declared at the start of this file.
71 bool IsMetaDataKey(const leveldb::Slice& s) {
72 return s.size() != 0 && s[0] == '\1';
73 }
74
75 class KeyComparator : public leveldb::Comparator {
76 public:
77 int Compare(const leveldb::Slice& s1,
78 const leveldb::Slice& s2) const override {
79 if (IsMetaDataKey(s1) != IsMetaDataKey(s2)) {
80 if (IsMetaDataKey(s1))
81 return -1;
82 return 1;
83 }
84
85 if (IsMetaDataKey(s1))
86 return leveldb::BytewiseComparator()->Compare(s1, s2);
87
88 mojo::CacheKeyPtr k1, k2;
89 bool result = Deserialize(s1, &k1) && Deserialize(s2, &k2);
90 DCHECK(result);
91 if (k1->request_origin.get() < k2->request_origin.get())
92 return -1;
93 if (k1->request_origin.get() > k2->request_origin.get())
94 return +1;
95 if (k1->url.get() < k2->url.get())
96 return -1;
97 if (k1->url.get() > k2->url.get())
98 return +1;
99 if (k1->timestamp < k2->timestamp)
100 return 1;
101 if (k1->timestamp > k2->timestamp)
102 return -1;
103 return 0;
104 }
105
106 const char* Name() const override { return "KeyComparator"; }
107 void FindShortestSeparator(std::string*,
108 const leveldb::Slice&) const override {}
109 void FindShortSuccessor(std::string*) const override {}
110 };
111
112 } // namespace
113
114 URLResponseDiskCacheDB::Iterator::Iterator(linked_ptr<leveldb::DB> db)
115 : db_(db) {
116 it_.reset(db_->NewIterator(leveldb::ReadOptions()));
117 it_->SeekToFirst();
118 }
119
120 URLResponseDiskCacheDB::Iterator::~Iterator() {}
121
122 bool URLResponseDiskCacheDB::Iterator::HasNext() {
123 while (it_->Valid() && IsMetaDataKey(it_->key())) {
124 it_->Next();
125 }
126 return it_->Valid();
127 }
128
129 void URLResponseDiskCacheDB::Iterator::GetNext(CacheKeyPtr* key,
130 CacheEntryPtr* entry) {
131 // Calling HasNext() to ensure metadata are skipped.
132 bool has_next = HasNext();
133 DCHECK(has_next);
134 if (key)
135 Deserialize(it_->key(), key);
136 if (entry)
137 Deserialize(it_->value(), entry);
138 it_->Next();
139 }
140
141 URLResponseDiskCacheDB::URLResponseDiskCacheDB(const base::FilePath& db_path)
142 : comparator_(new KeyComparator) {
143 leveldb::DB* db;
144 leveldb::Options options;
145 options.create_if_missing = true;
146 options.comparator = comparator_.get();
147 leveldb::Status status = leveldb::DB::Open(options, db_path.value(), &db);
148 DCHECK(status.ok()) << status.ToString();
149 db_.reset(db);
150 }
151
152 uint64_t URLResponseDiskCacheDB::GetVersion() {
153 std::string value;
154 leveldb::Status status =
155 db_->Get(leveldb::ReadOptions(), kVersionKey, &value);
156 if (status.IsNotFound())
157 return 0u;
158 DCHECK(status.ok());
159 uint64_t version;
160 memcpy(&version, value.data(), sizeof(version));
161 return version;
162 }
163
164 void URLResponseDiskCacheDB::SetVersion(uint64_t version) {
165 leveldb::Status status = db_->Put(
166 leveldb::WriteOptions(), kVersionKey,
167 leveldb::Slice(reinterpret_cast<char*>(&version), sizeof(version)));
168 DCHECK(status.ok());
169 }
170
171 void URLResponseDiskCacheDB::PutNew(const std::string& request_origin,
172 const std::string& url,
173 CacheEntryPtr entry) {
174 CacheKeyPtr key = CacheKey::New();
175 key->request_origin = request_origin;
176 key->url = url;
177 key->timestamp = base::Time::Now().ToInternalValue();
178 std::string key_string;
179 Serialize(key.Pass(), &key_string);
180 std::string entry_string;
181 Serialize(entry.Pass(), &entry_string);
182 leveldb::Status s =
183 db_->Put(leveldb::WriteOptions(), key_string, entry_string);
184 DCHECK(s.ok());
185 }
186
187 CacheEntryPtr URLResponseDiskCacheDB::GetNewest(
188 const std::string& request_origin,
189 const std::string& url) {
190 CacheKeyPtr key = CacheKey::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(leveldb::ReadOptions()));
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 void URLResponseDiskCacheDB::Delete(CacheKeyPtr key) {
209 std::string key_string;
210 Serialize(key.Pass(), &key_string);
211 leveldb::Status s = db_->Delete(leveldb::WriteOptions(), key_string);
212 DCHECK(s.ok());
213 }
214
215 scoped_ptr<URLResponseDiskCacheDB::Iterator>
216 URLResponseDiskCacheDB::GetIterator() {
217 return make_scoped_ptr(new Iterator(db_));
218 }
219
220 URLResponseDiskCacheDB::~URLResponseDiskCacheDB() {}
221
222 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698