mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-04 15:02:25 +02:00
Update ^C Handling during upload|download operations
* Update ^C Handling during upload|download operations
This commit is contained in:
parent
39c04642cd
commit
bf029b4676
|
@ -161,13 +161,14 @@ class CurlResponse {
|
||||||
|
|
||||||
class CurlEngine {
|
class CurlEngine {
|
||||||
|
|
||||||
__gshared CurlEngine[] curlEnginePool;
|
// Shared pool of CurlEngine instances accessible across all threads
|
||||||
|
__gshared CurlEngine[] curlEnginePool; // __gshared is used to declare a variable that is shared across all threads
|
||||||
|
|
||||||
HTTP http;
|
HTTP http;
|
||||||
|
File uploadFile;
|
||||||
|
CurlResponse response;
|
||||||
bool keepAlive;
|
bool keepAlive;
|
||||||
ulong dnsTimeout;
|
ulong dnsTimeout;
|
||||||
CurlResponse response;
|
|
||||||
File uploadFile;
|
|
||||||
string internalThreadId;
|
string internalThreadId;
|
||||||
|
|
||||||
this() {
|
this() {
|
||||||
|
@ -176,31 +177,27 @@ class CurlEngine {
|
||||||
internalThreadId = generateAlphanumericString();
|
internalThreadId = generateAlphanumericString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The destructor should only clean up resources owned directly by this instance
|
||||||
~this() {
|
~this() {
|
||||||
// The destructor should only clean up resources owned directly by this instance
|
// Is the file still open?
|
||||||
addLogEntry("CurlEngine DESTRUCTOR CALLED", ["debug"]);
|
|
||||||
addLogEntry("CurlEngine DESTRUCTOR CALLED");
|
|
||||||
|
|
||||||
// Avoid modifying or destroying shared/static resources here
|
|
||||||
if (uploadFile.isOpen()) {
|
if (uploadFile.isOpen()) {
|
||||||
uploadFile.close();
|
uploadFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup class memory usage
|
// Is 'response' cleared?
|
||||||
object.destroy(uploadFile); // Destroy, however we cant set to null
|
if (response !is null) {
|
||||||
object.destroy(response); // Destroy, then set to null
|
object.destroy(response); // Destroy, then set to null
|
||||||
response = null;
|
response = null;
|
||||||
internalThreadId = null;
|
}
|
||||||
|
|
||||||
// Is the actual http instance is stopped?
|
// Is the actual http instance is stopped?
|
||||||
if (!http.isStopped) {
|
if (!http.isStopped) {
|
||||||
// instance was not stopped .. need to stop it
|
// HTTP instance was not stopped .. need to stop it
|
||||||
addLogEntry("CurlEngine DESTRUCTOR HTTP INSTANCE WAS NOT STOPPED - STOPPING", ["debug"]);
|
|
||||||
http.shutdown();
|
http.shutdown();
|
||||||
|
object.destroy(http); // Destroy, however we cant set to null
|
||||||
}
|
}
|
||||||
object.destroy(http); // Destroy, however we cant set to null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CurlEngine getCurlInstance() {
|
static CurlEngine getCurlInstance() {
|
||||||
synchronized (CurlEngine.classinfo) {
|
synchronized (CurlEngine.classinfo) {
|
||||||
// What is the current pool size
|
// What is the current pool size
|
||||||
|
@ -232,6 +229,7 @@ class CurlEngine {
|
||||||
synchronized (CurlEngine.classinfo) {
|
synchronized (CurlEngine.classinfo) {
|
||||||
// What is the current pool size
|
// What is the current pool size
|
||||||
addLogEntry("CURL ENGINES TO RELEASE: " ~ to!string(curlEnginePool.length), ["debug"]);
|
addLogEntry("CURL ENGINES TO RELEASE: " ~ to!string(curlEnginePool.length), ["debug"]);
|
||||||
|
addLogEntry("CURL ENGINES TO RELEASE: " ~ to!string(curlEnginePool.length));
|
||||||
|
|
||||||
// Safely iterate and clean up each CurlEngine instance
|
// Safely iterate and clean up each CurlEngine instance
|
||||||
foreach (curlEngineInstance; curlEnginePool) {
|
foreach (curlEngineInstance; curlEnginePool) {
|
||||||
|
@ -253,12 +251,11 @@ class CurlEngine {
|
||||||
|
|
||||||
// Destroy all curl instances
|
// Destroy all curl instances
|
||||||
static void destroyAllCurlInstances() {
|
static void destroyAllCurlInstances() {
|
||||||
|
|
||||||
addLogEntry("DESTROY ALL CURL ENGINES", ["debug"]);
|
addLogEntry("DESTROY ALL CURL ENGINES", ["debug"]);
|
||||||
|
addLogEntry("DESTROY ALL CURL ENGINES");
|
||||||
// Release all 'curl' instances
|
// Release all 'curl' instances
|
||||||
releaseAllCurlInstances();
|
releaseAllCurlInstances();
|
||||||
// Destroy curlEnginePool, set to null
|
|
||||||
object.destroy(curlEnginePool);
|
|
||||||
curlEnginePool = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are releasing a curl instance back to the pool
|
// We are releasing a curl instance back to the pool
|
||||||
|
|
|
@ -53,6 +53,7 @@ class LogBuffer {
|
||||||
flushThread.start();
|
flushThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The destructor should only clean up resources owned directly by this instance
|
||||||
~this() {
|
~this() {
|
||||||
object.destroy(bufferLock);
|
object.destroy(bufferLock);
|
||||||
object.destroy(condReady);
|
object.destroy(condReady);
|
||||||
|
|
18
src/main.d
18
src/main.d
|
@ -1367,13 +1367,8 @@ extern(C) nothrow @nogc @system void exitHandler(int value) {
|
||||||
assumeNoGC ( () {
|
assumeNoGC ( () {
|
||||||
addLogEntry("\nReceived termination signal, initiating cleanup");
|
addLogEntry("\nReceived termination signal, initiating cleanup");
|
||||||
// Wait for all parallel jobs that depend on the database to complete
|
// Wait for all parallel jobs that depend on the database to complete
|
||||||
|
|
||||||
addLogEntry("Waiting for any existing upload|download process to complete");
|
addLogEntry("Waiting for any existing upload|download process to complete");
|
||||||
taskPool.finish(true);
|
syncEngineInstance.shutdown();
|
||||||
|
|
||||||
// Force kill any running threads
|
|
||||||
//addLogEntry("Forcing any active thread to exit");
|
|
||||||
//taskPool.finish(false);
|
|
||||||
|
|
||||||
// Perform the shutdown process
|
// Perform the shutdown process
|
||||||
performSynchronisedExitProcess("exitHandler");
|
performSynchronisedExitProcess("exitHandler");
|
||||||
|
@ -1403,17 +1398,16 @@ void performSynchronisedExitProcess(string scopeCaller = null) {
|
||||||
shutdownOneDriveWebhook();
|
shutdownOneDriveWebhook();
|
||||||
// Shutdown the client side filtering objects
|
// Shutdown the client side filtering objects
|
||||||
shutdownSelectiveSync();
|
shutdownSelectiveSync();
|
||||||
|
// Destroy all 'curl' instances
|
||||||
|
destroyCurlInstances();
|
||||||
// Shutdown the sync engine
|
// Shutdown the sync engine
|
||||||
shutdownSyncEngine();
|
shutdownSyncEngine();
|
||||||
// Shutdown any local filesystem monitoring
|
// Shutdown any local filesystem monitoring
|
||||||
shutdownFilesystemMonitor();
|
shutdownFilesystemMonitor();
|
||||||
// Shutdown the database
|
// Shutdown the database
|
||||||
shutdownDatabase();
|
shutdownDatabase();
|
||||||
// Destroy all 'curl' instances
|
|
||||||
destroyCurlInstances();
|
|
||||||
// Shutdown the application configuration objects
|
// Shutdown the application configuration objects
|
||||||
shutdownAppConfig();
|
shutdownAppConfig();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
addLogEntry("Error during performStandardExitProcess: " ~ e.toString(), ["error"]);
|
addLogEntry("Error during performStandardExitProcess: " ~ e.toString(), ["error"]);
|
||||||
}
|
}
|
||||||
|
@ -1449,7 +1443,7 @@ void shutdownFilesystemMonitor() {
|
||||||
void shutdownSelectiveSync() {
|
void shutdownSelectiveSync() {
|
||||||
if (selectiveSync !is null) {
|
if (selectiveSync !is null) {
|
||||||
addLogEntry("Shutdown Client Side Filtering instance", ["debug"]);
|
addLogEntry("Shutdown Client Side Filtering instance", ["debug"]);
|
||||||
selectiveSync.shutdown();
|
selectiveSync.shutdown();
|
||||||
object.destroy(selectiveSync);
|
object.destroy(selectiveSync);
|
||||||
selectiveSync = null;
|
selectiveSync = null;
|
||||||
}
|
}
|
||||||
|
@ -1458,7 +1452,7 @@ void shutdownSelectiveSync() {
|
||||||
void shutdownSyncEngine() {
|
void shutdownSyncEngine() {
|
||||||
if (syncEngineInstance !is null) {
|
if (syncEngineInstance !is null) {
|
||||||
addLogEntry("Shutdown Sync Engine instance", ["debug"]);
|
addLogEntry("Shutdown Sync Engine instance", ["debug"]);
|
||||||
//syncEngineInstance.shutdown(); - potentially need this and also check for a ~this() for class cleanup
|
syncEngineInstance.shutdown(); // Make sure any running thread completes first
|
||||||
object.destroy(syncEngineInstance);
|
object.destroy(syncEngineInstance);
|
||||||
syncEngineInstance = null;
|
syncEngineInstance = null;
|
||||||
}
|
}
|
||||||
|
@ -1480,7 +1474,7 @@ void shutdownAppConfig() {
|
||||||
// We were running with --dry-run , clean up the applicable database
|
// We were running with --dry-run , clean up the applicable database
|
||||||
cleanupDryRunDatabaseFiles(runtimeDatabaseFile);
|
cleanupDryRunDatabaseFiles(runtimeDatabaseFile);
|
||||||
}
|
}
|
||||||
object.destroy(appConfig);
|
object.destroy(appConfig);
|
||||||
appConfig = null;
|
appConfig = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,17 +111,19 @@ class OneDriveApi {
|
||||||
siteSearchUrl = appConfig.globalGraphEndpoint ~ "/v1.0/sites?search";
|
siteSearchUrl = appConfig.globalGraphEndpoint ~ "/v1.0/sites?search";
|
||||||
siteDriveUrl = appConfig.globalGraphEndpoint ~ "/v1.0/sites/";
|
siteDriveUrl = appConfig.globalGraphEndpoint ~ "/v1.0/sites/";
|
||||||
|
|
||||||
|
|
||||||
// Subscriptions
|
// Subscriptions
|
||||||
subscriptionUrl = appConfig.globalGraphEndpoint ~ "/v1.0/subscriptions";
|
subscriptionUrl = appConfig.globalGraphEndpoint ~ "/v1.0/subscriptions";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The destructor should only clean up resources owned directly by this instance
|
||||||
~this() {
|
~this() {
|
||||||
// We cant destroy 'appConfig' here as this leads to a segfault
|
if (curlEngine !is null) {
|
||||||
object.destroy(curlEngine);
|
curlEngine = null;
|
||||||
object.destroy(response);
|
}
|
||||||
curlEngine = null;
|
|
||||||
response = null;
|
if (response !is null) {
|
||||||
|
response = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the OneDrive API class
|
// Initialise the OneDrive API class
|
||||||
|
@ -353,12 +355,6 @@ class OneDriveApi {
|
||||||
return authorised;
|
return authorised;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinitialise the OneDrive API class
|
|
||||||
bool reinitialise() {
|
|
||||||
releaseCurlEngine();
|
|
||||||
return initialise(this.keepAlive);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the API has been configured correctly, print the items that been configured
|
// If the API has been configured correctly, print the items that been configured
|
||||||
void debugOutputConfiguredAPIItems() {
|
void debugOutputConfiguredAPIItems() {
|
||||||
// Debug output of configured URL's
|
// Debug output of configured URL's
|
||||||
|
@ -1120,7 +1116,6 @@ class OneDriveApi {
|
||||||
|
|
||||||
// Wrapper function for all requests to OneDrive API
|
// Wrapper function for all requests to OneDrive API
|
||||||
// - This should throw a OneDriveException so that this exception can be handled appropriately elsewhere in the application
|
// - This should throw a OneDriveException so that this exception can be handled appropriately elsewhere in the application
|
||||||
|
|
||||||
private JSONValue oneDriveErrorHandlerWrapper(CurlResponse delegate(CurlResponse response) executer, bool validateJSONResponse, string callingFunction, int lineno) {
|
private JSONValue oneDriveErrorHandlerWrapper(CurlResponse delegate(CurlResponse response) executer, bool validateJSONResponse, string callingFunction, int lineno) {
|
||||||
// Create a new 'curl' response
|
// Create a new 'curl' response
|
||||||
response = new CurlResponse();
|
response = new CurlResponse();
|
||||||
|
|
32
src/sync.d
32
src/sync.d
|
@ -185,9 +185,9 @@ class SyncEngine {
|
||||||
this(ApplicationConfig appConfig, ItemDatabase itemDB, ClientSideFiltering selectiveSync) {
|
this(ApplicationConfig appConfig, ItemDatabase itemDB, ClientSideFiltering selectiveSync) {
|
||||||
|
|
||||||
// Create the specific task pool to process items in parallel
|
// Create the specific task pool to process items in parallel
|
||||||
this.processPool = new TaskPool(to!int(appConfig.getValueLong("threads")));
|
processPool = new TaskPool(to!int(appConfig.getValueLong("threads")));
|
||||||
addLogEntry("PROCESS POOL WORKER THREADS: " ~ to!string(processPool.size), ["debug"]);
|
addLogEntry("PROCESS POOL WORKER THREADS: " ~ to!string(processPool.size), ["debug"]);
|
||||||
|
|
||||||
// Configure the class varaible to consume the application configuration
|
// Configure the class varaible to consume the application configuration
|
||||||
this.appConfig = appConfig;
|
this.appConfig = appConfig;
|
||||||
// Configure the class varaible to consume the database configuration
|
// Configure the class varaible to consume the database configuration
|
||||||
|
@ -302,23 +302,15 @@ class SyncEngine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~this() {
|
// The destructor should only clean up resources owned directly by this instance
|
||||||
this.processPool.finish(true);
|
~this() {
|
||||||
object.destroy(this.processPool); // Destroy, then set to null
|
processPool.finish(true);
|
||||||
this.processPool = null;
|
|
||||||
object.destroy(this.appConfig); // Destroy, then set to null
|
|
||||||
this.appConfig = null;
|
|
||||||
object.destroy(this.itemDB); // Destroy, then set to null
|
|
||||||
this.itemDB = null;
|
|
||||||
object.destroy(this.selectiveSync); // Destroy, then set to null
|
|
||||||
this.selectiveSync = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the Sync Engine class
|
// Initialise the Sync Engine class
|
||||||
bool initialise() {
|
bool initialise() {
|
||||||
|
|
||||||
// Control whether the worker threads are daemon threads. A daemon thread is automatically terminated when all non-daemon threads have terminated.
|
// Control whether the worker threads are daemon threads. A daemon thread is automatically terminated when all non-daemon threads have terminated.
|
||||||
processPool.isDaemon(true);
|
processPool.isDaemon(true);
|
||||||
|
|
||||||
// Create a new instance of the OneDrive API
|
// Create a new instance of the OneDrive API
|
||||||
OneDriveApi oneDriveApiInstance;
|
OneDriveApi oneDriveApiInstance;
|
||||||
|
@ -387,15 +379,15 @@ class SyncEngine {
|
||||||
|
|
||||||
// Shutdown this API instance, as we will create API instances as required, when required
|
// Shutdown this API instance, as we will create API instances as required, when required
|
||||||
oneDriveApiInstance.releaseCurlEngine();
|
oneDriveApiInstance.releaseCurlEngine();
|
||||||
|
|
||||||
// Free object and memory
|
|
||||||
//object.destroy(oneDriveApiInstance);
|
|
||||||
//oneDriveApiInstance = null;
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown the sync engine, wait for anything in processPool to complete
|
||||||
|
void shutdown() {
|
||||||
|
addLogEntry("SYNC-ENGINE: Waiting for all internal threads to complete", ["debug"]);
|
||||||
|
processPool.finish(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Get Default Drive Details for this Account
|
// Get Default Drive Details for this Account
|
||||||
void getDefaultDriveDetails() {
|
void getDefaultDriveDetails() {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue