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" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 const char kSql[] = "DELETE FROM " REQUEST_QUEUE_TABLE_NAME | 70 const char kSql[] = "DELETE FROM " REQUEST_QUEUE_TABLE_NAME |
| 71 " WHERE client_namespace=? AND client_id=?"; | 71 " WHERE client_namespace=? AND client_id=?"; |
| 72 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 72 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 73 statement.BindString(0, client_id.name_space); | 73 statement.BindString(0, client_id.name_space); |
| 74 statement.BindString(1, client_id.id); | 74 statement.BindString(1, client_id.id); |
| 75 DVLOG(2) << kSql << " client_namespace " << client_id.name_space | 75 DVLOG(2) << kSql << " client_namespace " << client_id.name_space |
| 76 << " client_id " << client_id.id; | 76 << " client_id " << client_id.id; |
| 77 return statement.Run(); | 77 return statement.Run(); |
| 78 } | 78 } |
| 79 | 79 |
| 80 bool PauseRequest(sql::Connection* db, const int64_t request_id) { | |
| 81 const char kSql[] = "UPDATE " REQUEST_QUEUE_TABLE_NAME | |
| 82 " SET state=?" | |
| 83 " WHERE request_id=?"; | |
| 84 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | |
| 85 statement.BindInt64( | |
| 86 0, static_cast<long>(SavePageRequest::RequestState::PAUSED)); | |
| 87 statement.BindInt64(1, request_id); | |
| 88 return statement.Run(); | |
| 89 } | |
| 90 | |
| 91 bool ResumeRequest(sql::Connection* db, const int64_t request_id) { | |
| 92 const char kSql[] = "UPDATE " REQUEST_QUEUE_TABLE_NAME | |
| 93 " SET state=?" | |
| 94 " WHERE request_id=?"; | |
| 95 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | |
| 96 statement.BindInt64( | |
| 97 0, static_cast<long>(SavePageRequest::RequestState::AVAILABLE)); | |
| 98 statement.BindInt64(1, request_id); | |
| 99 return statement.Run(); | |
| 100 } | |
| 101 | |
| 80 bool DeleteRequestsByIds(sql::Connection* db, | 102 bool DeleteRequestsByIds(sql::Connection* db, |
| 81 const std::vector<int64_t>& request_ids, | 103 const std::vector<int64_t>& request_ids, |
| 82 int* count) { | 104 int* count) { |
| 83 DCHECK(count); | 105 DCHECK(count); |
| 84 // If you create a transaction but don't Commit() it is automatically | 106 // If you create a transaction but don't Commit() it is automatically |
| 85 // rolled back by its destructor when it falls out of scope. | 107 // rolled back by its destructor when it falls out of scope. |
| 86 sql::Transaction transaction(db); | 108 sql::Transaction transaction(db); |
| 87 if (!transaction.Begin()) | 109 if (!transaction.Begin()) |
| 88 return false; | 110 return false; |
| 89 | 111 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 116 return false; | 138 return false; |
| 117 *count += db->GetLastChangeCount(); | 139 *count += db->GetLastChangeCount(); |
| 118 } | 140 } |
| 119 | 141 |
| 120 if (!transaction.Commit()) | 142 if (!transaction.Commit()) |
| 121 return false; | 143 return false; |
| 122 | 144 |
| 123 return true; | 145 return true; |
| 124 } | 146 } |
| 125 | 147 |
| 148 RequestQueueStore::UpdateStatus PauseRequests( | |
| 149 sql::Connection* db, const std::vector<int64_t>& request_ids) { | |
| 150 // If you create a transaction but don't Commit() it is automatically | |
| 151 // rolled back by its destructor when it falls out of scope. | |
| 152 sql::Transaction transaction(db); | |
| 153 if (!transaction.Begin()) | |
| 154 return RequestQueueStore::UpdateStatus::FAILED; | |
| 155 for (const auto& request_id : request_ids) { | |
| 156 if (!PauseRequest(db, request_id)) | |
| 157 return RequestQueueStore::UpdateStatus::FAILED; | |
| 158 } | |
| 159 | |
| 160 if (!transaction.Commit()) | |
| 161 return RequestQueueStore::UpdateStatus::FAILED; | |
| 162 | |
| 163 return RequestQueueStore::UpdateStatus::UPDATED; | |
| 164 } | |
| 165 | |
| 166 RequestQueueStore::UpdateStatus ResumeRequests( | |
| 167 sql::Connection* db, const std::vector<int64_t>& request_ids) { | |
| 168 // If you create a transaction but don't Commit() it is automatically | |
| 169 // rolled back by its destructor when it falls out of scope. | |
| 170 sql::Transaction transaction(db); | |
| 171 if (!transaction.Begin()) | |
| 172 return RequestQueueStore::UpdateStatus::FAILED; | |
| 173 | |
| 174 for (const auto& request_id : request_ids) { | |
| 175 if (!ResumeRequest(db, request_id)) | |
| 176 return RequestQueueStore::UpdateStatus::FAILED; | |
| 177 } | |
| 178 | |
| 179 if (!transaction.Commit()) | |
| 180 return RequestQueueStore::UpdateStatus::FAILED; | |
| 181 | |
| 182 return RequestQueueStore::UpdateStatus::UPDATED; | |
| 183 } | |
| 184 | |
| 126 // Create a save page request from a SQL result. Expects complete rows with | 185 // Create a save page request from a SQL result. Expects complete rows with |
| 127 // all columns present. Columns are in order they are defined in select query | 186 // all columns present. Columns are in order they are defined in select query |
| 128 // in |RequestQueueStore::RequestSync| method. | 187 // in |RequestQueueStore::RequestSync| method. |
| 129 SavePageRequest MakeSavePageRequest(const sql::Statement& statement) { | 188 SavePageRequest MakeSavePageRequest(const sql::Statement& statement) { |
| 130 const int64_t id = statement.ColumnInt64(0); | 189 const int64_t id = statement.ColumnInt64(0); |
| 131 const base::Time creation_time = | 190 const base::Time creation_time = |
| 132 base::Time::FromInternalValue(statement.ColumnInt64(1)); | 191 base::Time::FromInternalValue(statement.ColumnInt64(1)); |
| 133 const base::Time activation_time = | 192 const base::Time activation_time = |
| 134 base::Time::FromInternalValue(statement.ColumnInt64(2)); | 193 base::Time::FromInternalValue(statement.ColumnInt64(2)); |
| 135 const base::Time last_attempt_time = | 194 const base::Time last_attempt_time = |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 const RemoveCallback& callback) { | 342 const RemoveCallback& callback) { |
| 284 // TODO(fgorski): add UMA metrics here. | 343 // TODO(fgorski): add UMA metrics here. |
| 285 int count = 0; | 344 int count = 0; |
| 286 if (DeleteRequestsByClientIds(db, client_ids, &count)) | 345 if (DeleteRequestsByClientIds(db, client_ids, &count)) |
| 287 runner->PostTask(FROM_HERE, base::Bind(callback, true, count)); | 346 runner->PostTask(FROM_HERE, base::Bind(callback, true, count)); |
| 288 else | 347 else |
| 289 runner->PostTask(FROM_HERE, base::Bind(callback, false, 0)); | 348 runner->PostTask(FROM_HERE, base::Bind(callback, false, 0)); |
| 290 } | 349 } |
| 291 | 350 |
| 292 // static | 351 // static |
| 352 void RequestQueueStoreSQL::PauseRequestsSync( | |
|
Dmitry Titov
2016/08/09 23:46:33
I am not sure the store must have methods like Pau
Pete Williamson
2016/08/10 01:34:10
Done.
| |
| 353 sql::Connection* db, | |
| 354 scoped_refptr<base::SingleThreadTaskRunner> runner, | |
| 355 const std::vector<int64_t>& request_ids, | |
| 356 const UpdateCallback& callback) { | |
| 357 // TODO(fgorski): add UMA metrics here. | |
| 358 RequestQueueStore::UpdateStatus status = | |
| 359 offline_pages::PauseRequests(db, request_ids); | |
| 360 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | |
| 361 } | |
| 362 | |
| 363 // static | |
| 364 void RequestQueueStoreSQL::ResumeRequestsSync( | |
| 365 sql::Connection* db, | |
| 366 scoped_refptr<base::SingleThreadTaskRunner> runner, | |
| 367 const std::vector<int64_t>& request_ids, | |
| 368 const UpdateCallback& callback) { | |
| 369 // TODO(fgorski): add UMA metrics here. | |
| 370 RequestQueueStore::UpdateStatus status = | |
| 371 offline_pages::ResumeRequests(db, request_ids); | |
| 372 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | |
| 373 } | |
| 374 | |
| 375 // static | |
| 293 void RequestQueueStoreSQL::ResetSync( | 376 void RequestQueueStoreSQL::ResetSync( |
| 294 sql::Connection* db, | 377 sql::Connection* db, |
| 295 const base::FilePath& db_file_path, | 378 const base::FilePath& db_file_path, |
| 296 scoped_refptr<base::SingleThreadTaskRunner> runner, | 379 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 297 const ResetCallback& callback) { | 380 const ResetCallback& callback) { |
| 298 // This method deletes the content of the whole store and reinitializes it. | 381 // This method deletes the content of the whole store and reinitializes it. |
| 299 bool success = db->Raze(); | 382 bool success = db->Raze(); |
| 300 db->Close(); | 383 db->Close(); |
| 301 if (success) | 384 if (success) |
| 302 success = InitDatabase(db, db_file_path); | 385 success = InitDatabase(db, db_file_path); |
| 303 runner->PostTask(FROM_HERE, base::Bind(callback, success)); | 386 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 304 } | 387 } |
| 305 | 388 |
| 306 void RequestQueueStoreSQL::GetRequests(const GetRequestsCallback& callback) { | 389 bool RequestQueueStoreSQL::CheckDb(const RemoveCallback& callback) { |
| 390 DCHECK(db_.get()); | |
| 391 if (!db_.get()) { | |
| 392 // Nothing to do, but post a callback instead of calling directly | |
| 393 // to preserve the async style behavior to prevent bugs. | |
| 394 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 395 FROM_HERE, base::Bind(callback, false, 0)); | |
| 396 return false; | |
| 397 } | |
| 398 return true; | |
| 399 } | |
| 400 | |
| 401 bool RequestQueueStoreSQL::CheckDb(const GetRequestsCallback& callback) { | |
| 307 DCHECK(db_.get()); | 402 DCHECK(db_.get()); |
| 308 if (!db_.get()) { | 403 if (!db_.get()) { |
| 309 // Nothing to do, but post a callback instead of calling directly | 404 // Nothing to do, but post a callback instead of calling directly |
| 310 // to preserve the async style behavior to prevent bugs. | 405 // to preserve the async style behavior to prevent bugs. |
| 311 base::ThreadTaskRunnerHandle::Get()->PostTask( | 406 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 312 FROM_HERE, base::Bind(callback, false, std::vector<SavePageRequest>())); | 407 FROM_HERE, base::Bind(callback, false, std::vector<SavePageRequest>())); |
| 408 return false; | |
| 409 } | |
| 410 return true; | |
| 411 } | |
| 412 | |
| 413 bool RequestQueueStoreSQL::CheckDb(const UpdateCallback& callback) { | |
|
Dmitry Titov
2016/08/09 23:46:33
The answer to multiple CheckDB functions is to pas
Pete Williamson
2016/08/10 01:34:10
Done.
| |
| 414 DCHECK(db_.get()); | |
| 415 if (!db_.get()) { | |
| 416 // Nothing to do, but post a callback instead of calling directly | |
| 417 // to preserve the async style behavior to prevent bugs. | |
| 418 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 419 FROM_HERE, base::Bind(callback, UpdateStatus::FAILED)); | |
| 420 return false; | |
| 421 } | |
| 422 | |
| 423 return true; | |
| 424 } | |
| 425 | |
| 426 bool RequestQueueStoreSQL::CheckDb(const ResetCallback& callback) { | |
| 427 DCHECK(db_.get()); | |
| 428 if (!db_.get()) { | |
| 429 // Nothing to do, but post a callback instead of calling directly | |
| 430 // to preserve the async style behavior to prevent bugs. | |
| 431 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
| 432 base::Bind(callback, false)); | |
| 433 return false; | |
| 434 } | |
| 435 | |
| 436 return true; | |
| 437 } | |
| 438 | |
| 439 void RequestQueueStoreSQL::GetRequests(const GetRequestsCallback& callback) { | |
| 440 DCHECK(db_.get()); | |
| 441 if (!CheckDb(callback)) | |
| 313 return; | 442 return; |
| 314 } | |
| 315 | 443 |
| 316 background_task_runner_->PostTask( | 444 background_task_runner_->PostTask( |
| 317 FROM_HERE, base::Bind(&RequestQueueStoreSQL::GetRequestsSync, db_.get(), | 445 FROM_HERE, base::Bind(&RequestQueueStoreSQL::GetRequestsSync, db_.get(), |
| 318 base::ThreadTaskRunnerHandle::Get(), callback)); | 446 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 319 } | 447 } |
| 320 | 448 |
| 321 void RequestQueueStoreSQL::AddOrUpdateRequest(const SavePageRequest& request, | 449 void RequestQueueStoreSQL::AddOrUpdateRequest(const SavePageRequest& request, |
| 322 const UpdateCallback& callback) { | 450 const UpdateCallback& callback) { |
| 323 DCHECK(db_.get()); | 451 DCHECK(db_.get()); |
| 324 if (!db_.get()) { | 452 if (!CheckDb(callback)) |
| 325 // Nothing to do, but post a callback instead of calling directly | |
| 326 // to preserve the async style behavior to prevent bugs. | |
| 327 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 328 FROM_HERE, base::Bind(callback, UpdateStatus::FAILED)); | |
| 329 return; | 453 return; |
| 330 } | |
| 331 | 454 |
| 332 background_task_runner_->PostTask( | 455 background_task_runner_->PostTask( |
| 333 FROM_HERE, | 456 FROM_HERE, |
| 334 base::Bind(&RequestQueueStoreSQL::AddOrUpdateRequestSync, db_.get(), | 457 base::Bind(&RequestQueueStoreSQL::AddOrUpdateRequestSync, db_.get(), |
| 335 base::ThreadTaskRunnerHandle::Get(), request, callback)); | 458 base::ThreadTaskRunnerHandle::Get(), request, callback)); |
| 336 } | 459 } |
| 337 | 460 |
| 338 // TODO(petewil): This is unused, since request_coordinator doesn't keep | |
| 339 // request_ids, and neither do clients. Plan is to remove this API in a future | |
| 340 // changelist. If we do discover a need to keep it, name it | |
| 341 // RemoveRequestsByRequestId to be more parallell with RemoveRequestsByClientId. | |
| 342 void RequestQueueStoreSQL::RemoveRequests( | 461 void RequestQueueStoreSQL::RemoveRequests( |
| 343 const std::vector<int64_t>& request_ids, | 462 const std::vector<int64_t>& request_ids, |
| 344 const RemoveCallback& callback) { | 463 const RemoveCallback& callback) { |
| 345 DCHECK(db_.get()); | 464 if (!CheckDb(callback)) |
| 346 if (!db_.get()) { | |
| 347 // Nothing to do, but post a callback instead of calling directly | |
| 348 // to preserve the async style behavior to prevent bugs. | |
| 349 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 350 FROM_HERE, base::Bind(callback, false, 0)); | |
| 351 return; | 465 return; |
| 352 } | |
| 353 | 466 |
| 354 background_task_runner_->PostTask( | 467 background_task_runner_->PostTask( |
| 355 FROM_HERE, | 468 FROM_HERE, |
| 356 base::Bind(&RequestQueueStoreSQL::RemoveRequestsSync, db_.get(), | 469 base::Bind(&RequestQueueStoreSQL::RemoveRequestsSync, db_.get(), |
| 357 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | 470 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); |
| 358 } | 471 } |
| 359 | 472 |
| 360 void RequestQueueStoreSQL::RemoveRequestsByClientId( | 473 void RequestQueueStoreSQL::RemoveRequestsByClientId( |
| 361 const std::vector<ClientId>& client_ids, | 474 const std::vector<ClientId>& client_ids, |
| 362 const RemoveCallback& callback) { | 475 const RemoveCallback& callback) { |
| 363 DCHECK(db_.get()); | 476 DCHECK(db_.get()); |
| 364 if (!db_.get()) { | 477 if (!db_.get()) { |
| 365 // Nothing to do, but post a callback instead of calling directly | 478 // Nothing to do, but post a callback instead of calling directly |
| 366 // to preserve the async style behavior to prevent bugs. | 479 // to preserve the async style behavior to prevent bugs. |
| 367 base::ThreadTaskRunnerHandle::Get()->PostTask( | 480 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 368 FROM_HERE, base::Bind(callback, false, 0)); | 481 FROM_HERE, base::Bind(callback, false, 0)); |
| 369 return; | 482 return; |
| 370 } | 483 } |
| 371 | 484 |
| 372 background_task_runner_->PostTask( | 485 background_task_runner_->PostTask( |
| 373 FROM_HERE, | 486 FROM_HERE, |
| 374 base::Bind(&RequestQueueStoreSQL::RemoveRequestsByClientIdSync, db_.get(), | 487 base::Bind(&RequestQueueStoreSQL::RemoveRequestsByClientIdSync, db_.get(), |
| 375 base::ThreadTaskRunnerHandle::Get(), client_ids, callback)); | 488 base::ThreadTaskRunnerHandle::Get(), client_ids, callback)); |
| 376 } | 489 } |
| 377 | 490 |
| 378 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { | 491 void RequestQueueStoreSQL::PauseRequests( |
| 379 DCHECK(db_.get()); | 492 const std::vector<int64_t>& request_ids, |
| 380 if (!db_.get()) { | 493 const UpdateCallback& callback) { |
| 381 // Nothing to do, but post a callback instead of calling directly | 494 if (!CheckDb(callback)) |
| 382 // to preserve the async style behavior to prevent bugs. | 495 return; |
| 383 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 496 |
| 384 base::Bind(callback, false)); | 497 background_task_runner_->PostTask( |
| 498 FROM_HERE, | |
| 499 base::Bind(&RequestQueueStoreSQL::PauseRequestsSync, db_.get(), | |
| 500 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | |
| 501 } | |
| 502 | |
| 503 void RequestQueueStoreSQL::ResumeRequests( | |
| 504 const std::vector<int64_t>& request_ids, | |
| 505 const UpdateCallback& callback) { | |
| 506 if (!CheckDb(callback)) { | |
| 385 return; | 507 return; |
| 386 } | 508 } |
| 387 | 509 |
| 510 background_task_runner_->PostTask( | |
| 511 FROM_HERE, | |
| 512 base::Bind(&RequestQueueStoreSQL::ResumeRequestsSync, db_.get(), | |
| 513 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | |
| 514 } | |
| 515 | |
| 516 | |
| 517 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { | |
| 518 DCHECK(db_.get()); | |
| 519 if (!CheckDb(callback)) { | |
| 520 return; | |
| 521 } | |
| 522 | |
| 388 background_task_runner_->PostTask( | 523 background_task_runner_->PostTask( |
| 389 FROM_HERE, | 524 FROM_HERE, |
| 390 base::Bind(&RequestQueueStoreSQL::ResetSync, db_.get(), db_file_path_, | 525 base::Bind(&RequestQueueStoreSQL::ResetSync, db_.get(), db_file_path_, |
| 391 base::ThreadTaskRunnerHandle::Get(), | 526 base::ThreadTaskRunnerHandle::Get(), |
| 392 base::Bind(&RequestQueueStoreSQL::OnResetDone, | 527 base::Bind(&RequestQueueStoreSQL::OnResetDone, |
| 393 weak_ptr_factory_.GetWeakPtr(), callback))); | 528 weak_ptr_factory_.GetWeakPtr(), callback))); |
| 394 } | 529 } |
| 395 | 530 |
| 396 void RequestQueueStoreSQL::OpenConnection() { | 531 void RequestQueueStoreSQL::OpenConnection() { |
| 397 DCHECK(!db_); | 532 DCHECK(!db_); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 413 } | 548 } |
| 414 | 549 |
| 415 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, | 550 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, |
| 416 bool success) { | 551 bool success) { |
| 417 // Complete connection initialization post reset. | 552 // Complete connection initialization post reset. |
| 418 OnOpenConnectionDone(success); | 553 OnOpenConnectionDone(success); |
| 419 callback.Run(success); | 554 callback.Run(success); |
| 420 } | 555 } |
| 421 | 556 |
| 422 } // namespace offline_pages | 557 } // namespace offline_pages |
| OLD | NEW |