diff --git a/src/itemdb.d b/src/itemdb.d index ed587c25..777dc0e4 100644 --- a/src/itemdb.d +++ b/src/itemdb.d @@ -680,6 +680,7 @@ final class ItemDatabase { try { auto stmt = db.prepare("VACUUM;"); stmt.exec(); + log.vdebug("Database vacuum is complete"); } catch (SqliteException e) { writeln(); log.error("ERROR: Unable to perform a database vacuum: " ~ e.msg); diff --git a/src/main.d b/src/main.d index 05927114..f0fe6bc7 100644 --- a/src/main.d +++ b/src/main.d @@ -898,28 +898,33 @@ int main(string[] cliArgs) { void performStandardExitProcess(string scopeCaller) { // Who called this function log.vdebug("Running performStandardExitProcess due to: ", scopeCaller); - - // Shutdown the database - if (itemDB !is null) { - // Make sure the .wal file is incorporated into the main db before we exit - itemDB.performVacuum(); - object.destroy(itemDB); - } - + + // Wait for all parallel jobs that depend on the database to complete + log.vdebug("Wait for all parallel jobs that depend on the database to complete"); + taskPool.finish(true); + // Shutdown the OneDrive API instance if (oneDriveApiInstance !is null) { + log.vdebug("Shutdown OneDrive API instance"); oneDriveApiInstance.shutdown(); object.destroy(oneDriveApiInstance); } // Shutdown the sync engine - if (syncEngineInstance !is null) object.destroy(syncEngineInstance); + if (syncEngineInstance !is null) { + log.vdebug("Shutdown Sync Engine instance"); + object.destroy(syncEngineInstance); + } // Shutdown the client side filtering objects - if (selectiveSync !is null) object.destroy(selectiveSync); + if (selectiveSync !is null) { + log.vdebug("Shutdown Client Side Filtering instance"); + object.destroy(selectiveSync); + } // Shutdown the application configuration objects if (appConfig !is null) { + log.vdebug("Shutdown Application Configuration instance"); // Cleanup any existing dry-run elements ... these should never be left hanging around cleanupDryRunDatabaseFiles(appConfig.databaseFilePathDryRun); object.destroy(appConfig); @@ -927,10 +932,22 @@ void performStandardExitProcess(string scopeCaller) { // Shutdown any local filesystem monitoring if (filesystemMonitor !is null) { + log.vdebug("Shutdown Filesystem Monitoring instance"); filesystemMonitor.shutdown(); object.destroy(filesystemMonitor); } + // Shutdown the database + if (itemDB !is null) { + log.vdebug("Shutdown Database instance"); + // Make sure the .wal file is incorporated into the main db before we exit + if (itemDB.isDatabaseInitialised()) { + itemDB.performVacuum(); + } + object.destroy(itemDB); + } + + // Set all objects to null if (scopeCaller == "failureScope") { // Set these to be null due to failure scope - prevent 'ERROR: Unable to perform a database vacuum: out of memory' when the exit scope is then called log.vdebug("Setting Class Objects to null due to failure scope"); diff --git a/src/onedrive.d b/src/onedrive.d index d18ed49b..c81271c2 100644 --- a/src/onedrive.d +++ b/src/onedrive.d @@ -76,6 +76,7 @@ class OneDriveWebhook { private ushort port; private Tid parentTid; private shared uint count; + private bool started; static OneDriveWebhook getOrCreate(string host, ushort port, Tid parentTid) { if (!instantiated_) { @@ -97,9 +98,23 @@ class OneDriveWebhook { this.parentTid = parentTid; this.count = 0; } + + void serve() { + spawn(&serveStatic); + this.started = true; + log.log("Started webhook server"); + } + + void stop() { + if (this.started) { + RequestServer.stop(); + this.started = false; + } + log.log("Stopped webhook server"); + } // The static serve() is necessary because spawn() does not like instance methods - static serve() { + private static void serveStatic() { // we won't create the singleton instance if it hasn't been created already // such case is a bug which should crash the program and gets fixed instance_.serveImpl(); @@ -458,9 +473,20 @@ class OneDriveApi { // Shutdown OneDrive API Curl Engine void shutdown() { + // Delete subscription if there exists any - deleteSubscription(); - + try { + deleteSubscription(); + } catch (OneDriveException e) { + logSubscriptionError(e); + } + + // Shutdown webhook server if it is running + if (webhook !is null) { + webhook.stop(); + object.destroy(webhook); + } + // Reset any values to defaults, freeing any set objects curlEngine.http.clearRequestHeaders(); curlEngine.http.onSend = null; @@ -858,7 +884,7 @@ class OneDriveApi { to!ushort(appConfig.getValueLong("webhook_listening_port")), thisTid ); - spawn(&OneDriveWebhook.serve); + webhook.serve(); } auto elapsed = Clock.currTime(UTC()) - subscriptionLastErrorAt; @@ -999,13 +1025,14 @@ class OneDriveApi { private void deleteSubscription() { if (!hasValidSubscription()) { + log.vdebug("No valid Microsoft OneDrive webhook subscription to delete"); return; } string url; url = subscriptionUrl ~ "/" ~ subscriptionId; - del(url); - log.log("Deleted subscription"); + performDelete(url); + log.vdebug("Deleted Microsoft OneDrive webhook subscription"); } private void logSubscriptionError(OneDriveException e) {