public StartServiceInfo(string service, string value, string[] serverArgs) { // // Separate the entry point from the arguments. // name = service; try { args = IceUtilInternal.Options.split(value); } catch (IceUtilInternal.Options.BadQuote ex) { FailureException e = new FailureException(); e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.Message; throw e; } Debug.Assert(args.Length > 0); entryPoint = args[0]; // // Shift the arguments. // string[] tmp = new string[args.Length - 1]; Array.Copy(args, 1, tmp, 0, args.Length - 1); args = tmp; if (serverArgs.Length > 0) { ArrayList l = new ArrayList(); for (int j = 0; j < args.Length; j++) { l.Add(args[j]); } for (int j = 0; j < serverArgs.Length; j++) { if (serverArgs[j].StartsWith("--" + service + ".", StringComparison.Ordinal)) { l.Add(serverArgs[j]); } } args = (string[])l.ToArray(typeof(string)); } }
public int run() { try { Ice.Properties properties = _communicator.getProperties(); // // Create an object adapter. Services probably should NOT share // this object adapter, as the endpoint(s) for this object adapter // will most likely need to be firewalled for security reasons. // Ice.ObjectAdapter adapter = null; if (properties.getProperty("IceBox.ServiceManager.Endpoints").Length != 0) { adapter = _communicator.createObjectAdapter("IceBox.ServiceManager"); Ice.Identity identity = new Ice.Identity(); identity.category = properties.getPropertyWithDefault("IceBox.InstanceName", "IceBox"); identity.name = "ServiceManager"; adapter.add(this, identity); } // // Parse the property set with the prefix "IceBox.Service.". These // properties should have the following format: // // IceBox.Service.Foo=<assembly>:Package.Foo [args] // // We parse the service properties specified in IceBox.LoadOrder // first, then the ones from remaining services. // string prefix = "IceBox.Service."; Dictionary <string, string> services = properties.getPropertiesForPrefix(prefix); string[] loadOrder = properties.getPropertyAsList("IceBox.LoadOrder"); List <StartServiceInfo> servicesInfo = new List <StartServiceInfo>(); for (int i = 0; i < loadOrder.Length; ++i) { if (loadOrder[i].Length > 0) { string key = prefix + loadOrder[i]; string value = services[key]; if (value == null) { FailureException ex = new FailureException(); ex.reason = "ServiceManager: no service definition for `" + loadOrder[i] + "'"; throw ex; } servicesInfo.Add(new StartServiceInfo(loadOrder[i], value, _argv)); services.Remove(key); } } foreach (KeyValuePair <string, string> entry in services) { string name = entry.Key.Substring(prefix.Length); string value = entry.Value; servicesInfo.Add(new StartServiceInfo(name, value, _argv)); } // // Check if some services are using the shared communicator in which // case we create the shared communicator now with a property set that // is the union of all the service properties (from services that use // the shared communicator). // if (properties.getPropertiesForPrefix("IceBox.UseSharedCommunicator.").Count > 0) { Ice.InitializationData initData = new Ice.InitializationData(); initData.properties = createServiceProperties("SharedCommunicator"); foreach (StartServiceInfo service in servicesInfo) { if (properties.getPropertyAsInt("IceBox.UseSharedCommunicator." + service.name) <= 0) { continue; } // // Load the service properties using the shared communicator properties as // the default properties. // Ice.Properties svcProperties = Ice.Util.createProperties(ref service.args, initData.properties); // // Remove properties from the shared property set that a service explicitly clears. // Dictionary <string, string> allProps = initData.properties.getPropertiesForPrefix(""); foreach (string key in allProps.Keys) { if (svcProperties.getProperty(key).Length == 0) { initData.properties.setProperty(key, ""); } } // // Add the service properties to the shared communicator properties. // foreach (KeyValuePair <string, string> entry in svcProperties.getPropertiesForPrefix("")) { initData.properties.setProperty(entry.Key, entry.Value); } // // Parse <service>.* command line options (the Ice command line options // were parsed by the call to createProperties above). // service.args = initData.properties.parseCommandLineOptions(service.name, service.args); } string facetNamePrefix = "IceBox.SharedCommunicator."; bool addFacets = configureAdmin(initData.properties, facetNamePrefix); _sharedCommunicator = Ice.Util.initialize(initData); if (addFacets) { // Add all facets created on shared communicator to the IceBox communicator // but renamed <prefix>.<facet-name>, except for the Process facet which is // never added. foreach (KeyValuePair <string, Ice.Object> p in _sharedCommunicator.findAllAdminFacets()) { if (!p.Key.Equals("Process")) { _communicator.addAdminFacet(p.Value, facetNamePrefix + p.Key); } } } } foreach (StartServiceInfo s in servicesInfo) { startService(s.name, s.entryPoint, s.args); } // // We may want to notify external scripts that the services // have started. This is done by defining the property: // // PrintServicesReady=bundleName // // Where bundleName is whatever you choose to call this set of // services. It will be echoed back as "bundleName ready". // // This must be done after start() has been invoked on the // services. // string bundleName = properties.getProperty("IceBox.PrintServicesReady"); if (bundleName.Length > 0) { Console.Out.WriteLine(bundleName + " ready"); } // // Don't move after the adapter activation. This allows // applications to wait for the service manager to be // reachable before sending a signal to shutdown the // // Ice.Application.shutdownOnInterrupt(); // // Register "this" as a facet to the Admin object and create Admin object // try { _communicator.addAdminFacet(this, "IceBox.ServiceManager"); _communicator.getAdmin(); } catch (Ice.ObjectAdapterDeactivatedException) { // // Expected if the communicator has been shutdown. // } // // Start request dispatching after we've started the services. // if (adapter != null) { try { adapter.activate(); } catch (Ice.ObjectAdapterDeactivatedException) { // // Expected if the communicator has been shutdown. // } } _communicator.waitForShutdown(); } catch (FailureException ex) { _logger.error(ex.ToString()); return(1); } catch (Exception ex) { _logger.error("ServiceManager: caught exception:\n" + ex.ToString()); return(1); } finally { // // Invoke stop() on the services. // stopAll(); } return(0); }
private void startService(string service, string entryPoint, string[] args) { lock (this) { // // Extract the assembly name and the class name. // string err = "ServiceManager: unable to load service '" + entryPoint + "': "; int sepPos = entryPoint.IndexOf(':'); if (sepPos != -1) { const string driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (entryPoint.Length > 3 && sepPos == 1 && driveLetters.IndexOf(entryPoint[0]) != -1 && (entryPoint[2] == '\\' || entryPoint[2] == '/')) { sepPos = entryPoint.IndexOf(':', 3); } } if (sepPos == -1) { FailureException e = new FailureException(); e.reason = err + "invalid entry point format"; throw e; } System.Reflection.Assembly serviceAssembly = null; string assemblyName = entryPoint.Substring(0, sepPos); string className = entryPoint.Substring(sepPos + 1); try { // // First try to load the assembly using Assembly.Load, which will succeed // if a fully-qualified name is provided or if a partial name has been qualified // in configuration. If that fails, try Assembly.LoadFrom(), which will succeed // if a file name is configured or a partial name is configured and DEVPATH is used. // try { serviceAssembly = System.Reflection.Assembly.Load(assemblyName); } catch (System.IO.IOException ex) { try { serviceAssembly = System.Reflection.Assembly.LoadFrom(assemblyName); } catch (System.IO.IOException) { throw ex; } } } catch (Exception ex) { FailureException e = new FailureException(ex); e.reason = err + "unable to load assembly: " + assemblyName; throw e; } // // Instantiate the class. // Type c = null; try { c = serviceAssembly.GetType(className, true); } catch (Exception ex) { FailureException e = new FailureException(ex); e.reason = err + "GetType failed for '" + className + "'"; throw e; } ServiceInfo info = new ServiceInfo(); info.name = service; info.status = ServiceStatus.Stopped; info.args = args; // // If IceBox.UseSharedCommunicator.<name> is defined, create a // communicator for the service. The communicator inherits // from the shared communicator properties. If it's not // defined, add the service properties to the shared // commnunicator property set. // Ice.Communicator communicator; if (_communicator.getProperties().getPropertyAsInt("IceBox.UseSharedCommunicator." + service) > 0) { Debug.Assert(_sharedCommunicator != null); communicator = _sharedCommunicator; } else { // // Create the service properties. We use the communicator properties as the default // properties if IceBox.InheritProperties is set. // Ice.InitializationData initData = new Ice.InitializationData(); initData.properties = createServiceProperties(service); if (info.args.Length > 0) { // // Create the service properties with the given service arguments. This should // read the service config file if it's specified with --Ice.Config. // initData.properties = Ice.Util.createProperties(ref info.args, initData.properties); // // Next, parse the service "<service>.*" command line options (the Ice command // line options were parsed by the createProperties above) // info.args = initData.properties.parseCommandLineOptions(service, info.args); } // // Clone the logger to assign a new prefix. If one of the built-in loggers is configured // don't set any logger. // if (initData.properties.getProperty("Ice.LogFile").Length == 0) { initData.logger = _logger.cloneWithPrefix(initData.properties.getProperty("Ice.ProgramName")); } // // If Admin is enabled on the IceBox communicator, for each service that does not set // Ice.Admin.Enabled, we set Ice.Admin.Enabled=1 to have this service create facets; then // we add these facets to the IceBox Admin object as IceBox.Service.<service>.<facet>. // string serviceFacetNamePrefix = "IceBox.Service." + service + "."; bool addFacets = configureAdmin(initData.properties, serviceFacetNamePrefix); // // Remaining command line options are passed to the communicator. This is // necessary for Ice plug-in properties (e.g.: IceSSL). // info.communicator = Ice.Util.initialize(ref info.args, initData); communicator = info.communicator; if (addFacets) { // Add all facets created on the service communicator to the IceBox communicator // but renamed IceBox.Service.<service>.<facet-name>, except for the Process facet // which is never added foreach (KeyValuePair <string, Ice.Object> p in communicator.findAllAdminFacets()) { if (!p.Key.Equals("Process")) { _communicator.addAdminFacet(p.Value, serviceFacetNamePrefix + p.Key); } } } } try { // // Instantiate the service. // try { // // If the service class provides a constructor that accepts an Ice.Communicator argument, // use that in preference to the default constructor. // Type[] parameterTypes = new Type[1]; parameterTypes[0] = typeof(Ice.Communicator); System.Reflection.ConstructorInfo ci = c.GetConstructor(parameterTypes); if (ci != null) { try { object[] parameters = new object[1]; parameters[0] = _communicator; info.service = (Service)ci.Invoke(parameters); } catch (MethodAccessException ex) { FailureException e = new FailureException(ex); e.reason = err + "unable to access service constructor " + className + "(Ice.Communicator)"; throw e; } } else { // // Fall back to the default constructor. // try { info.service = (Service)IceInternal.AssemblyUtil.createInstance(c); if (info.service == null) { FailureException e = new FailureException(); e.reason = err + "no default constructor for '" + className + "'"; throw e; } } catch (UnauthorizedAccessException ex) { FailureException e = new FailureException(ex); e.reason = err + "unauthorized access to default service constructor for " + className; throw e; } } } catch (FailureException) { throw; } catch (InvalidCastException ex) { FailureException e = new FailureException(ex); e.reason = err + "service does not implement IceBox.Service"; throw e; } catch (System.Reflection.TargetInvocationException ex) { if (ex.InnerException is FailureException) { throw ex.InnerException; } else { FailureException e = new FailureException(ex.InnerException); e.reason = err + "exception in service constructor for " + className; throw e; } } catch (Exception ex) { FailureException e = new FailureException(ex); e.reason = err + "exception in service constructor " + className; throw e; } try { info.service.start(service, communicator, info.args); } catch (FailureException) { throw; } catch (Exception ex) { FailureException e = new FailureException(ex); e.reason = "exception while starting service " + service; throw e; } info.status = ServiceStatus.Started; _services.Add(info); } catch (Exception) { if (info.communicator != null) { destroyServiceCommunicator(service, info.communicator); } throw; } } }
private void startService(string service, string entryPoint, string[] args) { _m.Lock(); try { // // Extract the assembly name and the class name. // string err = "ServiceManager: unable to load service '" + entryPoint + "': "; int sepPos = entryPoint.IndexOf(':'); if (sepPos != -1 && IceInternal.AssemblyUtil.platform_ == IceInternal.AssemblyUtil.Platform.Windows) { const string driveLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (entryPoint.Length > 3 && sepPos == 1 && driveLetters.IndexOf(entryPoint[0]) != -1 && (entryPoint[2] == '\\' || entryPoint[2] == '/')) { sepPos = entryPoint.IndexOf(':', 3); } } if (sepPos == -1) { FailureException e = new FailureException(); e.reason = err + "invalid entry point format"; throw e; } System.Reflection.Assembly serviceAssembly = null; string assemblyName = entryPoint.Substring(0, sepPos); string className = entryPoint.Substring(sepPos + 1); try { // // First try to load the assembly using Assembly.Load, which will succeed // if a fully-qualified name is provided or if a partial name has been qualified // in configuration. If that fails, try Assembly.LoadFrom(), which will succeed // if a file name is configured or a partial name is configured and DEVPATH is used. // try { serviceAssembly = System.Reflection.Assembly.Load(assemblyName); } catch (System.IO.IOException ex) { try { serviceAssembly = System.Reflection.Assembly.LoadFrom(assemblyName); } catch (System.IO.IOException) { throw ex; } } } catch (System.Exception ex) { FailureException e = new FailureException(ex); e.reason = err + "unable to load assembly: " + assemblyName; throw e; } // // Instantiate the class. // System.Type c = null; try { c = serviceAssembly.GetType(className, true); } catch (System.Exception ex) { FailureException e = new FailureException(ex); e.reason = err + "GetType failed for '" + className + "'"; throw e; } ServiceInfo info = new ServiceInfo(); info.name = service; info.status = ServiceStatus.Stopped; info.args = args; // // If IceBox.UseSharedCommunicator.<name> is defined, create a // communicator for the service. The communicator inherits // from the shared communicator properties. If it's not // defined, add the service properties to the shared // commnunicator property set. // Ice.Communicator communicator; IceInternal.MetricsAdminI metricsAdmin = null; if (_communicator.getProperties().getPropertyAsInt("IceBox.UseSharedCommunicator." + service) > 0) { Debug.Assert(_sharedCommunicator != null); communicator = _sharedCommunicator; if (communicator.getObserver() is IceInternal.CommunicatorObserverI) { IceInternal.CommunicatorObserverI o = (IceInternal.CommunicatorObserverI)communicator.getObserver(); metricsAdmin = o.getMetricsAdmin(); } } else { // // Create the service properties. We use the communicator properties as the default // properties if IceBox.InheritProperties is set. // Ice.InitializationData initData = new Ice.InitializationData(); initData.properties = createServiceProperties(service); if (info.args.Length > 0) { // // Create the service properties with the given service arguments. This should // read the service config file if it's specified with --Ice.Config. // initData.properties = Ice.Util.createProperties(ref info.args, initData.properties); // // Next, parse the service "<service>.*" command line options (the Ice command // line options were parsed by the createProperties above) // info.args = initData.properties.parseCommandLineOptions(service, info.args); } // // Clone the logger to assign a new prefix. If one of the built-in loggers is configured // don't set any logger. // if (initData.properties.getProperty("Ice.LogFile").Length == 0 && (initData.properties.getPropertyAsInt("Ice.UseSyslog") == 0 || IceInternal.AssemblyUtil.platform_ == IceInternal.AssemblyUtil.Platform.Windows)) { initData.logger = _logger.cloneWithPrefix(initData.properties.getProperty("Ice.ProgramName")); } // // If Ice metrics are enabled on the IceBox communicator, we also enable them on // the service communicator. // if (_communicator.getObserver() is IceInternal.CommunicatorObserverI) { metricsAdmin = new IceInternal.MetricsAdminI(initData.properties, initData.logger); initData.observer = new IceInternal.CommunicatorObserverI(metricsAdmin); } // // Remaining command line options are passed to the communicator. This is // necessary for Ice plug-in properties (e.g.: IceSSL). // info.communicator = Ice.Util.initialize(ref info.args, initData); communicator = info.communicator; // // Ensure the metrics admin plugin uses the same property set as the // communicator. This is necessary to correctly deal with runtime // property updates. // if (metricsAdmin != null) { metricsAdmin.setProperties(communicator.getProperties()); } } try { // // Add a PropertiesAdmin facet to the service manager's communicator that provides // access to this service's property set. We do this prior to instantiating the // service so that the service's constructor is able to access the facet (e.g., // in case it wants to set a callback). // string facetName = "IceBox.Service." + info.name + ".Properties"; IceInternal.PropertiesAdminI propAdmin = new IceInternal.PropertiesAdminI(facetName, communicator.getProperties(), communicator.getLogger()); _communicator.addAdminFacet(propAdmin, facetName); // // If a metrics admin facet is setup for the service, register // it with the IceBox communicator. // if (metricsAdmin != null) { _communicator.addAdminFacet(metricsAdmin, "IceBox.Service." + info.name + ".Metrics"); // Ensure the metrics admin facet is notified of property updates. propAdmin.addUpdateCallback(metricsAdmin); } // // Instantiate the service. // try { // // If the service class provides a constructor that accepts an Ice.Communicator argument, // use that in preference to the default constructor. // Type[] parameterTypes = new Type[1]; parameterTypes[0] = typeof(Ice.Communicator); System.Reflection.ConstructorInfo ci = c.GetConstructor(parameterTypes); if (ci != null) { try { Object[] parameters = new Object[1]; parameters[0] = _communicator; info.service = (Service)ci.Invoke(parameters); } catch (System.MethodAccessException ex) { FailureException e = new FailureException(ex); e.reason = err + "unable to access service constructor " + className + "(Ice.Communicator)"; throw e; } } else { // // Fall back to the default constructor. // try { info.service = (Service)IceInternal.AssemblyUtil.createInstance(c); if (info.service == null) { FailureException e = new FailureException(); e.reason = err + "no default constructor for '" + className + "'"; throw e; } } catch (System.UnauthorizedAccessException ex) { FailureException e = new FailureException(ex); e.reason = err + "unauthorized access to default service constructor for " + className; throw e; } } } catch (FailureException) { throw; } catch (System.InvalidCastException ex) { FailureException e = new FailureException(ex); e.reason = err + "service does not implement IceBox.Service"; throw e; } catch (System.Reflection.TargetInvocationException ex) { if (ex.InnerException is IceBox.FailureException) { throw ex.InnerException; } else { FailureException e = new FailureException(ex.InnerException); e.reason = err + "exception in service constructor for " + className; throw e; } } catch (System.Exception ex) { FailureException e = new FailureException(ex); e.reason = err + "exception in service constructor " + className; throw e; } try { info.service.start(service, communicator, info.args); } catch (FailureException) { throw; } catch (System.Exception ex) { FailureException e = new FailureException(ex); e.reason = "exception while starting service " + service; throw e; } info.status = ServiceStatus.Started; _services.Add(info); } catch (Ice.ObjectAdapterDeactivatedException) { // // Can be raised by addAdminFacet if the service manager communicator has been shut down. // if (info.communicator != null) { destroyServiceCommunicator(service, info.communicator); } } catch (System.Exception ex) { try { _communicator.removeAdminFacet("IceBox.Service." + service + ".Properties"); } catch (Ice.LocalException) { // Ignored } if (info.communicator != null) { destroyServiceCommunicator(service, info.communicator); } throw ex; } } finally { _m.Unlock(); } }