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 "sql/connection.h" | 5 #include "sql/connection.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/debug/dump_without_crashing.h" | 14 #include "base/debug/dump_without_crashing.h" |
| 15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 16 #include "base/files/file_util.h" | 16 #include "base/files/file_util.h" |
| 17 #include "base/format_macros.h" | 17 #include "base/format_macros.h" |
| 18 #include "base/json/json_file_value_serializer.h" | 18 #include "base/json/json_file_value_serializer.h" |
| 19 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
| 20 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
| 22 #include "base/metrics/histogram.h" | 22 #include "base/metrics/histogram.h" |
| 23 #include "base/metrics/sparse_histogram.h" | 23 #include "base/metrics/sparse_histogram.h" |
| 24 #include "base/strings/string_split.h" | 24 #include "base/strings/string_split.h" |
| 25 #include "base/strings/string_util.h" | 25 #include "base/strings/string_util.h" |
| 26 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
| 27 #include "base/strings/utf_string_conversions.h" | 27 #include "base/strings/utf_string_conversions.h" |
| 28 #include "base/synchronization/lock.h" | 28 #include "base/synchronization/lock.h" |
| 29 #include "base/trace_event/memory_dump_manager.h" | 29 #include "base/trace_event/memory_dump_manager.h" |
| 30 #include "base/trace_event/process_memory_dump.h" | 30 #include "sql/connection_memory_dump_provider.h" |
| 31 #include "sql/meta_table.h" | 31 #include "sql/meta_table.h" |
| 32 #include "sql/statement.h" | 32 #include "sql/statement.h" |
| 33 #include "third_party/sqlite/sqlite3.h" | 33 #include "third_party/sqlite/sqlite3.h" |
| 34 | 34 |
| 35 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) | 35 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) |
| 36 #include "third_party/sqlite/src/ext/icu/sqliteicu.h" | 36 #include "third_party/sqlite/src/ext/icu/sqliteicu.h" |
| 37 #endif | 37 #endif |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 int basic_error = error & 0xff; | 247 int basic_error = error & 0xff; |
| 248 | 248 |
| 249 // These errors relate more to the runtime context of the system than to | 249 // These errors relate more to the runtime context of the system than to |
| 250 // errors with a SQL statement or with the schema, so they aren't generally | 250 // errors with a SQL statement or with the schema, so they aren't generally |
| 251 // interesting to flag. This list is not comprehensive. | 251 // interesting to flag. This list is not comprehensive. |
| 252 return basic_error == SQLITE_BUSY || | 252 return basic_error == SQLITE_BUSY || |
| 253 basic_error == SQLITE_NOTADB || | 253 basic_error == SQLITE_NOTADB || |
| 254 basic_error == SQLITE_CORRUPT; | 254 basic_error == SQLITE_CORRUPT; |
| 255 } | 255 } |
| 256 | 256 |
| 257 bool Connection::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, | |
| 258 base::trace_event::ProcessMemoryDump* pmd) { | |
| 259 if (args.level_of_detail == | |
| 260 base::trace_event::MemoryDumpLevelOfDetail::LIGHT || | |
| 261 !db_) { | |
| 262 return true; | |
| 263 } | |
| 264 | |
| 265 // The high water mark is not tracked for the following usages. | |
| 266 int cache_size, dummy_int; | |
| 267 sqlite3_db_status(db_, SQLITE_DBSTATUS_CACHE_USED, &cache_size, &dummy_int, | |
| 268 0 /* resetFlag */); | |
| 269 int schema_size; | |
| 270 sqlite3_db_status(db_, SQLITE_DBSTATUS_SCHEMA_USED, &schema_size, &dummy_int, | |
| 271 0 /* resetFlag */); | |
| 272 int statement_size; | |
| 273 sqlite3_db_status(db_, SQLITE_DBSTATUS_STMT_USED, &statement_size, &dummy_int, | |
| 274 0 /* resetFlag */); | |
| 275 | |
| 276 std::string name = base::StringPrintf( | |
| 277 "sqlite/%s_connection/%p", | |
| 278 histogram_tag_.empty() ? "Unknown" : histogram_tag_.c_str(), this); | |
| 279 base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(name); | |
| 280 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | |
| 281 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
| 282 cache_size + schema_size + statement_size); | |
| 283 dump->AddScalar("cache_size", | |
| 284 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
| 285 cache_size); | |
| 286 dump->AddScalar("schema_size", | |
| 287 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
| 288 schema_size); | |
| 289 dump->AddScalar("statement_size", | |
| 290 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | |
| 291 statement_size); | |
| 292 return true; | |
| 293 } | |
| 294 | |
| 295 void Connection::ReportDiagnosticInfo(int extended_error, Statement* stmt) { | 257 void Connection::ReportDiagnosticInfo(int extended_error, Statement* stmt) { |
| 296 AssertIOAllowed(); | 258 AssertIOAllowed(); |
| 297 | 259 |
| 298 std::string debug_info; | 260 std::string debug_info; |
| 299 const int error = (extended_error & 0xFF); | 261 const int error = (extended_error & 0xFF); |
| 300 if (error == SQLITE_CORRUPT) { | 262 if (error == SQLITE_CORRUPT) { |
| 301 debug_info = CollectCorruptionInfo(); | 263 debug_info = CollectCorruptionInfo(); |
| 302 } else { | 264 } else { |
| 303 debug_info = CollectErrorInfo(extended_error, stmt); | 265 debug_info = CollectErrorInfo(extended_error, stmt); |
| 304 } | 266 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 poisoned_(false), | 341 poisoned_(false), |
| 380 mmap_disabled_(false), | 342 mmap_disabled_(false), |
| 381 mmap_enabled_(false), | 343 mmap_enabled_(false), |
| 382 total_changes_at_last_release_(0), | 344 total_changes_at_last_release_(0), |
| 383 stats_histogram_(NULL), | 345 stats_histogram_(NULL), |
| 384 commit_time_histogram_(NULL), | 346 commit_time_histogram_(NULL), |
| 385 autocommit_time_histogram_(NULL), | 347 autocommit_time_histogram_(NULL), |
| 386 update_time_histogram_(NULL), | 348 update_time_histogram_(NULL), |
| 387 query_time_histogram_(NULL), | 349 query_time_histogram_(NULL), |
| 388 clock_(new TimeSource()) { | 350 clock_(new TimeSource()) { |
| 389 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | |
| 390 this, "sql::Connection", nullptr); | |
| 391 } | 351 } |
| 392 | 352 |
| 393 Connection::~Connection() { | 353 Connection::~Connection() { |
| 394 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | |
| 395 this); | |
| 396 Close(); | 354 Close(); |
| 397 } | 355 } |
| 398 | 356 |
| 399 void Connection::RecordEvent(Events event, size_t count) { | 357 void Connection::RecordEvent(Events event, size_t count) { |
| 400 for (size_t i = 0; i < count; ++i) { | 358 for (size_t i = 0; i < count; ++i) { |
| 401 UMA_HISTOGRAM_ENUMERATION("Sqlite.Stats", event, EVENT_MAX_VALUE); | 359 UMA_HISTOGRAM_ENUMERATION("Sqlite.Stats", event, EVENT_MAX_VALUE); |
| 402 } | 360 } |
| 403 | 361 |
| 404 if (stats_histogram_) { | 362 if (stats_histogram_) { |
| 405 for (size_t i = 0; i < count; ++i) { | 363 for (size_t i = 0; i < count; ++i) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 | 462 |
| 505 if (db_) { | 463 if (db_) { |
| 506 // Call to AssertIOAllowed() cannot go at the beginning of the function | 464 // Call to AssertIOAllowed() cannot go at the beginning of the function |
| 507 // because Close() must be called from destructor to clean | 465 // because Close() must be called from destructor to clean |
| 508 // statement_cache_, it won't cause any disk access and it most probably | 466 // statement_cache_, it won't cause any disk access and it most probably |
| 509 // will happen on thread not allowing disk access. | 467 // will happen on thread not allowing disk access. |
| 510 // TODO(paivanof@gmail.com): This should move to the beginning | 468 // TODO(paivanof@gmail.com): This should move to the beginning |
| 511 // of the function. http://crbug.com/136655. | 469 // of the function. http://crbug.com/136655. |
| 512 AssertIOAllowed(); | 470 AssertIOAllowed(); |
| 513 | 471 |
| 472 // Reseting acquires a lock to ensure no dump is happening on the database | |
| 473 // at the same time. Unregister takes ownership of provider and it is safe | |
| 474 // since the db is reset. memory_dump_provider_ could be null if db_ was | |
| 475 // poisoned. | |
| 476 if (memory_dump_provider_) { | |
| 477 memory_dump_provider_->ResetDatabase(); | |
| 478 base::trace_event::MemoryDumpManager::GetInstance() | |
| 479 ->UnregisterAndDeleteDumpProviderSoon( | |
| 480 std::move(memory_dump_provider_)); | |
| 481 } | |
|
Scott Hess - ex-Googler
2016/01/12 19:33:14
OK, reasoning this out, a dump before the reset is
Primiano Tucci (use gerrit)
2016/01/12 19:38:02
Yup, this reasoning matches perfectly ours :)
| |
| 482 | |
| 514 int rc = sqlite3_close(db_); | 483 int rc = sqlite3_close(db_); |
| 515 if (rc != SQLITE_OK) { | 484 if (rc != SQLITE_OK) { |
| 516 UMA_HISTOGRAM_SPARSE_SLOWLY("Sqlite.CloseFailure", rc); | 485 UMA_HISTOGRAM_SPARSE_SLOWLY("Sqlite.CloseFailure", rc); |
| 517 DLOG(FATAL) << "sqlite3_close failed: " << GetErrorMessage(); | 486 DLOG(FATAL) << "sqlite3_close failed: " << GetErrorMessage(); |
| 518 } | 487 } |
| 519 } | 488 } |
| 520 db_ = NULL; | 489 db_ = NULL; |
| 521 } | 490 } |
| 522 | 491 |
| 523 void Connection::Close() { | 492 void Connection::Close() { |
| (...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1841 | 1810 |
| 1842 // Determine if memory-mapping has actually been enabled. The Execute() above | 1811 // Determine if memory-mapping has actually been enabled. The Execute() above |
| 1843 // can succeed without changing the amount mapped. | 1812 // can succeed without changing the amount mapped. |
| 1844 mmap_enabled_ = false; | 1813 mmap_enabled_ = false; |
| 1845 { | 1814 { |
| 1846 Statement s(GetUniqueStatement("PRAGMA mmap_size")); | 1815 Statement s(GetUniqueStatement("PRAGMA mmap_size")); |
| 1847 if (s.Step() && s.ColumnInt64(0) > 0) | 1816 if (s.Step() && s.ColumnInt64(0) > 0) |
| 1848 mmap_enabled_ = true; | 1817 mmap_enabled_ = true; |
| 1849 } | 1818 } |
| 1850 | 1819 |
| 1820 DCHECK(!memory_dump_provider_); | |
| 1821 memory_dump_provider_.reset( | |
| 1822 new ConnectionMemoryDumpProvider(db_, histogram_tag_)); | |
| 1823 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | |
| 1824 memory_dump_provider_.get(), "sql::Connection", nullptr); | |
| 1825 | |
| 1851 return true; | 1826 return true; |
| 1852 } | 1827 } |
| 1853 | 1828 |
| 1854 void Connection::DoRollback() { | 1829 void Connection::DoRollback() { |
| 1855 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); | 1830 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); |
| 1856 | 1831 |
| 1857 // Collect the rollback time manually, sql::Statement would register it as | 1832 // Collect the rollback time manually, sql::Statement would register it as |
| 1858 // query time only. | 1833 // query time only. |
| 1859 const base::TimeTicks before = Now(); | 1834 const base::TimeTicks before = Now(); |
| 1860 rollback.RunWithoutTimers(); | 1835 rollback.RunWithoutTimers(); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1984 ignore_result(Execute(kNoWritableSchema)); | 1959 ignore_result(Execute(kNoWritableSchema)); |
| 1985 | 1960 |
| 1986 return ret; | 1961 return ret; |
| 1987 } | 1962 } |
| 1988 | 1963 |
| 1989 base::TimeTicks TimeSource::Now() { | 1964 base::TimeTicks TimeSource::Now() { |
| 1990 return base::TimeTicks::Now(); | 1965 return base::TimeTicks::Now(); |
| 1991 } | 1966 } |
| 1992 | 1967 |
| 1993 } // namespace sql | 1968 } // namespace sql |
| OLD | NEW |