Exemplo n.º 1
0
        /// <inheritdoc />
        public IChatTrackingContext CreateTrackingContext()
        {
            if (customCommandHandler == null)
            {
                throw new InvalidOperationException("RegisterCommandHandler() hasn't been called!");
            }

            IChatTrackingContext context = null;

            lock (mappedChannels)
                context = new ChatTrackingContext(
                    customCommandHandler,
                    mappedChannels.Select(y => y.Value.Channel),
                    loggerFactory.CreateLogger <ChatTrackingContext>(),
                    () =>
                {
                    lock (trackingContexts)
                        trackingContexts.Remove(context);
                });

            lock (trackingContexts)
                trackingContexts.Add(context);

            return(context);
        }
        /// <summary>
        /// Construct a <see cref="SessionController"/>
        /// </summary>
        /// <param name="reattachInformation">The value of <see cref="reattachInformation"/></param>
        /// <param name="process">The value of <see cref="process"/></param>
        /// <param name="byondLock">The value of <see cref="byondLock"/></param>
        /// <param name="byondTopicSender">The value of <see cref="byondTopicSender"/></param>
        /// <param name="bridgeRegistrar">The <see cref="IBridgeRegistrar"/> used to populate <see cref="bridgeRegistration"/>.</param>
        /// <param name="chat">The value of <see cref="chat"/></param>
        /// <param name="chatTrackingContext">The value of <see cref="chatTrackingContext"/></param>
        /// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="SessionController"/>.</param>
        /// <param name="logger">The value of <see cref="logger"/></param>
        /// <param name="startupTimeout">The optional time to wait before failing the <see cref="LaunchResult"/></param>
        /// <param name="reattached">If this is a reattached session.</param>
        public SessionController(
            ReattachInformation reattachInformation,
            IProcess process,
            IByondExecutableLock byondLock,
            ITopicClient byondTopicSender,
            IChatTrackingContext chatTrackingContext,
            IBridgeRegistrar bridgeRegistrar,
            IChatManager chat,
            IAssemblyInformationProvider assemblyInformationProvider,
            ILogger <SessionController> logger,
            uint?startupTimeout,
            bool reattached)
        {
            this.reattachInformation = reattachInformation ?? throw new ArgumentNullException(nameof(reattachInformation));
            this.process             = process ?? throw new ArgumentNullException(nameof(process));
            this.byondLock           = byondLock ?? throw new ArgumentNullException(nameof(byondLock));
            this.byondTopicSender    = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
            this.chatTrackingContext = chatTrackingContext ?? throw new ArgumentNullException(nameof(chatTrackingContext));
            bridgeRegistration       = bridgeRegistrar?.RegisterHandler(this) ?? throw new ArgumentNullException(nameof(bridgeRegistrar));
            this.chat   = chat ?? throw new ArgumentNullException(nameof(chat));
            this.logger = logger ?? throw new ArgumentNullException(nameof(logger));

            this.chatTrackingContext.SetChannelSink(this);

            portClosedForReboot = false;
            disposed            = false;
            apiValidationStatus = ApiValidationStatus.NeverValidated;
            released            = false;

            rebootTcs           = new TaskCompletionSource <object>();
            primeTcs            = new TaskCompletionSource <object>();
            reattachTopicCts    = new CancellationTokenSource();
            synchronizationLock = new object();

            _ = process.Lifetime.ContinueWith(
                x =>
            {
                if (!disposed)
                {
                    reattachTopicCts.Cancel();
                }
                chatTrackingContext.Active = false;
            },
                TaskScheduler.Current);

            LaunchResult = GetLaunchResult(
                assemblyInformationProvider,
                startupTimeout,
                reattached);

            logger.LogDebug("Created session controller. Primary: {0}, CommsKey: {1}, Port: {2}", IsPrimary, reattachInformation.AccessIdentifier, Port);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="RuntimeInformation"/> <see langword="class"/>.
        /// </summary>
        /// <param name="chatTrackingContext">The <see cref="IChatTrackingContext"/> to use.</param>
        /// <param name="dmbProvider">The <see cref="IDmbProvider"/> to get revision information from.</param>
        /// <param name="serverVersion">The value of <see cref="ServerVersion"/>.</param>
        /// <param name="instanceName">The value of <see cref="InstanceName"/>.</param>
        /// <param name="securityLevel">The value of <see cref="SecurityLevel"/>.</param>
        /// <param name="serverPort">The value of <see cref="ServerPort"/>.</param>
        /// <param name="apiValidateOnly">The value of <see cref="ApiValidateOnly"/>.</param>
        public RuntimeInformation(
            IChatTrackingContext chatTrackingContext,
            IDmbProvider dmbProvider,
            Version serverVersion,
            string instanceName,
            DreamDaemonSecurity?securityLevel,
            ushort serverPort,
            bool apiValidateOnly)
            : base(chatTrackingContext?.Channels ?? throw new ArgumentNullException(nameof(chatTrackingContext)))
        {
            if (dmbProvider == null)
            {
                throw new ArgumentNullException(nameof(dmbProvider));
            }

            ServerVersion = serverVersion ?? throw new ArgumentNullException(nameof(serverVersion));

            Revision = new Api.Models.Internal.RevisionInformation
            {
                CommitSha       = dmbProvider.CompileJob.RevisionInformation.CommitSha,
                Timestamp       = dmbProvider.CompileJob.RevisionInformation.Timestamp,
                OriginCommitSha = dmbProvider.CompileJob.RevisionInformation.OriginCommitSha
            };

            TestMerges = (IReadOnlyCollection <TestMergeInformation>)dmbProvider
                         .CompileJob
                         .RevisionInformation
                         .ActiveTestMerges?
                         .Select(x => x.TestMerge)
                         .Select(x => new TestMergeInformation(x, Revision))
                         .ToList()
                         ?? Array.Empty <TestMergeInformation>();

            InstanceName    = instanceName ?? throw new ArgumentNullException(nameof(instanceName));
            SecurityLevel   = securityLevel;
            ServerPort      = serverPort;
            ApiValidateOnly = apiValidateOnly;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Construct a <see cref="SessionController"/>
        /// </summary>
        /// <param name="reattachInformation">The value of <see cref="reattachInformation"/></param>
        /// <param name="metadata">The owning <see cref="Instance"/>.</param>
        /// <param name="process">The value of <see cref="process"/></param>
        /// <param name="byondLock">The value of <see cref="byondLock"/></param>
        /// <param name="byondTopicSender">The value of <see cref="byondTopicSender"/></param>
        /// <param name="bridgeRegistrar">The <see cref="IBridgeRegistrar"/> used to populate <see cref="bridgeRegistration"/>.</param>
        /// <param name="chat">The value of <see cref="chat"/></param>
        /// <param name="chatTrackingContext">The value of <see cref="chatTrackingContext"/></param>
        /// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="SessionController"/>.</param>
        /// <param name="logger">The value of <see cref="logger"/></param>
        /// <param name="postLifetimeCallback">The <see cref="Func{TResult}"/> returning a <see cref="Task"/> to be run after the <paramref name="process"/> ends.</param>
        /// <param name="startupTimeout">The optional time to wait before failing the <see cref="LaunchResult"/></param>
        /// <param name="reattached">If this is a reattached session.</param>
        /// <param name="apiValidate">If this is a DMAPI validation session.</param>
        public SessionController(
            ReattachInformation reattachInformation,
            Api.Models.Instance metadata,
            IProcess process,
            IByondExecutableLock byondLock,
            ITopicClient byondTopicSender,
            IChatTrackingContext chatTrackingContext,
            IBridgeRegistrar bridgeRegistrar,
            IChatManager chat,
            IAssemblyInformationProvider assemblyInformationProvider,
            ILogger <SessionController> logger,
            Func <Task> postLifetimeCallback,
            uint?startupTimeout,
            bool reattached,
            bool apiValidate)
        {
            this.reattachInformation = reattachInformation ?? throw new ArgumentNullException(nameof(reattachInformation));
            this.metadata            = metadata ?? throw new ArgumentNullException(nameof(metadata));
            this.process             = process ?? throw new ArgumentNullException(nameof(process));
            this.byondLock           = byondLock ?? throw new ArgumentNullException(nameof(byondLock));
            this.byondTopicSender    = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
            this.chatTrackingContext = chatTrackingContext ?? throw new ArgumentNullException(nameof(chatTrackingContext));
            if (bridgeRegistrar == null)
            {
                throw new ArgumentNullException(nameof(bridgeRegistrar));
            }
            this.chat   = chat ?? throw new ArgumentNullException(nameof(chat));
            this.logger = logger ?? throw new ArgumentNullException(nameof(logger));

            portClosedForReboot = false;
            disposed            = false;
            apiValidationStatus = ApiValidationStatus.NeverValidated;
            released            = false;

            rebootTcs = new TaskCompletionSource <object>();
            primeTcs  = new TaskCompletionSource <object>();
            initialBridgeRequestTcs = new TaskCompletionSource <object>();
            reattachTopicCts        = new CancellationTokenSource();
            synchronizationLock     = new object();

            if (apiValidate || DMApiAvailable)
            {
                bridgeRegistration = bridgeRegistrar.RegisterHandler(this);
                this.chatTrackingContext.SetChannelSink(this);
            }
            else
            {
                logger.LogTrace(
                    "Not registering session with {0} DMAPI version for interop!",
                    reattachInformation.Dmb.CompileJob.DMApiVersion == null
                                                ? "no"
                                                : $"incompatible ({reattachInformation.Dmb.CompileJob.DMApiVersion})");
            }

            async Task <int> WrapLifetime()
            {
                var exitCode = await process.Lifetime.ConfigureAwait(false);

                await postLifetimeCallback().ConfigureAwait(false);

                return(exitCode);
            }

            Lifetime = WrapLifetime();

            LaunchResult = GetLaunchResult(
                assemblyInformationProvider,
                startupTimeout,
                reattached,
                apiValidate);

            logger.LogDebug(
                "Created session controller. CommsKey: {0}, Port: {1}",
                reattachInformation.AccessIdentifier,
                reattachInformation.Port);
        }