internal static Task Get(Database database, string workflowName, string name) { if (database == null) { throw new ArgumentNullException("database", "database is null."); } if (workflowName == null) { throw new ArgumentNullException("workflowName", "workflowName is null."); } if (name == null) { throw new ArgumentNullException("name", "name is null."); } Workflow workflow = Workflow.Get(database, workflowName); workflow.WorkflowLock.EnterReadLock(); try { if (!workflow.TaskNames.ContainsKey(name)) { throw new Exception(string.Format("Task named \"{0}\" not found in the workflow named \"{1}\".", name, workflowName)); } return(workflow.Tasks[workflow.TaskNames[name]]); } finally { workflow.WorkflowLock.ExitReadLock(); } }
public static QueueTask Dequeue(Database database, string queueName) { if (database == null) { throw new ArgumentNullException("database", "database is null."); } if (queueName == null) { throw new ArgumentNullException("queueName", "queueName is null."); } if (Queue.IsEmpty(database, queueName)) { return(null); } Workflow workflow; Task task; Queue queue; Guid workflowId, taskId; for (int attemptNum = 0; attemptNum < MAX_DEQUEUE_ATTEMPTS; attemptNum++) { queue = Queue.Get(database, queueName); queue.QueueLock.EnterReadLock(); try { if (queue.QueuedTasks.Count == 0) { return(null); } var first = queue.QueuedTasks.First.Value; workflowId = first.Item1; taskId = first.Item2; } finally { queue.QueueLock.ExitReadLock(); } workflow = Workflow.Get(database, workflowId); if (workflow == null) { continue; } workflow.WorkflowLock.EnterReadLock(); try { task = workflow.Tasks[taskId]; } finally { workflow.WorkflowLock.ExitReadLock(); } workflow.WorkflowLock.EnterWriteLock(); try { queue.QueueLock.EnterWriteLock(); try { // Validate state; if (queue.QueuedTasks.Count == 0) { return(null); } if (queue.QueuedTasks.First().Item2 != taskId) { continue; } queue.QueuedTasks.RemoveFirst(); queue.RunningTasks.Add(taskId); task.State = TaskState.Running; return(new QueueTask() { WorkflowName = workflow.Name, TaskName = task.Name, }); } finally { queue.QueueLock.ExitWriteLock(); } } finally { workflow.WorkflowLock.ExitWriteLock(); } } return(null); }
public static void Create(Database database, string workflowName, string name, string queueName) { if (database == null) { throw new ArgumentNullException("database", "database is null."); } if (workflowName == null) { throw new ArgumentNullException("workflowName", "workflowName is null."); } if (name == null) { throw new ArgumentNullException("name", "name is null."); } if (queueName == null) { throw new ArgumentNullException("queueName", "queueName is null."); } Task task; var workflow = Workflow.Get(database, workflowName); var queue = Queue.Get(database, queueName); queue.QueueLock.EnterReadLock(); try { task = new Task(name, queue.Id); } finally { queue.QueueLock.ExitReadLock(); } database.WorkflowsLock.EnterReadLock(); try { if (!database.WorkflowNames.ContainsKey(workflowName)) { throw new Exception(string.Format("Workflow with the name \"{0}\" not found.", workflowName)); } workflow = database.Workflows[database.WorkflowNames[workflowName]]; if (workflow.Suspended) { workflow.WorkflowLock.EnterUpgradeableReadLock(); try { workflow.Tasks.Add(task.Id, task); workflow.TaskNames.Add(task.Name, task.Id); } finally { workflow.WorkflowLock.ExitUpgradeableReadLock(); } } else { database.QueuesLock.EnterReadLock(); try { workflow.WorkflowLock.EnterUpgradeableReadLock(); try { queue.QueueLock.EnterWriteLock(); try { workflow.Tasks.Add(task.Id, task); workflow.TaskNames.Add(task.Name, task.Id); queue.QueuedTasks.AddLast(new LinkedListNode <Tuple <Guid, Guid> >(new Tuple <Guid, Guid>(workflow.Id, task.Id))); } finally { queue.QueueLock.ExitWriteLock(); } } finally { workflow.WorkflowLock.ExitUpgradeableReadLock(); } } finally { database.QueuesLock.ExitReadLock(); } } } finally { database.WorkflowsLock.ExitReadLock(); } }
public static void AddDependency(Database database, string workflowName, string nameDependantOn, string nameDependancyTo) { if (database == null) { throw new ArgumentNullException("database", "database is null."); } if (workflowName == null) { throw new ArgumentNullException("workflowName", "workflowName is null."); } if (nameDependantOn == null) { throw new ArgumentNullException("nameDependantOn", "nameDependantOn is null."); } if (workflowName == null) { throw new ArgumentNullException("nameDependancyTo", "nameDependancyTo is null."); } var workflow = Workflow.Get(database, workflowName); var dependantOn = Task.Get(database, workflowName, nameDependantOn); var dependancyTo = Task.Get(database, workflowName, nameDependancyTo); var dependancyToQueue = Queue.Get(database, dependancyTo.QueueId); workflow.WorkflowLock.EnterWriteLock(); try { switch (dependancyTo.State) { case TaskState.AwaitDependence: break; case TaskState.Queued: if (!workflow.Suspended) { dependancyToQueue.QueueLock.EnterWriteLock(); try { dependancyToQueue.QueuedTasks.Remove(dependancyToQueue.QueuedTasks.First(t => t.Item2 == dependancyTo.Id)); } finally { dependancyToQueue.QueueLock.ExitWriteLock(); } } break; case TaskState.Running: case TaskState.Completed: case TaskState.Failed: default: throw new InvalidOperationException("Can only add dependancy to a task which has not yet been started."); } dependancyTo.State = TaskState.AwaitDependence; dependantOn.DependencyTo.Add(dependancyTo.Id); dependancyTo.DependantOn.Add(dependantOn.Id); switch (dependantOn.State) { case TaskState.AwaitDependence: case TaskState.Queued: case TaskState.Running: dependancyTo.OutstandingDependencies.Add(dependantOn.Id); break; } } finally { workflow.WorkflowLock.ExitWriteLock(); } }