diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt index f8dc906502..4cf46cbbc0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/Session.kt @@ -238,4 +238,9 @@ interface Session : } val sharedSecretStorageService: SharedSecretStorageService + + /** + * Maintenance API, allows to print outs info on DB size to logcat + */ + fun dbgTraceDbInfo() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index 34be1b8d05..0eefca1b4c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -155,4 +155,6 @@ interface CryptoService { // For testing shared session fun getSharedWithInfo(roomId: String?, sessionId: String): MXUsersDevicesMap fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? + + fun logDbUsageInfo() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index 326eac8f91..d3a3fd9fbd 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -314,6 +314,10 @@ internal class DefaultCryptoService @Inject constructor( } // Just update fetchDevicesList(NoOpMatrixCallback()) + + cryptoCoroutineScope.launch(coroutineDispatchers.crypto) { + cryptoStore.tidyUpDataBase() + } } fun ensureDevice() { @@ -1291,6 +1295,11 @@ internal class DefaultCryptoService @Inject constructor( override fun getWithHeldMegolmSession(roomId: String, sessionId: String): RoomKeyWithHeldContent? { return cryptoStore.getWithHeldMegolmSession(roomId, sessionId) } + + override fun logDbUsageInfo() { + cryptoStore.logDbUsageInfo() + } + /* ========================================================================================== * For test only * ========================================================================================== */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt index 72d541d4df..9a9f645b49 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt @@ -456,4 +456,6 @@ internal interface IMXCryptoStore { fun setDeviceKeysUploaded(uploaded: Boolean) fun getDeviceKeysUploaded(): Boolean + fun tidyUpDataBase() + fun logDbUsageInfo() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index 5d19e6d607..ec1a5d73a1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -95,6 +95,7 @@ import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.olm.OlmAccount import org.matrix.olm.OlmException import timber.log.Timber +import java.lang.StringBuilder import javax.inject.Inject import kotlin.collections.set @@ -1666,4 +1667,61 @@ internal class RealmCryptoStore @Inject constructor( result } } + + /** + * Some entries in the DB can get a bit out of control with time + * So we need to tidy up a bit + */ + override fun tidyUpDataBase() { + val prevWeekTs = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1_000 + doRealmTransaction(realmConfiguration) { realm -> + + // Only keep one week history + realm.where() + .lessThan(IncomingGossipingRequestEntityFields.LOCAL_CREATION_TIMESTAMP, prevWeekTs) + .findAll().let { + Timber.i("## Crypto Clean up ${it.size} IncomingGossipingRequestEntity") + it.deleteAllFromRealm() + } + + // Clean the cancelled ones? + realm.where() + .equalTo(OutgoingGossipingRequestEntityFields.REQUEST_STATE_STR, OutgoingGossipingRequestState.CANCELLED.name) + .equalTo(OutgoingGossipingRequestEntityFields.TYPE_STR, GossipRequestType.KEY.name) + .findAll().let { + Timber.i("## Crypto Clean up ${it.size} OutgoingGossipingRequestEntity") + it.deleteAllFromRealm() + } + + // Only keep one week history + realm.where() + .lessThan(GossipingEventEntityFields.AGE_LOCAL_TS, prevWeekTs) + .findAll().let { + Timber.i("## Crypto Clean up ${it.size} GossipingEventEntityFields") + it.deleteAllFromRealm() + } + + // Can we do something for WithHeldSessionEntity? + } + } + + /** + * Prints out database info + */ + override fun logDbUsageInfo() { + Realm.getInstance(realmConfiguration).use { realm -> + val info = StringBuilder() + // Check if we have data + info.append("\n==============================================") + info.append("\n==============================================") + info.append("\nCrypto Realm is empty: ${realm.isEmpty}") + realmConfiguration.realmObjectClasses.forEach { modelClazz -> + val count = realm.where(modelClazz).count() + info.append("\nCrypto Realm - count ${modelClazz.simpleName}: $count") + } + info.append("\n==============================================") + info.append("\n==============================================") + Timber.i(info.toString()) + } + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt index 7e182525a9..3b1fc73bc9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultSession.kt @@ -18,7 +18,9 @@ package org.matrix.android.sdk.internal.session import androidx.annotation.MainThread import dagger.Lazy +import io.realm.Realm import io.realm.RealmConfiguration +import io.realm.kotlin.where import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import okhttp3.OkHttpClient @@ -197,7 +199,7 @@ internal class DefaultSession @Inject constructor( override fun close() { assert(isOpen) stopSync() - // timelineEventDecryptor.destroy() + // timelineEventDecryptor.destroy() uiHandler.post { lifecycleObservers.forEach { it.onStop() } } @@ -284,4 +286,22 @@ internal class DefaultSession @Inject constructor( override fun toString(): String { return "$myUserId - ${sessionParams.deviceId}" } + + override fun dbgTraceDbInfo() { + Realm.getInstance(realmConfiguration).use { realm -> + val info = StringBuilder() + + // Check if we have data + info.append("\n==============================================") + info.append("\n==============================================") + info.append("\nSession Realm is empty: ${realm.isEmpty}") + realmConfiguration.realmObjectClasses.forEach { modelClazz -> + val count = realm.where(modelClazz).count() + info.append("\nSession Realm - count ${modelClazz.simpleName}: $count") + } + info.append("\n==============================================") + info.append("\n==============================================") + Timber.i(info.toString()) + } + } } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 95fe16ea51..4514c9ef80 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -446,6 +446,8 @@ class BugReporter @Inject constructor( */ fun openBugReportScreen(activity: FragmentActivity, forSuggestion: Boolean = false) { screenshot = takeScreenshot(activity) + activeSessionHolder.getSafeActiveSession()?.dbgTraceDbInfo() + activeSessionHolder.getSafeActiveSession()?.cryptoService()?.logDbUsageInfo() val intent = Intent(activity, BugReportActivity::class.java) intent.putExtra("FOR_SUGGESTION", forSuggestion)