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

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: 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 statement.BindString16(col, path.value()); 59 statement.BindString16(col, path.value());
60 } 60 }
61 base::FilePath ColumnFilePath(sql::Statement& statement, int col) { 61 base::FilePath ColumnFilePath(sql::Statement& statement, int col) {
62 return base::FilePath(statement.ColumnString16(col)); 62 return base::FilePath(statement.ColumnString16(col));
63 } 63 }
64 64
65 #endif 65 #endif
66 66
67 } // namespace 67 } // namespace
68 68
69 // static
70 bool DownloadDatabase::IsParallelDownloadingEnabled() {
71 return base::FeatureList::IsEnabled(kParallelDownloading);
72 }
73
69 DownloadDatabase::DownloadDatabase( 74 DownloadDatabase::DownloadDatabase(
70 DownloadInterruptReason download_interrupt_reason_none, 75 DownloadInterruptReason download_interrupt_reason_none,
71 DownloadInterruptReason download_interrupt_reason_crash) 76 DownloadInterruptReason download_interrupt_reason_crash)
72 : owning_thread_set_(false), 77 : owning_thread_set_(false),
73 owning_thread_(0), 78 owning_thread_(0),
74 in_progress_entry_cleanup_completed_(false), 79 in_progress_entry_cleanup_completed_(false),
75 download_interrupt_reason_none_(download_interrupt_reason_none), 80 download_interrupt_reason_none_(download_interrupt_reason_none),
76 download_interrupt_reason_crash_(download_interrupt_reason_crash) { 81 download_interrupt_reason_crash_(download_interrupt_reason_crash) {
77 } 82 }
78 83
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 310
306 const char kUrlChainSchema[] = 311 const char kUrlChainSchema[] =
307 "CREATE TABLE downloads_url_chains (" 312 "CREATE TABLE downloads_url_chains ("
308 "id INTEGER NOT NULL," // downloads.id. 313 "id INTEGER NOT NULL," // downloads.id.
309 "chain_index INTEGER NOT NULL," // Index of url in chain 314 "chain_index INTEGER NOT NULL," // Index of url in chain
310 // 0 is initial target, 315 // 0 is initial target,
311 // MAX is target after redirects. 316 // MAX is target after redirects.
312 "url LONGVARCHAR NOT NULL, " // URL. 317 "url LONGVARCHAR NOT NULL, " // URL.
313 "PRIMARY KEY (id, chain_index) )"; 318 "PRIMARY KEY (id, chain_index) )";
314 319
320 bool ret;
315 if (GetDB().DoesTableExist("downloads")) { 321 if (GetDB().DoesTableExist("downloads")) {
316 return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") && 322 ret = EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") &&
317 EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0"); 323 EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0");
318 } else { 324 } else {
319 // If the "downloads" table doesn't exist, the downloads_url_chain 325 // If the "downloads" table doesn't exist, the downloads_url_chain
320 // table better not. 326 // and the downloads_jobs table better not.
321 return (!GetDB().DoesTableExist("downloads_url_chain") && 327 ret = !GetDB().DoesTableExist("downloads_url_chain") &&
322 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema)); 328 !GetDB().DoesTableExist("downloads_jobs") &&
329 GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema);
323 } 330 }
331 if (IsParallelDownloadingEnabled())
332 ret = ret && EnsureDownloadJobsTableExists();
333
334 return ret;
324 } 335 }
325 336
326 uint32_t DownloadDatabase::GetNextDownloadId() { 337 uint32_t DownloadDatabase::GetNextDownloadId() {
327 sql::Statement select_max_id(GetDB().GetUniqueStatement( 338 sql::Statement select_max_id(GetDB().GetUniqueStatement(
328 "SELECT max(id) FROM downloads")); 339 "SELECT max(id) FROM downloads"));
329 bool result = select_max_id.Step(); 340 bool result = select_max_id.Step();
330 DCHECK(result); 341 DCHECK(result);
331 // If there are zero records in the downloads table, then max(id) will 342 // If there are zero records in the downloads table, then max(id) will
332 // return 0 = kInvalidDownloadId, so GetNextDownloadId() will set 343 // return 0 = kInvalidDownloadId, so GetNextDownloadId() will set
333 // *id = kInvalidDownloadId + 1. 344 // *id = kInvalidDownloadId + 1.
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 url_chain->push_back(GURL()); 477 url_chain->push_back(GURL());
467 current_chain_size++; 478 current_chain_size++;
468 } 479 }
469 if (current_chain_size > chain_index) 480 if (current_chain_size > chain_index)
470 continue; 481 continue;
471 482
472 // Save the record. 483 // Save the record.
473 url_chain->push_back(GURL(statement_chain.ColumnString(2))); 484 url_chain->push_back(GURL(statement_chain.ColumnString(2)));
474 } 485 }
475 486
487 if (IsParallelDownloadingEnabled()) {
asanka 2017/02/01 22:34:10 The DB schema shouldn't depend on a feature state.
qinmin 2017/02/01 23:37:26 removed all feature state checking in this file. S
488 sql::Statement statement_download_job(GetDB().GetCachedStatement(
489 SQL_FROM_HERE,
490 "SELECT id, job_id, start_position, length, received_bytes, "
491 "state, interrupt_reason FROM downloads_jobs "
492 "ORDER BY id, job_id"));
493
494 while (statement_download_job.Step()) {
495 int column = 0;
496 // See the comment above about SQLITE lacking unsigned integers.
497 int64_t signed_id = statement_download_job.ColumnInt64(column++);
498 if (signed_id <= static_cast<int64_t>(kInvalidDownloadId))
499 continue;
500 int id = IntToDownloadId(signed_id);
501 DownloadJobInfo info;
502 info.id = IntToDownloadId(signed_id);
503 info.job_id = statement_download_job.ColumnInt(column++);
504 info.start_position = statement_download_job.ColumnInt64(column++);
505 info.length = statement_download_job.ColumnInt64(column++);
506 info.received_bytes = statement_download_job.ColumnInt64(column++);
507 info.state = IntToDownloadState(
508 statement_download_job.ColumnInt(column++));
509 info.interrupt_reason = IntToDownloadInterruptReason(
510 statement_download_job.ColumnInt(column++));
511 // Confirm the id has already been seen--if it hasn't, discard the
512 // record.
513 DCHECK(base::ContainsKey(info_map, id));
514 if (!base::ContainsKey(info_map, id))
515 continue;
516 info_map[id]->download_job_info.push_back(info);
517 }
518 }
519
476 for (std::map<uint32_t, DownloadRow*>::iterator it = info_map.begin(); 520 for (std::map<uint32_t, DownloadRow*>::iterator it = info_map.begin();
477 it != info_map.end(); ++it) { 521 it != info_map.end(); ++it) {
478 DownloadRow* row = it->second; 522 DownloadRow* row = it->second;
479 bool empty_url_chain = row->url_chain.empty(); 523 bool empty_url_chain = row->url_chain.empty();
480 UMA_HISTOGRAM_BOOLEAN("Download.DatabaseEmptyUrlChain", empty_url_chain); 524 UMA_HISTOGRAM_BOOLEAN("Download.DatabaseEmptyUrlChain", empty_url_chain);
481 if (empty_url_chain) { 525 if (empty_url_chain) {
482 RemoveDownload(row->id); 526 RemoveDownload(row->id);
483 } else { 527 } else {
484 // Copy the contents of the stored info. 528 // Copy the contents of the stored info.
485 results->push_back(*row); 529 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()); 570 statement.BindBlob(column++, data.hash.data(), data.hash.size());
527 statement.BindInt64(column++, data.end_time.ToInternalValue()); 571 statement.BindInt64(column++, data.end_time.ToInternalValue());
528 statement.BindInt64(column++, data.total_bytes); 572 statement.BindInt64(column++, data.total_bytes);
529 statement.BindInt(column++, (data.opened ? 1 : 0)); 573 statement.BindInt(column++, (data.opened ? 1 : 0));
530 statement.BindString(column++, data.by_ext_id); 574 statement.BindString(column++, data.by_ext_id);
531 statement.BindString(column++, data.by_ext_name); 575 statement.BindString(column++, data.by_ext_name);
532 statement.BindString(column++, data.etag); 576 statement.BindString(column++, data.etag);
533 statement.BindString(column++, data.last_modified); 577 statement.BindString(column++, data.last_modified);
534 statement.BindInt(column++, DownloadIdToInt(data.id)); 578 statement.BindInt(column++, DownloadIdToInt(data.id));
535 579
536 return statement.Run(); 580 if (!statement.Run())
581 return false;
582
583 if (IsParallelDownloadingEnabled()) {
584 for (size_t i = 0; i < data.download_job_info.size(); ++i) {
585 if (!UpdateDownloadJob(data.id, data.download_job_info[i], false))
586 return false;
587 }
588 }
589
590 return true;
537 } 591 }
538 592
539 void DownloadDatabase::EnsureInProgressEntriesCleanedUp() { 593 void DownloadDatabase::EnsureInProgressEntriesCleanedUp() {
540 if (in_progress_entry_cleanup_completed_) 594 if (in_progress_entry_cleanup_completed_)
541 return; 595 return;
542 596
543 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 597 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
544 "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?")); 598 "UPDATE downloads SET state=?, interrupt_reason=? WHERE state=?"));
545 statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED)); 599 statement.BindInt(0, DownloadStateToInt(DownloadState::INTERRUPTED));
546 statement.BindInt( 600 statement.BindInt(
547 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_)); 601 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_));
548 statement.BindInt(2, DownloadStateToInt(DownloadState::IN_PROGRESS)); 602 statement.BindInt(2, DownloadStateToInt(DownloadState::IN_PROGRESS));
549 603
550 statement.Run(); 604 statement.Run();
605
606 if (IsParallelDownloadingEnabled()) {
607 sql::Statement statement_download_job(GetDB().GetCachedStatement(
608 SQL_FROM_HERE,
609 "UPDATE downloads_jobs SET state=?, interrupt_reason=? WHERE state=?"));
610 statement_download_job.BindInt(
611 0, DownloadStateToInt(DownloadState::INTERRUPTED));
612 statement_download_job.BindInt(
613 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_));
614 statement_download_job.BindInt(
615 2, DownloadStateToInt(DownloadState::IN_PROGRESS));
616 statement_download_job.Run();
617 }
551 in_progress_entry_cleanup_completed_ = true; 618 in_progress_entry_cleanup_completed_ = true;
552 } 619 }
553 620
554 bool DownloadDatabase::CreateDownload(const DownloadRow& info) { 621 bool DownloadDatabase::CreateDownload(const DownloadRow& info) {
555 DCHECK_NE(kInvalidDownloadId, info.id); 622 DCHECK_NE(kInvalidDownloadId, info.id);
556 DCHECK(!info.guid.empty()); 623 DCHECK(!info.guid.empty());
557 SCOPED_UMA_HISTOGRAM_TIMER("Download.Database.CreateDownloadDuration"); 624 SCOPED_UMA_HISTOGRAM_TIMER("Download.Database.CreateDownloadDuration");
558 EnsureInProgressEntriesCleanedUp(); 625 EnsureInProgressEntriesCleanedUp();
559 626
560 if (info.url_chain.empty()) 627 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)); 710 statement_insert_chain.BindInt(1, static_cast<int>(i));
644 statement_insert_chain.BindString(2, info.url_chain[i].spec()); 711 statement_insert_chain.BindString(2, info.url_chain[i].spec());
645 if (!statement_insert_chain.Run()) { 712 if (!statement_insert_chain.Run()) {
646 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainInsertError", 713 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainInsertError",
647 GetDB().GetErrorCode() & 0xff, 50); 714 GetDB().GetErrorCode() & 0xff, 50);
648 RemoveDownload(info.id); 715 RemoveDownload(info.id);
649 return false; 716 return false;
650 } 717 }
651 statement_insert_chain.Reset(true); 718 statement_insert_chain.Reset(true);
652 } 719 }
720
721 if (IsParallelDownloadingEnabled()) {
722 for (size_t i = 0; i < info.download_job_info.size(); ++i) {
723 if (!UpdateDownloadJob(info.id, info.download_job_info[i], true)) {
724 RemoveDownload(info.id);
725 return false;
726 }
727 }
728 }
729
653 return true; 730 return true;
654 } 731 }
655 732
656 void DownloadDatabase::RemoveDownload(uint32_t id) { 733 void DownloadDatabase::RemoveDownload(uint32_t id) {
657 EnsureInProgressEntriesCleanedUp(); 734 EnsureInProgressEntriesCleanedUp();
658 735
659 sql::Statement downloads_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 736 sql::Statement downloads_statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
660 "DELETE FROM downloads WHERE id=?")); 737 "DELETE FROM downloads WHERE id=?"));
661 downloads_statement.BindInt(0, id); 738 downloads_statement.BindInt(0, id);
662 if (!downloads_statement.Run()) { 739 if (!downloads_statement.Run()) {
663 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainDeleteError", 740 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseMainDeleteError",
664 GetDB().GetErrorCode() & 0xff, 50); 741 GetDB().GetErrorCode() & 0xff, 50);
665 return; 742 return;
666 } 743 }
667 RemoveDownloadURLs(id); 744 RemoveDownloadURLs(id);
745 if (IsParallelDownloadingEnabled()) {
746 RemoveDownloadJobs(id);
747 }
668 } 748 }
669 749
670 void DownloadDatabase::RemoveDownloadURLs(uint32_t id) { 750 void DownloadDatabase::RemoveDownloadURLs(uint32_t id) {
671 sql::Statement urlchain_statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 751 sql::Statement urlchain_statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
672 "DELETE FROM downloads_url_chains WHERE id=?")); 752 "DELETE FROM downloads_url_chains WHERE id=?"));
673 urlchain_statement.BindInt(0, id); 753 urlchain_statement.BindInt(0, id);
674 if (!urlchain_statement.Run()) { 754 if (!urlchain_statement.Run()) {
675 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainDeleteError", 755 UMA_HISTOGRAM_ENUMERATION("Download.DatabaseURLChainDeleteError",
676 GetDB().GetErrorCode() & 0xff, 50); 756 GetDB().GetErrorCode() & 0xff, 50);
677 } 757 }
678 } 758 }
679 759
680 size_t DownloadDatabase::CountDownloads() { 760 size_t DownloadDatabase::CountDownloads() {
681 EnsureInProgressEntriesCleanedUp(); 761 EnsureInProgressEntriesCleanedUp();
682 762
683 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, 763 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE,
684 "SELECT count(*) from downloads")); 764 "SELECT count(*) from downloads"));
685 statement.Step(); 765 statement.Step();
686 return statement.ColumnInt(0); 766 return statement.ColumnInt(0);
687 } 767 }
688 768
769 bool DownloadDatabase::EnsureDownloadJobsTableExists() {
770 // TODO(qinmin): increment the current history database version by 1 once
771 // this feature is no longer experimental.
772 const char kJobsSchema[] =
773 "CREATE TABLE downloads_jobs ("
774 "id INTEGER NOT NULL," // downloads.id.
775 "job_id INTEGER NOT NULL," // Download job id.
776 "start_position INTEGER NOT NULL," // The start request position of the
777 // download job.
778 "length INTEGER NOT NULL," // length of the request, -1
779 // if not specified
780 "received_bytes INTEGER NOT NULL," // Total bytes downloaded.
781 "state INTEGER NOT NULL," // To be determined.
782 "interrupt_reason INTEGER NOT NULL, " // DownloadInterruptReason
783 "PRIMARY KEY (id, job_id) )";
784
785 return GetDB().DoesTableExist("downloads_jobs") ||
786 GetDB().Execute(kJobsSchema);
787 }
788
789 bool DownloadDatabase::UpdateDownloadJob(
790 const DownloadJobInfo& info, bool is_new_download) {
791 sql::Statement statement_query(GetDB().GetCachedStatement(
792 SQL_FROM_HERE,
793 "SELECT count(*) "
794 "FROM downloads_jobs "
795 "WHERE id=? AND job_id=?"));
796 statement_query.BindInt(0, info.id);
797 statement_query.BindInt(1, info.job_id);
798
799 bool job_exists = false;
800 if (statement_query.Step()) {
801 job_exists = statement_query.ColumnInt(0) > 0;
802 // There should not be any jobs in downloads_jobs for this id. If there
803 // are, we don't want them to interfere with inserting the correct jobs,
804 // so just remove them.
805 if (is_new_download && job_exists)
806 RemoveDownloadJobs(info.id);
807 }
808 int column = 0;
809
810 if (!is_new_download && job_exists) {
811 sql::Statement statement_update(GetDB().GetCachedStatement(
812 SQL_FROM_HERE,
813 "UPDATE downloads_jobs "
814 "SET start_position=?, length=?, received_bytes=?, state=?, "
815 "interrupt_reason=? "
816 "WHERE id=? AND job_id=?"));
817 statement_update.BindInt64(column++, info.start_position);
818 statement_update.BindInt64(column++, info.length);
819 statement_update.BindInt64(column++, info.received_bytes);
820 statement_update.BindInt(column++, DownloadStateToInt(info.state));
821 statement_update.BindInt(
822 column++, DownloadInterruptReasonToInt(info.interrupt_reason));
823 statement_update.BindInt(column++, info.id);
824 statement_update.BindInt(column++, info.job_id);
825 return statement_update.Run();
826 } else {
827 sql::Statement statement_insert(GetDB().GetCachedStatement(
828 SQL_FROM_HERE,
829 "INSERT INTO downloads_jobs "
830 "(id, job_id, start_position, length, received_bytes, state, "
831 "interrupt_reason) "
832 "VALUES (?, ?, ?, ?, ?, ?, ?)"));
833 statement_insert.BindInt(column++, info.id);
834 statement_insert.BindInt(column++, info.job_id);
835 statement_insert.BindInt64(column++, info.start_position);
836 statement_insert.BindInt64(column++, info.length);
837 statement_insert.BindInt64(column++, info.received_bytes);
838 statement_insert.BindInt(column++, DownloadStateToInt(info.state));
839 statement_insert.BindInt(
840 column++, DownloadInterruptReasonToInt(info.interrupt_reason));
841
842 return statement_insert.Run();
843 }
844 }
845
846 void DownloadDatabase::RemoveDownloadJobs(uint32_t id) {
847 sql::Statement statement_delete(GetDB().GetCachedStatement(SQL_FROM_HERE,
848 "DELETE FROM downloads_jobs WHERE id=?"));
849 statement_delete.BindInt(0, id);
850 statement_delete.Run();
851 }
852
689 } // namespace history 853 } // namespace history
OLDNEW
« no previous file with comments | « components/history/core/browser/download_database.h ('k') | components/history/core/browser/download_job_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698