internal MisfireHandler(JobStoreSupport jobStoreSupport) { this.jobStoreSupport = jobStoreSupport; string threadName = $"QuartzScheduler_{jobStoreSupport.InstanceName}-{jobStoreSupport.InstanceId}_MisfireHandler"; taskScheduler = new QueuedTaskScheduler(threadCount: 1, threadName: threadName, useForegroundThreads: !jobStoreSupport.MakeThreadsDaemons); cancellationTokenSource = new CancellationTokenSource(); }
/// <summary> </summary> private IScheduler Instantiate() { if (cfg == null) { Initialize(); } if (initException != null) { throw initException; } ISchedulerExporter exporter = null; IJobStore js; IThreadPool tp; QuartzScheduler qs = null; IDbConnectionManager dbMgr = null; Type instanceIdGeneratorType = null; NameValueCollection tProps; bool autoId = false; TimeSpan idleWaitTime = TimeSpan.Zero; TimeSpan dbFailureRetry = TimeSpan.FromSeconds(15); IThreadExecutor threadExecutor; SchedulerRepository schedRep = SchedulerRepository.Instance; // Get Scheduler Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string schedName = cfg.GetStringProperty(PropertySchedulerInstanceName, "QuartzScheduler"); string threadName = cfg.GetStringProperty(PropertySchedulerThreadName, "{0}_QuartzSchedulerThread".FormatInvariant(schedName)); string schedInstId = cfg.GetStringProperty(PropertySchedulerInstanceId, DefaultInstanceId); if (schedInstId.Equals(AutoGenerateInstanceId)) { autoId = true; instanceIdGeneratorType = LoadType(cfg.GetStringProperty(PropertySchedulerInstanceIdGeneratorType)) ?? typeof(SimpleInstanceIdGenerator); } else if (schedInstId.Equals(SystemPropertyAsInstanceId)) { autoId = true; instanceIdGeneratorType = typeof(SystemPropertyInstanceIdGenerator); } Type typeLoadHelperType = LoadType(cfg.GetStringProperty(PropertySchedulerTypeLoadHelperType)); Type jobFactoryType = LoadType(cfg.GetStringProperty(PropertySchedulerJobFactoryType, null)); idleWaitTime = cfg.GetTimeSpanProperty(PropertySchedulerIdleWaitTime, idleWaitTime); if (idleWaitTime > TimeSpan.Zero && idleWaitTime < TimeSpan.FromMilliseconds(1000)) { throw new SchedulerException("quartz.scheduler.idleWaitTime of less than 1000ms is not legal."); } dbFailureRetry = cfg.GetTimeSpanProperty(PropertySchedulerDbFailureRetryInterval, dbFailureRetry); if (dbFailureRetry < TimeSpan.Zero) { throw new SchedulerException(PropertySchedulerDbFailureRetryInterval + " of less than 0 ms is not legal."); } bool makeSchedulerThreadDaemon = cfg.GetBooleanProperty(PropertySchedulerMakeSchedulerThreadDaemon); long batchTimeWindow = cfg.GetLongProperty(PropertySchedulerBatchTimeWindow, 0L); int maxBatchSize = cfg.GetIntProperty(PropertySchedulerMaxBatchSize, 1); bool interruptJobsOnShutdown = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdown, false); bool interruptJobsOnShutdownWithWait = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdownWithWait, false); NameValueCollection schedCtxtProps = cfg.GetPropertyGroup(PropertySchedulerContextPrefix, true); bool proxyScheduler = cfg.GetBooleanProperty(PropertySchedulerProxy, false); // Create type load helper ITypeLoadHelper loadHelper; try { loadHelper = ObjectUtils.InstantiateType <ITypeLoadHelper>(typeLoadHelperType ?? typeof(SimpleTypeLoadHelper)); } catch (Exception e) { throw new SchedulerConfigException("Unable to instantiate type load helper: {0}".FormatInvariant(e.Message), e); } loadHelper.Initialize(); // If Proxying to remote scheduler, short-circuit here... // ~~~~~~~~~~~~~~~~~~ if (proxyScheduler) { if (autoId) { schedInstId = DefaultInstanceId; } Type proxyType = loadHelper.LoadType(cfg.GetStringProperty(PropertySchedulerProxyType)) ?? typeof(RemotingSchedulerProxyFactory); IRemotableSchedulerProxyFactory factory; try { factory = ObjectUtils.InstantiateType <IRemotableSchedulerProxyFactory>(proxyType); ObjectUtils.SetObjectProperties(factory, cfg.GetPropertyGroup(PropertySchedulerProxy, true)); } catch (Exception e) { initException = new SchedulerException("Remotable proxy factory '{0}' could not be instantiated.".FormatInvariant(proxyType), e); throw initException; } string uid = QuartzSchedulerResources.GetUniqueIdentifier(schedName, schedInstId); RemoteScheduler remoteScheduler = new RemoteScheduler(uid, factory); schedRep.Bind(remoteScheduler); return(remoteScheduler); } IJobFactory jobFactory = null; if (jobFactoryType != null) { try { jobFactory = ObjectUtils.InstantiateType <IJobFactory>(jobFactoryType); } catch (Exception e) { throw new SchedulerConfigException("Unable to Instantiate JobFactory: {0}".FormatInvariant(e.Message), e); } tProps = cfg.GetPropertyGroup(PropertySchedulerJobFactoryPrefix, true); try { ObjectUtils.SetObjectProperties(jobFactory, tProps); } catch (Exception e) { initException = new SchedulerException("JobFactory of type '{0}' props could not be configured.".FormatInvariant(jobFactoryType), e); throw initException; } } IInstanceIdGenerator instanceIdGenerator = null; if (instanceIdGeneratorType != null) { try { instanceIdGenerator = ObjectUtils.InstantiateType <IInstanceIdGenerator>(instanceIdGeneratorType); } catch (Exception e) { throw new SchedulerConfigException("Unable to Instantiate InstanceIdGenerator: {0}".FormatInvariant(e.Message), e); } tProps = cfg.GetPropertyGroup(PropertySchedulerInstanceIdGeneratorPrefix, true); try { ObjectUtils.SetObjectProperties(instanceIdGenerator, tProps); } catch (Exception e) { initException = new SchedulerException("InstanceIdGenerator of type '{0}' props could not be configured.".FormatInvariant(instanceIdGeneratorType), e); throw initException; } } // Get ThreadPool Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type tpType = loadHelper.LoadType(cfg.GetStringProperty(PropertyThreadPoolType)) ?? typeof(SimpleThreadPool); try { tp = ObjectUtils.InstantiateType <IThreadPool>(tpType); } catch (Exception e) { initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e); throw initException; } tProps = cfg.GetPropertyGroup(PropertyThreadPoolPrefix, true); try { ObjectUtils.SetObjectProperties(tp, tProps); } catch (Exception e) { initException = new SchedulerException("ThreadPool type '{0}' props could not be configured.".FormatInvariant(tpType), e); throw initException; } // Set up any DataSources // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IList <string> dsNames = cfg.GetPropertyGroups(PropertyDataSourcePrefix); foreach (string dataSourceName in dsNames) { string datasourceKey = "{0}.{1}".FormatInvariant(PropertyDataSourcePrefix, dataSourceName); NameValueCollection propertyGroup = cfg.GetPropertyGroup(datasourceKey, true); PropertiesParser pp = new PropertiesParser(propertyGroup); Type cpType = loadHelper.LoadType(pp.GetStringProperty(PropertyDbProviderType, null)); // custom connectionProvider... if (cpType != null) { IDbProvider cp; try { cp = ObjectUtils.InstantiateType <IDbProvider>(cpType); } catch (Exception e) { initException = new SchedulerException("ConnectionProvider of type '{0}' could not be instantiated.".FormatInvariant(cpType), e); throw initException; } try { // remove the type name, so it isn't attempted to be set pp.UnderlyingProperties.Remove(PropertyDbProviderType); ObjectUtils.SetObjectProperties(cp, pp.UnderlyingProperties); cp.Initialize(); } catch (Exception e) { initException = new SchedulerException("ConnectionProvider type '{0}' props could not be configured.".FormatInvariant(cpType), e); throw initException; } dbMgr = DBConnectionManager.Instance; dbMgr.AddConnectionProvider(dataSourceName, cp); } else { string dsProvider = pp.GetStringProperty(PropertyDataSourceProvider, null); string dsConnectionString = pp.GetStringProperty(PropertyDataSourceConnectionString, null); string dsConnectionStringName = pp.GetStringProperty(PropertyDataSourceConnectionStringName, null); if (dsConnectionString == null && !String.IsNullOrEmpty(dsConnectionStringName)) { ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[dsConnectionStringName]; if (connectionStringSettings == null) { initException = new SchedulerException("Named connection string '{0}' not found for DataSource: {1}".FormatInvariant(dsConnectionStringName, dataSourceName)); throw initException; } dsConnectionString = connectionStringSettings.ConnectionString; } if (dsProvider == null) { initException = new SchedulerException("Provider not specified for DataSource: {0}".FormatInvariant(dataSourceName)); throw initException; } if (dsConnectionString == null) { initException = new SchedulerException("Connection string not specified for DataSource: {0}".FormatInvariant(dataSourceName)); throw initException; } try { DbProvider dbp = new DbProvider(dsProvider, dsConnectionString); dbp.Initialize(); dbMgr = DBConnectionManager.Instance; dbMgr.AddConnectionProvider(dataSourceName, dbp); } catch (Exception exception) { initException = new SchedulerException("Could not Initialize DataSource: {0}".FormatInvariant(dataSourceName), exception); throw initException; } } } // Get object serializer properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IObjectSerializer objectSerializer; string objectSerializerType = cfg.GetStringProperty("quartz.serializer.type"); if (objectSerializerType != null) { tProps = cfg.GetPropertyGroup(PropertyObjectSerializer, true); try { objectSerializer = ObjectUtils.InstantiateType <IObjectSerializer>(loadHelper.LoadType(objectSerializerType)); log.Info("Using custom implementation for object serializer: " + objectSerializerType); ObjectUtils.SetObjectProperties(objectSerializer, tProps); } catch (Exception e) { initException = new SchedulerException("Object serializer type '" + objectSerializerType + "' could not be instantiated.", e); throw initException; } } else { log.Info("Using default implementation for object serializer"); objectSerializer = new DefaultObjectSerializer(); } // Get JobStore Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type jsType = loadHelper.LoadType(cfg.GetStringProperty(PropertyJobStoreType)); try { js = ObjectUtils.InstantiateType <IJobStore>(jsType ?? typeof(RAMJobStore)); } catch (Exception e) { initException = new SchedulerException("JobStore of type '{0}' could not be instantiated.".FormatInvariant(jsType), e); throw initException; } SchedulerDetailsSetter.SetDetails(js, schedName, schedInstId); tProps = cfg.GetPropertyGroup(PropertyJobStorePrefix, true, new string[] { PropertyJobStoreLockHandlerPrefix }); try { ObjectUtils.SetObjectProperties(js, tProps); } catch (Exception e) { initException = new SchedulerException("JobStore type '{0}' props could not be configured.".FormatInvariant(jsType), e); throw initException; } JobStoreSupport jobStoreSupport = js as JobStoreSupport; if (jobStoreSupport != null) { // Install custom lock handler (Semaphore) Type lockHandlerType = loadHelper.LoadType(cfg.GetStringProperty(PropertyJobStoreLockHandlerType)); if (lockHandlerType != null) { try { ISemaphore lockHandler; ConstructorInfo cWithDbProvider = lockHandlerType.GetConstructor(new Type[] { typeof(DbProvider) }); if (cWithDbProvider != null) { // takes db provider IDbProvider dbProvider = DBConnectionManager.Instance.GetDbProvider(jobStoreSupport.DataSource); lockHandler = (ISemaphore)cWithDbProvider.Invoke(new object[] { dbProvider }); } else { lockHandler = ObjectUtils.InstantiateType <ISemaphore>(lockHandlerType); } tProps = cfg.GetPropertyGroup(PropertyJobStoreLockHandlerPrefix, true); // If this lock handler requires the table prefix, add it to its properties. if (lockHandler is ITablePrefixAware) { tProps[PropertyTablePrefix] = jobStoreSupport.TablePrefix; tProps[PropertySchedulerName] = schedName; } try { ObjectUtils.SetObjectProperties(lockHandler, tProps); } catch (Exception e) { initException = new SchedulerException("JobStore LockHandler type '{0}' props could not be configured.".FormatInvariant(lockHandlerType), e); throw initException; } jobStoreSupport.LockHandler = lockHandler; Log.Info("Using custom data access locking (synchronization): " + lockHandlerType); } catch (Exception e) { initException = new SchedulerException("JobStore LockHandler type '{0}' could not be instantiated.".FormatInvariant(lockHandlerType), e); throw initException; } } } // Set up any SchedulerPlugins // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IList <string> pluginNames = cfg.GetPropertyGroups(PropertyPluginPrefix); ISchedulerPlugin[] plugins = new ISchedulerPlugin[pluginNames.Count]; for (int i = 0; i < pluginNames.Count; i++) { NameValueCollection pp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyPluginPrefix, pluginNames[i]), true); string plugInType = pp[PropertyPluginType]; if (plugInType == null) { initException = new SchedulerException("SchedulerPlugin type not specified for plugin '{0}'".FormatInvariant(pluginNames[i])); throw initException; } ISchedulerPlugin plugin; try { plugin = ObjectUtils.InstantiateType <ISchedulerPlugin>(LoadType(plugInType)); } catch (Exception e) { initException = new SchedulerException("SchedulerPlugin of type '{0}' could not be instantiated.".FormatInvariant(plugInType), e); throw initException; } try { ObjectUtils.SetObjectProperties(plugin, pp); } catch (Exception e) { initException = new SchedulerException("JobStore SchedulerPlugin '{0}' props could not be configured.".FormatInvariant(plugInType), e); throw initException; } plugins[i] = plugin; } // Set up any JobListeners // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IList <string> jobListenerNames = cfg.GetPropertyGroups(PropertyJobListenerPrefix); IJobListener[] jobListeners = new IJobListener[jobListenerNames.Count]; for (int i = 0; i < jobListenerNames.Count; i++) { NameValueCollection lp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyJobListenerPrefix, jobListenerNames[i]), true); string listenerType = lp[PropertyListenerType]; if (listenerType == null) { initException = new SchedulerException("JobListener type not specified for listener '{0}'".FormatInvariant(jobListenerNames[i])); throw initException; } IJobListener listener; try { listener = ObjectUtils.InstantiateType <IJobListener>(loadHelper.LoadType(listenerType)); } catch (Exception e) { initException = new SchedulerException("JobListener of type '{0}' could not be instantiated.".FormatInvariant(listenerType), e); throw initException; } try { PropertyInfo nameProperty = listener.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance); if (nameProperty != null && nameProperty.CanWrite) { nameProperty.GetSetMethod().Invoke(listener, new object[] { jobListenerNames[i] }); } ObjectUtils.SetObjectProperties(listener, lp); } catch (Exception e) { initException = new SchedulerException("JobListener '{0}' props could not be configured.".FormatInvariant(listenerType), e); throw initException; } jobListeners[i] = listener; } // Set up any TriggerListeners // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IList <string> triggerListenerNames = cfg.GetPropertyGroups(PropertyTriggerListenerPrefix); ITriggerListener[] triggerListeners = new ITriggerListener[triggerListenerNames.Count]; for (int i = 0; i < triggerListenerNames.Count; i++) { NameValueCollection lp = cfg.GetPropertyGroup("{0}.{1}".FormatInvariant(PropertyTriggerListenerPrefix, triggerListenerNames[i]), true); string listenerType = lp[PropertyListenerType]; if (listenerType == null) { initException = new SchedulerException("TriggerListener type not specified for listener '{0}'".FormatInvariant(triggerListenerNames[i])); throw initException; } ITriggerListener listener; try { listener = ObjectUtils.InstantiateType <ITriggerListener>(loadHelper.LoadType(listenerType)); } catch (Exception e) { initException = new SchedulerException("TriggerListener of type '{0}' could not be instantiated.".FormatInvariant(listenerType), e); throw initException; } try { PropertyInfo nameProperty = listener.GetType().GetProperty("Name", BindingFlags.Public | BindingFlags.Instance); if (nameProperty != null && nameProperty.CanWrite) { nameProperty.GetSetMethod().Invoke(listener, new object[] { triggerListenerNames[i] }); } ObjectUtils.SetObjectProperties(listener, lp); } catch (Exception e) { initException = new SchedulerException("TriggerListener '{0}' props could not be configured.".FormatInvariant(listenerType), e); throw initException; } triggerListeners[i] = listener; } // Get exporter // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string exporterType = cfg.GetStringProperty(PropertySchedulerExporterType, null); if (exporterType != null) { try { exporter = ObjectUtils.InstantiateType <ISchedulerExporter>(loadHelper.LoadType(exporterType)); } catch (Exception e) { initException = new SchedulerException("Scheduler exporter of type '{0}' could not be instantiated.".FormatInvariant(exporterType), e); throw initException; } tProps = cfg.GetPropertyGroup(PropertySchedulerExporterPrefix, true); try { ObjectUtils.SetObjectProperties(exporter, tProps); } catch (Exception e) { initException = new SchedulerException("Scheduler exporter type '{0}' props could not be configured.".FormatInvariant(exporterType), e); throw initException; } } bool tpInited = false; bool qsInited = false; // Get ThreadExecutor Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string threadExecutorClass = cfg.GetStringProperty(PropertyThreadExecutorType); if (threadExecutorClass != null) { tProps = cfg.GetPropertyGroup(PropertyThreadExecutor, true); try { threadExecutor = ObjectUtils.InstantiateType <IThreadExecutor>(loadHelper.LoadType(threadExecutorClass)); log.Info("Using custom implementation for ThreadExecutor: " + threadExecutorClass); ObjectUtils.SetObjectProperties(threadExecutor, tProps); } catch (Exception e) { initException = new SchedulerException( "ThreadExecutor class '" + threadExecutorClass + "' could not be instantiated.", e); throw initException; } } else { log.Info("Using default implementation for ThreadExecutor"); threadExecutor = new DefaultThreadExecutor(); } // Fire everything up // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ try { IJobRunShellFactory jrsf = new StdJobRunShellFactory(); if (autoId) { try { schedInstId = DefaultInstanceId; if (js.Clustered) { schedInstId = instanceIdGenerator.GenerateInstanceId(); } } catch (Exception e) { Log.Error("Couldn't generate instance Id!", e); throw new SystemException("Cannot run without an instance id."); } } jobStoreSupport = js as JobStoreSupport; if (jobStoreSupport != null) { jobStoreSupport.DbRetryInterval = dbFailureRetry; jobStoreSupport.ThreadExecutor = threadExecutor; // object serializer jobStoreSupport.ObjectSerializer = objectSerializer; } QuartzSchedulerResources rsrcs = new QuartzSchedulerResources(); rsrcs.Name = schedName; rsrcs.ThreadName = threadName; rsrcs.InstanceId = schedInstId; rsrcs.JobRunShellFactory = jrsf; rsrcs.MakeSchedulerThreadDaemon = makeSchedulerThreadDaemon; rsrcs.BatchTimeWindow = TimeSpan.FromMilliseconds(batchTimeWindow); rsrcs.MaxBatchSize = maxBatchSize; rsrcs.InterruptJobsOnShutdown = interruptJobsOnShutdown; rsrcs.InterruptJobsOnShutdownWithWait = interruptJobsOnShutdownWithWait; rsrcs.SchedulerExporter = exporter; SchedulerDetailsSetter.SetDetails(tp, schedName, schedInstId); rsrcs.ThreadExecutor = threadExecutor; threadExecutor.Initialize(); rsrcs.ThreadPool = tp; tp.Initialize(); tpInited = true; rsrcs.JobStore = js; // add plugins foreach (ISchedulerPlugin plugin in plugins) { rsrcs.AddSchedulerPlugin(plugin); } qs = new QuartzScheduler(rsrcs, idleWaitTime); qsInited = true; // Create Scheduler ref... IScheduler sched = Instantiate(rsrcs, qs); // set job factory if specified if (jobFactory != null) { qs.JobFactory = jobFactory; } // Initialize plugins now that we have a Scheduler instance. for (int i = 0; i < plugins.Length; i++) { plugins[i].Initialize(pluginNames[i], sched); } // add listeners foreach (IJobListener listener in jobListeners) { qs.ListenerManager.AddJobListener(listener, EverythingMatcher <JobKey> .AllJobs()); } foreach (ITriggerListener listener in triggerListeners) { qs.ListenerManager.AddTriggerListener(listener, EverythingMatcher <TriggerKey> .AllTriggers()); } // set scheduler context data... foreach (string key in schedCtxtProps) { string val = schedCtxtProps.Get(key); sched.Context.Put(key, val); } // fire up job store, and runshell factory js.InstanceId = schedInstId; js.InstanceName = schedName; js.ThreadPoolSize = tp.PoolSize; js.Initialize(loadHelper, qs.SchedulerSignaler); jrsf.Initialize(sched); qs.Initialize(); Log.Info("Quartz scheduler '{0}' initialized".FormatInvariant(sched.SchedulerName)); Log.Info("Quartz scheduler version: {0}".FormatInvariant(qs.Version)); // prevents the repository from being garbage collected qs.AddNoGCObject(schedRep); // prevents the db manager from being garbage collected if (dbMgr != null) { qs.AddNoGCObject(dbMgr); } schedRep.Bind(sched); return(sched); } catch (SchedulerException) { ShutdownFromInstantiateException(tp, qs, tpInited, qsInited); throw; } catch { ShutdownFromInstantiateException(tp, qs, tpInited, qsInited); throw; } }
internal ClusterManager(JobStoreSupport jobStoreSupport) { this.jobStoreSupport = jobStoreSupport; cancellationTokenSource = new CancellationTokenSource(); }
internal ClusterManager(JobStoreSupport jobStoreSupport) { this.jobStoreSupport = jobStoreSupport; cancellationTokenSource = new CancellationTokenSource(); log = LogProvider.GetLogger(typeof(ClusterManager)); }
/// <summary> </summary> private IScheduler Instantiate() { if (cfg == null) { Initialize(); } if (initException != null) { throw initException; } ISchedulerExporter exporter = null; IJobStore js; IThreadPool tp; QuartzScheduler qs = null; DBConnectionManager dbMgr = null; string instanceIdGeneratorType = null; NameValueCollection tProps; bool autoId = false; TimeSpan idleWaitTime = TimeSpan.Zero; TimeSpan dbFailureRetry = TimeSpan.Zero; string typeLoadHelperType; string jobFactoryType; SchedulerRepository schedRep = SchedulerRepository.Instance; // Get Scheduler Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string schedName = cfg.GetStringProperty(PropertySchedulerInstanceName, "QuartzScheduler"); string threadName = cfg.GetStringProperty(PropertySchedulerThreadName, string.Format(CultureInfo.InvariantCulture, "{0}_QuartzSchedulerThread", schedName)); string schedInstId = cfg.GetStringProperty(PropertySchedulerInstanceId, DefaultInstanceId); if (schedInstId.Equals(AutoGenerateInstanceId)) { autoId = true; instanceIdGeneratorType = cfg.GetStringProperty(PropertySchedulerInstanceIdGeneratorType, "Quartz.Simpl.SimpleInstanceIdGenerator, Quartz"); } typeLoadHelperType = cfg.GetStringProperty(PropertySchedulerTypeLoadHelperType, "Quartz.Simpl.SimpleTypeLoadHelper, Quartz"); jobFactoryType = cfg.GetStringProperty(PropertySchedulerJobFactoryType, null); idleWaitTime = cfg.GetTimeSpanProperty(PropertySchedulerIdleWaitTime, idleWaitTime); dbFailureRetry = cfg.GetTimeSpanProperty(PropertySchedulerDbFailureRetryInterval, dbFailureRetry); bool makeSchedulerThreadDaemon = cfg.GetBooleanProperty(PropertySchedulerMakeSchedulerThreadDaemon); long batchTimeWindow = cfg.GetLongProperty(PropertySchedulerBatchTimeWindow, 0L); int maxBatchSize = cfg.GetIntProperty(PropertySchedulerMaxBatchSize, 10); bool interruptJobsOnShutdown = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdown, false); bool interruptJobsOnShutdownWithWait = cfg.GetBooleanProperty(PropertySchedulerInterruptJobsOnShutdownWithWait, false); NameValueCollection schedCtxtProps = cfg.GetPropertyGroup(PropertySchedulerContextPrefix, true); bool proxyScheduler = cfg.GetBooleanProperty(PropertySchedulerProxy, false); // If Proxying to remote scheduler, short-circuit here... // ~~~~~~~~~~~~~~~~~~ if (proxyScheduler) { if (autoId) { schedInstId = DefaultInstanceId; } string uid = QuartzSchedulerResources.GetUniqueIdentifier(schedName, schedInstId); RemoteScheduler remoteScheduler = new RemoteScheduler(uid); string remoteSchedulerAddress = cfg.GetStringProperty(PropertySchedulerProxyAddress); remoteScheduler.RemoteSchedulerAddress = remoteSchedulerAddress; schedRep.Bind(remoteScheduler); return(remoteScheduler); } // Create type load helper ITypeLoadHelper loadHelper; try { loadHelper = ObjectUtils.InstantiateType <ITypeLoadHelper>(LoadType(typeLoadHelperType)); } catch (Exception e) { throw new SchedulerConfigException( string.Format(CultureInfo.InvariantCulture, "Unable to instantiate type load helper: {0}", e.Message), e); } loadHelper.Initialize(); IJobFactory jobFactory = null; if (jobFactoryType != null) { try { jobFactory = ObjectUtils.InstantiateType <IJobFactory>(loadHelper.LoadType(jobFactoryType)); } catch (Exception e) { throw new SchedulerConfigException( string.Format(CultureInfo.InvariantCulture, "Unable to Instantiate JobFactory: {0}", e.Message), e); } tProps = cfg.GetPropertyGroup(PropertySchedulerJobFactoryPrefix, true); try { ObjectUtils.SetObjectProperties(jobFactory, tProps); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobFactory of type '{0}' props could not be configured.", jobFactoryType), e); throw initException; } } IInstanceIdGenerator instanceIdGenerator = null; if (instanceIdGeneratorType != null) { try { instanceIdGenerator = ObjectUtils.InstantiateType <IInstanceIdGenerator>(loadHelper.LoadType(instanceIdGeneratorType)); } catch (Exception e) { throw new SchedulerConfigException( string.Format(CultureInfo.InvariantCulture, "Unable to Instantiate InstanceIdGenerator: {0}", e.Message), e); } tProps = cfg.GetPropertyGroup(PropertySchedulerInstanceIdGeneratorPrefix, true); try { ObjectUtils.SetObjectProperties(instanceIdGenerator, tProps); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "InstanceIdGenerator of type '{0}' props could not be configured.", instanceIdGeneratorType), e); throw initException; } } // Get ThreadPool Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string tpType = cfg.GetStringProperty(PropertyThreadPoolType, typeof(SimpleThreadPool).AssemblyQualifiedName); if (tpType == null) { initException = new SchedulerException("ThreadPool type not specified. "); throw initException; } try { tp = ObjectUtils.InstantiateType <IThreadPool>(loadHelper.LoadType(tpType)); } catch (Exception e) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "ThreadPool type '{0}' could not be instantiated.", tpType), e); throw initException; } tProps = cfg.GetPropertyGroup(PropertyThreadPoolPrefix, true); try { ObjectUtils.SetObjectProperties(tp, tProps); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "ThreadPool type '{0}' props could not be configured.", tpType), e); throw initException; } // Set up any DataSources // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string[] dsNames = cfg.GetPropertyGroups(PropertyDataSourcePrefix); for (int i = 0; i < dsNames.Length; i++) { PropertiesParser pp = new PropertiesParser( cfg.GetPropertyGroup(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", PropertyDataSourcePrefix, dsNames[i]), true)); string cpType = pp.GetStringProperty(PropertyDbProviderType, null); // custom connectionProvider... if (cpType != null) { IDbProvider cp; try { cp = ObjectUtils.InstantiateType <IDbProvider>(loadHelper.LoadType(cpType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "ConnectionProvider of type '{0}' could not be instantiated.", cpType), e); throw initException; } try { // remove the type name, so it isn't attempted to be set pp.UnderlyingProperties.Remove(PropertyDbProviderType); ObjectUtils.SetObjectProperties(cp, pp.UnderlyingProperties); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "ConnectionProvider type '{0}' props could not be configured.", cpType), e); throw initException; } dbMgr = DBConnectionManager.Instance; dbMgr.AddConnectionProvider(dsNames[i], cp); } else { string dsProvider = pp.GetStringProperty(PropertyDataSourceProvider, null); string dsConnectionString = pp.GetStringProperty(PropertyDataSourceConnectionString, null); string dsConnectionStringName = pp.GetStringProperty(PropertyDataSourceConnectionStringName, null); if (dsConnectionString == null && !String.IsNullOrEmpty(dsConnectionStringName)) { ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[dsConnectionStringName]; if (connectionStringSettings == null) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Named connection string '{0}' not found for DataSource: {1}", dsConnectionStringName, dsNames[i])); throw initException; } dsConnectionString = connectionStringSettings.ConnectionString; } if (dsProvider == null) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Provider not specified for DataSource: {0}", dsNames[i])); throw initException; } if (dsConnectionString == null) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Connection string not specified for DataSource: {0}", dsNames[i])); throw initException; } try { DbProvider dbp = new DbProvider(dsProvider, dsConnectionString); dbMgr = DBConnectionManager.Instance; dbMgr.AddConnectionProvider(dsNames[i], dbp); } catch (Exception exception) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Could not Initialize DataSource: {0}", dsNames[i]), exception); throw initException; } } } // Get JobStore Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string jsType = cfg.GetStringProperty(PropertyJobStoreType, typeof(RAMJobStore).FullName); if (jsType == null) { initException = new SchedulerException("JobStore type not specified. "); throw initException; } try { js = ObjectUtils.InstantiateType <IJobStore>(loadHelper.LoadType(jsType)); } catch (Exception e) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "JobStore of type '{0}' could not be instantiated.", jsType), e); throw initException; } SchedulerDetailsSetter.SetDetails(js, schedName, schedInstId); tProps = cfg.GetPropertyGroup(PropertyJobStorePrefix, true, new string[] { PropertyJobStoreLockHandlerPrefix }); try { ObjectUtils.SetObjectProperties(js, tProps); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobStore type '{0}' props could not be configured.", jsType), e); throw initException; } if (js is JobStoreSupport) { // Install custom lock handler (Semaphore) string lockHandlerTypeName = cfg.GetStringProperty(PropertyJobStoreLockHandlerType); if (lockHandlerTypeName != null) { try { Type lockHandlerType = loadHelper.LoadType(lockHandlerTypeName); ISemaphore lockHandler; ConstructorInfo cWithDbProvider = lockHandlerType.GetConstructor(new Type[] { typeof(DbProvider) }); if (cWithDbProvider != null) { // takes db provider IDbProvider dbProvider = DBConnectionManager.Instance.GetDbProvider(((JobStoreSupport)js).DataSource); lockHandler = (ISemaphore)cWithDbProvider.Invoke(new object[] { dbProvider }); } else { lockHandler = ObjectUtils.InstantiateType <ISemaphore>(lockHandlerType); } tProps = cfg.GetPropertyGroup(PropertyJobStoreLockHandlerPrefix, true); // If this lock handler requires the table prefix, add it to its properties. if (lockHandler is ITablePrefixAware) { tProps[PropertyTablePrefix] = ((JobStoreSupport)js).TablePrefix; tProps[PropertySchedulerName] = schedName; } try { ObjectUtils.SetObjectProperties(lockHandler, tProps); } catch (Exception e) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "JobStore LockHandler type '{0}' props could not be configured.", lockHandlerTypeName), e); throw initException; } ((JobStoreSupport)js).LockHandler = lockHandler; Log.Info("Using custom data access locking (synchronization): " + lockHandlerType); } catch (Exception e) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "JobStore LockHandler type '{0}' could not be instantiated.", lockHandlerTypeName), e); throw initException; } } } // Set up any SchedulerPlugins // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string[] pluginNames = cfg.GetPropertyGroups(PropertyPluginPrefix); ISchedulerPlugin[] plugins = new ISchedulerPlugin[pluginNames.Length]; for (int i = 0; i < pluginNames.Length; i++) { NameValueCollection pp = cfg.GetPropertyGroup(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", PropertyPluginPrefix, pluginNames[i]), true); string plugInType = pp[PropertyPluginType] ?? null; if (plugInType == null) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "SchedulerPlugin type not specified for plugin '{0}'", pluginNames[i])); throw initException; } ISchedulerPlugin plugin; try { plugin = ObjectUtils.InstantiateType <ISchedulerPlugin>(LoadType(plugInType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "SchedulerPlugin of type '{0}' could not be instantiated.", plugInType), e); throw initException; } try { ObjectUtils.SetObjectProperties(plugin, pp); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobStore SchedulerPlugin '{0}' props could not be configured.", plugInType), e); throw initException; } plugins[i] = plugin; } // Set up any JobListeners // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type[] strArg = new Type[] { typeof(string) }; string[] jobListenerNames = cfg.GetPropertyGroups(PropertyJobListenerPrefix); IJobListener[] jobListeners = new IJobListener[jobListenerNames.Length]; for (int i = 0; i < jobListenerNames.Length; i++) { NameValueCollection lp = cfg.GetPropertyGroup(string.Format(CultureInfo.InvariantCulture, "{0}.{1}", PropertyJobListenerPrefix, jobListenerNames[i]), true); string listenerType = lp[PropertyListenerType]; if (listenerType == null) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobListener type not specified for listener '{0}'", jobListenerNames[i])); throw initException; } IJobListener listener; try { listener = ObjectUtils.InstantiateType <IJobListener>(loadHelper.LoadType(listenerType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobListener of type '{0}' could not be instantiated.", listenerType), e); throw initException; } try { MethodInfo nameSetter = listener.GetType().GetMethod("setName", strArg); if (nameSetter != null) { nameSetter.Invoke(listener, new object[] { jobListenerNames[i] }); } ObjectUtils.SetObjectProperties(listener, lp); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobListener '{0}' props could not be configured.", listenerType), e); throw initException; } jobListeners[i] = listener; } // Set up any TriggerListeners // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string[] triggerListenerNames = cfg.GetPropertyGroups(PropertyTriggerListenerPrefix); ITriggerListener[] triggerListeners = new ITriggerListener[triggerListenerNames.Length]; for (int i = 0; i < triggerListenerNames.Length; i++) { NameValueCollection lp = cfg.GetPropertyGroup( string.Format(CultureInfo.InvariantCulture, "{0}.{1}", PropertyTriggerListenerPrefix, triggerListenerNames[i]), true); string listenerType = lp[PropertyListenerType]; if (listenerType == null) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "TriggerListener type not specified for listener '{0}'", triggerListenerNames[i])); throw initException; } ITriggerListener listener; try { listener = ObjectUtils.InstantiateType <ITriggerListener>(loadHelper.LoadType(listenerType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "TriggerListener of type '{0}' could not be instantiated.", listenerType), e); throw initException; } try { MethodInfo nameSetter = listener.GetType().GetMethod("setName", strArg); if (nameSetter != null) { nameSetter.Invoke(listener, (new object[] { triggerListenerNames[i] })); } ObjectUtils.SetObjectProperties(listener, lp); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "TriggerListener '{0}' props could not be configured.", listenerType), e); throw initException; } triggerListeners[i] = listener; } // Get exporter // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string exporterType = cfg.GetStringProperty(PropertySchedulerExporterType, null); if (exporterType != null) { try { exporter = ObjectUtils.InstantiateType <ISchedulerExporter>(loadHelper.LoadType(exporterType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "Scheduler exporter of type '{0}' could not be instantiated.", exporterType), e); throw initException; } tProps = cfg.GetPropertyGroup(PropertySchedulerExporterPrefix, true); try { ObjectUtils.SetObjectProperties(exporter, tProps); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "Scheduler exporter type '{0}' props could not be configured.", exporterType), e); throw initException; } } bool tpInited = false; bool qsInited = false; // Fire everything up // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ try { IJobRunShellFactory jrsf = new StdJobRunShellFactory(); if (autoId) { try { schedInstId = DefaultInstanceId; if (js.Clustered) { schedInstId = instanceIdGenerator.GenerateInstanceId(); } } catch (Exception e) { Log.Error("Couldn't generate instance Id!", e); throw new SystemException("Cannot run without an instance id."); } } if (js is JobStoreSupport) { JobStoreSupport jjs = (JobStoreSupport)js; jjs.DbRetryInterval = dbFailureRetry; } QuartzSchedulerResources rsrcs = new QuartzSchedulerResources(); rsrcs.Name = schedName; rsrcs.ThreadName = threadName; rsrcs.InstanceId = schedInstId; rsrcs.JobRunShellFactory = jrsf; rsrcs.MakeSchedulerThreadDaemon = makeSchedulerThreadDaemon; rsrcs.BatchTimeWindow = TimeSpan.FromMilliseconds(batchTimeWindow); rsrcs.MaxBatchSize = maxBatchSize; rsrcs.InterruptJobsOnShutdown = interruptJobsOnShutdown; rsrcs.InterruptJobsOnShutdownWithWait = interruptJobsOnShutdownWithWait; rsrcs.SchedulerExporter = exporter; SchedulerDetailsSetter.SetDetails(tp, schedName, schedInstId); rsrcs.ThreadPool = tp; if (tp is SimpleThreadPool) { ((SimpleThreadPool)tp).ThreadNamePrefix = schedName + "_Worker"; } tp.Initialize(); tpInited = true; rsrcs.JobStore = js; // add plugins for (int i = 0; i < plugins.Length; i++) { rsrcs.AddSchedulerPlugin(plugins[i]); } qs = new QuartzScheduler(rsrcs, idleWaitTime, dbFailureRetry); qsInited = true; // Create Scheduler ref... IScheduler sched = Instantiate(rsrcs, qs); // set job factory if specified if (jobFactory != null) { qs.JobFactory = jobFactory; } // Initialize plugins now that we have a Scheduler instance. for (int i = 0; i < plugins.Length; i++) { plugins[i].Initialize(pluginNames[i], sched); } // add listeners for (int i = 0; i < jobListeners.Length; i++) { qs.ListenerManager.AddJobListener(jobListeners[i], EverythingMatcher <JobKey> .AllJobs()); } for (int i = 0; i < triggerListeners.Length; i++) { qs.ListenerManager.AddTriggerListener(triggerListeners[i], EverythingMatcher <TriggerKey> .AllTriggers()); } // set scheduler context data... foreach (string key in schedCtxtProps) { string val = schedCtxtProps.Get(key); sched.Context.Put(key, val); } // fire up job store, and runshell factory js.InstanceId = schedInstId; js.InstanceName = schedName; js.ThreadPoolSize = tp.PoolSize; js.Initialize(loadHelper, qs.SchedulerSignaler); jrsf.Initialize(sched); Log.Info(string.Format(CultureInfo.InvariantCulture, "Quartz scheduler '{0}' initialized", sched.SchedulerName)); Log.Info(string.Format(CultureInfo.InvariantCulture, "Quartz scheduler version: {0}", qs.Version)); // prevents the repository from being garbage collected qs.AddNoGCObject(schedRep); // prevents the db manager from being garbage collected if (dbMgr != null) { qs.AddNoGCObject(dbMgr); } schedRep.Bind(sched); return(sched); } catch (SchedulerException) { if (qsInited) { qs.Shutdown(false); } else if (tpInited) { tp.Shutdown(false); } throw; } catch { if (qsInited) { qs.Shutdown(false); } else if (tpInited) { tp.Shutdown(false); } throw; } }