// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using EpicGames.UBA.Impl;
namespace EpicGames.UBA
{
///
/// Information needed to create a session server
///
/// Root directory to store content addressable data
/// Path to a trace file that records the build
/// If the custom allocator should be disabled
/// If the visualizer should be launched
/// If the content addressable storage should be reset
/// If intermediate/output files should be written to disk
/// More detailed trace information
/// Wait for memory before starting new processes
/// Kill processes when close to run out of memory
/// Store .obj files compressed on disk
public readonly struct SessionServerCreateInfo(string rootDirectory, string traceOutputFile, bool disableCustomAllocator, bool launchVisualizer, bool resetCas, bool writeToDisk, bool detailedTrace, bool allowWaitOnMem, bool allowKillOnMem, bool storeObjFilesCompressed)
{
///
/// Root directory to store content addressable data
///
public string RootDirectory { get; } = rootDirectory;
///
/// Path to a trace file that records the build
///
public string TraceOutputFile { get; } = traceOutputFile;
///
/// If the custom allocator should be disabled
///
public bool DisableCustomAllocator { get; } = disableCustomAllocator;
///
/// If the visualizer should be launched
///
public bool LaunchVisualizer { get; } = launchVisualizer;
///
/// If the content addressable storage should be reset
///
public bool ResetCas { get; } = resetCas;
///
/// If intermediate/output files should be written to disk
///
public bool WriteToDisk { get; } = writeToDisk;
///
/// More detailed trace information
///
public bool DetailedTrace { get; } = detailedTrace;
///
/// Wait for memory before starting new processes
///
public bool AllowWaitOnMem { get; } = allowWaitOnMem;
///
/// Kill processes when close to run out of memory
///
public bool AllowKillOnMem { get; } = allowKillOnMem;
///
/// Store .obj files compressed on disk
///
public bool StoreObjFilesCompressed { get; } = storeObjFilesCompressed;
}
///
/// Base interface for session server create info
///
public interface ISessionServerCreateInfo : IBaseInterface
{
///
/// Create a ISessionServerCreateInfo object
///
/// The storage server
/// The client
/// The logger
/// The session create info
/// The ISessionServerCreateInfo
public static ISessionServerCreateInfo CreateSessionServerCreateInfo(IStorageServer storage, IServer client, ILogger logger, SessionServerCreateInfo info)
{
return new SessionServerCreateInfoImpl(storage, client, logger, info);
}
}
///
/// Event args for remote process slot available event
///
/// Is true if the available remote process slot is on a cross architecture machine
public class RemoteProcessSlotAvailableEventArgs(bool isCrossArchitecture) : EventArgs
{
///
/// Is true if the available remote process slot is on a cross architecture machine
///
public bool IsCrossArchitecture { get; } = isCrossArchitecture;
}
///
/// Event args for remote process returned event
///
/// The process being returned
public class RemoteProcessReturnedEventArgs(IProcess process) : EventArgs
{
///
/// The remote process that was returned
///
public IProcess Process { get; } = process;
}
///
/// Base interface for a session server instance
///
public interface ISessionServer : IBaseInterface
{
///
/// Degeate for remote process slot available events
///
/// The sender object
/// The event args
public delegate void RemoteProcessSlotAvailableEventHandler(object sender, RemoteProcessSlotAvailableEventArgs e);
///
/// Degeate for remote process returned events
///
/// The sender object
/// The event args
public delegate void RemoteProcessReturnedEventHandler(object sender, RemoteProcessReturnedEventArgs e);
///
/// Remote process slot available event handler
///
public abstract event RemoteProcessSlotAvailableEventHandler? RemoteProcessSlotAvailable;
///
/// Remote process returned event handler
///
public abstract event RemoteProcessReturnedEventHandler? RemoteProcessReturned;
///
/// Will tell all remote machines that they can disconnect once their active processes are done
/// Will also stop listening for new remote machines
///
public abstract void DisableRemoteExecution();
///
/// Set max number of processes that can be executed remotely.
/// Setting this can let the backend disconnect remote workers earlier
///
public abstract void SetMaxRemoteProcessCount(uint count);
///
/// Run a local process
///
/// Process start info
/// If the process should be run async
/// Optional callback when the process exits
/// Should be true unless process does not work being detoured (And in that case we need to manually register file system changes)
/// The process being run
public abstract IProcess RunProcess(ProcessStartInfo info, bool async, IProcess.ExitedEventHandler? exitedEventHandler, bool enableDetour);
///
/// Run a remote process
///
/// Process start info
/// Optional callback when the process exits
/// Number of cores this process uses
/// Optionally contains input that we know process will need. Memory block containing zero-terminated strings with an extra termination in the end.
/// Number of strings in known inputs
/// True means that this process can run on a different architecture and expects a mapping to exist
/// The remote process being run
public abstract IProcess RunProcessRemote(ProcessStartInfo info, IProcess.ExitedEventHandler? exitedEventHandler, double weight = 1.0, byte[]? knownInputs = null, uint knownInputsCount = 0, bool canExecuteCrossArchitecture = false);
///
/// Register roots data and get handle back
///
/// Buffer containing roots used for cache and vfs. Format is multiples of byte/utf8string/utf8string. rootindex/vfspath/localpath
/// Size of buffer in bytes
/// The remote process being run
public abstract ulong RegisterRoots(byte[] rootsData, uint rootsDataSize);
///
/// Refresh cached information about directories
///
/// The directories to refresh
public abstract void RefreshDirectories(params string[] directories);
///
/// Registers external files write to session caches
///
/// The files to register
public abstract void RegisterNewFiles(params string[] files);
///
/// Registers virtual files that are part of other files (mapped into sections of existing file)
///
/// Name of the virtual file
/// Name of the source file
/// Offset inside the source file
/// Size of the segment inside the source file
public abstract bool RegisterVirtualFile(string name, string sourceFile, ulong sourceOffset, ulong sourceSize);
///
/// Registers the start of an external process
///
/// The description of the process
/// The process id that should be sent into EndExternalProcess
public abstract uint BeginExternalProcess(string description);
///
/// Registers the end of an external process
///
/// The id returned by BeginExternalProcess
/// The exit code of the external process
public abstract void EndExternalProcess(uint id, uint exitCode);
///
/// Writes external status to the uba trace stream which can then be visualized by ubavisualizer
///
/// Total processes in session
/// Processes done in session
/// Number of errors in session
public abstract void UpdateProgress(uint processesTotal, uint processesDone, uint errorCount);
///
/// Writes external status to the uba trace stream which can then be visualized by ubavisualizer
///
/// Row of status text. Reuse one index to show one line in visualizer
/// The identation of status name that will be shown in visualizer
/// The status text that will be shown in visualizer
/// The status type
/// Optional hyperlink that can be used to make text clickable in visualizer
public abstract void UpdateStatus(uint statusRow, uint statusColumn, string statusText, LogEntryType statusType, string? statusLink = null);
///
/// Set a custom cas key for a process's tracked inputs
///
/// The file to track
/// The working directory
/// The process to get tracked inputs from
public abstract void SetCustomCasKeyFromTrackedInputs(string file, string workingDirectory, IProcess process);
///
/// Cancel all processes
///
public abstract void CancelAll();
///
/// Print summary information to the logger
///
public abstract void PrintSummary();
///
/// Create a ISessionServer object
///
/// The session server create info
/// The ISessionServer
public static ISessionServer CreateSessionServer(ISessionServerCreateInfo info)
{
return new SessionServerImpl(info);
}
}
}