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 <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/dump_without_crashing.h" | 10 #include "base/debug/dump_without_crashing.h" |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
183 | 183 |
184 // TODO(shess): NULL in file->pMethods has been observed on android_dbg | 184 // TODO(shess): NULL in file->pMethods has been observed on android_dbg |
185 // content_unittests, even though it should not be possible. | 185 // content_unittests, even though it should not be possible. |
186 // http://crbug.com/329982 | 186 // http://crbug.com/329982 |
187 if (!*file || !(*file)->pMethods) | 187 if (!*file || !(*file)->pMethods) |
188 return SQLITE_ERROR; | 188 return SQLITE_ERROR; |
189 | 189 |
190 return rc; | 190 return rc; |
191 } | 191 } |
192 | 192 |
193 // Convenience to get the sqlite3_file* and the size for the "main" database. | |
194 int GetSqlite3FileAndSize(sqlite3* db, | |
195 sqlite3_file** file, sqlite3_int64* db_size) { | |
196 int rc = GetSqlite3File(db, file); | |
197 if (rc != SQLITE_OK) | |
198 return rc; | |
199 | |
200 return (*file)->pMethods->xFileSize(*file, db_size); | |
201 } | |
202 | |
193 // This should match UMA_HISTOGRAM_MEDIUM_TIMES(). | 203 // This should match UMA_HISTOGRAM_MEDIUM_TIMES(). |
194 base::HistogramBase* GetMediumTimeHistogram(const std::string& name) { | 204 base::HistogramBase* GetMediumTimeHistogram(const std::string& name) { |
195 return base::Histogram::FactoryTimeGet( | 205 return base::Histogram::FactoryTimeGet( |
196 name, | 206 name, |
197 base::TimeDelta::FromMilliseconds(10), | 207 base::TimeDelta::FromMilliseconds(10), |
198 base::TimeDelta::FromMinutes(3), | 208 base::TimeDelta::FromMinutes(3), |
199 50, | 209 50, |
200 base::HistogramBase::kUmaTargetedHistogramFlag); | 210 base::HistogramBase::kUmaTargetedHistogramFlag); |
201 } | 211 } |
202 | 212 |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 } | 518 } |
509 | 519 |
510 // Use local settings if provided, otherwise use documented defaults. The | 520 // Use local settings if provided, otherwise use documented defaults. The |
511 // actual results could be fetching via PRAGMA calls. | 521 // actual results could be fetching via PRAGMA calls. |
512 const int page_size = page_size_ ? page_size_ : 1024; | 522 const int page_size = page_size_ ? page_size_ : 1024; |
513 sqlite3_int64 preload_size = page_size * (cache_size_ ? cache_size_ : 2000); | 523 sqlite3_int64 preload_size = page_size * (cache_size_ ? cache_size_ : 2000); |
514 if (preload_size < 1) | 524 if (preload_size < 1) |
515 return; | 525 return; |
516 | 526 |
517 sqlite3_file* file = NULL; | 527 sqlite3_file* file = NULL; |
518 int rc = GetSqlite3File(db_, &file); | 528 sqlite3_int64 file_size = 0; |
529 int rc = GetSqlite3FileAndSize(db_, &file, &file_size); | |
519 if (rc != SQLITE_OK) | 530 if (rc != SQLITE_OK) |
520 return; | 531 return; |
521 | 532 |
522 sqlite3_int64 file_size = 0; | |
523 rc = file->pMethods->xFileSize(file, &file_size); | |
524 if (rc != SQLITE_OK) | |
525 return; | |
526 | |
527 // Don't preload more than the file contains. | 533 // Don't preload more than the file contains. |
528 if (preload_size > file_size) | 534 if (preload_size > file_size) |
529 preload_size = file_size; | 535 preload_size = file_size; |
530 | 536 |
531 scoped_ptr<char[]> buf(new char[page_size]); | 537 scoped_ptr<char[]> buf(new char[page_size]); |
532 for (sqlite3_int64 pos = 0; pos < preload_size; pos += page_size) { | 538 for (sqlite3_int64 pos = 0; pos < preload_size; pos += page_size) { |
533 rc = file->pMethods->xRead(file, buf.get(), page_size, pos); | 539 rc = file->pMethods->xRead(file, buf.get(), page_size, pos); |
534 if (rc != SQLITE_OK) | 540 if (rc != SQLITE_OK) |
535 return; | 541 return; |
536 } | 542 } |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
848 // keep close to the 2000-character size limit for dumping. | 854 // keep close to the 2000-character size limit for dumping. |
849 const size_t kMaxMessages = 20; | 855 const size_t kMaxMessages = 20; |
850 for (size_t i = 0; i < kMaxMessages && i < messages.size(); ++i) { | 856 for (size_t i = 0; i < kMaxMessages && i < messages.size(); ++i) { |
851 base::StringAppendF(&debug_info, "%s\n", messages[i].c_str()); | 857 base::StringAppendF(&debug_info, "%s\n", messages[i].c_str()); |
852 } | 858 } |
853 } | 859 } |
854 | 860 |
855 return debug_info; | 861 return debug_info; |
856 } | 862 } |
857 | 863 |
864 size_t Connection::MmapHelper() { | |
865 AssertIOAllowed(); | |
866 | |
867 // TODO(shess): Using sql::MetaTable seems indicated, but mixing | |
868 // sql::MetaTable and direct access seems error-prone. It might make sense to | |
869 // simply integrate sql::MetaTable functionality into sql::Connection. | |
870 | |
871 #if defined(OS_IOS) | |
872 // iOS SQLite does not support memory mapping. | |
873 return 0; | |
874 #endif | |
875 | |
876 // If the database doesn't have a place to track progress, assume the worst. | |
877 // This will happen when new databases are created. | |
878 if (!DoesTableExist("meta")) { | |
879 RecordOneEvent(EVENT_MMAP_META_MISSING); | |
880 return 0; | |
881 } | |
882 | |
883 // Key into meta table to get status from a previous run. The value | |
884 // represents how much data in bytes has successfully been read from the | |
885 // database. |kMmapFailure| indicates that there was a read error and the | |
886 // database should not be memory-mapped, while |kMmapSuccess| indicates that | |
887 // the entire file was read at some point and can be memory-mapped without | |
888 // constraint. | |
889 const char* kMmapStatusKey = "mmap_status"; | |
890 static const sqlite3_int64 kMmapFailure = -2; | |
891 static const sqlite3_int64 kMmapSuccess = -1; | |
892 | |
893 // Start reading from 0 unless status is found in meta table. | |
894 sqlite3_int64 mmap_ofs = 0; | |
895 | |
896 // Retrieve the current status. It is fine for the status to be missing | |
897 // entirely, but any error prevents memory-mapping. | |
898 { | |
899 const char* kMmapStatusSql = "SELECT value FROM meta WHERE key = ?"; | |
900 Statement s(GetUniqueStatement(kMmapStatusSql)); | |
901 s.BindString(0, kMmapStatusKey); | |
902 if (s.Step()) { | |
903 mmap_ofs = s.ColumnInt64(0); | |
904 } else if (!s.Succeeded()) { | |
905 RecordOneEvent(EVENT_MMAP_META_FAILURE_READ); | |
906 return 0; | |
907 } | |
908 } | |
909 | |
910 // Database read failed in the past, don't memory map. | |
911 if (mmap_ofs == kMmapFailure) { | |
912 RecordOneEvent(EVENT_MMAP_FAILED); | |
913 return 0; | |
914 } else if (mmap_ofs != kMmapSuccess) { | |
915 // Continue reading from previous offset. | |
916 DCHECK_GE(mmap_ofs, 0); | |
917 | |
918 // TODO(shess): Could this reading code be shared with Preload()? It would | |
919 // require locking twice (this code wouldn't be able to access |db_size| so | |
920 // the helper would have to return amount read). | |
921 | |
922 // Read more of the database looking for errors. The VFS interface is used | |
923 // to assure that the reads are valid for SQLite. |g_reads_allowed| is used | |
924 // to limit checking to 20MB per run of Chromium. | |
925 sqlite3_file* file = NULL; | |
926 sqlite3_int64 db_size = 0; | |
927 int rc = GetSqlite3FileAndSize(db_, &file, &db_size); | |
928 if (rc != SQLITE_OK) { | |
929 RecordOneEvent(EVENT_MMAP_VFS_FAILURE); | |
930 return 0; | |
931 } | |
932 | |
933 // Read the data left, or |g_reads_allowed|, whichever is smaller. | |
934 // |g_reads_allowed| limits the total amount of I/O to spend verifying data | |
935 // in a single Chromium run. | |
936 sqlite3_int64 amount = db_size - mmap_ofs; | |
937 if (amount < 0) | |
938 amount = 0; | |
rmcilroy
2015/11/05 15:34:46
If the database got truncated between the previous
Scott Hess - ex-Googler
2015/11/05 18:25:07
Good catch!
| |
939 if (amount > 0) { | |
940 base::AutoLock lock(g_sqlite_init_lock.Get()); | |
941 static sqlite3_int64 g_reads_allowed = 20 * 1024 * 1024; | |
942 if (g_reads_allowed < amount) | |
943 amount = g_reads_allowed; | |
944 g_reads_allowed -= amount; | |
945 } | |
946 | |
947 if (amount <= 0) { | |
948 DCHECK_EQ(0, amount); | |
949 RecordOneEvent(EVENT_MMAP_SUCCESS_NO_PROGRESS); | |
950 } else { | |
951 static const int kPageSize = 4096; | |
952 char buf[kPageSize]; | |
953 while (amount > 0 && mmap_ofs >= 0) { | |
954 rc = file->pMethods->xRead(file, buf, sizeof(buf), mmap_ofs); | |
955 if (rc == SQLITE_OK) { | |
956 mmap_ofs += sizeof(buf); | |
957 amount -= sizeof(buf); | |
958 } else if (rc == SQLITE_IOERR_SHORT_READ) { | |
959 mmap_ofs = db_size; | |
960 break; | |
961 } else { | |
962 mmap_ofs = kMmapFailure; | |
963 break; | |
964 } | |
965 } | |
966 | |
967 // Log these events after update to distinguish meta update failure. | |
968 Events event; | |
969 if (mmap_ofs >= db_size) { | |
970 mmap_ofs = kMmapSuccess; | |
971 event = EVENT_MMAP_SUCCESS_NEW; | |
972 } else if (mmap_ofs > 0) { | |
973 event = EVENT_MMAP_SUCCESS_PARTIAL; | |
974 } else { | |
975 DCHECK_EQ(kMmapFailure, mmap_ofs); | |
976 event = EVENT_MMAP_FAILED_NEW; | |
977 } | |
978 | |
979 const char* kMmapUpdateStatusSql = "REPLACE INTO meta VALUES (?, ?)"; | |
980 Statement s(GetUniqueStatement(kMmapUpdateStatusSql)); | |
981 s.BindString(0, kMmapStatusKey); | |
982 s.BindInt64(1, mmap_ofs); | |
983 if (!s.Run()) { | |
984 RecordOneEvent(EVENT_MMAP_META_FAILURE_UPDATE); | |
985 return 0; | |
986 } | |
987 | |
988 RecordOneEvent(event); | |
989 } | |
990 } | |
991 | |
992 if (mmap_ofs == kMmapFailure) | |
993 return 0; | |
994 if (mmap_ofs == kMmapSuccess) | |
995 return 256 * 1024 * 1024; | |
996 return mmap_ofs; | |
997 } | |
998 | |
858 void Connection::TrimMemory(bool aggressively) { | 999 void Connection::TrimMemory(bool aggressively) { |
859 if (!db_) | 1000 if (!db_) |
860 return; | 1001 return; |
861 | 1002 |
862 // TODO(shess): investigate using sqlite3_db_release_memory() when possible. | 1003 // TODO(shess): investigate using sqlite3_db_release_memory() when possible. |
863 int original_cache_size; | 1004 int original_cache_size; |
864 { | 1005 { |
865 Statement sql_get_original(GetUniqueStatement("PRAGMA cache_size")); | 1006 Statement sql_get_original(GetUniqueStatement("PRAGMA cache_size")); |
866 if (!sql_get_original.Step()) { | 1007 if (!sql_get_original.Step()) { |
867 DLOG(WARNING) << "Could not get cache size " << GetErrorMessage(); | 1008 DLOG(WARNING) << "Could not get cache size " << GetErrorMessage(); |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1621 | 1762 |
1622 // http://www.sqlite.org/pragma.html#pragma_journal_mode | 1763 // http://www.sqlite.org/pragma.html#pragma_journal_mode |
1623 // DELETE (default) - delete -journal file to commit. | 1764 // DELETE (default) - delete -journal file to commit. |
1624 // TRUNCATE - truncate -journal file to commit. | 1765 // TRUNCATE - truncate -journal file to commit. |
1625 // PERSIST - zero out header of -journal file to commit. | 1766 // PERSIST - zero out header of -journal file to commit. |
1626 // TRUNCATE should be faster than DELETE because it won't need directory | 1767 // TRUNCATE should be faster than DELETE because it won't need directory |
1627 // changes for each transaction. PERSIST may break the spirit of using | 1768 // changes for each transaction. PERSIST may break the spirit of using |
1628 // secure_delete. | 1769 // secure_delete. |
1629 ignore_result(Execute("PRAGMA journal_mode = TRUNCATE")); | 1770 ignore_result(Execute("PRAGMA journal_mode = TRUNCATE")); |
1630 | 1771 |
1631 // Enable memory-mapped access. This value will be capped by | |
1632 // SQLITE_MAX_MMAP_SIZE, which could be different between 32-bit and 64-bit | |
1633 // platforms. | |
1634 mmap_enabled_ = false; | |
1635 if (!mmap_disabled_) | |
1636 ignore_result(Execute("PRAGMA mmap_size = 268435456")); // 256MB. | |
1637 { | |
1638 Statement s(GetUniqueStatement("PRAGMA mmap_size")); | |
1639 if (s.Step() && s.ColumnInt64(0) > 0) | |
1640 mmap_enabled_ = true; | |
1641 } | |
1642 | |
1643 const base::TimeDelta kBusyTimeout = | 1772 const base::TimeDelta kBusyTimeout = |
1644 base::TimeDelta::FromSeconds(kBusyTimeoutSeconds); | 1773 base::TimeDelta::FromSeconds(kBusyTimeoutSeconds); |
1645 | 1774 |
1646 if (page_size_ != 0) { | 1775 if (page_size_ != 0) { |
1647 // Enforce SQLite restrictions on |page_size_|. | 1776 // Enforce SQLite restrictions on |page_size_|. |
1648 DCHECK(!(page_size_ & (page_size_ - 1))) | 1777 DCHECK(!(page_size_ & (page_size_ - 1))) |
1649 << " page_size_ " << page_size_ << " is not a power of two."; | 1778 << " page_size_ " << page_size_ << " is not a power of two."; |
1650 const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h | 1779 const int kSqliteMaxPageSize = 32768; // from sqliteLimit.h |
1651 DCHECK_LE(page_size_, kSqliteMaxPageSize); | 1780 DCHECK_LE(page_size_, kSqliteMaxPageSize); |
1652 const std::string sql = | 1781 const std::string sql = |
1653 base::StringPrintf("PRAGMA page_size=%d", page_size_); | 1782 base::StringPrintf("PRAGMA page_size=%d", page_size_); |
1654 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout)); | 1783 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout)); |
1655 } | 1784 } |
1656 | 1785 |
1657 if (cache_size_ != 0) { | 1786 if (cache_size_ != 0) { |
1658 const std::string sql = | 1787 const std::string sql = |
1659 base::StringPrintf("PRAGMA cache_size=%d", cache_size_); | 1788 base::StringPrintf("PRAGMA cache_size=%d", cache_size_); |
1660 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout)); | 1789 ignore_result(ExecuteWithTimeout(sql.c_str(), kBusyTimeout)); |
1661 } | 1790 } |
1662 | 1791 |
1663 if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) { | 1792 if (!ExecuteWithTimeout("PRAGMA secure_delete=ON", kBusyTimeout)) { |
1664 bool was_poisoned = poisoned_; | 1793 bool was_poisoned = poisoned_; |
1665 Close(); | 1794 Close(); |
1666 if (was_poisoned && retry_flag == RETRY_ON_POISON) | 1795 if (was_poisoned && retry_flag == RETRY_ON_POISON) |
1667 return OpenInternal(file_name, NO_RETRY); | 1796 return OpenInternal(file_name, NO_RETRY); |
1668 return false; | 1797 return false; |
1669 } | 1798 } |
1670 | 1799 |
1800 // Enable memory-mapped access. The explicit-disable case is because SQLite | |
1801 // can be built to default-enable mmap. MmapHelper() calculates a safe range | |
1802 // to memory-map based on past regular I/O. This value will be capped by | |
1803 // SQLITE_MAX_MMAP_SIZE, which could be different between 32-bit and 64-bit | |
1804 // platforms. | |
1805 size_t mmap_size = mmap_disabled_ ? 0 : MmapHelper(); | |
1806 std::string mmap_sql = | |
1807 base::StringPrintf("PRAGMA mmap_size = %" PRIuS, mmap_size); | |
1808 ignore_result(Execute(mmap_sql.c_str())); | |
1809 | |
1810 // Determine if memory-mapping has actually been enabled. The Execute() above | |
1811 // can succeed without changing the amount mapped. | |
1812 mmap_enabled_ = false; | |
1813 { | |
1814 Statement s(GetUniqueStatement("PRAGMA mmap_size")); | |
1815 if (s.Step() && s.ColumnInt64(0) > 0) | |
1816 mmap_enabled_ = true; | |
1817 } | |
1818 | |
1671 return true; | 1819 return true; |
1672 } | 1820 } |
1673 | 1821 |
1674 void Connection::DoRollback() { | 1822 void Connection::DoRollback() { |
1675 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); | 1823 Statement rollback(GetCachedStatement(SQL_FROM_HERE, "ROLLBACK")); |
1676 | 1824 |
1677 // Collect the rollback time manually, sql::Statement would register it as | 1825 // Collect the rollback time manually, sql::Statement would register it as |
1678 // query time only. | 1826 // query time only. |
1679 const base::TimeTicks before = Now(); | 1827 const base::TimeTicks before = Now(); |
1680 rollback.RunWithoutTimers(); | 1828 rollback.RunWithoutTimers(); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1800 ignore_result(Execute(kNoWritableSchema)); | 1948 ignore_result(Execute(kNoWritableSchema)); |
1801 | 1949 |
1802 return ret; | 1950 return ret; |
1803 } | 1951 } |
1804 | 1952 |
1805 base::TimeTicks TimeSource::Now() { | 1953 base::TimeTicks TimeSource::Now() { |
1806 return base::TimeTicks::Now(); | 1954 return base::TimeTicks::Now(); |
1807 } | 1955 } |
1808 | 1956 |
1809 } // namespace sql | 1957 } // namespace sql |
OLD | NEW |