/// <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; }
/// <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(); } }