Skip to content

Adjust sqlite size calculation to account for WAL #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 6, 2019
Merged

Conversation

rsgowman
Copy link
Member

@rsgowman rsgowman commented Feb 4, 2019

SQLite supports two methods of commiting; a rollback journal and a
write-ahead-log (WAL). By default, a rollback journal is used. However,
on Android 9 (P), the default changed slightly to a WAL-compatible mode:
https://source.android.com/devices/tech/perf/compatibility-wal. This
mode causes a WAL to be written to disk.

Our prior method of calculating the database size did not take the WAL
into account. In practice, this isn't too awful, as the contents of the
WAL would eventually be written back into the main database file, but in
the meantime, our calculation could be off by upwards of a few MB. This
commit changes the size calulation to ask sqlite rather than looking at
the size of the file on disk.

SQLite supports two methods of commiting; a rollback journal and a
write-ahead-log (WAL). By default, a rollback journal is used. However,
on Android 9 (P), the default changed slightly to a WAL-compatible mode:
https://source.android.com/devices/tech/perf/compatibility-wal. This
mode causes a WAL to be written to disk.

Our prior method of calculating the database size did not take the WAL
into account. In practice, this isn't too awful, as the contents of the
WAL would eventually be written back into the main database file, but in
the meantime, our calculation could be off by upwards of a few MB. This
commit changes the size calulation to ask sqlite rather than looking at
the size of the file on disk.
@rsgowman rsgowman self-assigned this Feb 4, 2019
@googlebot googlebot added the cla: yes Override cla label Feb 4, 2019
@rsgowman rsgowman requested a review from mikelehen February 4, 2019 19:20
@rsgowman rsgowman assigned mikelehen and unassigned rsgowman Feb 4, 2019
@rsgowman
Copy link
Member Author

rsgowman commented Feb 4, 2019

cc @ashwinraghav

Copy link
Contributor

@mikelehen mikelehen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@@ -83,6 +83,7 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
testOptions.unitTests.includeAndroidResources = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically tangential to your PR, right? Please confirm you're including it intentionally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please confirm that including this flag now does not generate a warning.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically tangential to your PR, right? Please confirm you're including it intentionally.

Mostly tangential, though it causes the issue to manifest itself. (Also required by Ashwin's changes.)

Also, please confirm that including this flag now does not generate a warning.

This does not seem to introduce any new warnings.

Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM at a high level though I have some lower-level concerns.

@@ -1,4 +1,7 @@
# Unreleased
- [fixed] Fixed calculation of SQLite database size on Android 9 (P) devices.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Android 9 (P)" is a nonstandard way of referring to this. Android documentation calls this "Android 9 Pie". We should follow since the changelog gets rolled up into our public release notes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -83,6 +83,7 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
testOptions.unitTests.includeAndroidResources = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, please confirm that including this flag now does not generate a warning.

* @see https://www.sqlite.org/pragma.html
*/
private long pragma(String pragmaName) {
Cursor cursor = db.rawQuery("PRAGMA " + pragmaName, null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a matter of principle we should avoid composing SQL through string concatenation. This construct is subject to SQL injection attacks if we're not careful. Better to just have the caller pass the whole query string.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, it's not possible to use a prepared statement here. We could instead allow the caller to pass the entire sql statement, but that's probably worse. Instead, we decided to un-refactor this. (Done).

* @param pragmaName Must be a valid 'pragma-name' and must refer to a long value.
* @see https://www.sqlite.org/pragma.html
*/
private long pragma(String pragmaName) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all pragmas resolve to a single long value. Maybe name this simpleQueryForLong?

I suggest that name because for queries that resolve to a single 1x1 result, SQLite supports running them with SQLiteStatement.simpleQueryForLong in a way that avoids allocating a cursor.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer relevant.

@rsgowman rsgowman assigned wilhuff and unassigned mikelehen Feb 4, 2019
Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

* @see https://www.sqlite.org/pragma.html#pragma_page_size
*/
private long getPageSize() {
Cursor cursor = db.rawQuery("PRAGMA page_size", null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could cut down on the verbosity here by writing this as:

return query("PRAGMA page_size").firstValue(row -> row.getLong(0));

@google-oss-bot
Copy link
Contributor

@rsgowman: The following test failed, say /retest to rerun them all:

Test name Commit Details Rerun command
smoke-tests-release 111ab9a link /test smoke-tests-release

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@rsgowman rsgowman merged commit 859b7fc into master Feb 6, 2019
@rsgowman rsgowman deleted the rsgowman/wal branch February 6, 2019 18:29
@firebase firebase locked and limited conversation to collaborators Oct 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes Override cla size/S
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants