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

Unified Diff: components/previews/core/previews_opt_out_store_sql.cc

Issue 2410153008: Add remaining implementations to PreviewsOptOutStoreSQL (Closed)
Patch Set: shess comments Created 4 years, 2 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/previews/core/previews_opt_out_store_sql.cc
diff --git a/components/previews/core/previews_opt_out_store_sql.cc b/components/previews/core/previews_opt_out_store_sql.cc
index 1673b78b5e29842db96fd553f242668c2a2a4982..d4e6a59eac658be2f87160b297f2300a116749e2 100644
--- a/components/previews/core/previews_opt_out_store_sql.cc
+++ b/components/previews/core/previews_opt_out_store_sql.cc
@@ -1,39 +1,48 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/previews/core/previews_opt_out_store_sql.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/previews/core/previews_black_list.h"
#include "components/previews/core/previews_black_list_item.h"
#include "components/previews/core/previews_experiments.h"
#include "sql/connection.h"
#include "sql/recovery.h"
#include "sql/statement.h"
#include "sql/transaction.h"
namespace previews {
namespace {
// This is a macro instead of a const, so it can be used inline in other SQL
// statements below.
#define PREVIEWS_TABLE_NAME "previews_v1"
+// The maximum number of entries allowed per host. Entries are evicted based on
+// entry time.
+const int kMaxRowsPerHost = 32;
+
+// The maximum number of entries allowed in the data base. Entries are evicted
+// based on entry time.
+const int kMaxRowsInDB = 3200;
+
void CreateSchema(sql::Connection* db) {
const char kSql[] = "CREATE TABLE IF NOT EXISTS " PREVIEWS_TABLE_NAME
" (host_name VARCHAR NOT NULL,"
" time INTEGER NOT NULL,"
" opt_out INTEGER NOT NULL,"
" type INTEGER NOT NULL,"
" PRIMARY KEY(host_name, time DESC, opt_out, type))";
if (!db->Execute(kSql))
return;
}
@@ -87,90 +96,189 @@ void InitDatabase(sql::Connection* db, base::FilePath path) {
if (!base::CreateDirectoryAndGetError(path.DirName(), &err)) {
return;
}
if (!db->Open(path)) {
return;
}
CreateSchema(db);
}
+// Adds the new entry to the data base.
+void AddPreviewNavigationToDataBase(sql::Connection* db,
+ bool opt_out,
+ const std::string& host_name,
+ PreviewsType type,
+ base::Time now) {
+ // Adds the new entry.
+ const char kSqlInsert[] = "INSERT INTO " PREVIEWS_TABLE_NAME
+ " (host_name, time, opt_out, type)"
+ " VALUES "
+ " (?, ?, ?, ?)";
+
+ sql::Statement statement_insert(
+ db->GetCachedStatement(SQL_FROM_HERE, kSqlInsert));
+ statement_insert.BindString(0, host_name);
+ statement_insert.BindInt64(1, now.ToInternalValue());
+ statement_insert.BindBool(2, opt_out);
+ statement_insert.BindInt(3, static_cast<int>(type));
+ statement_insert.Run();
+}
+
+// Removes entries for |host_name| if the per-host row limit is exceeded.
+// Removes entries if per data base row limit is exceeded.
+void MaybeEvictHostEntryFromDataBase(sql::Connection* db,
+ const std::string& host_name) {
+ // Delete the oldest entries if there are more than |kMaxRowsPerHost| for
+ // |host_name|.
+ // DELETE ... LIMIT -1 OFFSET x means delete all but the first x entries.
+ const char kSqlDeleteByHost[] = "DELETE FROM " PREVIEWS_TABLE_NAME
+ " WHERE ROWID IN"
+ " (SELECT ROWID from " PREVIEWS_TABLE_NAME
+ " WHERE host_name == ?"
+ " ORDER BY time DESC"
+ " LIMIT -1 OFFSET ?)";
+
+ sql::Statement statement_delete_by_host(
+ db->GetCachedStatement(SQL_FROM_HERE, kSqlDeleteByHost));
+ statement_delete_by_host.BindString(0, host_name);
+ statement_delete_by_host.BindInt(1, kMaxRowsPerHost);
+ statement_delete_by_host.Run();
+}
+
void LoadBlackListFromDataBase(
sql::Connection* db,
scoped_refptr<base::SingleThreadTaskRunner> runner,
LoadBlackListCallback callback) {
// Gets the table sorted by host and time. Limits the number of hosts using
// most recent opt_out time as the limiting function.
const char kSql[] =
"SELECT host_name, time, opt_out"
" FROM " PREVIEWS_TABLE_NAME;
sql::Statement statement(db->GetUniqueStatement(kSql));
std::unique_ptr<BlackListItemMap> black_list_item_map(new BlackListItemMap());
+ int count = 0;
// Add the host name, the visit time, and opt out history to
// |black_list_item_map|.
while (statement.Step()) {
+ ++count;
std::string host_name = statement.ColumnString(0);
PreviewsBlackListItem* black_list_item =
PreviewsBlackList::GetOrCreateBlackListItem(black_list_item_map.get(),
host_name);
DCHECK_LE(black_list_item_map->size(),
params::MaxInMemoryHostsInBlackList());
// Allows the internal logic of PreviewsBlackListItem to determine how to
// evict entries when there are more than
// |StoredHistoryLengthForBlackList()| for the host.
black_list_item->AddPreviewNavigation(
statement.ColumnBool(2),
base::Time::FromInternalValue(statement.ColumnInt64(1)));
}
+ // TODO(ryansturm): Add UMA to log |count|. crbug.com/656739
Scott Hess - ex-Googler 2016/10/17 23:18:09 Also please be sure to test this. In thinking abo
RyanSturm 2016/10/17 23:26:38 Acknowledged.
+ if (count > kMaxRowsInDB) {
+ // Delete the oldest entries if there are more than |kMaxEntriesInDB|.
+ // DELETE ... LIMIT -1 OFFSET x means delete all but the first x entries.
+ const char kSqlDeleteByDBSize[] = "DELETE FROM " PREVIEWS_TABLE_NAME
+ " WHERE ROWID IN"
+ " (SELECT ROWID from " PREVIEWS_TABLE_NAME
+ " ORDER BY time DESC"
+ " LIMIT -1 OFFSET ?)";
+
+ sql::Statement statement_delete(
+ db->GetCachedStatement(SQL_FROM_HERE, kSqlDeleteByDBSize));
+ statement_delete.BindInt(0, kMaxRowsInDB);
+ statement_delete.Run();
+ }
+
runner->PostTask(FROM_HERE,
base::Bind(callback, base::Passed(&black_list_item_map)));
}
-// Synchronous implementation, this is run on the background thread
-// and actually does the work to access SQL.
+// Synchronous implementations, these are run on the background thread
+// and actually do the work to access the SQL data base.
void LoadBlackListSync(sql::Connection* db,
const base::FilePath& path,
scoped_refptr<base::SingleThreadTaskRunner> runner,
LoadBlackListCallback callback) {
if (!db->is_open())
InitDatabase(db, path);
LoadBlackListFromDataBase(db, runner, callback);
}
+// Deletes every row in the table that has entry time between |begin_time| and
+// |end_time|.
+void ClearBlackListSync(sql::Connection* db,
+ base::Time begin_time,
+ base::Time end_time) {
+ const char kSql[] =
+ "DELETE FROM " PREVIEWS_TABLE_NAME " WHERE time >= ? and time <= ?";
+
+ sql::Statement statement(db->GetUniqueStatement(kSql));
+ statement.BindInt64(0, begin_time.ToInternalValue());
+ statement.BindInt64(1, end_time.ToInternalValue());
+ statement.Run();
+}
+
+void AddPreviewNavigationSync(bool opt_out,
+ const std::string& host_name,
+ PreviewsType type,
+ base::Time now,
+ sql::Connection* db) {
+ sql::Transaction transaction(db);
+ if (!transaction.Begin())
+ return;
+ AddPreviewNavigationToDataBase(db, opt_out, host_name, type, now);
+ MaybeEvictHostEntryFromDataBase(db, host_name);
+ transaction.Commit();
+}
+
} // namespace
PreviewsOptOutStoreSQL::PreviewsOptOutStoreSQL(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<base::SequencedTaskRunner> background_task_runner,
const base::FilePath& path)
: io_task_runner_(io_task_runner),
background_task_runner_(background_task_runner),
db_file_path_(path) {}
PreviewsOptOutStoreSQL::~PreviewsOptOutStoreSQL() {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (db_.get()) {
background_task_runner_->DeleteSoon(FROM_HERE, db_.release());
}
}
void PreviewsOptOutStoreSQL::AddPreviewNavigation(bool opt_out,
const std::string& host_name,
PreviewsType type,
- base::Time now) {}
+ base::Time now) {
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
+ DCHECK(db_.get());
+ background_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&AddPreviewNavigationSync, opt_out, host_name, type,
+ now, db_.get()));
+}
void PreviewsOptOutStoreSQL::ClearBlackList(base::Time begin_time,
- base::Time end_time) {}
+ base::Time end_time) {
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
+ DCHECK(db_.get());
+ background_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&ClearBlackListSync, db_.get(), begin_time, end_time));
+}
void PreviewsOptOutStoreSQL::LoadBlackList(LoadBlackListCallback callback) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
if (!db_)
db_ = base::MakeUnique<sql::Connection>();
background_task_runner_->PostTask(
FROM_HERE, base::Bind(&LoadBlackListSync, db_.get(), db_file_path_,
base::ThreadTaskRunnerHandle::Get(), callback));
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698