/// <summary> /// Returns the first job on the queue whose dependencies have been met, whose status /// is set to 'waiting', and which isn't owned by any JobWorkers /// </summary> /// <returns></returns> private TaggedJob GetNextAvailableJob() { TaggedJob oJob = null; lock (mainForm.Jobs.ResourceLock) { foreach (TaggedJob job in mainForm.Jobs.GlobalJobQueue.JobList) { if (mode == JobWorkerMode.CloseOnLocalListCompleted && // if this worker is about to be closed after local queue processing (job.OwningWorker == null || !job.OwningWorker.Equals(this.Name))) // ignore jobs which are not assigned to this worker { continue; } if (job.Status == JobStatus.WAITING && // only process waiting jobs (job.OwningWorker == null || job.OwningWorker.Equals(this.Name)) && // only process unassigned jobs or jobs which are assigned to the current worker mainForm.Jobs.AreDependenciesMet(job) && // check if all job dependencies are fullfilled (mainForm.Jobs.CanNewJobBeStarted(job.Job) || bIsTemporaryWorker)) // check if a blocking encoding is already in process - always process if temporary worker { job.Status = JobStatus.PROCESSING; // mark job as in processing so that no other worker can fetch it oJob = job; break; } } } return(oJob); }
/// <summary> /// starts the next job in the queue which is available /// </summary> /// <returns></returns> private JobStartInfo StartNextJobInQueue() { TaggedJob job = GetNextAvailableJob(); if (job == null) { status = JobWorkerStatus.Idle; RefreshAll(); return(JobStartInfo.NO_JOBS_WAITING); } status = JobWorkerStatus.Running; RefreshAll(); if (StartEncoding(job)) { // successfully started return(JobStartInfo.JOB_STARTED); } else { status = JobWorkerStatus.Idle; RefreshAll(); return(JobStartInfo.COULDNT_START); } }
/// <summary> /// marks job currently marked as processing as aborted /// </summary> private void markJobAborted() { TaggedJob job = currentJob; job.Status = JobStatus.ABORTED; job.End = DateTime.Now; LogItem i = new LogItem("Deleting aborted output"); i.LogValue("Delete aborted ouptut set", mainForm.Settings.DeleteAbortedOutput); if (mainForm.Settings.DeleteAbortedOutput) { i.LogValue("File to delete", job.Job.Output); try { File.Delete(job.Job.Output); i.LogEvent("File deleted"); } catch (Exception e) { i.LogValue("Error deleting file", e, ImageType.Warning); } } log.Add(i); }
private void MarkDependentJobs() { List <string> oList = new List <string>(); foreach (ListViewItem oItem in queueListView.SelectedItems) { if (!jobs.ContainsKey(oItem.Text)) // check if it has been removed { continue; } TaggedJob job = jobs[oItem.Text]; if (job == null) { continue; } GetAllDependantJobs(job, ref oList); } queueListView.SuspendLayout(); foreach (ListViewItem oItem in queueListView.Items) { if (oList.Contains(oItem.Text)) { oItem.BackColor = Color.FromArgb(255, 225, 235, 255); } else { oItem.BackColor = SystemColors.Window; } } queueListView.ResumeLayout(); }
private JobStartInfo startNextJobInQueue() { mainForm.Jobs.ResourceLock.WaitOne(10000, false); TaggedJob job = getNextJob(); if (job == null) { status = JobWorkerStatus.Idle; mainForm.Jobs.ResourceLock.Release(); return(JobStartInfo.NO_JOBS_WAITING); } while (job != null) { if (job.Job.EncodingMode.Equals("audio") && mainForm.Jobs.IsAnyWorkerEncodingAudio) { // another audio encoding is already in process. postpone the worker status = JobWorkerStatus.Postponed; mainForm.Jobs.ResourceLock.Release(); return(JobStartInfo.NO_JOBS_WAITING); } if (startEncoding(job)) // successful { mainForm.Jobs.ResourceLock.Release(); return(JobStartInfo.JOB_STARTED); } job = getNextJob(); } status = JobWorkerStatus.Idle; mainForm.Jobs.ResourceLock.Release(); return(JobStartInfo.COULDNT_START); }
private void editJobButton_Click(object sender, EventArgs e) { bool bJobCanBeEdited = false; if (queueListView.SelectedItems.Count != 1) { return; } TaggedJob job = jobs[queueListView.SelectedItems[0].Text]; if (job.Status != JobStatus.WAITING && job.Status != JobStatus.POSTPONED) { return; } foreach (IDable <ReconfigureJob> i in MainForm.Instance.PackageSystem.JobConfigurers.Values) { Job j = i.Data(job.Job); if (j != null) { bJobCanBeEdited = true; job.Job = j; } } if (!bJobCanBeEdited) { MessageBox.Show("This kind of job cannot be edited.", "Cannot edit job", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
internal void enqueueJob(TaggedJob j) { if (InvokeRequired) { Invoke(new MethodInvoker(delegate { enqueueJob(j); })); return; } queueListView.Items.Add(new ListViewItem(new string[] { j.Name, "", "", "", "", "", "", "", "", "" })); jobs[j.Name] = j; refreshQueue(); }
internal void removeJobFromQueue(TaggedJob job) { if (InvokeRequired) { Invoke(new MethodInvoker(delegate { removeJobFromQueue(job); })); return; } queueListView.Items[indexOf(job)].Remove(); jobs.Remove(job.Name); queueListView.Refresh(); }
/// <summary> /// Returns true if any selected jobs have the requested status /// </summary> /// <param name="status"></param> /// <returns></returns> private bool AnyJobsHaveStatus(JobStatus status) { foreach (ListViewItem item in this.queueListView.SelectedItems) { TaggedJob job = jobs[item.Text]; if (job.Status == status) { return(true); } } return(false); }
/// Sets the job status of the selected jobs to postponed. /// No selected jobs should currently be running. /// </summary> /// <param name="sender">This parameter is ignored</param> /// <param name="e">This parameter is ignored</param> private void PostponeMenuItem_Click(object sender, EventArgs e) { foreach (ListViewItem item in this.queueListView.SelectedItems) { int position = item.Index; TaggedJob job = jobs[item.Text]; Debug.Assert(job.Status != JobStatus.PROCESSING && job.Status != JobStatus.PAUSED, "shouldn't be able to postpone an active job"); job.Status = JobStatus.POSTPONED; this.queueListView.Items[position].SubItems[5].Text = job.StatusString; } }
internal void AddMenuItem(string name, string parent, SingleJobHandler handler) { ToolStripMenuItem item = new ToolStripMenuItem(name); item.Click += delegate(object sender, EventArgs e) { Debug.Assert(queueListView.SelectedItems.Count == 1); TaggedJob j = jobs[queueListView.SelectedItems[0].Text]; handler(j); }; singleJobHandlers.Add(item); addItem(item, parent); }
/// <summary> /// Sets the jobs status of the selected jobs to waiting. /// No selected jobs should currently be running. /// </summary> /// <param name="sender">This parameter is ignored</param> /// <param name="e">This parameter is ignored</param> private void waitingMenuItem_Click(object sender, EventArgs e) { foreach (ListViewItem item in this.queueListView.SelectedItems) { int position = item.Index; TaggedJob job = jobs[item.Text]; Debug.Assert(job.Status != JobStatus.PROCESSING, "shouldn't be able to set an active job back to waiting"); job.Status = JobStatus.WAITING; queueListView.Items[position].SubItems[5].Text = job.StatusString; } }
private void processUserRequestToDelete(string name) { if (!jobs.ContainsKey(name)) // Check if it has already been deleted { return; } TaggedJob job = jobs[name]; if (job == null) { return; } RequestJobDeleted(job); }
private int indexOf(TaggedJob j) { Debug.Assert(jobs.ContainsKey(j.Name), "Looking for a job which isn't in the jobs dictionary"); foreach (ListViewItem i in queueListView.Items) { if (i.Text == j.Name) { int index = i.Index; Debug.Assert(index >= 0); return(index); } } Debug.Assert(false, "Couldn't find job in the GUI queue"); throw new Exception(); }
/// <summary> /// Tells if the current selection can be edited. /// Checks: /// if one job actually selected /// whether the selected job is waiting or postponed /// </summary> /// <returns></returns> private bool IsSelectionEditable() { if (queueListView.SelectedItems.Count != 1) { return(false); } TaggedJob job = jobs[queueListView.SelectedItems[0].Text]; if (job.Status != JobStatus.WAITING && job.Status != JobStatus.POSTPONED) { return(false); } return(true); }
/// <summary> /// Copies completion info into the job: end time, FPS, status. /// </summary> /// <param name="job">Job to fill with info</param> /// <param name="su">StatusUpdate with info</param> private void copyInfoIntoJob(TaggedJob job, StatusUpdate su) { Debug.Assert(su.IsComplete); job.End = DateTime.Now; job.EncodingSpeed = su.ProcessingSpeed; if (su.WasAborted) { job.Status = JobStatus.ABORTED; } else if (su.HasError) { job.Status = JobStatus.ERROR; } }
/// <summary> /// marks job currently marked as processing as aborted /// </summary> private void markJobAborted() { if (currentJob == null) { return; } TaggedJob job = currentJob; job.Status = JobStatus.ABORTED; job.End = DateTime.Now; long iCounter = 0; LogItem i = new LogItem("Deleting aborted output"); i.LogValue("Delete aborted ouptut set", mainForm.Settings.DeleteAbortedOutput); if (mainForm.Settings.DeleteAbortedOutput) { i.LogValue("File to delete", job.Job.Output); while (File.Exists(job.Job.Output)) { try { File.Delete(job.Job.Output); } catch (Exception e) { if (++iCounter >= 10) { i.LogValue("Error deleting file", e, ImageType.Warning); break; } else { i.LogEvent("Error deleting file - trying again", ImageType.Information); System.Threading.Thread.Sleep(1000); } } } if (!File.Exists(job.Job.Output)) { i.LogEvent("File deleted"); } } log.Add(i); }
public void refreshQueue() { if (!Visible) { return; } if (queueListView.InvokeRequired) { queueListView.Invoke(new MethodInvoker(delegate { refreshQueue(); })); return; } queueListView.BeginUpdate(); foreach (ListViewItem item in queueListView.Items) { TaggedJob job = jobs[item.Text]; item.SubItems[1].Text = job.InputFileName; item.SubItems[2].Text = job.OutputFileName; item.SubItems[3].Text = job.Job.CodecString; item.SubItems[4].Text = job.Job.EncodingMode; item.SubItems[5].Text = job.StatusString; item.SubItems[6].Text = job.OwningWorker ?? ""; if (job.Status == JobStatus.DONE) { item.SubItems[8].Text = job.End.ToLongTimeString(); item.SubItems[9].Text = job.EncodingSpeed; } else { item.SubItems[8].Text = ""; item.SubItems[9].Text = ""; } if (job.Status == JobStatus.DONE || job.Status == JobStatus.PROCESSING || job.Status == JobStatus.ABORTING) { item.SubItems[7].Text = job.Start.ToLongTimeString(); } else { item.SubItems[7].Text = ""; } } queueListView.EndUpdate(); queueListView.Refresh(); }
/// <summary> /// handles the doubleclick event for the listview /// changes the job status from waiting -> postponed to waiting /// from done -> waiting -> postponed -> waiting /// from error -> waiting -> postponed -> waiting /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void queueListView_DoubleClick(object sender, EventArgs e) { if (this.queueListView.SelectedItems.Count > 0) // otherwise { int position = this.queueListView.SelectedItems[0].Index; TaggedJob job = jobs[this.queueListView.SelectedItems[0].Text]; if (job.Status == JobStatus.WAITING) // waiting -> postponed { job.Status = JobStatus.POSTPONED; } else { job.Status = JobStatus.WAITING; } this.queueListView.Items[position].SubItems[5].Text = job.StatusString; } }
private void GetAllDependantJobs(TaggedJob job, ref List <string> oList) { if (oList.Contains(job.Name)) { return; } oList.Add(job.Name); foreach (TaggedJob j in job.EnabledJobs) { GetAllDependantJobs(j, ref oList); } foreach (TaggedJob j in job.RequiredJobs) { GetAllDependantJobs(j, ref oList); } }
private List <TaggedJob> removeAllDependantJobsFromQueue(TaggedJob job) { removeJobFromQueue(job); List <TaggedJob> list = new List <TaggedJob>(); foreach (TaggedJob j in job.EnabledJobs) { if (jobs.ContainsKey(j.Name)) { list.AddRange(removeAllDependantJobsFromQueue(j)); } else { list.Add(j); } } return(list); }
private void InputFolderToolStripMenuItem_Click(object sender, EventArgs e) { foreach (ListViewItem item in this.queueListView.SelectedItems) { TaggedJob job = jobs[item.Text]; if (!Directory.Exists(FileUtil.GetDirectoryName(job.InputFile))) { continue; } try { Process prc = new Process(); prc.StartInfo.FileName = FileUtil.GetDirectoryName(job.InputFile); prc.Start(); } catch (Exception) { } } }
private void OutputFileToolStripMenuItem_Click(object sender, EventArgs e) { foreach (ListViewItem item in this.queueListView.SelectedItems) { TaggedJob job = jobs[item.Text]; if (!File.Exists(job.OutputFile)) { continue; } try { Process prc = new Process(); prc.StartInfo.FileName = job.OutputFile; prc.Start(); } catch (Exception) { } } }
/// <summary> /// marks job currently marked as processing as aborted /// </summary> private void MarkJobAborted() { if (currentJob == null) { return; } TaggedJob job = currentJob; job.Status = JobStatus.ABORTED; job.End = DateTime.Now; LogItem i = new LogItem(string.Format("[{0:G}] {1}", DateTime.Now, "Deleting aborted output")); i.LogValue("Delete aborted output set", mainForm.Settings.DeleteAbortedOutput); if (mainForm.Settings.DeleteAbortedOutput && File.Exists(job.Job.Output)) { // delete outout file and temporary files if (File.Exists(job.Job.Output)) { FileUtil.DeleteFile(job.Job.Output, i); if (!File.Exists(job.Job.Output)) { i.LogValue("File deleted", job.Job.Output); } } foreach (string strFile in job.Job.FilesToDelete) { if (!File.Exists(strFile)) { continue; } FileUtil.DeleteFile(strFile, i); if (!File.Exists(strFile)) { i.LogValue("File deleted", strFile); } } } log.Add(i); }
/// <summary> /// marks job currently marked as processing as aborted /// </summary> private void markJobAborted() { TaggedJob job = currentJob; job.Status = JobStatus.ABORTED; job.End = DateTime.Now; if (mainForm.Settings.DeleteAbortedOutput) { mainForm.addToLog("Job aborted, deleting output file..."); try { File.Delete(job.Job.Output); mainForm.addToLog("Deletion successful.\r\n"); } catch (Exception) { mainForm.addToLog("Deletion failed.\r\n"); } } }
/// <summary> /// handles the doubleclick event for the listview /// changes the job status from waiting -> postponed to waiting /// from done -> waiting -> postponed -> waiting /// from error -> waiting -> postponed -> waiting /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void QueueListView_DoubleClick(object sender, EventArgs e) { if (this.queueListView.SelectedItems.Count > 0) // otherwise { int position = this.queueListView.SelectedItems[0].Index; TaggedJob job = jobs[this.queueListView.SelectedItems[0].Text]; if (job.Status == JobStatus.PROCESSING || job.Status == JobStatus.PAUSED || job.Status == JobStatus.ABORTING) // job is being processed -> do nothing { return; } if (job.Status == JobStatus.WAITING) // waiting -> postponed { job.Status = JobStatus.POSTPONED; } else { job.Status = JobStatus.WAITING; } this.queueListView.Items[position].SubItems[5].Text = job.StatusString; } }
private JobStartInfo startNextJobInQueue() { TaggedJob job = getNextJob(); if (job == null) { status = JobWorkerStatus.Idle; return(JobStartInfo.NO_JOBS_WAITING); } while (job != null) { if (startEncoding(job)) // successful { return(JobStartInfo.JOB_STARTED); } job = getNextJob(); } status = JobWorkerStatus.Idle; return(JobStartInfo.COULDNT_START); }
private void loadJobButton_Click(object sender, EventArgs e) { if (queueListView.SelectedItems.Count != 1) { return; } TaggedJob job = jobs[queueListView.SelectedItems[0].Text]; if (job.Status != JobStatus.WAITING) { return; } foreach (IDable <ReconfigureJob> i in MainForm.Instance.PackageSystem.JobConfigurers.Values) { Job j = i.Data(job.Job); if (j != null) { job.Job = j; } } }
/// <summary> /// updates the actual GUI with the status information received as parameter /// If the StatusUpdate indicates that the job has ended, the Progress window is closed /// and the logging messages from the StatusUpdate object are added to the log tab /// if the job mentioned in the statusupdate has a next job name defined, the job is looked /// up and processing of that job starts - this applies even in queue encoding mode /// the linked jobs will always be encoded first, regardless of their position in the queue /// If we're in queue encoding mode, the next nob in the queue is also started /// </summary> /// <param name="su">StatusUpdate object containing the current encoder stats</param> private void UpdateGUIStatus(StatusUpdate su) { if (su.IsComplete) { JobFinished(su); return; } // job is not complete yet try { if (pw.IsHandleCreated && pw.Visible) // the window is there, send the update to the window { TaggedJob job = mainForm.Jobs.ByName(su.JobName); su.JobStatus = job.Status; if (job.Status != JobStatus.PAUSED) { pw.BeginInvoke(new UpdateStatusCallback(pw.UpdateStatus), su); } } } catch (Exception e) { mainForm.Log.LogValue("Error trying to update status while a job is running", e, ImageType.Warning); } if (su.PercentageDoneExact > 100) { progress = 100; } else { progress = su.PercentageDoneExact ?? 0; } UpdateProgress(); }
internal void AddJob(TaggedJob j) { j.OwningWorker = this.Name; jobQueue1.enqueueJob(j); localJobs[j.Name] = j; }