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

Side by Side Diff: components/offline_pages/background/request_queue_store_sql.cc

Issue 2363563002: [Offline pages] Implementation of RQStore.UpdateRequests with StoreUpdateResult (Closed)
Patch Set: Updating test, adding handling for store/transaction failures. Created 4 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
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/offline_pages/background/request_queue_store_sql.h" 5 #include "components/offline_pages/background/request_queue_store_sql.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/sequenced_task_runner.h" 12 #include "base/sequenced_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h" 13 #include "base/threading/thread_task_runner_handle.h"
14 #include "components/offline_pages/background/save_page_request.h" 14 #include "components/offline_pages/background/save_page_request.h"
15 #include "sql/connection.h" 15 #include "sql/connection.h"
16 #include "sql/statement.h" 16 #include "sql/statement.h"
17 #include "sql/transaction.h" 17 #include "sql/transaction.h"
18 18
19 namespace offline_pages { 19 namespace offline_pages {
20 20
21 template class StoreUpdateResult<SavePageRequest>;
22
21 namespace { 23 namespace {
22 24
23 using UpdateStatus = RequestQueueStore::UpdateStatus; 25 using UpdateStatus = RequestQueueStore::UpdateStatus;
24 26
25 // This is a macro instead of a const so that 27 // This is a macro instead of a const so that
26 // it can be used inline in other SQL statements below. 28 // it can be used inline in other SQL statements below.
27 #define REQUEST_QUEUE_TABLE_NAME "request_queue_v1" 29 #define REQUEST_QUEUE_TABLE_NAME "request_queue_v1"
28 const bool kUserRequested = true; 30 const bool kUserRequested = true;
29 31
30 bool CreateRequestQueueTable(sql::Connection* db) { 32 bool CreateRequestQueueTable(sql::Connection* db) {
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 statement.BindString(8, request.client_id().name_space); 240 statement.BindString(8, request.client_id().name_space);
239 statement.BindString(9, request.client_id().id); 241 statement.BindString(9, request.client_id().id);
240 242
241 if (!statement.Run()) 243 if (!statement.Run())
242 return ItemActionStatus::STORE_ERROR; 244 return ItemActionStatus::STORE_ERROR;
243 if (db->GetLastChangeCount() == 0) 245 if (db->GetLastChangeCount() == 0)
244 return ItemActionStatus::ALREADY_EXISTS; 246 return ItemActionStatus::ALREADY_EXISTS;
245 return ItemActionStatus::SUCCESS; 247 return ItemActionStatus::SUCCESS;
246 } 248 }
247 249
248 RequestQueueStore::UpdateStatus InsertOrReplace( 250 ItemActionStatus Update(sql::Connection* db, const SavePageRequest& request) {
249 sql::Connection* db, 251 const char kSql[] =
250 const SavePageRequest& request) { 252 "UPDATE OR IGNORE " REQUEST_QUEUE_TABLE_NAME
251 // In order to use the enums in the Bind* methods, keep the order of fields 253 " SET creation_time = ?, activation_time = ?, last_attempt_time = ?,"
252 // the same as in the definition/select query. 254 " started_attempt_count = ?, completed_attempt_count = ?, state = ?,"
253 const char kInsertSql[] = 255 " url = ?, client_namespace = ?, client_id = ?"
254 "INSERT OR REPLACE INTO " REQUEST_QUEUE_TABLE_NAME 256 " WHERE request_id = ?";
255 " (request_id, creation_time, activation_time, last_attempt_time, "
256 " started_attempt_count, completed_attempt_count, state, url, "
257 " client_namespace, client_id) "
258 " VALUES "
259 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
260 257
261 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kInsertSql)); 258 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
262 statement.BindInt64(0, request.request_id()); 259 statement.BindInt64(0, request.creation_time().ToInternalValue());
263 statement.BindInt64(1, request.creation_time().ToInternalValue()); 260 statement.BindInt64(1, request.activation_time().ToInternalValue());
264 statement.BindInt64(2, request.activation_time().ToInternalValue()); 261 statement.BindInt64(2, request.last_attempt_time().ToInternalValue());
265 statement.BindInt64(3, request.last_attempt_time().ToInternalValue()); 262 statement.BindInt64(3, request.started_attempt_count());
266 statement.BindInt64(4, request.started_attempt_count()); 263 statement.BindInt64(4, request.completed_attempt_count());
267 statement.BindInt64(5, request.completed_attempt_count()); 264 statement.BindInt64(5, static_cast<int64_t>(request.request_state()));
268 statement.BindInt64(6, static_cast<int64_t>(request.request_state())); 265 statement.BindString(6, request.url().spec());
269 statement.BindString(7, request.url().spec()); 266 statement.BindString(7, request.client_id().name_space);
270 statement.BindString(8, request.client_id().name_space); 267 statement.BindString(8, request.client_id().id);
271 statement.BindString(9, request.client_id().id); 268 statement.BindInt64(9, request.request_id());
272 269
273 // TODO(fgorski): Replace the UpdateStatus with boolean in the 270 if (!statement.Run())
274 // RequestQueueStore interface and update this code. 271 return ItemActionStatus::STORE_ERROR;
275 return statement.Run() ? RequestQueueStore::UpdateStatus::UPDATED 272 if (db->GetLastChangeCount() == 0)
276 : RequestQueueStore::UpdateStatus::FAILED; 273 return ItemActionStatus::NOT_FOUND;
274 return ItemActionStatus::SUCCESS;
275 }
276
277 void PostStoreUpdateResultForIds(
278 scoped_refptr<base::SingleThreadTaskRunner> runner,
279 StoreState store_state,
280 const std::vector<int64_t>& item_ids,
281 ItemActionStatus action_status,
282 const RequestQueueStore::UpdateCallback& callback) {
283 std::unique_ptr<UpdateRequestsResult> result(
284 new UpdateRequestsResult(store_state));
285 for (const auto& item_id : item_ids)
286 result->item_statuses.push_back(std::make_pair(item_id, action_status));
287 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
288 }
289
290 void PostStoreErrorForAllRequests(
291 scoped_refptr<base::SingleThreadTaskRunner> runner,
292 const std::vector<SavePageRequest>& items,
293 const RequestQueueStore::UpdateCallback& callback) {
294 std::vector<int64_t> item_ids;
295 for (const auto& item : items)
296 item_ids.push_back(item.request_id());
297 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids,
298 ItemActionStatus::STORE_ERROR, callback);
277 } 299 }
278 300
279 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { 301 bool InitDatabase(sql::Connection* db, const base::FilePath& path) {
280 db->set_page_size(4096); 302 db->set_page_size(4096);
281 db->set_cache_size(500); 303 db->set_cache_size(500);
282 db->set_histogram_tag("BackgroundRequestQueue"); 304 db->set_histogram_tag("BackgroundRequestQueue");
283 db->set_exclusive_locking(); 305 db->set_exclusive_locking();
284 306
285 base::File::Error err; 307 base::File::Error err;
286 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) 308 if (!base::CreateDirectoryAndGetError(path.DirName(), &err))
(...skipping 26 matching lines...) Expand all
313 335
314 void AddRequestSync(sql::Connection* db, 336 void AddRequestSync(sql::Connection* db,
315 scoped_refptr<base::SingleThreadTaskRunner> runner, 337 scoped_refptr<base::SingleThreadTaskRunner> runner,
316 const SavePageRequest& request, 338 const SavePageRequest& request,
317 const RequestQueueStore::AddCallback& callback) { 339 const RequestQueueStore::AddCallback& callback) {
318 // TODO(fgorski): add UMA metrics here. 340 // TODO(fgorski): add UMA metrics here.
319 ItemActionStatus status = Insert(db, request); 341 ItemActionStatus status = Insert(db, request);
320 runner->PostTask(FROM_HERE, base::Bind(callback, status)); 342 runner->PostTask(FROM_HERE, base::Bind(callback, status));
321 } 343 }
322 344
323 void AddOrUpdateRequestSync(sql::Connection* db, 345 void UpdateRequestsSync(sql::Connection* db,
324 scoped_refptr<base::SingleThreadTaskRunner> runner, 346 scoped_refptr<base::SingleThreadTaskRunner> runner,
325 const SavePageRequest& request, 347 const std::vector<SavePageRequest>& requests,
326 const RequestQueueStore::UpdateCallback& callback) { 348 const RequestQueueStore::UpdateCallback& callback) {
327 // TODO(fgorski): add UMA metrics here. 349 // TODO(fgorski): add UMA metrics here.
328 RequestQueueStore::UpdateStatus status = InsertOrReplace(db, request); 350 std::unique_ptr<UpdateRequestsResult> result(
329 runner->PostTask(FROM_HERE, base::Bind(callback, status)); 351 new UpdateRequestsResult(StoreState::LOADED));
352
353 sql::Transaction transaction(db);
354 if (!transaction.Begin()) {
355 PostStoreErrorForAllRequests(runner, requests, callback);
356 return;
357 }
358
359 for (const auto& request : requests) {
360 ItemActionStatus status = Update(db, request);
361 result->item_statuses.push_back(
362 std::make_pair(request.request_id(), status));
363 if (status == ItemActionStatus::SUCCESS)
364 result->updated_items.push_back(request);
365 }
366
367 if (!transaction.Commit()) {
368 PostStoreErrorForAllRequests(runner, requests, callback);
369 return;
370 }
371
372 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result)));
330 } 373 }
331 374
332 void RemoveRequestsSync(sql::Connection* db, 375 void RemoveRequestsSync(sql::Connection* db,
333 scoped_refptr<base::SingleThreadTaskRunner> runner, 376 scoped_refptr<base::SingleThreadTaskRunner> runner,
334 const std::vector<int64_t>& request_ids, 377 const std::vector<int64_t>& request_ids,
335 const RequestQueueStore::RemoveCallback& callback) { 378 const RequestQueueStore::RemoveCallback& callback) {
336 RequestQueue::UpdateMultipleRequestResults results; 379 RequestQueue::UpdateMultipleRequestResults results;
337 std::vector<std::unique_ptr<SavePageRequest>> requests; 380 std::vector<std::unique_ptr<SavePageRequest>> requests;
338 // TODO(fgorski): add UMA metrics here. 381 // TODO(fgorski): add UMA metrics here.
339 DeleteRequestsByIds(db, request_ids, results, &requests); 382 DeleteRequestsByIds(db, request_ids, results, &requests);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 const AddCallback& callback) { 462 const AddCallback& callback) {
420 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) 463 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR)))
421 return; 464 return;
422 465
423 background_task_runner_->PostTask( 466 background_task_runner_->PostTask(
424 FROM_HERE, 467 FROM_HERE,
425 base::Bind(&AddRequestSync, db_.get(), 468 base::Bind(&AddRequestSync, db_.get(),
426 base::ThreadTaskRunnerHandle::Get(), request, callback)); 469 base::ThreadTaskRunnerHandle::Get(), request, callback));
427 } 470 }
428 471
429 void RequestQueueStoreSQL::AddOrUpdateRequest(const SavePageRequest& request, 472 void RequestQueueStoreSQL::UpdateRequests(
430 const UpdateCallback& callback) { 473 const std::vector<SavePageRequest>& requests,
431 DCHECK(db_.get()); 474 const UpdateCallback& callback) {
432 if (!CheckDb(base::Bind(callback, UpdateStatus::FAILED))) 475 if (!db_.get()) {
476 PostStoreErrorForAllRequests(base::ThreadTaskRunnerHandle::Get(), requests,
477 callback);
433 return; 478 return;
479 }
434 480
435 background_task_runner_->PostTask( 481 background_task_runner_->PostTask(
436 FROM_HERE, 482 FROM_HERE,
437 base::Bind(&AddOrUpdateRequestSync, db_.get(), 483 base::Bind(&UpdateRequestsSync, db_.get(),
438 base::ThreadTaskRunnerHandle::Get(), request, callback)); 484 base::ThreadTaskRunnerHandle::Get(), requests, callback));
439 } 485 }
440 486
441 void RequestQueueStoreSQL::RemoveRequests( 487 void RequestQueueStoreSQL::RemoveRequests(
442 const std::vector<int64_t>& request_ids, 488 const std::vector<int64_t>& request_ids,
443 const RemoveCallback& callback) { 489 const RemoveCallback& callback) {
444 // Set up a failed set of results in case we fail the DB check. 490 // Set up a failed set of results in case we fail the DB check.
445 RequestQueue::UpdateMultipleRequestResults results; 491 RequestQueue::UpdateMultipleRequestResults results;
446 for (int64_t request_id : request_ids) { 492 for (int64_t request_id : request_ids) {
447 results.push_back(std::make_pair( 493 results.push_back(std::make_pair(
448 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); 494 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 } 555 }
510 556
511 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, 557 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback,
512 bool success) { 558 bool success) {
513 // Complete connection initialization post reset. 559 // Complete connection initialization post reset.
514 OnOpenConnectionDone(success); 560 OnOpenConnectionDone(success);
515 callback.Run(success); 561 callback.Run(success);
516 } 562 }
517 563
518 } // namespace offline_pages 564 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698