diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManager.java b/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManager.java index af614491e37b9624e60829d67e776e1f50e33e93..571df42d55706c0640c83480bbdd4a90bf85e775 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManager.java +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManager.java @@ -50,6 +50,7 @@ public interface LifecycleManager { enum LifecycleState { NOT_STARTED, + DB_OPEN, STARTING, MIGRATING_DATABASE, COMPACTING_DATABASE, @@ -83,6 +84,8 @@ public interface LifecycleManager { */ void registerForShutdown(ExecutorService e); + void openDatabase(); + /** * Opens the {@link Database} using the given key and starts any * registered {@link Service Services}. diff --git a/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.kt b/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.kt index 2e4781ed23032f3e6a7fcc1deec6717d0f5096f7..212851be60eec309177033bec735bdcfadb95ce3 100644 --- a/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.kt +++ b/mailbox-core/src/main/java/org/briarproject/mailbox/core/lifecycle/LifecycleManagerImpl.kt @@ -25,6 +25,7 @@ import org.briarproject.mailbox.core.db.Database import org.briarproject.mailbox.core.db.MigrationListener import org.briarproject.mailbox.core.lifecycle.LifecycleManager.LifecycleState import org.briarproject.mailbox.core.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE +import org.briarproject.mailbox.core.lifecycle.LifecycleManager.LifecycleState.DB_OPEN import org.briarproject.mailbox.core.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE import org.briarproject.mailbox.core.lifecycle.LifecycleManager.LifecycleState.NOT_STARTED import org.briarproject.mailbox.core.lifecycle.LifecycleManager.LifecycleState.RUNNING @@ -99,30 +100,32 @@ internal class LifecycleManagerImpl @Inject constructor( executors.add(e) } + @GuardedBy("startStopWipeSemaphore") + override fun openDatabase() { + if (!startStopWipeSemaphore.tryAcquire()) { + LOG.info("Already starting or stopping") + return + } + try { + openDatabaseInternally() + } finally { + startStopWipeSemaphore.release() + } + } + @GuardedBy("startStopWipeSemaphore") override fun startServices(): StartResult { if (!startStopWipeSemaphore.tryAcquire()) { LOG.info("Already starting or stopping") return ALREADY_RUNNING } - state.compareAndSet(NOT_STARTED, STARTING) return try { - LOG.info("Opening database") - var start = now() - val reopened = db.open(this) - if (reopened) logDuration(LOG, { "Reopening database" }, start) - else logDuration(LOG, { "Creating database" }, start) - // Inform hooks that DB was opened - db.write { txn -> - for (hook in openDatabaseHooks) { - hook.onDatabaseOpened(txn) - } - } + openDatabaseInternally() + state.compareAndSet(DB_OPEN, STARTING) LOG.info("Starting services") state.value = STARTING_SERVICES - dbLatch.countDown() for (s in services) { - start = now() + val start = now() s.startService() logDuration(LOG, { "Starting service ${s.javaClass.simpleName}" }, start) } @@ -137,6 +140,26 @@ internal class LifecycleManagerImpl @Inject constructor( } } + private fun openDatabaseInternally() { + if (state.value != NOT_STARTED) { + return + } + LOG.info("Opening database") + var start = now() + val reopened = db.open(this) + if (reopened) logDuration(LOG, { "Reopening database" }, start) + else logDuration(LOG, { "Creating database" }, start) + // Inform hooks that DB was opened + db.write { txn -> + for (hook in openDatabaseHooks) { + hook.onDatabaseOpened(txn) + } + } + logDuration(LOG, { "Opening database" }, start) + state.value = DB_OPEN + dbLatch.countDown() + } + // startStopWipeSemaphore is being held during this because it will be called during db.open() // in startServices() @GuardedBy("startStopWipeSemaphore")