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