/**
  	 * @EventName Editor.AbnormalShutdown
	 *
	 * @Trigger Fired only by the editor at startup, once for each "abnormal shutdown" detected that has not already been sent.
	 *
	 * @Type Static
	 *
	 * @EventParam SessionId Analytics SessionID of the session that abnormally terminated.
	 * @EventParam EngineVersion EngineVersion of the session that abnormally terminated.
	 * @EventParam ShutdownType - one of Crashed, Debugger, or AbormalShutdown
	 *               * Crashed - we definitely detected a crash (whether or not a debugger was attached)
	 *               * Debugger - the session crashed or shutdown abnormally, but we had a debugger attached at startup, so abnormal termination is much more likely because the user was debugging.
	 *               * AbnormalShutdown - this happens when we didn't detect a normal shutdown, but none of the above cases is the cause.
	 * @EventParam Timestamp - the UTC time of the last known time the crashed session was running, within 5 minutes.
	 *
	 * @TODO: Debugger should be a completely separate flag, since it's orthogonal to whether we detect a crash or shutdown.
	 *
	 * @Comments The editor will only try to check for abnormal terminations if it determines it is a real editor run (not a commandlet or PIE, or editor -game run), and the user has not disabled sending Engine Usage data to Epic via the Editor global preferences.
	 *
	 * SessionId can be used to find the actual session associated with this crash in the data.
	 *
	 * Use THIS instead of the current event's analytics AppVersion field, since the crash could be from an old version. Could technically be found by searching the data for the SessionId and checking the version there, but sending it here simplifies the backend processing and ensure we have the version here even if we never got the original events.
	 *
	 * If multiple versions of the editor or launched, this code will properly track each one and its shutdown status. So during startup, an editor instance may need to fire off several events.
	 *
	 * When attributing abnormal terminations to engine versions, be sure to use the EngineVersion associated with this event, and not the AppVersion. AppVersion is for the session that is currently sending the event, not for the session that crashed. That is why EngineVersion is sent separately.
	 *
	 * The editor updates this timestamp every 5 minutes, so we should know the time of the crash within 5 minutes. It should technically correlate with the last heartbeat we receive in the data for that session.
	 */
	void SendAbnormalShutdownReport(const FSessionRecord& Record)
	{
		FGameProjectGenerationModule& GameProjectModule = FModuleManager::LoadModuleChecked<FGameProjectGenerationModule>(TEXT("GameProjectGeneration"));
		bool bHasCode = GameProjectModule.Get().ProjectHasCodeFiles();

#if PLATFORM_WINDOWS
		const FString PlatformName(TEXT("Windows"));
#elif PLATFORM_MAC
		const FString PlatformName(TEXT("Mac"));
#elif PLATFORM_LINUX
		const FString PlatformName(TEXT("Linux"));
#else
		const FString PlatformName(TEXT("Unknown"));
#endif

		FGuid SessionId;
		FString SessionIdString = Record.SessionId;
		if (FGuid::Parse(SessionIdString, SessionId))
		{
			// convert session guid to one with braces for sending to analytics
			SessionIdString = SessionId.ToString(EGuidFormats::DigitsWithHyphensInBraces);
		}

		FString ShutdownTypeString = Record.bCrashed ? EditorAnalyticsDefs::CrashSessionToken :
			(Record.bIsDebugger ? EditorAnalyticsDefs::DebuggerSessionToken : EditorAnalyticsDefs::AbnormalSessionToken);

		TArray< FAnalyticsEventAttribute > AbnormalShutdownAttributes;
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("SessionId"), SessionIdString));
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("EngineVersion"), Record.EngineVersion));
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("ShutdownType"), ShutdownTypeString));
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("Timestamp"), Record.Timestamp.ToIso8601()));

		FEditorAnalytics::ReportEvent(TEXT("Editor.AbnormalShutdown"), PlatformName, bHasCode, AbnormalShutdownAttributes);
	}
    static FName Generate(UUserDefinedStruct* Struct, const FString& NameBase, const FGuid Guid, FString* OutFriendlyName = NULL)
    {
        check(Struct);

        FString Result;
        if (!NameBase.IsEmpty())
        {
            const FName NewNameBase(*NameBase);
            if (ensure(NewNameBase.IsValidXName(INVALID_OBJECTNAME_CHARACTERS)))
            {
                Result = NameBase;
            }
        }

        if (Result.IsEmpty())
        {
            Result = TEXT("MemberVar");
        }

        const uint32 UniqueNameId = CastChecked<UUserDefinedStructEditorData>(Struct->EditorData)->GenerateUniqueNameIdForMemberVariable();
        const FString FriendlyName = FString::Printf(TEXT("%s_%u"), *Result, UniqueNameId);
        if (OutFriendlyName)
        {
            *OutFriendlyName = FriendlyName;
        }
        const FName NameResult = *FString::Printf(TEXT("%s_%s"), *FriendlyName, *Guid.ToString(EGuidFormats::Digits));
        check(NameResult.IsValidXName(INVALID_OBJECTNAME_CHARACTERS));
        return NameResult;
    }
void FOnlineSessionInfoNull::Init(const FOnlineSubsystemNull& Subsystem)
{
	// Read the IP from the system
	bool bCanBindAll;
	HostAddr = ISocketSubsystem::Get()->GetLocalHostAddr(*GLog, bCanBindAll);

	// The below is a workaround for systems that set hostname to a distinct address from 127.0.0.1 on a loopback interface.
	// See e.g. https://www.debian.org/doc/manuals/debian-reference/ch05.en.html#_the_hostname_resolution
	// and http://serverfault.com/questions/363095/why-does-my-hostname-appear-with-the-address-127-0-1-1-rather-than-127-0-0-1-in
	// Since we bind to 0.0.0.0, we won't answer on 127.0.1.1, so we need to advertise ourselves as 127.0.0.1 for any other loopback address we may have.
	uint32 HostIp = 0;
	HostAddr->GetIp(HostIp); // will return in host order
	// if this address is on loopback interface, advertise it as 127.0.0.1
	if ((HostIp & 0xff000000) == 0x7f000000)
	{
		HostAddr->SetIp(0x7f000001);	// 127.0.0.1
	}

	// Now set the port that was configured
	HostAddr->SetPort(GetPortFromNetDriver(Subsystem.GetInstanceName()));

	FGuid OwnerGuid;
	FPlatformMisc::CreateGuid(OwnerGuid);
	SessionId = FUniqueNetIdString(OwnerGuid.ToString());
}
	void CreateAndWriteRecordForSession()
	{
		FGuid SessionId;
		if (FGuid::Parse(FEngineAnalytics::GetProvider().GetSessionID(), SessionId))
		{
			// convert session guid to one without braces or other chars that might not be suitable for storage
			CurrentSession.SessionId = SessionId.ToString(EGuidFormats::DigitsWithHyphens);
		}
		else
		{
			CurrentSession.SessionId = FEngineAnalytics::GetProvider().GetSessionID();
		}

		CurrentSession.EngineVersion = FEngineVersion::Current().ToString(EVersionComponent::Changelist);
		CurrentSession.Timestamp = FDateTime::UtcNow();
		CurrentSession.bCrashed = false;
		CurrentSession.bIsDebugger = FPlatformMisc::IsDebuggerPresent();
		CurrentSessionSectionName = GetStoreSectionString(CurrentSession.SessionId);

		FString IsDebuggerString = CurrentSession.bIsDebugger ? EditorAnalyticsDefs::TrueValueString : EditorAnalyticsDefs::FalseValueString;

		FPlatformMisc::SetStoredValue(EditorAnalyticsDefs::StoreId, CurrentSessionSectionName, EditorAnalyticsDefs::CrashStoreKey, EditorAnalyticsDefs::FalseValueString);
		FPlatformMisc::SetStoredValue(EditorAnalyticsDefs::StoreId, CurrentSessionSectionName, EditorAnalyticsDefs::EngineVersionStoreKey, CurrentSession.EngineVersion);
		FPlatformMisc::SetStoredValue(EditorAnalyticsDefs::StoreId, CurrentSessionSectionName, EditorAnalyticsDefs::TimestampStoreKey, TimestampToString(CurrentSession.Timestamp));
		FPlatformMisc::SetStoredValue(EditorAnalyticsDefs::StoreId, CurrentSessionSectionName, EditorAnalyticsDefs::DebuggerStoreKey, IsDebuggerString);

		SessionRecords.Add(CurrentSession);
	}
