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

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: Follow review 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/memory/scoped_ptr.h"
9 #include "base/time/time.h"
10 #include "leveldb/comparator.h"
11 #include "leveldb/db.h"
12 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
13 #include "services/url_response_disk_cache/url_response_disk_cache_entry.mojom.h "
14
15 namespace mojo {
16 namespace {
17
18 // List of keys for metadata. All metadata keys must start with a '\1'
19 // character.
20 const char kVersionKey[] = "\1version";
21
22 // TODO(darin): These Serialize / Deserialize methods should not live here.
23 // They use private details of the bindings system. Instead, we should provide
24 // these as helper functions under mojo/public/cpp/bindings/.
25
26 template <typename T>
27 void Serialize(T input, std::string* output) {
28 typedef typename mojo::internal::WrapperTraits<T>::DataType DataType;
29 size_t size = GetSerializedSize_(input);
30
31 output->clear();
32 output->resize(size);
33
34 mojo::internal::FixedBuffer buf;
35 buf.Initialize(&output->at(0), size);
36
37 DataType data_type;
38 Serialize_(input.Pass(), &buf, &data_type);
39 std::vector<Handle> handles;
40 data_type->EncodePointersAndHandles(&handles);
41 }
42
43 template <typename T>
44 bool Deserialize(void* data, size_t size, T* output) {
45 typedef typename mojo::internal::WrapperTraits<T>::DataType DataType;
46 mojo::internal::BoundsChecker bounds_checker(data, size, 0);
47 if (!std::remove_pointer<DataType>::type::Validate(data, &bounds_checker)) {
48 return false;
49 }
50 DataType data_type = reinterpret_cast<DataType>(data);
51 std::vector<Handle> handles;
52 data_type->DecodePointersAndHandles(&handles);
53 Deserialize_(data_type, output);
54 return true;
55 }
56
57 template <typename T>
58 bool Deserialize(std::string s, T* output) {
59 return Deserialize(&s.at(0), s.size(), output);
60 }
61
62 template <typename T>
63 bool Deserialize(const leveldb::Slice& s, T* output) {
64 return Deserialize(s.ToString(), output);
65 }
66
67 // Returns whether the key is for a metadata entry. Metadata entries are
68 // declared at the start of this file.
69 bool IsMetaDataKey(const leveldb::Slice& s) {
70 return s.size() != 0 && s[0] == '\1';
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::CacheKeyPtr 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 } // namespace
111
112 URLResponseDiskCacheDB::Iterator::Iterator(linked_ptr<leveldb::DB> db)
113 : db_(db) {
114 it_.reset(db_->NewIterator(leveldb::ReadOptions()));
115 it_->SeekToFirst();
116 }
117
118 URLResponseDiskCacheDB::Iterator::~Iterator() {}
119
120 bool URLResponseDiskCacheDB::Iterator::HasNext() {
121 while (it_->Valid() && IsMetaDataKey(it_->key())) {
122 it_->Next();
123 }
124 return it_->Valid();
125 }
126
127 void URLResponseDiskCacheDB::Iterator::GetNext(CacheKeyPtr* key,
ppi 2015/09/15 15:21:22 Do you want to either document that HasNext() need
qsr 2015/09/16 11:46:37 Done.
128 CacheEntryPtr* entry) {
129 DCHECK(it_->Valid());
130 if (key)
131 Deserialize(it_->key(), key);
132 if (entry)
133 Deserialize(it_->value(), entry);
134 it_->Next();
135 }
136
137 URLResponseDiskCacheDB::URLResponseDiskCacheDB(const base::FilePath& db_path)
138 : comparator_(new KeyComparator) {
139 leveldb::DB* db;
140 leveldb::Options options;
141 options.create_if_missing = true;
142 options.comparator = comparator_.get();
143 leveldb::Status status = leveldb::DB::Open(options, db_path.value(), &db);
144 DCHECK(status.ok()) << status.ToString();
145 db_.reset(db);
146 }
147
148 uint64_t URLResponseDiskCacheDB::GetVersion() {
149 std::string value;
150 leveldb::Status status =
151 db_->Get(leveldb::ReadOptions(), kVersionKey, &value);
152 if (status.IsNotFound())
153 return 0u;
154 DCHECK(status.ok());
155 uint64_t version;
156 memcpy(&version, value.data(), sizeof(version));
ppi 2015/09/15 15:21:22 should we include <string.h> for memcpy?
qsr 2015/09/16 11:46:37 Done.
157 return version;
158 }
159
160 void URLResponseDiskCacheDB::SetVersion(uint64_t version) {
161 leveldb::Status status = db_->Put(
162 leveldb::WriteOptions(), kVersionKey,
163 leveldb::Slice(reinterpret_cast<char*>(&version), sizeof(version)));
164 DCHECK(status.ok());
165 }
166
167 void URLResponseDiskCacheDB::PutNewest(const std::string& request_origin,
168 const std::string& url,
169 CacheEntryPtr entry) {
170 CacheKeyPtr key = CacheKey::New();
171 key->request_origin = request_origin;
172 key->url = url;
173 key->timestamp = base::Time::Now().ToInternalValue();
174 std::string key_string;
175 Serialize(key.Pass(), &key_string);
176 std::string entry_string;
177 Serialize(entry.Pass(), &entry_string);
178 leveldb::Status s =
179 db_->Put(leveldb::WriteOptions(), key_string, entry_string);
180 DCHECK(s.ok());
181 }
182
183 CacheEntryPtr URLResponseDiskCacheDB::GetNewest(
184 const std::string& request_origin,
185 const std::string& url) {
186 CacheKeyPtr key = CacheKey::New();
187 key->request_origin = request_origin;
188 key->url = url;
189 key->timestamp = std::numeric_limits<int64>::max();
190 std::string key_string;
191 Serialize(key.Pass(), &key_string);
192 scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
193 it->Seek(key_string);
194 CacheEntryPtr result;
195 if (it->Valid()) {
196 Deserialize(it->key(), &key);
197 if (key->request_origin == request_origin && key->url == url) {
198 Deserialize(it->value(), &result);
199 }
200 }
201 return result.Pass();
202 }
203
204 void URLResponseDiskCacheDB::Delete(CacheKeyPtr key) {
205 std::string key_string;
206 Serialize(key.Pass(), &key_string);
207 leveldb::Status s = db_->Delete(leveldb::WriteOptions(), key_string);
208 DCHECK(s.ok());
209 }
210
211 scoped_ptr<URLResponseDiskCacheDB::Iterator> URLResponseDiskCacheDB::Iterate() {
212 return make_scoped_ptr(new Iterator(db_));
213 }
214
215 URLResponseDiskCacheDB::~URLResponseDiskCacheDB() {}
216
217 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698