Files
UnrealEngineUWP/Engine/Source/Programs/CrashReportClient/Private/RecoveryService.cpp
Stefan Boberg 1f813eb516 Copying //UE4/Dev-Core to Main (//UE4/Main)
#rb many

[CL 9405827 by Stefan Boberg in Main branch]
2019-10-03 16:26:48 -04:00

139 lines
4.7 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "RecoveryService.h"
#if CRASH_REPORT_WITH_RECOVERY
#include "HAL/FileManager.h"
#include "CrashReportClient.h" // For CrashReportClientLog
#include "Interfaces/IPluginManager.h"
#include "IMessagingModule.h"
#include "ConcertSettings.h"
#include "ConcertSyncSessionFlags.h"
#include "IConcertServer.h"
#include "IConcertSession.h"
#include "IConcertSyncServer.h"
#include "IConcertSyncServerModule.h"
#include "ConcertMessageData.h"
#include "Runtime/Launch/Resources/Version.h"
static const TCHAR RecoveryServiceName[] = TEXT("Disaster Recovery Service");
bool FRecoveryService::CollectFiles(const FString& DestDir, bool bMetaDataOnly, bool bAnonymizeMetaData)
{
auto LogError = [](const TCHAR* Reason)
{
UE_LOG(CrashReportClientLog, Error, TEXT("Failed to collect recovery session file(s). %s"), Reason);
};
if (!Server)
{
LogError(TEXT("The recovery service is not running."));
return false;
}
else if (!IFileManager::Get().DirectoryExists(*DestDir))
{
LogError(TEXT("The destination folder doesn't exist."));
return false;
}
FGuid ExportedSessionId = GetRecoverySessionId();
if (!ExportedSessionId.IsValid())
{
LogError(TEXT("The session session could not be found."));
return false;
}
FText ErrorMsg;
FConcertSessionFilter Filter;
Filter.bMetaDataOnly = bMetaDataOnly;
if (!Server->GetConcertServer()->ExportSession(ExportedSessionId, Filter, DestDir, bAnonymizeMetaData, ErrorMsg))
{
LogError(TEXT("Server failed to export the session."));
return false;
}
return true;
}
bool FRecoveryService::Startup()
{
#if UE_BUILD_SHIPPING && (!defined(PLATFORM_SUPPORTS_MESSAGEBUS) || !PLATFORM_SUPPORTS_MESSAGEBUS)
#error PLATFORM_SUPPORTS_MESSAGEBUS was explicitly defined in CrashReportClient.Target.cs for shipping configuration. MessageBus is required by Concert. Ensure it is still enabled.
#endif
if (!IMessagingModule::Get().GetDefaultBus())
{
UE_LOG(CrashReportClientLog, Error, TEXT("MessageBus is not enabled in this configuration. Recovery service will be disabled!"));
return false;
}
if (!IConcertSyncServerModule::IsAvailable())
{
UE_LOG(CrashReportClientLog, Error, TEXT("ConcertSyncServer Module is missing. Recovery service will be disabled!"));
return false;
}
TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin("UdpMessaging");
if (!Plugin || !Plugin->IsEnabled())
{
// The UdpMessaging plugin should be added to the {appname}.Target.cs build file.
UE_LOG(CrashReportClientLog, Error, TEXT("The 'UDP Messaging' plugin is disabled. The Concert server only supports UDP protocol. Recovery service will be disabled!"));
return false;
}
// Setup the disaster recovery server configuration
UConcertServerConfig* ServerConfig = IConcertSyncServerModule::Get().ParseServerSettings(FCommandLine::Get());
ServerConfig->bAutoArchiveOnReboot = true; // If server crashed, was killed, etc, ensure the recovery session is archived (expected by recovery flow).
ServerConfig->NumSessionsToKeep = 10;
ServerConfig->EndpointSettings.RemoteEndpointTimeoutSeconds = 0;
ServerConfig->WorkingDir = GetRecoveryServiceWorkingDir();
ServerConfig->ArchiveDir = GetRecoveryServiceArchivedDir();
FConcertSessionFilter AutoArchiveSessionFilter;
AutoArchiveSessionFilter.bIncludeIgnoredActivities = true;
// Start disaster recovery server.
Server = IConcertSyncServerModule::Get().CreateServer(TEXT("DisasterRecovery"), AutoArchiveSessionFilter);
Server->Startup(ServerConfig, EConcertSyncSessionFlags::Default_DisasterRecoverySession);
UE_LOG(CrashReportClientLog, Display, TEXT("%s Initialized (Name: %s, Version: %d.%d, Role: %s)"), RecoveryServiceName, *Server->GetConcertServer()->GetServerInfo().ServerName, ENGINE_MAJOR_VERSION, ENGINE_MINOR_VERSION, *Server->GetConcertServer()->GetRole());
return true;
}
void FRecoveryService::Shutdown()
{
if (Server)
{
Server->Shutdown();
Server.Reset();
UE_LOG(CrashReportClientLog, Display, TEXT("%s Shutdown"), RecoveryServiceName);
}
}
FString FRecoveryService::GetRecoveryServiceWorkingDir() const
{
return FPaths::ProjectIntermediateDir();
}
FString FRecoveryService::GetRecoveryServiceArchivedDir() const
{
return FPaths::ProjectSavedDir();
}
FGuid FRecoveryService::GetRecoverySessionId() const
{
// As long as the Concert server is up, the session would remain live (it's going to be archived when the server shutdown or reboot).
for (TSharedPtr<IConcertServerSession>& Session : Server->GetConcertServer()->GetSessions())
{
// As convention, the disaster recovery session names starts with the server name, followed by the project name, and date time.
if (Session->GetName().StartsWith(Server->GetConcertServer()->GetServerInfo().ServerName))
{
return Session->GetId();
}
}
return FGuid();// Not found.
}
#endif