summaryrefslogtreecommitdiffstats
path: root/sql/connection_unittest.cc
diff options
context:
space:
mode:
authorshess <shess@chromium.org>2015-12-17 17:18:08 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-18 01:19:51 +0000
commit9bf2c6745727731429baa207db994de5278505a0 (patch)
tree8c9bae35ab2d6ec26690816f175a064ecfb6633a /sql/connection_unittest.cc
parentdfbb949421a0f2634ae49d5343d270d7e147203b (diff)
downloadchromium_src-9bf2c6745727731429baa207db994de5278505a0.zip
chromium_src-9bf2c6745727731429baa207db994de5278505a0.tar.gz
chromium_src-9bf2c6745727731429baa207db994de5278505a0.tar.bz2
[sql] Consider fresh databases suitable for memory-mapped I/O.
GetAppropriateMmapSize() is called to validate the database as error-free before enabling memory-mapped mode. The validation status is stored in the [meta] table, since new databases have no [meta] table it previously defaulted to not turning on memory-mapping. Then on second open the file would be validated. This change uses the lack of [meta] table as a signal that the file is new and should be safe to memory-map. Additionally the code creating [meta] pre-populates that setting. Additionally disable memory-mapped mode for databases which do not make use of the [meta] table. This makes the existing settings explicit. BUG=537742, 555578 TBR=rdevlin.cronin@chromium.org, michaeln@chromium.org, zea@chromium.org, sky@chromium.org Review URL: https://codereview.chromium.org/1533703002 Cr-Commit-Position: refs/heads/master@{#365959}
Diffstat (limited to 'sql/connection_unittest.cc')
-rw-r--r--sql/connection_unittest.cc87
1 files changed, 87 insertions, 0 deletions
diff --git a/sql/connection_unittest.cc b/sql/connection_unittest.cc
index b1946e4..219da7f 100644
--- a/sql/connection_unittest.cc
+++ b/sql/connection_unittest.cc
@@ -1381,4 +1381,91 @@ TEST_F(SQLConnectionTest, RegisterIntentToUpload) {
}
#endif // !defined(MOJO_APPTEST_IMPL)
+// Test that a fresh database has mmap enabled by default, if mmap'ed I/O is
+// enabled by SQLite.
+TEST_F(SQLConnectionTest, MmapInitiallyEnabled) {
+ {
+ sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
+
+ // SQLite doesn't have mmap support (perhaps an early iOS release).
+ if (!s.Step())
+ return;
+
+ // If mmap I/O is not on, attempt to turn it on. If that succeeds, then
+ // Open() should have turned it on. If mmap support is disabled, 0 is
+ // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for
+ // instance MojoVFS), -1 is returned.
+ if (s.ColumnInt(0) <= 0) {
+ ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576"));
+ s.Reset(true);
+ ASSERT_TRUE(s.Step());
+ EXPECT_LE(s.ColumnInt(0), 0);
+ }
+ }
+
+ // Test that explicit disable prevents mmap'ed I/O.
+ db().Close();
+ sql::Connection::Delete(db_path());
+ db().set_mmap_disabled();
+ ASSERT_TRUE(db().Open(db_path()));
+ {
+ sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
+ ASSERT_TRUE(s.Step());
+ EXPECT_LE(s.ColumnInt(0), 0);
+ }
+}
+
+// Test specific operation of the GetAppropriateMmapSize() helper.
+#if defined(OS_IOS)
+TEST_F(SQLConnectionTest, GetAppropriateMmapSize) {
+ ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
+}
+#else
+TEST_F(SQLConnectionTest, GetAppropriateMmapSize) {
+ const size_t kMmapAlot = 25 * 1024 * 1024;
+
+ // If there is no meta table (as for a fresh database), assume that everything
+ // should be mapped.
+ ASSERT_TRUE(!db().DoesTableExist("meta"));
+ ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
+
+ // Getting the status fails if there is an error. GetAppropriateMmapSize()
+ // should not call GetMmapStatus() if the table does not exist, but this is an
+ // easy error to setup for testing.
+ int64_t mmap_status;
+ {
+ sql::ScopedErrorIgnorer ignore_errors;
+ ignore_errors.IgnoreError(SQLITE_ERROR);
+ ASSERT_FALSE(MetaTable::GetMmapStatus(&db(), &mmap_status));
+ ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
+ }
+
+ // When the meta table is first created, it sets up to map everything.
+ MetaTable().Init(&db(), 1, 1);
+ ASSERT_TRUE(db().DoesTableExist("meta"));
+ ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
+ ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
+ ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
+
+ // Failure status maps nothing.
+ ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', -2)"));
+ ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
+
+ // Re-initializing the meta table does not re-create the key if the table
+ // already exists.
+ ASSERT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'mmap_status'"));
+ MetaTable().Init(&db(), 1, 1);
+ ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
+ ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
+ ASSERT_EQ(0, mmap_status);
+
+ // With no key, map everything and create the key.
+ // TODO(shess): This really should be "maps everything after validating it",
+ // but that is more complicated to structure.
+ ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
+ ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
+ ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
+}
+#endif
+
} // namespace sql