diff --git a/MonkeyWrench.DataClasses/Database/DBLane.generated.cs b/MonkeyWrench.DataClasses/Database/DBLane.generated.cs
index 92e0920..401c18b 100644
--- a/MonkeyWrench.DataClasses/Database/DBLane.generated.cs
+++ b/MonkeyWrench.DataClasses/Database/DBLane.generated.cs
@@ -29,6 +29,7 @@ public partial class DBLane : DBRecord
private bool _enabled;
private DateTime? _changed_date;
private string _additional_roles;
+ private int _priority;
public string @lane { get { return _lane; } set { _lane = value; } }
public string @source_control { get { return _source_control; } set { _source_control = value; } }
@@ -41,6 +42,7 @@ public partial class DBLane : DBRecord
public bool @enabled { get { return _enabled; } set { _enabled = value; } }
public DateTime? @changed_date { get { return _changed_date; } set { _changed_date = value; } }
public string @additional_roles { get { return _additional_roles; } set { _additional_roles = value; } }
+ public int @priority { get { return _priority; } set { _priority = value; } }
public override string Table
@@ -53,7 +55,7 @@ public override string Table
{
get
{
- return new string [] { "lane", "source_control", "repository", "min_revision", "max_revision", "parent_lane_id", "commit_filter", "traverse_merge", "enabled", "changed_date", "additional_roles" };
+ return new string [] { "lane", "source_control", "repository", "min_revision", "max_revision", "parent_lane_id", "commit_filter", "traverse_merge", "enabled", "changed_date", "additional_roles", "priority" };
}
}
diff --git a/MonkeyWrench.DataClasses/Database/DBQueueManagement.cs b/MonkeyWrench.DataClasses/Database/DBQueueManagement.cs
index ed1ff17..8b99764 100755
--- a/MonkeyWrench.DataClasses/Database/DBQueueManagement.cs
+++ b/MonkeyWrench.DataClasses/Database/DBQueueManagement.cs
@@ -21,5 +21,6 @@ public enum DBQueueManagement
FinishBeforeNew = 0,
ExecuteLatestAsap = 1, // currently same as FinishBeforeNew (i.e. ignored)
OneRevisionWorkAtATime = 2, //
+ ChooseHighestPriorityLeastRecent = 3
}
}
diff --git a/MonkeyWrench.DataClasses/Database/DBRevisionWork.generated.cs b/MonkeyWrench.DataClasses/Database/DBRevisionWork.generated.cs
index 084d5f5..5a19c37 100644
--- a/MonkeyWrench.DataClasses/Database/DBRevisionWork.generated.cs
+++ b/MonkeyWrench.DataClasses/Database/DBRevisionWork.generated.cs
@@ -29,6 +29,7 @@ public partial class DBRevisionWork : DBRecord
private DateTime? _assignedtime;
private DateTime? _startedtime;
private DateTime? _endtime;
+ private int _priority;
public int @lane_id { get { return _lane_id; } set { _lane_id = value; } }
public int @host_id { get { return _host_id; } set { _host_id = value; } }
@@ -41,6 +42,7 @@ public partial class DBRevisionWork : DBRecord
public DateTime? @assignedtime { get { return _assignedtime; } set { _assignedtime = value; } }
public DateTime? @startedtime { get { return _startedtime; } set { _startedtime = value; } }
public DateTime? @endtime { get { return _endtime; } set { _endtime = value; } }
+ public int @priority { get { return _priority; } set { _priority = value; } }
public override string Table
@@ -53,7 +55,7 @@ public override string Table
{
get
{
- return new string [] { "lane_id", "host_id", "workhost_id", "revision_id", "state", "lock_expires", "completed", "createdtime", "assignedtime", "startedtime", "endtime" };
+ return new string [] { "lane_id", "host_id", "workhost_id", "revision_id", "state", "lock_expires", "completed", "createdtime", "assignedtime", "startedtime", "endtime", "priority" };
}
}
diff --git a/MonkeyWrench.Database/DB.cs b/MonkeyWrench.Database/DB.cs
index 86c4dc6..2f254da 100755
--- a/MonkeyWrench.Database/DB.cs
+++ b/MonkeyWrench.Database/DB.cs
@@ -1163,7 +1163,7 @@ INNER JOIN
AND RevisionWork.lane_id = @lane_id
AND RevisionWork.state <> @dependencynotfulfilled AND RevisionWork.state <> 10 AND RevisionWork.State <> @ignore
AND RevisionWork.completed = false
-ORDER BY RevisionWork.workhost_id IS NULL ASC, Revision.date DESC
+ORDER BY RevisionWork.workhost_id IS NULL ASC, RevisionWork.priority DESC, Revision.date DESC
LIMIT 1
;";
DB.CreateParameter (cmd, "host_id", host.id);
diff --git a/MonkeyWrench.Web.UI/EditHost.aspx b/MonkeyWrench.Web.UI/EditHost.aspx
index 98b3b4d..bcc355a 100755
--- a/MonkeyWrench.Web.UI/EditHost.aspx
+++ b/MonkeyWrench.Web.UI/EditHost.aspx
@@ -47,6 +47,7 @@
+
diff --git a/MonkeyWrench.Web.UI/EditHost.aspx.designer.cs b/MonkeyWrench.Web.UI/EditHost.aspx.designer.cs
index 1b62e96..14bf229 100755
--- a/MonkeyWrench.Web.UI/EditHost.aspx.designer.cs
+++ b/MonkeyWrench.Web.UI/EditHost.aspx.designer.cs
@@ -1,194 +1,56 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:2.0.50727.3082
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-
-
-public partial class EditHost {
-
- ///
- /// tblData control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Table tblData;
-
- ///
- /// txtID control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox txtID;
-
- ///
- /// txtHost control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox txtHost;
-
- ///
- /// txtPassword control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox txtPassword;
-
- ///
- /// cmbQueueManagement control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.DropDownList cmbQueueManagement;
-
- ///
- /// txtDescription control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox txtDescription;
-
- ///
- /// txtArchitecture control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox txtArchitecture;
-
- ///
- /// chkEnabled control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.CheckBox chkEnabled;
-
- ///
- /// cmdSave control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Button cmdSave;
-
- ///
- /// cmdDeleteAllWork control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Button cmdDeleteAllWork;
-
- ///
- /// cmdClearAllWork control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Button cmdClearAllWork;
-
- ///
- /// lblPasswordWarning control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Label lblPasswordWarning;
-
- ///
- /// lblMessage control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Label lblMessage;
-
- ///
- /// tblLanes control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Table tblLanes;
-
- ///
- /// tblMasters control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Table tblMasters;
-
- ///
- /// cmbMasterHosts control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.DropDownList cmbMasterHosts;
-
- ///
- /// cmdAddMasterHost control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.LinkButton cmdAddMasterHost;
-
- ///
- /// tblSlaves control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Table tblSlaves;
-
- ///
- /// editorVariables control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::MonkeyWrench.Web.UI.EnvironmentVariablesEditor editorVariables;
-
- ///
- /// lblConfiguration control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.HtmlControls.HtmlGenericControl lblConfiguration;
-}
+// ------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Mono Runtime Version: 4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// ------------------------------------------------------------------------------
+
+
+
+public partial class EditHost {
+
+ protected System.Web.UI.WebControls.Content Content2;
+
+ protected System.Web.UI.WebControls.Table tblData;
+
+ protected System.Web.UI.WebControls.TextBox txtID;
+
+ protected System.Web.UI.WebControls.TextBox txtHost;
+
+ protected System.Web.UI.WebControls.TextBox txtPassword;
+
+ protected System.Web.UI.WebControls.DropDownList cmbQueueManagement;
+
+ protected System.Web.UI.WebControls.TextBox txtDescription;
+
+ protected System.Web.UI.WebControls.TextBox txtArchitecture;
+
+ protected System.Web.UI.WebControls.CheckBox chkEnabled;
+
+ protected System.Web.UI.WebControls.Button cmdSave;
+
+ protected System.Web.UI.WebControls.Button cmdDeleteAllWork;
+
+ protected System.Web.UI.WebControls.Button cmdClearAllWork;
+
+ protected System.Web.UI.WebControls.Label lblPasswordWarning;
+
+ protected System.Web.UI.WebControls.Label lblMessage;
+
+ protected System.Web.UI.WebControls.Table tblLanes;
+
+ protected System.Web.UI.WebControls.Table tblMasters;
+
+ protected System.Web.UI.WebControls.DropDownList cmbMasterHosts;
+
+ protected System.Web.UI.WebControls.LinkButton cmdAddMasterHost;
+
+ protected System.Web.UI.WebControls.Table tblSlaves;
+
+ protected MonkeyWrench.Web.UI.EnvironmentVariablesEditor editorVariables;
+
+ protected System.Web.UI.HtmlControls.HtmlGenericControl lblConfiguration;
+}
diff --git a/MonkeyWrench.Web.UI/EditLane.aspx b/MonkeyWrench.Web.UI/EditLane.aspx
index 9fa9efa..f210c33 100755
--- a/MonkeyWrench.Web.UI/EditLane.aspx
+++ b/MonkeyWrench.Web.UI/EditLane.aspx
@@ -57,6 +57,17 @@
Comma-separated list of additional roles (besides admin) that can edit this lane.
+
+ Priority:
+
+
+
+
+
+
+
+ Default priority of all builds in the lane.
+
Parent lane:
diff --git a/MonkeyWrench.Web.UI/EditLane.aspx.cs b/MonkeyWrench.Web.UI/EditLane.aspx.cs
index 41d08cb..d860c2a 100755
--- a/MonkeyWrench.Web.UI/EditLane.aspx.cs
+++ b/MonkeyWrench.Web.UI/EditLane.aspx.cs
@@ -90,6 +90,8 @@ protected override void OnInit (EventArgs e)
}
}
+ lstPriority.SelectedIndex = Int32.Parse (lstPriority.Items.FindByValue (response.Lane.priority.ToString ()).Value);
+
if (!IsPostBack) {
for (int i = 0; i < cmbSourceControl.Items.Count; i++) {
cmbSourceControl.Items [i].Selected = lane.source_control == cmbSourceControl.Items [i].Text;
@@ -701,6 +703,7 @@ protected void cmdSave_Click (object sender, EventArgs e)
lane.traverse_merge = chkTraverseMerges.Checked;
lane.enabled = chkEnabled.Checked;
lane.additional_roles = txtRoles.Text;
+ lane.priority = Int32.Parse (lstPriority.SelectedItem.Value);
Utils.LocalWebService.EditLaneWithTags (Master.WebServiceLogin, lane, !string.IsNullOrEmpty (txtTags.Text) ? txtTags.Text.Split (',') : null);
RedirectToSelf ();
diff --git a/MonkeyWrench.Web.UI/EditLane.aspx.designer.cs b/MonkeyWrench.Web.UI/EditLane.aspx.designer.cs
index 1f0872f..58c703e 100644
--- a/MonkeyWrench.Web.UI/EditLane.aspx.designer.cs
+++ b/MonkeyWrench.Web.UI/EditLane.aspx.designer.cs
@@ -33,6 +33,8 @@ public partial class EditLane {
protected System.Web.UI.WebControls.TextBox txtTags;
protected System.Web.UI.WebControls.TextBox txtRoles;
+
+ protected System.Web.UI.WebControls.DropDownList lstPriority;
protected System.Web.UI.WebControls.DropDownList lstParentLane;
diff --git a/MonkeyWrench.Web.WebService/Scheduler/Scheduler.cs b/MonkeyWrench.Web.WebService/Scheduler/Scheduler.cs
index e943234..ca8397e 100755
--- a/MonkeyWrench.Web.WebService/Scheduler/Scheduler.cs
+++ b/MonkeyWrench.Web.WebService/Scheduler/Scheduler.cs
@@ -193,8 +193,8 @@ public static bool AddRevisionWork (DB db, List lanes, List
try {
using (var cmd = db.CreateCommand (@"
- INSERT INTO RevisionWork (lane_id, host_id, revision_id, state)
- SELECT Lane.id, Host.id, Revision.id, 10
+ INSERT INTO RevisionWork (lane_id, host_id, revision_id, priority, state)
+ SELECT Lane.id, Host.id, Revision.id, Lane.priority, 10
FROM HostLane
INNER JOIN Host ON HostLane.host_id = Host.id
INNER JOIN Lane ON HostLane.lane_id = Lane.id
@@ -266,8 +266,8 @@ public static bool AddRevisionWorkSlow (DB db, List lanes, List 1) {
+ int lane_index = -1;
+ int highest_priority = 0;
+ int p = 0;
+ DateTime latest_date = DateTime.MaxValue;
+ DateTime ld = DateTime.MaxValue;
+
+ // we need to find the latest revisionwork each hostlane has completed.
+ // we want to work on the hostlane which has waited the longest amount
+ // of time without getting work done (but which has pending work to do).
+
+ for (int i = 0; i < hostlanes.Count; i++) {
+ DBHostLane hl = hostlanes [i];
+ // check if this hostlane has pending work and get its priority.
+ // this would ideally be included in the query below, but I'm not sure
+ // how to do that while still distinguising the case where nothing has
+ // been done ever for a hostlane.
+ using (IDbCommand cmd = db.CreateCommand ()) {
+ cmd.CommandText = @"
+SELECT RevisionWork.priority
+FROM RevisionWork
+WHERE
+ RevisionWork.host_id = @host_id
+AND (RevisionWork.workhost_id = @workhost_id OR RevisionWork.workhost_id IS NULL)
+AND RevisionWork.completed = false
+AND RevisionWork.state <> 9 AND RevisionWork.state <> 10 AND RevisionWork.state <> 11
+AND lane_id = @lane_id
+AND RevisionWork.priority >= @priority
+ORDER BY RevisionWork.priority DESC
+LIMIT 1;
+ ";
+ DB.CreateParameter (cmd, "lane_id", hl.lane_id);
+ DB.CreateParameter (cmd, "host_id", hl.host_id);
+ DB.CreateParameter (cmd, "workhost_id", response.Host.id);
+ DB.CreateParameter (cmd, "priority", highest_priority);
+
+ object obj = cmd.ExecuteScalar ();
+ if (obj == DBNull.Value || obj == null) {
+ // there is nothing to do for this hostlane
+ continue;
+ } else {
+ p = (int)obj;
+ }
+ }
+
+ // find the latest completed (this may not be correct, maybe find the latest unstarted?)
+ // revisionwork for this hostlane.
+ using (IDbCommand cmd = db.CreateCommand ()) {
+ cmd.CommandText = @"
+SELECT RevisionWork.endtime
+FROM RevisionWork
+WHERE
+ RevisionWork.host_id = @host_id
+AND (RevisionWork.workhost_id = @workhost_id OR RevisionWork.workhost_id IS NULL)
+AND RevisionWork.completed = true
+AND lane_id = @lane_id
+ORDER BY RevisionWork.endtime DESC
+LIMIT 1;
+ ";
+
+ DB.CreateParameter (cmd, "lane_id", hl.lane_id);
+ DB.CreateParameter (cmd, "host_id", hl.host_id);
+ DB.CreateParameter (cmd, "workhost_id", response.Host.id);
+
+ object obj = cmd.ExecuteScalar ();
+
+ if (obj is DateTime) {
+ ld = (DateTime) obj;
+ } else {
+ // Nothing has been done for this lane
+ ld = DateTime.MinValue;
+ }
+
+ if (p > highest_priority || (p == highest_priority && ld < latest_date)) {
+ highest_priority = p;
+ latest_date = ld;
+ lane_index = i;
+ }
+ }
+ }
+
+ if (lane_index >= 0) {
+ DBHostLane tmp = hostlanes [lane_index];
+ hostlanes.Clear ();
+ hostlanes.Add (tmp);
+ } else {
+ hostlanes.Clear (); // there is nothing to do at all
+ }
+ }
+ break;
}
foreach (DBHostLane hl in hostlanes) {
diff --git a/scripts/database.sql b/scripts/database.sql
index 9b5761a..ade4cdb 100644
--- a/scripts/database.sql
+++ b/scripts/database.sql
@@ -78,7 +78,12 @@ CREATE TABLE Lane (
traverse_merge boolean NOT NULL DEFAULT FALSE, -- if commits from a merge (besides the merge commit itself) should be included.
enabled boolean NOT NULL DEFAULT TRUE, -- if a lane is enabled or not.
changed_date timestamp NULL DEFAULT NULL, -- the latest date something happened in this lane,
- additional_roles text NULL DEFAULT NULL, -- additional roles for access (for users who are not admin)
+ additional_roles text NULL DEFAULT NULL, -- additional roles for access (for users who are not admin)
+ priority int NOT NULL DEFAULT 1 CHECK (priority >= 0), -- default priority for new revisionworks
+ -- Possible values:
+ -- * 0: PR lanes, least priority
+ -- * 1: Unremarkable lanes
+ -- * 2: Release lanes, highest priority
UNIQUE (lane)
);
INSERT INTO Lane (lane, source_control, repository) VALUES ('monkeywrench', 'git', 'git://github.com/mono/monkeywrench');
@@ -86,6 +91,7 @@ INSERT INTO Lane (lane, source_control, repository) VALUES ('monkeywrench', 'git
-- ALTER TABLE Lane ADD COLUMN enabled boolean NOT NULL DEFAULT TRUE;
-- ALTER TABLE Lane ADD COLUMN changed_date timestamp NULL DEFAULT NULL;
-- ALTER TABLE Lane ADD CONSTRAINT parentlane_fkey FOREIGN KEY (parent_lane_id) REFERENCES Lane (id);
+-- ALTER TABLE Lane ADD COLUMN priority integer DEFAULT 1 CHECK (priority >= 0), ALTER COLUMN priority SET NOT NULL;
-- Command to set the latest changed_date on every lane.
-- UPDATE Lane SET changed_date = (SELECT MAX(endtime) FROM RevisionWork WHERE RevisionWork.lane_id = Lane.id);
@@ -254,6 +260,7 @@ CREATE TABLE RevisionWork (
assignedtime timestamptz NULL, -- Time that workhost_id was assigned
startedtime timestamptz NULL, -- Time that the first work was created, denormalized from `MIN(work.starttime) WHERE work.revisionwork_id = id`
endtime timestamptz NULL, -- Time that the RevisionWork was completed
+ priority int NOT NULL DEFAULT 1 CHECK (priority >= 0),
-- alter table revisionwork add column endtime timestamp NOT NULL DEFAULT '2000-01-01 00:00:00+0';
@@ -269,6 +276,7 @@ CREATE TABLE RevisionWork (
-- WHERE endtime != '2000-01-01 00:00:00+0'::timestamp;
-- ALTER TABLE revisionwork DROP COLUMN endtime;
-- ALTER TABLE revisionwork RENAME COLUMN end_time_temp TO endtime;
+
UNIQUE (lane_id, host_id, revision_id)
);
@@ -299,6 +307,7 @@ CREATE INDEX RevisionWork_state_idx ON RevisionWork (state);
-- alter table RevisionWork drop constraint revisionwork_workhost_id_fkey;
-- alter table RevisionWork add constraint revisionwork_workhost_id_fkey foreign key (workhost_id) references host (id) on delete cascade;
-- alter table RevisionWork drop constraint revisionwork_workhost_id_fkey2;
+-- ALTER TABLE revisionwork ADD COLUMN priority integer DEFAULT 1 CHECK (priority >= 0), ALTER COLUMN priority SET NOT NULL;
CREATE TABLE Work (
id serial PRIMARY KEY,