| Index: chrome/browser/net/sqlite_persistent_cookie_store.cc
|
| diff --git a/chrome/browser/net/sqlite_persistent_cookie_store.cc b/chrome/browser/net/sqlite_persistent_cookie_store.cc
|
| index ef531c363f15f15244c1ba60b89d5cbd18b969ce..6c4ac1f0b793faf58acda1008f0f9f1ab1b72cff 100644
|
| --- a/chrome/browser/net/sqlite_persistent_cookie_store.cc
|
| +++ b/chrome/browser/net/sqlite_persistent_cookie_store.cc
|
| @@ -21,6 +21,7 @@
|
| #include "base/synchronization/lock.h"
|
| #include "base/threading/thread.h"
|
| #include "base/threading/thread_restrictions.h"
|
| +#include "base/time.h"
|
| #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "googleurl/src/gurl.h"
|
| @@ -39,15 +40,15 @@ using content::BrowserThread;
|
| // delegates to Backend::Load, which posts a Backend::LoadAndNotifyOnDBThread
|
| // task to the DB thread. This task calls Backend::ChainLoadCookies(), which
|
| // repeatedly posts itself to the DB thread to load each eTLD+1's cookies in
|
| -// separate tasks. When this is complete, Backend::NotifyOnIOThread is posted
|
| -// to the IO thread, which notifies the caller of SQLitePersistentCookieStore::
|
| -// Load that the load is complete.
|
| +// separate tasks. When this is complete, Backend::CompleteLoadOnIOThread is
|
| +// posted to the IO thread, which notifies the caller of
|
| +// SQLitePersistentCookieStore::Load that the load is complete.
|
| //
|
| // If a priority load request is invoked via SQLitePersistentCookieStore::
|
| // LoadCookiesForKey, it is delegated to Backend::LoadCookiesForKey, which posts
|
| // Backend::LoadKeyAndNotifyOnDBThread to the DB thread. That routine loads just
|
| // that single domain key (eTLD+1)'s cookies, and posts a Backend::
|
| -// NotifyOnIOThread to the IO thread to notify the caller of
|
| +// CompleteLoadForKeyOnIOThread to the IO thread to notify the caller of
|
| // SQLitePersistentCookieStore::LoadCookiesForKey that that load is complete.
|
| //
|
| // Subsequent to loading, mutations may be queued by any thread using
|
| @@ -62,7 +63,9 @@ class SQLitePersistentCookieStore::Backend
|
| db_(NULL),
|
| num_pending_(0),
|
| clear_local_state_on_exit_(false),
|
| - initialized_(false) {
|
| + initialized_(false),
|
| + num_priority_waiting_(0),
|
| + total_priority_requests_(0) {
|
| }
|
|
|
| // Creates or loads the SQLite database.
|
| @@ -133,9 +136,26 @@ class SQLitePersistentCookieStore::Backend
|
| // Notifies the CookieMonster when loading completes for a specific domain key
|
| // or for all domain keys. Triggers the callback and passes it all cookies
|
| // that have been loaded from DB since last IO notification.
|
| - void NotifyOnIOThread(
|
| - const LoadedCallback& loaded_callback,
|
| - bool load_success);
|
| + void Notify(const LoadedCallback& loaded_callback, bool load_success);
|
| +
|
| + // Sends notification when the entire store is loaded, and reports metrics
|
| + // for the total time to load and aggregated results from any priority loads
|
| + // that occurred.
|
| + void CompleteLoadOnIOThread(const LoadedCallback& loaded_callback,
|
| + bool load_success);
|
| +
|
| + // Sends notification when a single priority load completes. Updates priority
|
| + // load metric data. The data is sent only after the final load completes.
|
| + void CompleteLoadForKeyOnIOThread(const LoadedCallback& loaded_callback,
|
| + bool load_success);
|
| +
|
| + // Sends all metrics, including posting a ReportMetricsOnDBThread task.
|
| + // Called after all priority and regular loading is complete.
|
| + void ReportMetrics();
|
| +
|
| + // Sends DB-thread owned metrics (i.e., the combined duration of all DB-thread
|
| + // tasks).
|
| + void ReportMetricsOnDBThread();
|
|
|
| // Initialize the data base.
|
| bool InitializeDatabase();
|
| @@ -165,8 +185,7 @@ class SQLitePersistentCookieStore::Backend
|
| PendingOperationsList::size_type num_pending_;
|
| // True if the persistent store should be deleted upon destruction.
|
| bool clear_local_state_on_exit_;
|
| - // Guard |cookies_|, |pending_|, |num_pending_| and
|
| - // |clear_local_state_on_exit_|.
|
| + // Guard |cookies_|, |pending_|, |num_pending_|, |clear_local_state_on_exit_|
|
| base::Lock lock_;
|
|
|
| // Temporary buffer for cookies loaded from DB. Accumulates cookies to reduce
|
| @@ -180,6 +199,22 @@ class SQLitePersistentCookieStore::Backend
|
| // Indicates if DB has been initialized.
|
| bool initialized_;
|
|
|
| + // The cumulative time spent loading the cookies on the DB thread. Incremented
|
| + // and reported from the DB thread.
|
| + base::TimeDelta cookie_load_duration_;
|
| +
|
| + // Guards the following metrics-related properties (only accessed when
|
| + // starting/completing priority loads or completing the total load).
|
| + base::Lock metrics_lock_;
|
| + int num_priority_waiting_;
|
| + // The total number of priority requests.
|
| + int total_priority_requests_;
|
| + // The time when |num_priority_waiting_| incremented to 1.
|
| + base::Time current_priority_wait_start_;
|
| + // The cumulative duration of time when |num_priority_waiting_| was greater
|
| + // than 1.
|
| + base::TimeDelta priority_wait_duration_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(Backend);
|
| };
|
|
|
| @@ -196,6 +231,29 @@ static const int kCompatibleVersionNumber = 3;
|
|
|
| namespace {
|
|
|
| +// Increments a specified TimeDelta by the duration between this object's
|
| +// constructor and destructor. Not thread safe. Multiple instances may be
|
| +// created with the same delta instance as long as their lifetimes are nested.
|
| +// The shortest lived instances have no impact.
|
| +class IncrementTimeDelta {
|
| + public:
|
| + explicit IncrementTimeDelta(base::TimeDelta* delta) :
|
| + delta_(delta),
|
| + original_value_(*delta),
|
| + start_(base::Time::Now()) {}
|
| +
|
| + ~IncrementTimeDelta() {
|
| + *delta_ = original_value_ + base::Time::Now() - start_;
|
| + }
|
| +
|
| + private:
|
| + base::TimeDelta* delta_;
|
| + base::TimeDelta original_value_;
|
| + base::Time start_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(IncrementTimeDelta);
|
| +};
|
| +
|
| // Initializes the cookies table, returning true on success.
|
| bool InitTable(sql::Connection* db) {
|
| if (!db->DoesTableExist("cookies")) {
|
| @@ -237,6 +295,14 @@ void SQLitePersistentCookieStore::Backend::Load(
|
| void SQLitePersistentCookieStore::Backend::LoadCookiesForKey(
|
| const std::string& key,
|
| const LoadedCallback& loaded_callback) {
|
| + {
|
| + base::AutoLock locked(metrics_lock_);
|
| + if (num_priority_waiting_ == 0)
|
| + current_priority_wait_start_ = base::Time::Now();
|
| + num_priority_waiting_++;
|
| + total_priority_requests_++;
|
| + }
|
| +
|
| BrowserThread::PostTask(
|
| BrowserThread::DB, FROM_HERE,
|
| base::Bind(&Backend::LoadKeyAndNotifyOnDBThread, this,
|
| @@ -247,11 +313,12 @@ void SQLitePersistentCookieStore::Backend::LoadCookiesForKey(
|
| void SQLitePersistentCookieStore::Backend::LoadAndNotifyOnDBThread(
|
| const LoadedCallback& loaded_callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
|
| + IncrementTimeDelta increment(&cookie_load_duration_);
|
|
|
| if (!InitializeDatabase()) {
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&SQLitePersistentCookieStore::Backend::NotifyOnIOThread,
|
| + base::Bind(&SQLitePersistentCookieStore::Backend::CompleteLoadOnIOThread,
|
| this, loaded_callback, false));
|
| } else {
|
| ChainLoadCookies(loaded_callback);
|
| @@ -262,6 +329,7 @@ void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyOnDBThread(
|
| const std::string& key,
|
| const LoadedCallback& loaded_callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
|
| + IncrementTimeDelta increment(&cookie_load_duration_);
|
|
|
| bool success = false;
|
| if (InitializeDatabase()) {
|
| @@ -277,11 +345,62 @@ void SQLitePersistentCookieStore::Backend::LoadKeyAndNotifyOnDBThread(
|
|
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&SQLitePersistentCookieStore::Backend::NotifyOnIOThread,
|
| - this, loaded_callback, success));
|
| + base::Bind(
|
| + &SQLitePersistentCookieStore::Backend::CompleteLoadForKeyOnIOThread,
|
| + this, loaded_callback, success));
|
| +}
|
| +
|
| +void SQLitePersistentCookieStore::Backend::CompleteLoadForKeyOnIOThread(
|
| + const LoadedCallback& loaded_callback,
|
| + bool load_success) {
|
| + Notify(loaded_callback, load_success);
|
| +
|
| + {
|
| + base::AutoLock locked(metrics_lock_);
|
| + num_priority_waiting_--;
|
| + if (num_priority_waiting_ == 0) {
|
| + priority_wait_duration_ +=
|
| + base::Time::Now() - current_priority_wait_start_;
|
| + }
|
| + }
|
| +
|
| +}
|
| +
|
| +void SQLitePersistentCookieStore::Backend::ReportMetricsOnDBThread() {
|
| + UMA_HISTOGRAM_CUSTOM_TIMES(
|
| + "Cookie.TimeLoad",
|
| + cookie_load_duration_,
|
| + base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
|
| + 50);
|
| +}
|
| +
|
| +void SQLitePersistentCookieStore::Backend::ReportMetrics() {
|
| + BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, base::Bind(
|
| + &SQLitePersistentCookieStore::Backend::ReportMetricsOnDBThread, this));
|
| +
|
| + {
|
| + base::AutoLock locked(metrics_lock_);
|
| + UMA_HISTOGRAM_CUSTOM_TIMES(
|
| + "Cookie.PriorityBlockingTime",
|
| + priority_wait_duration_,
|
| + base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1),
|
| + 50);
|
| +
|
| + UMA_HISTOGRAM_COUNTS_100(
|
| + "Cookie.PriorityLoadCount",
|
| + total_priority_requests_);
|
| + }
|
| +}
|
| +
|
| +void SQLitePersistentCookieStore::Backend::CompleteLoadOnIOThread(
|
| + const LoadedCallback& loaded_callback, bool load_success) {
|
| + Notify(loaded_callback, load_success);
|
| +
|
| + if (load_success)
|
| + ReportMetrics();
|
| }
|
|
|
| -void SQLitePersistentCookieStore::Backend::NotifyOnIOThread(
|
| +void SQLitePersistentCookieStore::Backend::Notify(
|
| const LoadedCallback& loaded_callback,
|
| bool load_success) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| @@ -355,6 +474,7 @@ bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
|
| void SQLitePersistentCookieStore::Backend::ChainLoadCookies(
|
| const LoadedCallback& loaded_callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
|
| + IncrementTimeDelta increment(&cookie_load_duration_);
|
|
|
| bool load_success = true;
|
|
|
| @@ -376,7 +496,7 @@ void SQLitePersistentCookieStore::Backend::ChainLoadCookies(
|
| } else {
|
| BrowserThread::PostTask(
|
| BrowserThread::IO, FROM_HERE,
|
| - base::Bind(&SQLitePersistentCookieStore::Backend::NotifyOnIOThread,
|
| + base::Bind(&SQLitePersistentCookieStore::Backend::CompleteLoadOnIOThread,
|
| this, loaded_callback, load_success));
|
| }
|
| }
|
|
|