public TriggerPropertyBundle LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = commandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, tablePrefix, schedNameLiteral))) { commandAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); commandAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (IDataReader rs = cmd.ExecuteReader()) { if (rs.Read()) { int repeatCount = rs.GetInt32(AdoConstants.ColumnRepeatCount); long repeatInterval = rs.GetInt64(AdoConstants.ColumnRepeatInterval); int timesTriggered = rs.GetInt32(AdoConstants.ColumnTimesTriggered); SimpleScheduleBuilder sb = SimpleScheduleBuilder.Create() .WithRepeatCount(repeatCount) .WithInterval(TimeSpan.FromMilliseconds(repeatInterval)); string[] statePropertyNames = { "timesTriggered" }; object[] statePropertyValues = { timesTriggered }; return(new TriggerPropertyBundle(sb, statePropertyNames, statePropertyValues)); } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, tablePrefix, schedNameLiteral)); } }
/// <inheritdoc /> public virtual async Task <IReadOnlyCollection <SchedulerStateRecord> > SelectSchedulerStateRecords( ConnectionAndTransactionHolder conn, string?instanceName, CancellationToken cancellationToken = default) { DbCommand cmd; List <SchedulerStateRecord> list = new List <SchedulerStateRecord>(); if (instanceName != null) { cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlSelectSchedulerState)); AddCommandParameter(cmd, "instanceName", instanceName); } else { cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlSelectSchedulerStates)); } AddCommandParameter(cmd, "schedulerName", schedName); using var rs = await cmd.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false); while (await rs.ReadAsync(cancellationToken).ConfigureAwait(false)) { SchedulerStateRecord rec = new SchedulerStateRecord(); rec.SchedulerInstanceId = rs.GetString(ColumnInstanceName) !; rec.CheckinTimestamp = GetDateTimeFromDbValue(rs[ColumnLastCheckinTime]) ?? DateTimeOffset.MinValue; rec.CheckinInterval = GetTimeSpanFromDbValue(rs[ColumnCheckinInterval]) ?? TimeSpan.Zero; list.Add(rec); } return(list); }
/// <summary> /// Execute the SQL that will lock the proper database row. /// </summary> protected override async Task ExecuteSQL(Guid requestorId, ConnectionAndTransactionHolder conn, string lockName, string expandedSql, string expandedInsertSql) { Exception lastFailure = null; for (int i = 0; i < RetryCount; i++) { try { if (!await LockViaUpdate(requestorId, conn, lockName, expandedSql).ConfigureAwait(false)) { await LockViaInsert(requestorId, conn, lockName, expandedInsertSql).ConfigureAwait(false); } return; } catch (Exception e) { lastFailure = e; if (i + 1 == RetryCount) { Log.DebugFormat("Lock '{0}' was not obtained by: {1}", lockName, requestorId); } else { Log.DebugFormat("Lock '{0}' was not obtained by: {1} - will try again.", lockName, requestorId); } await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); } } if (lastFailure != null) { throw new LockException("Failure obtaining db row lock: " + lastFailure.Message, lastFailure); } }
/** * Execute the SQL select for update that will lock the proper database row. */ protected override void ExecuteSQL(ConnectionAndTransactionHolder conn, string lockName, string expandedSQL) { try { using (IDbCommand cmd = AdoUtil.PrepareCommand(conn, expandedSQL)) { AdoUtil.AddCommandParameter(cmd, 1, "lockName", lockName); using (IDataReader rs = cmd.ExecuteReader()) { if (Log.IsDebugEnabled) { Log.Debug("Lock '" + lockName + "' is being obtained: " + Thread.CurrentThread.Name); } if (!rs.Read()) { throw new Exception(AdoJobStoreUtil.ReplaceTablePrefix("No row exists in table " + TablePrefixSubst + TableLocks + " for lock named: " + lockName, TablePrefix)); } } } } catch (Exception sqle) { if (Log.IsDebugEnabled) { Log.Debug( "Lock '" + lockName + "' was not obtained by: " + Thread.CurrentThread.Name); } throw new LockException("Failure obtaining db row lock: " + sqle.Message, sqle); } }
private async Task LockViaInsert( Guid requestorId, ConnectionAndTransactionHolder conn, string lockName, string sql, CancellationToken cancellationToken) { if (sql == null) { throw new ArgumentNullException(nameof(sql)); } if (Log.IsDebugEnabled()) { Log.DebugFormat("Inserting new lock row for lock: '{0}' being obtained: {1}", lockName, requestorId); } using var cmd = AdoUtil.PrepareCommand(conn, sql); AdoUtil.AddCommandParameter(cmd, "schedulerName", SchedName); AdoUtil.AddCommandParameter(cmd, "lockName", lockName); if (await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false) != 1) { throw new InvalidOperationException( AdoJobStoreUtil.ReplaceTablePrefix("No row exists, and one could not be inserted in table " + TablePrefixSubst + TableLocks + " for lock named: " + lockName, TablePrefix)); } }
/// <summary> /// Execute the SQL that will lock the proper database row. /// </summary> /// <param name="conn"></param> /// <param name="lockName"></param> /// <param name="expandedSQL"></param> /// <param name="expandedInsertSQL"></param> protected override void ExecuteSQL(ConnectionAndTransactionHolder conn, string lockName, string expandedSQL, string expandedInsertSQL) { try { using (IDbCommand cmd = AdoUtil.PrepareCommand(conn, expandedSQL)) { AdoUtil.AddCommandParameter(cmd, "lockName", lockName); int numUpdate = cmd.ExecuteNonQuery(); if (numUpdate < 1) { using (IDbCommand cmd2 = AdoUtil.PrepareCommand(conn, expandedInsertSQL)) { AdoUtil.AddCommandParameter(cmd2, "lockName", lockName); int res = cmd2.ExecuteNonQuery(); if (res != 1) { throw new Exception(AdoJobStoreUtil.ReplaceTablePrefix( "No row exists, and one could not be inserted in table " + TablePrefixSubst + TableLocks + " for lock named: " + lockName, TablePrefix, SchedulerNameLiteral)); } } } } } catch (Exception sqle) { throw new LockException( "Failure obtaining db row lock: " + sqle.Message, sqle); } }
public TriggerPropertyBundle LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = CommandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectCronTriggers, TablePrefix, SchedNameLiteral))) { CommandAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); CommandAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (IDataReader rs = cmd.ExecuteReader()) { if (rs.Read()) { string cronExpr = rs.GetString(AdoConstants.ColumnCronExpression); string timeZoneId = rs.GetString(AdoConstants.ColumnTimeZoneId); CronScheduleBuilder cb = CronScheduleBuilder.CronSchedule(cronExpr); if (timeZoneId != null) { cb.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById(timeZoneId)); } return new TriggerPropertyBundle(cb, null, null); } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectCronTriggers, TablePrefix, SchedNameLiteral)); } }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <returns>True if the lock was obtained.</returns> public virtual bool ObtainLock(DbMetadata metadata, ConnectionAndTransactionHolder conn, string lockName) { lock (this) { lockName = String.Intern(lockName); if (!IsLockOwner(conn, lockName)) { while (locks.Contains(lockName)) { try { Monitor.Wait(this); } catch (ThreadInterruptedException) { } } ThreadLocks.Add(lockName); locks.Add(lockName); } return true; } }
public async Task <TriggerPropertyBundle> LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (var rs = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) { if (await rs.ReadAsync().ConfigureAwait(false)) { int repeatCount = rs.GetInt32(AdoConstants.ColumnRepeatCount); TimeSpan repeatInterval = DbAccessor.GetTimeSpanFromDbValue(rs[AdoConstants.ColumnRepeatInterval]) ?? TimeSpan.Zero; int timesTriggered = rs.GetInt32(AdoConstants.ColumnTimesTriggered); SimpleScheduleBuilder sb = SimpleScheduleBuilder.Create() .WithRepeatCount(repeatCount) .WithInterval(repeatInterval); string[] statePropertyNames = { "timesTriggered" }; object[] statePropertyValues = { timesTriggered }; return(new TriggerPropertyBundle(sb, statePropertyNames, statePropertyValues)); } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, TablePrefix, SchedNameLiteral)); } }
public async Task <TriggerPropertyBundle> LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectCronTriggers, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (var rs = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) { if (await rs.ReadAsync().ConfigureAwait(false)) { string cronExpr = rs.GetString(AdoConstants.ColumnCronExpression); string timeZoneId = rs.GetString(AdoConstants.ColumnTimeZoneId); CronScheduleBuilder cb = CronScheduleBuilder.CronSchedule(cronExpr); if (timeZoneId != null) { cb.InTimeZone(TimeZoneUtil.FindTimeZoneById(timeZoneId)); } return(new TriggerPropertyBundle(cb, null, null)); } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectCronTriggers, TablePrefix, SchedNameLiteral)); } }
/// <inheritdoc /> public virtual async Task <IJobDetail?> SelectJobDetail( ConnectionAndTransactionHolder conn, JobKey jobKey, ITypeLoadHelper loadHelper, CancellationToken cancellationToken = default) { using var cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlSelectJobDetail)); AddCommandParameter(cmd, "schedulerName", schedName); AddCommandParameter(cmd, "jobName", jobKey.Name); AddCommandParameter(cmd, "jobGroup", jobKey.Group); using var rs = await cmd.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false); JobDetailImpl?job = null; if (await rs.ReadAsync(cancellationToken).ConfigureAwait(false)) { job = new JobDetailImpl(); job.Name = rs.GetString(ColumnJobName) !; job.Group = rs.GetString(ColumnJobGroup) !; job.Description = rs.GetString(ColumnDescription); job.JobType = loadHelper.LoadType(rs.GetString(ColumnJobClass) !) !; job.Durable = GetBooleanFromDbValue(rs[ColumnIsDurable]); job.RequestsRecovery = GetBooleanFromDbValue(rs[ColumnRequestsRecovery]); var map = await ReadMapFromReader(rs, 6).ConfigureAwait(false); if (map != null) { job.JobDataMap = new JobDataMap(map); } } return(job); }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <returns>True if the lock was obtained.</returns> public virtual bool ObtainLock(DbMetadata metadata, ConnectionAndTransactionHolder conn, string lockName) { lock (this) { lockName = String.Intern(lockName); if (!IsLockOwner(conn, lockName)) { while (locks.Contains(lockName)) { try { Monitor.Wait(this); } catch (ThreadInterruptedException) { } } ThreadLocks.Add(lockName); locks.Add(lockName); } return(true); } }
/// <summary> /// Execute the SQL that will lock the proper database row. /// </summary> protected abstract Task ExecuteSQL( Guid requestorId, ConnectionAndTransactionHolder conn, string lockName, string expandedSql, string expandedInsertSql, CancellationToken cancellationToken);
public async Task <TriggerPropertyBundle> LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(SelectSimplePropsTrigger, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (var rs = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) { if (await rs.ReadAsync().ConfigureAwait(false)) { SimplePropertiesTriggerProperties properties = new SimplePropertiesTriggerProperties(); properties.String1 = rs.GetString(ColumnStrProp1); properties.String2 = rs.GetString(ColumnStrProp2); properties.String3 = rs.GetString(ColumnStrProp3); properties.Int1 = rs.GetInt32(ColumnIntProp1); properties.Int2 = rs.GetInt32(ColumnIntProp2); properties.Long1 = rs.GetInt64(ColumnLongProp1); properties.Long2 = rs.GetInt64(ColumnLongProp2); properties.Decimal1 = rs.GetDecimal(ColumnDecProp1); properties.Decimal2 = rs.GetDecimal(ColumnDecProp2); properties.Boolean1 = DbAccessor.GetBooleanFromDbValue(rs[ColumnBoolProp1]); properties.Boolean2 = DbAccessor.GetBooleanFromDbValue(rs[ColumnBoolProp2]); return(GetTriggerPropertyBundle(properties)); } } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, TablePrefix, SchedNameLiteral)); }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <param name="metadata"></param> /// <param name="conn"></param> /// <param name="lockName"></param> /// <returns>true if the lock was obtained.</returns> public bool ObtainLock(DbMetadata metadata, ConnectionAndTransactionHolder conn, string lockName) { lockName = string.Intern(lockName); if (Log.IsDebugEnabled) { Log.DebugFormat("Lock '{0}' is desired by: {1}", lockName, Thread.CurrentThread.Name); } if (!IsLockOwner(conn, lockName)) { ExecuteSQL(conn, lockName, expandedSQL, expandedInsertSQL); if (Log.IsDebugEnabled) { Log.DebugFormat("Lock '{0}' given to: {1}", lockName, Thread.CurrentThread.Name); } ThreadLocks.Add(lockName); //getThreadLocksObtainer().put(lockName, new // Exception("Obtainer...")); } else if (log.IsDebugEnabled) { Log.DebugFormat("Lock '{0}' Is already owned by: {1}", lockName, Thread.CurrentThread.Name); } return(true); }
public TriggerPropertyBundle LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = CommandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, TablePrefix, SchedNameLiteral))) { CommandAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); CommandAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (IDataReader rs = cmd.ExecuteReader()) { if (rs.Read()) { int repeatCount = rs.GetInt32(AdoConstants.ColumnRepeatCount); long repeatInterval = rs.GetInt64(AdoConstants.ColumnRepeatInterval); int timesTriggered = rs.GetInt32(AdoConstants.ColumnTimesTriggered); SimpleScheduleBuilder sb = SimpleScheduleBuilder.Create() .WithRepeatCount(repeatCount) .WithInterval(TimeSpan.FromMilliseconds(repeatInterval)); string[] statePropertyNames = {"timesTriggered"}; object[] statePropertyValues = {timesTriggered}; return new TriggerPropertyBundle(sb, statePropertyNames, statePropertyValues); } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, TablePrefix, SchedNameLiteral)); } }
public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail) { SimplePropertiesTriggerProperties properties = GetTriggerProperties(trigger); using (IDbCommand cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(InsertSimplePropsTrigger, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group); DbAccessor.AddCommandParameter(cmd, "string1", properties.String1); DbAccessor.AddCommandParameter(cmd, "string2", properties.String2); DbAccessor.AddCommandParameter(cmd, "string3", properties.String3); DbAccessor.AddCommandParameter(cmd, "int1", properties.Int1); DbAccessor.AddCommandParameter(cmd, "int2", properties.Int2); DbAccessor.AddCommandParameter(cmd, "long1", properties.Long1); DbAccessor.AddCommandParameter(cmd, "long2", properties.Long2); DbAccessor.AddCommandParameter(cmd, "decimal1", properties.Decimal1); DbAccessor.AddCommandParameter(cmd, "decimal2", properties.Decimal2); DbAccessor.AddCommandParameter(cmd, "boolean1", DbAccessor.GetDbBooleanValue(properties.Boolean1)); DbAccessor.AddCommandParameter(cmd, "boolean2", DbAccessor.GetDbBooleanValue(properties.Boolean2)); DbAccessor.AddCommandParameter(cmd, "timeZoneId", properties.TimeZoneId); return(cmd.ExecuteNonQuery()); } }
public async Task <int> UpdateExtendedTriggerProperties( ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail, CancellationToken cancellationToken = default) { SimplePropertiesTriggerProperties properties = GetTriggerProperties(trigger); using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(UpdateSimplePropsTrigger, TablePrefix))) { DbAccessor.AddCommandParameter(cmd, "schedulerName", SchedName); DbAccessor.AddCommandParameter(cmd, "string1", properties.String1); DbAccessor.AddCommandParameter(cmd, "string2", properties.String2); DbAccessor.AddCommandParameter(cmd, "string3", properties.String3); DbAccessor.AddCommandParameter(cmd, "int1", properties.Int1); DbAccessor.AddCommandParameter(cmd, "int2", properties.Int2); DbAccessor.AddCommandParameter(cmd, "long1", properties.Long1); DbAccessor.AddCommandParameter(cmd, "long2", properties.Long2); DbAccessor.AddCommandParameter(cmd, "decimal1", properties.Decimal1); DbAccessor.AddCommandParameter(cmd, "decimal2", properties.Decimal2); DbAccessor.AddCommandParameter(cmd, "boolean1", DbAccessor.GetDbBooleanValue(properties.Boolean1)); DbAccessor.AddCommandParameter(cmd, "boolean2", DbAccessor.GetDbBooleanValue(properties.Boolean2)); DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group); DbAccessor.AddCommandParameter(cmd, "timeZoneId", properties.TimeZoneId); return(await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false)); } }
public TriggerPropertyBundle LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = adoUtil.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectCronTriggers, tablePrefix, schedNameLiteral))) { adoUtil.AddCommandParameter(cmd, "triggerName", triggerKey.Name); adoUtil.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (IDataReader rs = cmd.ExecuteReader()) { if (rs.Read()) { string cronExpr = rs.GetString(AdoConstants.ColumnCronExpression); string timeZoneId = rs.GetString(AdoConstants.ColumnTimeZoneId); CronScheduleBuilder cb = CronScheduleBuilder.CronSchedule(cronExpr); if (timeZoneId != null) { cb.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById(timeZoneId)); } return(new TriggerPropertyBundle(cb, null, null)); } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectCronTriggers, tablePrefix, schedNameLiteral)); } }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <param name="requestorId"></param> /// <param name="conn"></param> /// <param name="lockName"></param> /// <returns>true if the lock was obtained.</returns> public async Task <bool> ObtainLock(Guid requestorId, ConnectionAndTransactionHolder conn, string lockName) { if (log.IsDebugEnabled()) { Log.DebugFormat("Lock '{0}' is desired by: {1}", lockName, requestorId); } if (!IsLockOwner(requestorId, lockName)) { await ExecuteSQL(requestorId, conn, lockName, expandedSQL, expandedInsertSQL).ConfigureAwait(false); if (log.IsDebugEnabled()) { Log.DebugFormat("Lock '{0}' given to: {1}", lockName, requestorId); } lock (syncRoot) { HashSet <string> requestorLocks; if (!locks.TryGetValue(requestorId, out requestorLocks)) { requestorLocks = new HashSet <string>(); locks[requestorId] = requestorLocks; } requestorLocks.Add(lockName); } } else if (log.IsDebugEnabled()) { Log.DebugFormat("Lock '{0}' Is already owned by: {1}", lockName, requestorId); } return(true); }
public TriggerPropertyBundle LoadExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = commandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(SelectSimplePropsTrigger, tablePrefix, schedNameLiteral))) { commandAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); commandAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); using (IDataReader rs = cmd.ExecuteReader()) { if (rs.Read()) { SimplePropertiesTriggerProperties properties = new SimplePropertiesTriggerProperties(); properties.String1 = (rs.GetString(ColumnStrProp1)); properties.String2 = (rs.GetString(ColumnStrProp2)); properties.String3 = (rs.GetString(ColumnStrProp3)); properties.Int1 = (rs.GetInt32(ColumnIntProp1)); properties.Int2 = (rs.GetInt32(ColumnIntProp2)); properties.Long1 = (rs.GetInt32(ColumnLongProp1)); properties.Long2 = (rs.GetInt32(ColumnLongProp2)); properties.Decimal1 = (rs.GetDecimal(ColumnDecProp1)); properties.Decimal2 = (rs.GetDecimal(ColumnDecProp2)); properties.Boolean1 = (rs.GetBoolean(ColumnBoolProp1)); properties.Boolean2 = (rs.GetBoolean(ColumnBoolProp2)); return(GetTriggerPropertyBundle(properties)); } } } throw new InvalidOperationException("No record found for selection of Trigger with key: '" + triggerKey + "' and statement: " + AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlSelectSimpleTrigger, tablePrefix, schedNameLiteral)); }
/// <inheritdoc /> public virtual Task <IJobDetail?> SelectJobForTrigger( ConnectionAndTransactionHolder conn, TriggerKey triggerKey, ITypeLoadHelper loadHelper, CancellationToken cancellationToken = default) { return(SelectJobForTrigger(conn, triggerKey, loadHelper, true, cancellationToken)); }
public IDbCommand PrepareCommand(ConnectionAndTransactionHolder cth, string commandText) { IDbCommand cmd = dbProvider.CreateCommand(); cmd.CommandText = commandText; cmd.Connection = cth.Connection; cmd.Transaction = cth.Transaction; return cmd; }
public IDbCommand PrepareCommand(ConnectionAndTransactionHolder cth, string commandText) { IDbCommand cmd = dbProvider.CreateCommand(); cmd.CommandText = commandText; cmd.Connection = cth.Connection; cmd.Transaction = cth.Transaction; return(cmd); }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <returns>True if the lock was obtained.</returns> public virtual Task <bool> ObtainLock( Guid requestorId, ConnectionAndTransactionHolder conn, string lockName, CancellationToken cancellationToken = default(CancellationToken)) { if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' is desired by: {requestorId}"); } lock (syncRoot) { if (!IsLockOwner(requestorId, lockName)) { if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' is being obtained: {requestorId}"); } while (locks.Contains(lockName)) { try { Monitor.Wait(syncRoot); } catch (ThreadInterruptedException) { if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' was not obtained by: {requestorId}"); } } } HashSet <string> requestorLocks; if (!threadLocks.TryGetValue(requestorId, out requestorLocks)) { requestorLocks = new HashSet <string>(); threadLocks[requestorId] = requestorLocks; } requestorLocks.Add(lockName); locks.Add(lockName); if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' given to: {requestorId}"); } } else if (log.IsDebugEnabled()) { log.DebugException($"Lock '{lockName}' already owned by: {requestorId} -- but not owner!", new Exception("stack-trace of wrongful returner")); } return(Task.FromResult(true)); } }
/// <summary> /// Determine whether the calling thread owns a lock on the identified /// resource. /// </summary> public virtual bool IsLockOwner(ConnectionAndTransactionHolder conn, String lockName) { lock (this) { lockName = String.Intern(lockName); return(ThreadLocks.Contains(lockName)); } }
private async Task <bool> LockViaUpdate(Guid requestorId, ConnectionAndTransactionHolder conn, string lockName, string sql) { using (DbCommand cmd = AdoUtil.PrepareCommand(conn, sql)) { AdoUtil.AddCommandParameter(cmd, "lockName", lockName); Log.DebugFormat("Lock '{0}' is being obtained: {1}", lockName, requestorId); return(await cmd.ExecuteNonQueryAsync().ConfigureAwait(false) >= 1); } }
public int DeleteExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = commandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlDeleteSimpleTrigger, tablePrefix, schedNameLiteral))) { commandAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); commandAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); return(cmd.ExecuteNonQuery()); } }
private bool LockViaUpdate(ConnectionAndTransactionHolder conn, string lockName, string sql) { using (IDbCommand cmd = AdoUtil.PrepareCommand(conn, sql)) { AdoUtil.AddCommandParameter(cmd, "lockName", lockName); Log.DebugFormat("Lock '{0}' is being obtained: {1}", lockName, Thread.CurrentThread.Name); return(cmd.ExecuteNonQuery() >= 1); } }
/// <summary> /// Release the lock on the identified resource if it is held by the calling /// thread. /// </summary> /// <param name="conn"></param> /// <param name="lockName"></param> public void ReleaseLock(ConnectionAndTransactionHolder conn, string lockName) { lockName = string.Intern(lockName); if (IsLockOwner(conn, lockName)) { ThreadLocks.Remove(lockName); //getThreadLocksObtainer().remove(lockName); } }
/// <inheritdoc /> public virtual async Task <int> DeleteCalendar( ConnectionAndTransactionHolder conn, string calendarName, CancellationToken cancellationToken = default) { using var cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlDeleteCalendar)); AddCommandParameter(cmd, "schedulerName", schedName); AddCommandParameter(cmd, "calendarName", calendarName); return(await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false)); }
public int DeleteExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (IDbCommand cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlDeleteCronTrigger, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); return cmd.ExecuteNonQuery(); } }
public async Task <int> DeleteExtendedTriggerProperties(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlDeleteCronTrigger, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); return(await cmd.ExecuteNonQueryAsync().ConfigureAwait(false)); } }
/// <inheritdoc /> public virtual async Task <int> SelectNumCalendars( ConnectionAndTransactionHolder conn, CancellationToken cancellationToken = default) { using var cmd = PrepareCommand(conn, ReplaceTablePrefix(SqlSelectNumCalendars)); AddCommandParameter(cmd, "schedulerName", schedName); int count = Convert.ToInt32(await cmd.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false)); return(count); }
public async Task <int> DeleteExtendedTriggerProperties( ConnectionAndTransactionHolder conn, TriggerKey triggerKey, CancellationToken cancellationToken = default) { using var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlDeleteSimpleTrigger, TablePrefix)); DbAccessor.AddCommandParameter(cmd, "schedulerName", SchedName); DbAccessor.AddCommandParameter(cmd, "triggerName", triggerKey.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", triggerKey.Group); return(await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <returns>True if the lock was obtained.</returns> public virtual Task<bool> ObtainLock(Guid requestorId, ConnectionAndTransactionHolder conn, string lockName) { if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' is desired by: {requestorId}"); } lock (syncRoot) { if (!IsLockOwner(requestorId, lockName)) { if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' is being obtained: {requestorId}"); } while (locks.Contains(lockName)) { try { Monitor.Wait(syncRoot); } catch (ThreadInterruptedException) { if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' was not obtained by: {requestorId}"); } } } HashSet<string> requestorLocks; if (!threadLocks.TryGetValue(requestorId, out requestorLocks)) { requestorLocks = new HashSet<string>(); threadLocks[requestorId] = requestorLocks; } requestorLocks.Add(lockName); locks.Add(lockName); if (log.IsDebugEnabled()) { log.Debug($"Lock '{lockName}' given to: {requestorId}"); } } else if (log.IsDebugEnabled()) { log.DebugException($"Lock '{lockName}' already owned by: {requestorId} -- but not owner!", new Exception("stack-trace of wrongful returner")); } return Task.FromResult(true); } }
/// <summary> /// Execute the SQL select for update that will lock the proper database row. /// </summary> protected override void ExecuteSQL(ConnectionAndTransactionHolder conn, string lockName, string expandedSQL, string expandedInsertSQL) { try { using (IDbCommand cmd = AdoUtil.PrepareCommand(conn, expandedSQL)) { AdoUtil.AddCommandParameter(cmd, "lockName", lockName); bool found = false; using (IDataReader rs = cmd.ExecuteReader()) { if (Log.IsDebugEnabled) { Log.Debug("Lock '" + lockName + "' is being obtained: " + Thread.CurrentThread.Name); } found = rs.Read(); } if (!found) { Log.Debug( "Inserting new lock row for lock: '" + lockName + "' being obtained by thread: " + Thread.CurrentThread.Name); using (IDbCommand cmd2 = AdoUtil.PrepareCommand(conn, expandedInsertSQL)) { AdoUtil.AddCommandParameter(cmd2, "lockName", lockName); int res = cmd2.ExecuteNonQuery(); if (res != 1) { throw new Exception(AdoJobStoreUtil.ReplaceTablePrefix( "No row exists, and one could not be inserted in table " + TablePrefixSubst + TableLocks + " for lock named: " + lockName, TablePrefix, SchedulerNameLiteral)); } } } } } catch (Exception sqle) { if (Log.IsDebugEnabled) { Log.Debug( "Lock '" + lockName + "' was not obtained by: " + Thread.CurrentThread.Name); } throw new LockException("Failure obtaining db row lock: " + sqle.Message, sqle); } }
public DbCommand PrepareCommand(ConnectionAndTransactionHolder cth, string commandText) { DbCommand cmd = dbProvider.CreateCommand(); cmd.CommandText = commandText; cth.Attach(cmd); if (log.IsDebugEnabled()) { log.DebugFormat("Prepared SQL: {0}", cmd.CommandText); } return cmd; }
public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail) { ICronTrigger cronTrigger = (ICronTrigger) trigger; using (IDbCommand cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertCronTrigger, TablePrefix, SchedNameLiteral))) { DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name); DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group); DbAccessor.AddCommandParameter(cmd, "triggerCronExpression", cronTrigger.CronExpressionString); DbAccessor.AddCommandParameter(cmd, "triggerTimeZone", cronTrigger.TimeZone.Id); return cmd.ExecuteNonQuery(); } }
public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail) { ISimpleTrigger simpleTrigger = (ISimpleTrigger) trigger; using (IDbCommand cmd = commandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertSimpleTrigger, tablePrefix, schedNameLiteral))) { commandAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name); commandAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group); commandAccessor.AddCommandParameter(cmd, "triggerRepeatCount", simpleTrigger.RepeatCount); commandAccessor.AddCommandParameter(cmd, "triggerRepeatInterval", simpleTrigger.RepeatInterval.TotalMilliseconds); commandAccessor.AddCommandParameter(cmd, "triggerTimesTriggered", simpleTrigger.TimesTriggered); return cmd.ExecuteNonQuery(); } }
/// <summary> /// Grants a lock on the identified resource to the calling thread (blocking /// until it is available). /// </summary> /// <returns>True if the lock was obtained.</returns> public virtual bool ObtainLock(DbMetadata metadata, ConnectionAndTransactionHolder conn, string lockName) { lock (this) { lockName = String.Intern(lockName); if (log.IsDebugEnabled) log.Debug("Lock '" + lockName + "' is desired by: " + Thread.CurrentThread.Name); if (!IsLockOwner(conn, lockName)) { if (log.IsDebugEnabled) { log.Debug("Lock '" + lockName + "' is being obtained: " + Thread.CurrentThread.Name); } while (locks.Contains(lockName)) { try { Monitor.Wait(this); } catch (ThreadInterruptedException) { if (log.IsDebugEnabled) { log.Debug("Lock '" + lockName + "' was not obtained by: " + Thread.CurrentThread.Name); } } } if (log.IsDebugEnabled) { log.Debug(string.Format(CultureInfo.InvariantCulture, "Lock '{0}' given to: {1}", lockName, Thread.CurrentThread.Name)); } ThreadLocks.Add(lockName); locks.Add(lockName); } else if (log.IsDebugEnabled) { log.Debug(string.Format(CultureInfo.InvariantCulture, "Lock '{0}' already owned by: {1} -- but not owner!", lockName, Thread.CurrentThread.Name), new Exception("stack-trace of wrongful returner")); } return true; } }
public void TestSelectBlobTriggerWithNoBlobContent() { var dbProvider = MockRepository.GenerateMock<IDbProvider>(); var connection = MockRepository.GenerateMock<IDbConnection>(); var transaction = MockRepository.GenerateMock<IDbTransaction>(); var command = (IDbCommand) MockRepository.GenerateMock<StubCommand>(); var dbMetadata = new DbMetadata(); dbProvider.Stub(x => x.Metadata).Repeat.Any().Return(dbMetadata); dbProvider.Stub(x => x.CreateCommand()).Return(command); var dataReader = MockRepository.GenerateMock<IDataReader>(); command.Stub(x => x.ExecuteReader()).Return(dataReader); command.Stub(x => x.Parameters).Repeat.Any().Return(new StubParameterCollection()); command.Stub(x => x.CommandText).Return("").Repeat.Any(); command.Stub(x => x.CreateParameter()).Repeat.Any().Return(new StubDataParameter()); var adoDelegate = new StdAdoDelegate(); var delegateInitializationArgs = new DelegateInitializationArgs { TablePrefix = "QRTZ_", InstanceId = "TESTSCHED", InstanceName = "INSTANCE", TypeLoadHelper = new SimpleTypeLoadHelper(), UseProperties = false, InitString = "", Logger = LogManager.GetLogger(GetType()), DbProvider = dbProvider }; adoDelegate.Initialize(delegateInitializationArgs); var conn = new ConnectionAndTransactionHolder(connection, transaction); // First result set has results, second has none dataReader.Stub(x => x.Read()).Return(true).Repeat.Once(); dataReader.Stub(x => x.Read()).Return(false); dataReader.Stub(x => x[AdoConstants.ColumnTriggerType]).Return(AdoConstants.TriggerTypeBlob); IOperableTrigger trigger = adoDelegate.SelectTrigger(conn, new TriggerKey("test")); Assert.That(trigger, Is.Null); }
/// <summary> /// Execute the SQL that will lock the proper database row. /// </summary> /// <param name="conn"></param> /// <param name="lockName"></param> /// <param name="expandedSQL"></param> /// <param name="expandedInsertSQL"></param> protected override void ExecuteSQL(ConnectionAndTransactionHolder conn, string lockName, string expandedSQL, string expandedInsertSQL) { Exception lastFailure = null; for (int i = 0; i < RetryCount; i++) { try { if (!LockViaUpdate(conn, lockName, expandedSQL)) { LockViaInsert(conn, lockName, expandedInsertSQL); } return; } catch (Exception e) { lastFailure = e; if ((i + 1) == RetryCount) { Log.DebugFormat("Lock '{0}' was not obtained by: {1}", lockName, Thread.CurrentThread.Name); } else { Log.DebugFormat("Lock '{0}' was not obtained by: {1} - will try again.", lockName, Thread.CurrentThread.Name); } try { Thread.Sleep(TimeSpan.FromSeconds(1)); } catch (ThreadInterruptedException) { Thread.CurrentThread.Interrupt(); } } } if (lastFailure != null) { throw new LockException("Failure obtaining db row lock: " + lastFailure.Message, lastFailure); } }
/// <summary> /// Gets the state of the trigger. /// </summary> /// <param name="conn">The conn.</param> /// <param name="triggerKey">The key identifying the trigger.</param> /// <returns></returns> public virtual TriggerState GetTriggerState(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { try { string ts = Delegate.SelectTriggerState(conn, triggerKey); if (ts == null) { return TriggerState.None; } if (ts.Equals(StateDeleted)) { return TriggerState.None; } if (ts.Equals(StateComplete)) { return TriggerState.Complete; } if (ts.Equals(StatePaused)) { return TriggerState.Paused; } if (ts.Equals(StatePausedBlocked)) { return TriggerState.Blocked; } if (ts.Equals(StateError)) { return TriggerState.Error; } if (ts.Equals(StateBlocked)) { return TriggerState.Blocked; } return TriggerState.Normal; } catch (Exception e) { throw new JobPersistenceException( "Couldn't determine state of trigger (" + triggerKey + "): " + e.Message, e); } }
private static void CheckNotZombied(ConnectionAndTransactionHolder cth) { if (cth == null) { throw new ArgumentNullException("cth", "Connnection-transaction pair cannot be null"); } if (cth.Transaction != null && cth.Transaction.Connection == null) { throw new DataException("Transaction not connected, or was disconnected"); } }
protected virtual bool UpdateMisfiredTrigger(ConnectionAndTransactionHolder conn, TriggerKey triggerKey, string newStateIfNotComplete, bool forceState) { try { IOperableTrigger trig = RetrieveTrigger(conn, triggerKey); DateTimeOffset misfireTime = SystemTime.UtcNow(); if (MisfireThreshold > TimeSpan.Zero) { misfireTime = misfireTime.AddMilliseconds(-1*MisfireThreshold.TotalMilliseconds); } if (trig.GetNextFireTimeUtc().Value > misfireTime) { return false; } DoUpdateOfMisfiredTrigger(conn, trig, forceState, newStateIfNotComplete, false); return true; } catch (Exception e) { throw new JobPersistenceException( string.Format("Couldn't update misfired trigger '{0}': {1}", triggerKey, e.Message), e); } }
/// <summary> /// Delete a trigger, its listeners, and its Simple/Cron/BLOB sub-table entry. /// </summary> /// <seealso cref="RemoveJob(ConnectionAndTransactionHolder, JobKey, bool)" /> /// <seealso cref="RemoveTrigger(ConnectionAndTransactionHolder, TriggerKey)" /> /// <seealso cref="ReplaceTrigger(ConnectionAndTransactionHolder, TriggerKey, IOperableTrigger)" /> private bool DeleteTriggerAndChildren(ConnectionAndTransactionHolder conn, TriggerKey key) { IDriverDelegate del = Delegate; return (del.DeleteTrigger(conn, key) > 0); }
/// <summary> /// Delete a job and its listeners. /// </summary> /// <seealso cref="JobStoreSupport.RemoveJob(ConnectionAndTransactionHolder, JobKey, bool)" /> /// <seealso cref="RemoveTrigger(ConnectionAndTransactionHolder, TriggerKey)" /> private bool DeleteJobAndChildren(ConnectionAndTransactionHolder conn, JobKey key) { return (Delegate.DeleteJobDetail(conn, key) > 0); }
/// <summary> /// Closes the connection. /// </summary> /// <param name="connectionAndTransactionHolder">The connection and transaction holder.</param> protected override void CloseConnection(ConnectionAndTransactionHolder connectionAndTransactionHolder) { // Will work for transactional and non-transactional connections. ConnectionUtils.DisposeConnection(connectionAndTransactionHolder.Connection, dbProvider); }
private void DoUpdateOfMisfiredTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger trig, bool forceState, string newStateIfNotComplete, bool recovering) { ICalendar cal = null; if (trig.CalendarName != null) { cal = RetrieveCalendar(conn, trig.CalendarName); } schedSignaler.NotifyTriggerListenersMisfired(trig); trig.UpdateAfterMisfire(cal); if (!trig.GetNextFireTimeUtc().HasValue) { StoreTrigger(conn, trig, null, true, StateComplete, forceState, recovering); schedSignaler.NotifySchedulerListenersFinalized(trig); } else { StoreTrigger(conn, trig, null, true, newStateIfNotComplete, forceState, false); } }
/// <summary> /// Create dummy <see cref="SchedulerStateRecord" /> objects for fired triggers /// that have no scheduler state record. Checkin timestamp and interval are /// left as zero on these dummy <see cref="SchedulerStateRecord" /> objects. /// </summary> /// <param name="conn"></param> /// <param name="schedulerStateRecords">List of all current <see cref="SchedulerStateRecord" />s</param> private IList<SchedulerStateRecord> FindOrphanedFailedInstances(ConnectionAndTransactionHolder conn, IList<SchedulerStateRecord> schedulerStateRecords) { IList<SchedulerStateRecord> orphanedInstances = new List<SchedulerStateRecord>(); Collection.ISet<string> allFiredTriggerInstanceNames = Delegate.SelectFiredTriggerInstanceNames(conn); if (allFiredTriggerInstanceNames.Count > 0) { foreach (SchedulerStateRecord rec in schedulerStateRecords) { allFiredTriggerInstanceNames.Remove(rec.SchedulerInstanceId); } foreach (string name in allFiredTriggerInstanceNames) { SchedulerStateRecord orphanedInstance = new SchedulerStateRecord(); orphanedInstance.SchedulerInstanceId = name; orphanedInstances.Add(orphanedInstance); Log.Warn("Found orphaned fired triggers for instance: " + orphanedInstance.SchedulerInstanceId); } } return orphanedInstances; }
//private int lastRecoverCount = 0; public virtual RecoverMisfiredJobsResult RecoverMisfiredJobs(ConnectionAndTransactionHolder conn, bool recovering) { // If recovering, we want to handle all of the misfired // triggers right away. int maxMisfiresToHandleAtATime = (recovering) ? -1 : MaxMisfiresToHandleAtATime; IList<TriggerKey> misfiredTriggers = new List<TriggerKey>(); DateTimeOffset earliestNewTime = DateTimeOffset.MaxValue; // We must still look for the MISFIRED state in case triggers were left // in this state when upgrading to this version that does not support it. bool hasMoreMisfiredTriggers = Delegate.HasMisfiredTriggersInState(conn, StateWaiting, MisfireTime, maxMisfiresToHandleAtATime, misfiredTriggers); if (hasMoreMisfiredTriggers) { Log.Info( "Handling the first " + misfiredTriggers.Count + " triggers that missed their scheduled fire-time. " + "More misfired triggers remain to be processed."); } else if (misfiredTriggers.Count > 0) { Log.Info( "Handling " + misfiredTriggers.Count + " trigger(s) that missed their scheduled fire-time."); } else { Log.Debug( "Found 0 triggers that missed their scheduled fire-time."); return RecoverMisfiredJobsResult.NoOp; } foreach (TriggerKey triggerKey in misfiredTriggers) { IOperableTrigger trig = RetrieveTrigger(conn, triggerKey); if (trig == null) { continue; } DoUpdateOfMisfiredTrigger(conn, trig, false, StateWaiting, recovering); DateTimeOffset? nextTime = trig.GetNextFireTimeUtc(); if (nextTime.HasValue && nextTime.Value < earliestNewTime) { earliestNewTime = nextTime.Value; } } return new RecoverMisfiredJobsResult(hasMoreMisfiredTriggers, misfiredTriggers.Count, earliestNewTime); }
/// <summary> /// Pause all of the <see cref="ITrigger" />s in the given group. /// </summary> public virtual Collection.ISet<string> PauseTriggerGroup(ConnectionAndTransactionHolder conn, GroupMatcher<TriggerKey> matcher) { try { Delegate.UpdateTriggerGroupStateFromOtherStates(conn, matcher, StatePaused, StateAcquired, StateWaiting, StateWaiting); Delegate.UpdateTriggerGroupStateFromOtherState(conn, matcher, StatePausedBlocked, StateBlocked); IList<String> groups = Delegate.SelectTriggerGroups(conn, matcher); // make sure to account for an exact group match for a group that doesn't yet exist StringOperator op = matcher.CompareWithOperator; if (op.Equals(StringOperator.Equality) && !groups.Contains(matcher.CompareToValue)) { groups.Add(matcher.CompareToValue); } foreach (string group in groups) { if (!Delegate.IsTriggerGroupPaused(conn, group)) { Delegate.InsertPausedTriggerGroup(conn, group); } } return new Collection.HashSet<string>(groups); } catch (Exception e) { throw new JobPersistenceException("Couldn't pause trigger group '" + matcher + "': " + e.Message, e); } }
/// <summary> /// Pause the <see cref="ITrigger" /> with the given name. /// </summary> public virtual void PauseTrigger(ConnectionAndTransactionHolder conn, TriggerKey triggerKey) { try { string oldState = Delegate.SelectTriggerState(conn, triggerKey); if (oldState.Equals(StateWaiting) || oldState.Equals(StateAcquired)) { Delegate.UpdateTriggerState(conn, triggerKey, StatePaused); } else if (oldState.Equals(StateBlocked)) { Delegate.UpdateTriggerState(conn, triggerKey, StatePausedBlocked); } } catch (Exception e) { throw new JobPersistenceException( "Couldn't pause trigger '" + triggerKey + "': " + e.Message, e); } }
/// <summary> /// Pause all of the <see cref="ITrigger" />s in the /// given group. /// </summary> public virtual Collection.ISet<string> GetPausedTriggerGroups(ConnectionAndTransactionHolder conn) { try { return Delegate.SelectPausedTriggerGroups(conn); } catch (Exception e) { throw new JobPersistenceException("Couldn't determine paused trigger groups: " + e.Message, e); } }
/// <summary> /// Execute the SQL select for update that will lock the proper database row. /// </summary> protected override void ExecuteSQL(ConnectionAndTransactionHolder conn, string lockName, string expandedSQL, string expandedInsertSQL) { // attempt lock two times (to work-around possible race conditions in inserting the lock row the first time running) int count = 0; do { count++; try { using (IDbCommand cmd = AdoUtil.PrepareCommand(conn, expandedSQL)) { AdoUtil.AddCommandParameter(cmd, "lockName", lockName); bool found; using (IDataReader rs = cmd.ExecuteReader()) { if (Log.IsDebugEnabled) { Log.DebugFormat("Lock '{0}' is being obtained: {1}", lockName, Thread.CurrentThread.Name); } found = rs.Read(); } if (!found) { if (Log.IsDebugEnabled) { Log.DebugFormat("Inserting new lock row for lock: '{0}' being obtained by thread: {1}", lockName, Thread.CurrentThread.Name); } using (IDbCommand cmd2 = AdoUtil.PrepareCommand(conn, expandedInsertSQL)) { AdoUtil.AddCommandParameter(cmd2, "lockName", lockName); int res = cmd2.ExecuteNonQuery(); if (res != 1) { if (count < 3) { // pause a bit to give another thread some time to commit the insert of the new lock row try { Thread.Sleep(TimeSpan.FromSeconds(1)); } catch (ThreadInterruptedException) { Thread.CurrentThread.Interrupt(); } // try again ... continue; } throw new Exception(AdoJobStoreUtil.ReplaceTablePrefix( "No row exists, and one could not be inserted in table " + TablePrefixSubst + TableLocks + " for lock named: " + lockName, TablePrefix, SchedulerNameLiteral)); } } break; // obtained lock, no need to retry } } } catch (Exception sqle) { if (Log.IsDebugEnabled) { Log.DebugFormat("Lock '{0}' was not obtained by: {1}{2}", lockName, Thread.CurrentThread.Name, (count < 3 ? " - will try again." : "")); } if (count < 3) { // pause a bit to give another thread some time to commit the insert of the new lock row try { Thread.Sleep(TimeSpan.FromSeconds(1)); } catch (ThreadInterruptedException) { Thread.CurrentThread.Interrupt(); } // try again ... continue; } throw new LockException("Failure obtaining db row lock: " + sqle.Message, sqle); } } while (count < 2); }
/// <summary> /// Pause all triggers - equivalent of calling <see cref="PauseTriggers(GroupMatcher{TriggerKey})" /> /// on every group. /// <para> /// When <see cref="ResumeAll()" /> is called (to un-pause), trigger misfire /// instructions WILL be applied. /// </para> /// </summary> /// <seealso cref="ResumeAll()" /> /// <seealso cref="String" /> public virtual void PauseAll(ConnectionAndTransactionHolder conn) { IList<string> groupNames = GetTriggerGroupNames(conn); foreach (string groupName in groupNames) { PauseTriggerGroup(conn, GroupMatcher<TriggerKey>.GroupEquals(groupName)); } try { if (!Delegate.IsTriggerGroupPaused(conn, AllGroupsPaused)) { Delegate.InsertPausedTriggerGroup(conn, AllGroupsPaused); } } catch (Exception e) { throw new JobPersistenceException("Couldn't pause all trigger groups: " + e.Message, e); } }