Skip to content

Commit 9c277a1

Browse files
committed
Adjust sqlite size calculation to account for WAL
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.
1 parent 6d7b42c commit 9c277a1

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

firebase-firestore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Unreleased
2+
- [fixed] Fixed calculation of SQLite database size on Android 9 (P) devices.
3+
Previous method could be off by a few MBs on these devices, potentially
4+
delaying garbage collection.
25

36
# 18.0.1
47
- [fixed] Fixed an issue where Firestore would crash if handling write batches

firebase-firestore/firebase-firestore.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ android {
8383
sourceCompatibility JavaVersion.VERSION_1_8
8484
targetCompatibility JavaVersion.VERSION_1_8
8585
}
86+
testOptions.unitTests.includeAndroidResources = true
8687
}
8788

8889
dependencies {

firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLitePersistence.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import com.google.firebase.firestore.util.Consumer;
3535
import com.google.firebase.firestore.util.Logger;
3636
import com.google.firebase.firestore.util.Supplier;
37-
import java.io.File;
3837
import java.io.UnsupportedEncodingException;
3938
import java.net.URLEncoder;
4039
import java.util.ArrayList;
@@ -77,7 +76,6 @@ public static String databaseName(String persistenceKey, DatabaseId databaseId)
7776
private final OpenHelper opener;
7877
private final LocalSerializer serializer;
7978
private SQLiteDatabase db;
80-
private File databasePath;
8179
private boolean started;
8280
private final SQLiteQueryCache queryCache;
8381
private final SQLiteRemoteDocumentCache remoteDocumentCache;
@@ -106,7 +104,6 @@ public SQLitePersistence(
106104
LruGarbageCollector.Params params) {
107105
String databaseName = databaseName(persistenceKey, databaseId);
108106
this.opener = new OpenHelper(context, databaseName);
109-
this.databasePath = context.getDatabasePath(databaseName);
110107
this.serializer = serializer;
111108
this.queryCache = new SQLiteQueryCache(this, this.serializer);
112109
this.remoteDocumentCache = new SQLiteRemoteDocumentCache(this, this.serializer);
@@ -199,7 +196,40 @@ <T> T runTransaction(String action, Supplier<T> operation) {
199196
}
200197

201198
long getByteSize() {
202-
return databasePath.length();
199+
return getPageCount() * getPageSize();
200+
}
201+
202+
/**
203+
* Gets the page size of the database. Typically 4096.
204+
*
205+
* @see https://www.sqlite.org/pragma.html#pragma_page_size
206+
*/
207+
private long getPageSize() {
208+
return pragma("page_size");
209+
}
210+
211+
/**
212+
* Gets the number of pages in the database file. Multiplying this with the page size yields the
213+
* approximate size of the database on disk (including the WAL, if relevant).
214+
*
215+
* @see https://www.sqlite.org/pragma.html#pragma_page_count.
216+
*/
217+
private long getPageCount() {
218+
return pragma("page_count");
219+
}
220+
221+
/**
222+
* @param pragmaName Must be a valid 'pragma-name' and must refer to a long value.
223+
* @see https://www.sqlite.org/pragma.html
224+
*/
225+
private long pragma(String pragmaName) {
226+
Cursor cursor = db.rawQuery("PRAGMA " + pragmaName, null);
227+
try {
228+
cursor.moveToFirst();
229+
return cursor.getLong(/*column=*/ 0);
230+
} finally {
231+
cursor.close();
232+
}
203233
}
204234

205235
/**

0 commit comments

Comments
 (0)