Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "chrome/browser/history/visit_database.h" | 5 #include "chrome/browser/history/visit_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
| 14 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 16 #include "base/timer.h" | 16 #include "base/timer.h" |
| 17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "chrome/browser/history/url_database.h" | 18 #include "chrome/browser/history/url_database.h" |
| 19 #include "chrome/browser/history/visit_filter.h" | 19 #include "chrome/browser/history/visit_filter.h" |
| 20 #include "chrome/common/url_constants.h" | 20 #include "chrome/common/url_constants.h" |
| 21 #include "content/public/common/page_transition_types.h" | 21 #include "content/public/common/page_transition_types.h" |
| 22 #include "sql/statement.h" | 22 #include "sql/statement.h" |
| 23 | 23 |
| 24 // Rows, in order, of the visit table. | 24 // Rows, in order, of the visit table. |
| 25 #define HISTORY_VISIT_ROW_FIELDS \ | 25 #define HISTORY_VISIT_ROW_FIELDS \ |
| 26 " id,url,visit_time,from_visit,transition,segment_id,is_indexed " | 26 " id,url,visit_time,from_visit,transition,segment_id,is_indexed," \ |
|
GeorgeY
2012/03/27 21:15:57
nit: I think we should have 4 spaces indent here a
Wei Li
2012/03/27 23:01:50
Done.
| |
| 27 "visit_duration " | |
| 27 | 28 |
| 28 namespace history { | 29 namespace history { |
| 29 | 30 |
| 30 // Performs analysis of all local browsing data in the visits table to | 31 // Performs analysis of all local browsing data in the visits table to |
| 31 // assess the feasibility of performing prerendering on that data. | 32 // assess the feasibility of performing prerendering on that data. |
| 32 // Will emulate prerendering based on a simple heuristic: On each | 33 // Will emulate prerendering based on a simple heuristic: On each |
| 33 // pageview, pick most likely next page viewed in the next 5 minutes | 34 // pageview, pick most likely next page viewed in the next 5 minutes |
| 34 // based on historical data; keep a maximum of 5 prerenders; evict | 35 // based on historical data; keep a maximum of 5 prerenders; evict |
| 35 // prerenders older than 5 minutes or based on likelihood. Will report | 36 // prerenders older than 5 minutes or based on likelihood. Will report |
| 36 // back hypothetical prerender rate & accuracy via histograms. | 37 // back hypothetical prerender rate & accuracy via histograms. |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 visit_analysis_->Init(); | 338 visit_analysis_->Init(); |
| 338 if (!GetDB().DoesTableExist("visits")) { | 339 if (!GetDB().DoesTableExist("visits")) { |
| 339 if (!GetDB().Execute("CREATE TABLE visits(" | 340 if (!GetDB().Execute("CREATE TABLE visits(" |
| 340 "id INTEGER PRIMARY KEY," | 341 "id INTEGER PRIMARY KEY," |
| 341 "url INTEGER NOT NULL," // key of the URL this corresponds to | 342 "url INTEGER NOT NULL," // key of the URL this corresponds to |
| 342 "visit_time INTEGER NOT NULL," | 343 "visit_time INTEGER NOT NULL," |
| 343 "from_visit INTEGER," | 344 "from_visit INTEGER," |
| 344 "transition INTEGER DEFAULT 0 NOT NULL," | 345 "transition INTEGER DEFAULT 0 NOT NULL," |
| 345 "segment_id INTEGER," | 346 "segment_id INTEGER," |
| 346 // True when we have indexed data for this visit. | 347 // True when we have indexed data for this visit. |
| 347 "is_indexed BOOLEAN)")) | 348 "is_indexed BOOLEAN," |
| 349 "visit_duration INTEGER DEFAULT 0 NOT NULL)")) | |
| 348 return false; | 350 return false; |
| 349 } else if (!GetDB().DoesColumnExist("visits", "is_indexed")) { | 351 } else { |
| 350 // Old versions don't have the is_indexed column, we can just add that and | 352 if (!GetDB().DoesColumnExist("visits", "is_indexed")) { |
| 351 // not worry about different database revisions, since old ones will | 353 // Old versions don't have the is_indexed column, we can just add that and |
| 352 // continue to work. | 354 // not worry about different database revisions, since old ones will |
| 353 // | 355 // continue to work. |
| 354 // TODO(brettw) this should be removed once we think everybody has been | 356 // |
| 355 // updated (added early Mar 2008). | 357 // TODO(brettw) this should be removed once we think everybody has been |
| 356 if (!GetDB().Execute("ALTER TABLE visits ADD COLUMN is_indexed BOOLEAN")) | 358 // updated (added early Mar 2008). |
| 357 return false; | 359 if (!GetDB().Execute("ALTER TABLE visits ADD COLUMN is_indexed BOOLEAN")) |
| 360 return false; | |
| 361 } | |
| 362 if (!GetDB().DoesColumnExist("visits", "visit_duration")) { | |
|
GeorgeY
2012/03/27 21:15:57
Why do we need to do here as well in addition to M
Wei Li
2012/03/27 23:01:50
I used this to guard some manual errors such as ve
| |
| 363 // Old versions don't have the visit_duration column, we can just add that | |
| 364 // without worrying about different database revisions since old ones will | |
| 365 // continue to work. | |
| 366 if (!GetDB().Execute("ALTER TABLE visits " | |
| 367 "ADD COLUMN visit_duration INTEGER DEFAULT 0 NOT NULL")) | |
| 368 return false; | |
| 369 } | |
| 358 } | 370 } |
| 359 | 371 |
| 360 // Visit source table contains the source information for all the visits. To | 372 // Visit source table contains the source information for all the visits. To |
| 361 // save space, we do not record those user browsed visits which would be the | 373 // save space, we do not record those user browsed visits which would be the |
| 362 // majority in this table. Only other sources are recorded. | 374 // majority in this table. Only other sources are recorded. |
| 363 // Due to the tight relationship between visit_source and visits table, they | 375 // Due to the tight relationship between visit_source and visits table, they |
| 364 // should be created and dropped at the same time. | 376 // should be created and dropped at the same time. |
| 365 if (!GetDB().DoesTableExist("visit_source")) { | 377 if (!GetDB().DoesTableExist("visit_source")) { |
| 366 if (!GetDB().Execute("CREATE TABLE visit_source(" | 378 if (!GetDB().Execute("CREATE TABLE visit_source(" |
| 367 "id INTEGER PRIMARY KEY,source INTEGER NOT NULL)")) | 379 "id INTEGER PRIMARY KEY,source INTEGER NOT NULL)")) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 400 // Must be in sync with HISTORY_VISIT_ROW_FIELDS. | 412 // Must be in sync with HISTORY_VISIT_ROW_FIELDS. |
| 401 // static | 413 // static |
| 402 void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) { | 414 void VisitDatabase::FillVisitRow(sql::Statement& statement, VisitRow* visit) { |
| 403 visit->visit_id = statement.ColumnInt64(0); | 415 visit->visit_id = statement.ColumnInt64(0); |
| 404 visit->url_id = statement.ColumnInt64(1); | 416 visit->url_id = statement.ColumnInt64(1); |
| 405 visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2)); | 417 visit->visit_time = base::Time::FromInternalValue(statement.ColumnInt64(2)); |
| 406 visit->referring_visit = statement.ColumnInt64(3); | 418 visit->referring_visit = statement.ColumnInt64(3); |
| 407 visit->transition = content::PageTransitionFromInt(statement.ColumnInt(4)); | 419 visit->transition = content::PageTransitionFromInt(statement.ColumnInt(4)); |
| 408 visit->segment_id = statement.ColumnInt64(5); | 420 visit->segment_id = statement.ColumnInt64(5); |
| 409 visit->is_indexed = !!statement.ColumnInt(6); | 421 visit->is_indexed = !!statement.ColumnInt(6); |
| 422 visit->visit_duration = | |
| 423 base::TimeDelta::FromInternalValue(statement.ColumnInt64(7)); | |
| 410 } | 424 } |
| 411 | 425 |
| 412 // static | 426 // static |
| 413 bool VisitDatabase::FillVisitVector(sql::Statement& statement, | 427 bool VisitDatabase::FillVisitVector(sql::Statement& statement, |
| 414 VisitVector* visits) { | 428 VisitVector* visits) { |
| 415 if (!statement.is_valid()) | 429 if (!statement.is_valid()) |
| 416 return false; | 430 return false; |
| 417 | 431 |
| 418 while (statement.Step()) { | 432 while (statement.Step()) { |
| 419 history::VisitRow visit; | 433 history::VisitRow visit; |
| 420 FillVisitRow(statement, &visit); | 434 FillVisitRow(statement, &visit); |
| 421 visits->push_back(visit); | 435 visits->push_back(visit); |
| 422 } | 436 } |
| 423 | 437 |
| 424 return statement.Succeeded(); | 438 return statement.Succeeded(); |
| 425 } | 439 } |
| 426 | 440 |
| 427 VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) { | 441 VisitID VisitDatabase::AddVisit(VisitRow* visit, VisitSource source) { |
| 428 visit_analysis_->AddVisit(visit); | 442 visit_analysis_->AddVisit(visit); |
| 429 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 443 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 430 "INSERT INTO visits " | 444 "INSERT INTO visits " |
| 431 "(url, visit_time, from_visit, transition, segment_id, is_indexed) " | 445 "(url, visit_time, from_visit, transition, segment_id, is_indexed, " |
| 432 "VALUES (?,?,?,?,?,?)")); | 446 "visit_duration) VALUES (?,?,?,?,?,?,?)")); |
| 433 statement.BindInt64(0, visit->url_id); | 447 statement.BindInt64(0, visit->url_id); |
| 434 statement.BindInt64(1, visit->visit_time.ToInternalValue()); | 448 statement.BindInt64(1, visit->visit_time.ToInternalValue()); |
| 435 statement.BindInt64(2, visit->referring_visit); | 449 statement.BindInt64(2, visit->referring_visit); |
| 436 statement.BindInt64(3, visit->transition); | 450 statement.BindInt64(3, visit->transition); |
| 437 statement.BindInt64(4, visit->segment_id); | 451 statement.BindInt64(4, visit->segment_id); |
| 438 statement.BindInt64(5, visit->is_indexed); | 452 statement.BindInt64(5, visit->is_indexed); |
| 453 statement.BindInt64(6, visit->visit_duration.ToInternalValue()); | |
| 439 | 454 |
| 440 if (!statement.Run()) { | 455 if (!statement.Run()) { |
| 441 VLOG(0) << "Failed to execute visit insert statement: " | 456 VLOG(0) << "Failed to execute visit insert statement: " |
| 442 << "url_id = " << visit->url_id; | 457 << "url_id = " << visit->url_id; |
| 443 return 0; | 458 return 0; |
| 444 } | 459 } |
| 445 | 460 |
| 446 visit->visit_id = GetDB().GetLastInsertRowId(); | 461 visit->visit_id = GetDB().GetLastInsertRowId(); |
| 447 | 462 |
| 448 if (source != SOURCE_BROWSED) { | 463 if (source != SOURCE_BROWSED) { |
| 449 // Record the source of this visit when it is not browsed. | 464 // Record the source of this visit when it is not browsed. |
| 450 sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE, | 465 sql::Statement statement1(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 451 "INSERT INTO visit_source (id, source) VALUES (?,?)")); | 466 "INSERT INTO visit_source (id, source) VALUES (?,?)")); |
| 452 statement1.BindInt64(0, visit->visit_id); | 467 statement1.BindInt64(0, visit->visit_id); |
| 453 statement1.BindInt64(1, source); | 468 statement1.BindInt64(1, source); |
| 454 | 469 |
| 455 if (!statement1.Run()) { | 470 if (!statement1.Run()) { |
| 456 VLOG(0) << "Failed to execute visit_source insert statement: " | 471 VLOG(0) << "Failed to execute visit_source insert statement: " |
| 457 << "url_id = " << visit->visit_id; | 472 << "id = " << visit->visit_id; |
| 458 return 0; | 473 return 0; |
| 459 } | 474 } |
| 460 } | 475 } |
| 461 | 476 |
| 462 return visit->visit_id; | 477 return visit->visit_id; |
| 463 } | 478 } |
| 464 | 479 |
| 465 void VisitDatabase::DeleteVisit(const VisitRow& visit) { | 480 void VisitDatabase::DeleteVisit(const VisitRow& visit) { |
| 466 // Patch around this visit. Any visits that this went to will now have their | 481 // Patch around this visit. Any visits that this went to will now have their |
| 467 // "source" be the deleted visit's source. | 482 // "source" be the deleted visit's source. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 } | 522 } |
| 508 | 523 |
| 509 bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { | 524 bool VisitDatabase::UpdateVisitRow(const VisitRow& visit) { |
| 510 // Don't store inconsistent data to the database. | 525 // Don't store inconsistent data to the database. |
| 511 DCHECK_NE(visit.visit_id, visit.referring_visit); | 526 DCHECK_NE(visit.visit_id, visit.referring_visit); |
| 512 if (visit.visit_id == visit.referring_visit) | 527 if (visit.visit_id == visit.referring_visit) |
| 513 return false; | 528 return false; |
| 514 | 529 |
| 515 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 530 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 516 "UPDATE visits SET " | 531 "UPDATE visits SET " |
| 517 "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?,is_indexed=? " | 532 "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?,is_indexed=?," |
| 518 "WHERE id=?")); | 533 "visit_duration=? WHERE id=?")); |
| 519 statement.BindInt64(0, visit.url_id); | 534 statement.BindInt64(0, visit.url_id); |
| 520 statement.BindInt64(1, visit.visit_time.ToInternalValue()); | 535 statement.BindInt64(1, visit.visit_time.ToInternalValue()); |
| 521 statement.BindInt64(2, visit.referring_visit); | 536 statement.BindInt64(2, visit.referring_visit); |
| 522 statement.BindInt64(3, visit.transition); | 537 statement.BindInt64(3, visit.transition); |
| 523 statement.BindInt64(4, visit.segment_id); | 538 statement.BindInt64(4, visit.segment_id); |
| 524 statement.BindInt64(5, visit.is_indexed); | 539 statement.BindInt64(5, visit.is_indexed); |
| 525 statement.BindInt64(6, visit.visit_id); | 540 statement.BindInt64(6, visit.visit_duration.ToInternalValue()); |
| 541 statement.BindInt64(7, visit.visit_id); | |
| 526 | 542 |
| 527 return statement.Run(); | 543 return statement.Run(); |
| 528 } | 544 } |
| 529 | 545 |
| 530 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { | 546 bool VisitDatabase::GetVisitsForURL(URLID url_id, VisitVector* visits) { |
| 531 visits->clear(); | 547 visits->clear(); |
| 532 | 548 |
| 533 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, | 549 sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
| 534 "SELECT" HISTORY_VISIT_ROW_FIELDS | 550 "SELECT" HISTORY_VISIT_ROW_FIELDS |
| 535 "FROM visits " | 551 "FROM visits " |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 | 851 |
| 836 // Get the source entries out of the query result. | 852 // Get the source entries out of the query result. |
| 837 while (statement.Step()) { | 853 while (statement.Step()) { |
| 838 std::pair<VisitID, VisitSource> source_entry(statement.ColumnInt64(0), | 854 std::pair<VisitID, VisitSource> source_entry(statement.ColumnInt64(0), |
| 839 static_cast<VisitSource>(statement.ColumnInt(1))); | 855 static_cast<VisitSource>(statement.ColumnInt(1))); |
| 840 sources->insert(source_entry); | 856 sources->insert(source_entry); |
| 841 } | 857 } |
| 842 } | 858 } |
| 843 } | 859 } |
| 844 | 860 |
| 861 bool VisitDatabase::MigrateVisitsWithoutDuration() { | |
| 862 if (!GetDB().DoesTableExist("visits")) { | |
| 863 NOTREACHED() << " Visits table should exist before migration"; | |
| 864 return false; | |
| 865 } | |
| 866 | |
| 867 if (!GetDB().DoesColumnExist("visits", "visit_duration")) { | |
| 868 // Old versions don't have the visit_duration column, we modify the table | |
| 869 // to add that field. | |
| 870 if (!GetDB().Execute( | |
| 871 "ALTER TABLE visits ADD COLUMN visit_duration DEFAULT 0 NOT NULL")) | |
| 872 return false; | |
| 873 } | |
| 874 return true; | |
| 875 } | |
| 876 | |
| 845 } // namespace history | 877 } // namespace history |
| OLD | NEW |