source: trunk/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectJobsView.cs @ 16208

Last change on this file since 16208 was 16208, checked in by jzenisek, 12 months ago

#2839: updated job execution implementation in ProjectJobsView

File size: 15.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Threading.Tasks;
27using System.Windows.Forms;
28using HeuristicLab.MainForm;
29using HeuristicLab.MainForm.WindowsForms;
30using HeuristicLab.Core.Views;
31using HeuristicLab.Data;
32using HeuristicLab.Clients.Hive.Views;
33using HeuristicLab.Core;
34
35namespace HeuristicLab.Clients.Hive.Administrator.Views {
36  [View("ProjectView")]
37  [Content(typeof(Project), IsDefaultView = false)]
38  public partial class ProjectJobsView : ItemView {
39    private const string JOB_ID = "Id";
40    private const string JOB_NAME = "Name";
41    private const string JOB_OWNER = "Owner";
42    private const string JOB_OWNERID = "Owner Id";
43    private const string JOB_DATECREATED = "Date Created";
44    private const string JOB_STATE = "State";
45    private const string JOB_EXECUTIONSTATE = "Execution State";
46    private const string JOB_DESCRIPTION = "Description";
47    private const string JOB_TASKCOUNT = "Tasks";
48    private const string JOB_CALCULATINGTASKCOUNT = "Calculating";
49    private const string JOB_FINISHEDTASKCOUNT = "Finished";
50
51    private readonly Color onlineStatusColor = Color.FromArgb(255, 189, 249, 143); // #bdf98f
52    private readonly Color onlineStatusColor2 = Color.FromArgb(255, 157, 249, 143); // #9df98f
53    private readonly Color statisticsPendingStatusColor = Color.FromArgb(255, 249, 210, 145); // #f9d291
54    private readonly Color deletionPendingStatusColor = Color.FromArgb(255, 249, 172, 144); // #f9ac90
55    private readonly Color deletionPendingStatusColor2 = Color.FromArgb(255, 249, 149, 143); // #f9958f
56
57    private IProgress progress;
58    public IProgress Progress {
59      get { return progress; }
60      set {
61        this.progress = value;
62        OnIsProgressingChanged();
63      }
64    }
65
66    public new Project Content {
67      get { return (Project)base.Content; }
68      set { base.Content = value; }
69    }
70
71    public ProjectJobsView() {
72      InitializeComponent();
73      progress = new Progress();
74
75      removeButton.Enabled = false;     
76    }
77
78    protected override void RegisterContentEvents() {
79      base.RegisterContentEvents();
80      matrixView.DataGridView.SelectionChanged += DataGridView_SelectionChanged;
81      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().AddOperationProgressToView(this, progress);
82    }
83
84    protected override void DeregisterContentEvents() {
85      matrixView.DataGridView.SelectionChanged -= DataGridView_SelectionChanged;
86      MainFormManager.GetMainForm<HeuristicLab.MainForm.WindowsForms.MainForm>().RemoveOperationProgressFromView(this, false);
87      base.DeregisterContentEvents();
88    }
89
90    private void DataGridView_SelectionChanged(object sender, EventArgs e) {
91      SetEnabledStateOfControls();
92    }
93
94    #region Overrides
95    protected override void OnContentChanged() {
96      base.OnContentChanged();
97      removeButton.Enabled = false;
98      UpdateJobs();
99      SetEnabledStateOfControls();
100    }
101
102    protected override void SetEnabledStateOfControls() {
103      base.SetEnabledStateOfControls();
104      bool enabled = Content != null && !Locked && !ReadOnly;
105
106      matrixView.Enabled = enabled;
107
108      // Buttons (start/resume, pause, stop, remove)
109      refreshButton.Enabled = startButton.Enabled = pauseButton.Enabled = stopButton.Enabled = removeButton.Enabled = false;
110
111      if (enabled && progress.ProgressState != ProgressState.Started) {
112        var jobs = GetSelectedJobs().ToList();
113        if (jobs.Any()) {
114
115          // TODO: include isControllable?!
116          startButton.Enabled = jobs.All(x =>
117            !x.IsProgressing && x.HiveTasks != null && x.HiveTasks.Count > 0
118            && x.Job.ProjectId != null && x.Job.ProjectId != Guid.Empty && x.Job.ResourceIds != null && x.Job.ResourceIds.Any()
119            && (x.ExecutionState == ExecutionState.Prepared || x.ExecutionState == ExecutionState.Paused));
120          pauseButton.Enabled = jobs.All(x => !x.IsProgressing && x.ExecutionState == ExecutionState.Started);
121          stopButton.Enabled = jobs.All(x => !x.IsProgressing && (x.ExecutionState == ExecutionState.Started || x.ExecutionState == ExecutionState.Paused));
122          removeButton.Enabled = jobs.All(x => !x.IsProgressing && x.Job.State == JobState.Online);
123        }
124      }
125
126      // refresh Button
127      if (Content != null && !Locked && progress.ProgressState != ProgressState.Started) {
128        refreshButton.Enabled = true;
129      }
130    }
131
132    #endregion Overrides
133
134    #region Event Handlers
135    private void ProjectJobsView_Load(object sender, EventArgs e) {
136     
137    }
138
139    private void refreshButton_Click(object sender, EventArgs e) {
140      var task = System.Threading.Tasks.Task.Factory.StartNew(RefreshJobsAsync);
141      progress.Start("Refreshing jobs...");
142      SetEnabledStateOfControls();
143
144      task.ContinueWith((t) => {
145        matrixView.DataGridView.ClearSelection();
146      });
147    }
148
149    private void removeButton_Click(object sender, EventArgs e) {
150      var jobs = GetSelectedJobs();
151
152      if (jobs.Any()) {
153        var result = MessageBox.Show("Do you really want to remove following job(s):\n\n"
154                                     + String.Join("\n", jobs.Select(x => x.Job.Name)),
155          "HeuristicLab Hive Administrator",
156          MessageBoxButtons.YesNo,
157          MessageBoxIcon.Question);
158
159        if (result == DialogResult.Yes) {         
160          var task = System.Threading.Tasks.Task.Factory.StartNew(RemoveJobsAsync, jobs);
161          progress.Start();
162          SetEnabledStateOfControls();
163
164          task.ContinueWith((t) => {
165            matrixView.DataGridView.ClearSelection();
166            RefreshJobs();
167            progress.Finish();
168          }, TaskContinuationOptions.NotOnFaulted);
169
170          task.ContinueWith((t) => {
171            matrixView.DataGridView.ClearSelection();
172            RefreshJobs();
173            progress.Finish();
174            MessageBox.Show("An error occured removing the job(s). " + t.Exception.Message, "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
175          }, TaskContinuationOptions.OnlyOnFaulted);
176        }
177      }
178    }
179
180    private void startButton_Click(object sender, EventArgs e) {
181      var jobs = GetSelectedJobs();
182
183      if (jobs.Any()) {
184        var result = MessageBox.Show("Do you really want to resume following job(s):\n\n"
185                                     + String.Join("\n", jobs.Select(x => x.Job.Name)),
186          "HeuristicLab Hive Administrator",
187          MessageBoxButtons.YesNo,
188          MessageBoxIcon.Question);
189
190        if (result == DialogResult.Yes) {
191          var task = System.Threading.Tasks.Task.Factory.StartNew(ResumeJobsAsync, jobs);
192          progress.Start();
193          SetEnabledStateOfControls();
194
195          task.ContinueWith((t) => {
196            matrixView.DataGridView.ClearSelection();
197            RefreshJobs();
198            progress.Finish();
199          });
200
201          task.ContinueWith((t) => {
202            matrixView.DataGridView.ClearSelection();
203            RefreshJobs();
204            progress.Finish();
205            MessageBox.Show("An error occured resuming the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
206          }, TaskContinuationOptions.OnlyOnFaulted);
207        }
208      }
209    }
210
211    private void pauseButton_Click(object sender, EventArgs e) {
212      var jobs = GetSelectedJobs();
213
214      if (jobs.Any()) {
215        var result = MessageBox.Show("Do you really want to pause following job(s):\n\n"
216                                     + String.Join("\n", jobs.Select(x => x.Job.Name)),
217          "HeuristicLab Hive Administrator",
218          MessageBoxButtons.YesNo,
219          MessageBoxIcon.Question);
220
221        if (result == DialogResult.Yes) {
222          var task = System.Threading.Tasks.Task.Factory.StartNew(PauseJobsAsync, jobs);
223          progress.Start();
224          SetEnabledStateOfControls();
225
226          task.ContinueWith((t) => {
227            matrixView.DataGridView.ClearSelection();
228            RefreshJobs();
229            progress.Finish();
230          });
231
232          task.ContinueWith((t) => {
233            matrixView.DataGridView.ClearSelection();
234            RefreshJobs();
235            progress.Finish();
236            MessageBox.Show("An error occured pausing the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
237          }, TaskContinuationOptions.OnlyOnFaulted);
238        }
239      }
240    }
241
242    private void stopButton_Click(object sender, EventArgs e) {
243      var jobs = GetSelectedJobs();
244
245      if (jobs.Any()) {
246        var result = MessageBox.Show("Do you really want to stop following job(s):\n\n"
247                                     + String.Join("\n", jobs.Select(x => x.Job.Name)),
248          "HeuristicLab Hive Administrator",
249          MessageBoxButtons.YesNo,
250          MessageBoxIcon.Question);
251
252        if (result == DialogResult.Yes) {
253          var task = System.Threading.Tasks.Task.Factory.StartNew(StopJobsAsync, jobs);
254          progress.Start();
255          SetEnabledStateOfControls();
256
257          task.ContinueWith((t) => {
258            matrixView.DataGridView.ClearSelection();
259            RefreshJobs();
260            progress.Finish();
261          });
262
263          task.ContinueWith((t) => {
264            matrixView.DataGridView.ClearSelection();
265            RefreshJobs();
266            progress.Finish();
267            MessageBox.Show("An error occured stopping the job(s).", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);           
268          }, TaskContinuationOptions.OnlyOnFaulted);
269        }
270      }
271    }
272
273    public event EventHandler IsProgressingChanged;
274    private void OnIsProgressingChanged() {
275      var handler = IsProgressingChanged;
276      if (handler != null) handler(this, EventArgs.Empty);
277    }
278    #endregion Event Handlers
279
280    #region Helpers
281
282    private IEnumerable<RefreshableJob> GetSelectedJobs() {
283      if (Content == null || matrixView.DataGridView.SelectedRows == null || matrixView.DataGridView.SelectedRows.Count == 0)
284        return Enumerable.Empty<RefreshableJob>() ;
285
286      var jobs = new List<RefreshableJob>();
287      foreach (DataGridViewRow r in matrixView.DataGridView.SelectedRows) {
288        if (((string)r.Cells[0].Value) == JobState.Online.ToString()) {
289          jobs.Add(HiveAdminClient.Instance.Jobs[Content.Id].FirstOrDefault(x => x.Id == Guid.Parse((string) r.Cells[9].Value)));
290        }
291      }
292
293      return jobs;
294    }
295
296    private void RefreshJobs() {
297      HiveAdminClient.Instance.RefreshJobs();
298      UpdateJobs();
299      SetEnabledStateOfControls();
300    }
301
302    private StringMatrix CreateValueMatrix() {
303      if (Content == null || Content.Id == Guid.Empty)
304        return new StringMatrix();
305
306      var jobs = HiveAdminClient.Instance.Jobs[Content.Id];
307      var resources = HiveAdminClient.Instance.Resources;
308      string[,] values = new string[jobs.Count, 11];
309
310      for(int i = 0; i < jobs.Count; i++) {
311        var job = jobs.ElementAt(i);       
312        values[i, 0] = job.Job.State.ToString();
313        values[i, 1] = job.ExecutionState.ToString();
314        values[i, 2] = job.Job.DateCreated.ToString();
315        values[i, 3] = job.Job.OwnerUsername;
316        values[i, 4] = job.Job.Name;
317        values[i, 5] = job.Job.JobCount.ToString();
318        values[i, 6] = job.Job.CalculatingCount.ToString();
319        values[i, 7] = job.Job.FinishedCount.ToString();
320        values[i, 8] = job.Job.Description;       
321        values[i, 9] = job.Job.Id.ToString();
322        values[i, 10] = job.Job.OwnerUserId.ToString();
323      }
324     
325      var matrix = new StringMatrix(values);
326      matrix.ColumnNames = new string[] { JOB_STATE, JOB_EXECUTIONSTATE, JOB_DATECREATED, JOB_OWNER, JOB_NAME, JOB_TASKCOUNT, JOB_CALCULATINGTASKCOUNT, JOB_FINISHEDTASKCOUNT, JOB_DESCRIPTION, JOB_ID, JOB_OWNERID };
327      matrix.SortableView = true;
328      return matrix;
329    }
330   
331    private void UpdateJobs() {
332      if (InvokeRequired) Invoke((Action)UpdateJobs);
333      else {
334        if(Content != null && Content.Id != null && Content.Id != Guid.Empty) {
335          var matrix = CreateValueMatrix();
336          matrixView.Content = matrix;
337          if(matrix != null) {
338            foreach (DataGridViewRow row in matrixView.DataGridView.Rows) {
339              string val = ((string)row.Cells[0].Value);
340              if (val == JobState.Online.ToString()) {
341                row.DefaultCellStyle.BackColor = onlineStatusColor;
342              } else if (val == JobState.StatisticsPending.ToString()) {
343                row.DefaultCellStyle.BackColor = statisticsPendingStatusColor;
344              } else if (val == JobState.DeletionPending.ToString()) {
345                row.DefaultCellStyle.BackColor = deletionPendingStatusColor;
346              }
347            }
348
349            matrixView.DataGridView.AutoResizeColumns();
350            matrixView.DataGridView.Columns[0].MinimumWidth = 90;
351            matrixView.DataGridView.Columns[1].MinimumWidth = 108;
352          }
353        } 
354      }
355    }
356
357    private void RefreshJobsAsync() {
358      RefreshJobs();
359    }
360
361    private void ResumeJobsAsync(object jobs) {
362      var jobList = (IEnumerable<RefreshableJob>)jobs;
363      foreach (var job in jobList) {
364        progress.Status = "Resuming job \"" + job.Job.Name + "\"...";
365        HiveAdminClient.ResumeJob(job);
366      }
367    }
368
369    private void PauseJobsAsync(object jobs) {
370      var jobList = (IEnumerable<RefreshableJob>)jobs;
371      foreach (var job in jobList) {
372        progress.Status = "Pausing job \"" + job.Job.Name + "\"...";
373        HiveAdminClient.PauseJob(job);
374      }
375    }
376
377    private void StopJobsAsync(object jobs) {
378      var jobList = (IEnumerable<RefreshableJob>) jobs;
379      foreach (var job in jobList) {       
380        progress.Status = "Stopping job \"" + job.Job.Name + "\"...";
381        HiveAdminClient.StopJob(job);
382      }
383    }
384
385    private void RemoveJobsAsync(object jobs) {
386      var jobList = (IEnumerable<RefreshableJob>)jobs;
387      progress.Start();
388      foreach (var job in jobList) {
389        progress.Status = "Deleting job \"" + job.Job.Name + "\"...";
390        HiveAdminClient.RemoveJob(job);
391      }
392      progress.Finish();
393    }
394
395    private void ShowHiveInformationDialog() {
396      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
397      else {
398        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
399          dialog.ShowDialog(this);
400        }
401      }
402    }
403    #endregion Helpers
404  }
405}
Note: See TracBrowser for help on using the repository browser.