void FMessageRouter::FilterSubscriptions( TArray<IMessageSubscriptionPtr>& Subscriptions, const IMessageContextRef& Context, TArray<IReceiveMessagesPtr>& OutRecipients ) { EMessageScope MessageScope = Context->GetScope(); for (int32 SubscriptionIndex = 0; SubscriptionIndex < Subscriptions.Num(); ++SubscriptionIndex) { const IMessageSubscriptionPtr& Subscription = Subscriptions[SubscriptionIndex]; if (Subscription->IsEnabled() && Subscription->GetScopeRange().Contains(MessageScope)) { IReceiveMessagesPtr Subscriber = Subscription->GetSubscriber().Pin(); if (Subscriber.IsValid()) { if (MessageScope == EMessageScope::Thread) { ENamedThreads::Type RecipientThread = Subscriber->GetRecipientThread(); ENamedThreads::Type SenderThread = Context->GetSenderThread(); if (RecipientThread != SenderThread) { continue; } } OutRecipients.AddUnique(Subscriber); } else { Subscriptions.RemoveAtSwap(SubscriptionIndex); --SubscriptionIndex; } } } }
void FMessageRouter::DispatchMessage( const IMessageContextRef& Context ) { if (Context->IsValid()) { TArray<IReceiveMessagesPtr> Recipients; // get recipients, either from the context... const TArray<FMessageAddress>& RecipientList = Context->GetRecipients(); if (RecipientList.Num() > 0) { for (int32 Index = 0; Index < RecipientList.Num(); Index++) { IReceiveMessagesPtr Recipient = ActiveRecipients.FindRef(RecipientList[Index]).Pin(); if (Recipient.IsValid()) { Recipients.AddUnique(Recipient); } else { ActiveRecipients.Remove(RecipientList[Index]); } } } // ... or from subscriptions else { FilterSubscriptions(ActiveSubscriptions.FindOrAdd(Context->GetMessageType()), Context, Recipients); FilterSubscriptions(ActiveSubscriptions.FindOrAdd(NAME_All), Context, Recipients); } // dispatch the message for (int32 RecipientIndex = 0; RecipientIndex < Recipients.Num(); RecipientIndex++) { IReceiveMessagesPtr Recipient = Recipients[RecipientIndex]; ENamedThreads::Type RecipientThread = Recipient->GetRecipientThread(); if (RecipientThread == ENamedThreads::AnyThread) { Tracer->TraceDispatchedMessage(Context, Recipient.ToSharedRef(), false); Recipient->ReceiveMessage(Context); Tracer->TraceHandledMessage(Context, Recipient.ToSharedRef()); } else { TGraphTask<FMessageDispatchTask>::CreateTask().ConstructAndDispatchWhenReady(RecipientThread, Context, Recipient, Tracer); } } } }
void FMessageTracer::TraceSentMessage(const IMessageContextRef& Context) { if (!Running) { return; } double Timestamp = FPlatformTime::Seconds(); Traces.Enqueue([=]() { // look up endpoint info FMessageTracerEndpointInfoPtr EndpointInfo = AddressesToEndpointInfos.FindRef(Context->GetSender()); if (!EndpointInfo.IsValid()) { return; } // create message info FMessageTracerMessageInfoRef MessageInfo = MakeShareable(new FMessageTracerMessageInfo()); { MessageInfo->Context = Context; MessageInfo->Intercepted = false; MessageInfo->SenderInfo = EndpointInfo; MessageInfo->TimeRouted = 0.0; MessageInfo->TimeSent = Timestamp; MessageInfos.Add(Context, MessageInfo); } // add message type FMessageTracerTypeInfoPtr& TypeInfo = MessageTypes.FindOrAdd(Context->GetMessageType()); if (!TypeInfo.IsValid()) { TypeInfo = MakeShareable(new FMessageTracerTypeInfo()); TypeInfo->TypeName = Context->GetMessageType(); TypeAddedDelegate.Broadcast(TypeInfo.ToSharedRef()); } TypeInfo->Messages.Add(MessageInfo); // update database EndpointInfo->SentMessages.Add(MessageInfo); MessageInfo->TypeInfo = TypeInfo; MessagesAddedDelegate.Broadcast(MessageInfo); }); }
void FEngineService::HandleTerminateMessage( const FEngineServiceTerminate& Message, const IMessageContextRef& Context ) { if (AuthorizedUsers.Contains(Message.UserName)) { if (GEngine != NULL) { UE_LOG(LogEngineService, Log, TEXT("%s terminated this instance remotely."), *Message.UserName); if (GEngine->IsEditor()) { GEngine->Exec( NULL, TEXT("QUIT_EDITOR"), *GLog); } else { GEngine->Exec( NULL, TEXT("QUIT"), *GLog); } } else { SendNotification(TEXT("Termination failed because the Engine has not started up yet or is unavailable."), Context->GetSender()); } } else { SendNotification(TEXT("You are not authorized to terminate this instance."), Context->GetSender()); } }
void FMessageRouter::HandleRouteMessage( IMessageContextRef Context ) { // intercept routing TArray<IMessageInterceptorPtr>& Interceptors = ActiveInterceptors.FindOrAdd(Context->GetMessageType()); for (TArray<IMessageInterceptorPtr>::TIterator It(Interceptors); It; ++It) { if ((*It)->InterceptMessage(Context)) { Tracer->TraceInterceptedMessage(Context, It->ToSharedRef()); return; } } // dispatch the message // @todo gmp: implement time synchronization between networked message endpoints if (false) //(Context->GetTimeSent() > CurrentTime) { DelayedMessages.HeapPush(FDelayedMessage(Context, ++DelayedMessagesSequence)); } else { DispatchMessage(Context); } Tracer->TraceRoutedMessage(Context); }
void FSessionInfo::UpdateFromMessage( const FSessionServicePong& Message, const IMessageContextRef& Context ) { if (Message.SessionId != SessionId) { return; } // update session info Standalone = Message.Standalone; SessionOwner = Message.SessionOwner; SessionName = Message.SessionName; // update instance TSharedPtr<FSessionInstanceInfo>& Instance = Instances.FindOrAdd(Context->GetSender()); if (Instance.IsValid()) { Instance->UpdateFromMessage(Message, Context); } else { IMessageBusPtr MessageBus = MessageBusPtr.Pin(); if (MessageBus.IsValid()) { Instance = MakeShareable(new FSessionInstanceInfo(Message.InstanceId, AsShared(), MessageBus.ToSharedRef())); Instance->OnLogReceived().AddSP(this, &FSessionInfo::HandleLogReceived); Instance->UpdateFromMessage(Message, Context); InstanceDiscoveredEvent.Broadcast(AsShared(), Instance.ToSharedRef()); } } LastUpdateTime = FDateTime::UtcNow(); }
void FSessionService::SendPong(const IMessageContextRef& Context, const FString& UserName) { if (!MessageEndpoint.IsValid()) { return; } FSessionServicePong* Message = new FSessionServicePong(); { Message->Authorized = FApp::IsAuthorizedUser(UserName); Message->BuildDate = FApp::GetBuildDate(); Message->DeviceName = FPlatformProcess::ComputerName(); Message->InstanceId = FApp::GetInstanceId(); Message->InstanceName = FApp::GetInstanceName(); #if PLATFORM_DESKTOP Message->IsConsoleBuild = false; #else Message->IsConsoleBuild = true; #endif Message->PlatformName = FPlatformProperties::PlatformName(); Message->SessionId = FApp::GetSessionId(); Message->SessionName = FApp::GetSessionName(); Message->SessionOwner = FApp::GetSessionOwner(); Message->Standalone = FApp::IsStandalone(); } MessageEndpoint->Send(Message, Context->GetSender()); }
void FTargetDeviceProxy::UpdateFromMessage( const FTargetDeviceServicePong& Message, const IMessageContextRef& Context ) { if (Message.DeviceID == Id) { MessageAddress = Context->GetSender(); Connected = Message.Connected; HostName = Message.HostName; HostUser = Message.HostUser; Id = Message.DeviceID; Make = Message.Make; Model = Message.Model; Name = Message.Name; DeviceUser = Message.DeviceUser; DeviceUserPassword = Message.DeviceUserPassword; Platform = Message.PlatformName; Shared = Message.Shared; SupportsMultiLaunch = Message.SupportsMultiLaunch; SupportsPowerOff = Message.SupportsPowerOff; SupportsPowerOn = Message.SupportsPowerOn; SupportsReboot = Message.SupportsReboot; LastUpdateTime = FDateTime::UtcNow(); } }
void FIOSTargetPlatform::HandlePongMessage( const FIOSLaunchDaemonPong& Message, const IMessageContextRef& Context ) { FTargetDeviceId DeviceId; FTargetDeviceId::Parse(Message.DeviceID, DeviceId); FIOSTargetDevicePtr& Device = Devices.FindOrAdd(DeviceId); if (!Device.IsValid()) { Device = MakeShareable(new FIOSTargetDevice(*this)); Device->SetFeature(ETargetDeviceFeatures::Reboot, Message.bCanReboot); Device->SetFeature(ETargetDeviceFeatures::PowerOn, Message.bCanPowerOn); Device->SetFeature(ETargetDeviceFeatures::PowerOff, Message.bCanPowerOff); Device->SetDeviceId(DeviceId); Device->SetDeviceName(Message.DeviceName); Device->SetDeviceType(Message.DeviceType); Device->SetDeviceEndpoint(Context->GetSender()); Device->SetIsSimulated(Message.DeviceID.Contains(TEXT("Simulator"))); DeviceDiscoveredEvent.Broadcast(Device.ToSharedRef()); } Device->LastPinged = FDateTime::UtcNow(); }
void FAutomationWorkerModule::HandleFindWorkersMessage(const FAutomationWorkerFindWorkers& Message, const IMessageContextRef& Context) { // Set the Instance name to be the same as the session browser. This information should be shared at some point if ((Message.SessionId == FApp::GetSessionId()) && (Message.Changelist == 10000)) { TestRequesterAddress = Context->GetSender(); #if WITH_EDITOR //If the asset registry is loading assets then we'll wait for it to stop before running our automation tests. FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry"); if (AssetRegistryModule.Get().IsLoadingAssets()) { if (!AssetRegistryModule.Get().OnFilesLoaded().IsBoundToObject(this)) { AssetRegistryModule.Get().OnFilesLoaded().AddRaw(this, &FAutomationWorkerModule::SendWorkerFound); GLog->Logf(ELogVerbosity::Log, TEXT("...Forcing Asset Registry Load For Automation")); } } else #endif { //If the registry is not loading then we'll just go ahead and run our tests. SendWorkerFound(); } } }
void FAutomationWorkerModule::HandleRequestTestsMessage( const FAutomationWorkerRequestTests& Message, const IMessageContextRef& Context ) { FAutomationTestFramework::GetInstance().SetDeveloperDirectoryIncluded(Message.DeveloperDirectoryIncluded); FAutomationTestFramework::GetInstance().SetVisualCommandletFilter(Message.VisualCommandletFilterOn); FAutomationTestFramework::GetInstance().GetValidTestNames( TestInfo ); SendTests(Context->GetSender()); }
void FAutomationWorkerModule::HandleRequestTestsMessage( const FAutomationWorkerRequestTests& Message, const IMessageContextRef& Context ) { FAutomationTestFramework::Get().LoadTestModules(); FAutomationTestFramework::Get().SetDeveloperDirectoryIncluded(Message.DeveloperDirectoryIncluded); FAutomationTestFramework::Get().SetRequestedTestFilter(Message.RequestedTestFlags); FAutomationTestFramework::Get().GetValidTestNames( TestInfo ); SendTests(Context->GetSender()); }
void FAutomationControllerManager::HandleFindWorkersResponseMessage( const FAutomationWorkerFindWorkersResponse& Message, const IMessageContextRef& Context ) { if (Message.SessionId == ActiveSessionId) { DeviceClusterManager.AddDeviceFromMessage(Context->GetSender(), Message, DeviceGroupFlags); } RequestTests(); SetControllerStatus( EAutomationControllerModuleState::Ready ); }
void FSessionInstanceInfo::UpdateFromMessage( const FSessionServicePong& Message, const IMessageContextRef& Context ) { if (Message.InstanceId != InstanceId) { return; } if (MessageEndpoint.IsValid() && (ApplicationAddress != Context->GetSender())) { MessageEndpoint->Send(new FSessionServiceLogSubscribe(), Context->GetSender()); } ApplicationAddress = Context->GetSender(); BuildDate = Message.BuildDate; DeviceName = Message.DeviceName; InstanceName = Message.InstanceName; IsConsoleBuild = Message.IsConsoleBuild; PlatformName = Message.PlatformName; LastUpdateTime = FDateTime::UtcNow(); }
void FMessageBridge::ReceiveMessage( const IMessageContextRef& Context ) { if (!Enabled) { return; } // get remote nodes TArray<FGuid> RemoteNodes; if (Context->GetRecipients().Num() > 0) { RemoteNodes = AddressBook.GetNodesFor(Context->GetRecipients()); if (RemoteNodes.Num() == 0) { return; } } // forward message to remote nodes Transport->TransportMessage(Context, RemoteNodes); }
void FWidgetSnapshotService::HandleWidgetSnapshotRequestMessage(const FWidgetSnapshotRequest& Message, const IMessageContextRef& Context) { if (MessageEndpoint.IsValid() && Message.TargetInstanceId == FApp::GetInstanceId()) { FWidgetSnapshotData SnapshotData; SnapshotData.TakeSnapshot(); FWidgetSnapshotResponse* WidgetSnapshotResponse = new FWidgetSnapshotResponse; WidgetSnapshotResponse->SnapshotRequestId = Message.SnapshotRequestId; SnapshotData.SaveSnapshotToBuffer(WidgetSnapshotResponse->SnapshotData); MessageEndpoint->Send(WidgetSnapshotResponse, Context->GetSender()); } }
void FSessionInstanceInfo::UpdateFromMessage( const FEngineServicePong& Message, const IMessageContextRef& Context ) { if (Message.InstanceId != InstanceId) { return; } CurrentLevel = Message.CurrentLevel; EngineAddress = Context->GetSender(); EngineVersion = Message.EngineVersion; HasBegunPlay = Message.HasBegunPlay; WorldTimeSeconds = Message.WorldTimeSeconds; InstanceType = Message.InstanceType; }
void FAutomationWorkerModule::HandleRunTestsMessage( const FAutomationWorkerRunTests& Message, const IMessageContextRef& Context ) { ExecutionCount = Message.ExecutionCount; TestName = Message.TestName; TestRequesterGUID = Context->GetSender(); // Always allow the first network command to execute bExecuteNextNetworkCommand = true; // We are not executing network command sub-commands right now bExecutingNetworkCommandResults = false; FAutomationTestFramework::GetInstance().StartTestByName(Message.TestName, Message.RoleIndex); }
void FMessageBridge::HandleTransportMessageReceived( const IMessageContextRef& Context, const FGuid& NodeId ) { if (!Enabled || !Bus.IsValid()) { return; } // discard expired messages if (Context->GetExpiration() < FDateTime::UtcNow()) { return; } // register newly discovered endpoints if (!AddressBook.Contains(Context->GetSender())) { AddressBook.Add(Context->GetSender(), NodeId); Bus->Register(Context->GetSender(), AsShared()); } // forward message to local bus Bus->Forward(Context, Context->GetRecipients(), FTimespan::Zero(), AsShared()); }
void FMessageTracer::ProcessSentMessage( IMessageContextRef Context, double TimeSeconds ) { FMessageTracerEndpointInfoPtr EndpointInfo = AddressesToEndpointInfos.FindRef(Context->GetSender()); if (!EndpointInfo.IsValid()) { return; } // create message info FMessageTracerMessageInfoRef MessageInfo = MakeShareable(new FMessageTracerMessageInfo()); MessageInfo->Context = Context; MessageInfo->SenderInfo = EndpointInfo; MessageInfo->TimeRouted = 0.0; MessageInfo->TimeSent = TimeSeconds; MessageInfos.Add(Context, MessageInfo); // add message type FMessageTracerTypeInfoPtr& TypeInfo = MessageTypes.FindOrAdd(Context->GetMessageType()); if (!TypeInfo.IsValid()) { TypeInfo = MakeShareable(new FMessageTracerTypeInfo()); TypeInfo->TypeName = Context->GetMessageType(); TypeAddedDelegate.Broadcast(TypeInfo.ToSharedRef()); } TypeInfo->Messages.Add(MessageInfo); // update database EndpointInfo->SentMessages.Add(MessageInfo); MessageInfo->TypeInfo = TypeInfo; MessagesAddedDelegate.Broadcast(MessageInfo); }
void FMessageBridge::ReceiveMessage( const IMessageContextRef& Context ) { if (!Enabled) { return; } TArray<FGuid> TransportNodes; if (Context->GetRecipients().Num() > 0) { TransportNodes = AddressBook.GetNodesFor(Context->GetRecipients()); if (TransportNodes.Num() == 0) { return; } } // forward message to transport nodes FMessageDataRef MessageData = MakeShareable(new FMessageData()); TGraphTask<FMessageSerializeTask>::CreateTask().ConstructAndDispatchWhenReady(Context, MessageData, Serializer.ToSharedRef()); Transport->TransportMessage(MessageData, Context->GetAttachment(), TransportNodes); }
void FProfilerClientManager::HandleServiceAuthorizeMessage( const FProfilerServiceAuthorize& Message, const IMessageContextRef& Context ) { #if STATS if (ActiveSessionId == Message.SessionId && PendingInstances.Contains(Message.InstanceId)) { PendingInstances.Remove(Message.InstanceId); FServiceConnection& Connection = Connections.FindOrAdd(Message.InstanceId); Connection.ServiceAddress = Context->GetSender(); Connection.InstanceId = Message.InstanceId; Connection.CurrentData.Frame = 0; } // Fire the client connection event ProfilerClientConnectedDelegate.Broadcast(ActiveSessionId, Message.InstanceId); #endif }
void FLaunchDaemonMessageHandler::HandlePingMessage(const FIOSLaunchDaemonPing& Message, const IMessageContextRef& Context) { if (MessageEndpoint.IsValid()) { FMessageAddress MessageSender = Context->GetSender(); MessageEndpoint->Send(new FIOSLaunchDaemonPong(FString(FPlatformProperties::PlatformName()) + (TARGET_IPHONE_SIMULATOR ? FString(TEXT("Simulator:")) : FString(TEXT("@"))) + FString(FPlatformProcess::ComputerName()) , FPlatformProcess::ComputerName() , "ULD_Ready" , UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone? "Phone" : "Tablet" , false , false , false ), MessageSender); } }
void FAutomationWorkerModule::HandleRunTestsMessage( const FAutomationWorkerRunTests& Message, const IMessageContextRef& Context ) { ExecutionCount = Message.ExecutionCount; TestName = Message.TestName; BeautifiedTestName = Message.BeautifiedTestName; bSendAnalytics = Message.bSendAnalytics; TestRequesterAddress = Context->GetSender(); FAutomationTestFramework::Get().SetScreenshotOptions(Message.bScreenshotsEnabled); // Always allow the first network command to execute bExecuteNextNetworkCommand = true; // We are not executing network command sub-commands right now bExecutingNetworkCommandResults = false; FAutomationTestFramework::Get().StartTestByName(Message.TestName, Message.RoleIndex); }
void FEngineService::HandleExecuteCommandMessage( const FEngineServiceExecuteCommand& Message, const IMessageContextRef& Context ) { if (AuthorizedUsers.Contains(Message.UserName)) { if (GEngine != NULL) { GEngine->DeferredCommands.Add(Message.Command); UE_LOG(LogEngineService, Log, TEXT("%s executed the remote command: %s"), *Message.UserName, *Message.Command); } else { SendNotification(TEXT("The command could not be executed because the Engine has not started up yet."), Context->GetSender()); } } else { SendNotification(TEXT("You are not authorized to execute console commands."), Context->GetSender()); } }
void FServiceConnection::Initialize( const FProfilerServiceAuthorize2& Message, const IMessageContextRef& Context ) { #if STATS ServiceAddress = Context->GetSender(); InstanceId = Message.InstanceId; CurrentData.Frame = 0; // add the supplied meta data FArrayReader ArrayReader(true); ArrayReader.Append(Message.Data); MetaData.CriticalSection = &CriticalSection; int64 Size = ArrayReader.TotalSize(); // read in the magic, at some point may need to know what it actually is uint32 Magic = 0; ArrayReader << Magic; // read in the data TArray<FStatMessage> StatMessages; { SCOPE_CYCLE_COUNTER(STAT_PC_ReadStatMessages); while(ArrayReader.Tell() < Size) { // read the message new (StatMessages) FStatMessage(Stream.ReadMessage(ArrayReader)); } static FStatNameAndInfo Adv(NAME_AdvanceFrame, "", TEXT(""), EStatDataType::ST_int64, true, false); new (StatMessages) FStatMessage(Adv.GetEncodedName(), EStatOperation::AdvanceFrameEventGameThread, 1LL, false); } // generate a thread state from the data { SCOPE_CYCLE_COUNTER(STAT_PC_AddStatMessages); CurrentThreadState.AddMessages(StatMessages); } UpdateMetaData(); #endif }
void FAutomationControllerManager::HandleRequestNextNetworkCommandMessage( const FAutomationWorkerRequestNextNetworkCommand& Message, const IMessageContextRef& Context ) { // Harvest iteration of running the tests this result came from (stops stale results from being committed to subsequent runs) if (Message.ExecutionCount == ExecutionCount) { // Find the device id for the address int32 ClusterIndex; int32 DeviceIndex; verify(DeviceClusterManager.FindDevice(Context->GetSender(), ClusterIndex, DeviceIndex)); // Verify this device thought it was busy TSharedPtr <IAutomationReport> Report = DeviceClusterManager.GetTest(ClusterIndex, DeviceIndex); check (Report.IsValid()); // Increment network command responses bool bAllResponsesReceived = Report->IncrementNetworkCommandResponses(); // Test if we've accumulated all responses AND this was the result for the round of test running AND we're still running tests if (bAllResponsesReceived && (ClusterDistributionMask & (1<<ClusterIndex))) { // Reset the counter Report->ResetNetworkCommandResponses(); // For every device in this networked test TArray<FMessageAddress> DeviceAddresses = DeviceClusterManager.GetDevicesReservedForTest(ClusterIndex, Report); check (DeviceAddresses.Num() == Report->GetNumParticipantsRequired()); // Send it to each device for (int32 AddressIndex = 0; AddressIndex < DeviceAddresses.Num(); ++AddressIndex) { //send "next command message" to worker MessageEndpoint->Send(new FAutomationWorkerNextNetworkCommandReply(), DeviceAddresses[AddressIndex]); } } } }
void FEngineService::SendPong( const IMessageContextRef& Context ) { if (MessageEndpoint.IsValid()) { FEngineServicePong* Message = new FEngineServicePong(); Message->EngineVersion = GEngineNetVersion; Message->InstanceId = FApp::GetInstanceId(); Message->SessionId = FApp::GetSessionId(); if (GEngine == NULL) { Message->InstanceType = TEXT("Unknown"); } else if (IsRunningDedicatedServer()) { Message->InstanceType = TEXT("Server"); } else if (IsRunningCommandlet()) { Message->InstanceType = TEXT("Commandlet"); } else if (GEngine->IsEditor()) { Message->InstanceType = TEXT("Editor"); } else if ( IsRunningGame() ) { Message->InstanceType = TEXT("Game"); } else { Message->InstanceType = TEXT("Other"); } FWorldContext const* ContextToUse = NULL; // TODO: Should we be iterating here and sending a message for each context? // We're going to look through the WorldContexts and pull any Game context we find // If there isn't a Game context, we'll take the first PIE we find // and if none of those we'll use an Editor for (const FWorldContext& WorldContext : GEngine->GetWorldContexts()) { if (WorldContext.WorldType == EWorldType::Game) { ContextToUse = &WorldContext; break; } else if (WorldContext.WorldType == EWorldType::PIE && (ContextToUse == NULL || ContextToUse->WorldType != EWorldType::PIE)) { ContextToUse = &WorldContext; } else if (WorldContext.WorldType == EWorldType::Editor && ContextToUse == NULL) { ContextToUse = &WorldContext; } } if (ContextToUse != NULL && ContextToUse->World() != NULL) { Message->CurrentLevel = ContextToUse->World()->GetMapName(); Message->HasBegunPlay = ContextToUse->World()->HasBegunPlay(); Message->WorldTimeSeconds = ContextToUse->World()->TimeSeconds; } MessageEndpoint->Send(Message, Context->GetSender()); } }
void FProfilerClientManager::HandleServiceFileChunk( const FProfilerServiceFileChunk& FileChunk, const IMessageContextRef& Context ) { #if STATS const TCHAR* StrTmp = TEXT(".tmp"); // Read file chunk header. FMemoryReader Reader(FileChunk.Header); FProfilerFileChunkHeader FileChunkHeader; Reader << FileChunkHeader; FileChunkHeader.Validate(); const bool bValidFileChunk = !FailedTransfer.Contains( FileChunk.Filename ); // @TODO yrx 2014-03-24 At this moment received file chunks are handled on the main thread, asynchronous file receiving is planned for the future release. if (ActiveSessionId.IsValid() && Connections.Find(FileChunk.InstanceId) != nullptr && bValidFileChunk) { FReceivedFileInfo* ReceivedFileInfo = ActiveTransfers.Find( FileChunk.Filename ); if( !ReceivedFileInfo ) { const FString PathName = FPaths::ProfilingDir() + TEXT("UnrealStats/Received/"); const FString StatFilepath = PathName + FileChunk.Filename + StrTmp; UE_LOG(LogProfile, Log, TEXT( "Opening stats file for service-client sending: %s" ), *StatFilepath ); FArchive* FileWriter = IFileManager::Get().CreateFileWriter(*StatFilepath); if( !FileWriter ) { UE_LOG(LogProfile, Error, TEXT( "Could not open: %s" ), *StatFilepath ); return; } ReceivedFileInfo = &ActiveTransfers.Add( FileChunk.Filename, FReceivedFileInfo(FileWriter,0,StatFilepath) ); ProfilerFileTransferDelegate.Broadcast( FileChunk.Filename, ReceivedFileInfo->Progress, FileChunkHeader.FileSize ); } const bool bSimulateBadFileChunk = true;//FMath::Rand() % 10 != 0; const bool bSuccess = CheckHashAndWrite( FileChunk, FileChunkHeader, ReceivedFileInfo->FileWriter ) && bSimulateBadFileChunk; if( bSuccess ) { ReceivedFileInfo->Progress += FileChunkHeader.ChunkSize; ReceivedFileInfo->Update(); if( ReceivedFileInfo->Progress == FileChunkHeader.FileSize ) { // File has been successfully sent, so send this information to the profiler service. if( MessageEndpoint.IsValid() ) { MessageEndpoint->Send( new FProfilerServiceFileChunk( FGuid(),FileChunk.Filename,FProfilerFileChunkHeader(0,0,0,EProfilerFileChunkType::FinalizeFile).AsArray() ), Context->GetSender() ); ProfilerFileTransferDelegate.Broadcast( FileChunk.Filename, ReceivedFileInfo->Progress, FileChunkHeader.FileSize ); } // Delete the file writer. delete ReceivedFileInfo->FileWriter; ReceivedFileInfo->FileWriter = nullptr; // Rename the stats file. IFileManager::Get().Move( *ReceivedFileInfo->DestFilepath.Replace( StrTmp, TEXT("") ), *ReceivedFileInfo->DestFilepath ); ActiveTransfers.Remove( FileChunk.Filename ); UE_LOG(LogProfile, Log, TEXT( "File service-client received successfully: %s" ), *FileChunk.Filename ); } else { ProfilerFileTransferDelegate.Broadcast( FileChunk.Filename, ReceivedFileInfo->Progress, FileChunkHeader.FileSize ); } } else { // This chunk is a bad chunk, so ask for resending it. if( MessageEndpoint.IsValid() ) { MessageEndpoint->Send( new FProfilerServiceFileChunk(FileChunk,FProfilerServiceFileChunk::FNullTag()), Context->GetSender() ); UE_LOG(LogProfile, Log, TEXT("Received a bad chunk of file, resending: %5i, %6u, %10u, %s"), FileChunk.Data.Num(), ReceivedFileInfo->Progress, FileChunkHeader.FileSize, *FileChunk.Filename ); } } } #endif }
void FSessionService::HandleSessionLogUnsubscribeMessage(const FSessionServiceLogUnsubscribe& Message, const IMessageContextRef& Context) { FScopeLock Lock(&LogSubscribersLock); LogSubscribers.Remove(Context->GetSender()); }