| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 | 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 | 62 // all columns present. Columns are in order they are defined in select query |
| 63 // in |RequestQueueStore::RequestSync| method. | 63 // in |GetOneRequest| method. |
| 64 std::unique_ptr<SavePageRequest> MakeSavePageRequest( | 64 std::unique_ptr<SavePageRequest> MakeSavePageRequest( |
| 65 const sql::Statement& statement) { | 65 const sql::Statement& statement) { |
| 66 const int64_t id = statement.ColumnInt64(0); | 66 const int64_t id = statement.ColumnInt64(0); |
| 67 const base::Time creation_time = | 67 const base::Time creation_time = |
| 68 base::Time::FromInternalValue(statement.ColumnInt64(1)); | 68 base::Time::FromInternalValue(statement.ColumnInt64(1)); |
| 69 const base::Time activation_time = | 69 const base::Time activation_time = |
| 70 base::Time::FromInternalValue(statement.ColumnInt64(2)); | 70 base::Time::FromInternalValue(statement.ColumnInt64(2)); |
| 71 const base::Time last_attempt_time = | 71 const base::Time last_attempt_time = |
| 72 base::Time::FromInternalValue(statement.ColumnInt64(3)); | 72 base::Time::FromInternalValue(statement.ColumnInt64(3)); |
| 73 const int64_t started_attempt_count = statement.ColumnInt64(4); | 73 const int64_t started_attempt_count = statement.ColumnInt64(4); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 base::File::Error err; | 255 base::File::Error err; |
| 256 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) | 256 if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) |
| 257 return false; | 257 return false; |
| 258 if (!db->Open(path)) | 258 if (!db->Open(path)) |
| 259 return false; | 259 return false; |
| 260 db->Preload(); | 260 db->Preload(); |
| 261 | 261 |
| 262 return CreateSchema(db); | 262 return CreateSchema(db); |
| 263 } | 263 } |
| 264 | 264 |
| 265 } // anonymous namespace | 265 void GetRequestsSync(sql::Connection* db, |
| 266 | 266 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 267 RequestQueueStoreSQL::RequestQueueStoreSQL( | 267 const RequestQueueStore::GetRequestsCallback& callback) { |
| 268 scoped_refptr<base::SequencedTaskRunner> background_task_runner, | |
| 269 const base::FilePath& path) | |
| 270 : background_task_runner_(std::move(background_task_runner)), | |
| 271 db_file_path_(path.AppendASCII("RequestQueue.db")), | |
| 272 weak_ptr_factory_(this) { | |
| 273 OpenConnection(); | |
| 274 } | |
| 275 | |
| 276 RequestQueueStoreSQL::~RequestQueueStoreSQL() { | |
| 277 if (db_.get()) | |
| 278 background_task_runner_->DeleteSoon(FROM_HERE, db_.release()); | |
| 279 } | |
| 280 | |
| 281 // static | |
| 282 void RequestQueueStoreSQL::OpenConnectionSync( | |
| 283 sql::Connection* db, | |
| 284 scoped_refptr<base::SingleThreadTaskRunner> runner, | |
| 285 const base::FilePath& path, | |
| 286 const base::Callback<void(bool)>& callback) { | |
| 287 bool success = InitDatabase(db, path); | |
| 288 runner->PostTask(FROM_HERE, base::Bind(callback, success)); | |
| 289 } | |
| 290 | |
| 291 // static | |
| 292 void RequestQueueStoreSQL::GetRequestsSync( | |
| 293 sql::Connection* db, | |
| 294 scoped_refptr<base::SingleThreadTaskRunner> runner, | |
| 295 const GetRequestsCallback& callback) { | |
| 296 const char kSql[] = | 268 const char kSql[] = |
| 297 "SELECT request_id, creation_time, activation_time," | 269 "SELECT request_id, creation_time, activation_time," |
| 298 " last_attempt_time, started_attempt_count, completed_attempt_count," | 270 " last_attempt_time, started_attempt_count, completed_attempt_count," |
| 299 " state, url, client_namespace, client_id" | 271 " state, url, client_namespace, client_id" |
| 300 " FROM " REQUEST_QUEUE_TABLE_NAME; | 272 " FROM " REQUEST_QUEUE_TABLE_NAME; |
| 301 | 273 |
| 302 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); | 274 sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); |
| 303 | 275 |
| 304 std::vector<std::unique_ptr<SavePageRequest>> requests; | 276 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 305 while (statement.Step()) | 277 while (statement.Step()) |
| 306 requests.push_back(MakeSavePageRequest(statement)); | 278 requests.push_back(MakeSavePageRequest(statement)); |
| 307 | 279 |
| 308 runner->PostTask(FROM_HERE, base::Bind(callback, statement.Succeeded(), | 280 runner->PostTask(FROM_HERE, base::Bind(callback, statement.Succeeded(), |
| 309 base::Passed(&requests))); | 281 base::Passed(&requests))); |
| 310 } | 282 } |
| 311 | 283 |
| 312 // static | 284 void AddOrUpdateRequestSync(sql::Connection* db, |
| 313 void RequestQueueStoreSQL::AddOrUpdateRequestSync( | 285 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 314 sql::Connection* db, | 286 const SavePageRequest& request, |
| 315 scoped_refptr<base::SingleThreadTaskRunner> runner, | 287 const RequestQueueStore::UpdateCallback& callback) { |
| 316 const SavePageRequest& request, | |
| 317 const UpdateCallback& callback) { | |
| 318 // TODO(fgorski): add UMA metrics here. | 288 // TODO(fgorski): add UMA metrics here. |
| 319 RequestQueueStore::UpdateStatus status = InsertOrReplace(db, request); | 289 RequestQueueStore::UpdateStatus status = InsertOrReplace(db, request); |
| 320 runner->PostTask(FROM_HERE, base::Bind(callback, status)); | 290 runner->PostTask(FROM_HERE, base::Bind(callback, status)); |
| 321 } | 291 } |
| 322 | 292 |
| 323 // static | 293 void RemoveRequestsSync(sql::Connection* db, |
| 324 void RequestQueueStoreSQL::RemoveRequestsSync( | 294 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 325 sql::Connection* db, | 295 const std::vector<int64_t>& request_ids, |
| 326 scoped_refptr<base::SingleThreadTaskRunner> runner, | 296 const RequestQueueStore::RemoveCallback& callback) { |
| 327 const std::vector<int64_t>& request_ids, | |
| 328 const RemoveCallback& callback) { | |
| 329 RequestQueue::UpdateMultipleRequestResults results; | 297 RequestQueue::UpdateMultipleRequestResults results; |
| 330 std::vector<std::unique_ptr<SavePageRequest>> requests; | 298 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 331 // TODO(fgorski): add UMA metrics here. | 299 // TODO(fgorski): add UMA metrics here. |
| 332 DeleteRequestsByIds(db, request_ids, results, &requests); | 300 DeleteRequestsByIds(db, request_ids, results, &requests); |
| 333 runner->PostTask(FROM_HERE, | 301 runner->PostTask(FROM_HERE, |
| 334 base::Bind(callback, results, base::Passed(&requests))); | 302 base::Bind(callback, results, base::Passed(&requests))); |
| 335 } | 303 } |
| 336 | 304 |
| 337 // static | 305 void ChangeRequestsStateSync( |
| 338 void RequestQueueStoreSQL::ChangeRequestsStateSync( | |
| 339 sql::Connection* db, | 306 sql::Connection* db, |
| 340 scoped_refptr<base::SingleThreadTaskRunner> runner, | 307 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 341 const std::vector<int64_t>& request_ids, | 308 const std::vector<int64_t>& request_ids, |
| 342 const SavePageRequest::RequestState new_state, | 309 const SavePageRequest::RequestState new_state, |
| 343 const UpdateMultipleRequestsCallback& callback) { | 310 const RequestQueue::UpdateMultipleRequestsCallback& callback) { |
| 344 RequestQueue::UpdateMultipleRequestResults results; | 311 RequestQueue::UpdateMultipleRequestResults results; |
| 345 std::vector<std::unique_ptr<SavePageRequest>> requests; | 312 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 346 // TODO(fgorski): add UMA metrics here. | 313 // TODO(fgorski): add UMA metrics here. |
| 347 offline_pages::ChangeRequestsState(db, request_ids, new_state, results, | 314 offline_pages::ChangeRequestsState(db, request_ids, new_state, results, |
| 348 requests); | 315 requests); |
| 349 runner->PostTask(FROM_HERE, | 316 runner->PostTask(FROM_HERE, |
| 350 base::Bind(callback, results, base::Passed(&requests))); | 317 base::Bind(callback, results, base::Passed(&requests))); |
| 351 } | 318 } |
| 352 | 319 |
| 353 // static | 320 void OpenConnectionSync(sql::Connection* db, |
| 354 void RequestQueueStoreSQL::ResetSync( | 321 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 355 sql::Connection* db, | 322 const base::FilePath& path, |
| 356 const base::FilePath& db_file_path, | 323 const base::Callback<void(bool)>& callback) { |
| 357 scoped_refptr<base::SingleThreadTaskRunner> runner, | 324 bool success = InitDatabase(db, path); |
| 358 const ResetCallback& callback) { | 325 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 326 } |
| 327 |
| 328 void ResetSync(sql::Connection* db, |
| 329 const base::FilePath& db_file_path, |
| 330 scoped_refptr<base::SingleThreadTaskRunner> runner, |
| 331 const RequestQueueStore::ResetCallback& callback) { |
| 359 // This method deletes the content of the whole store and reinitializes it. | 332 // This method deletes the content of the whole store and reinitializes it. |
| 360 bool success = db->Raze(); | 333 bool success = db->Raze(); |
| 361 db->Close(); | 334 db->Close(); |
| 362 if (success) | 335 if (success) |
| 363 success = InitDatabase(db, db_file_path); | 336 success = InitDatabase(db, db_file_path); |
| 364 runner->PostTask(FROM_HERE, base::Bind(callback, success)); | 337 runner->PostTask(FROM_HERE, base::Bind(callback, success)); |
| 365 } | 338 } |
| 366 | 339 |
| 340 } // anonymous namespace |
| 341 |
| 342 RequestQueueStoreSQL::RequestQueueStoreSQL( |
| 343 scoped_refptr<base::SequencedTaskRunner> background_task_runner, |
| 344 const base::FilePath& path) |
| 345 : background_task_runner_(std::move(background_task_runner)), |
| 346 db_file_path_(path.AppendASCII("RequestQueue.db")), |
| 347 weak_ptr_factory_(this) { |
| 348 OpenConnection(); |
| 349 } |
| 350 |
| 351 RequestQueueStoreSQL::~RequestQueueStoreSQL() { |
| 352 if (db_.get()) |
| 353 background_task_runner_->DeleteSoon(FROM_HERE, db_.release()); |
| 354 } |
| 355 |
| 367 bool RequestQueueStoreSQL::CheckDb(const base::Closure& callback) { | 356 bool RequestQueueStoreSQL::CheckDb(const base::Closure& callback) { |
| 368 DCHECK(db_.get()); | 357 DCHECK(db_.get()); |
| 369 if (!db_.get()) { | 358 if (!db_.get()) { |
| 370 // Nothing to do, but post a callback instead of calling directly | 359 // Nothing to do, but post a callback instead of calling directly |
| 371 // to preserve the async style behavior to prevent bugs. | 360 // to preserve the async style behavior to prevent bugs. |
| 372 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 361 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 373 base::Bind(callback)); | 362 base::Bind(callback)); |
| 374 return false; | 363 return false; |
| 375 } | 364 } |
| 376 return true; | 365 return true; |
| 377 } | 366 } |
| 378 | 367 |
| 379 void RequestQueueStoreSQL::GetRequests(const GetRequestsCallback& callback) { | 368 void RequestQueueStoreSQL::GetRequests(const GetRequestsCallback& callback) { |
| 380 DCHECK(db_.get()); | 369 DCHECK(db_.get()); |
| 381 std::vector<std::unique_ptr<SavePageRequest>> requests; | 370 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 382 if (!CheckDb(base::Bind(callback, false, base::Passed(&requests)))) | 371 if (!CheckDb(base::Bind(callback, false, base::Passed(&requests)))) |
| 383 return; | 372 return; |
| 384 | 373 |
| 385 background_task_runner_->PostTask( | 374 background_task_runner_->PostTask( |
| 386 FROM_HERE, base::Bind(&RequestQueueStoreSQL::GetRequestsSync, db_.get(), | 375 FROM_HERE, base::Bind(&GetRequestsSync, db_.get(), |
| 387 base::ThreadTaskRunnerHandle::Get(), callback)); | 376 base::ThreadTaskRunnerHandle::Get(), callback)); |
| 388 } | 377 } |
| 389 | 378 |
| 390 void RequestQueueStoreSQL::AddOrUpdateRequest(const SavePageRequest& request, | 379 void RequestQueueStoreSQL::AddOrUpdateRequest(const SavePageRequest& request, |
| 391 const UpdateCallback& callback) { | 380 const UpdateCallback& callback) { |
| 392 DCHECK(db_.get()); | 381 DCHECK(db_.get()); |
| 393 if (!CheckDb(base::Bind(callback, UpdateStatus::FAILED))) | 382 if (!CheckDb(base::Bind(callback, UpdateStatus::FAILED))) |
| 394 return; | 383 return; |
| 395 | 384 |
| 396 background_task_runner_->PostTask( | 385 background_task_runner_->PostTask( |
| 397 FROM_HERE, | 386 FROM_HERE, |
| 398 base::Bind(&RequestQueueStoreSQL::AddOrUpdateRequestSync, db_.get(), | 387 base::Bind(&AddOrUpdateRequestSync, db_.get(), |
| 399 base::ThreadTaskRunnerHandle::Get(), request, callback)); | 388 base::ThreadTaskRunnerHandle::Get(), request, callback)); |
| 400 } | 389 } |
| 401 | 390 |
| 402 // RemoveRequestsByRequestId to be more parallell with RemoveRequestsByClientId. | 391 // RemoveRequestsByRequestId to be more parallell with RemoveRequestsByClientId. |
| 403 void RequestQueueStoreSQL::RemoveRequests( | 392 void RequestQueueStoreSQL::RemoveRequests( |
| 404 const std::vector<int64_t>& request_ids, | 393 const std::vector<int64_t>& request_ids, |
| 405 const RemoveCallback& callback) { | 394 const RemoveCallback& callback) { |
| 406 // Set up a failed set of results in case we fail the DB check. | 395 // Set up a failed set of results in case we fail the DB check. |
| 407 RequestQueue::UpdateMultipleRequestResults results; | 396 RequestQueue::UpdateMultipleRequestResults results; |
| 408 for (int64_t request_id : request_ids) { | 397 for (int64_t request_id : request_ids) { |
| 409 results.push_back(std::make_pair( | 398 results.push_back(std::make_pair( |
| 410 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); | 399 request_id, RequestQueue::UpdateRequestResult::STORE_FAILURE)); |
| 411 } | 400 } |
| 412 | 401 |
| 413 if (!CheckDb(base::Bind( | 402 if (!CheckDb(base::Bind( |
| 414 callback, results, | 403 callback, results, |
| 415 base::Passed(std::vector<std::unique_ptr<SavePageRequest>>())))) { | 404 base::Passed(std::vector<std::unique_ptr<SavePageRequest>>())))) { |
| 416 return; | 405 return; |
| 417 } | 406 } |
| 418 | 407 |
| 419 background_task_runner_->PostTask( | 408 background_task_runner_->PostTask( |
| 420 FROM_HERE, | 409 FROM_HERE, |
| 421 base::Bind(&RequestQueueStoreSQL::RemoveRequestsSync, db_.get(), | 410 base::Bind(&RemoveRequestsSync, db_.get(), |
| 422 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); | 411 base::ThreadTaskRunnerHandle::Get(), request_ids, callback)); |
| 423 } | 412 } |
| 424 | 413 |
| 425 void RequestQueueStoreSQL::ChangeRequestsState( | 414 void RequestQueueStoreSQL::ChangeRequestsState( |
| 426 const std::vector<int64_t>& request_ids, | 415 const std::vector<int64_t>& request_ids, |
| 427 const SavePageRequest::RequestState new_state, | 416 const SavePageRequest::RequestState new_state, |
| 428 const UpdateMultipleRequestsCallback& callback) { | 417 const UpdateMultipleRequestsCallback& callback) { |
| 429 RequestQueue::UpdateMultipleRequestResults results; | 418 RequestQueue::UpdateMultipleRequestResults results; |
| 430 std::vector<std::unique_ptr<SavePageRequest>> requests; | 419 std::vector<std::unique_ptr<SavePageRequest>> requests; |
| 431 if (!CheckDb(base::Bind(callback, results, base::Passed(&requests)))) { | 420 if (!CheckDb(base::Bind(callback, results, base::Passed(&requests)))) { |
| 432 return; | 421 return; |
| 433 } | 422 } |
| 434 | 423 |
| 435 background_task_runner_->PostTask( | 424 background_task_runner_->PostTask( |
| 436 FROM_HERE, base::Bind(&RequestQueueStoreSQL::ChangeRequestsStateSync, | 425 FROM_HERE, base::Bind(&ChangeRequestsStateSync, db_.get(), |
| 437 db_.get(), base::ThreadTaskRunnerHandle::Get(), | 426 base::ThreadTaskRunnerHandle::Get(), request_ids, |
| 438 request_ids, new_state, callback)); | 427 new_state, callback)); |
| 439 } | 428 } |
| 440 | 429 |
| 441 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { | 430 void RequestQueueStoreSQL::Reset(const ResetCallback& callback) { |
| 442 DCHECK(db_.get()); | 431 DCHECK(db_.get()); |
| 443 if (!CheckDb(base::Bind(callback, false))) | 432 if (!CheckDb(base::Bind(callback, false))) |
| 444 return; | 433 return; |
| 445 | 434 |
| 446 background_task_runner_->PostTask( | 435 background_task_runner_->PostTask( |
| 447 FROM_HERE, | 436 FROM_HERE, |
| 448 base::Bind(&RequestQueueStoreSQL::ResetSync, db_.get(), db_file_path_, | 437 base::Bind(&ResetSync, db_.get(), db_file_path_, |
| 449 base::ThreadTaskRunnerHandle::Get(), | 438 base::ThreadTaskRunnerHandle::Get(), |
| 450 base::Bind(&RequestQueueStoreSQL::OnResetDone, | 439 base::Bind(&RequestQueueStoreSQL::OnResetDone, |
| 451 weak_ptr_factory_.GetWeakPtr(), callback))); | 440 weak_ptr_factory_.GetWeakPtr(), callback))); |
| 452 } | 441 } |
| 453 | 442 |
| 454 void RequestQueueStoreSQL::OpenConnection() { | 443 void RequestQueueStoreSQL::OpenConnection() { |
| 455 DCHECK(!db_); | 444 DCHECK(!db_); |
| 456 db_.reset(new sql::Connection()); | 445 db_.reset(new sql::Connection()); |
| 457 background_task_runner_->PostTask( | 446 background_task_runner_->PostTask( |
| 458 FROM_HERE, | 447 FROM_HERE, |
| 459 base::Bind(&RequestQueueStoreSQL::OpenConnectionSync, db_.get(), | 448 base::Bind(&OpenConnectionSync, db_.get(), |
| 460 base::ThreadTaskRunnerHandle::Get(), db_file_path_, | 449 base::ThreadTaskRunnerHandle::Get(), db_file_path_, |
| 461 base::Bind(&RequestQueueStoreSQL::OnOpenConnectionDone, | 450 base::Bind(&RequestQueueStoreSQL::OnOpenConnectionDone, |
| 462 weak_ptr_factory_.GetWeakPtr()))); | 451 weak_ptr_factory_.GetWeakPtr()))); |
| 463 } | 452 } |
| 464 | 453 |
| 465 void RequestQueueStoreSQL::OnOpenConnectionDone(bool success) { | 454 void RequestQueueStoreSQL::OnOpenConnectionDone(bool success) { |
| 466 DCHECK(db_.get()); | 455 DCHECK(db_.get()); |
| 467 | 456 |
| 468 // Unfortunately we were not able to open DB connection. | 457 // Unfortunately we were not able to open DB connection. |
| 469 if (!success) | 458 if (!success) |
| 470 db_.reset(); | 459 db_.reset(); |
| 471 } | 460 } |
| 472 | 461 |
| 473 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, | 462 void RequestQueueStoreSQL::OnResetDone(const ResetCallback& callback, |
| 474 bool success) { | 463 bool success) { |
| 475 // Complete connection initialization post reset. | 464 // Complete connection initialization post reset. |
| 476 OnOpenConnectionDone(success); | 465 OnOpenConnectionDone(success); |
| 477 callback.Run(success); | 466 callback.Run(success); |
| 478 } | 467 } |
| 479 | 468 |
| 480 } // namespace offline_pages | 469 } // namespace offline_pages |
| OLD | NEW |