// Have a similar process function for the normal tcp connection.
void FNetworkFileServerHttp::Process(FArchive& In, TArray<uint8>&Out, FNetworkFileServerHttp* Server)
{
	int loops = 0;
	while(!In.AtEnd())
	{
		UE_LOG(LogFileServer, Log, TEXT("In %d "), loops++);
		// Every Request has a Guid attached to it - similar to Web session IDs.
		FGuid ClientGuid;
		In << ClientGuid;

		UE_LOG(LogFileServer, Log, TEXT("Recieved GUID %s"), *ClientGuid.ToString());

		FNetworkFileServerClientConnectionHTTP* Connection = NULL;
		if (Server->RequestHandlers.Contains(ClientGuid))
		{
			UE_LOG(LogFileServer, Log, TEXT("Picking up an existing handler" ));
			Connection = Server->RequestHandlers[ClientGuid];
		}
		else
		{
			UE_LOG(LogFileServer, Log, TEXT("Creating a handler" ));
			Connection = Server->CreateNewConnection();
			Server->RequestHandlers.Add(ClientGuid,Connection);
		}

		Connection->ProcessPayload(In);
		Out.Append(Connection->GetOutBuffer());
		Connection->ResetBuffer();
	}
}
/**
 * Start capturing stats for upload
 * Uses the unique ApiKey associated with your app
 */
bool FAnalyticsProviderET::StartSession(const TArray<FAnalyticsEventAttribute>& Attributes)
{
	UE_LOG(LogAnalytics, Log, TEXT("[%s] AnalyticsET::StartSession"),*APIKey);

	// end/flush previous session before staring new one
	if (bSessionInProgress)
	{
		EndSession();
	}

	FGuid SessionGUID;
	FPlatformMisc::CreateGuid(SessionGUID);
	SessionID = SessionGUID.ToString(EGuidFormats::DigitsWithHyphensInBraces);

	// always ensure we send a few specific attributes on session start.
	TArray<FAnalyticsEventAttribute> AppendedAttributes(Attributes);
	// this is for legacy reasons (we used to use this ID, so helps us create old->new mappings).
	AppendedAttributes.Emplace(TEXT("UniqueDeviceId"), FPlatformMisc::GetUniqueDeviceId());
	// we should always know what platform is hosting this session.
	AppendedAttributes.Emplace(TEXT("Platform"), FString(FPlatformProperties::IniPlatformName()));
	AppendedAttributes.Emplace(TEXT("LegacyURL"), bUsingLegacyAppServer ? TEXT("true") : TEXT("false"));

	RecordEvent(TEXT("SessionStart"), AppendedAttributes);
	bSessionInProgress = true;
	return bSessionInProgress;
}
TSharedRef<FObjectBindingNode> FSequencerNodeTree::AddObjectBinding(const FString& ObjectName, const FGuid& ObjectBinding, TMap<FGuid, const FMovieSceneBinding*>& GuidToBindingMap, TArray< TSharedRef<FSequencerDisplayNode> >& OutNodeList)
{
	TSharedPtr<FObjectBindingNode> ObjectNode;
	TSharedPtr<FObjectBindingNode>* FoundObjectNode = ObjectBindingMap.Find(ObjectBinding);
	if (FoundObjectNode != nullptr)
	{
		ObjectNode = *FoundObjectNode;
	}
	else
	{
		// The node name is the object guid
		FName ObjectNodeName = *ObjectBinding.ToString();

		// Try to get the parent object node if there is one.
		TSharedPtr<FObjectBindingNode> ParentNode;
		TArray<UObject*> RuntimeObjects;
		UMovieSceneSequence* Animation = Sequencer.GetFocusedMovieSceneSequence();
		UObject* RuntimeObject = Animation->FindObject(ObjectBinding);
		if ( RuntimeObject != nullptr)
		{
			UObject* ParentObject = Animation->GetParentObject(RuntimeObject);
			if (ParentObject != nullptr)
			{
				FGuid ParentBinding = Animation->FindObjectId(*ParentObject);
				TSharedPtr<FObjectBindingNode>* FoundParentNode = ObjectBindingMap.Find( ParentBinding );
				if ( FoundParentNode != nullptr )
				{
					ParentNode = *FoundParentNode;
				}
				else
				{
					const FMovieSceneBinding** FoundParentMovieSceneBinding = GuidToBindingMap.Find( ParentBinding );
					if ( FoundParentMovieSceneBinding != nullptr )
					{
						ParentNode = AddObjectBinding( (*FoundParentMovieSceneBinding)->GetName(), ParentBinding, GuidToBindingMap, OutNodeList );
					}
				}
			}
		}

		// Create the node.
		ObjectNode = MakeShareable( new FObjectBindingNode( ObjectNodeName, ObjectName, ObjectBinding, ParentNode, *this ) );
		if (ParentNode.IsValid())
		{
			ParentNode->AddObjectBindingNode(ObjectNode.ToSharedRef());
		}
		else
		{
			OutNodeList.Add( ObjectNode.ToSharedRef() );
		}

		// Map the guid to the object binding node for fast lookup later
		ObjectBindingMap.Add( ObjectBinding, ObjectNode );
	}

	return ObjectNode.ToSharedRef();
}
Example #8
0
void FWebJSScripting::InvokeJSFunction(FGuid FunctionId, const CefRefPtr<CefListValue>& FunctionArguments, bool bIsError)
{
	CefRefPtr<CefProcessMessage> Message = CefProcessMessage::Create(TEXT("UE::ExecuteJSFunction"));
	CefRefPtr<CefListValue> MessageArguments = Message->GetArgumentList();
	MessageArguments->SetString(0, *FunctionId.ToString(EGuidFormats::Digits));
	MessageArguments->SetList(1, FunctionArguments);
	MessageArguments->SetBool(2, bIsError);
	SendProcessMessage(Message);
}
CefRefPtr<CefDictionaryValue> FUnrealCEFSubProcessRemoteScripting::V8FunctionToCef(CefRefPtr<CefV8Value> Object, CefRefPtr<CefV8Value> Function)
{
	CefRefPtr<CefDictionaryValue> Result = CefDictionaryValue::Create();
	FGuid Guid = CallbackRegistry.FindOrAdd(CefV8Context::GetCurrentContext(), Object, Function);
	Result->SetString("$type", "callback");
	Result->SetString("$id", *Guid.ToString(EGuidFormats::Digits));
	Result->SetString("$name", Function->GetFunctionName());
	return Result;
}
Example #10
0
	virtual FString GetPluginSpecificCacheKeySuffix() const override
	{
		const uint16 Version = 13;

		return FString::Printf( TEXT("%s_%s_%s_%hu")
			, *Format.ToString()
			, *DataGuid.ToString()
			, *MeshId
			, Version
			);
	}
