Chromium Code Reviews| 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 "components/offline_pages/offline_store_types_impl.h" | |
| 15 #include "sql/connection.h" | 16 #include "sql/connection.h" |
| 16 #include "sql/statement.h" | 17 #include "sql/statement.h" |
| 17 #include "sql/transaction.h" | 18 #include "sql/transaction.h" |
| 18 | 19 |
| 19 namespace offline_pages { | 20 namespace offline_pages { |
| 20 | 21 |
| 22 template class StoreUpdateResult<SavePageRequest>; | |
| 23 | |
| 21 namespace { | 24 namespace { |
| 22 | 25 |
| 23 using UpdateStatus = RequestQueueStore::UpdateStatus; | 26 using UpdateStatus = RequestQueueStore::UpdateStatus; |
| 24 | 27 |
| 25 // This is a macro instead of a const so that | 28 // This is a macro instead of a const so that |
| 26 // it can be used inline in other SQL statements below. | 29 // it can be used inline in other SQL statements below. |
| 27 #define REQUEST_QUEUE_TABLE_NAME "request_queue_v1" | 30 #define REQUEST_QUEUE_TABLE_NAME "request_queue_v1" |
| 28 const bool kUserRequested = true; | 31 const bool kUserRequested = true; |
| 29 | 32 |
| 30 bool CreateRequestQueueTable(sql::Connection* db) { | 33 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); | 241 statement.BindString(8, request.client_id().name_space); |
| 239 statement.BindString(9, request.client_id().id); | 242 statement.BindString(9, request.client_id().id); |
| 240 | 243 |
| 241 if (!statement.Run()) | 244 if (!statement.Run()) |
| 242 return ItemActionStatus::STORE_ERROR; | 245 return ItemActionStatus::STORE_ERROR; |
| 243 if (db->GetLastChangeCount() == 0) | 246 if (db->GetLastChangeCount() == 0) |
| 244 return ItemActionStatus::ALREADY_EXISTS; | 247 return ItemActionStatus::ALREADY_EXISTS; |
| 245 return ItemActionStatus::SUCCESS; | 248 return ItemActionStatus::SUCCESS; |
| 246 } | 249 } |
| 247 | 250 |
| 248 RequestQueueStore::UpdateStatus InsertOrReplace( | 251 ItemActionStatus Update(sql::Connection* db, const SavePageRequest& request) { |
| 249 sql::Connection* db, | 252 const char kSql[] = |
| 250 const SavePageRequest& request) { | 253 "UPDATE OR IGNORE " REQUEST_QUEUE_TABLE_NAME |
| 251 // In order to use the enums in the Bind* methods, keep the order of fields | 254 " SET creation_time = ?, activation_time = ?, last_attempt_time = ?," |
|
Pete Williamson
2016/09/22 00:12:50
Why are these in a different order than before? (I
fgorski
2016/09/22 15:47:53
You are correct that it does not matter.
If you lo
| |
| 252 // the same as in the definition/select query. | 255 " started_attempt_count = ?, completed_attempt_count = ?, state = ?," |
| 253 const char kInsertSql[] = | 256 " url = ?, client_namespace = ?, client_id = ?" |
| 254 "INSERT OR REPLACE INTO " REQUEST_QUEUE_TABLE_NAME | 257 " 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 | 258 |
| 261 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kInsertSql)); | 259 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 262 statement.BindInt64(0, request.request_id()); | 260 statement.BindInt64(0, request.creation_time().ToInternalValue()); |
| 263 statement.BindInt64(1, request.creation_time().ToInternalValue()); | 261 statement.BindInt64(1, request.activation_time().ToInternalValue()); |
| 264 statement.BindInt64(2, request.activation_time().ToInternalValue()); | 262 statement.BindInt64(2, request.last_attempt_time().ToInternalValue()); |
| 265 statement.BindInt64(3, request.last_attempt_time().ToInternalValue()); | 263 statement.BindInt64(3, request.started_attempt_count()); |
| 266 statement.BindInt64(4, request.started_attempt_count()); | 264 statement.BindInt64(4, request.completed_attempt_count()); |
| 267 statement.BindInt64(5, request.completed_attempt_count()); | 265 statement.BindInt64(5, static_cast<int64_t>(request.request_state())); |
| 268 statement.BindInt64(6, static_cast<int64_t>(request.request_state())); | 266 statement.BindString(6, request.url().spec()); |
| 269 statement.BindString(7, request.url().spec()); | 267 statement.BindString(7, request.client_id().name_space); |
| 270 statement.BindString(8, request.client_id().name_space); | 268 statement.BindString(8, request.client_id().id); |
| 271 statement.BindString(9, request.client_id().id); | 269 statement.BindInt64(9, request.request_id()); |
| 272 | 270 |
| 273 // TODO(fgorski): Replace the UpdateStatus with boolean in the | 271 if (!statement.Run()) |
| 274 // RequestQueueStore interface and update this code. | 272 return ItemActionStatus::STORE_ERROR; |
| 275 return statement.Run() ? RequestQueueStore::UpdateStatus::UPDATED | 273 if (db->GetLastChangeCount() == 0) |
| 276 : RequestQueueStore::UpdateStatus::FAILED; | 274 return ItemActionStatus::NOT_FOUND; |
| 275 return ItemActionStatus::SUCCESS; | |
| 277 } | 276 } |
| 278 | 277 |
| 279 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { | 278 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { |
| 280 db->set_page_size(4096); | 279 db->set_page_size(4096); |
| 281 db->set_cache_size(500); | 280 db->set_cache_size(500); |
| 282 db->set_histogram_tag("BackgroundRequestQueue"); | 281 db->set_histogram_tag("BackgroundRequestQueue"); |
| 283 db->set_exclusive_locking(); | 282 db->set_exclusive_locking(); |
| 284 | 283 |
| 285 base::File::Error err; | 284 base::File::Error err; |
| 286 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) | 285 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 313 | 312 |
| 314 void AddRequestSync(sql::Connection* db, | 313 void AddRequestSync(sql::Connection* db, |
| 315 scoped_refptr<base::SingleThreadTaskRunner> runner, | 314 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 316 const SavePageRequest& request, | 315 const SavePageRequest& request, |
| 317 const RequestQueueStore::AddCallback& callback) { | 316 const RequestQueueStore::AddCallback& callback) { |
| 318 // TODO(fgorski): add UMA metrics here. | 317 // TODO(fgorski): add UMA metrics here. |
| 319 ItemActionStatus status = Insert(db, request); | 318 ItemActionStatus status = Insert(db, request); |
| 320 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | 319 runner->PostTask(FROM_HERE, base::Bind(callback, status)); |
| 321 } | 320 } |
| 322 | 321 |
| 323 void AddOrUpdateRequestSync(sql::Connection* db, | 322 void UpdateRequestsSync(sql::Connection* db, |
| 324 scoped_refptr<base::SingleThreadTaskRunner> runner, | 323 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 325 const SavePageRequest& request, | 324 const std::vector<SavePageRequest>& requests, |
| 326 const RequestQueueStore::UpdateCallback& callback) { | 325 const RequestQueueStore::UpdateCallback& callback) { |
| 327 // TODO(fgorski): add UMA metrics here. | 326 // TODO(fgorski): add UMA metrics here. |
| 328 RequestQueueStore::UpdateStatus status = InsertOrReplace(db, request); | 327 std::unique_ptr<UpdateRequestsResult> result( |
| 329 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | 328 new UpdateRequestsResult(StoreState::LOADED)); |
| 329 | |
| 330 sql::Transaction transaction(db); | |
| 331 if (!transaction.Begin()) { | |
| 332 // post error for all items. | |
| 333 return; | |
| 334 } | |
| 335 | |
| 336 for (const auto& request : requests) { | |
| 337 ItemActionStatus status = Update(db, request); | |
| 338 result->item_statuses.push_back( | |
| 339 std::make_pair(request.request_id(), status)); | |
| 340 if (status == ItemActionStatus::SUCCESS) | |
| 341 result->updated_items.push_back(request); | |
| 342 } | |
| 343 | |
| 344 if (!transaction.Commit()) { | |
| 345 // post error for all items. | |
| 346 return; | |
| 347 } | |
| 348 | |
| 349 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); | |
| 330 } | 350 } |
| 331 | 351 |
| 332 void RemoveRequestsSync(sql::Connection* db, | 352 void RemoveRequestsSync(sql::Connection* db, |
| 333 scoped_refptr<base::SingleThreadTaskRunner> runner, | 353 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 334 const std::vector<int64_t>& request_ids, | 354 const std::vector<int64_t>& request_ids, |
| 335 const RequestQueueStore::RemoveCallback& callback) { | 355 const RequestQueueStore::RemoveCallback& callback) { |
| 336 RequestQueue::UpdateMultipleRequestResults results; | 356 RequestQueue::UpdateMultipleRequestResults results; |
| 337 std::vector<std::unique_ptr<SavePageRequest>> requests; | 357 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 338 // TODO(fgorski): add UMA metrics here. | 358 // TODO(fgorski): add UMA metrics here. |
| 339 DeleteRequestsByIds(db, request_ids, results, &requests); | 359 DeleteRequestsByIds(db, request_ids, results, &requests); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 const AddCallback& callback) { | 439 const AddCallback& callback) { |
| 420 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) | 440 if (!CheckDb(base::Bind(callback, ItemActionStatus::STORE_ERROR))) |
| 421 return; | 441 return; |
| 422 | 442 |
| 423 background_task_runner_->PostTask( | 443 background_task_runner_->PostTask( |
| 424 FROM_HERE, | 444 FROM_HERE, |
| 425 base::Bind(&AddRequestSync, db_.get(), | 445 base::Bind(&AddRequestSync, db_.get(), |
| 426 base::ThreadTaskRunnerHandle::Get(), request, callback)); | 446 base::ThreadTaskRunnerHandle::Get(), request, callback)); |
| 427 } | 447 } |
| 428 | 448 |
| 429 void RequestQueueStoreSQL::AddOrUpdateRequest(const SavePageRequest& request, | 449 void RequestQueueStoreSQL::UpdateRequests( |
| 430 const UpdateCallback& callback) { | 450 const std::vector<SavePageRequest>& requests, |
| 431 DCHECK(db_.get()); | 451 const UpdateCallback& callback) { |
| 432 if (!CheckDb(base::Bind(callback, UpdateStatus::FAILED))) | 452 if (!db_.get()) { |
| 453 // port store error for all. | |
| 433 return; | 454 return; |
| 455 } | |
| 434 | 456 |
| 435 background_task_runner_->PostTask( | 457 background_task_runner_->PostTask( |
| 436 FROM_HERE, | 458 FROM_HERE, |
| 437 base::Bind(&AddOrUpdateRequestSync, db_.get(), | 459 base::Bind(&UpdateRequestsSync, db_.get(), |
| 438 base::ThreadTaskRunnerHandle::Get(), request, callback)); | 460 base::ThreadTaskRunnerHandle::Get(), requests, callback)); |
| 439 } | 461 } |
| 440 | 462 |
| 441 void RequestQueueStoreSQL::RemoveRequests( | 463 void RequestQueueStoreSQL::RemoveRequests( |
| 442 const std::vector<int64_t>& request_ids, | 464 const std::vector<int64_t>& request_ids, |
| 443 const RemoveCallback& callback) { | 465 const RemoveCallback& callback) { |
| 444 // Set up a failed set of results in case we fail the DB check. | 466 // Set up a failed set of results in case we fail the DB check. |
| 445 RequestQueue::UpdateMultipleRequestResults results; | 467 RequestQueue::UpdateMultipleRequestResults results; |
| 446 for (int64_t request_id : request_ids) { | 468 for (int64_t request_id : request_ids) { |
| 447 results.push_back(std::make_pair( | 469 results.push_back(std::make_pair( |
| 448 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | 470 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 } | 531 } |
| 510 | 532 |
| 511 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, | 533 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, |
| 512 bool success) { | 534 bool success) { |
| 513 // Complete connection initialization post reset. | 535 // Complete connection initialization post reset. |
| 514 OnOpenConnectionDone(success); | 536 OnOpenConnectionDone(success); |
| 515 callback.Run(success); | 537 callback.Run(success); |
| 516 } | 538 } |
| 517 | 539 |
| 518 } // namespace offline_pages | 540 } // namespace offline_pages |
| OLD | NEW |