예제 #1
0
        /// <inheritdoc />
        public Task <IIpcResult> Send(IIpcOperation operation)
        {
            Contract.Requires(operation != null);

            var request = new Request(operation);

            // Must add the request to the m_pendingRequest dictionary before posting it to m_sendRequestBlock
            // Otherwise, the following can happen:
            //   1) the request is posted
            //   2) the request is picked up from the queue and processed
            //   3) the request handler looks up corresponding completionSource in the dictionary which is not there yet (ERROR)
            //   4) the TaskCompletionSource is added to the dictionary
            var completionSource = TaskSourceSlim.Create <IIpcResult>();

            m_pendingRequests[request.Id] = completionSource;

            operation.Timestamp.Request_BeforePostTime = DateTime.UtcNow;
            bool posted = m_sendRequestBlock.Post(request);

            if (!posted)
            {
                // if the request was not posted:
                // (1) remove it from the dictionary
                TaskSourceSlim <IIpcResult> src;
                m_pendingRequests.TryRemove(request.Id, out src);

                // (2) complete it (with TransmissionError)
                completionSource.TrySetResult(new IpcResult(
                                                  IpcResultStatus.TransmissionError,
                                                  "Could not post IPC request: the client has already terminated."));
            }

            return(completionSource.Task);
        }
예제 #2
0
        private async Task <IIpcResult> ParseAndExecuteCommandAsync(int id, IIpcOperation operation)
        {
            string cmdLine = operation.Payload;

            m_logger.Verbose($"Command received. Request #{id}, CommandLine: {cmdLine}");
            ConfiguredCommand conf;

            using (m_counters.StartStopwatch(DaemonCounter.ParseArgsDuration))
            {
                conf = ParseArgs(cmdLine, m_parser);
            }

            IIpcResult result;

            using (var duration = m_counters.StartStopwatch(DaemonCounter.ServerActionDuration))
            {
                result = await conf.Command.ServerAction(conf, this);

                result.ActionDuration = duration.Elapsed;
            }

            TimeSpan queueDuration = operation.Timestamp.Daemon_BeforeExecuteTime - operation.Timestamp.Daemon_AfterReceivedTime;

            m_counters.AddToCounter(DaemonCounter.QueueDurationMs, (long)queueDuration.TotalMilliseconds);

            return(result);
        }
예제 #3
0
파일: Request.cs 프로젝트: kittinap/kunnjae
        private Request(int id, IIpcOperation operation)
        {
            Contract.Requires(operation != null);

            Id        = id;
            Operation = operation;
        }
예제 #4
0
파일: Request.cs 프로젝트: kittinap/kunnjae
        /// <nodoc/>
        public Request(IIpcOperation operation)
        {
            Contract.Requires(operation != null);

            Id        = Interlocked.Increment(ref s_requestIdCounter);
            Operation = operation;
        }
예제 #5
0
        /// <summary>
        /// Asynchronously serializes given <see cref="IIpcOperation"/> to a stream writer.
        /// </summary>
        /// <remarks>
        /// Doesn't handle any exceptions.
        /// </remarks>
        public static async Task SerializeAsync(Stream stream, IIpcOperation op, CancellationToken token)
        {
            await Utils.WriteBooleanAsync(stream, op.ShouldWaitForServerAck, token);

            await Utils.WriteStringAsync(stream, op.Payload, token);

            await stream.FlushAsync(token);
        }
예제 #6
0
        /// <summary>
        /// 1. serializes an <see cref="IIpcOperation"/> over via <paramref name="stream"/>;
        /// 2. if the operation is synchronous, reads an <see cref="IIpcResult"/> from <paramref name="stream"/>.
        /// </summary>
        internal static async Task <IIpcResult> SendOperationAndExecuteRemotelyAsync(IIpcOperation operation, Stream stream, CancellationToken token)
        {
            await IpcOperation.SerializeAsync(stream, operation, token);

            return(operation.ShouldWaitForServerAck
                ? await IpcResult.DeserializeAsync(stream, token)
                : IpcResult.Success());
        }
예제 #7
0
        /// <inheritdoc/>
        /// <remarks>
        /// Connects to server over TCP/IP, then serializes given <paramref name="operation"/>
        /// (<see cref="IpcOperation.SerializeAsync(Stream, IIpcOperation, CancellationToken)"/>)
        /// and sends it over TCP/IP <see cref="Stream"/>.
        /// </remarks>
        Task <IIpcResult> IClient.Send(IIpcOperation operation)
        {
            Contract.Requires(operation != null);

            return(ConnectAndExecute((stream) =>
            {
                return Utils.SendOperationAndExecuteRemotelyAsync(operation, stream, CancellationToken.None);
            }));
        }
