2014-03-14 14:13:41 -04:00
|
|
|
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "TaskBrowserPrivatePCH.h"
|
|
|
|
|
#include "TaskDatabase.h"
|
|
|
|
|
#include "TaskDatabaseThread.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if WITH_TESTTRACK
|
|
|
|
|
#include "TestTrackTaskDatabaseProvider.h"
|
|
|
|
|
#endif // WITH_TESTTRACK
|
|
|
|
|
|
|
|
|
|
DEFINE_LOG_CATEGORY(LogTaskDatabaseDefs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace TaskDatabaseSystem
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/** Global threaded task database singleton object */
|
|
|
|
|
FTaskDatabaseThreadRunnable* GTaskDatabaseThreadRunnable = NULL;
|
|
|
|
|
|
|
|
|
|
/** The actual task database thread object */
|
|
|
|
|
FRunnableThread* GTaskDatabaseThread = NULL;
|
|
|
|
|
|
|
|
|
|
/** True if a request has been sent and we're waiting for a response */
|
|
|
|
|
bool GIsWaitingForResponse = false;
|
|
|
|
|
|
|
|
|
|
/** True if we're currently connected to the database (as far as we know) */
|
|
|
|
|
bool GIsConnected = false;
|
|
|
|
|
|
|
|
|
|
/** Array of main-thread 'listeners' that registered to hear about completed requests */
|
|
|
|
|
TArray< FTaskDatabaseListener* > GListeners;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize the task database system. This must be called before anything else.
|
|
|
|
|
*
|
|
|
|
|
* @return True if successful
|
|
|
|
|
*/
|
|
|
|
|
bool Init()
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Initializing Task Database" ) );
|
|
|
|
|
|
|
|
|
|
if( GTaskDatabaseThreadRunnable != NULL )
|
|
|
|
|
{
|
|
|
|
|
// Already initialized?
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We're not connected yet!
|
|
|
|
|
GIsConnected = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create and initialize the task database provider
|
|
|
|
|
FTaskDatabaseProviderInterface* TaskDatabaseProvider = NULL;
|
|
|
|
|
|
|
|
|
|
#if WITH_TESTTRACK
|
|
|
|
|
TaskDatabaseProvider = FTestTrackProvider::CreateTestTrackProvider();
|
|
|
|
|
#endif // WITH_TESTTRACK
|
|
|
|
|
|
|
|
|
|
if( TaskDatabaseProvider == NULL )
|
|
|
|
|
{
|
|
|
|
|
// Failed to initialized task database provider
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Allocate threaded task database
|
|
|
|
|
GTaskDatabaseThreadRunnable =
|
|
|
|
|
new FTaskDatabaseThreadRunnable( TaskDatabaseProvider );
|
|
|
|
|
check( GTaskDatabaseThreadRunnable != NULL );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// No requests have been issued yet
|
|
|
|
|
GIsWaitingForResponse = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Select thread priority
|
|
|
|
|
// @todo: Consider using TPri_Low here since task database ops shouldn't require much CPU
|
|
|
|
|
EThreadPriority TaskDatabaseThreadPriority = TPri_Normal;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Starting Task Database Thread" ) );
|
|
|
|
|
|
|
|
|
|
// Launch the task database thread!
|
|
|
|
|
GTaskDatabaseThread = FRunnableThread::Create(
|
|
|
|
|
GTaskDatabaseThreadRunnable, // Runnable module
|
2014-05-12 08:39:12 -04:00
|
|
|
TEXT("TaskDatabaseThread"), // Thread name
|
2014-03-14 14:13:41 -04:00
|
|
|
0, // Stack size
|
|
|
|
|
TaskDatabaseThreadPriority ); // Thread priority
|
|
|
|
|
|
|
|
|
|
if( GTaskDatabaseThread == NULL )
|
|
|
|
|
{
|
|
|
|
|
// Failed to launch the thread
|
|
|
|
|
delete GTaskDatabaseThreadRunnable;
|
|
|
|
|
GTaskDatabaseThreadRunnable = NULL;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Suspend the task worker thread until there is actually work to do
|
|
|
|
|
GTaskDatabaseThreadRunnable->bThreadSafeShouldSuspend = true;
|
|
|
|
|
// GTaskDatabaseThread->Suspend( true );
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Task Database initialized" ) );
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Process any responses that are outstanding and fire off callback events */
|
|
|
|
|
void ProcessCompletedRequests()
|
|
|
|
|
{
|
|
|
|
|
if( GIsWaitingForResponse )
|
|
|
|
|
{
|
|
|
|
|
FTaskDatabaseResponse* ResponseToBroadcast = NULL;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
FScopeLock ScopeLock( >askDatabaseThreadRunnable->CriticalSection );
|
|
|
|
|
|
|
|
|
|
// Any requests pending?
|
|
|
|
|
if( GTaskDatabaseThreadRunnable->ThreadSafeResponse != NULL )
|
|
|
|
|
{
|
|
|
|
|
// There should never be another request already enqueued. We delete and clear the
|
|
|
|
|
// request data as soon as the response is generated.
|
|
|
|
|
check( GTaskDatabaseThreadRunnable->ThreadSafeCurrentRequest == NULL );
|
|
|
|
|
|
|
|
|
|
// OK, we've received a response to our last request!
|
|
|
|
|
ResponseToBroadcast = GTaskDatabaseThreadRunnable->ThreadSafeResponse;
|
|
|
|
|
|
|
|
|
|
// Tell the task database thread it can start working on other tasks now
|
|
|
|
|
GTaskDatabaseThreadRunnable->ThreadSafeResponse = NULL;
|
|
|
|
|
|
|
|
|
|
// No longer waiting for anything
|
|
|
|
|
GIsWaitingForResponse = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( ResponseToBroadcast != NULL )
|
|
|
|
|
{
|
|
|
|
|
// We completed our task, so go back to sleep
|
|
|
|
|
GTaskDatabaseThreadRunnable->bThreadSafeShouldSuspend = true;
|
|
|
|
|
// GTaskDatabaseThread->Suspend( true );
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Broadcasting response for completed request (Type: %i)" ), ( int32 )ResponseToBroadcast->RequestType );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Peek to see if this is a connection event, and update our status if so
|
|
|
|
|
if( ResponseToBroadcast->RequestType == ETaskDatabaseRequestType::ConnectToDatabase )
|
|
|
|
|
{
|
|
|
|
|
// We assume we're disconnected if a 'connect to database' request fails
|
|
|
|
|
GIsConnected = ResponseToBroadcast->bSucceeded;
|
|
|
|
|
}
|
|
|
|
|
else if( ResponseToBroadcast->RequestType == ETaskDatabaseRequestType::DisconnectFromDatabase )
|
|
|
|
|
{
|
|
|
|
|
// We assume we're no longer connected after completing a disconnect request
|
|
|
|
|
GIsConnected = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( ResponseToBroadcast->bFailedBecauseOfDisconnection )
|
|
|
|
|
{
|
|
|
|
|
// We were disconnected unexpectedly!
|
|
|
|
|
GIsConnected = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Broadcast callbacks for this response
|
|
|
|
|
for( TArray< FTaskDatabaseListener* >::TIterator ListenerIter( GListeners ); ListenerIter; ++ListenerIter )
|
|
|
|
|
{
|
|
|
|
|
FTaskDatabaseListener* CurListener = *ListenerIter;
|
|
|
|
|
check( CurListener != NULL );
|
|
|
|
|
|
|
|
|
|
CurListener->OnTaskDatabaseRequestCompleted( ResponseToBroadcast );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We're done with the response data now
|
|
|
|
|
delete ResponseToBroadcast;
|
|
|
|
|
ResponseToBroadcast = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Clean up the task database system. Call this after before exiting the app. */
|
|
|
|
|
void Destroy()
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Destroying Task Database" ) );
|
|
|
|
|
|
|
|
|
|
// Clear listener array
|
|
|
|
|
GListeners.Empty();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( IsInitialized() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Destroying: Waiting for current task to complete" ) );
|
|
|
|
|
|
|
|
|
|
// We're probably trying to shutdown the editor, so never wait an innappropriate amount of time
|
|
|
|
|
const float MaxTimeToWaitForThread = 5.0f;
|
|
|
|
|
const double TimeStartedWaiting = FPlatformTime::Seconds();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Wait for the current task to complete
|
|
|
|
|
GTaskDatabaseThreadRunnable->bThreadSafeShouldSuspend = false;
|
|
|
|
|
while( GIsWaitingForResponse && ( FPlatformTime::Seconds() - TimeStartedWaiting ) < MaxTimeToWaitForThread )
|
|
|
|
|
{
|
|
|
|
|
ProcessCompletedRequests();
|
|
|
|
|
FPlatformProcess::Sleep( 0.01f );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Are we connected? If so, we'll log out before shutting down
|
|
|
|
|
if( IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Destroying: Logging out of database" ) );
|
|
|
|
|
|
|
|
|
|
// Initiate a log out before exiting
|
|
|
|
|
DisconnectFromDatabase_Async();
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Destroying: Waiting for log out to complete" ) );
|
|
|
|
|
|
|
|
|
|
// Wait for the current task to complete
|
|
|
|
|
while( GIsWaitingForResponse && ( FPlatformTime::Seconds() - TimeStartedWaiting ) < MaxTimeToWaitForThread )
|
|
|
|
|
{
|
|
|
|
|
ProcessCompletedRequests();
|
|
|
|
|
FPlatformProcess::Sleep( 0.01f );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Destroying: Ready to destroy" ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Stop the task database
|
|
|
|
|
if( GTaskDatabaseThreadRunnable != NULL )
|
|
|
|
|
{
|
|
|
|
|
GTaskDatabaseThreadRunnable->bThreadSafeShouldSuspend = false;
|
|
|
|
|
GTaskDatabaseThreadRunnable->Stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Kill the task database thread
|
|
|
|
|
if( GTaskDatabaseThread != NULL )
|
|
|
|
|
{
|
|
|
|
|
// GTaskDatabaseThread->Suspend( false );
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Waiting for Task Database thread to complete" ) );
|
|
|
|
|
|
|
|
|
|
// NOTE: We shouldn't really have to wait long here since we already waited earlier
|
|
|
|
|
GTaskDatabaseThread->WaitForCompletion();
|
|
|
|
|
|
|
|
|
|
delete GTaskDatabaseThread;
|
|
|
|
|
|
|
|
|
|
GTaskDatabaseThread = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Destroy the task database object
|
|
|
|
|
if( GTaskDatabaseThreadRunnable != NULL )
|
|
|
|
|
{
|
|
|
|
|
delete GTaskDatabaseThreadRunnable;
|
|
|
|
|
GTaskDatabaseThreadRunnable = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GIsConnected = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Task Database destroyed" ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if the task database system was initialized successfully
|
|
|
|
|
*
|
|
|
|
|
* @return True if initialized
|
|
|
|
|
*/
|
|
|
|
|
bool IsInitialized()
|
|
|
|
|
{
|
|
|
|
|
return ( GTaskDatabaseThreadRunnable != NULL );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if we're currently waiting for a response from the server
|
|
|
|
|
*
|
|
|
|
|
* @return True if a request is in progress
|
|
|
|
|
*/
|
|
|
|
|
bool IsRequestInProgress()
|
|
|
|
|
{
|
|
|
|
|
return GIsWaitingForResponse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns true if we're currently connected to a database
|
|
|
|
|
*
|
|
|
|
|
* @return True if currently connected
|
|
|
|
|
*/
|
|
|
|
|
bool IsConnected()
|
|
|
|
|
{
|
|
|
|
|
return GIsConnected;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Kicks off an asynchronous request using the task database thread
|
|
|
|
|
*
|
|
|
|
|
* @param Request The request to start. Assumes ownership of allocated memory.
|
|
|
|
|
*
|
|
|
|
|
* @return True if successful
|
|
|
|
|
*/
|
|
|
|
|
bool StartAsyncRequest( FTaskDatabaseRequest* Request )
|
|
|
|
|
{
|
|
|
|
|
check( Request != NULL );
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Starting async request (Type: %i)" ), ( int32 )Request->RequestType );
|
|
|
|
|
|
|
|
|
|
// First, process any outstanding request so that we're not holding up the queue
|
|
|
|
|
// @todo: Should we do this here? It's a bit risky because the frontend UI may not be expecting to
|
|
|
|
|
// receive callback events while in a 'start request' stack frame. Maybe just leave this to Update()
|
|
|
|
|
ProcessCompletedRequests();
|
|
|
|
|
|
|
|
|
|
if( GIsWaitingForResponse )
|
|
|
|
|
{
|
|
|
|
|
// Another request is already in progress. Can't start this request yet.
|
|
|
|
|
delete Request;
|
|
|
|
|
Request = NULL;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
FScopeLock ScopeLock( >askDatabaseThreadRunnable->CriticalSection );
|
|
|
|
|
|
|
|
|
|
// Current request should always be NULL when GIsWaitingForResponse is false
|
|
|
|
|
check( GTaskDatabaseThreadRunnable->ThreadSafeCurrentRequest == NULL );
|
|
|
|
|
|
|
|
|
|
// Start the request
|
|
|
|
|
GTaskDatabaseThreadRunnable->ThreadSafeCurrentRequest = Request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We're waiting for a response now
|
|
|
|
|
GIsWaitingForResponse = true;
|
|
|
|
|
|
|
|
|
|
// Wake the thread up to start working
|
|
|
|
|
GTaskDatabaseThreadRunnable->bThreadSafeShouldSuspend = false;
|
|
|
|
|
// GTaskDatabaseThread->Suspend( false );
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Updates the task database and checks for any completed requests, firing callbacks if needed. This
|
|
|
|
|
should usually be called with every engine Tick. */
|
|
|
|
|
void Update()
|
|
|
|
|
{
|
|
|
|
|
// Process and requests that may have completed and fire callbacks
|
|
|
|
|
ProcessCompletedRequests();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds the specified object as a 'listener' for completed task database requests. Remember to remove
|
|
|
|
|
* the object using UnregisterListener() before it's deleted!
|
|
|
|
|
*
|
|
|
|
|
* @param Listener The object to register. Should not be NULL.
|
|
|
|
|
*/
|
|
|
|
|
void RegisterListener( FTaskDatabaseListener* Listener )
|
|
|
|
|
{
|
|
|
|
|
check( Listener != NULL );
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Listener registered (Pointer: %i)" ), ( int32 )Listener );
|
|
|
|
|
|
|
|
|
|
GListeners.AddUnique( Listener );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Removes the specified object from the list of 'listeners'
|
|
|
|
|
*
|
|
|
|
|
* @param Listener The object to unregister. Should have been previously registered.
|
|
|
|
|
*/
|
|
|
|
|
void UnregisterListener( FTaskDatabaseListener* Listener )
|
|
|
|
|
{
|
|
|
|
|
check( Listener != NULL )
|
|
|
|
|
|
|
|
|
|
TDLOG( TEXT( "Listener unregistered (Pointer: %i)" ), ( int32 )Listener );
|
|
|
|
|
|
|
|
|
|
GListeners.RemoveSwap( Listener );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initiates asynchronous query for available task databases
|
|
|
|
|
*
|
|
|
|
|
* @param InServerName Server host name
|
|
|
|
|
* @param InServerPort Server port
|
|
|
|
|
* @param InLoginUserName User name
|
|
|
|
|
* @param InLoginPassword Password
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool QueryAvailableDatabases_Async( const FString& InServerName, const uint32 InServerPort, const FString& InLoginUserName, const FString& InLoginPassword )
|
|
|
|
|
{
|
|
|
|
|
if( IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we're already connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build a server URL string (e.g. "http://myservername:80")
|
|
|
|
|
FString ServerURL =
|
|
|
|
|
FString( TEXT( "http://" ) ) +
|
|
|
|
|
InServerName +
|
|
|
|
|
FString( TEXT( ":" ) ) +
|
|
|
|
|
FString( FString::FromInt( InServerPort ) );
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest_QueryAvailableDatabases* Request = new FTaskDatabaseRequest_QueryAvailableDatabases();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::QueryAvailableDatabases;
|
|
|
|
|
Request->ServerURL = ServerURL;
|
|
|
|
|
Request->LoginUserName = InLoginUserName;
|
|
|
|
|
Request->LoginPassword = InLoginPassword;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Asynchronously connects to the task database and attempts to login to a specific database
|
|
|
|
|
*
|
|
|
|
|
* @param InServerName Server host name
|
|
|
|
|
* @param InServerPort Server port
|
|
|
|
|
* @param InLoginUserName User name
|
|
|
|
|
* @param InLoginPassword Password
|
|
|
|
|
* @param InDatabaeName The database to login to
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool ConnectToDatabase_Async( const FString& InServerName, const uint32 InServerPort, const FString& InLoginUserName, const FString& InLoginPassword, const FString& InDatabaseName )
|
|
|
|
|
{
|
|
|
|
|
if( IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we're already connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Build a server URL string (e.g. "http://myservername:80")
|
|
|
|
|
FString ServerURL =
|
|
|
|
|
FString( TEXT( "http://" ) ) +
|
|
|
|
|
InServerName +
|
|
|
|
|
FString( TEXT( ":" ) ) +
|
|
|
|
|
FString( FString::FromInt( InServerPort ) );
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest_ConnectToDatabase* Request = new FTaskDatabaseRequest_ConnectToDatabase();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::ConnectToDatabase;
|
|
|
|
|
Request->ServerURL = ServerURL;
|
|
|
|
|
Request->LoginUserName = InLoginUserName;
|
|
|
|
|
Request->LoginPassword = InLoginPassword;
|
|
|
|
|
Request->DatabaseName = InDatabaseName;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Disconnects from the database asynchronously
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool DisconnectFromDatabase_Async()
|
|
|
|
|
{
|
|
|
|
|
if( !IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we'not connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest* Request = new FTaskDatabaseRequest();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::DisconnectFromDatabase;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Asynchronously queries a list of available database filters
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool QueryFilters_Async()
|
|
|
|
|
{
|
|
|
|
|
if( !IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we'not connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest* Request = new FTaskDatabaseRequest();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::QueryFilters;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Asynchronously queries a list of task entries for the specified filter name
|
|
|
|
|
*
|
|
|
|
|
* @param InFilterName Name of the filter (can be empty string)
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool QueryTasks_Async( const FString& InFilterName )
|
|
|
|
|
{
|
|
|
|
|
if( !IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we'not connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest_QueryTasks* Request = new FTaskDatabaseRequest_QueryTasks();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::QueryTasks;
|
|
|
|
|
Request->FilterName = InFilterName;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Asynchronously queries details about a single specific task entry
|
|
|
|
|
*
|
|
|
|
|
* @param InTaskNumber The database task number for the task entry
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool QueryTaskDetails_Async( const uint32 InTaskNumber )
|
|
|
|
|
{
|
|
|
|
|
if( !IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we'not connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest_QueryTaskDetails* Request = new FTaskDatabaseRequest_QueryTaskDetails();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::QueryTaskDetails;
|
|
|
|
|
Request->TaskNumber = InTaskNumber;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Attempts to asynchronously mark the specified task as completed
|
|
|
|
|
*
|
|
|
|
|
* @param InTaskNumber The database task number to mark complete
|
|
|
|
|
* @param InResolutionData Information about how the task should be resolved
|
|
|
|
|
*
|
|
|
|
|
* @return True if async requested was kicked off successfully
|
|
|
|
|
*/
|
|
|
|
|
bool MarkTaskComplete_Async( const uint32 InTaskNumber, const FTaskResolutionData& InResolutionData )
|
|
|
|
|
{
|
|
|
|
|
if( !IsConnected() )
|
|
|
|
|
{
|
|
|
|
|
TDLOG( TEXT( "Async request failed because we'not connected to a server" ) );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FTaskDatabaseRequest_MarkTaskComplete* Request = new FTaskDatabaseRequest_MarkTaskComplete();
|
|
|
|
|
Request->RequestType = ETaskDatabaseRequestType::MarkTaskComplete;
|
|
|
|
|
Request->TaskNumber = InTaskNumber;
|
|
|
|
|
Request->ResolutionData = InResolutionData;
|
|
|
|
|
|
|
|
|
|
return StartAsyncRequest( Request );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|