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

Unified Diff: components/history/core/browser/download_database.cc

Issue 2665243003: add a download slices table into history download db (Closed)
Patch Set: use Select changes() instead of select count(*) 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 side-by-side diff with in-line comments
Download patch
Index: components/history/core/browser/download_database.cc
diff --git a/components/history/core/browser/download_database.cc b/components/history/core/browser/download_database.cc
index 5994bf5e2564fcf5b8d27d9ef830866cedaa29d0..b6d1f29196c6771507fdb052977663d4087c1c90 100644
--- a/components/history/core/browser/download_database.cc
+++ b/components/history/core/browser/download_database.cc
@@ -21,6 +21,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/history/core/browser/download_constants.h"
+#include "components/history/core/browser/download_job_info.h"
#include "components/history/core/browser/download_row.h"
#include "components/history/core/browser/history_types.h"
#include "sql/statement.h"
@@ -312,15 +313,32 @@ bool DownloadDatabase::InitDownloadTable() {
"url LONGVARCHAR NOT NULL, " // URL.
"PRIMARY KEY (id, chain_index) )";
+ const char kJobsSchema[] =
+ "CREATE TABLE downloads_jobs ("
+ "download_id INTEGER NOT NULL," // downloads.id.
+ "job_id INTEGER NOT NULL," // Download job id.
+ "start_position INTEGER NOT NULL," // The start request position of the
+ // download job.
+ "length INTEGER NOT NULL," // Length of the request, -1
+ // if not specified
+ "received_bytes INTEGER NOT NULL," // Total bytes downloaded.
+ "state INTEGER NOT NULL," // State of the download job.
+ "interrupt_reason INTEGER NOT NULL, " // DownloadInterruptReason
+ "PRIMARY KEY (download_id, job_id) )";
+
+ bool ret;
if (GetDB().DoesTableExist("downloads")) {
- return EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") &&
- EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0");
+ ret = EnsureColumnExists("end_time", "INTEGER NOT NULL DEFAULT 0") &&
+ EnsureColumnExists("opened", "INTEGER NOT NULL DEFAULT 0");
} else {
// If the "downloads" table doesn't exist, the downloads_url_chain
// table better not.
- return (!GetDB().DoesTableExist("downloads_url_chain") &&
- GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema));
+ ret = (!GetDB().DoesTableExist("downloads_url_chain") &&
+ GetDB().Execute(kSchema) && GetDB().Execute(kUrlChainSchema));
}
+
+ return ret && (GetDB().DoesTableExist("downloads_jobs") ||
+ GetDB().Execute(kJobsSchema));
Scott Hess - ex-Googler 2017/02/06 21:22:16 IMHO this is getting convoluted. Someone coming a
qinmin 2017/02/06 23:39:22 The issue is related to database versions. downloa
}
uint32_t DownloadDatabase::GetNextDownloadId() {
@@ -473,6 +491,8 @@ void DownloadDatabase::QueryDownloads(std::vector<DownloadRow>* results) {
url_chain->push_back(GURL(statement_chain.ColumnString(2)));
}
+ QueryDownloadJobs(&info_map);
+
for (std::map<uint32_t, DownloadRow*>::iterator it = info_map.begin();
it != info_map.end(); ++it) {
DownloadRow* row = it->second;
@@ -533,7 +553,16 @@ bool DownloadDatabase::UpdateDownload(const DownloadRow& data) {
statement.BindString(column++, data.last_modified);
statement.BindInt(column++, DownloadIdToInt(data.id));
- return statement.Run();
+ if (!statement.Run())
+ return false;
+ for (size_t i = 0; i < data.download_job_info.size(); ++i) {
+ if (!UpdateDownloadJob(data.download_job_info[i]) &&
+ !CreateDownloadJob(data.download_job_info[i])) {
Scott Hess - ex-Googler 2017/02/06 21:23:51 Oh, as I noted elsewhere, since update is touching
qinmin 2017/02/06 23:39:22 Done. Switched to use REPLACE(short form of INSERT
+ return false;
+ }
+ }
+
+ return true;
}
void DownloadDatabase::EnsureInProgressEntriesCleanedUp() {
@@ -548,6 +577,17 @@ void DownloadDatabase::EnsureInProgressEntriesCleanedUp() {
statement.BindInt(2, DownloadStateToInt(DownloadState::IN_PROGRESS));
statement.Run();
+
+ sql::Statement statement_download_job(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "UPDATE downloads_jobs SET state=?, interrupt_reason=? WHERE state=?"));
+ statement_download_job.BindInt(
+ 0, DownloadStateToInt(DownloadState::INTERRUPTED));
+ statement_download_job.BindInt(
+ 1, DownloadInterruptReasonToInt(download_interrupt_reason_crash_));
+ statement_download_job.BindInt(
+ 2, DownloadStateToInt(DownloadState::IN_PROGRESS));
+ statement_download_job.Run();
in_progress_entry_cleanup_completed_ = true;
}
@@ -650,6 +690,14 @@ bool DownloadDatabase::CreateDownload(const DownloadRow& info) {
}
statement_insert_chain.Reset(true);
}
+
+ for (size_t i = 0; i < info.download_job_info.size(); ++i) {
+ if (!CreateDownloadJob(info.download_job_info[i])) {
+ RemoveDownload(info.id);
+ return false;
+ }
+ }
+
return true;
}
@@ -665,6 +713,7 @@ void DownloadDatabase::RemoveDownload(uint32_t id) {
return;
}
RemoveDownloadURLs(id);
+ RemoveDownloadJobs(id);
Scott Hess - ex-Googler 2017/02/06 21:22:16 Are these statements all in a containing transacti
qinmin 2017/02/06 23:39:21 Yes, all these statement are in a long running tra
}
void DownloadDatabase::RemoveDownloadURLs(uint32_t id) {
@@ -686,4 +735,98 @@ size_t DownloadDatabase::CountDownloads() {
return statement.ColumnInt(0);
}
+bool DownloadDatabase::CreateDownloadJob(const DownloadJobInfo& info) {
+ sql::Statement statement_insert(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "INSERT INTO downloads_jobs "
+ "(download_id, job_id, start_position, length, received_bytes, state, "
+ "interrupt_reason) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)"));
+ int column = 0;
+ statement_insert.BindInt(column++, info.download_id);
+ statement_insert.BindInt(column++, info.job_id);
+ statement_insert.BindInt64(column++, info.start_position);
+ statement_insert.BindInt64(column++, info.length);
+ statement_insert.BindInt64(column++, info.received_bytes);
+ statement_insert.BindInt(column++, DownloadStateToInt(info.state));
+ statement_insert.BindInt(
+ column++, DownloadInterruptReasonToInt(info.interrupt_reason));
+ return statement_insert.Run();
+}
+
+bool DownloadDatabase::UpdateDownloadJob(const DownloadJobInfo& info) {
+ sql::Statement statement_update(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "UPDATE downloads_jobs "
+ "SET start_position=?, length=?, received_bytes=?, state=?, "
+ "interrupt_reason=? "
+ "WHERE download_id=? AND job_id=?"));
+ int column = 0;
+ statement_update.BindInt64(column++, info.start_position);
+ statement_update.BindInt64(column++, info.length);
+ statement_update.BindInt64(column++, info.received_bytes);
+ statement_update.BindInt(column++, DownloadStateToInt(info.state));
+ statement_update.BindInt(
+ column++, DownloadInterruptReasonToInt(info.interrupt_reason));
+ statement_update.BindInt(column++, info.download_id);
+ statement_update.BindInt(column++, info.job_id);
+ if (!statement_update.Run())
+ return false;
+
+ // Need to check whether the entry exists. Unfortunately, running an
+ // UPDATE statement will always return true even if the entry doesn't exist.
+ sql::Statement statement_query(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "SELECT changes()"));
+ return statement_query.Step() && statement_query.ColumnInt(0) != 0;
+}
+
+void DownloadDatabase::RemoveDownloadJobs(uint32_t id) {
+ sql::Statement statement_delete(GetDB().GetCachedStatement(SQL_FROM_HERE,
+ "DELETE FROM downloads_jobs WHERE download_id=?"));
+ statement_delete.BindInt(0, id);
+ statement_delete.Run();
+}
+
+void DownloadDatabase::QueryDownloadJobs(
+ std::map<uint32_t, DownloadRow*>* download_row_map) {
Scott Hess - ex-Googler 2017/02/06 21:22:16 If you keep the out pointer, you should DCHECK it,
qinmin 2017/02/06 23:39:22 Done.
+ sql::Statement statement_download_job(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "SELECT download_id, job_id, start_position, length, received_bytes, "
+ "state, interrupt_reason FROM downloads_jobs "
+ "ORDER BY download_id, job_id"));
+
+ while (statement_download_job.Step()) {
+ int column = 0;
+ // See the comment above about SQLITE lacking unsigned integers.
Scott Hess - ex-Googler 2017/02/06 21:22:16 404 - Comment Not Found That said - why does it n
qinmin 2017/02/06 23:39:22 Changed the comments to make it make more sense. T
+ int64_t signed_id = statement_download_job.ColumnInt64(column++);
+ if (signed_id <= static_cast<int64_t>(kInvalidDownloadId)) {
+ LOG(ERROR) << "Invalid download ID found in downloads_jobs table "
+ << signed_id;
+ continue;
+ }
+ int download_id = IntToDownloadId(signed_id);
Scott Hess - ex-Googler 2017/02/06 21:22:16 This should either be DownloadId to match the func
qinmin 2017/02/06 23:39:21 Done.
+ // Confirm the download_id has already been seen--if it hasn't, discard the
+ // record.
Scott Hess - ex-Googler 2017/02/06 21:22:16 The record is still in the database, right? Is th
qinmin 2017/02/06 23:39:21 Call RemoveDownloadJobs() to remove the job from d
+ bool found = base::ContainsKey(*download_row_map, download_id);
+ UMA_HISTOGRAM_BOOLEAN(
+ "Download.DatabaseDownloadExistsForDownloadJob", found);
+ DCHECK(found);
+ if (!found)
+ continue;
+
+ DownloadJobInfo info;
+ info.download_id = download_id;
+ info.job_id = statement_download_job.ColumnInt(column++);
+ info.start_position = statement_download_job.ColumnInt64(column++);
+ info.length = statement_download_job.ColumnInt64(column++);
+ info.received_bytes = statement_download_job.ColumnInt64(column++);
+ info.state = IntToDownloadState(
+ statement_download_job.ColumnInt(column++));
+ info.interrupt_reason = IntToDownloadInterruptReason(
+ statement_download_job.ColumnInt(column++));
+ (*download_row_map)[download_id]->download_job_info.push_back(info);
+ }
+}
+
} // namespace history

Powered by Google App Engine
This is Rietveld 408576698