예제 #8
0
        async Task <IIpcResult> IIpcOperationExecutor.ExecuteAsync(IIpcOperation op)
        {
            Contract.Requires(op != null);

            Tracing.Logger.Log.ApiServerOperationReceived(m_loggingContext, op.Payload);
            var maybeIpcResult = await TryDeserialize(op.Payload)
                                 .ThenAsync(cmd => TryExecuteCommand(cmd));

            return(maybeIpcResult.Succeeded
                ? maybeIpcResult.Result
                : new IpcResult(IpcResultStatus.ExecutionError, maybeIpcResult.Failure.Describe()));
        }
예제 #9
0
        /// <summary>
        /// 1. deserializes an <see cref="IIpcOperation"/> from a given <paramref name="stream"/>;
        /// 2. executes the operation (via <paramref name="executor"/>);
        /// 3. serializes and sends back the result via <paramref name="stream"/>.
        ///
        /// If executing the operation (via <paramref name="executor"/>) fails, the <see cref="IIpcResult.ExitCode"/>
        /// of the result is <see cref="IpcResultStatus.ExecutionError"/>
        /// </summary>
        internal static async Task <IIpcResult> ReceiveOperationAndExecuteLocallyAsync(Stream stream, IIpcOperationExecutor executor, CancellationToken token)
        {
            IIpcOperation operation = await IpcOperation.DeserializeAsync(stream, token);

            IIpcResult result = await HandleExceptionsAsync(IpcResultStatus.ExecutionError, () => executor.ExecuteAsync(operation));

            if (operation.ShouldWaitForServerAck)
            {
                await IpcResult.SerializeAsync(stream, result, token);
            }

            return(result);
        }
예제 #10
0
        /// <inheritdoc />
        public async Task <IIpcResult> Send(IIpcOperation operation)
        {
            Contract.Requires(operation != null);

            var maybeClient = await m_multiplexingClientLazyTask.Value;

            if (maybeClient.Succeeded)
            {
                return(await maybeClient.Result.Send(operation));
            }
            else
            {
                return(new IpcResult(IpcResultStatus.ConnectionError, "Failing this client because creating multiplexing client failed" + maybeClient.Failure.Describe()));
            }
        }
예제 #11
0
 Task <IIpcResult> IClient.Send(IIpcOperation operation)
 {
     Contract.Requires(operation != null);
     if (InternalClient != null)
     {
         if (global::BuildXL.Ipc.ExternalApi.Commands.Command.Deserialize(operation.Payload) is RegisterFilesForBuildManifestCommand)
         {
             // Override for RegisterFileForBuildManifestCommand (Always true)
             return(Task.FromResult(SendFn(operation)));
         }
         else
         {
             return(InternalClient.Send(operation));
         }
     }
     return(Task.FromResult(SendFn(operation)));
 }
예제 #12
0
 Task <IIpcResult> IClient.Send(IIpcOperation operation)
 {
     Contract.Requires(operation != null);
     return(Task.FromResult(SendFn(operation)));
 }
예제 #13
0
        Task <IIpcResult> IIpcOperationExecutor.ExecuteAsync(int id, IIpcOperation operation)
        {
            Contract.Requires(operation != null);

            return(ParseAndExecuteCommandAsync(id, operation));
        }
예제 #14
0
 /// <summary>
 /// Always returns <see cref="IIpcResult.Success(string)"/> echoing the payload received in <paramref name="operation"/>.
 /// </summary>
 public Task <IIpcResult> Send(IIpcOperation operation)
 {
     Contract.Requires(operation != null);
     return(Task.FromResult((IIpcResult) new IpcResult(m_status, operation.Payload)));
 }
예제 #15
0
        protected static IIpcResult SendWithTimeout(IClient client, IIpcOperation op)
        {
            var sendTask = client.Send(op);

            return(sendTask.GetAwaiter().GetResult());
        }
예제 #16
0
        /// <inheritdoc />
        public Task <IIpcResult> ExecuteAsync(int id, IIpcOperation op)
        {
            Contract.Requires(op != null);

            return(Task.FromResult(m_executor(op)));
        }