diff options
author | shess <shess@chromium.org> | 2015-12-17 17:18:08 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-18 01:19:51 +0000 |
commit | 9bf2c6745727731429baa207db994de5278505a0 (patch) | |
tree | 8c9bae35ab2d6ec26690816f175a064ecfb6633a /sql/connection_unittest.cc | |
parent | dfbb949421a0f2634ae49d5343d270d7e147203b (diff) | |
download | chromium_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.cc | 87 |
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 |