internal void SaveServiceInstance( ServiceExecutionHost host, Guid instanceID, Guid parentInstanceID, ServiceConfiguration config, ServiceStateInfo stateInfo, SchedulingInfo schedulingInfo ) { // The first time we save write the configuration to XML. Otherwise ignore. string serializedConfig = null; if (stateInfo.State == ServiceState.Initializing) { var stringWriter = new StringWriter(); using (var writer = new XmlTextWriter(stringWriter)) new NetDataContractSerializer().WriteObject(writer, config); serializedConfig = stringWriter.ToString(); } var env = this.EnvironmentConfiguration; using (var connection = new SqlConnection(env.ConnectionString)) { var command = new SqlCommand(env.SP_InstanceSave, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@instanceID", instanceID.ToString("N")); command.Parameters.AddWithValue("@parentInstanceID", SqlUtility.SqlValue(parentInstanceID, Guid.Empty, () => parentInstanceID.ToString("N"))); command.Parameters.AddWithValue("@profileID", SqlUtility.SqlValue(config.Profile, () => config.Profile.ProfileID.ToString("N"))); command.Parameters.AddWithValue("@serviceName", config.ServiceName); command.Parameters.AddWithValue("@hostName", host.HostName); command.Parameters.AddWithValue("@hostGuid", host.HostGuid.ToString("N")); command.Parameters.AddWithValue("@progress", stateInfo.Progress); command.Parameters.AddWithValue("@state", stateInfo.State); command.Parameters.AddWithValue("@outcome", stateInfo.Outcome); command.Parameters.AddWithValue("@timeInitialized", SqlUtility.SqlValue(stateInfo.TimeInitialized, DateTime.MinValue)); command.Parameters.AddWithValue("@timeStarted", SqlUtility.SqlValue(stateInfo.TimeStarted, DateTime.MinValue)); command.Parameters.AddWithValue("@timeEnded", SqlUtility.SqlValue(stateInfo.TimeEnded, DateTime.MinValue)); command.Parameters.AddWithValue("@timeLastPaused", SqlUtility.SqlValue(stateInfo.TimeLastPaused, DateTime.MinValue)); command.Parameters.AddWithValue("@timeLastResumed", SqlUtility.SqlValue(stateInfo.TimeLastResumed, DateTime.MinValue)); command.Parameters.AddWithValue("@resumeCount", stateInfo.ResumeCount); command.Parameters.AddWithValue("@configuration", SqlUtility.SqlValue(serializedConfig)); command.Parameters.AddWithValue("@Scheduling_Status", SqlUtility.SqlValue(schedulingInfo, () => schedulingInfo.SchedulingStatus)); command.Parameters.AddWithValue("@Scheduling_Scope", SqlUtility.SqlValue(schedulingInfo, () => schedulingInfo.SchedulingScope)); command.Parameters.AddWithValue("@Scheduling_MaxDeviationBefore", SqlUtility.SqlValue(schedulingInfo, () => schedulingInfo.MaxDeviationBefore)); command.Parameters.AddWithValue("@Scheduling_MaxDeviationAfter", SqlUtility.SqlValue(schedulingInfo, () => schedulingInfo.MaxDeviationAfter)); command.Parameters.AddWithValue("@Scheduling_RequestedTime", SqlUtility.SqlValue(schedulingInfo, () => SqlUtility.SqlValue(schedulingInfo.RequestedTime, DateTime.MinValue))); command.Parameters.AddWithValue("@Scheduling_ExpectedStartTime", SqlUtility.SqlValue(schedulingInfo, () => SqlUtility.SqlValue(schedulingInfo.ExpectedStartTime, DateTime.MinValue))); command.Parameters.AddWithValue("@Scheduling_ExpectedEndTime", SqlUtility.SqlValue(schedulingInfo, () => SqlUtility.SqlValue(schedulingInfo.ExpectedEndTime, DateTime.MinValue))); connection.Open(); command.ExecuteNonQuery(); } }
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); } }
internal void Init(ServiceExecutionHost host, ServiceEnvironmentConfiguration envConfig, ServiceConfiguration config, SchedulingInfo schedulingInfo, Guid instanceID, Guid parentInstanceID) { Host = host; this.Environment = new ServiceEnvironment(envConfig); this.InstanceID = instanceID; this.Configuration = config; this.SchedulingInfo = schedulingInfo; if (parentInstanceID != Guid.Empty) { this.ParentInstance = Environment.GetServiceInstance(parentInstanceID); } Current = this; // Monitor app domain-level events AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(this.DomainUnhandledException); AppDomain.CurrentDomain.DomainUnload += new EventHandler(this.DomainUnload); StateInfo.TimeInitialized = DateTime.Now; StateInfo.State = ServiceState.Ready; NotifyState(); }