/**
 * @EventName QosStats_DatacenterEvent
 * @Trigger Attempt to determine a user datacenter from available QoS information
 * @Type static
 * @EventParam QosStats_SessionId string Guid of this attempt
 * @EventParam QosStats_Version integer Qos analytics version
 * @EventParam QosStats_Timestamp string Timestamp when this whole attempt started
 * @EventParam QosStats_TotalTime float Total time this complete attempt took, includes delay between all ping queries (ms)
 * @EventParam QosStats_DatacenterId string Data center selected
 * @EventParam QosStats_NumRegions integer Total number of regions considered or known at the time
 * @EventParam QosStats_NumResults integer Total number of results found for consideration
 * @EventParam QosStats_NumSuccessCount integer Total number of successful ping evaluations
 * @EventParam QosStats_RegionDetails string CSV details about the regions
 * @EventParam QosStats_SearchDetails string CSV details about the individual servers queried

 * @Comments Analytics data for a complete qos datacenter determination attempt
 */
void FQosDatacenterStats::ParseQosResults(TSharedPtr<IAnalyticsProvider>& AnalyticsProvider, FGuid& SessionId)
{
	TArray<FAnalyticsEventAttribute> QoSAttributes;

	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_SessionId, SessionId.ToString()));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_Version, StatsVersion));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_Timestamp, QosData.Timestamp));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_TotalTime, QosData.SearchTime.MSecs));

	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_DeterminationType, ToString(QosData.DeterminationType)));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_DatacenterId, QosData.BestDatacenterId));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_NumRegions, QosData.Regions.Num()));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_NumResults, QosData.NumTotalSearches));
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_NumSuccessCount, QosData.NumSuccessAttempts));

	FString RegionDetails;
	if (QosData.Regions.Num() > 0)
	{
		for (auto& Region : QosData.Regions)
		{
			RegionDetails += FString::Printf(TEXT("{\"RegionId\":\"%s\", \"AvgPing\":\"%d\", \"NumResults\":%d},"),
				!Region.RegionId.IsEmpty() ? *Region.RegionId : TEXT("Unknown"),
				Region.AvgPing,
				Region.NumResults
				);
		}
		RegionDetails = RegionDetails.LeftChop(1);
	}

	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_RegionDetails, RegionDetails));

	FString SearchDetails;
	if (QosData.SearchResults.Num() > 0)
	{
		for (auto& SearchResult : QosData.SearchResults)
		{
			SearchDetails += FString::Printf(TEXT("{\"OwnerId\":\"%s\", \"RegionId\":\"%s\", \"PingInMs\":%d, \"bIsValid\":%s},"),
				SearchResult.OwnerId.IsValid() ? *SearchResult.OwnerId->ToString() : TEXT("Unknown"),
				*SearchResult.DatacenterId,
				SearchResult.PingInMs,
				SearchResult.bIsValid ? TEXT("true") : TEXT("false")
				);
		}
		SearchDetails = SearchDetails.LeftChop(1);
	}
	QoSAttributes.Add(FAnalyticsEventAttribute(QosStats_SearchDetails, SearchDetails));

	//PrintEventAndAttributes(QosStats_DatacenterEvent, QoSAttributes);
	if (AnalyticsProvider.IsValid())
	{
		AnalyticsProvider->RecordEvent(QosStats_DatacenterEvent, QoSAttributes);
	}
}
	FArchive* CreateOutputArchive()
	{
		FArchive* OutputFilePtr = nullptr;
		if (CommunicationMode == ThroughFile)
		{
			const double StartTime = FPlatformTime::Seconds();
			bool bResult = false;

			// It seems XGE does not support deleting files.
			// Don't delete the input file if we are running under Incredibuild.
			// Instead, we signal completion by creating a zero byte "Success" file after the output file has been fully written.
			if (!GShaderCompileUseXGE)
			{
				do 
				{
					// Remove the input file so that it won't get processed more than once
					bResult = IFileManager::Get().Delete(*InputFilePath);
				} 
				while (!bResult && (FPlatformTime::Seconds() - StartTime < 2));

				if (!bResult)
				{
					UE_LOG(LogShaders, Fatal,TEXT("Couldn't delete input file %s, is it readonly?"), *InputFilePath);
				}
			}

			// To make sure that the process waiting for results won't read unfinished output file,
			// we use a temp file name during compilation.
			do
			{
				FGuid Guid;
				FPlatformMisc::CreateGuid(Guid);
				TempFilePath = WorkingDirectory + Guid.ToString();
			} while (IFileManager::Get().FileSize(*TempFilePath) != INDEX_NONE);

			const double StartTime2 = FPlatformTime::Seconds();

			do 
			{
				// Create the output file.
				OutputFilePtr = IFileManager::Get().CreateFileWriter(*TempFilePath,FILEWRITE_EvenIfReadOnly);
			} 
			while (!OutputFilePtr && (FPlatformTime::Seconds() - StartTime2 < 2));
			
			if (!OutputFilePtr)
			{
				UE_LOG(LogShaders, Fatal,TEXT("Couldn't save output file %s"), *TempFilePath);
			}
		}

		return OutputFilePtr;
	}
