Remove old thread remappings.

This commit is contained in:
Greyson Parrelli
2024-04-17 15:04:22 -04:00
parent ce1b73970c
commit 9762899272
4 changed files with 58 additions and 26 deletions

View File

@@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.database.MessageTable;
import org.thoughtcrime.securesms.database.OneTimePreKeyTable;
import org.thoughtcrime.securesms.database.PendingRetryReceiptTable;
import org.thoughtcrime.securesms.database.ReactionTable;
import org.thoughtcrime.securesms.database.RemappedRecordTables;
import org.thoughtcrime.securesms.database.SearchTable;
import org.thoughtcrime.securesms.database.SenderKeyTable;
import org.thoughtcrime.securesms.database.SenderKeySharedTable;
@@ -92,7 +93,9 @@ public class FullBackupExporter extends FullBackupBase {
SenderKeyTable.TABLE_NAME,
SenderKeySharedTable.TABLE_NAME,
PendingRetryReceiptTable.TABLE_NAME,
AvatarPickerDatabase.TABLE_NAME
AvatarPickerDatabase.TABLE_NAME,
RemappedRecordTables.Recipients.TABLE_NAME,
RemappedRecordTables.Threads.TABLE_NAME
);
public static BackupEvent export(@NonNull Context context,

View File

@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.database
import android.content.Context
import android.database.Cursor
import androidx.core.content.contentValuesOf
import org.signal.core.util.delete
import org.signal.core.util.logging.Log
import org.signal.core.util.readToList
import org.signal.core.util.requireLong
@@ -30,7 +31,7 @@ class RemappedRecordTables internal constructor(context: Context?, databaseHelpe
const val NEW_ID = "new_id"
}
private object Recipients {
object Recipients {
const val TABLE_NAME = "remapped_recipients"
const val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME (
@@ -41,7 +42,7 @@ class RemappedRecordTables internal constructor(context: Context?, databaseHelpe
"""
}
private object Threads {
object Threads {
const val TABLE_NAME = "remapped_threads"
const val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME (
@@ -56,6 +57,9 @@ class RemappedRecordTables internal constructor(context: Context?, databaseHelpe
val recipientMap: MutableMap<RecipientId, RecipientId> = HashMap()
readableDatabase.withinTransaction { db ->
trimInvalidRecipientEntries(db)
trimInvalidThreadEntries(db)
val mappings = getAllMappings(db, Recipients.TABLE_NAME)
for (mapping in mappings) {
val oldId = RecipientId.from(mapping.oldId)
@@ -102,6 +106,32 @@ class RemappedRecordTables internal constructor(context: Context?, databaseHelpe
.run()
}
fun deleteThreadMapping(oldId: Long) {
writableDatabase.delete(Threads.TABLE_NAME)
.where("$OLD_ID = ?", oldId)
.run()
}
private fun trimInvalidRecipientEntries(db: SQLiteDatabase) {
val count = db.delete(Recipients.TABLE_NAME)
.where("$OLD_ID IN (SELECT $ID FROM ${RecipientTable.TABLE_NAME})")
.run()
if (count > 0) {
Log.w(TAG, "Trimmed $count invalid recipient entries.", true)
}
}
private fun trimInvalidThreadEntries(db: SQLiteDatabase) {
val count = db.delete(Threads.TABLE_NAME)
.where("$OLD_ID IN (SELECT $ID FROM ${ThreadTable.TABLE_NAME})")
.run()
if (count > 0) {
Log.w(TAG, "Trimmed $count invalid thread entries.", true)
}
}
private fun getAllMappings(db: SQLiteDatabase, table: String): List<Mapping> {
return db.select()
.from(table)

View File

@@ -49,27 +49,18 @@ class RemappedRecords {
return Optional.ofNullable(threadMap.get(oldId));
}
void deleteThread(long oldId) {
ensureInTransaction();
ensureThreadMapIsPopulated();
threadMap.remove(oldId);
SignalDatabase.remappedRecords().deleteThreadMapping(oldId);
}
boolean areAnyRemapped(@NonNull Collection<RecipientId> recipientIds) {
ensureRecipientMapIsPopulated();
return recipientIds.stream().anyMatch(id -> recipientMap.containsKey(id));
}
@NonNull Set<RecipientId> remap(@NonNull Collection<RecipientId> recipientIds) {
ensureRecipientMapIsPopulated();
Set<RecipientId> remapped = new LinkedHashSet<>();
for (RecipientId original : recipientIds) {
if (recipientMap.containsKey(original)) {
remapped.add(recipientMap.get(original));
} else {
remapped.add(original);
}
}
return remapped;
}
@NonNull String buildRemapDescription(@NonNull Collection<RecipientId> recipientIds) {
StringBuilder builder = new StringBuilder();

View File

@@ -1141,15 +1141,23 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
fun getOrCreateValidThreadId(recipient: Recipient, candidateId: Long, distributionType: Int): Long {
return if (candidateId != -1L) {
val remapped = RemappedRecords.getInstance().getThread(candidateId)
if (remapped.isPresent) {
Log.i(TAG, "Using remapped threadId: " + candidateId + " -> " + remapped.get())
remapped.get()
if (areThreadIdAndRecipientAssociated(candidateId, recipient)) {
candidateId
} else {
if (areThreadIdAndRecipientAssociated(candidateId, recipient)) {
candidateId
val remapped = RemappedRecords.getInstance().getThread(candidateId)
if (remapped.isPresent) {
if (areThreadIdAndRecipientAssociated(remapped.get(), recipient)) {
Log.i(TAG, "Using remapped threadId: $candidateId -> ${remapped.get()}")
remapped.get()
} else {
Log.i(TAG, "There's a remap for $candidateId -> ${remapped.get()}, but it's not associated with $recipient. Deleting old remap and throwing.")
writableDatabase.withinTransaction {
RemappedRecords.getInstance().deleteThread(candidateId)
}
throw IllegalArgumentException("Candidate threadId ($candidateId) is not associated with recipient ($recipient)")
}
} else {
throw IllegalArgumentException()
throw IllegalArgumentException("Candidate threadId ($candidateId) is not associated with recipient ($recipient)")
}
}
} else {