/// <summary> /// Aborts execution of a running service. /// </summary> /// <param name="instanceID"></param> void IServiceExecutionHost.AbortService(Guid instanceID) { ServiceRuntimeInfo runtimeInfo = Get(instanceID); lock (runtimeInfo.ExecutionSync) runtimeInfo.ServiceRef.Abort(); }
void DomainUnload(object sender, EventArgs e) { // Get the service instance ID of the appdomain AppDomain appDomain = (AppDomain)sender; Guid instanceID; if (!_serviceByAppDomain.TryGetValue(appDomain.Id, out instanceID)) { return; } // Get the runtime in the appdomain ServiceRuntimeInfo runtimeInfo = Get(instanceID, throwex: false); if (runtimeInfo == null) { return; } // Remove the service lock (_services) { _services.Remove(instanceID); _serviceByAppDomain.Remove(appDomain.Id); } }
void IServiceExecutionHost.Connect(Guid instanceID, Guid connectionGuid, string usageName) { EnsureNotDisposed(); ServiceRuntimeInfo runtimeInfo; // Check if instance ID exists lock (_services) { if (!_services.TryGetValue(instanceID, out runtimeInfo)) { runtimeInfo = new ServiceRuntimeInfo(instanceID); _services.Add(instanceID, runtimeInfo); } } lock (runtimeInfo.Connections) { runtimeInfo.Connections.Add(connectionGuid, new ServiceConnectionInfo() { ConnectionGuid = connectionGuid, InstanceId = instanceID, UsageName = usageName, Callback = OperationContext.Current.GetCallbackChannel <IServiceConnection>() }); } }
void IServiceExecutionHost.ResumeService(Guid instanceID) { EnsureNotDisposed(); ServiceRuntimeInfo runtimeInfo = Get(instanceID); lock (runtimeInfo.ExecutionSync) { try { runtimeInfo.ServiceRef.Resume(); } catch (AppDomainUnloadedException) { HostLog("Service was killed while trying to resume.", null, LogMessageType.Warning); } } }
void IServiceExecutionHost.Connect(Guid instanceID, Guid connectionGuid) { ServiceRuntimeInfo runtimeInfo; // Check if instance ID exists lock (_services) { if (!_services.TryGetValue(instanceID, out runtimeInfo)) { runtimeInfo = new ServiceRuntimeInfo(instanceID); _services.Add(instanceID, runtimeInfo); } } runtimeInfo.Connections.Add(connectionGuid, OperationContext.Current.GetCallbackChannel <IServiceConnection>()); }
void DomainUnload(object sender, EventArgs e) { // Get the service instance ID of the appdomain AppDomain appDomain = (AppDomain)sender; Guid instanceID; if (!_serviceByAppDomain.TryGetValue(appDomain.Id, out instanceID)) { return; } // Get the runtime in the appdomain ServiceRuntimeInfo runtimeInfo = Get(instanceID, throwex: false); if (runtimeInfo == null) { return; } // Remove the service lock (_services) { _services.Remove(instanceID); _serviceByAppDomain.Remove(appDomain.Id); } #region Probably not necessary - TBD // http://stackoverflow.com/questions/8165398/do-i-need-to-close-and-or-dispose-callback-channels-acquired-through-operationco // Dispose of open channels /* * lock (runtimeInfo.Connections) * { * foreach (IServiceConnection connection in runtimeInfo.Connections.Values) * { * try { connection.Dispose(); } * catch (Exception ex) * { * HostLog("Forcing the connection to close caused an exception.", ex, LogMessageType.Warning); * } * } * } */ #endregion }
internal void InstanceLog(Guid instanceID, Guid profileID, string serviceName, string contextInfo, string message, Exception ex, LogMessageType messageType) { // Get the runtime in the appdomain ServiceRuntimeInfo runtimeInfo = Get(instanceID, throwex: false); var entry = new LogMessage( source: serviceName, contextInfo: contextInfo, message: message, ex: ex, messageType: messageType ) { ServiceInstanceID = instanceID, ServiceProfileID = profileID }; Log.Write(entry); }
/// <summary> /// Aborts execution of a running service. /// </summary> /// <param name="instanceID"></param> void IServiceExecutionHost.AbortService(Guid instanceID) { EnsureNotDisposed(); ServiceRuntimeInfo runtimeInfo = Get(instanceID); lock (runtimeInfo.ExecutionSync) { if (runtimeInfo.StateInfo == null) { // Special case to notify connections (ServiceInstance objects) that a service has been canceled and will never run lock (runtimeInfo.Connections) { foreach (IServiceConnection connection in runtimeInfo.Connections.Values) { connection.ReceiveState(new ServiceStateInfo() { State = ServiceState.Ended, Outcome = ServiceOutcome.Canceled }); } // candidate for DeadLock lock (_services) _services.Remove(instanceID); } } else { // Abort a running service try { runtimeInfo.ServiceRef.Abort(); } catch (AppDomainUnloadedException) { HostLog("Service was killed while trying to abort.", null, LogMessageType.Warning); } } } }
void IServiceExecutionHost.InitializeService(ServiceConfiguration config, SchedulingInfo schedulingInfo, Guid instanceID, Guid parentInstanceID, Guid connectionGuid) { if (String.IsNullOrEmpty(config.ServiceClass)) { throw new ServiceException("ServiceConfiguration.ServiceClass cannot be empty."); } ServiceRuntimeInfo runtimeInfo = Get(instanceID); lock (runtimeInfo.ExecutionSync) { if (runtimeInfo.StateInfo != null && runtimeInfo.StateInfo.Value.State != ServiceState.Uninitialized) { throw new ServiceException("Service is already initialized."); } // Save init data for later runtimeInfo.ParentInstanceID = parentInstanceID; runtimeInfo.Configuration = config; runtimeInfo.SchedulingInfo = schedulingInfo; UpdateState(instanceID, new ServiceStateInfo() { State = ServiceState.Initializing }); // Load the app domain, and attach to its events AppDomain domain = AppDomain.CreateDomain( String.Format("Edge service - {0} ({1})", config.ServiceName, instanceID) ); domain.DomainUnload += new EventHandler(DomainUnload); // Instantiate the service type in the new domain Service serviceRef; if (config.AssemblyPath == null) { Type serviceType = Type.GetType(config.ServiceClass, false); if (serviceType == null) { serviceType = Type.GetType(String.Format("Edge.Core.Services.{0}.{0}Service", config.ServiceClass), false); } if (serviceType == null) { throw new ServiceException(String.Format("Service type '{0}' could not be found. Please specify AssemblyPath if the service is not in the host directory.", config.ServiceClass)); } serviceRef = (Service)domain.CreateInstanceAndUnwrap(serviceType.Assembly.FullName, serviceType.FullName); } else { // A 3rd party service serviceRef = (Service)domain.CreateInstanceFromAndUnwrap( config.AssemblyPath, config.ServiceClass ); } runtimeInfo.ServiceRef = serviceRef; runtimeInfo.AppDomain = domain; lock (_serviceByAppDomain) { _serviceByAppDomain.Add(domain.Id, runtimeInfo.InstanceID); }; // Give the service ref its properties serviceRef.Init(this, this.Environment.EnvironmentConfiguration, config, schedulingInfo, instanceID, parentInstanceID); } }