/// <summary>
        /// Gets performance statistics for each known node. 
        /// This operation can take significant amount of time.
        /// </summary>
        /// <returns>Performance statistics for each node.</returns>
        public async Task<Dictionary<ServiceUri, PerformanceStatistics>> GetPerformanceStatistics()
        {
            var performanceStatistics = new Dictionary<ServiceUri, PerformanceStatistics>();

            // snapshot services list
            var availableServices = default(List<ServiceUri>);
            lock (AvailableServicesLock)
            {
                availableServices = AvailableServices.Skip(0).ToList();
            }

            // get performance statistics from each node
            foreach (var service in availableServices)
            {
                using (var client = new Bluepath.ServiceReferences.RemoteExecutorServiceClient(
                    service.Binding,
                    service.ToEndpointAddress()))
                {
                    try
                    {
                        Log.TraceMessage(Log.Activity.Info, string.Format("[PerfStat] Getting performance statistics from '{0}'.", service.Address));
                        performanceStatistics.Add(service, (await client.GetPerformanceStatisticsAsync()).FromServiceReference());
                    }
                    catch(Exception ex)
                    {
                        Log.ExceptionMessage(ex, Log.Activity.Info, "Failed getting performance stats - ignoring.");
                    }
                }
            }

            return performanceStatistics;
        }
예제 #2
0
        /// <summary>
        /// Executes method set previously by Initialize method.
        /// </summary>
        /// <param name="eid">Unique identifier of the executor.</param>
        /// <param name="parameters">Parameters for the method. Note that it gets interpreted as object1, object2, etc.
        /// So if method expects one argument of type object[], you need to wrap it with additional object[] 
        /// (object[] { object[] } - outer array indicates that method accepts one parameter, and inner is actual parameter).</param>
        /// <param name="callbackUri">Specifies uri which will be used for callback.
        /// Null for no callback.</param>
        public void Execute(Guid eid, object[] parameters, ServiceUri callbackUri)
        {
            var executor = GetExecutor(eid);

            Log.TraceMessage(
                callbackUri != null ? Log.Activity.Starting_local_executor_with_callback : Log.Activity.Starting_local_executor_without_callback,
                string.Format(
                        "Starting local executor. Upon completion callback will{0} be sent{1}{2}.",
                        callbackUri != null ? string.Empty : " not",
                        callbackUri != null ? " to " : string.Empty,
                        callbackUri != null ? callbackUri.Address : string.Empty),
                        keywords: executor.Eid.EidAsLogKeywords());

            executor.Execute(parameters);

            if (callbackUri != null)
            {
                var t = new Thread(() =>
                {
                    try
                    {
                        using (var client =
                            new Bluepath.ServiceReferences.RemoteExecutorServiceClient(
                                callbackUri.Binding,
                                callbackUri.ToEndpointAddress()))
                        {
                            // Join on local executor doesn't throw exceptions by design
                            // Exception caused by user code (if any) can be accessed using Exception property
                            executor.Join();

                            Log.TraceMessage(Log.Activity.Sending_callback_with_result, string.Format("Sending callback with result. State: {0}. Elapsed time: {1}.", executor.ExecutorState, executor.ElapsedTime), keywords: executor.Eid.EidAsLogKeywords());

                            var result = new ServiceReferences.RemoteExecutorServiceResult
                            {
                                Result = executor.IsResultAvailable ? executor.Result : null,
                                ElapsedTime = executor.ElapsedTime,
                                ExecutorState = (ServiceReferences.ExecutorState)((int)executor.ExecutorState),
                                Error = executor.Exception
                            };

                            // TODO: Serialization of result can fail and we should do something about it (like send an error message back)
                            client.ExecuteCallback(eid, result);
                        }
                    }
                    catch(Exception ex)
                    {
                        Log.ExceptionMessage(ex, Log.Activity.Send_callback_failed, "Send callback failed.");
                    }
                });

                t.Name = string.Format("Execute callback sender thread for executor '{0}'", executor.Eid);
                t.Start();
            }
        }