Example #13
0
void FWebJSScripting::InvokeJSFunction(FGuid FunctionId, int32 ArgCount, FWebJSParam Arguments[], bool bIsError)
{
	CefRefPtr<CefListValue> FunctionArguments = CefListValue::Create();
	for ( int32 i=0; i<ArgCount; i++)
	{
		SetConverted(FunctionArguments, i, Arguments[i]);
	}

	CefRefPtr<CefProcessMessage> Message = CefProcessMessage::Create(TEXT("UE::ExecuteJSFunction"));
	CefRefPtr<CefListValue> MessageArguments = Message->GetArgumentList();
	MessageArguments->SetString(0, *FunctionId.ToString(EGuidFormats::Digits));
	MessageArguments->SetList(1, FunctionArguments);
	MessageArguments->SetBool(2, bIsError);
	SendProcessMessage(Message);
}
CefRefPtr<CefV8Value> FUnrealCEFSubProcessRemoteScripting::CreateUObjectProxy(FGuid ObjectId, CefRefPtr<CefListValue> Methods)
{
	CefRefPtr<CefV8Context> Context = CefV8Context::GetCurrentContext();
	CefRefPtr<CefBrowser> Browser = Context->GetBrowser();
	CefRefPtr<CefV8Value> Result = CefV8Value::CreateObject(nullptr);
	CefRefPtr<FUnrealCEFSubProcessRemoteObject> Remote = new FUnrealCEFSubProcessRemoteObject(this, Browser, ObjectId);
	for (size_t I=0; I < Methods->GetSize(); ++I)
	{
		CefString MethodName = Methods->GetString(I);
		CefRefPtr<CefV8Value> FunctionProxy = CefV8Value::CreateFunction(MethodName, new FUnrealCEFSubProcessRemoteMethodHandler(Remote, MethodName));
		Result->SetValue(MethodName, FunctionProxy, static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_DONTDELETE | V8_PROPERTY_ATTRIBUTE_READONLY ));
	}
	Result->SetValue("$id", CefV8Value::CreateString(*ObjectId.ToString(EGuidFormats::Digits)),  static_cast<CefV8Value::PropertyAttribute>(V8_PROPERTY_ATTRIBUTE_DONTDELETE | V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM));
	return Result;
}
bool FUnrealCEFSubProcessRemoteObject::ExecuteMethod(const CefString& MethodName, CefRefPtr<CefV8Value> Object, const CefV8ValueList& Arguments, CefRefPtr<CefV8Value>& Retval, CefString& InException)
{
	CefRefPtr<CefV8Context> Context = CefV8Context::GetCurrentContext();
	CefRefPtr<CefV8Exception> Exception;
	CefRefPtr<CefV8Value> PromiseObjects;

	// Run JS code that creates and unwraps a Promise object
	if (!Context->Eval(
		"(function() " \
		"{ "
		"	var Accept, Reject, PromiseObject;" \
		"	PromiseObject = new Promise(function(InAccept, InReject) " \
		"	{"
		"		Accept = InAccept;" \
		"		Reject = InReject;" \
		"	});" \
		"	return [PromiseObject, Accept, Reject];" \
		"})()" , PromiseObjects, Exception))
	{
		InException = Exception->GetMessage();
		return false;
	}

	if (!(PromiseObjects.get() && PromiseObjects->IsArray() && PromiseObjects->GetArrayLength() == 3))
	{
		return false;
	}

	Retval = PromiseObjects->GetValue(0);
	CefRefPtr<CefV8Value> Accept = PromiseObjects->GetValue(1);
	CefRefPtr<CefV8Value> Reject = PromiseObjects->GetValue(2);

	check(Retval->IsObject());
	check(Accept->IsFunction());
	check(Reject->IsFunction());

	FGuid CallbackGuid = RemoteScripting->CallbackRegistry.FindOrAdd(Context, Retval, Accept, Reject, true);
	CefRefPtr<CefProcessMessage> Message = CefProcessMessage::Create("UE::ExecuteUObjectMethod");
	CefRefPtr<CefListValue> MessageArguments = Message->GetArgumentList();
	MessageArguments->SetString(0, CefString(*ObjectId.ToString(EGuidFormats::Digits)));
	MessageArguments->SetString(1, MethodName);
	MessageArguments->SetString(2, CefString(*CallbackGuid.ToString(EGuidFormats::Digits)));
	MessageArguments->SetList(3, RemoteScripting->V8ArrayToCef(Arguments));

	Browser->SendProcessMessage(PID_BROWSER, Message);

	return true;
}
TSharedRef<FObjectBindingNode> FSequencerNodeTree::AddObjectBinding( const FText& ObjectName, const FGuid& ObjectBinding )
{
	// The node name is the object guid
	FName ObjectNodeName = *ObjectBinding.ToString();
	TSharedPtr<FSequencerDisplayNode> ParentNode = NULL;

	TSharedRef< FObjectBindingNode > ObjectNode = MakeShareable( new FObjectBindingNode( ObjectNodeName, ObjectName, ObjectBinding, ParentNode, *this ) );

	// Object binding nodes are always root nodes
	RootNodes.Add( ObjectNode );

	// Map the guid to the object binding node for fast lookup later
	ObjectBindingMap.Add( ObjectBinding, ObjectNode );

	return ObjectNode;
}
void FBuildPatchChunkCache::WaitForChunk( const FGuid& ChunkGuid )
{
	// Wait for the chunk to be available
	double StartedWaiting = FPlatformTime::Seconds();
	while( ChunkCache.Contains( ChunkGuid ) == false && !FBuildPatchInstallError::HasFatalError() )
	{
		FPlatformProcess::Sleep( 0.1f );
		const double CurrentTime = FPlatformTime::Seconds();
		if( BuildProgress->GetPauseState() )
		{
			BuildProgress->WaitWhilePaused();
			StartedWaiting = CurrentTime;
		}
		if( ( CurrentTime - StartedWaiting ) > 5.0 )
		{
			GWarn->Logf( TEXT( "FBuildPatchChunkCache: Still waiting for chunk %s" ), *ChunkGuid.ToString() );
			StartedWaiting = CurrentTime;
		}
	}
}
void FGenericCrashContext::Initialize()
{
	NCachedCrashContextProperties::bIsInternalBuild = FEngineBuildSettings::IsInternalBuild();
	NCachedCrashContextProperties::bIsPerforceBuild = FEngineBuildSettings::IsPerforceBuild();
	NCachedCrashContextProperties::bIsSourceDistribution = FEngineBuildSettings::IsSourceDistribution();
	NCachedCrashContextProperties::bIsUE4Release = FApp::IsEngineInstalled();

	NCachedCrashContextProperties::GameName = FString::Printf( TEXT("UE4-%s"), FApp::GetGameName() );
	NCachedCrashContextProperties::ExecutableName = FPlatformProcess::ExecutableName();
	NCachedCrashContextProperties::PlatformName = FPlatformProperties::PlatformName();
	NCachedCrashContextProperties::PlatformNameIni = FPlatformProperties::IniPlatformName();
	NCachedCrashContextProperties::BaseDir = FPlatformProcess::BaseDir();
	NCachedCrashContextProperties::RootDir = FPlatformMisc::RootDir();
	NCachedCrashContextProperties::EpicAccountId = FPlatformMisc::GetEpicAccountId();
	NCachedCrashContextProperties::MachineIdStr = FPlatformMisc::GetMachineId().ToString(EGuidFormats::Digits);
	FPlatformMisc::GetOSVersions(NCachedCrashContextProperties::OsVersion, NCachedCrashContextProperties::OsSubVersion);
	NCachedCrashContextProperties::NumberOfCores = FPlatformMisc::NumberOfCores();
	NCachedCrashContextProperties::NumberOfCoresIncludingHyperthreads = FPlatformMisc::NumberOfCoresIncludingHyperthreads();

	NCachedCrashContextProperties::CPUVendor = FPlatformMisc::GetCPUVendor();
	NCachedCrashContextProperties::CPUBrand = FPlatformMisc::GetCPUBrand();
	NCachedCrashContextProperties::PrimaryGPUBrand = FPlatformMisc::GetPrimaryGPUBrand();
	NCachedCrashContextProperties::UserName = FPlatformProcess::UserName();
	NCachedCrashContextProperties::DefaultLocale = FPlatformMisc::GetDefaultLocale();

	// Using the -fullcrashdump parameter will cause full memory minidumps to be created for crashes
	NCachedCrashContextProperties::CrashDumpMode = (int32)ECrashDumpMode::Default;
	if (FCommandLine::IsInitialized())
	{
		const TCHAR* CmdLine = FCommandLine::Get();
		if (FParse::Param( CmdLine, TEXT("fullcrashdump") ))
		{
			NCachedCrashContextProperties::CrashDumpMode = (int32)ECrashDumpMode::FullDump;
		}
	}

	const FGuid Guid = FGuid::NewGuid();
	NCachedCrashContextProperties::CrashGUID = FString::Printf(TEXT("UE4CC-%s-%s"), *NCachedCrashContextProperties::PlatformNameIni, *Guid.ToString(EGuidFormats::Digits));

	// Initialize delegate for updating SecondsSinceStart, beacuse FPlatformTime::Seconds() is not POSIX safe.
	const float PollingInterval = 1.0f;
	FTicker::GetCoreTicker().AddTicker( FTickerDelegate::CreateLambda( []( float DeltaTime )
	{
		NCachedCrashContextProperties::SecondsSinceStart = int32(FPlatformTime::Seconds() - GStartTime);
		return true;
	} ), PollingInterval );

	bIsInitialized = true;
}
Example #19
0
void FQuestionBlock::SubmitQuestions( const FGuid& SurveyIdentifier )
{
	if ( FEngineAnalytics::IsAvailable() )
	{
		if ( Style == Style_InlineText || Style == Style_MultilineText )
		{
			FString AnswerName = TEXT("Answer");
			for (int QuestionIndex = 0; QuestionIndex < Questions.Num(); QuestionIndex++)
			{
				TArray< FString > UserTextAnswersForQuestion = UserTextAnswers[QuestionIndex];

				TArray< FAnalyticsEventAttribute > EventAttributes;
				EventAttributes.Add( FAnalyticsEventAttribute( TEXT("SurveyID"), SurveyIdentifier.ToString() ) );
				EventAttributes.Add( FAnalyticsEventAttribute( TEXT("Question"), Questions[QuestionIndex].ToString() ) );

				int32 AnswerFlags = 0; 
				for (int AnswerIndex = 0; AnswerIndex < UserTextAnswersForQuestion.Num(); AnswerIndex++)
				{
					if ( !UserTextAnswersForQuestion[AnswerIndex].IsEmpty() )
					{
						AnswerFlags |= ( 1 << AnswerIndex );
					}
				}

				EventAttributes.Add( FAnalyticsEventAttribute( TEXT("AnswerFlags"), AnswerFlags ) );

				for (int AnswerIndex = 0; AnswerIndex < Answers.Num(); AnswerIndex++)
				{
					FString AnswerText = Answers[ AnswerIndex ].Text.ToString();
					if ( AnswerText.IsEmpty() )
					{
						AnswerText = FString::FormatAsNumber( AnswerIndex + 1 );
					}

					EventAttributes.Add( FAnalyticsEventAttribute( AnswerText, UserTextAnswersForQuestion[ AnswerIndex ] ) );
				}

				FEngineAnalytics::GetProvider().RecordEvent( TEXT("Survey"), EventAttributes);
			}
		}
		else
		{
			FString AnswerName = TEXT("Answer");
			for (int QuestionIndex = 0; QuestionIndex < Questions.Num(); QuestionIndex++)
			{
				TArray< int32 > UserAnswersForQuestion = UserAnswers[QuestionIndex];

				TArray< FAnalyticsEventAttribute > EventAttributes;
				EventAttributes.Add( FAnalyticsEventAttribute( TEXT("SurveyID"), SurveyIdentifier.ToString() ) );
				EventAttributes.Add( FAnalyticsEventAttribute( TEXT("Question"), Questions[QuestionIndex].ToString() ) );

				int32 AnswerFlags = 0; 
				for (int AnswerIndex = 0; AnswerIndex < UserAnswersForQuestion.Num(); AnswerIndex++)
				{
					AnswerFlags |= ( 1 << UserAnswersForQuestion[AnswerIndex] );
				}

				EventAttributes.Add( FAnalyticsEventAttribute( TEXT("AnswerFlags"), AnswerFlags ) );

				for (int AnswerIndex = 0; AnswerIndex < Answers.Num(); AnswerIndex++)
				{
					const FString Value = UserAnswersForQuestion.Contains( AnswerIndex ) ? TEXT("true") : TEXT("false");
					EventAttributes.Add( FAnalyticsEventAttribute( Answers[ AnswerIndex ].Text.ToString(), Value ) );
				}

				FEngineAnalytics::GetProvider().RecordEvent( TEXT("Survey"), EventAttributes);
			}
		}
	}
}
FString FReflectionCaptureEncodedHDRDerivedData::GetDDCKeyString(const FGuid& StateId)
{
	return FDerivedDataCacheInterface::BuildCacheKey(TEXT("REFL_ENC"), REFLECTIONCAPTURE_ENCODED_DERIVEDDATA_VER, *StateId.ToString());
}
Example #21
0
const FString FBuildPatchUtils::GetFileOldFilename( const FString& RootDirectory, const FGuid& FileGUID )
{
	check( FileGUID.IsValid() );
	return FPaths::Combine( *RootDirectory, *FString::Printf( TEXT("Files/%02d/%s.file"), FCrc::MemCrc_DEPRECATED( &FileGUID, sizeof( FGuid ) ) % 100, *FileGUID.ToString() ) );
}
Example #22
0
const FString FBuildPatchUtils::GetFileNewFilename(const EBuildPatchAppManifestVersion::Type ManifestVersion, const FString& RootDirectory, const FGuid& FileGUID, const uint64& FileHash)
{
	check( FileGUID.IsValid() );
	return FPaths::Combine( *RootDirectory, *FString::Printf( TEXT("%s/%02d/%016llX_%s.file"), *EBuildPatchAppManifestVersion::GetFileSubdir( ManifestVersion ), FCrc::MemCrc32( &FileGUID, sizeof( FGuid ) ) % 100, FileHash, *FileGUID.ToString() ) );
}
bool FGuidTest::RunTest( const FString& Parameters )
{
	FGuid g = FGuid(305419896, 2271560481, 305419896, 2271560481);

	// string conversions
	TestEqual(TEXT("String conversion (Default) must return EGuidFormats::Digits string"), g.ToString(), g.ToString(EGuidFormats::Digits));
	TestEqual<FString>(TEXT("String conversion (EGuidFormats::Digits)"), g.ToString(EGuidFormats::Digits), TEXT("12345678876543211234567887654321"));
	TestEqual<FString>(TEXT("String conversion (EGuidFormats::DigitsWithHyphens)"), g.ToString(EGuidFormats::DigitsWithHyphens), TEXT("12345678-8765-4321-1234-567887654321"));
	TestEqual<FString>(TEXT("String conversion (EGuidFormats::DigitsWithHyphensInBraces)"), g.ToString(EGuidFormats::DigitsWithHyphensInBraces), TEXT("{12345678-8765-4321-1234-567887654321}"));
	TestEqual<FString>(TEXT("String conversion (EGuidFormats::DigitsWithHyphensInParentheses)"), g.ToString(EGuidFormats::DigitsWithHyphensInParentheses), TEXT("(12345678-8765-4321-1234-567887654321)"));
	TestEqual<FString>(TEXT("String conversion (EGuidFormats::HexValuesInBraces)"), g.ToString(EGuidFormats::HexValuesInBraces), TEXT("{0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}}"));
	TestEqual<FString>(TEXT("String conversion (EGuidFormats::UniqueObjectGuid)"), g.ToString(EGuidFormats::UniqueObjectGuid), TEXT("12345678-87654321-12345678-87654321"));

	// parsing valid strings (exact)
	FGuid g2_1;

	TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::Digits)"), FGuid::ParseExact(TEXT("12345678876543211234567887654321"), EGuidFormats::Digits, g2_1));
	TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::Digits)"), g2_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphens)"), FGuid::ParseExact(TEXT("12345678-8765-4321-1234-567887654321"), EGuidFormats::DigitsWithHyphens, g2_1));
	TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphens)"), g2_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInBraces)"), FGuid::ParseExact(TEXT("{12345678-8765-4321-1234-567887654321}"), EGuidFormats::DigitsWithHyphensInBraces, g2_1));
	TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInBraces)"), g2_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInParentheses)"), FGuid::ParseExact(TEXT("(12345678-8765-4321-1234-567887654321)"), EGuidFormats::DigitsWithHyphensInParentheses, g2_1));
	TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::DigitsWithHyphensInParentheses)"), g2_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::HexValuesInBraces)"), FGuid::ParseExact(TEXT("{0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}}"), EGuidFormats::HexValuesInBraces, g2_1));
	TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::HexValuesInBraces)"), g2_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (EGuidFormats::UniqueObjectGuid)"), FGuid::ParseExact(TEXT("12345678-87654321-12345678-87654321"), EGuidFormats::UniqueObjectGuid, g2_1));
	TestEqual(TEXT("Parsing valid strings must succeed (EGuidFormats::UniqueObjectGuid)"), g2_1, g);

	// parsing invalid strings (exact)


	// parsing valid strings (automatic)
	FGuid g3_1;

	TestTrue(TEXT("Parsing valid strings must succeed (12345678876543211234567887654321)"), FGuid::Parse(TEXT("12345678876543211234567887654321"), g3_1));
	TestEqual(TEXT("Parsing valid strings must succeed (12345678876543211234567887654321)"), g3_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (12345678-8765-4321-1234-567887654321)"), FGuid::Parse(TEXT("12345678-8765-4321-1234-567887654321"), g3_1));
	TestEqual(TEXT("Parsing valid strings must succeed (12345678-8765-4321-1234-567887654321)"), g3_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed ({12345678-8765-4321-1234-567887654321})"), FGuid::Parse(TEXT("{12345678-8765-4321-1234-567887654321}"), g3_1));
	TestEqual(TEXT("Parsing valid strings must succeed ({12345678-8765-4321-1234-567887654321})"), g3_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed ((12345678-8765-4321-1234-567887654321))"), FGuid::Parse(TEXT("(12345678-8765-4321-1234-567887654321)"), g3_1));
	TestEqual(TEXT("Parsing valid strings must succeed ((12345678-8765-4321-1234-567887654321))"), g3_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed ({0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}})"), FGuid::Parse(TEXT("{0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}}"), g3_1));
	TestEqual(TEXT("Parsing valid strings must succeed ({0x12345678,0x8765,0x4321,{0x12,0x34,0x56,0x78,0x87,0x65,0x43,0x21}})"), g3_1, g);

	TestTrue(TEXT("Parsing valid strings must succeed (12345678-87654321-12345678-87654321)"), FGuid::Parse(TEXT("12345678-87654321-12345678-87654321"), g3_1));
	TestEqual(TEXT("Parsing valid strings must succeed (12345678-87654321-12345678-87654321)"), g3_1, g);

	//parsing invalid strings (automatic)

	// GUID validation
	FGuid g4_1 = FGuid::NewGuid();

	TestTrue(TEXT("New GUIDs must be valid"), g4_1.IsValid());
	
	g4_1.Invalidate();

	TestFalse(TEXT("Invalidated GUIDs must be invalid"), g4_1.IsValid());

	return true;
}
bool FBuildPatchChunkCache::RecycleChunkFromBuild( const FGuid& ChunkGuid )
{
	// Must never double acquire
	check( ChunkCache.Contains( ChunkGuid ) == false );

	// Debug leaving any files open
	bool bSuccess = true;

	// Get the app manifest that this chunk can be sourced from
	FBuildPatchAppManifestPtr ChunkSourceAppManifest = InstallationInfo.GetManifestContainingChunk(ChunkGuid);
	if (!ChunkSourceAppManifest.IsValid())
	{
		return false;
	}

	// Get the install directory for this manifest
	const FString ChunkSourceInstallDir = InstallationInfo.GetManifestInstallDir(ChunkSourceAppManifest);
	if(ChunkSourceInstallDir.Len() <= 0)
	{
		return false;
	}

	// We need to generate an inventory of all chunk parts in this build that refer to the chunk that we require
	TMap< FGuid, TArray< FFileChunkPart > > ChunkPartInventory;
	TArray< FGuid > Array;
	Array.Add( ChunkGuid );
	ChunkSourceAppManifest->EnumerateChunkPartInventory(Array, ChunkPartInventory);

	// Attempt construction of the chunk from the parts
	FArchive* BuildFileIn = NULL;
	FString  BuildFileOpened;
	int64 BuildFileInSize = 0;

	// We must have a hash for this chunk or else we cant verify it
	uint8 HashType = 0;
	uint64 ChunkHash = 0;
	FSHAHashData ChunkShaHash;
	if (InstallManifet->GetChunkShaHash(ChunkGuid, ChunkShaHash))
	{
		HashType = FChunkHeader::HASH_SHA1;
	}
	else if (ChunkSourceAppManifest->GetChunkHash(ChunkGuid, ChunkHash))
	{
		HashType = FChunkHeader::HASH_ROLLING;
	}
	TArray< FFileChunkPart >* FileChunkPartsPtr = ChunkPartInventory.Find( ChunkGuid );
	bSuccess = (FileChunkPartsPtr != NULL && HashType != 0);
	if( bSuccess )
	{
		const TArray< FFileChunkPart >& FileChunkParts = *FileChunkPartsPtr;
		TArray< uint8 > TempArray;
		TempArray.AddUninitialized( FBuildPatchData::ChunkDataSize );
		uint8* TempChunkConstruction = TempArray.GetData();
		FMemory::Memzero( TempChunkConstruction, FBuildPatchData::ChunkDataSize );
		bSuccess = FileChunkParts.Num() > 0;
		for( auto FileChunkPartIt = FileChunkParts.CreateConstIterator(); FileChunkPartIt && bSuccess && !FBuildPatchInstallError::HasFatalError(); ++FileChunkPartIt )
		{
			const FFileChunkPart& FileChunkPart = *FileChunkPartIt;
			FString FullFilename = ChunkSourceInstallDir / FileChunkPart.Filename;
			// Close current build file ?
			if( BuildFileIn != NULL && BuildFileOpened != FullFilename )
			{
				BuildFileIn->Close();
				delete BuildFileIn;
				BuildFileIn = NULL;
				BuildFileOpened = TEXT( "" );
				BuildFileInSize = 0;
			}
			// Open build file ?
			if( BuildFileIn == NULL )
			{
				BuildFileIn = IFileManager::Get().CreateFileReader( *FullFilename );
				bSuccess = BuildFileIn != NULL;
				if( !bSuccess )
				{
					BuildFileOpened = TEXT( "" );
					FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, FileChunkPart.Filename, FPlatformMisc::GetLastError(), TEXT( "ChunkRecycle" ), TEXT( "Source File Missing" ) );
					GWarn->Logf( TEXT( "BuildPatchChunkConstruction: Warning: Failed to load source file for chunk. %s" ), *FullFilename );
				}
				else
				{
					BuildFileOpened = FullFilename;
					BuildFileInSize = BuildFileIn->TotalSize();
				}
			}
			// Grab the section of the chunk
			if( BuildFileIn != NULL )
			{
				// Make sure we don't attempt to read off the end of the file
				const int64 LastRequiredByte = FileChunkPart.FileOffset + FileChunkPart.ChunkPart.Size;
				if( BuildFileInSize >= LastRequiredByte )
				{
					BuildFileIn->Seek( FileChunkPart.FileOffset );
					BuildFileIn->Serialize( TempChunkConstruction + FileChunkPart.ChunkPart.Offset, FileChunkPart.ChunkPart.Size );
				}
				else
				{
					bSuccess = false;
					FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, FileChunkPart.Filename, INDEX_NONE, TEXT( "ChunkRecycle" ), TEXT( "Source File Too Small" ) );
					GWarn->Logf( TEXT( "BuildPatchChunkConstruction: Warning: Source file too small for chunk position. %s" ), *FullFilename );
				}
			}
		}

		// Check no other fatal errors were registered in the meantime
		bSuccess = bSuccess && !FBuildPatchInstallError::HasFatalError();

		// Check chunk hash
		if( bSuccess )
		{
			FSHAHashData ShaHashCheck;
			switch (HashType)
			{
			case FChunkHeader::HASH_ROLLING:
				bSuccess = FRollingHash< FBuildPatchData::ChunkDataSize >::GetHashForDataSet(TempChunkConstruction) == ChunkHash;
				break;
			case FChunkHeader::HASH_SHA1:
				FSHA1::HashBuffer(TempChunkConstruction, FBuildPatchData::ChunkDataSize, ShaHashCheck.Hash);
				bSuccess = ShaHashCheck == ChunkShaHash;
				break;
			default:
				bSuccess = false;
			}
			if( !bSuccess )
			{
				FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, TEXT( "" ), INDEX_NONE, TEXT( "ChunkRecycle" ), TEXT( "Chunk Hash Fail" ) );
				GWarn->Logf( TEXT( "BuildPatchChunkConstruction: Warning: Hash check failed for recycled chunk %s" ), *ChunkGuid.ToString() );
			}
		}

		// Save the chunk to cache if all went well
		if( bSuccess )
		{
			// It was added asynchronously!!
			check( ChunkCache.Contains( ChunkGuid ) == false );

			// Create the ChunkFile data structure
			FChunkFile* NewChunkFile = new FChunkFile( GetRemainingReferenceCount( ChunkGuid ), true );

			// Lock data
			FChunkHeader* ChunkHeader;
			uint8* ChunkData;
			NewChunkFile->GetDataLock( &ChunkData, &ChunkHeader );

			// Copy the data
			FMemoryReader MemReader( TempArray );
			MemReader.Serialize( ChunkData, FBuildPatchData::ChunkDataSize );

			// Setup the header
			ChunkHeader->Guid = ChunkGuid;
			ChunkHeader->StoredAs = FChunkHeader::STORED_RAW;
			ChunkHeader->DataSize = FBuildPatchData::ChunkDataSize; // This would change if compressing/encrypting
			ChunkHeader->HashType = HashType;
			ChunkHeader->RollingHash = ChunkHash;
			ChunkHeader->SHAHash = ChunkShaHash;

			// Release data
			NewChunkFile->ReleaseDataLock();

			// Count chunk
			NumChunksRecycled.Increment();

			// Add it to our cache.
			ChunkCache.Add( ChunkGuid, NewChunkFile );
		}

		// Close any open file
		if( BuildFileIn != NULL )
		{
			BuildFileIn->Close();
			delete BuildFileIn;
			BuildFileIn = NULL;
		}
	}
	
	return bSuccess;
}
bool FBuildPatchChunkCache::ReadChunkFromDriveCache( const FGuid& ChunkGuid )
{
	bool bSuccess = true;

	// Get the chunk filename
	const FString Filename = FBuildPatchUtils::GetChunkOldFilename( ChunkCacheStage, ChunkGuid );

	// Read the chunk
	FArchive* FileReader = IFileManager::Get().CreateFileReader( *Filename );
	bSuccess = FileReader != NULL;
	if( bSuccess )
	{
		// Get file size
		const int64 FileSize = FileReader->TotalSize();

		// Create the ChunkFile data structure
		FChunkFile* NewChunkFile = new FChunkFile( GetRemainingReferenceCount( ChunkGuid ), true );

		// Lock data
		FChunkHeader* ChunkHeader;
		uint8* ChunkData;
		NewChunkFile->GetDataLock( &ChunkData, &ChunkHeader );

		// Read the header
		*FileReader << *ChunkHeader;

		// Check header magic
		bSuccess = ChunkHeader->IsValidMagic();
		if ( bSuccess )
		{
			// Check the right data size
			bSuccess = ChunkHeader->DataSize == FBuildPatchData::ChunkDataSize;
			if( bSuccess )
			{
				// Check Header and data size
				bSuccess = ( ChunkHeader->HeaderSize + ChunkHeader->DataSize ) == FileSize;
				if( bSuccess )
				{
					// Read the data
					FileReader->Serialize( ChunkData, FBuildPatchData::ChunkDataSize );
					// Verify the data hash
					FSHAHashData ShaHashCheck;
					switch (ChunkHeader->HashType)
					{
					case FChunkHeader::HASH_ROLLING:
						bSuccess = ChunkHeader->RollingHash == FRollingHash< FBuildPatchData::ChunkDataSize >::GetHashForDataSet(ChunkData);
						break;
					case FChunkHeader::HASH_SHA1:
						FSHA1::HashBuffer(ChunkData, FBuildPatchData::ChunkDataSize, ShaHashCheck.Hash);
						bSuccess = ShaHashCheck == ChunkHeader->SHAHash;
						break;
					default:
						bSuccess = false;
					}
					if( !bSuccess )
					{
						FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, Filename, INDEX_NONE, TEXT( "DriveCache" ), TEXT( "Hash Check Failed" ) );
						GLog->Logf( TEXT( "FBuildPatchChunkCache: ERROR: ReadChunkFromDriveCache chunk failed hash check %s" ), *ChunkGuid.ToString() );
					}
					else
					{
						// Count loads
						NumDriveCacheChunkLoads.Increment();
						GLog->Logf( TEXT( "FBuildPatchChunkCache: ReadChunkFromDriveCache loaded chunk %s" ), *ChunkGuid.ToString() );
					}
				}
				else
				{
					FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, Filename, INDEX_NONE, TEXT( "DriveCache" ), TEXT( "Incorrect File Size" ) );
					GLog->Logf( TEXT( "FBuildPatchChunkCache: ERROR: ReadChunkFromDriveCache header info does not match file size %s" ), *ChunkGuid.ToString() );
				}
			}
			else
			{
				FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, Filename, INDEX_NONE, TEXT( "DriveCache" ), TEXT( "Datasize/Hashtype Mismatch" ) );
				GLog->Logf( TEXT( "FBuildPatchChunkCache: ERROR: ReadChunkFromDriveCache mismatch datasize/hashtype combination %s" ), *ChunkGuid.ToString() );
			}
		}
		else
		{
			FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, Filename, INDEX_NONE, TEXT( "DriveCache" ), TEXT( "Corrupt Header" ) );
			GLog->Logf( TEXT( "FBuildPatchChunkCache: ERROR: ReadChunkFromDriveCache corrupt header %s" ), *ChunkGuid.ToString() );
		}

		// Release data
		NewChunkFile->ReleaseDataLock();

		// Add the newly filled data to the cache if successful
		if( bSuccess )
		{
			ChunkCache.Add( ChunkGuid, NewChunkFile );
		}
		// If there was a problem, remove from cache and reservation
		else
		{
			ChunkCache.Remove( ChunkGuid );
		}

		// Close the file
		FileReader->Close();
		delete FileReader;

	}
	else
	{
		FBuildPatchAnalytics::RecordChunkCacheError( ChunkGuid, Filename, FPlatformMisc::GetLastError(), TEXT( "DriveCache" ), TEXT( "Open File Fail" ) );
		GLog->Logf( TEXT( "BuildPatchServices: ERROR: GetChunkData could not open chunk file %s" ), *ChunkGuid.ToString() );
	}

	return bSuccess;
}
void FGenericCrashContext::Initialize()
{
	NCachedCrashContextProperties::bIsInternalBuild = FEngineBuildSettings::IsInternalBuild();
	NCachedCrashContextProperties::bIsPerforceBuild = FEngineBuildSettings::IsPerforceBuild();
	NCachedCrashContextProperties::bIsSourceDistribution = FEngineBuildSettings::IsSourceDistribution();
	NCachedCrashContextProperties::bIsUE4Release = FApp::IsEngineInstalled();

	NCachedCrashContextProperties::ExecutableName = FPlatformProcess::ExecutableName();
	NCachedCrashContextProperties::PlatformName = FPlatformProperties::PlatformName();
	NCachedCrashContextProperties::PlatformNameIni = FPlatformProperties::IniPlatformName();
	NCachedCrashContextProperties::BaseDir = FPlatformProcess::BaseDir();
	NCachedCrashContextProperties::RootDir = FPlatformMisc::RootDir();
	NCachedCrashContextProperties::EpicAccountId = FPlatformMisc::GetEpicAccountId();
	NCachedCrashContextProperties::MachineIdStr = FPlatformMisc::GetMachineId().ToString(EGuidFormats::Digits);
	FPlatformMisc::GetOSVersions(NCachedCrashContextProperties::OsVersion, NCachedCrashContextProperties::OsSubVersion);
	NCachedCrashContextProperties::NumberOfCores = FPlatformMisc::NumberOfCores();
	NCachedCrashContextProperties::NumberOfCoresIncludingHyperthreads = FPlatformMisc::NumberOfCoresIncludingHyperthreads();

	NCachedCrashContextProperties::CPUVendor = FPlatformMisc::GetCPUVendor();
	NCachedCrashContextProperties::CPUBrand = FPlatformMisc::GetCPUBrand();
	NCachedCrashContextProperties::PrimaryGPUBrand = FPlatformMisc::GetPrimaryGPUBrand();
	NCachedCrashContextProperties::UserName = FPlatformProcess::UserName();
	NCachedCrashContextProperties::DefaultLocale = FPlatformMisc::GetDefaultLocale();

	// Using the -fullcrashdump parameter will cause full memory minidumps to be created for crashes
	NCachedCrashContextProperties::CrashDumpMode = (int32)ECrashDumpMode::Default;
	if (FCommandLine::IsInitialized())
	{
		const TCHAR* CmdLine = FCommandLine::Get();
		if (FParse::Param( CmdLine, TEXT("fullcrashdump") ))
		{
			NCachedCrashContextProperties::CrashDumpMode = (int32)ECrashDumpMode::FullDump;
		}
	}

	const FGuid Guid = FGuid::NewGuid();
	NCachedCrashContextProperties::CrashGUID = FString::Printf(TEXT("UE4CC-%s-%s"), *NCachedCrashContextProperties::PlatformNameIni, *Guid.ToString(EGuidFormats::Digits));

	bIsInitialized = true;
}