| 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" |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 128 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 129 statement.BindInt64(0, request_id); | 129 statement.BindInt64(0, request_id); |
| 130 if (!statement.Run()) | 130 if (!statement.Run()) |
| 131 return RequestQueue::UpdateRequestResult::STORE_FAILURE; | 131 return RequestQueue::UpdateRequestResult::STORE_FAILURE; |
| 132 else if (db->GetLastChangeCount() == 0) | 132 else if (db->GetLastChangeCount() == 0) |
| 133 return RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 133 return RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 134 else | 134 else |
| 135 return RequestQueue::UpdateRequestResult::SUCCESS; | 135 return RequestQueue::UpdateRequestResult::SUCCESS; |
| 136 } | 136 } |
| 137 | 137 |
| 138 bool ChangeRequestState(sql::Connection* db, | 138 ItemActionStatus ChangeRequestState( |
| 139 const int64_t request_id, | 139 sql::Connection* db, |
| 140 const SavePageRequest::RequestState new_state) { | 140 const int64_t request_id, |
| 141 const SavePageRequest::RequestState new_state) { |
| 141 const char kSql[] = "UPDATE " REQUEST_QUEUE_TABLE_NAME | 142 const char kSql[] = "UPDATE " REQUEST_QUEUE_TABLE_NAME |
| 142 " SET state=?" | 143 " SET state=?" |
| 143 " WHERE request_id=?"; | 144 " WHERE request_id=?"; |
| 144 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 145 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 145 statement.BindInt64(0, static_cast<int64_t>(new_state)); | 146 statement.BindInt64(0, static_cast<int64_t>(new_state)); |
| 146 statement.BindInt64(1, request_id); | 147 statement.BindInt64(1, request_id); |
| 147 return statement.Run(); | 148 |
| 149 if (!statement.Run()) |
| 150 return ItemActionStatus::STORE_ERROR; |
| 151 if (db->GetLastChangeCount() == 0) |
| 152 return ItemActionStatus::NOT_FOUND; |
| 153 return ItemActionStatus::SUCCESS; |
| 148 } | 154 } |
| 149 | 155 |
| 150 // Helper function to delete requests corresponding to passed in requestIds, | 156 // Helper function to delete requests corresponding to passed in requestIds, |
| 151 // and fill an outparam with the removed requests. | 157 // and fill an outparam with the removed requests. |
| 152 bool DeleteRequestsByIds( | 158 bool DeleteRequestsByIds( |
| 153 sql::Connection* db, | 159 sql::Connection* db, |
| 154 const std::vector<int64_t>& request_ids, | 160 const std::vector<int64_t>& request_ids, |
| 155 RequestQueue::UpdateMultipleRequestResults& results, | 161 RequestQueue::UpdateMultipleRequestResults& results, |
| 156 std::vector<std::unique_ptr<SavePageRequest>>* requests) { | 162 std::vector<std::unique_ptr<SavePageRequest>>* requests) { |
| 157 // If you create a transaction but don't Commit() it is automatically | 163 // If you create a transaction but don't Commit() it is automatically |
| (...skipping 17 matching lines...) Expand all Loading... |
| 175 | 181 |
| 176 if (!transaction.Commit()) { | 182 if (!transaction.Commit()) { |
| 177 requests->clear(); | 183 requests->clear(); |
| 178 BuildFailedResultList(request_ids, results); | 184 BuildFailedResultList(request_ids, results); |
| 179 return false; | 185 return false; |
| 180 } | 186 } |
| 181 | 187 |
| 182 return true; | 188 return true; |
| 183 } | 189 } |
| 184 | 190 |
| 185 bool ChangeRequestsState( | |
| 186 sql::Connection* db, | |
| 187 const std::vector<int64_t>& request_ids, | |
| 188 SavePageRequest::RequestState new_state, | |
| 189 RequestQueue::UpdateMultipleRequestResults& results, | |
| 190 std::vector<std::unique_ptr<SavePageRequest>>& requests) { | |
| 191 // If you create a transaction but don't Commit() it is automatically | |
| 192 // rolled back by its destructor when it falls out of scope. | |
| 193 sql::Transaction transaction(db); | |
| 194 if (!transaction.Begin()) { | |
| 195 BuildFailedResultList(request_ids, results); | |
| 196 return false; | |
| 197 } | |
| 198 | |
| 199 // Update a request, then get it, and put the item we got on the output list. | |
| 200 for (const auto& request_id : request_ids) { | |
| 201 RequestQueue::UpdateRequestResult status; | |
| 202 if (!ChangeRequestState(db, request_id, new_state)) | |
| 203 status = RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | |
| 204 else | |
| 205 status = RequestQueue::UpdateRequestResult::SUCCESS; | |
| 206 | |
| 207 // Make output request_id/status pair, and put a copy of the updated request | |
| 208 // on output list. | |
| 209 results.push_back(std::make_pair(request_id, status)); | |
| 210 requests.push_back(GetOneRequest(db, request_id)); | |
| 211 } | |
| 212 | |
| 213 if (!transaction.Commit()) { | |
| 214 requests.clear(); | |
| 215 BuildFailedResultList(request_ids, results); | |
| 216 return false; | |
| 217 } | |
| 218 | |
| 219 return true; | |
| 220 } | |
| 221 | |
| 222 ItemActionStatus Insert(sql::Connection* db, const SavePageRequest& request) { | 191 ItemActionStatus Insert(sql::Connection* db, const SavePageRequest& request) { |
| 223 const char kSql[] = | 192 const char kSql[] = |
| 224 "INSERT OR IGNORE INTO " REQUEST_QUEUE_TABLE_NAME | 193 "INSERT OR IGNORE INTO " REQUEST_QUEUE_TABLE_NAME |
| 225 " (request_id, creation_time, activation_time," | 194 " (request_id, creation_time, activation_time," |
| 226 " last_attempt_time, started_attempt_count, completed_attempt_count," | 195 " last_attempt_time, started_attempt_count, completed_attempt_count," |
| 227 " state, url, client_namespace, client_id)" | 196 " state, url, client_namespace, client_id)" |
| 228 " VALUES " | 197 " VALUES " |
| 229 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; | 198 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
| 230 | 199 |
| 231 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 200 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 scoped_refptr<base::SingleThreadTaskRunner> runner, | 260 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 292 const std::vector<SavePageRequest>& items, | 261 const std::vector<SavePageRequest>& items, |
| 293 const RequestQueueStore::UpdateCallback& callback) { | 262 const RequestQueueStore::UpdateCallback& callback) { |
| 294 std::vector<int64_t> item_ids; | 263 std::vector<int64_t> item_ids; |
| 295 for (const auto& item : items) | 264 for (const auto& item : items) |
| 296 item_ids.push_back(item.request_id()); | 265 item_ids.push_back(item.request_id()); |
| 297 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids, | 266 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids, |
| 298 ItemActionStatus::STORE_ERROR, callback); | 267 ItemActionStatus::STORE_ERROR, callback); |
| 299 } | 268 } |
| 300 | 269 |
| 270 void PostStoreErrorForAllIds( |
| 271 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 272 const std::vector<int64_t>& item_ids, |
| 273 const RequestQueueStore::UpdateCallback& callback) { |
| 274 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids, |
| 275 ItemActionStatus::STORE_ERROR, callback); |
| 276 } |
| 277 |
| 301 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { | 278 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { |
| 302 db->set_page_size(4096); | 279 db->set_page_size(4096); |
| 303 db->set_cache_size(500); | 280 db->set_cache_size(500); |
| 304 db->set_histogram_tag("BackgroundRequestQueue"); | 281 db->set_histogram_tag("BackgroundRequestQueue"); |
| 305 db->set_exclusive_locking(); | 282 db->set_exclusive_locking(); |
| 306 | 283 |
| 307 base::File::Error err; | 284 base::File::Error err; |
| 308 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) | 285 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) |
| 309 return false; | 286 return false; |
| 310 if (!db->Open(path)) | 287 if (!db->Open(path)) |
| 311 return false; | 288 return false; |
| 312 db->Preload(); | 289 db->Preload(); |
| 313 | 290 |
| 314 return CreateSchema(db); | 291 return CreateSchema(db); |
| 315 } | 292 } |
| 316 | 293 |
| 294 std::unique_ptr<SavePageRequest> GetRequestByIdSync(sql::Connection* db, |
| 295 int64_t item_id) { |
| 296 const char kSql[] = |
| 297 "SELECT * FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id = ?"; |
| 298 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 299 statement.BindInt64(0, item_id); |
| 300 |
| 301 if (statement.Step()) { |
| 302 return MakeSavePageRequest(statement); |
| 303 } |
| 304 |
| 305 return std::unique_ptr<SavePageRequest>(nullptr); |
| 306 } |
| 307 |
| 317 void GetRequestsSync(sql::Connection* db, | 308 void GetRequestsSync(sql::Connection* db, |
| 318 scoped_refptr<base::SingleThreadTaskRunner> runner, | 309 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 319 const RequestQueueStore::GetRequestsCallback& callback) { | 310 const RequestQueueStore::GetRequestsCallback& callback) { |
| 320 const char kSql[] = | 311 const char kSql[] = |
| 321 "SELECT request_id, creation_time, activation_time," | 312 "SELECT request_id, creation_time, activation_time," |
| 322 " last_attempt_time, started_attempt_count, completed_attempt_count," | 313 " last_attempt_time, started_attempt_count, completed_attempt_count," |
| 323 " state, url, client_namespace, client_id" | 314 " state, url, client_namespace, client_id" |
| 324 " FROM " REQUEST_QUEUE_TABLE_NAME; | 315 " FROM " REQUEST_QUEUE_TABLE_NAME; |
| 325 | 316 |
| 326 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 317 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 const std::vector<int64_t>& request_ids, | 368 const std::vector<int64_t>& request_ids, |
| 378 const RequestQueueStore::RemoveCallback& callback) { | 369 const RequestQueueStore::RemoveCallback& callback) { |
| 379 RequestQueue::UpdateMultipleRequestResults results; | 370 RequestQueue::UpdateMultipleRequestResults results; |
| 380 std::vector<std::unique_ptr<SavePageRequest>> requests; | 371 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 381 // TODO(fgorski): add UMA metrics here. | 372 // TODO(fgorski): add UMA metrics here. |
| 382 DeleteRequestsByIds(db, request_ids, results, &requests); | 373 DeleteRequestsByIds(db, request_ids, results, &requests); |
| 383 runner->PostTask(FROM_HERE, | 374 runner->PostTask(FROM_HERE, |
| 384 base::Bind(callback, results, base::Passed(&requests))); | 375 base::Bind(callback, results, base::Passed(&requests))); |
| 385 } | 376 } |
| 386 | 377 |
| 378 // TODO(fgorski): This method is to be completely removed by petewil's patch. |
| 387 void ChangeRequestsStateSync( | 379 void ChangeRequestsStateSync( |
| 388 sql::Connection* db, | 380 sql::Connection* db, |
| 389 scoped_refptr<base::SingleThreadTaskRunner> runner, | 381 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 390 const std::vector<int64_t>& request_ids, | 382 const std::vector<int64_t>& request_ids, |
| 391 const SavePageRequest::RequestState new_state, | 383 const SavePageRequest::RequestState new_state, |
| 392 const RequestQueue::UpdateMultipleRequestsCallback& callback) { | 384 const RequestQueueStore::UpdateCallback& callback) { |
| 393 RequestQueue::UpdateMultipleRequestResults results; | |
| 394 std::vector<std::unique_ptr<SavePageRequest>> requests; | |
| 395 // TODO(fgorski): add UMA metrics here. | 385 // TODO(fgorski): add UMA metrics here. |
| 396 offline_pages::ChangeRequestsState(db, request_ids, new_state, results, | 386 std::unique_ptr<UpdateRequestsResult> result( |
| 397 requests); | 387 new UpdateRequestsResult(StoreState::LOADED)); |
| 398 runner->PostTask(FROM_HERE, | 388 |
| 399 base::Bind(callback, results, base::Passed(&requests))); | 389 sql::Transaction transaction(db); |
| 390 if (!transaction.Begin()) { |
| 391 PostStoreErrorForAllIds(runner, request_ids, callback); |
| 392 return; |
| 393 } |
| 394 |
| 395 // Update a request, then get it, and put the item we got on the output list. |
| 396 for (const auto& request_id : request_ids) { |
| 397 ItemActionStatus status = ChangeRequestState(db, request_id, new_state); |
| 398 if (status == ItemActionStatus::SUCCESS) { |
| 399 std::unique_ptr<SavePageRequest> request = |
| 400 GetRequestByIdSync(db, request_id); |
| 401 if (request.get()) |
| 402 result->updated_items.push_back(*request); |
| 403 else |
| 404 status = ItemActionStatus::STORE_ERROR; |
| 405 } |
| 406 |
| 407 result->item_statuses.push_back(std::make_pair(request_id, status)); |
| 408 } |
| 409 |
| 410 if (!transaction.Commit()) { |
| 411 PostStoreErrorForAllIds(runner, request_ids, callback); |
| 412 return; |
| 413 } |
| 414 |
| 415 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); |
| 400 } | 416 } |
| 401 | 417 |
| 402 void OpenConnectionSync(sql::Connection* db, | 418 void OpenConnectionSync(sql::Connection* db, |
| 403 scoped_refptr<base::SingleThreadTaskRunner> runner, | 419 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 404 const base::FilePath& path, | 420 const base::FilePath& path, |
| 405 const base::Callback<void(bool)>& callback) { | 421 const base::Callback<void(bool)>& callback) { |
| 406 bool success = InitDatabase(db, path); | 422 bool success = InitDatabase(db, path); |
| 407 runner->PostTask(FROM_HERE, base::Bind(callback, success)); | 423 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 408 } | 424 } |
| 409 | 425 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 | 518 |
| 503 background_task_runner_->PostTask( | 519 background_task_runner_->PostTask( |
| 504 FROM_HERE, | 520 FROM_HERE, |
| 505 base::Bind(&RemoveRequestsSync, db_.get(), | 521 base::Bind(&RemoveRequestsSync, db_.get(), |
| 506 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | 522 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); |
| 507 } | 523 } |
| 508 | 524 |
| 509 void RequestQueueStoreSQL::ChangeRequestsState( | 525 void RequestQueueStoreSQL::ChangeRequestsState( |
| 510 const std::vector<int64_t>& request_ids, | 526 const std::vector<int64_t>& request_ids, |
| 511 const SavePageRequest::RequestState new_state, | 527 const SavePageRequest::RequestState new_state, |
| 512 const UpdateMultipleRequestsCallback& callback) { | 528 const UpdateCallback& callback) { |
| 513 RequestQueue::UpdateMultipleRequestResults results; | 529 if (!db_.get()) { |
| 514 std::vector<std::unique_ptr<SavePageRequest>> requests; | 530 PostStoreErrorForAllIds(base::ThreadTaskRunnerHandle::Get(), request_ids, |
| 515 if (!CheckDb(base::Bind(callback, results, base::Passed(&requests)))) { | 531 callback); |
| 516 return; | 532 return; |
| 517 } | 533 } |
| 518 | 534 |
| 519 background_task_runner_->PostTask( | 535 background_task_runner_->PostTask( |
| 520 FROM_HERE, base::Bind(&ChangeRequestsStateSync, db_.get(), | 536 FROM_HERE, base::Bind(&ChangeRequestsStateSync, db_.get(), |
| 521 base::ThreadTaskRunnerHandle::Get(), request_ids, | 537 base::ThreadTaskRunnerHandle::Get(), request_ids, |
| 522 new_state, callback)); | 538 new_state, callback)); |
| 523 } | 539 } |
| 524 | 540 |
| 525 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { | 541 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 555 } | 571 } |
| 556 | 572 |
| 557 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, | 573 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, |
| 558 bool success) { | 574 bool success) { |
| 559 // Complete connection initialization post reset. | 575 // Complete connection initialization post reset. |
| 560 OnOpenConnectionDone(success); | 576 OnOpenConnectionDone(success); |
| 561 callback.Run(success); | 577 callback.Run(success); |
| 562 } | 578 } |
| 563 | 579 |
| 564 } // namespace offline_pages | 580 } // namespace offline_pages |
| OLD | NEW |