private CriticalSectionState GetCriticalSectionState(int taskDefinitionId, CriticalSectionType criticalSectionType, SqlCommand command) { command.Parameters.Clear(); if (criticalSectionType == CriticalSectionType.User) { command.CommandText = TokensQueryBuilder.GetUserCriticalSectionStateQuery; } else { command.CommandText = TokensQueryBuilder.GetClientCriticalSectionStateQuery; } command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinitionId; using (var reader = command.ExecuteReader()) { var readSuccess = reader.Read(); if (readSuccess) { var csState = new CriticalSectionState(); csState.IsGranted = int.Parse(reader[GetCsStatusColumnName(criticalSectionType)].ToString()) == 0; csState.GrantedToExecution = reader[GetGrantedToColumnName(criticalSectionType)].ToString(); csState.SetQueue(reader[GetQueueColumnName(criticalSectionType)].ToString()); csState.StartTrackingModifications(); return(csState); } } throw new CriticalSectionException("No Task exists with id " + taskDefinitionId); }
public StartCriticalSectionRequest(TaskId taskId, string taskExecutionId, TaskDeathMode taskDeathMode, CriticalSectionType criticalSectionType) : base(taskId, taskExecutionId) { TaskDeathMode = taskDeathMode; Type = criticalSectionType; }
private string GetQueueColumnName(CriticalSectionType criticalSectionType) { if (criticalSectionType == CriticalSectionType.User) { return("UserCsQueue"); } return("ClientCsQueue"); }
private string GetCsStatusColumnName(CriticalSectionType criticalSectionType) { if (criticalSectionType == CriticalSectionType.User) { return("UserCsStatus"); } return("ClientCsStatus"); }
private string GetGrantedToColumnName(CriticalSectionType criticalSectionType) { if (criticalSectionType == CriticalSectionType.User) { return("UserCsTaskExecutionId"); } return("ClientCsTaskExecutionId"); }
public CriticalSectionContext(ICriticalSectionRepository criticalSectionRepository, TaskExecutionInstance taskExecutionInstance, TaskExecutionOptions taskExecutionOptions, CriticalSectionType criticalSectionType) { _criticalSectionRepository = criticalSectionRepository; _taskExecutionInstance = taskExecutionInstance; _taskExecutionOptions = taskExecutionOptions; _criticalSectionType = criticalSectionType; ValidateOptions(); }
private CompleteCriticalSectionResponse ReturnCriticalSectionToken(TaskId taskId, int taskDefinitionId, string taskExecutionId, CriticalSectionType criticalSectionType) { var response = new CompleteCriticalSectionResponse(); using (var connection = CreateNewConnection(taskId)) { SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable); var command = connection.CreateCommand(); command.Transaction = transaction; if (criticalSectionType == CriticalSectionType.User) command.CommandText = TokensQueryBuilder.ReturnUserCriticalSectionTokenQuery; else command.CommandText = TokensQueryBuilder.ReturnClientCriticalSectionTokenQuery; command.CommandTimeout = ConnectionStore.Instance.GetConnection(taskId).QueryTimeoutSeconds; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinitionId; command.Parameters.Add("@TaskExecutionId", SqlDbType.Int).Value = int.Parse(taskExecutionId); try { command.ExecuteNonQuery(); transaction.Commit(); } catch (SqlException sqlEx) { TryRollBack(transaction, sqlEx); } catch (Exception ex) { TryRollback(transaction, ex); } } return response; }
private async Task <CompleteCriticalSectionResponse> ReturnCriticalSectionTokenAsync(TaskId taskId, int taskDefinitionId, string taskExecutionId, CriticalSectionType criticalSectionType) { var response = new CompleteCriticalSectionResponse(); using (var connection = await CreateNewConnectionAsync(taskId).ConfigureAwait(false)) { SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable); var command = connection.CreateCommand(); command.Transaction = transaction; if (criticalSectionType == CriticalSectionType.User) { command.CommandText = TokensQueryBuilder.ReturnUserCriticalSectionTokenQuery; } else { command.CommandText = TokensQueryBuilder.ReturnClientCriticalSectionTokenQuery; } command.CommandTimeout = ConnectionStore.Instance.GetConnection(taskId).QueryTimeoutSeconds; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinitionId; command.Parameters.Add("@TaskExecutionId", SqlDbType.Int).Value = int.Parse(taskExecutionId); try { await command.ExecuteNonQueryAsync().ConfigureAwait(false); transaction.Commit(); } catch (SqlException sqlEx) { TryRollBack(transaction, sqlEx); } catch (Exception ex) { TryRollback(transaction, ex); } } return(response); }
private async Task UpdateCriticalSectionStateAsync(int taskDefinitionId, CriticalSectionState csState, CriticalSectionType criticalSectionType, SqlCommand command) { command.Parameters.Clear(); if (criticalSectionType == CriticalSectionType.User) { command.CommandText = TokensQueryBuilder.SetUserCriticalSectionStateQuery; } else { command.CommandText = TokensQueryBuilder.SetClientCriticalSectionStateQuery; } command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinitionId; command.Parameters.Add("@CsStatus", SqlDbType.Int).Value = csState.IsGranted ? 1 : 0; command.Parameters.Add("@CsTaskExecutionId", SqlDbType.Int).Value = csState.GrantedToExecution; command.Parameters.Add("@CsQueue", SqlDbType.VarChar, 8000).Value = csState.GetQueueString(); await command.ExecuteNonQueryAsync().ConfigureAwait(false); }
private string GetCsStatusColumnName(CriticalSectionType criticalSectionType) { if (criticalSectionType == CriticalSectionType.User) return "UserCsStatus"; return "ClientCsStatus"; }
private CriticalSectionState GetCriticalSectionState(int taskDefinitionId, CriticalSectionType criticalSectionType, SqlCommand command) { command.Parameters.Clear(); if (criticalSectionType == CriticalSectionType.User) command.CommandText = TokensQueryBuilder.GetUserCriticalSectionStateQuery; else command.CommandText = TokensQueryBuilder.GetClientCriticalSectionStateQuery; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinitionId; using (var reader = command.ExecuteReader()) { var readSuccess = reader.Read(); if (readSuccess) { var csState = new CriticalSectionState(); csState.IsGranted = int.Parse(reader[GetCsStatusColumnName(criticalSectionType)].ToString()) == 0; csState.GrantedToExecution = reader[GetGrantedToColumnName(criticalSectionType)].ToString(); csState.SetQueue(reader[GetQueueColumnName(criticalSectionType)].ToString()); csState.StartTrackingModifications(); return csState; } } throw new CriticalSectionException("No Task exists with id " + taskDefinitionId); }
public CompleteCriticalSectionRequest(TaskId taskId, string taskExecutionId, CriticalSectionType criticalSectionType) : base(taskId, taskExecutionId) { Type = criticalSectionType; }
private bool TryAcquireCriticalSection(TaskId taskId, int taskDefinitionId, string taskExecutionId, CriticalSectionType criticalSectionType) { bool granted = false; using (var connection = CreateNewConnection(taskId)) { SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable); var command = connection.CreateCommand(); command.Transaction = transaction; command.CommandTimeout = ConnectionStore.Instance.GetConnection(taskId).QueryTimeoutSeconds; ; try { AcquireRowLock(taskDefinitionId, taskExecutionId, command); var csState = GetCriticalSectionState(taskDefinitionId, criticalSectionType, command); CleanseOfExpiredExecutions(csState, command); if (csState.IsGranted) { // if the critical section is still granted to another execution after cleansing // then we rejected the request. If the execution is not in the queue then we add it if (!csState.ExistsInQueue(taskExecutionId)) csState.AddToQueue(taskExecutionId); granted = false; } else { if (csState.GetQueue().Any()) { if (csState.GetFirstExecutionIdInQueue() == taskExecutionId) { GrantCriticalSection(csState, taskDefinitionId, taskExecutionId, command); csState.RemoveFirstInQueue(); granted = true; } else { // not next in queue so cannot be granted the critical section granted = false; } } else { GrantCriticalSection(csState, taskDefinitionId, taskExecutionId, command); granted = true; } } if (csState.HasBeenModified) UpdateCriticalSectionState(taskDefinitionId, csState, criticalSectionType, command); transaction.Commit(); } catch (SqlException sqlEx) { TryRollBack(transaction, sqlEx); } catch (Exception ex) { TryRollback(transaction, ex); } } return granted; }
private string GetQueueColumnName(CriticalSectionType criticalSectionType) { if (criticalSectionType == CriticalSectionType.User) return "UserCsQueue"; return "ClientCsQueue"; }
private string GetGrantedToColumnName(CriticalSectionType criticalSectionType) { if (criticalSectionType == CriticalSectionType.User) return "UserCsTaskExecutionId"; return "ClientCsTaskExecutionId"; }
private async Task <bool> TryAcquireCriticalSectionAsync(TaskId taskId, int taskDefinitionId, string taskExecutionId, CriticalSectionType criticalSectionType) { bool granted = false; using (var connection = await CreateNewConnectionAsync(taskId).ConfigureAwait(false)) { SqlTransaction transaction = connection.BeginTransaction(IsolationLevel.Serializable); var command = connection.CreateCommand(); command.Transaction = transaction; command.CommandTimeout = ConnectionStore.Instance.GetConnection(taskId).QueryTimeoutSeconds;; try { await AcquireRowLockAsync(taskDefinitionId, taskExecutionId, command).ConfigureAwait(false); var csState = await GetCriticalSectionStateAsync(taskDefinitionId, criticalSectionType, command).ConfigureAwait(false); await CleanseOfExpiredExecutionsAsync(csState, command).ConfigureAwait(false); if (csState.IsGranted) { // if the critical section is still granted to another execution after cleansing // then we rejected the request. If the execution is not in the queue then we add it if (!csState.ExistsInQueue(taskExecutionId)) { csState.AddToQueue(taskExecutionId); } granted = false; } else { if (csState.GetQueue().Any()) { if (csState.GetFirstExecutionIdInQueue() == taskExecutionId) { GrantCriticalSection(csState, taskDefinitionId, taskExecutionId, command); csState.RemoveFirstInQueue(); granted = true; } else { // not next in queue so cannot be granted the critical section granted = false; } } else { GrantCriticalSection(csState, taskDefinitionId, taskExecutionId, command); granted = true; } } if (csState.HasBeenModified) { await UpdateCriticalSectionStateAsync(taskDefinitionId, csState, criticalSectionType, command).ConfigureAwait(false); } transaction.Commit(); } catch (SqlException sqlEx) { TryRollBack(transaction, sqlEx); } catch (Exception ex) { TryRollback(transaction, ex); } } return(granted); }
private void UpdateCriticalSectionState(int taskDefinitionId, CriticalSectionState csState, CriticalSectionType criticalSectionType, SqlCommand command) { command.Parameters.Clear(); if (criticalSectionType == CriticalSectionType.User) command.CommandText = TokensQueryBuilder.SetUserCriticalSectionStateQuery; else command.CommandText = TokensQueryBuilder.SetClientCriticalSectionStateQuery; command.Parameters.Add("@TaskDefinitionId", SqlDbType.Int).Value = taskDefinitionId; command.Parameters.Add("@CsStatus", SqlDbType.Int).Value = csState.IsGranted ? 1 : 0; command.Parameters.Add("@CsTaskExecutionId", SqlDbType.Int).Value = csState.GrantedToExecution; command.Parameters.Add("@CsQueue", SqlDbType.VarChar, 8000).Value = csState.GetQueueString(); command.ExecuteNonQuery(); }