| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 return false; | 51 return false; |
| 52 } | 52 } |
| 53 | 53 |
| 54 if (!CreateRequestQueueTable(db)) | 54 if (!CreateRequestQueueTable(db)) |
| 55 return false; | 55 return false; |
| 56 | 56 |
| 57 // TODO(fgorski): Add indices here. | 57 // TODO(fgorski): Add indices here. |
| 58 return true; | 58 return true; |
| 59 } | 59 } |
| 60 | 60 |
| 61 // Create a save page request from a SQL result. Expects complete rows with |
| 62 // all columns present. Columns are in order they are defined in select query |
| 63 // in |RequestQueueStore::RequestSync| method. |
| 64 SavePageRequest MakeSavePageRequest(const sql::Statement& statement) { |
| 65 const int64_t id = statement.ColumnInt64(0); |
| 66 const base::Time creation_time = |
| 67 base::Time::FromInternalValue(statement.ColumnInt64(1)); |
| 68 const base::Time activation_time = |
| 69 base::Time::FromInternalValue(statement.ColumnInt64(2)); |
| 70 const base::Time last_attempt_time = |
| 71 base::Time::FromInternalValue(statement.ColumnInt64(3)); |
| 72 const int64_t started_attempt_count = statement.ColumnInt64(4); |
| 73 const int64_t completed_attempt_count = statement.ColumnInt64(5); |
| 74 const SavePageRequest::RequestState state = |
| 75 static_cast<SavePageRequest::RequestState>(statement.ColumnInt64(6)); |
| 76 const GURL url(statement.ColumnString(7)); |
| 77 const ClientId client_id(statement.ColumnString(8), |
| 78 statement.ColumnString(9)); |
| 79 |
| 80 DVLOG(2) << "making save page request - id " << id << " url " << url |
| 81 << " client_id " << client_id.name_space << "-" << client_id.id |
| 82 << " creation time " << creation_time << " user requested " |
| 83 << kUserRequested; |
| 84 |
| 85 SavePageRequest request(id, url, client_id, creation_time, activation_time, |
| 86 kUserRequested); |
| 87 request.set_last_attempt_time(last_attempt_time); |
| 88 request.set_started_attempt_count(started_attempt_count); |
| 89 request.set_completed_attempt_count(completed_attempt_count); |
| 90 request.set_request_state(state); |
| 91 return request; |
| 92 } |
| 93 |
| 94 // Get a request for a specific id. |
| 95 SavePageRequest GetOneRequest(sql::Connection* db, const int64_t request_id) { |
| 96 const char kSql[] = |
| 97 "SELECT request_id, creation_time, activation_time," |
| 98 " last_attempt_time, started_attempt_count, completed_attempt_count," |
| 99 " state, url, client_namespace, client_id" |
| 100 " FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; |
| 101 |
| 102 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 103 statement.BindInt64(0, request_id); |
| 104 |
| 105 statement.Run(); |
| 106 return MakeSavePageRequest(statement); |
| 107 } |
| 108 |
| 109 void BuildFailedResultList(const std::vector<int64_t>& request_ids, |
| 110 RequestQueue::UpdateMultipleRequestResults results) { |
| 111 results.clear(); |
| 112 for (int64_t request_id : request_ids) |
| 113 results.push_back(std::make_pair( |
| 114 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); |
| 115 } |
| 116 |
| 61 bool DeleteRequestById(sql::Connection* db, int64_t request_id) { | 117 bool DeleteRequestById(sql::Connection* db, int64_t request_id) { |
| 62 const char kSql[] = | 118 const char kSql[] = |
| 63 "DELETE FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; | 119 "DELETE FROM " REQUEST_QUEUE_TABLE_NAME " WHERE request_id=?"; |
| 64 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 120 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 65 statement.BindInt64(0, request_id); | 121 statement.BindInt64(0, request_id); |
| 66 return statement.Run(); | 122 return statement.Run(); |
| 67 } | 123 } |
| 68 | 124 |
| 69 bool ChangeRequestState(sql::Connection* db, | 125 bool ChangeRequestState(sql::Connection* db, |
| 70 const int64_t request_id, | 126 const int64_t request_id, |
| 71 const SavePageRequest::RequestState new_state) { | 127 const SavePageRequest::RequestState new_state) { |
| 72 const char kSql[] = "UPDATE " REQUEST_QUEUE_TABLE_NAME | 128 const char kSql[] = "UPDATE " REQUEST_QUEUE_TABLE_NAME |
| 73 " SET state=?" | 129 " SET state=?" |
| 74 " WHERE request_id=?"; | 130 " WHERE request_id=?"; |
| 75 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 131 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 76 statement.BindInt64(0, static_cast<int64_t>(new_state)); | 132 statement.BindInt64(0, static_cast<int64_t>(new_state)); |
| 77 statement.BindInt64(1, request_id); | 133 statement.BindInt64(1, request_id); |
| 78 return statement.Run(); | 134 return statement.Run(); |
| 79 } | 135 } |
| 80 | 136 |
| 81 bool DeleteRequestsByIds(sql::Connection* db, | 137 bool DeleteRequestsByIds(sql::Connection* db, |
| 82 const std::vector<int64_t>& request_ids, | 138 const std::vector<int64_t>& request_ids, |
| 83 RequestQueue::UpdateMultipleRequestResults& results) { | 139 RequestQueue::UpdateMultipleRequestResults& results, |
| 140 std::vector<SavePageRequest>& requests) { |
| 84 // If you create a transaction but don't Commit() it is automatically | 141 // If you create a transaction but don't Commit() it is automatically |
| 85 // rolled back by its destructor when it falls out of scope. | 142 // rolled back by its destructor when it falls out of scope. |
| 86 sql::Transaction transaction(db); | 143 sql::Transaction transaction(db); |
| 87 if (!transaction.Begin()) { | 144 if (!transaction.Begin()) { |
| 88 for (int64_t request_id : request_ids) | 145 BuildFailedResultList(request_ids, results); |
| 89 results.push_back(std::make_pair( | |
| 90 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | |
| 91 return false; | 146 return false; |
| 92 } | 147 } |
| 93 | 148 |
| 94 for (auto request_id : request_ids) { | 149 // Read the request before we delete it, and if the delete worked, put it on |
| 150 // the queue of requests that got deleted. |
| 151 for (int64_t request_id : request_ids) { |
| 152 SavePageRequest request = GetOneRequest(db, request_id); |
| 95 RequestQueue::UpdateRequestResult result; | 153 RequestQueue::UpdateRequestResult result; |
| 96 if (DeleteRequestById(db, request_id)) | 154 if (DeleteRequestById(db, request_id)) { |
| 97 result = RequestQueue::UpdateRequestResult::SUCCESS; | 155 result = RequestQueue::UpdateRequestResult::SUCCESS; |
| 98 else | 156 requests.push_back(request); |
| 157 } else { |
| 99 result = RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 158 result = RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 159 } |
| 100 results.push_back(std::make_pair(request_id, result)); | 160 results.push_back(std::make_pair(request_id, result)); |
| 161 requests.push_back(request); |
| 101 } | 162 } |
| 102 | 163 |
| 103 if (!transaction.Commit()) { | 164 if (!transaction.Commit()) { |
| 104 results.clear(); | 165 requests.clear(); |
| 105 for (int64_t request_id : request_ids) | 166 BuildFailedResultList(request_ids, results); |
| 106 results.push_back(std::make_pair( | |
| 107 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | |
| 108 return false; | 167 return false; |
| 109 } | 168 } |
| 110 | 169 |
| 111 return true; | 170 return true; |
| 112 } | 171 } |
| 113 | 172 |
| 114 RequestQueueStore::UpdateStatus ChangeRequestsState( | 173 bool ChangeRequestsState(sql::Connection* db, |
| 115 sql::Connection* db, | 174 const std::vector<int64_t>& request_ids, |
| 116 const std::vector<int64_t>& request_ids, | 175 SavePageRequest::RequestState new_state, |
| 117 SavePageRequest::RequestState new_state) { | 176 RequestQueue::UpdateMultipleRequestResults& results, |
| 177 std::vector<SavePageRequest>& requests) { |
| 118 // If you create a transaction but don't Commit() it is automatically | 178 // If you create a transaction but don't Commit() it is automatically |
| 119 // rolled back by its destructor when it falls out of scope. | 179 // rolled back by its destructor when it falls out of scope. |
| 120 sql::Transaction transaction(db); | 180 sql::Transaction transaction(db); |
| 121 if (!transaction.Begin()) | 181 if (!transaction.Begin()) { |
| 122 return RequestQueueStore::UpdateStatus::FAILED; | 182 BuildFailedResultList(request_ids, results); |
| 123 for (const auto& request_id : request_ids) { | 183 return false; |
| 124 if (!ChangeRequestState(db, request_id, new_state)) | |
| 125 return RequestQueueStore::UpdateStatus::FAILED; | |
| 126 } | 184 } |
| 127 | 185 |
| 128 if (!transaction.Commit()) | 186 // Update a request, then get it, and put the item we got on the output list. |
| 129 return RequestQueueStore::UpdateStatus::FAILED; | 187 for (const auto& request_id : request_ids) { |
| 188 RequestQueue::UpdateRequestResult status; |
| 189 if (!ChangeRequestState(db, request_id, new_state)) |
| 190 status = RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 191 else |
| 192 status = RequestQueue::UpdateRequestResult::SUCCESS; |
| 130 | 193 |
| 131 return RequestQueueStore::UpdateStatus::UPDATED; | 194 // Make output request_id/status pair, and put a copy of the updated request |
| 132 } | 195 // on output list. |
| 196 results.push_back(std::make_pair(request_id, status)); |
| 197 requests.push_back(GetOneRequest(db, request_id)); |
| 198 } |
| 133 | 199 |
| 134 // Create a save page request from a SQL result. Expects complete rows with | 200 if (!transaction.Commit()) { |
| 135 // all columns present. Columns are in order they are defined in select query | 201 requests.clear(); |
| 136 // in |RequestQueueStore::RequestSync| method. | 202 BuildFailedResultList(request_ids, results); |
| 137 SavePageRequest MakeSavePageRequest(const sql::Statement& statement) { | 203 return false; |
| 138 const int64_t id = statement.ColumnInt64(0); | 204 } |
| 139 const base::Time creation_time = | |
| 140 base::Time::FromInternalValue(statement.ColumnInt64(1)); | |
| 141 const base::Time activation_time = | |
| 142 base::Time::FromInternalValue(statement.ColumnInt64(2)); | |
| 143 const base::Time last_attempt_time = | |
| 144 base::Time::FromInternalValue(statement.ColumnInt64(3)); | |
| 145 const int64_t started_attempt_count = statement.ColumnInt64(4); | |
| 146 const int64_t completed_attempt_count = statement.ColumnInt64(5); | |
| 147 const SavePageRequest::RequestState state = | |
| 148 static_cast<SavePageRequest::RequestState>(statement.ColumnInt64(6)); | |
| 149 const GURL url(statement.ColumnString(7)); | |
| 150 const ClientId client_id(statement.ColumnString(8), | |
| 151 statement.ColumnString(9)); | |
| 152 | 205 |
| 153 DVLOG(2) << "making save page request - id " << id << " url " << url | 206 return true; |
| 154 << " client_id " << client_id.name_space << "-" << client_id.id | |
| 155 << " creation time " << creation_time << " user requested " | |
| 156 << kUserRequested; | |
| 157 | |
| 158 SavePageRequest request( | |
| 159 id, url, client_id, creation_time, activation_time, kUserRequested); | |
| 160 request.set_last_attempt_time(last_attempt_time); | |
| 161 request.set_started_attempt_count(started_attempt_count); | |
| 162 request.set_completed_attempt_count(completed_attempt_count); | |
| 163 request.set_request_state(state); | |
| 164 return request; | |
| 165 } | 207 } |
| 166 | 208 |
| 167 RequestQueueStore::UpdateStatus InsertOrReplace( | 209 RequestQueueStore::UpdateStatus InsertOrReplace( |
| 168 sql::Connection* db, | 210 sql::Connection* db, |
| 169 const SavePageRequest& request) { | 211 const SavePageRequest& request) { |
| 170 // In order to use the enums in the Bind* methods, keep the order of fields | 212 // In order to use the enums in the Bind* methods, keep the order of fields |
| 171 // the same as in the definition/select query. | 213 // the same as in the definition/select query. |
| 172 const char kInsertSql[] = | 214 const char kInsertSql[] = |
| 173 "INSERT OR REPLACE INTO " REQUEST_QUEUE_TABLE_NAME | 215 "INSERT OR REPLACE INTO " REQUEST_QUEUE_TABLE_NAME |
| 174 " (request_id, creation_time, activation_time, last_attempt_time, " | 216 " (request_id, creation_time, activation_time, last_attempt_time, " |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | 311 runner->PostTask(FROM_HERE, base::Bind(callback, status)); |
| 270 } | 312 } |
| 271 | 313 |
| 272 // static | 314 // static |
| 273 void RequestQueueStoreSQL::RemoveRequestsSync( | 315 void RequestQueueStoreSQL::RemoveRequestsSync( |
| 274 sql::Connection* db, | 316 sql::Connection* db, |
| 275 scoped_refptr<base::SingleThreadTaskRunner> runner, | 317 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 276 const std::vector<int64_t>& request_ids, | 318 const std::vector<int64_t>& request_ids, |
| 277 const RemoveCallback& callback) { | 319 const RemoveCallback& callback) { |
| 278 RequestQueue::UpdateMultipleRequestResults results; | 320 RequestQueue::UpdateMultipleRequestResults results; |
| 321 std::vector<SavePageRequest> requests; |
| 279 // TODO(fgorski): add UMA metrics here. | 322 // TODO(fgorski): add UMA metrics here. |
| 280 DeleteRequestsByIds(db, request_ids, results); | 323 DeleteRequestsByIds(db, request_ids, results, requests); |
| 281 runner->PostTask(FROM_HERE, base::Bind(callback, results)); | 324 runner->PostTask(FROM_HERE, base::Bind(callback, results, requests)); |
| 282 } | 325 } |
| 283 | 326 |
| 284 // static | 327 // static |
| 285 void RequestQueueStoreSQL::ChangeRequestsStateSync( | 328 void RequestQueueStoreSQL::ChangeRequestsStateSync( |
| 286 sql::Connection* db, | 329 sql::Connection* db, |
| 287 scoped_refptr<base::SingleThreadTaskRunner> runner, | 330 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 288 const std::vector<int64_t>& request_ids, | 331 const std::vector<int64_t>& request_ids, |
| 289 const SavePageRequest::RequestState new_state, | 332 const SavePageRequest::RequestState new_state, |
| 290 const UpdateCallback& callback) { | 333 const UpdateMultipleRequestsCallback& callback) { |
| 334 RequestQueue::UpdateMultipleRequestResults results; |
| 335 std::vector<SavePageRequest> requests; |
| 291 // TODO(fgorski): add UMA metrics here. | 336 // TODO(fgorski): add UMA metrics here. |
| 292 RequestQueueStore::UpdateStatus status = | 337 offline_pages::ChangeRequestsState(db, request_ids, new_state, results, |
| 293 offline_pages::ChangeRequestsState(db, request_ids, new_state); | 338 requests); |
| 294 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | 339 runner->PostTask(FROM_HERE, base::Bind(callback, results, requests)); |
| 295 } | 340 } |
| 296 | 341 |
| 297 // static | 342 // static |
| 298 void RequestQueueStoreSQL::ResetSync( | 343 void RequestQueueStoreSQL::ResetSync( |
| 299 sql::Connection* db, | 344 sql::Connection* db, |
| 300 const base::FilePath& db_file_path, | 345 const base::FilePath& db_file_path, |
| 301 scoped_refptr<base::SingleThreadTaskRunner> runner, | 346 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 302 const ResetCallback& callback) { | 347 const ResetCallback& callback) { |
| 303 // This method deletes the content of the whole store and reinitializes it. | 348 // This method deletes the content of the whole store and reinitializes it. |
| 304 bool success = db->Raze(); | 349 bool success = db->Raze(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 base::Bind(&RequestQueueStoreSQL::AddOrUpdateRequestSync, db_.get(), | 386 base::Bind(&RequestQueueStoreSQL::AddOrUpdateRequestSync, db_.get(), |
| 342 base::ThreadTaskRunnerHandle::Get(), request, callback)); | 387 base::ThreadTaskRunnerHandle::Get(), request, callback)); |
| 343 } | 388 } |
| 344 | 389 |
| 345 // RemoveRequestsByRequestId to be more parallell with RemoveRequestsByClientId. | 390 // RemoveRequestsByRequestId to be more parallell with RemoveRequestsByClientId. |
| 346 void RequestQueueStoreSQL::RemoveRequests( | 391 void RequestQueueStoreSQL::RemoveRequests( |
| 347 const std::vector<int64_t>& request_ids, | 392 const std::vector<int64_t>& request_ids, |
| 348 const RemoveCallback& callback) { | 393 const RemoveCallback& callback) { |
| 349 // Set up a failed set of results in case we fail the DB check. | 394 // Set up a failed set of results in case we fail the DB check. |
| 350 RequestQueue::UpdateMultipleRequestResults results; | 395 RequestQueue::UpdateMultipleRequestResults results; |
| 351 for (int64_t request_id : request_ids) | 396 std::vector<SavePageRequest> requests; |
| 352 results.push_back(std::make_pair( | 397 for (int64_t request_id : request_ids) |
| 353 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | 398 results.push_back(std::make_pair( |
| 399 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); |
| 354 | 400 |
| 355 if (!CheckDb(base::Bind(callback, results))) | 401 if (!CheckDb(base::Bind(callback, results, requests))) |
| 356 return; | 402 return; |
| 357 | 403 |
| 358 background_task_runner_->PostTask( | 404 background_task_runner_->PostTask( |
| 359 FROM_HERE, | 405 FROM_HERE, |
| 360 base::Bind(&RequestQueueStoreSQL::RemoveRequestsSync, db_.get(), | 406 base::Bind(&RequestQueueStoreSQL::RemoveRequestsSync, db_.get(), |
| 361 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | 407 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); |
| 362 } | 408 } |
| 363 | 409 |
| 364 void RequestQueueStoreSQL::ChangeRequestsState( | 410 void RequestQueueStoreSQL::ChangeRequestsState( |
| 365 const std::vector<int64_t>& request_ids, | 411 const std::vector<int64_t>& request_ids, |
| 366 const SavePageRequest::RequestState new_state, | 412 const SavePageRequest::RequestState new_state, |
| 367 const UpdateCallback& callback) { | 413 const UpdateMultipleRequestsCallback& callback) { |
| 368 if (!CheckDb(base::Bind(callback, UpdateStatus::FAILED))) | 414 RequestQueue::UpdateMultipleRequestResults results; |
| 415 std::vector<SavePageRequest> requests; |
| 416 if (!CheckDb(base::Bind(callback, results, requests))) |
| 369 return; | 417 return; |
| 370 | 418 |
| 371 background_task_runner_->PostTask( | 419 background_task_runner_->PostTask( |
| 372 FROM_HERE, base::Bind(&RequestQueueStoreSQL::ChangeRequestsStateSync, | 420 FROM_HERE, base::Bind(&RequestQueueStoreSQL::ChangeRequestsStateSync, |
| 373 db_.get(), base::ThreadTaskRunnerHandle::Get(), | 421 db_.get(), base::ThreadTaskRunnerHandle::Get(), |
| 374 request_ids, new_state, callback)); | 422 request_ids, new_state, callback)); |
| 375 } | 423 } |
| 376 | 424 |
| 377 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { | 425 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { |
| 378 DCHECK(db_.get()); | 426 DCHECK(db_.get()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 407 } | 455 } |
| 408 | 456 |
| 409 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, | 457 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, |
| 410 bool success) { | 458 bool success) { |
| 411 // Complete connection initialization post reset. | 459 // Complete connection initialization post reset. |
| 412 OnOpenConnectionDone(success); | 460 OnOpenConnectionDone(success); |
| 413 callback.Run(success); | 461 callback.Run(success); |
| 414 } | 462 } |
| 415 | 463 |
| 416 } // namespace offline_pages | 464 } // namespace offline_pages |
| OLD | NEW |