mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-26 20:55:10 +00:00
Ensure various log database indexes are used.
This commit is contained in:
@@ -17,6 +17,7 @@ import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.mebiBytes
|
||||
import org.signal.core.util.readToList
|
||||
import org.signal.core.util.readToSingleInt
|
||||
import org.signal.core.util.readToSingleLong
|
||||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.select
|
||||
@@ -147,9 +148,12 @@ class LogDatabase private constructor(
|
||||
)
|
||||
"""
|
||||
|
||||
private const val KEEP_LONGER_INDEX = "keep_longer_index"
|
||||
private const val CREATED_AT_KEEP_LONGER_INDEX = "log_created_at_keep_longer_index"
|
||||
|
||||
val CREATE_INDEXES = arrayOf(
|
||||
"CREATE INDEX keep_longer_index ON $TABLE_NAME ($KEEP_LONGER)",
|
||||
"CREATE INDEX log_created_at_keep_longer_index ON $TABLE_NAME ($CREATED_AT, $KEEP_LONGER)"
|
||||
"CREATE INDEX $KEEP_LONGER_INDEX ON $TABLE_NAME ($KEEP_LONGER)",
|
||||
"CREATE INDEX $CREATED_AT_KEEP_LONGER_INDEX ON $TABLE_NAME ($CREATED_AT, $KEEP_LONGER)"
|
||||
)
|
||||
|
||||
val MAX_FILE_SIZE = 20L.mebiBytes.inWholeBytes
|
||||
@@ -173,8 +177,8 @@ class LogDatabase private constructor(
|
||||
.run()
|
||||
}
|
||||
|
||||
db.delete(TABLE_NAME)
|
||||
.where("($CREATED_AT < ? AND $KEEP_LONGER <= 0) OR ($CREATED_AT < ? AND $KEEP_LONGER => 1)", currentTime - DEFAULT_LIFESPAN, currentTime - LONGER_LIFESPAN)
|
||||
db.delete("$TABLE_NAME INDEXED BY $CREATED_AT_KEEP_LONGER_INDEX")
|
||||
.where("($CREATED_AT < ${currentTime - DEFAULT_LIFESPAN} AND $KEEP_LONGER <= 0) OR ($CREATED_AT < ${currentTime - LONGER_LIFESPAN} AND $KEEP_LONGER >= 1)")
|
||||
.run()
|
||||
}
|
||||
}
|
||||
@@ -182,7 +186,7 @@ class LogDatabase private constructor(
|
||||
fun getAllBeforeTime(time: Long): Reader {
|
||||
return readableDatabase
|
||||
.select(BODY)
|
||||
.from(TABLE_NAME)
|
||||
.from("$TABLE_NAME INDEXED BY $CREATED_AT_KEEP_LONGER_INDEX")
|
||||
.where("$CREATED_AT < $time")
|
||||
.run()
|
||||
.toReader()
|
||||
@@ -191,7 +195,7 @@ class LogDatabase private constructor(
|
||||
fun getRangeBeforeTime(start: Int, length: Int, time: Long): List<String> {
|
||||
return readableDatabase
|
||||
.select(BODY)
|
||||
.from(TABLE_NAME)
|
||||
.from("$TABLE_NAME INDEXED BY $CREATED_AT_KEEP_LONGER_INDEX")
|
||||
.where("$CREATED_AT < $time")
|
||||
.limit(limit = length, offset = start)
|
||||
.run()
|
||||
@@ -202,20 +206,22 @@ class LogDatabase private constructor(
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val stopwatch = Stopwatch("trim")
|
||||
|
||||
val sizeOfSpecialLogs: Long = getSize("$KEEP_LONGER = ?", arrayOf("1"))
|
||||
val remainingSize = MAX_FILE_SIZE - sizeOfSpecialLogs
|
||||
val sizeOfKeepLongerLogs: Long = getSize("$KEEP_LONGER = ?", arrayOf("1"), KEEP_LONGER_INDEX)
|
||||
val remainingSizeAfterKeepLonger = MAX_FILE_SIZE - sizeOfKeepLongerLogs
|
||||
|
||||
stopwatch.split("keepers-size")
|
||||
|
||||
if (remainingSize <= 0) {
|
||||
if (abs(remainingSize) > MAX_FILE_SIZE / 2) {
|
||||
// If we can't even fit our keep_longer logs within the size limit
|
||||
if (remainingSizeAfterKeepLonger <= 0) {
|
||||
if (abs(remainingSizeAfterKeepLonger) > MAX_FILE_SIZE / 2) {
|
||||
// Not only are KEEP_LONGER logs putting us over the storage limit, it's doing it by a lot! Delete half.
|
||||
val logCount = readableDatabase.getTableRowCount(TABLE_NAME)
|
||||
writableDatabase.execSQL("DELETE FROM $TABLE_NAME WHERE $ID < (SELECT MAX($ID) FROM (SELECT $ID FROM $TABLE_NAME LIMIT ${logCount / 2}))")
|
||||
} else {
|
||||
writableDatabase
|
||||
.delete(TABLE_NAME)
|
||||
.delete("$TABLE_NAME INDEXED BY $KEEP_LONGER_INDEX")
|
||||
.where("$KEEP_LONGER = 0")
|
||||
.run()
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -229,12 +235,12 @@ class LogDatabase private constructor(
|
||||
|
||||
while (lhs < rhs - 2) {
|
||||
mid = (lhs + rhs) / 2
|
||||
sizeOfChunk = getSize("$CREATED_AT > ? AND $CREATED_AT < ? AND $KEEP_LONGER = ?", SqlUtil.buildArgs(mid, currentTime, 0))
|
||||
sizeOfChunk = getSize("$CREATED_AT > ? AND $CREATED_AT < ? AND $KEEP_LONGER <= ?", SqlUtil.buildArgs(mid, currentTime, 0), CREATED_AT_KEEP_LONGER_INDEX)
|
||||
|
||||
if (sizeOfChunk > remainingSize) {
|
||||
if (sizeOfChunk > remainingSizeAfterKeepLonger) {
|
||||
lhs = mid
|
||||
} else if (sizeOfChunk < remainingSize) {
|
||||
if (remainingSize - sizeOfChunk < sizeDiffThreshold) {
|
||||
} else if (sizeOfChunk < remainingSizeAfterKeepLonger) {
|
||||
if (remainingSizeAfterKeepLonger - sizeOfChunk < sizeDiffThreshold) {
|
||||
break
|
||||
} else {
|
||||
rhs = mid
|
||||
@@ -246,7 +252,10 @@ class LogDatabase private constructor(
|
||||
|
||||
stopwatch.split("binary-search")
|
||||
|
||||
writableDatabase.delete(TABLE_NAME, "$CREATED_AT < ? AND $KEEP_LONGER = ?", SqlUtil.buildArgs(mid, 0))
|
||||
writableDatabase
|
||||
.delete("$TABLE_NAME INDEXED BY $CREATED_AT_KEEP_LONGER_INDEX")
|
||||
.where("$CREATED_AT < $mid AND $KEEP_LONGER <= 0")
|
||||
.run()
|
||||
|
||||
stopwatch.split("delete")
|
||||
stopwatch.stop(TAG)
|
||||
@@ -255,7 +264,7 @@ class LogDatabase private constructor(
|
||||
fun getLogCountBeforeTime(time: Long): Int {
|
||||
return readableDatabase
|
||||
.select("COUNT(*)")
|
||||
.from(TABLE_NAME)
|
||||
.from("$TABLE_NAME INDEXED BY $CREATED_AT_KEEP_LONGER_INDEX")
|
||||
.where("$CREATED_AT < $time")
|
||||
.run()
|
||||
.readToSingleInt()
|
||||
@@ -263,7 +272,7 @@ class LogDatabase private constructor(
|
||||
|
||||
fun clearKeepLonger() {
|
||||
writableDatabase
|
||||
.delete(TABLE_NAME)
|
||||
.delete("$TABLE_NAME INDEXED BY $KEEP_LONGER_INDEX")
|
||||
.where("$KEEP_LONGER = 1")
|
||||
.run()
|
||||
}
|
||||
@@ -272,14 +281,13 @@ class LogDatabase private constructor(
|
||||
writableDatabase.deleteAll(TABLE_NAME)
|
||||
}
|
||||
|
||||
private fun getSize(query: String?, args: Array<String>?): Long {
|
||||
readableDatabase.query(TABLE_NAME, arrayOf("SUM($SIZE)"), query, args, null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
cursor.getLong(0)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
private fun getSize(query: String, args: Array<String>, index: String): Long {
|
||||
return readableDatabase
|
||||
.select("SUM($SIZE)")
|
||||
.from("$TABLE_NAME INDEXED BY $index")
|
||||
.where(query, args)
|
||||
.run()
|
||||
.readToSingleLong(0)
|
||||
}
|
||||
|
||||
private fun Cursor.toReader(): CursorReader {
|
||||
|
||||
Reference in New Issue
Block a user