/// <summary> /// Initializes the job execution context with given scheduler and bundle. /// </summary> /// <param name="sched">The scheduler.</param> /// <param name="firedBundle">The bundle offired triggers.</param> public virtual void Initialize(SchedulerScheduler sched, TriggerFiredBundle firedBundle) { qs = sched; IJob job; JobDetail jobDetail = firedBundle.JobDetail; try { job = sched.JobFactory.NewJob(firedBundle); } catch (SchedulerException se) { sched.NotifySchedulerListenersError(string.Format(CultureInfo.InvariantCulture, "An error occured instantiating job to be executed. job= '{0}'", jobDetail.FullName), se); throw; } catch (Exception e) { SchedulerException se = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Problem instantiating type '{0}'", jobDetail.JobType.FullName), e); sched.NotifySchedulerListenersError(string.Format(CultureInfo.InvariantCulture, "An error occured instantiating job to be executed. job= '{0}'", jobDetail.FullName), se); throw se; } jec = new JobExecutionContext(scheduler, firedBundle, job); }
public SchedulerSignalerImpl(SchedulerScheduler sched, SchedulerSchedulerThread schedThread) { this.sched = sched; this.schedThread = schedThread; log.Info("Initialized Scheduler Signaller of type: " + GetType()); }
/// <summary> /// Passivates this instance. /// </summary> public virtual void Passivate() { jec = null; qs = null; }
public DelayedSchedulerStarter(SchedulerScheduler scheduler, TimeSpan delay, ILog logger) { this.scheduler = scheduler; this.delay = delay; this.logger = logger; }
/// <summary> /// Creates a scheduler using the specified thread pool and job store and /// binds it to RMI. /// </summary> /// <param name="schedulerName">The name for the scheduler.</param> /// <param name="schedulerInstanceId">The instance ID for the scheduler.</param> /// <param name="threadPool">The thread pool for executing jobs</param> /// <param name="jobStore">The type of job store</param> /// <param name="schedulerPluginMap"></param> /// <param name="idleWaitTime">The idle wait time. You can specify TimeSpan.Zero for /// the default value, which is currently 30000 ms.</param> /// <param name="dbFailureRetryInterval">The db failure retry interval.</param> public virtual void CreateScheduler(string schedulerName, string schedulerInstanceId, IThreadPool threadPool, IJobStore jobStore, IDictionary schedulerPluginMap, TimeSpan idleWaitTime, TimeSpan dbFailureRetryInterval) { // Currently only one run-shell factory is available... IJobRunShellFactory jrsf = new StdJobRunShellFactory(); // Fire everything up // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SchedulingContext schedCtxt = new SchedulingContext(); schedCtxt.InstanceId = schedulerInstanceId; SchedulerSchedulerResources qrs = new SchedulerSchedulerResources(); qrs.Name = schedulerName; qrs.InstanceId = schedulerInstanceId; qrs.JobRunShellFactory = jrsf; qrs.ThreadPool = threadPool; qrs.JobStore = jobStore; // add plugins if (schedulerPluginMap != null) { foreach (ISchedulerPlugin plugin in schedulerPluginMap.Values) { qrs.AddSchedulerPlugin(plugin); } } SchedulerScheduler qs = new SchedulerScheduler(qrs, schedCtxt, idleWaitTime, dbFailureRetryInterval); ITypeLoadHelper cch = new CascadingClassLoadHelper(); cch.Initialize(); jobStore.Initialize(cch, qs.SchedulerSignaler); IScheduler scheduler = new StdScheduler(qs, schedCtxt); // Initialize plugins now that we have a Scheduler instance. if (schedulerPluginMap != null) { foreach (DictionaryEntry pluginEntry in schedulerPluginMap) { ((ISchedulerPlugin)pluginEntry.Value).Initialize( (string) pluginEntry.Key, scheduler); } } jrsf.Initialize(scheduler, schedCtxt); Log.Info(string.Format(CultureInfo.InvariantCulture, "Scheduler scheduler '{0}", scheduler.SchedulerName)); Log.Info(string.Format(CultureInfo.InvariantCulture, "Scheduler scheduler version: {0}", qs.Version)); SchedulerRepository schedRep = SchedulerRepository.Instance; qs.AddNoGCObject(schedRep); // prevents the repository from being // garbage collected schedRep.Bind(scheduler); }
/// <summary> /// The main processing loop of the <see cref="SchedulerSchedulerThread" />. /// </summary> public override void Run() { bool lastAcquireFailed = false; while (!halted) { try { // check if we're supposed to pause... lock (sigLock) { while (paused && !halted) { try { // wait until togglePause(false) is called... Monitor.Wait(sigLock, 1000); } catch (ThreadInterruptedException) { } } if (halted) { break; } } int availTreadCount = qsRsrcs.ThreadPool.BlockForAvailableThreads(); if (availTreadCount > 0) // will always be true, due to semantics of blockForAvailableThreads... { Trigger trigger = null; DateTime now = DateTime.UtcNow; ClearSignaledSchedulingChange(); try { trigger = qsRsrcs.JobStore.AcquireNextTrigger(ctxt, now.Add(idleWaitTime)); lastAcquireFailed = false; } catch (JobPersistenceException jpe) { if (!lastAcquireFailed) { qs.NotifySchedulerListenersError( "An error occured while scanning for the next trigger to fire.", jpe); } lastAcquireFailed = true; } catch (Exception e) { if (!lastAcquireFailed) { Log.Error("SchedulerSchedulerThreadLoop: RuntimeException " + e.Message, e); } lastAcquireFailed = true; } if (trigger != null) { now = DateTime.UtcNow; DateTime triggerTime = trigger.GetNextFireTimeUtc().Value; TimeSpan timeUntilTrigger = triggerTime - now; while (timeUntilTrigger > TimeSpan.Zero) { lock (sigLock) { try { // we could have blocked a long while // on 'synchronize', so we must recompute now = DateTime.UtcNow; timeUntilTrigger = triggerTime - now; if (timeUntilTrigger.TotalMilliseconds >= 1) { Monitor.Wait(sigLock, timeUntilTrigger); } } catch (ThreadInterruptedException) { } } if (IsScheduleChanged()) { if (IsCandidateNewTimeEarlierWithinReason(triggerTime)) { // above call does a clearSignaledSchedulingChange() try { qsRsrcs.JobStore.ReleaseAcquiredTrigger(ctxt, trigger); } catch (JobPersistenceException jpe) { qs.NotifySchedulerListenersError( "An error occured while releasing trigger '" + trigger.FullName + "'", jpe); // db connection must have failed... keep // retrying until it's up... ReleaseTriggerRetryLoop(trigger); } catch (Exception e) { Log.Error( "releaseTriggerRetryLoop: RuntimeException " + e.Message, e); // db connection must have failed... keep // retrying until it's up... ReleaseTriggerRetryLoop(trigger); } trigger = null; break; } } now = DateTime.UtcNow; timeUntilTrigger = triggerTime - now; } if (trigger == null) { continue; } // set trigger to 'executing' TriggerFiredBundle bndle = null; bool goAhead = true; lock (sigLock) { goAhead = !halted; } if(goAhead) { try { bndle = qsRsrcs.JobStore.TriggerFired(ctxt, trigger); } catch (SchedulerException se) { qs.NotifySchedulerListenersError( string.Format(CultureInfo.InvariantCulture, "An error occured while firing trigger '{0}'", trigger.FullName), se); } catch (Exception e) { Log.Error( string.Format(CultureInfo.InvariantCulture, "RuntimeException while firing trigger {0}", trigger.FullName), e); // db connection must have failed... keep // retrying until it's up... ReleaseTriggerRetryLoop(trigger); } } // it's possible to get 'null' if the trigger was paused, // blocked, or other similar occurrences that prevent it being // fired at this time... or if the scheduler was shutdown (halted) if (bndle == null) { try { qsRsrcs.JobStore.ReleaseAcquiredTrigger(ctxt, trigger); } catch (SchedulerException se) { qs.NotifySchedulerListenersError( string.Format(CultureInfo.InvariantCulture, "An error occured while releasing trigger '{0}'", trigger.FullName), se); // db connection must have failed... keep retrying // until it's up... ReleaseTriggerRetryLoop(trigger); } continue; } // TODO: improvements: // // 2- make sure we can get a job runshell before firing trigger, or // don't let that throw an exception (right now it never does, // but the signature says it can). // 3- acquire more triggers at a time (based on num threads available?) JobRunShell shell; try { shell = qsRsrcs.JobRunShellFactory.BorrowJobRunShell(); shell.Initialize(qs, bndle); } catch (SchedulerException) { try { qsRsrcs.JobStore.TriggeredJobComplete(ctxt, trigger, bndle.JobDetail, SchedulerInstruction. SetAllJobTriggersError); } catch (SchedulerException se2) { qs.NotifySchedulerListenersError( string.Format( CultureInfo.InvariantCulture, "An error occured while placing job's triggers in error state '{0}'", trigger.FullName), se2); // db connection must have failed... keep retrying // until it's up... ErrorTriggerRetryLoop(bndle); } continue; } if (qsRsrcs.ThreadPool.RunInThread(shell) == false) { try { // this case should never happen, as it is indicative of the // scheduler being shutdown or a bug in the thread pool or // a thread pool being used concurrently - which the docs // say not to do... Log.Error("ThreadPool.runInThread() return false!"); qsRsrcs.JobStore.TriggeredJobComplete(ctxt, trigger, bndle.JobDetail, SchedulerInstruction. SetAllJobTriggersError); } catch (SchedulerException se2) { qs.NotifySchedulerListenersError( string.Format(CultureInfo.InvariantCulture, "An error occured while placing job's triggers in error state '{0}'", trigger.FullName), se2); // db connection must have failed... keep retrying // until it's up... ReleaseTriggerRetryLoop(trigger); } } continue; } } else { // if(availTreadCount > 0) continue; // should never happen, if threadPool.blockForAvailableThreads() follows contract } DateTime utcNow = DateTime.UtcNow; DateTime waitTime = utcNow.Add(GetRandomizedIdleWaitTime()); TimeSpan timeUntilContinue = waitTime - utcNow; lock (sigLock) { try { Monitor.Wait(sigLock, timeUntilContinue); } catch (ThreadInterruptedException) { } } } catch (Exception re) { if (Log != null) { Log.Error("Runtime error occured in main trigger firing loop.", re); } } } // loop... // drop references to scheduler stuff to aid garbage collection... qs = null; qsRsrcs = null; }
/// <summary> /// Construct a new <see cref="SchedulerSchedulerThread" /> for the given /// <see cref="SchedulerScheduler" /> as a <see cref="Thread" /> with the given /// attributes. /// </summary> internal SchedulerSchedulerThread(SchedulerScheduler qs, SchedulerSchedulerResources qsRsrcs, SchedulingContext ctxt, bool setDaemon, int threadPrio) : base(qsRsrcs.ThreadName) { log = LogManager.GetLogger(GetType()); //ThreadGroup generatedAux = qs.SchedulerThreadGroup; this.qs = qs; this.qsRsrcs = qsRsrcs; this.ctxt = ctxt; IsBackground = setDaemon; Priority = (ThreadPriority) threadPrio; // start the underlying thread, but put this object into the 'paused' // state // so processing doesn't start yet... paused = true; halted = false; Start(); }
/// <summary> /// Construct a new <see cref="SchedulerSchedulerThread" /> for the given /// <see cref="SchedulerScheduler" /> as a non-daemon <see cref="Thread" /> /// with normal priority. /// </summary> internal SchedulerSchedulerThread(SchedulerScheduler qs, SchedulerSchedulerResources qsRsrcs, SchedulingContext ctxt) : this(qs, qsRsrcs, ctxt, qsRsrcs.MakeSchedulerThreadDaemon, (int) ThreadPriority.Normal) { }
protected internal virtual IScheduler Instantiate(SchedulerSchedulerResources rsrcs, SchedulerScheduler qs) { SchedulingContext schedCtxt = new SchedulingContext(); schedCtxt.InstanceId = rsrcs.InstanceId; IScheduler sched = new StdScheduler(qs, schedCtxt); return sched; }
/// <summary> </summary> private IScheduler Instantiate() { if (cfg == null) { Initialize(); } if (initException != null) { throw initException; } ISchedulerExporter exporter = null; IJobStore js; IThreadPool tp; SchedulerScheduler qs; SchedulingContext schedCtxt; 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, "SchedulerScheduler"); string threadName = cfg.GetStringProperty(PropertySchedulerThreadName, string.Format(CultureInfo.InvariantCulture, "{0}_SchedulerSchedulerThread", schedName)); string schedInstId = cfg.GetStringProperty(PropertySchedulerInstanceId, DefaultInstanceId); if (schedInstId.Equals(AutoGenerateInstanceId)) { autoId = true; instanceIdGeneratorType = cfg.GetStringProperty(PropertySchedulerInstanceIdGeneratorType, "Scheduler.Simpl.SimpleInstanceIdGenerator, Scheduler"); } typeLoadHelperType = cfg.GetStringProperty(PropertySchedulerTypeLoadHelperType, "Scheduler.Simpl.CascadingClassLoadHelper, Scheduler"); jobFactoryType = cfg.GetStringProperty(PropertySchedulerJobFactoryType, null); idleWaitTime = cfg.GetTimeSpanProperty(PropertySchedulerIdleWaitTime, idleWaitTime); dbFailureRetry = cfg.GetTimeSpanProperty(PropertySchedulerDbFailureRetryInterval, dbFailureRetry); bool makeSchedulerThreadDaemon = cfg.GetBooleanProperty(PropertySchedulerMakeSchedulerThreadDaemon); 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; } schedCtxt = new SchedulingContext(); schedCtxt.InstanceId = schedInstId; string uid = SchedulerSchedulerResources.GetUniqueIdentifier(schedName, schedInstId); RemoteScheduler remoteScheduler = new RemoteScheduler(schedCtxt, uid); string remoteSchedulerAddress = cfg.GetStringProperty(PropertySchedulerProxyAddress); remoteScheduler.RemoteSchedulerAddress = remoteSchedulerAddress; schedRep.Bind(remoteScheduler); return remoteScheduler; } // Create type load helper ITypeLoadHelper loadHelper; try { loadHelper = (ITypeLoadHelper)ObjectUtils.InstantiateType(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 = (IJobFactory) ObjectUtils.InstantiateType(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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } } IInstanceIdGenerator instanceIdGenerator = null; if (instanceIdGeneratorType != null) { try { instanceIdGenerator = (IInstanceIdGenerator) ObjectUtils.InstantiateType(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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } } // Get ThreadPool Properties // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string tpType = cfg.GetStringProperty(PropertyThreadPoolType, typeof(SimpleThreadPool).AssemblyQualifiedName); if (tpType == null) { initException = new SchedulerException("ThreadPool type not specified. ", SchedulerException.ErrorBadConfiguration); throw initException; } try { tp = (IThreadPool) ObjectUtils.InstantiateType(loadHelper.LoadType(tpType)); } catch (Exception e) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "ThreadPool type '{0}' could not be instantiated.", tpType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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 = (IDbProvider) ObjectUtils.InstantiateType(loadHelper.LoadType(cpType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "ConnectionProvider of type '{0}' could not be instantiated.", cpType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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 && dsConnectionStringName != null && dsConnectionStringName.Length > 0) { #if NET_20 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; #endif } 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. ", SchedulerException.ErrorBadConfiguration); throw initException; } try { js = (IJobStore) ObjectUtils.InstantiateType(loadHelper.LoadType(jsType)); } catch (Exception e) { initException = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "JobStore of type '{0}' could not be instantiated.", jsType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } if (js is JobStoreSupport) { ((JobStoreSupport) js).InstanceId = schedInstId; ((JobStoreSupport) js).InstanceName = schedName; // 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 = (ISemaphore)ObjectUtils.InstantiateType(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; } 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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 ? null : pp[PropertyPluginType]; if (plugInType == null) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "SchedulerPlugin type not specified for plugin '{0}'", pluginNames[i]), SchedulerException.ErrorBadConfiguration); throw initException; } ISchedulerPlugin plugin; try { plugin = (ISchedulerPlugin) ObjectUtils.InstantiateType(LoadType(plugInType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "SchedulerPlugin of type '{0}' could not be instantiated.", plugInType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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] == null ? null : lp[PropertyListenerType]; if (listenerType == null) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobListener type not specified for listener '{0}'", jobListenerNames[i]), SchedulerException.ErrorBadConfiguration); throw initException; } IJobListener listener; try { listener = (IJobListener) ObjectUtils.InstantiateType(loadHelper.LoadType(listenerType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "JobListener of type '{0}' could not be instantiated.", listenerType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } try { MethodInfo nameSetter = listener.GetType().GetMethod("setName", (strArg == null) ? new Type[0] : 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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] == null ? null : lp[PropertyListenerType]; if (listenerType == null) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "TriggerListener type not specified for listener '{0}'", triggerListenerNames[i]), SchedulerException.ErrorBadConfiguration); throw initException; } ITriggerListener listener; try { listener = (ITriggerListener) ObjectUtils.InstantiateType(loadHelper.LoadType(listenerType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "TriggerListener of type '{0}' could not be instantiated.", listenerType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } try { MethodInfo nameSetter = listener.GetType().GetMethod("setName", (strArg == null) ? new Type[0] : 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } triggerListeners[i] = listener; } // Get exporter // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ string exporterType = cfg.GetStringProperty(PropertySchedulerExporterType, null); if (exporterType != null) { try { exporter = (ISchedulerExporter)ObjectUtils.InstantiateType(loadHelper.LoadType(exporterType)); } catch (Exception e) { initException = new SchedulerException( string.Format(CultureInfo.InvariantCulture, "Scheduler exporter of type '{0}' could not be instantiated.", exporterType), e); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; 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); initException.ErrorCode = SchedulerException.ErrorBadConfiguration; throw initException; } } // Fire everything up // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IJobRunShellFactory jrsf = new StdJobRunShellFactory(); if (autoId) { try { schedInstId = DefaultInstanceId; if (js is JobStoreSupport) { if (((JobStoreSupport) 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.InstanceId = schedInstId; jjs.DbRetryInterval = dbFailureRetry; } SchedulerSchedulerResources rsrcs = new SchedulerSchedulerResources(); rsrcs.Name = schedName; rsrcs.ThreadName = threadName; rsrcs.InstanceId = schedInstId; rsrcs.JobRunShellFactory = jrsf; rsrcs.MakeSchedulerThreadDaemon = makeSchedulerThreadDaemon; rsrcs.ThreadPool = tp; rsrcs.SchedulerExporter = exporter; if (tp is SimpleThreadPool) { ((SimpleThreadPool) tp).ThreadNamePrefix = schedName + "_Worker"; } tp.Initialize(); rsrcs.JobStore = js; // add plugins for (int i = 0; i < plugins.Length; i++) { rsrcs.AddSchedulerPlugin(plugins[i]); } schedCtxt = new SchedulingContext(); schedCtxt.InstanceId = rsrcs.InstanceId; qs = new SchedulerScheduler(rsrcs, schedCtxt, idleWaitTime, dbFailureRetry); // 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.AddGlobalJobListener(jobListeners[i]); } for (int i = 0; i < triggerListeners.Length; i++) { qs.AddGlobalTriggerListener(triggerListeners[i]); } // set scheduler context data... IEnumerator itr = new HashSet(schedCtxtProps).GetEnumerator(); while (itr.MoveNext()) { string key = (String) itr.Current; string val = schedCtxtProps.Get(key); sched.Context.Put(key, val); } // fire up job store, and runshell factory js.Initialize(loadHelper, qs.SchedulerSignaler); jrsf.Initialize(sched, schedCtxt); Log.Info(string.Format(CultureInfo.InvariantCulture, "Scheduler scheduler '{0}' initialized", sched.SchedulerName)); Log.Info(string.Format(CultureInfo.InvariantCulture, "Scheduler 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; }