| 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 " state, url, client_namespace, client_id" | 106 " state, url, client_namespace, client_id" |
| 107 " FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; | 107 " FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; |
| 108 | 108 |
| 109 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 109 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 110 statement.BindInt64(0, request_id); | 110 statement.BindInt64(0, request_id); |
| 111 | 111 |
| 112 statement.Run(); | 112 statement.Run(); |
| 113 return MakeSavePageRequest(statement); | 113 return MakeSavePageRequest(statement); |
| 114 } | 114 } |
| 115 | 115 |
| 116 void BuildFailedResultList(const std::vector<int64_t>& request_ids, | 116 ItemActionStatus DeleteRequestById(sql::Connection* db, int64_t request_id) { |
| 117 RequestQueue::UpdateMultipleRequestResults results) { | |
| 118 results.clear(); | |
| 119 for (int64_t request_id : request_ids) { | |
| 120 results.push_back(std::make_pair( | |
| 121 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 RequestQueue::UpdateRequestResult DeleteRequestById(sql::Connection* db, | |
| 126 int64_t request_id) { | |
| 127 const char kSql[] = | 117 const char kSql[] = |
| 128 "DELETE FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; | 118 "DELETE FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; |
| 129 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 119 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 130 statement.BindInt64(0, request_id); | 120 statement.BindInt64(0, request_id); |
| 131 if (!statement.Run()) | 121 if (!statement.Run()) |
| 132 return RequestQueue::UpdateRequestResult::STORE_FAILURE; | 122 return ItemActionStatus::STORE_ERROR; |
| 133 else if (db->GetLastChangeCount() == 0) | 123 else if (db->GetLastChangeCount() == 0) |
| 134 return RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 124 return ItemActionStatus::NOT_FOUND; |
| 135 else | 125 return ItemActionStatus::SUCCESS; |
| 136 return RequestQueue::UpdateRequestResult::SUCCESS; | |
| 137 } | |
| 138 | |
| 139 // Helper function to delete requests corresponding to passed in requestIds, | |
| 140 // and fill an outparam with the removed requests. | |
| 141 bool DeleteRequestsByIds( | |
| 142 sql::Connection* db, | |
| 143 const std::vector<int64_t>& request_ids, | |
| 144 RequestQueue::UpdateMultipleRequestResults& results, | |
| 145 std::vector<std::unique_ptr<SavePageRequest>>* requests) { | |
| 146 // If you create a transaction but don't Commit() it is automatically | |
| 147 // rolled back by its destructor when it falls out of scope. | |
| 148 sql::Transaction transaction(db); | |
| 149 if (!transaction.Begin()) { | |
| 150 BuildFailedResultList(request_ids, results); | |
| 151 return false; | |
| 152 } | |
| 153 | |
| 154 // Read the request before we delete it, and if the delete worked, put it on | |
| 155 // the queue of requests that got deleted. | |
| 156 for (int64_t request_id : request_ids) { | |
| 157 std::unique_ptr<SavePageRequest> request = GetOneRequest(db, request_id); | |
| 158 RequestQueue::UpdateRequestResult result = | |
| 159 DeleteRequestById(db, request_id); | |
| 160 results.push_back(std::make_pair(request_id, result)); | |
| 161 if (result == RequestQueue::UpdateRequestResult::SUCCESS) | |
| 162 requests->push_back(std::move(request)); | |
| 163 } | |
| 164 | |
| 165 if (!transaction.Commit()) { | |
| 166 requests->clear(); | |
| 167 BuildFailedResultList(request_ids, results); | |
| 168 return false; | |
| 169 } | |
| 170 | |
| 171 return true; | |
| 172 } | 126 } |
| 173 | 127 |
| 174 ItemActionStatus Insert(sql::Connection* db, const SavePageRequest& request) { | 128 ItemActionStatus Insert(sql::Connection* db, const SavePageRequest& request) { |
| 175 const char kSql[] = | 129 const char kSql[] = |
| 176 "INSERT OR IGNORE INTO " REQUEST_QUEUE_TABLE_NAME | 130 "INSERT OR IGNORE INTO " REQUEST_QUEUE_TABLE_NAME |
| 177 " (request_id, creation_time, activation_time," | 131 " (request_id, creation_time, activation_time," |
| 178 " last_attempt_time, started_attempt_count, completed_attempt_count," | 132 " last_attempt_time, started_attempt_count, completed_attempt_count," |
| 179 " state, url, client_namespace, client_id)" | 133 " state, url, client_namespace, client_id)" |
| 180 " VALUES " | 134 " VALUES " |
| 181 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; | 135 " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 scoped_refptr<base::SingleThreadTaskRunner> runner, | 197 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 244 const std::vector<SavePageRequest>& items, | 198 const std::vector<SavePageRequest>& items, |
| 245 const RequestQueueStore::UpdateCallback& callback) { | 199 const RequestQueueStore::UpdateCallback& callback) { |
| 246 std::vector<int64_t> item_ids; | 200 std::vector<int64_t> item_ids; |
| 247 for (const auto& item : items) | 201 for (const auto& item : items) |
| 248 item_ids.push_back(item.request_id()); | 202 item_ids.push_back(item.request_id()); |
| 249 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids, | 203 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids, |
| 250 ItemActionStatus::STORE_ERROR, callback); | 204 ItemActionStatus::STORE_ERROR, callback); |
| 251 } | 205 } |
| 252 | 206 |
| 207 void PostStoreErrorForAllIds( |
| 208 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 209 const std::vector<int64_t>& item_ids, |
| 210 const RequestQueueStore::UpdateCallback& callback) { |
| 211 PostStoreUpdateResultForIds(runner, StoreState::LOADED, item_ids, |
| 212 ItemActionStatus::STORE_ERROR, callback); |
| 213 } |
| 214 |
| 253 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { | 215 bool InitDatabase(sql::Connection* db, const base::FilePath& path) { |
| 254 db->set_page_size(4096); | 216 db->set_page_size(4096); |
| 255 db->set_cache_size(500); | 217 db->set_cache_size(500); |
| 256 db->set_histogram_tag("BackgroundRequestQueue"); | 218 db->set_histogram_tag("BackgroundRequestQueue"); |
| 257 db->set_exclusive_locking(); | 219 db->set_exclusive_locking(); |
| 258 | 220 |
| 259 base::File::Error err; | 221 base::File::Error err; |
| 260 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) | 222 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) |
| 261 return false; | 223 return false; |
| 262 if (!db->Open(path)) | 224 if (!db->Open(path)) |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 PostStoreErrorForAllRequests(runner, requests, callback); | 282 PostStoreErrorForAllRequests(runner, requests, callback); |
| 321 return; | 283 return; |
| 322 } | 284 } |
| 323 | 285 |
| 324 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); | 286 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); |
| 325 } | 287 } |
| 326 | 288 |
| 327 void RemoveRequestsSync(sql::Connection* db, | 289 void RemoveRequestsSync(sql::Connection* db, |
| 328 scoped_refptr<base::SingleThreadTaskRunner> runner, | 290 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 329 const std::vector<int64_t>& request_ids, | 291 const std::vector<int64_t>& request_ids, |
| 330 const RequestQueueStore::RemoveCallback& callback) { | 292 const RequestQueueStore::UpdateCallback& callback) { |
| 331 RequestQueue::UpdateMultipleRequestResults results; | 293 // TODO(fgorski): Perhaps add metrics here. |
| 332 std::vector<std::unique_ptr<SavePageRequest>> requests; | 294 std::unique_ptr<UpdateRequestsResult> result( |
| 333 // TODO(fgorski): add UMA metrics here. | 295 new UpdateRequestsResult(StoreState::LOADED)); |
| 334 DeleteRequestsByIds(db, request_ids, results, &requests); | 296 |
| 335 runner->PostTask(FROM_HERE, | 297 // If you create a transaction but don't Commit() it is automatically |
| 336 base::Bind(callback, results, base::Passed(&requests))); | 298 // rolled back by its destructor when it falls out of scope. |
| 299 sql::Transaction transaction(db); |
| 300 if (!transaction.Begin()) { |
| 301 PostStoreErrorForAllIds(runner, request_ids, callback); |
| 302 return; |
| 303 } |
| 304 |
| 305 // Read the request before we delete it, and if the delete worked, put it on |
| 306 // the queue of requests that got deleted. |
| 307 for (int64_t request_id : request_ids) { |
| 308 std::unique_ptr<SavePageRequest> request = GetOneRequest(db, request_id); |
| 309 ItemActionStatus status = DeleteRequestById(db, request_id); |
| 310 result->item_statuses.push_back(std::make_pair(request_id, status)); |
| 311 if (status == ItemActionStatus::SUCCESS) |
| 312 result->updated_items.push_back(*request); |
| 313 } |
| 314 |
| 315 if (!transaction.Commit()) { |
| 316 PostStoreErrorForAllIds(runner, request_ids, callback); |
| 317 return; |
| 318 } |
| 319 |
| 320 runner->PostTask(FROM_HERE, base::Bind(callback, base::Passed(&result))); |
| 337 } | 321 } |
| 338 | 322 |
| 339 void OpenConnectionSync(sql::Connection* db, | 323 void OpenConnectionSync(sql::Connection* db, |
| 340 scoped_refptr<base::SingleThreadTaskRunner> runner, | 324 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 341 const base::FilePath& path, | 325 const base::FilePath& path, |
| 342 const StoreStateCallback& callback) { | 326 const StoreStateCallback& callback) { |
| 343 StoreState state = | 327 StoreState state = |
| 344 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; | 328 InitDatabase(db, path) ? StoreState::LOADED : StoreState::FAILED_LOADING; |
| 345 runner->PostTask(FROM_HERE, base::Bind(callback, state)); | 329 runner->PostTask(FROM_HERE, base::Bind(callback, state)); |
| 346 } | 330 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 } | 406 } |
| 423 | 407 |
| 424 background_task_runner_->PostTask( | 408 background_task_runner_->PostTask( |
| 425 FROM_HERE, | 409 FROM_HERE, |
| 426 base::Bind(&UpdateRequestsSync, db_.get(), | 410 base::Bind(&UpdateRequestsSync, db_.get(), |
| 427 base::ThreadTaskRunnerHandle::Get(), requests, callback)); | 411 base::ThreadTaskRunnerHandle::Get(), requests, callback)); |
| 428 } | 412 } |
| 429 | 413 |
| 430 void RequestQueueStoreSQL::RemoveRequests( | 414 void RequestQueueStoreSQL::RemoveRequests( |
| 431 const std::vector<int64_t>& request_ids, | 415 const std::vector<int64_t>& request_ids, |
| 432 const RemoveCallback& callback) { | 416 const UpdateCallback& callback) { |
| 433 // Set up a failed set of results in case we fail the DB check. | 417 if (!db_.get()) { |
| 434 RequestQueue::UpdateMultipleRequestResults results; | 418 PostStoreErrorForAllIds(base::ThreadTaskRunnerHandle::Get(), request_ids, |
| 435 for (int64_t request_id : request_ids) { | 419 callback); |
| 436 results.push_back(std::make_pair( | |
| 437 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | |
| 438 } | |
| 439 | |
| 440 if (!CheckDb(base::Bind( | |
| 441 callback, results, | |
| 442 base::Passed(std::vector<std::unique_ptr<SavePageRequest>>())))) { | |
| 443 return; | 420 return; |
| 444 } | 421 } |
| 445 | 422 |
| 446 background_task_runner_->PostTask( | 423 background_task_runner_->PostTask( |
| 447 FROM_HERE, | 424 FROM_HERE, |
| 448 base::Bind(&RemoveRequestsSync, db_.get(), | 425 base::Bind(&RemoveRequestsSync, db_.get(), |
| 449 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | 426 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); |
| 450 } | 427 } |
| 451 | 428 |
| 452 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { | 429 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 // Complete connection initialization post reset. | 465 // Complete connection initialization post reset. |
| 489 OnOpenConnectionDone(state); | 466 OnOpenConnectionDone(state); |
| 490 callback.Run(state == StoreState::LOADED); | 467 callback.Run(state == StoreState::LOADED); |
| 491 } | 468 } |
| 492 | 469 |
| 493 StoreState RequestQueueStoreSQL::state() const { | 470 StoreState RequestQueueStoreSQL::state() const { |
| 494 return state_; | 471 return state_; |
| 495 } | 472 } |
| 496 | 473 |
| 497 } // namespace offline_pages | 474 } // namespace offline_pages |
| OLD | NEW |