Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(433)

Side by Side Diff: components/history/core/browser/download_database.cc

Issue 2665243003: add a download slices table into history download db (Closed)
Patch Set: addressing comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/history/core/browser/download_database.h" 5 #include "components/history/core/browser/download_database.h"
6 6
7 #include <inttypes.h> 7 #include <inttypes.h>
8 8
9 #include <limits> 9 #include <limits>
10 #include <memory> 10 #include <memory>
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 305
306 const char kUrlChainSchema[] = 306 const char kUrlChainSchema[] =
307 "CREATE TABLE downloads_url_chains (" 307 "CREATE TABLE downloads_url_chains ("
308 "id INTEGER NOT NULL," // downloads.id. 308 "id INTEGER NOT NULL," // downloads.id.
309 "chain_index INTEGER NOT NULL," // Index of url in chain 309 "chain_index INTEGER NOT NULL," // Index of url in chain
310 // 0 is initial target, 310 // 0 is initial target,
311 // MAX is target after redirects. 311 // MAX is target after redirects.
312 "url LONGVARCHAR NOT NULL, " // URL. 312 "url LONGVARCHAR NOT NULL, " // URL.
313 "PRIMARY KEY (id, chain_index) )"; 313 "PRIMARY KEY (id, chain_index) )";
314 314
315 const char kJobsSchema[] =
316 "CREATE TABLE downloads_jobs ("
317 "download_id INTEGER NOT NULL," // downloads.id.
318 "job_id INTEGER NOT NULL," // Download job id.
319 "start_position INTEGER NOT NULL," // The start request position of the
320 // download job.
321 "length INTEGER NOT NULL," // length of the request, -1
322 // if not specified
323 "received_bytes INTEGER NOT NULL," // Total bytes downloaded.
324 "state INTEGER NOT NULL," // To be determined.
sky 2017/02/03 16:02:33 Is this comment right? It seems like you're using
qinmin 2017/02/04 00:06:56 Done.
325 "interrupt_reason INTEGER NOT NULL, " // DownloadInterruptReason
326 "PRIMARY KEY (download_id, job_id) )";
327
328 bool ret;
315 if (GetDB().DoesTableExist("downloads")) { 329 if (GetDB().DoesTableExist("downloads")) {
316 return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") && 330 ret = EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") &&
317 EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0"); 331 EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0");
318 } else { 332 } else {
319 // If the "downloads" table doesn't exist, the downloads_url_chain 333 // If the "downloads" table doesn't exist, the downloads_url_chain
320 // table better not. 334 // table better not.
321 return (!GetDB().DoesTableExist("downloads_url_chain") && 335 ret = (!GetDB().DoesTableExist("downloads_url_chain") &&
322 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); 336 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema));
323 } 337 }
338
339 return ret && (GetDB().DoesTableExist("downloads_jobs") ||
340 GetDB().Execute(kJobsSchema));
324 } 341 }
325 342
326 uint32_t DownloadDatabase::GetNextDownloadId() { 343 uint32_t DownloadDatabase::GetNextDownloadId() {
327 sql::Statement select_max_id(GetDB().GetUniqueStatement( 344 sql::Statement select_max_id(GetDB().GetUniqueStatement(
328 "SELECT max(id) FROM downloads")); 345 "SELECT max(id) FROM downloads"));
329 bool result = select_max_id.Step(); 346 bool result = select_max_id.Step();
330 DCHECK(result); 347 DCHECK(result);
331 // If there are zero records in the downloads table, then max(id) will 348 // If there are zero records in the downloads table, then max(id) will
332 // return 0 = kInvalidDownloadId, so GetNextDownloadId() will set 349 // return 0 = kInvalidDownloadId, so GetNextDownloadId() will set
333 // *id = kInvalidDownloadId + 1. 350 // *id = kInvalidDownloadId + 1.
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 url_chain->push_back(GURL()); 483 url_chain->push_back(GURL());
467 current_chain_size++; 484 current_chain_size++;
468 } 485 }
469 if (current_chain_size > chain_index) 486 if (current_chain_size > chain_index)
470 continue; 487 continue;
471 488
472 // Save the record. 489 // Save the record.
473 url_chain->push_back(GURL(statement_chain.ColumnString(2))); 490 url_chain->push_back(GURL(statement_chain.ColumnString(2)));
474 } 491 }
475 492
493 sql::Statement statement_download_job(GetDB().GetCachedStatement(
sky 2017/02/03 16:02:33 wnloadDatabase::QueryDownload is incredibly long.
qinmin 2017/02/04 00:06:56 Done.
494 SQL_FROM_HERE,
495 "SELECT download_id, job_id, start_position, length, received_bytes, "
496 "state, interrupt_reason FROM downloads_jobs "
497 "ORDER BY download_id, job_id"));
498
499 while (statement_download_job.Step()) {
500 int column = 0;
501 // See the comment above about SQLITE lacking unsigned integers.
502 int64_t signed_id = statement_download_job.ColumnInt64(column++);
503 if (signed_id <= static_cast<int64_t>(kInvalidDownloadId))
504 continue;
sky 2017/02/03 16:02:33 Wouldn't this indicate corruption? Should we log i
qinmin 2017/02/04 00:06:56 Done.
505 int download_id = IntToDownloadId(signed_id);
506 // Confirm the download_id has already been seen--if it hasn't, discard the
507 // record.
508 bool found = base::ContainsKey(info_map, download_id);
509 UMA_HISTOGRAM_BOOLEAN(
510 "Download.DatabaseDownloadExistsForDownloadJob", found);
511 DCHECK(found);
512 if (!found)
513 continue;
514
515 DownloadJobInfo info;
516 info.download_id = download_id;
517 info.job_id = statement_download_job.ColumnInt(column++);
518 info.start_position = statement_download_job.ColumnInt64(column++);
519 info.length = statement_download_job.ColumnInt64(column++);
520 info.received_bytes = statement_download_job.ColumnInt64(column++);
521 info.state = IntToDownloadState(
522 statement_download_job.ColumnInt(column++));
523 info.interrupt_reason = IntToDownloadInterruptReason(
524 statement_download_job.ColumnInt(column++));
525 info_map[download_id]->download_job_info.push_back(info);
526 }
527
476 for (std::map<uint32_t, DownloadRow*>::iterator it = info_map.begin(); 528 for (std::map<uint32_t, DownloadRow*>::iterator it = info_map.begin();
477 it != info_map.end(); ++it) { 529 it != info_map.end(); ++it) {
478 DownloadRow* row = it->second; 530 DownloadRow* row = it->second;
479 bool empty_url_chain = row->url_chain.empty(); 531 bool empty_url_chain = row->url_chain.empty();
480 UMA_HISTOGRAM_BOOLEAN("Download.DatabaseEmptyUrlChain", empty_url_chain); 532 UMA_HISTOGRAM_BOOLEAN("Download.DatabaseEmptyUrlChain", empty_url_chain);
481 if (empty_url_chain) { 533 if (empty_url_chain) {
482 RemoveDownload(row->id); 534 RemoveDownload(row->id);
483 } else { 535 } else {
484 // Copy the contents of the stored info. 536 // Copy the contents of the stored info.
485 results->push_back(*row); 537 results->push_back(*row);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 statement.BindBlob(column++, data.hash.data(), data.hash.size()); 578 statement.BindBlob(column++, data.hash.data(), data.hash.size());
527 statement.BindInt64(column++, data.end_time.ToInternalValue()); 579 statement.BindInt64(column++, data.end_time.ToInternalValue());
528 statement.BindInt64(column++, data.total_bytes); 580 statement.BindInt64(column++, data.total_bytes);
529 statement.BindInt(column++, (data.opened ? 1 : 0)); 581 statement.BindInt(column++, (data.opened ? 1 : 0));
530 statement.BindString(column++, data.by_ext_id); 582 statement.BindString(column++, data.by_ext_id);
531 statement.BindString(column++, data.by_ext_name); 583 statement.BindString(column++, data.by_ext_name);
532 statement.BindString(column++, data.etag); 584 statement.BindString(column++, data.etag);
533 statement.BindString(column++, data.last_modified); 585 statement.BindString(column++, data.last_modified);
534 statement.BindInt(column++, DownloadIdToInt(data.id)); 586 statement.BindInt(column++, DownloadIdToInt(data.id));
535 587
536 return statement.Run(); 588 if (!statement.Run())
589 return false;
590
591 for (size_t i = 0; i < data.download_job_info.size(); ++i) {
592 // Create a new download job if it doesn't exist in the downloads_jobs
593 // table.
594 if (!UpdateDownloadJob(data.download_job_info[i]) &&
595 !CreateDownloadJob(data.download_job_info[i])) {
596 return false;
sky 2017/02/03 16:02:33 Is it possible to get test coverage of this code p
qinmin 2017/02/04 00:06:56 Done. Added HistoryBackendDBTest.UpdateDownloadWit
597 }
598 }
599
600 return true;
537 } 601 }
538 602
539 void DownloadDatabase::EnsureInProgressEntriesCleanedUp() { 603 void DownloadDatabase::EnsureInProgressEntriesCleanedUp() {
540 if (in_progress_entry_cleanup_completed_) 604 if (in_progress_entry_cleanup_completed_)
541 return; 605 return;
542 606
543 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 607 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
544 "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?")); 608 "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?"));
545 statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED)); 609 statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED));
546 statement.BindInt( 610 statement.BindInt(
547 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_)); 611 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_));
548 statement.BindInt(2, DownloadStateToInt(DownloadState::IN_PROGRESS)); 612 statement.BindInt(2, DownloadStateToInt(DownloadState::IN_PROGRESS));
549 613
550 statement.Run(); 614 statement.Run();
615
616 sql::Statement statement_download_job(GetDB().GetCachedStatement(
sky 2017/02/03 16:02:33 Is there test coverage of this code path?
qinmin 2017/02/04 00:06:56 Done. HistoryBackendDBTest.ConfirmDownloadInProgre
617 SQL_FROM_HERE,
618 "UPDATE downloads_jobs SET state=?, interrupt_reason=? WHERE state=?"));
619 statement_download_job.BindInt(
620 0, DownloadStateToInt(DownloadState::INTERRUPTED));
621 statement_download_job.BindInt(
622 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_));
623 statement_download_job.BindInt(
624 2, DownloadStateToInt(DownloadState::IN_PROGRESS));
625 statement_download_job.Run();
551 in_progress_entry_cleanup_completed_ = true; 626 in_progress_entry_cleanup_completed_ = true;
552 } 627 }
553 628
554 bool DownloadDatabase::CreateDownload(const DownloadRow& info) { 629 bool DownloadDatabase::CreateDownload(const DownloadRow& info) {
555 DCHECK_NE(kInvalidDownloadId, info.id); 630 DCHECK_NE(kInvalidDownloadId, info.id);
556 DCHECK(!info.guid.empty()); 631 DCHECK(!info.guid.empty());
557 SCOPED_UMA_HISTOGRAM_TIMER("Download.Database.CreateDownloadDuration"); 632 SCOPED_UMA_HISTOGRAM_TIMER("Download.Database.CreateDownloadDuration");
558 EnsureInProgressEntriesCleanedUp(); 633 EnsureInProgressEntriesCleanedUp();
559 634
560 if (info.url_chain.empty()) 635 if (info.url_chain.empty())
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 statement_insert_chain.BindInt(1, static_cast<int>(i)); 718 statement_insert_chain.BindInt(1, static_cast<int>(i));
644 statement_insert_chain.BindString(2, info.url_chain[i].spec()); 719 statement_insert_chain.BindString(2, info.url_chain[i].spec());
645 if (!statement_insert_chain.Run()) { 720 if (!statement_insert_chain.Run()) {
646 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainInsertError", 721 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainInsertError",
647 GetDB().GetErrorCode() & 0xff, 50); 722 GetDB().GetErrorCode() & 0xff, 50);
648 RemoveDownload(info.id); 723 RemoveDownload(info.id);
649 return false; 724 return false;
650 } 725 }
651 statement_insert_chain.Reset(true); 726 statement_insert_chain.Reset(true);
652 } 727 }
728
729 for (size_t i = 0; i < info.download_job_info.size(); ++i) {
730 if (!CreateDownloadJob(info.download_job_info[i])) {
731 RemoveDownload(info.id);
732 return false;
733 }
734 }
735
653 return true; 736 return true;
654 } 737 }
655 738
656 void DownloadDatabase::RemoveDownload(uint32_t id) { 739 void DownloadDatabase::RemoveDownload(uint32_t id) {
657 EnsureInProgressEntriesCleanedUp(); 740 EnsureInProgressEntriesCleanedUp();
658 741
659 sql::Statement downloads_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 742 sql::Statement downloads_statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
660 "DELETE FROM downloads WHERE id=?")); 743 "DELETE FROM downloads WHERE id=?"));
661 downloads_statement.BindInt(0, id); 744 downloads_statement.BindInt(0, id);
662 if (!downloads_statement.Run()) { 745 if (!downloads_statement.Run()) {
663 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainDeleteError", 746 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainDeleteError",
664 GetDB().GetErrorCode() & 0xff, 50); 747 GetDB().GetErrorCode() & 0xff, 50);
665 return; 748 return;
666 } 749 }
667 RemoveDownloadURLs(id); 750 RemoveDownloadURLs(id);
751 RemoveDownloadJobs(id);
sky 2017/02/03 16:02:33 Is there test coverage of this?
qinmin 2017/02/04 00:06:56 Done. HistoryBackendDBTest.ConfirmDownloadRowCreat
668 } 752 }
669 753
670 void DownloadDatabase::RemoveDownloadURLs(uint32_t id) { 754 void DownloadDatabase::RemoveDownloadURLs(uint32_t id) {
671 sql::Statement urlchain_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 755 sql::Statement urlchain_statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
672 "DELETE FROM downloads_url_chains WHERE id=?")); 756 "DELETE FROM downloads_url_chains WHERE id=?"));
673 urlchain_statement.BindInt(0, id); 757 urlchain_statement.BindInt(0, id);
674 if (!urlchain_statement.Run()) { 758 if (!urlchain_statement.Run()) {
675 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainDeleteError", 759 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainDeleteError",
676 GetDB().GetErrorCode() & 0xff, 50); 760 GetDB().GetErrorCode() & 0xff, 50);
677 } 761 }
678 } 762 }
679 763
680 size_t DownloadDatabase::CountDownloads() { 764 size_t DownloadDatabase::CountDownloads() {
681 EnsureInProgressEntriesCleanedUp(); 765 EnsureInProgressEntriesCleanedUp();
682 766
683 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 767 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
684 "SELECT count(*) from downloads")); 768 "SELECT count(*) from downloads"));
685 statement.Step(); 769 statement.Step();
686 return statement.ColumnInt(0); 770 return statement.ColumnInt(0);
687 } 771 }
688 772
773 bool DownloadDatabase::CreateDownloadJob(const DownloadJobInfo& info) {
774 sql::Statement statement_insert(GetDB().GetCachedStatement(
775 SQL_FROM_HERE,
776 "INSERT INTO downloads_jobs "
777 "(download_id, job_id, start_position, length, received_bytes, state, "
778 "interrupt_reason) "
779 "VALUES (?, ?, ?, ?, ?, ?, ?)"));
780 int column = 0;
781 statement_insert.BindInt(column++, info.download_id);
782 statement_insert.BindInt(column++, info.job_id);
783 statement_insert.BindInt64(column++, info.start_position);
784 statement_insert.BindInt64(column++, info.length);
785 statement_insert.BindInt64(column++, info.received_bytes);
786 statement_insert.BindInt(column++, DownloadStateToInt(info.state));
787 statement_insert.BindInt(
788 column++, DownloadInterruptReasonToInt(info.interrupt_reason));
789 return statement_insert.Run();
790 }
791
792 bool DownloadDatabase::UpdateDownloadJob(const DownloadJobInfo& info) {
793 sql::Statement statement_update(GetDB().GetCachedStatement(
794 SQL_FROM_HERE,
795 "UPDATE downloads_jobs "
796 "SET start_position=?, length=?, received_bytes=?, state=?, "
797 "interrupt_reason=? "
798 "WHERE download_id=? AND job_id=?"));
799 int column = 0;
800 statement_update.BindInt64(column++, info.start_position);
801 statement_update.BindInt64(column++, info.length);
802 statement_update.BindInt64(column++, info.received_bytes);
803 statement_update.BindInt(column++, DownloadStateToInt(info.state));
804 statement_update.BindInt(
805 column++, DownloadInterruptReasonToInt(info.interrupt_reason));
806 statement_update.BindInt(column++, info.download_id);
807 statement_update.BindInt(column++, info.job_id);
808 return statement_update.Run();
809 }
810
811 void DownloadDatabase::RemoveDownloadJobs(uint32_t id) {
812 sql::Statement statement_delete(GetDB().GetCachedStatement(SQL_FROM_HERE,
813 "DELETE FROM downloads_jobs WHERE download_id=?"));
814 statement_delete.BindInt(0, id);
815 statement_delete.Run();
816 }
817
689 } // namespace history 818 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698