diff options
author | huanr@chromium.org <huanr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-02 23:52:55 +0000 |
---|---|---|
committer | huanr@chromium.org <huanr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-02 23:52:55 +0000 |
commit | b25566cbeeca6b977ecbfcf1a8e56b554146d815 (patch) | |
tree | 101bdafb407c71250443deee7270325969708a38 /chrome/browser/history | |
parent | 95f1f41562a49729f1366196eb3a951af55914bf (diff) | |
download | chromium_src-b25566cbeeca6b977ecbfcf1a8e56b554146d815.zip chromium_src-b25566cbeeca6b977ecbfcf1a8e56b554146d815.tar.gz chromium_src-b25566cbeeca6b977ecbfcf1a8e56b554146d815.tar.bz2 |
Adding in memory log of history visit database. This
log will be saved in crash dump (to be done in next
CL) to help debug the corruption in history thread.
TEST=Added unit test.
BUG=16591
Review URL: http://codereview.chromium.org/187004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25276 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/history')
-rw-r--r-- | chrome/browser/history/visit_database.cc | 16 | ||||
-rw-r--r-- | chrome/browser/history/visit_log.cc | 56 | ||||
-rw-r--r-- | chrome/browser/history/visit_log.h | 61 | ||||
-rw-r--r-- | chrome/browser/history/visit_log_unittest.cc | 45 |
4 files changed, 178 insertions, 0 deletions
diff --git a/chrome/browser/history/visit_database.cc b/chrome/browser/history/visit_database.cc index 60d4c5b..48975b1 100644 --- a/chrome/browser/history/visit_database.cc +++ b/chrome/browser/history/visit_database.cc @@ -8,6 +8,7 @@ #include <set> #include "chrome/browser/history/visit_database.h" +#include "chrome/browser/history/visit_log.h" #include "chrome/browser/history/url_database.h" #include "chrome/common/page_transition_types.h" @@ -115,6 +116,7 @@ VisitID VisitDatabase::AddVisit(VisitRow* visit) { statement->bind_int64(3, visit->transition); statement->bind_int64(4, visit->segment_id); statement->bind_int64(5, visit->is_indexed); + AddEventToVisitLog(VisitLog::ADD_VISIT); if (statement->step() != SQLITE_DONE) return 0; @@ -132,6 +134,7 @@ void VisitDatabase::DeleteVisit(const VisitRow& visit) { return; update_chain->bind_int64(0, visit.referring_visit); update_chain->bind_int64(1, visit.visit_id); + AddEventToVisitLog(VisitLog::UPDATE_VISIT); update_chain->step(); // Now delete the actual visit. @@ -140,6 +143,7 @@ void VisitDatabase::DeleteVisit(const VisitRow& visit) { if (!del.is_valid()) return; del->bind_int64(0, visit.visit_id); + AddEventToVisitLog(VisitLog::DELETE_VISIT); del->step(); } @@ -150,6 +154,7 @@ bool VisitDatabase::GetRowForVisit(VisitID visit_id, VisitRow* out_visit) { return false; statement->bind_int64(0, visit_id); + AddEventToVisitLog(VisitLog::SELECT_VISIT); if (statement->step() != SQLITE_ROW) return false; @@ -172,6 +177,7 @@ bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { statement->bind_int64(4, visit.segment_id); statement->bind_int64(5, visit.is_indexed); statement->bind_int64(6, visit.visit_id); + AddEventToVisitLog(VisitLog::UPDATE_VISIT); return statement->step() == SQLITE_DONE; } @@ -187,6 +193,7 @@ bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { return false; statement->bind_int64(0, url_id); + AddEventToVisitLog(VisitLog::SELECT_VISIT); FillVisitVector(*statement, visits); return true; } @@ -210,6 +217,7 @@ void VisitDatabase::GetAllVisitsInRange(Time begin_time, Time end_time, statement->bind_int64(2, max_results ? max_results : std::numeric_limits<int64>::max()); + AddEventToVisitLog(VisitLog::SELECT_VISIT); FillVisitVector(*statement, visits); } @@ -239,6 +247,7 @@ void VisitDatabase::GetVisitsInRangeForTransition( statement->bind_int64(4, max_results ? max_results : std::numeric_limits<int64>::max()); + AddEventToVisitLog(VisitLog::SELECT_VISIT); FillVisitVector(*statement, visits); } @@ -271,6 +280,7 @@ void VisitDatabase::GetVisibleVisitsInRange(Time begin_time, Time end_time, statement->bind_int(5, PageTransition::MANUAL_SUBFRAME); statement->bind_int(6, PageTransition::KEYWORD_GENERATED); + AddEventToVisitLog(VisitLog::SELECT_VISIT); std::set<URLID> found_urls; while (statement->step() == SQLITE_ROW) { VisitRow visit; @@ -301,6 +311,7 @@ VisitID VisitDatabase::GetMostRecentVisitForURL(URLID url_id, return 0; statement->bind_int64(0, url_id); + AddEventToVisitLog(VisitLog::SELECT_VISIT); if (statement->step() != SQLITE_ROW) return 0; // No visits for this URL. @@ -329,6 +340,7 @@ bool VisitDatabase::GetMostRecentVisitsForURL(URLID url_id, statement->bind_int64(0, url_id); statement->bind_int(1, max_results); + AddEventToVisitLog(VisitLog::SELECT_VISIT); FillVisitVector(*statement, visits); return true; } @@ -347,6 +359,7 @@ bool VisitDatabase::GetRedirectFromVisit(VisitID from_visit, statement->bind_int64(0, from_visit); statement->bind_int(1, PageTransition::IS_REDIRECT_MASK); + AddEventToVisitLog(VisitLog::SELECT_VISIT); if (statement->step() != SQLITE_ROW) return false; // No redirect from this visit. if (to_visit) @@ -373,6 +386,7 @@ bool VisitDatabase::GetRedirectToVisit(VisitID to_visit, "WHERE v.id = ?"); statement->bind_int64(0, row.referring_visit); + AddEventToVisitLog(VisitLog::SELECT_VISIT); if (statement->step() != SQLITE_ROW) return false; @@ -413,6 +427,7 @@ bool VisitDatabase::GetVisitCountToHost(const GURL& url, statement->bind_string(0, host_query_min); statement->bind_string(1, host_query_max); + AddEventToVisitLog(VisitLog::SELECT_VISIT); if (statement->step() != SQLITE_ROW) { // We've never been to this page before. *count = 0; @@ -427,6 +442,7 @@ bool VisitDatabase::GetVisitCountToHost(const GURL& url, bool VisitDatabase::GetStartDate(Time* first_visit) { SQLITE_UNIQUE_STATEMENT(statement, GetStatementCache(), "SELECT MIN(visit_time) FROM visits WHERE visit_time != 0"); + AddEventToVisitLog(VisitLog::SELECT_VISIT); if (!statement.is_valid() || statement->step() != SQLITE_ROW || statement->column_int64(0) == 0) { *first_visit = Time::Now(); diff --git a/chrome/browser/history/visit_log.cc b/chrome/browser/history/visit_log.cc new file mode 100644 index 0000000..2c74265 --- /dev/null +++ b/chrome/browser/history/visit_log.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2009 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 "chrome/browser/history/visit_log.h" + +namespace history { + +static VisitLog* g_visit_log = NULL; + +VisitLog::VisitLog() + : index_(0), + num_add_(0), + num_delete_(0), + num_update_(0), + num_select_(0) { + memset(events_, NO_OP, sizeof(events_)); +} + +VisitLog::~VisitLog() { +} + +void VisitLog::AddEvent(EventType event) { + switch (event) { + case ADD_VISIT: + num_add_++; + break; + case DELETE_VISIT: + num_delete_++; + break; + case UPDATE_VISIT: + num_update_++; + break; + case SELECT_VISIT: + num_select_++; + break; + default: + return; + } + + events_[index_++] = event; + if (index_ == kVisitLogBufferSize) + index_ = 0; +} + +void InitVisitLog(VisitLog* vlog) { + g_visit_log = vlog; +} + +void AddEventToVisitLog(VisitLog::EventType event) { + if (!g_visit_log) + return; + g_visit_log->AddEvent(event); +} + +} // namespace history diff --git a/chrome/browser/history/visit_log.h b/chrome/browser/history/visit_log.h new file mode 100644 index 0000000..31c4976 --- /dev/null +++ b/chrome/browser/history/visit_log.h @@ -0,0 +1,61 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_HISTORY_VISIT_LOG_H_ +#define CHROME_BROWSER_HISTORY_VISIT_LOG_H_ + +#include "base/basictypes.h" + +namespace history { + +// VisitLog provides support for basic in-memory logging of history visit +// events. It keeps a circular buffer where the recent visit events is +// recorded. + +// This class is not thread safe. +class VisitLog { + public: + VisitLog(); + ~VisitLog(); + + enum EventType { + NO_OP, + ADD_VISIT, + DELETE_VISIT, + UPDATE_VISIT, + SELECT_VISIT, + }; + + static int events_buffer_size() { return kVisitLogBufferSize; } + unsigned char* events() { return events_; } + int index() { return index_; } + + int num_add() { return num_add_; } + int num_delete() { return num_delete_; } + int num_update() { return num_update_; } + int num_select() { return num_select_; } + + void AddEvent(EventType event); + + private: + // Circular buffer of recent events. + static const int kVisitLogBufferSize = 4096; + unsigned char events_[kVisitLogBufferSize]; + int index_; + + // Event counters + int num_add_; + int num_delete_; + int num_update_; + int num_select_; + + DISALLOW_COPY_AND_ASSIGN(VisitLog); +}; + +void InitVisitLog(VisitLog* vlog); +void AddEventToVisitLog(VisitLog::EventType event); + +} // namespace history + +#endif // CHROME_BROWSER_HISTORY_VISIT_LOG_H_ diff --git a/chrome/browser/history/visit_log_unittest.cc b/chrome/browser/history/visit_log_unittest.cc new file mode 100644 index 0000000..5389281 --- /dev/null +++ b/chrome/browser/history/visit_log_unittest.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2009 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 "chrome/browser/history/visit_log.h" +#include "testing/gtest/include/gtest/gtest.h" + +// A simple test that makes sure events are recorded correctly in circular +// buffer. +TEST(VisitLog, SimpleRecording) { + history::VisitLog vlog; + + unsigned char* vlog_buffer = vlog.events(); + int vlog_buffer_size = vlog.events_buffer_size(); + + ASSERT_EQ(history::VisitLog::NO_OP, vlog_buffer[0]); + ASSERT_EQ(history::VisitLog::NO_OP, vlog_buffer[1]); + ASSERT_EQ(history::VisitLog::NO_OP, vlog_buffer[2]); + ASSERT_EQ(history::VisitLog::NO_OP, vlog_buffer[vlog_buffer_size-1]); + + for (int i=0; i<vlog_buffer_size; i++) + vlog.AddEvent(history::VisitLog::ADD_VISIT); + + ASSERT_EQ(history::VisitLog::ADD_VISIT, vlog_buffer[0]); + ASSERT_EQ(history::VisitLog::ADD_VISIT, vlog_buffer[1]); + ASSERT_EQ(history::VisitLog::ADD_VISIT, vlog_buffer[2]); + ASSERT_EQ(history::VisitLog::ADD_VISIT, vlog_buffer[vlog_buffer_size-1]); + ASSERT_EQ(vlog_buffer_size, vlog.num_add()); + ASSERT_EQ(0, vlog.num_delete()); + ASSERT_EQ(0, vlog.num_update()); + ASSERT_EQ(0, vlog.num_select()); + + vlog.AddEvent(history::VisitLog::DELETE_VISIT); + vlog.AddEvent(history::VisitLog::UPDATE_VISIT); + vlog.AddEvent(history::VisitLog::SELECT_VISIT); + + ASSERT_EQ(history::VisitLog::DELETE_VISIT, vlog_buffer[0]); + ASSERT_EQ(history::VisitLog::UPDATE_VISIT, vlog_buffer[1]); + ASSERT_EQ(history::VisitLog::SELECT_VISIT, vlog_buffer[2]); + ASSERT_EQ(history::VisitLog::ADD_VISIT, vlog_buffer[vlog_buffer_size-1]); + ASSERT_EQ(vlog_buffer_size, vlog.num_add()); + ASSERT_EQ(1, vlog.num_delete()); + ASSERT_EQ(1, vlog.num_update()); + ASSERT_EQ(1, vlog.num_select()); +} |