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

Side by Side Diff: components/ntp_snippets/ntp_snippets_database.cc

Issue 2047713002: [NTP Snippets] Cache images in a LevelDB (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@protodb_get
Patch Set: add TODOs Created 4 years, 6 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/ntp_snippets/ntp_snippets_database.h" 5 #include "components/ntp_snippets/ntp_snippets_database.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "components/leveldb_proto/proto_database_impl.h" 10 #include "components/leveldb_proto/proto_database_impl.h"
11 #include "components/ntp_snippets/proto/ntp_snippets.pb.h" 11 #include "components/ntp_snippets/proto/ntp_snippets.pb.h"
12 12
13 using leveldb_proto::ProtoDatabaseImpl; 13 using leveldb_proto::ProtoDatabaseImpl;
14 14
15 namespace { 15 namespace {
16 // Statistics are logged to UMA with this string as part of histogram name. They 16 // Statistics are logged to UMA with this string as part of histogram name. They
17 // can all be found under LevelDB.*.NTPSnippets. Changing this needs to 17 // can all be found under LevelDB.*.NTPSnippets. Changing this needs to
18 // synchronize with histograms.xml, AND will also become incompatible with older 18 // synchronize with histograms.xml, AND will also become incompatible with older
19 // browsers still reporting the previous values. 19 // browsers still reporting the previous values.
20 const char kDatabaseUMAClientName[] = "NTPSnippets"; 20 const char kDatabaseUMAClientName[] = "NTPSnippets";
21 const char kImageDatabaseUMAClientName[] = "NTPSnippetImages";
22
23 const char kSnippetDatabaseFolder[] = "snippets";
24 const char kImageDatabaseFolder[] = "images";
21 } 25 }
22 26
23 namespace ntp_snippets { 27 namespace ntp_snippets {
24 28
25 NTPSnippetsDatabase::NTPSnippetsDatabase( 29 NTPSnippetsDatabase::NTPSnippetsDatabase(
26 const base::FilePath& database_dir, 30 const base::FilePath& database_dir,
27 scoped_refptr<base::SequencedTaskRunner> file_task_runner) 31 scoped_refptr<base::SequencedTaskRunner> file_task_runner)
28 : database_( 32 : database_(
29 new ProtoDatabaseImpl<SnippetProto>(std::move(file_task_runner))), 33 new ProtoDatabaseImpl<SnippetProto>(file_task_runner)),
30 database_initialized_(false), 34 database_initialized_(false),
35 image_database_(
36 new ProtoDatabaseImpl<SnippetImageProto>(file_task_runner)),
37 image_database_initialized_(false),
31 weak_ptr_factory_(this) { 38 weak_ptr_factory_(this) {
32 database_->Init(kDatabaseUMAClientName, database_dir, 39 base::FilePath snippet_dir = database_dir.AppendASCII(kSnippetDatabaseFolder);
40 database_->Init(kDatabaseUMAClientName, snippet_dir,
33 base::Bind(&NTPSnippetsDatabase::OnDatabaseInited, 41 base::Bind(&NTPSnippetsDatabase::OnDatabaseInited,
34 weak_ptr_factory_.GetWeakPtr())); 42 weak_ptr_factory_.GetWeakPtr()));
43
44 base::FilePath image_dir = database_dir.AppendASCII(kImageDatabaseFolder);
45 image_database_->Init(kImageDatabaseUMAClientName, image_dir,
46 base::Bind(&NTPSnippetsDatabase::OnImageDatabaseInited,
47 weak_ptr_factory_.GetWeakPtr()));
35 } 48 }
36 49
37 NTPSnippetsDatabase::~NTPSnippetsDatabase() {} 50 NTPSnippetsDatabase::~NTPSnippetsDatabase() {}
38 51
39 void NTPSnippetsDatabase::Load(const SnippetsLoadedCallback& callback) { 52 bool NTPSnippetsDatabase::IsInitialized() const {
40 if (database_ && database_initialized_) 53 return database_ && database_initialized_ && image_database_ &&
41 LoadImpl(callback); 54 image_database_initialized_;
42 else
43 pending_load_callbacks_.emplace_back(callback);
44 } 55 }
45 56
46 void NTPSnippetsDatabase::Save(const NTPSnippet& snippet) { 57 void NTPSnippetsDatabase::LoadSnippets(const SnippetsCallback& callback) {
58 if (IsInitialized())
59 LoadSnippetsImpl(callback);
60 else
61 pending_snippets_callbacks_.emplace_back(callback);
62 }
63
64 void NTPSnippetsDatabase::SaveSnippet(const NTPSnippet& snippet) {
47 std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector()); 65 std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector());
48 entries_to_save->emplace_back(snippet.id(), snippet.ToProto()); 66 entries_to_save->emplace_back(snippet.id(), snippet.ToProto());
49 SaveImpl(std::move(entries_to_save)); 67 SaveSnippetsImpl(std::move(entries_to_save));
50 } 68 }
51 69
52 void NTPSnippetsDatabase::Save(const NTPSnippet::PtrVector& snippets) { 70 void NTPSnippetsDatabase::SaveSnippets(const NTPSnippet::PtrVector& snippets) {
53 std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector()); 71 std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector());
54 for (const std::unique_ptr<NTPSnippet>& snippet : snippets) 72 for (const std::unique_ptr<NTPSnippet>& snippet : snippets)
55 entries_to_save->emplace_back(snippet->id(), snippet->ToProto()); 73 entries_to_save->emplace_back(snippet->id(), snippet->ToProto());
56 SaveImpl(std::move(entries_to_save)); 74 SaveSnippetsImpl(std::move(entries_to_save));
57 } 75 }
58 76
59 void NTPSnippetsDatabase::Delete(const std::string& snippet_id) { 77 void NTPSnippetsDatabase::DeleteSnippet(const std::string& snippet_id) {
60 DeleteImpl(base::WrapUnique(new std::vector<std::string>(1, snippet_id))); 78 DeleteSnippetsImpl(
79 base::WrapUnique(new std::vector<std::string>(1, snippet_id)));
61 } 80 }
62 81
63 void NTPSnippetsDatabase::Delete(const NTPSnippet::PtrVector& snippets) { 82 void NTPSnippetsDatabase::DeleteSnippets(
83 const NTPSnippet::PtrVector& snippets) {
64 std::unique_ptr<std::vector<std::string>> keys_to_remove( 84 std::unique_ptr<std::vector<std::string>> keys_to_remove(
65 new std::vector<std::string>()); 85 new std::vector<std::string>());
66 for (const std::unique_ptr<NTPSnippet>& snippet : snippets) 86 for (const std::unique_ptr<NTPSnippet>& snippet : snippets)
67 keys_to_remove->emplace_back(snippet->id()); 87 keys_to_remove->emplace_back(snippet->id());
68 DeleteImpl(std::move(keys_to_remove)); 88 DeleteSnippetsImpl(std::move(keys_to_remove));
89 }
90
91 void NTPSnippetsDatabase::LoadImage(const std::string& snippet_id,
92 const SnippetImageCallback& callback) {
93 if (IsInitialized())
94 LoadImageImpl(snippet_id, callback);
95 else
96 pending_image_callbacks_.emplace_back(snippet_id, callback);
97 }
98
99 void NTPSnippetsDatabase::SaveImage(const std::string& snippet_id,
100 const std::string& image_data) {
101 // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()).
102 if (!IsInitialized())
103 return;
104
105 SnippetImageProto image_proto;
106 image_proto.set_data(image_data);
107
108 std::unique_ptr<ImageKeyEntryVector> entries_to_save(
109 new ImageKeyEntryVector());
110 entries_to_save->emplace_back(snippet_id, std::move(image_proto));
111
112 image_database_->UpdateEntries(
113 std::move(entries_to_save),
114 base::WrapUnique(new std::vector<std::string>()),
115 base::Bind(&NTPSnippetsDatabase::OnImageDatabaseSaved,
116 weak_ptr_factory_.GetWeakPtr()));
117 }
118
119 void NTPSnippetsDatabase::DeleteImage(const std::string& snippet_id) {
120 DeleteImagesImpl(
121 base::WrapUnique(new std::vector<std::string>(1, snippet_id)));
69 } 122 }
70 123
71 void NTPSnippetsDatabase::OnDatabaseInited(bool success) { 124 void NTPSnippetsDatabase::OnDatabaseInited(bool success) {
72 DCHECK(!database_initialized_); 125 DCHECK(!database_initialized_);
73 if (!success) { 126 if (!success) {
74 DVLOG(1) << "NTPSnippetsDatabase init failed."; 127 DVLOG(1) << "NTPSnippetsDatabase init failed.";
75 database_.reset(); 128 ResetDatabases();
76 return; 129 return;
77 } 130 }
78 database_initialized_ = true; 131 database_initialized_ = true;
79 for (const SnippetsLoadedCallback& callback : pending_load_callbacks_) 132 if (IsInitialized())
80 LoadImpl(callback); 133 ProcessPendingLoads();
81 } 134 }
82 135
83 void NTPSnippetsDatabase::OnDatabaseLoaded( 136 void NTPSnippetsDatabase::OnDatabaseLoaded(
84 const SnippetsLoadedCallback& callback, 137 const SnippetsCallback& callback,
85 bool success, 138 bool success,
86 std::unique_ptr<std::vector<SnippetProto>> entries) { 139 std::unique_ptr<std::vector<SnippetProto>> entries) {
87 if (!success) { 140 if (!success) {
88 DVLOG(1) << "NTPSnippetsDatabase load failed."; 141 DVLOG(1) << "NTPSnippetsDatabase load failed.";
89 database_.reset(); 142 ResetDatabases();
90 return; 143 return;
91 } 144 }
92 145
93 std::unique_ptr<std::vector<std::string>> keys_to_remove( 146 std::unique_ptr<std::vector<std::string>> keys_to_remove(
94 new std::vector<std::string>()); 147 new std::vector<std::string>());
95 148
96 NTPSnippet::PtrVector snippets; 149 NTPSnippet::PtrVector snippets;
97 for (const SnippetProto& proto : *entries) { 150 for (const SnippetProto& proto : *entries) {
98 std::unique_ptr<NTPSnippet> snippet = NTPSnippet::CreateFromProto(proto); 151 std::unique_ptr<NTPSnippet> snippet = NTPSnippet::CreateFromProto(proto);
99 if (snippet) { 152 if (snippet) {
100 snippets.emplace_back(std::move(snippet)); 153 snippets.emplace_back(std::move(snippet));
101 } else { 154 } else {
102 LOG(WARNING) << "Invalid proto from DB " << proto.id(); 155 LOG(WARNING) << "Invalid proto from DB " << proto.id();
103 keys_to_remove->emplace_back(proto.id()); 156 keys_to_remove->emplace_back(proto.id());
104 } 157 }
105 } 158 }
106 159
107 callback.Run(std::move(snippets)); 160 callback.Run(std::move(snippets));
108 161
109 // If any of the snippet protos couldn't be converted to actual snippets, 162 // If any of the snippet protos couldn't be converted to actual snippets,
110 // clean them up now. 163 // clean them up now.
111 if (!keys_to_remove->empty()) 164 if (!keys_to_remove->empty())
112 DeleteImpl(std::move(keys_to_remove)); 165 DeleteSnippetsImpl(std::move(keys_to_remove));
113 } 166 }
114 167
115 void NTPSnippetsDatabase::OnDatabaseSaved(bool success) { 168 void NTPSnippetsDatabase::OnDatabaseSaved(bool success) {
116 if (!success) { 169 if (!success) {
117 DVLOG(1) << "NTPSnippetsDatabase save failed."; 170 DVLOG(1) << "NTPSnippetsDatabase save failed.";
118 database_.reset(); 171 ResetDatabases();
119 } 172 }
120 } 173 }
121 174
122 void NTPSnippetsDatabase::LoadImpl(const SnippetsLoadedCallback& callback) { 175 void NTPSnippetsDatabase::OnImageDatabaseInited(bool success) {
123 DCHECK(database_); 176 DCHECK(!image_database_initialized_);
124 DCHECK(database_initialized_); 177 if (!success) {
178 DVLOG(1) << "NTPSnippetsDatabase init failed.";
179 ResetDatabases();
180 return;
181 }
182 image_database_initialized_ = true;
183 if (IsInitialized())
184 ProcessPendingLoads();
185 }
186
187 void NTPSnippetsDatabase::OnImageDatabaseLoaded(
188 const SnippetImageCallback& callback,
189 bool success,
190 std::unique_ptr<SnippetImageProto> entry) {
191 if (!success) {
192 DVLOG(1) << "NTPSnippetsDatabase load failed.";
193 ResetDatabases();
194 return;
195 }
196
197 if (!entry) {
198 callback.Run(std::string());
199 return;
200 }
201
202 std::unique_ptr<std::string> data(entry->release_data());
203 callback.Run(std::move(*data));
204 }
205
206 void NTPSnippetsDatabase::OnImageDatabaseSaved(bool success) {
207 if (!success) {
208 DVLOG(1) << "NTPSnippetsDatabase save failed.";
209 ResetDatabases();
210 }
211 }
212
213 void NTPSnippetsDatabase::ProcessPendingLoads() {
214 DCHECK(IsInitialized());
215
216 for (const auto& callback : pending_snippets_callbacks_)
217 LoadSnippetsImpl(callback);
218 pending_snippets_callbacks_.clear();
219
220 for (const auto& id_callback : pending_image_callbacks_)
221 LoadImageImpl(id_callback.first, id_callback.second);
222 pending_image_callbacks_.clear();
223 }
224
225 void NTPSnippetsDatabase::LoadSnippetsImpl(const SnippetsCallback& callback) {
226 DCHECK(IsInitialized());
125 database_->LoadEntries(base::Bind(&NTPSnippetsDatabase::OnDatabaseLoaded, 227 database_->LoadEntries(base::Bind(&NTPSnippetsDatabase::OnDatabaseLoaded,
126 weak_ptr_factory_.GetWeakPtr(), 228 weak_ptr_factory_.GetWeakPtr(),
127 callback)); 229 callback));
128 } 230 }
129 231
130 void NTPSnippetsDatabase::SaveImpl( 232 void NTPSnippetsDatabase::SaveSnippetsImpl(
131 std::unique_ptr<KeyEntryVector> entries_to_save) { 233 std::unique_ptr<KeyEntryVector> entries_to_save) {
132 if (!database_ || !database_initialized_) 234 // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()).
235 if (!IsInitialized())
133 return; 236 return;
134 237
135 std::unique_ptr<std::vector<std::string>> keys_to_remove( 238 std::unique_ptr<std::vector<std::string>> keys_to_remove(
136 new std::vector<std::string>()); 239 new std::vector<std::string>());
137 database_->UpdateEntries(std::move(entries_to_save), 240 database_->UpdateEntries(std::move(entries_to_save),
138 std::move(keys_to_remove), 241 std::move(keys_to_remove),
139 base::Bind(&NTPSnippetsDatabase::OnDatabaseSaved, 242 base::Bind(&NTPSnippetsDatabase::OnDatabaseSaved,
140 weak_ptr_factory_.GetWeakPtr())); 243 weak_ptr_factory_.GetWeakPtr()));
141 } 244 }
142 245
143 void NTPSnippetsDatabase::DeleteImpl( 246 void NTPSnippetsDatabase::DeleteSnippetsImpl(
144 std::unique_ptr<std::vector<std::string>> keys_to_remove) { 247 std::unique_ptr<std::vector<std::string>> keys_to_remove) {
145 if (!database_ || !database_initialized_) 248 // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()).
249 if (!IsInitialized())
146 return; 250 return;
147 251
252 DeleteImagesImpl(
253 base::WrapUnique(new std::vector<std::string>(*keys_to_remove)));
254
148 std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector()); 255 std::unique_ptr<KeyEntryVector> entries_to_save(new KeyEntryVector());
149 database_->UpdateEntries(std::move(entries_to_save), 256 database_->UpdateEntries(std::move(entries_to_save),
150 std::move(keys_to_remove), 257 std::move(keys_to_remove),
151 base::Bind(&NTPSnippetsDatabase::OnDatabaseSaved, 258 base::Bind(&NTPSnippetsDatabase::OnDatabaseSaved,
152 weak_ptr_factory_.GetWeakPtr())); 259 weak_ptr_factory_.GetWeakPtr()));
153 } 260 }
154 261
262 void NTPSnippetsDatabase::LoadImageImpl(const std::string& snippet_id,
263 const SnippetImageCallback& callback) {
264 DCHECK(IsInitialized());
265 image_database_->GetEntry(
266 snippet_id,
267 base::Bind(&NTPSnippetsDatabase::OnImageDatabaseLoaded,
268 weak_ptr_factory_.GetWeakPtr(), callback));
269 }
270
271 void NTPSnippetsDatabase::DeleteImagesImpl(
272 std::unique_ptr<std::vector<std::string>> keys_to_remove) {
273 // TODO(treib): After we pass errors to the client, DCHECK(IsInitialized()).
274 if (!IsInitialized())
275 return;
276
277 image_database_->UpdateEntries(
278 base::WrapUnique(new ImageKeyEntryVector()),
279 std::move(keys_to_remove),
280 base::Bind(&NTPSnippetsDatabase::OnImageDatabaseSaved,
281 weak_ptr_factory_.GetWeakPtr()));
282 }
283
284 void NTPSnippetsDatabase::ResetDatabases() {
285 database_.reset();
286 image_database_.reset();
287 }
288
155 } // namespace ntp_snippets 289 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/ntp_snippets_database.h ('k') | components/ntp_snippets/ntp_snippets_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698