| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |