/// <summary>
		/// 
		/// </summary>
		/// <param name="db"></param>
		/// <param name="lane"></param>
		/// <param name="host"></param>
		/// <param name="limit"></param>
		/// <param name="page">First page = 0, second page = 1, etc.</param>
		/// <returns></returns>
		public static List<DBRevisionWorkView> Query (DB db, DBLane lane, DBHost host, int limit, int page)
		{
			Console.WriteLine ("Query {0} {1} {2} {3}", lane, host, limit, page);
			List<DBRevisionWorkView> result = new List<DBRevisionWorkView> ();
			using (IDbTransaction transaction = db.BeginTransaction ()) {
				using (IDbCommand cmd = db.CreateCommand ()) {
					// copy&paste from CustomTypes.sql
					cmd.CommandText = @"
SELECT RevisionWork.id, Revision.revision 
	INTO TEMP revisionwork_temptable
	FROM RevisionWork 
	INNER JOIN Revision on RevisionWork.revision_id = Revision.id 
	WHERE RevisionWork.lane_id = @lane_id AND RevisionWork.host_id = @host_id
	ORDER BY Revision.date DESC LIMIT @limit OFFSET @offset;

-- For some reason postgresql thinks the temp table has 1230 entries, while it usually has about 20 entries,
-- and decides to do a sequential scan on the work tabe. Analyze it to make it realize its untrue presumptions.
ANALYZE revisionwork_temptable; 

	SELECT 
		Work.id, Work.command_id, Work.state, Work.starttime, Work.endtime, Work.duration, Work.logfile, Work.summary, 
		Host.host, 
		Lane.lane, 
		Revision.author, Revision.revision, 
		Command.command, 
		Command.nonfatal, Command.alwaysexecute, Command.sequence, Command.internal,
		RevisionWork.lane_id, RevisionWork.host_id, RevisionWork.revision_id, 
		RevisionWork.state AS revisionwork_state,
		WorkHost.host AS workhost
	FROM Work
	INNER JOIN RevisionWork ON Work.revisionwork_id = RevisionWork.id
	INNER JOIN Revision ON RevisionWork.revision_id = Revision.id 
	INNER JOIN Lane ON RevisionWork.lane_id = Lane.id 
	INNER JOIN Host ON RevisionWork.host_id = Host.id 
	LEFT JOIN Host AS WorkHost ON RevisionWork.workhost_id = WorkHost.id
	INNER JOIN Command ON Work.command_id = Command.id
	WHERE
		Work.revisionwork_id IN (SELECT id FROM revisionwork_temptable)
	ORDER BY Revision.date DESC; 
";

					DB.CreateParameter (cmd, "lane_id", lane.id);
					DB.CreateParameter (cmd, "host_id", host.id);
					DB.CreateParameter (cmd, "limit", limit);
					DB.CreateParameter (cmd, "offset", page * limit);

					using (IDataReader reader = cmd.ExecuteReader ()) {
						while (reader.Read ()) {
							result.Add (new DBRevisionWorkView (reader));
						}
					}
				}

				return result;
			}
		}
	public string GenerateHeader (GetViewWorkTableDataResponse response, DBLane lane, DBHost host, DBCommand command)
	{
		if (!Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) {
			return string.Format (@"
<h2>Step {4} on lane '{2}' on '{3}' (<a href='ViewTable.aspx?lane_id={0}&amp;host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, command.command);
		} else {
			return string.Format (@"
<h2>Step {4} on lane '<a href='EditLane.aspx?lane_id={0}'>{2}</a>' on '<a href='EditHost.aspx?host_id={1}'>{3}</a>' 
(<a href='ViewTable.aspx?lane_id={0}&amp;host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, command.command);
		}
	}
Example #3
0
		/// <summary>
		/// Returns true if something was added to the database.
		/// </summary>
		/// <param name="db"></param>
		/// <param name="lane"></param>
		/// <param name="host"></param>
		/// <returns></returns>
		public static bool AddRevisionWork (DB db, DBLane lane, DBHost host)
		{
			StringBuilder sql = new StringBuilder ();
			int line_count = 0;

			Logger.Log ("AddRevisionWork ({0} (id: {1}), {2} (id: {3}))", lane.lane, lane.id, host.host, host.id);

			try {
				using (IDbCommand cmd = db.CreateCommand ()) {
					cmd.CommandText = @"
SELECT Lane.id AS lid, Revision.id AS rid, Host.id AS hid
FROM Host, Lane
INNER JOIN Revision ON Revision.lane_id = lane.id
WHERE 
	Lane.id = @lane_id AND 
	Host.id = @host_id AND
	NOT EXISTS (
		SELECT 1
		FROM RevisionWork 
		WHERE RevisionWork.lane_id = Lane.id AND RevisionWork.host_id = Host.id AND RevisionWork.revision_id = Revision.id
		);
";
					DB.CreateParameter (cmd, "lane_id", lane.id);
					DB.CreateParameter (cmd, "host_id", host.id);
					using (IDataReader reader = cmd.ExecuteReader ()) {
						while (reader.Read ()) {
							int lane_id = reader.GetInt32 (reader.GetOrdinal ("lid"));
							int host_id = reader.GetInt32 (reader.GetOrdinal ("hid"));
							int revision_id = reader.GetInt32 (reader.GetOrdinal ("rid"));
							line_count++;
							sql.AppendFormat ("INSERT INTO RevisionWork (lane_id, host_id, revision_id) VALUES ({0}, {1}, {2});", lane_id, host_id, revision_id);
						}
					}
				}
				if (line_count > 0) {
					Logger.Log ("AddRevisionWork: Adding {0} records.", line_count);
					db.ExecuteScalar (sql.ToString ());
				} else {
					Logger.Log ("AddRevisionWork: Nothing to add.");
				}
				Logger.Log ("AddRevisionWork [Done]");
				return line_count > 0;
			} catch (Exception ex) {
				Logger.Log ("AddRevisionWork got an exception: {0}\n{1}", ex.Message, ex.StackTrace);
				return false;
			}
		}
Example #4
0
	string confirmViewLaneAction(DBLane lane, DBHost host, DBRevision dbr, string action, string command)
	{
		return String.Format("javascript:confirmViewLaneAction (\"ViewLane.aspx?lane_id={0}&amp;host_id={2}&amp;revision_id={1}&amp;action={3}\", \"{4}\");", lane.id, dbr.id, host.id, action, command);
	}
	public string GenerateHeader (GetViewTableDataResponse response, DBLane lane, DBHost host, bool horizontal)
	{
		string result;
		string format;
		string disabled_msg = string.Empty;

		if (!response.Enabled)
			disabled_msg = " (Disabled)";

		if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) {
			format = @"<h2>Build Matrix for <a href='EditLane.aspx?lane_id={0}'>'{2}'</a> on <a href='EditHost.aspx?host_id={5}'>'{4}'</a>{6}</h2><br/>";
		} else {
			format = @"<h2>Build Matrix for '{2}' on '{4}'{6}</h2><br/>";
		}

		format += @"<a href='ViewTable.aspx?lane_id={0}&amp;host_id={1}&amp;horizontal={3}'>Reverse x/y axis</a><br/>";
		if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator))
			format += string.Format (@"<a href='javascript:clearRevisions ({0}, {1})'>Clear selected revisions</a><br/>", lane.id, host.id);

		format += "<br/>";

		result = string.Format (format, lane.id, host.id, lane.lane, horizontal ? "false" : "true", host.host, host.id, disabled_msg);

		return result;
	}
		private List<DBMasterHost> FindMasterHosts (DB db, DBHost host)
		{
			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = "SELECT * FROM MasterHost WHERE host_id = @host_id";
				DB.CreateParameter (cmd, "host_id", host.id);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					return DBRecord.LoadMany<DBMasterHost> (reader);
				}
			}
		}
		public int AddHost (WebServiceLogin login, string host)
		{
			using (DB db = new DB ()) {
				VerifyUserInRole (db, login, Roles.Administrator);

				if (string.IsNullOrEmpty (host))
					throw new ArgumentNullException ("name");

				for (int i = 0; i < host.Length; i++) {
					if (char.IsLetterOrDigit (host [i])) {
						continue;
					} else if (host [i] == '-' || host [i] == '_') {
						continue;
					} else {
						throw new ArgumentOutOfRangeException (string.Format ("The character '{0}' isn't valid.", host [i]));
					}
				}

				DBHost dbhost = new DBHost ();
				dbhost.host = host;
				dbhost.enabled = true;
				dbhost.Save (db);
				return dbhost.id;
			}
		}
		public void EditHost (WebServiceLogin login, DBHost host)
		{
			//WebServiceResponse response = new WebServiceResponse ();
			using (DB db = new DB ()) {
				VerifyUserInRole (db, login, Roles.Administrator);

				var oldHost = FindHost (db, host.id, null);
				host.Save (db);

				Audit (login, "edited host `{0}` -> `{1}`",
					Newtonsoft.Json.JsonConvert.SerializeObject(oldHost),
					Newtonsoft.Json.JsonConvert.SerializeObject(host)
				);
			}
		}
Example #9
0
		private List<DBMasterHost> FindMasterHosts (DB db, DBHost host)
		{
			List<DBMasterHost> result = null;

			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = "SELECT * FROM MasterHost WHERE host_id = @host_id";
				DB.CreateParameter (cmd, "host_id", host.id);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					while (reader.Read ()) {
						if (result == null)
							result = new List<DBMasterHost> ();
						result.Add (new DBMasterHost (reader));
					}
				}
			}

			return result;
		}
Example #10
0
	public string GenerateLaneTable (GetViewTableDataResponse response, DBLane lane, DBHost host, bool horizontal, int page, int limit)
	{
		StringBuilder matrix = new StringBuilder ();
		DateTime beginning = new DateTime (2001, 1, 1, 0, 0, 0);
		bool new_revision = true;
		int revision_id = 0;
		int result_index;
		List<DBRevisionWorkView> views = response.RevisionWorkViews;
		List<List<string>> table = new List<List<string>> ();
		List<string> row = new List<string> ();
		List<string> header = new List<string> ();
		List<string> header_classes = new List<string> ();

		try {
			for (int i = 0; i < views.Count; i++) {
				while (header.Count <= views [i].sequence) {
					header.Add (null);
				}
				if (header [views [i].sequence] != null)
					continue;

				header [views [i].sequence] = string.Format ("<a href='ViewWorkTable.aspx?lane_id={0}&amp;host_id={1}&amp;command_id={2}'>{3}</a>", lane.id, host.id, views [i].command_id, views [i].command);
			}
			header.RemoveAll (delegate (string match) { return match == null; });
			header.Insert (0, "Revision");
			header.Insert (1, "Author");
			if (Utils.IsInRole (MonkeyWrench.DataClasses.Logic.Roles.Administrator))
				header.Insert (2, "Select");
			header.Add ("Host");
			header.Add ("Duration");
			result_index = Utils.IsInRole (MonkeyWrench.DataClasses.Logic.Roles.Administrator) ? 3 : 2;
			table.Add (header);

			bool failed = false;
			double duration = 0;

			for (int i = 0; i < views.Count; i++) {
				DBRevisionWorkView view = views [i];
				DBState revisionwork_state = (DBState) view.revisionwork_state;
				DBState state = (DBState) view.state;

				new_revision = revision_id != view.revision_id;
				revision_id = view.revision_id;

				if (new_revision) {
					if (i > 0) {
						// matrix.AppendLine ("</tr>");
						table.Add (row);
						row [row.Count - 1] = TimeSpan.FromSeconds (duration).ToString ();
					}

					string revision = view.revision;
					long dummy;
					if (revision.Length > 16 && !long.TryParse (revision, out dummy))
						revision = revision.Substring (0, 8);

					row = new List<string> ();
					row.Add (string.Format ("<a href='ViewLane.aspx?lane_id={0}&amp;host_id={1}&amp;revision_id={2}' title='{4}'>{3}</a></td>", lane.id, host.id, view.revision_id, revision, string.Format ("Author: {1} Build start date: {0}", view.starttime.ToUniversalTime ().ToString ("yyyy/MM/dd HH:mm:ss UTC"), view.author)));
					row.Add (string.Format ("<a href='GetRevisionLog.aspx?id={0}'>{1}</a></td>", view.revision_id, view.author));
					if (Utils.IsInRole (MonkeyWrench.DataClasses.Logic.Roles.Administrator))
						row.Add (string.Format ("<input type=checkbox id='id_revision_chk_{1}' name='revision_id_{0}' />", view.revision_id, i));
					while (row.Count < header.Count - 2)
						row.Add ("-");
					row.Add (view.workhost ?? "");
					row.Add ("");
					header_classes.Add (revisionwork_state.ToString ().ToLower ());
					failed = false;
					duration = 0;
				}

				if (view.endtime > view.starttime)
					duration += (view.endtime - view.starttime).TotalSeconds;

				if (state == DBState.Failed && !view.nonfatal)
					failed = true;

				// result
				string result;
				switch (state) {
				case DBState.NotDone:
					result = failed ? "skipped" : "queued"; break;
				case DBState.Executing:
					result = "running"; break;
				case DBState.Failed:
					result = view.nonfatal ? "issues" : "failure"; break;
				case DBState.Success:
					result = "success"; break;
				case DBState.Aborted:
					result = "aborted"; break;
				case DBState.Timeout:
					result = "timeout"; break;
				case DBState.Paused:
					result = "paused"; break;
				default:
					result = "unknown"; break;
				}

				for (int j = 2; j < header.Count; j++) {
					if (header [j].Contains (view.command)) {
						row [j] = result;
						break;
					}
				}
			}

			table.Add (row);
			row [row.Count - 1] = TimeSpan.FromSeconds (duration).ToString ();

			matrix.AppendLine ("<table class='buildstatus'>");
			if (horizontal) {
				for (int i = 0; i < header.Count; i++) {
					matrix.Append ("<tr>");
					for (int j = 0; j < table.Count; j++) {
						string td = j == 0 ? "th" : "td";
						if ((i == 0 || i == row.Count - 1) && j > 0) {
							if (i == row.Count - 1) {
								matrix.AppendFormat ("<{0} class='{1}' style='white-space: nowrap;'>", td, header_classes [j - 1]);
							} else {
								matrix.AppendFormat ("<{0} class='{1}'>", td, header_classes [j - 1]);
							}
						} else if (i >= result_index && j > 1) {
							matrix.AppendFormat ("<{0} class='{1}'>", td, table [j] [i]);
						} else {
							matrix.AppendFormat ("<{0}>", td);
						}
						matrix.AppendFormat (table [j] [i]);
						matrix.AppendFormat ("</{0}>", td);
					}
					matrix.AppendLine ("</tr>");
				}
			} else {
				for (int i = 0; i < table.Count; i++) {
					row = table [i];
					matrix.Append ("<tr>\n");
					for (int j = 0; j < row.Count; j++) {
						string td = j == 0 ? "th" : "td";
						if ((j == 0 || j == row.Count - 1) & i > 0) {
							if (j == row.Count - 1) {
								matrix.AppendFormat ("\t<{0} class='{1}' style='white-space: nowrap;'>", td, header_classes [i - 1]);
							} else {
								matrix.AppendFormat ("\t<{0} class='{1}'>", td, header_classes [i - 1]);
							}
						} else if (j >= result_index && row [j] != "-" && i > 0) {
							matrix.AppendFormat ("\t<{0} class='{1}'>", td, row [j]);
						} else {
							matrix.AppendFormat ("\t<{0}>", td);
						}
						matrix.AppendFormat (row [j]);
						matrix.AppendFormat ("</{0}>\n", td);
					}
					matrix.AppendLine ("</tr>");
				}
			}
			matrix.AppendLine ("</table>");

		} catch (Exception ex) {
			matrix.Append (ex.ToString ().Replace ("\n", "</br>"));
		}
		return matrix.ToString ();
	}
Example #11
0
	public string GenerateLane (GetViewWorkTableDataResponse response, DBLane lane, DBHost host, DBCommand command)
	{
		StringBuilder matrix = new StringBuilder ();
		List<DBWorkView2> steps;

		steps = response.WorkViews;

		matrix.AppendLine ("<table class='buildstatus'>");
		matrix.AppendLine ("<tr>");
		matrix.AppendLine ("\t<th>Revision</th>");
		matrix.AppendLine ("\t<th>Start Time</th>");
		matrix.AppendLine ("\t<th>Duration</th>");;
		matrix.AppendLine ("\t<th>Html report</th>");
		matrix.AppendLine ("\t<th>Summary</th>");
		matrix.AppendLine ("\t<th>Files</th>");
		matrix.AppendLine ("</tr>");


		for (int i = 0; i < steps.Count; i++) {
			DBWorkView2 view = steps [i];
			List<DBWorkFileView> files = response.WorkFileViews [i];
			DBState state = (DBState) view.state;

			matrix.Append ("<tr>");

			// revision
			string result;
			switch (state) {
			case DBState.NotDone:
				result = "queued"; break;
			case DBState.Executing:
				result = "running"; break;
			case DBState.Failed:
				result = view.nonfatal ? "issues" : "failure"; break;
			case DBState.Success:
			case DBState.Aborted:
			case DBState.Timeout:
			case DBState.Paused:
			default:
				result =state.ToString ().ToLowerInvariant ();
				break;
			}

			// result

			matrix.AppendFormat ("\t<td class='{0}'><a href='ViewLane.aspx?lane_id={2}&host_id={3}&revision_id={4}'>{1}</a></td>", result, view.revision, lane.id, host.id, view.revision_id);

			if (state > DBState.NotDone && state != DBState.Paused && state != DBState.Ignore) {
				matrix.AppendFormat ("<td>{0}</td>", view.starttime.ToString ("yyyy/MM/dd HH:mm:ss UTC"));
			} else {
				matrix.AppendLine ("<td>-</td>");
			}
			// duration
			matrix.Append ("\t<td>");
			if (state >= DBState.Executing && state != DBState.Paused && state != DBState.Ignore) {
				matrix.Append ("[");
				matrix.Append (MonkeyWrench.Utilities.GetDurationFromWorkView (view).ToString ());
				matrix.Append ("]");
			} else {
				matrix.Append ("-");
			}
			matrix.AppendLine ("</td>");

			// html report
			matrix.AppendLine ("<td>");
			DBWorkFileView index_html = null;
			foreach (DBWorkFileView file in files) {
				if (file.filename == "index.html") {
					index_html = file;
					break;
				}
			}
			if (index_html != null) {
				matrix.AppendFormat ("<a href='ViewHtmlReport.aspx?workfile_id={0}'>View html report</a>", index_html.id);
			} else {
				matrix.AppendLine ("-");
			}
			matrix.AppendLine ("</td>");

			// summary
			matrix.AppendLine ("<td>");
			matrix.AppendLine (view.summary);
			matrix.AppendLine ("</td>");


			matrix.AppendLine ("</tr>");
		}
		
		matrix.AppendLine ("</table>");
		
		return matrix.ToString ();
	}
		private Dictionary<String, Object> BuildStatusFrom(int laneId, int revId, DBRevisionWork work, DBHost host)
		{
			if (host == null)
				throw new HttpException(404, "Build has not been assigned yet, cannot generate status.");
			var buildView = Utils.LocalWebService.GetViewLaneData (login, laneId, "", host.id, "", revId, "");

			var steps = new List<Dictionary<String, Object>>();
			for (int sidx = 0; sidx < buildView.WorkViews.Count; sidx++) {
				var step = buildView.WorkViews [sidx];
				var files = buildView.WorkFileViews [sidx];
				var links = buildView.Links.Where (l => l.work_id == step.id);
				steps.Add (BuildStepStatus (sidx, step, files, links));
			}

			return new Dictionary<String, Object> {
				{ "build_host", buildView.WorkHost.host },
				{ "build_host_id", buildView.WorkHost.id },
				{ "branch", MaxRevisionToBranch (buildView.Lane.max_revision) },
				{ "commit", buildView.Revision.revision },
				{ "completed", buildView.RevisionWork.completed },
				{ "end_time", work.endtime },
				{ "host", host.host },
				{ "host_id", host.id },
				{ "lane_id", laneId },
				{ "lane_name", buildView.Lane.lane },
				{ "revision_id", revId },
				{ "repository", buildView.Lane.repository },
				{ "start_time", buildView.WorkViews [0].starttime },
				{ "status", work.State.ToString ().ToLowerInvariant () },
				{ "steps", steps },
				{ "url", BuildLink (laneId, revId, host.id) }
			};
		}
Example #13
0
	void GenerateActionLink(StringBuilder header, DBLane lane, DBHost host, DBRevision dbr, string cmd, string short_label, string long_label, bool hidden = false)
	{
		var href = confirmViewLaneAction(lane, host, dbr, cmd, short_label);
		if (hidden)
			header.AppendFormat("- <a style='{0}' href='{1}'>{2}</a>", "display:none", href, long_label);
		else
			header.AppendFormat("- <a href='{0}'>{1}</a>", href, long_label);
	}
Example #14
0
		public void EditHost (WebServiceLogin login, DBHost host)
		{
			//WebServiceResponse response = new WebServiceResponse ();
			using (DB db = new DB ()) {
				VerifyUserInRole (db, login, Roles.Administrator);
				host.Save (db);
			}
		}
		/// <summary>
		/// Sets workhost to the specified host and saves it to the db.
		/// </summary>
		/// <param name="db"></param>
		/// <param name="host"></param>
		public static bool SetWorkHost (this DBRevisionWork rw, DB db, DBHost host)
		{
			object result;
			string update_cmd = string.Format (@"UPDATE RevisionWork SET workhost_id = {0} WHERE id = {1} AND workhost_id IS NULL;", host.id, rw.id);

			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = update_cmd;

				var rv = cmd.ExecuteNonQuery ();

				if (rv != 1) {
					Logger.Log ("{0}: {1} (failed)", cmd.CommandText, rv);
					return false;
				}
			}

			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = @"
SELECT workhost_id FROM RevisionWork where id = @id AND workhost_id = @workhost_id;
";
				DB.CreateParameter (cmd, "workhost_id", host.id);
				DB.CreateParameter (cmd, "id", rw.id);

				result = cmd.ExecuteScalar ();
				if (result != null && (result is int || result is long)) {
					rw.workhost_id = host.id;
					Logger.Log ("{0}: {1} (succeeded)", update_cmd, result);
					return true;
				}
				Logger.Log ("{0}: {1} (failed 2)", update_cmd, result);
				return false;
			}
		}
Example #16
0
		private List<DBHost> GetSlaveHosts (DB db, DBHost host)
		{
			List<DBHost> result = null;

			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = "SELECT Host.* FROM Host INNER JOIN MasterHost ON MasterHost.host_id = Host.id WHERE MasterHost.master_host_id = @host_id";
				DB.CreateParameter (cmd, "host_id", host.id);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					while (reader.Read ()) {
						if (result == null)
							result = new List<DBHost> ();
						result.Add (new DBHost (reader));
					}
				}
			}

			return result;
		}
Example #17
0
		/// <summary>
		/// Will return a locked revision work.
		/// </summary>
		/// <param name="lane"></param>
		/// <param name="host"></param>
		/// <returns></returns>
		public DBRevisionWork GetRevisionWork (DBLane lane, DBHost host, DBHost workhost)
		{
			DBRevisionWork result = null;

			using (IDbCommand cmd = CreateCommand ()) {
				// sorting by RevisionWork.workhost_id ensures that we'll get 
				// revisionwork which has been started at the top of the list.
				cmd.CommandText = @"
SELECT 
	RevisionWork.*
FROM 
	RevisionWork
INNER JOIN 
	Revision ON RevisionWork.revision_id = Revision.id
WHERE 
        RevisionWork.host_id = @host_id 
	AND (RevisionWork.workhost_id = @workhost_id OR RevisionWork.workhost_id IS NULL)
	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
LIMIT 1
;";
				DB.CreateParameter (cmd, "host_id", host.id);
				DB.CreateParameter (cmd, "lane_id", lane.id);
				DB.CreateParameter (cmd, "workhost_id", workhost.id);
				DB.CreateParameter (cmd, "dependencynotfulfilled", (int) DBState.DependencyNotFulfilled);
				DB.CreateParameter (cmd, "ignore", (int) DBState.Ignore);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					if (reader.Read ())
						result = new DBRevisionWork (reader);
				}
			}

			return result;
		}
Example #18
0
	public static string GenerateHeader (GetViewLaneDataResponse response, DBLane lane, DBHost host, DBRevision revision, string description)
	{
		if (!Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) {
			return string.Format (@"
<h2>{4} revision <a href='ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={6}'>{5}</a> on lane '{2}' on '<a href='ViewHostHistory.aspx?host_id={1}'>{3}</a>' 
(<a href='ViewTable.aspx?lane_id={0}&amp;host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, description, revision.revision, revision.id);
		} else {
			return string.Format (@"
<h2>{4} revision <a href='ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={6}'>{5}</a> on lane '<a href='EditLane.aspx?lane_id={0}'>{2}</a>' on '<a href='ViewHostHistory.aspx?host_id={1}'>{3}</a>' 
(<a href='ViewTable.aspx?lane_id={0}&amp;host_id={1}'>table</a>)</h2><br/>", lane.id, host.id, lane.lane, host.host, description, revision.revision, revision.id);
		}
	}
Example #19
0
		public DBHost LookupHost (string host, bool throwOnError)
		{
			DBHost result = null;
			using (IDbCommand cmd = CreateCommand ()) {
				cmd.CommandText = "SELECT * FROM Host WHERE host = @host";
				DB.CreateParameter (cmd, "host", host);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					if (!reader.Read ()) {
						if (!throwOnError)
							return null;
						throw new Exception (string.Format ("Could not find the host '{0}'.", host));
					}
					result = new DBHost (reader);
					if (reader.Read ()) {
						if (!throwOnError)
							return null;
						throw new Exception (string.Format ("Found more than one host named '{0}'.", host));
					}
				}
			}
			return result;
		}
		public void EditHostWithPassword (WebServiceLogin login, DBHost host, string password)
		{
			using (DB db = new DB ()) {
				using (IDbTransaction transaction = db.BeginTransaction ()) {
					VerifyUserInRole (db, login, Roles.Administrator);

					var oldHost = FindHost (db, host.id, null);
					host.Save (db);

					// NOTE: it is possible to change the password of an existing account by creating 
					// a host with the same name and specify the password. Given that admin rights
					// are required to create/modify hosts, it shouldn't pose a security issue.

					// TODO: if host changed name, delete the old user account.
					DBPerson person = FindPerson (db, host.host);

					if (person == null) {
						person = new DBPerson ();
						person.login = host.host;
						person.roles = Roles.BuildBot;
					} else {
						if (person.roles != Roles.BuildBot)
							throw new ArgumentException ("The hosts entry in the person table must have its roles set to 'BuildBot'.");
					}
					person.password = password;
					person.Save (db);
					transaction.Commit ();

					Audit (login, "edited host `{0}` -> `{1}`",
						Newtonsoft.Json.JsonConvert.SerializeObject(oldHost),
						Newtonsoft.Json.JsonConvert.SerializeObject(host)
					);
				}
			}
		}
		/// <summary>
		/// Finds pending steps for the current revision
		/// </summary>
		/// <returns></returns>
		public static List<DBWorkView2> GetNextWork (this DBRevisionWork rw, DB db, DBLane lane, DBHost host, DBRevision revision, bool multiple_work)
		{
			List<DBWorkView2> result = new List<DBWorkView2> (); ;

			if (revision == null)
				throw new ArgumentNullException ("revision");

			if (lane == null)
				throw new ArgumentNullException ("lane");

			if (host == null)
				throw new ArgumentNullException ("host");

			rw.FilterPendingWork (db, db.GetWork (rw), result, multiple_work);

			if (result.Count == 0 && !rw.completed) {
				rw.completed = true;
				rw.UpdateState (db);
			}

			return result;
		}
		private List<DBHost> GetMasterHosts (DB db, DBHost host)
		{
			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = "SELECT Host.* FROM Host INNER JOIN MasterHost ON MasterHost.master_host_id = Host.id WHERE MasterHost.host_id = @host_id";
				DB.CreateParameter (cmd, "host_id", host.id);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					return DBRecord.LoadMany<DBHost> (reader);
				}
			}
		}
		public static DBRevisionWork Find (DB db, DBLane lane, DBHost host, DBRevision revision)
		{
			DBRevisionWork result;

			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = "SELECT * FROM RevisionWork WHERE lane_id = @lane_id AND revision_id = @revision_id ";
				if (host != null) {
					cmd.CommandText += " AND host_id = @host_id;";
					DB.CreateParameter (cmd, "host_id", host.id);
				}
				DB.CreateParameter (cmd, "lane_id", lane.id);
				DB.CreateParameter (cmd, "revision_id", revision.id);
				using (IDataReader reader = cmd.ExecuteReader ()) {
					if (!reader.Read ())
						return null;

					result = new DBRevisionWork (reader);

					if (reader.Read ())
						throw new ApplicationException (string.Format ("Found more than one revision work for the specified lane/host/revision ({0}/{1}/{2})", lane.lane, host == null ? "null" : host.host, revision.revision));

					return result;
				}
			}
		}
	public string GeneratePager (GetViewTableDataResponse response, DBLane lane, DBHost host, int page, int limit)
	{
		StringBuilder pager = new StringBuilder ();
		int total = response.Count;
		int pages = total / limit;

		if (total % limit != 0)
			pages++;
		Console.WriteLine ("Pages: {0} total: {1}", pages, total);

		if (page > pages - 1)
			page = pages - 1;

		int range = 5;
		pager.AppendFormat ("<p> Page&nbsp;");
		if (pages < (range * 2)) {
			for (int i = 0; i < pages; i++) {
				pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit));
			}
		} else {
			if (page <= (range + 1)) {
				for (int i = 0; i < (page + range); i++) {
					if (page == i)
						pager.Append (string.Format ("<b>{0}</b>", i + 1));
					else
						pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit));
				}
				pager.AppendFormat ("...");
				pager.Append (GeneratePageLink (host.id, lane.id, pages - 2, limit));
				pager.Append (GeneratePageLink (host.id, lane.id, pages - 1, limit));
			} else if (page > (pages - range - 4)) {
				pager.Append (GeneratePageLink (host.id, lane.id, 1, limit));
				pager.Append (GeneratePageLink (host.id, lane.id, 2, limit));
				pager.AppendFormat ("...");
				for (int i = page - range; i < pages; i++) {
					if (page == i)
						pager.Append (string.Format ("<b>{0}</b>", i + 1));
					else
						pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit));
				}
			} else {
				pager.Append (GeneratePageLink (host.id, lane.id, 1, limit));
				pager.Append (GeneratePageLink (host.id, lane.id, 2, limit));
				pager.AppendFormat ("...");
				for (int i = page - range; i < page + range; i++) {
					if (page == i)
						pager.Append (string.Format ("<b>{0}</b>", i + 1));
					else
						pager.Append (GeneratePageLink (host.id, lane.id, i + 1, limit));
				}
				pager.AppendFormat ("...");
				pager.Append (GeneratePageLink (host.id, lane.id, pages - 2, limit));
				pager.Append (GeneratePageLink (host.id, lane.id, pages - 1, limit));
			}
		}
		pager.AppendFormat ("</p>");
		return pager.ToString ();
	}
		/// <summary>
		/// Sets workhost to the specified host and saves it to the db.
		/// </summary>
		/// <param name="db"></param>
		/// <param name="host"></param>
		public static bool SetWorkHost (this DBRevisionWork rw, DB db, DBHost host)
		{
			object result;
			using (IDbCommand cmd = db.CreateCommand ()) {
				cmd.CommandText = @"
UPDATE RevisionWork SET workhost_id = @workhost_id WHERE id = @id AND workhost_id IS NULL;
SELECT workhost_id FROM RevisionWork where id = @id AND workhost_id = @workhost_id;
";
				DB.CreateParameter (cmd, "workhost_id", host.id);
				DB.CreateParameter (cmd, "id", rw.id);

				result = cmd.ExecuteScalar ();
				if (result != null && (result is int || result is long)) {
					rw.workhost_id = host.id;
					return true;
				}
				return false;
			}
		}
	public string GenerateLaneTable (GetViewTableDataResponse response, DBLane lane, DBHost host, bool horizontal, int page, int limit)
	{
		StringBuilder matrix = new StringBuilder ();
		StringBuilder tooltip = new StringBuilder ();
		bool new_revision = true;
		int revision_id = 0;
		List<DBRevisionWorkView> views = response.RevisionWorkViews;
		List<List<TableNode>> table = new List<List<TableNode>> ();
		List<TableNode> row = new List<TableNode> ();
		List<TableNode> header = new List<TableNode> ();

		for (int i = 0; i < views.Count; i++) {
			while (header.Count <= views [i].sequence) {
				header.Add (null);
			}
			if (header [views [i].sequence] != null)
				continue;

			var node = new TableNode (string.Format ("<a href='ViewWorkTable.aspx?lane_id={0}&amp;host_id={1}&amp;command_id={2}'>{3}</a>", lane.id, host.id, views [i].command_id, views [i].command));
			node.command_id = views [i].command_id;
			header [views [i].sequence] = node;
		}
		header.RemoveAll (delegate (TableNode match) { return match == null; });
		header.Insert (0, new TableNode ("Revision", true));
		header.Insert (1, new TableNode ("Diff", true));
		header.Insert (2, new TableNode ("Author", true));
		//if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator)) {
		//    header.Insert (3, new TableNode ("Select", true));
		//}
		header.Add (new TableNode ("Host", true));
		header.Add (new TableNode ("Duration", true));
		table.Add (header);

		bool failed = false;
		double duration = 0;

		for (int i = 0; i < views.Count; i++) {
			DBRevisionWorkView view = views [i];
			DBState revisionwork_state = (DBState) view.revisionwork_state;
			DBState state = (DBState) view.state;

			new_revision = revision_id != view.revision_id;
			revision_id = view.revision_id;

			if (new_revision) {
				if (i > 0) {
					table.Add (row);
					row [row.Count - 1] = new TableNode (TimeSpan.FromSeconds (duration).ToString (), row [0].@class);
				}

				string revision = view.revision;
				long dummy;
				if (revision.Length > 16 && !long.TryParse (revision, out dummy))
					revision = revision.Substring (0, 8);

				string clazz = revisionwork_state.ToString ().ToLower ();
				clazz = clazz + " " + DarkenColor (clazz, table.Count);
				row = new List<TableNode> ();

				tooltip.Length = 0;
				tooltip.AppendFormat ("Author: {0}.", view.author);
				if (view.starttime.Date.Year > 2000)
					tooltip.AppendFormat (" Build start date: {0}.", view.starttime.ToUniversalTime ().ToString ("yyyy/MM/dd HH:mm:ss UTC"));

				row.Add (new TableNode (string.Format ("<a href='ViewLane.aspx?lane_id={0}&amp;host_id={1}&amp;revision_id={2}' title='{4}'>{3}</a>", lane.id, host.id, view.revision_id, revision, tooltip.ToString ()), clazz));
				row.Add (new TableNode (string.Format ("<a href='GetRevisionLog.aspx?id={0}'>diff</a>", view.revision_id)));
				row.Add (new TableNode (view.author));
				
				//if (Authentication.IsInRole (response, MonkeyWrench.DataClasses.Logic.Roles.Administrator))
				//    row.Add (new TableNode (string.Format ("<input type=checkbox id='id_revision_chk_{1}' name='revision_id_{0}' />", view.revision_id, i)));
				while (row.Count < header.Count - 2)
					row.Add (new TableNode ("-"));
				row.Add (new TableNode (view.workhost ?? ""));
				row.Add (new TableNode (""));
				failed = false;
				duration = 0;
			}

			if (view.endtime > view.starttime)
				duration += (view.endtime - view.starttime).TotalSeconds;

			if (state == DBState.Failed && !view.nonfatal)
				failed = true;
			else if (revisionwork_state == DBState.Failed)
				failed = true;

			// result
			string result;
			bool completed = true;
			switch (state) {
			case DBState.NotDone:
				completed = false;
				result = failed ? "skipped" : "queued"; break;
			case DBState.Executing:
				completed = false;
				result = "running"; break;
			case DBState.Failed:
				result = view.nonfatal ? "issues" : "failure"; break;
			case DBState.Success:
				result = "success"; break;
			case DBState.Aborted:
				result = "aborted"; break;
			case DBState.Timeout:
				result = "timeout"; break;
			case DBState.Paused:
				completed = false;
				result = "paused"; break;
			case DBState.Ignore:
				completed = false;
				result = "ignore"; break;
			default:
				completed = true;
				result = "unknown"; break;
			}

			for (int j = 2; j < header.Count; j++) {
				if (header [j].command_id == view.command_id) {
					if (completed) {
						row [j] = new TableNode (string.Format ("<a href='{0}'>{1}</a>", Utilities.CreateWebServiceDownloadUrl (Request, view.id, view.command + ".log", true), result));
					} else {
						row [j] = new TableNode (result);
					}
					row [j].@class = result + " " + DarkenColor (result, table.Count);
					break;
				}
			}
		}

		table.Add (row);
		row [row.Count - 1] = new TableNode (TimeSpan.FromSeconds (duration).ToString (), row [0].@class);

		matrix.AppendLine ("<table class='buildstatus'>");
		if (horizontal) {
			for (int i = 0; i < header.Count; i++) {
				matrix.Append ("<tr>");
				for (int j = 0; j < table.Count; j++) {
					TableNode node = table [j] [i];
					string td = node.is_header ? "th" : "td";
					matrix.Append ('<');
					matrix.Append (td);
					if (node.@class != null) {
						matrix.Append (" class='");
						matrix.Append (node.@class);
						matrix.Append ("'");
					}
					/*
					if (node.style != null) {
						matrix.Append (" style='");
						matrix.Append (node.style);
						matrix.Append ("'");
					}*/
					matrix.Append (">");
					matrix.Append (node.text);
					matrix.Append ("</");
					matrix.Append (td);
					matrix.Append (">");
				}
				matrix.AppendLine ("</tr>");
			}
		} else {
			for (int i = 0; i < table.Count; i++) {
				matrix.Append ("<tr>");
				for (int j = 0; j < row.Count; j++) {
					TableNode node = table [i] [j];
					string td = node.is_header ? "th" : "td";
					matrix.Append ('<');
					matrix.Append (td);
					if (node.@class != null) {
						matrix.Append (" class='");
						matrix.Append (node.@class);
						matrix.Append ("'");
					}
					/*
					if (node.style != null) {
						matrix.Append (" style='");
						matrix.Append (node.style);
						matrix.Append ("'");
					}*/
					matrix.Append (">");
					matrix.Append (node.text);
					matrix.Append ("</");
					matrix.Append (td);
					matrix.Append (">");
				}
				matrix.AppendLine ("</tr>");
			}
		}
		matrix.AppendLine ("</table>");
		return matrix.ToString ();
	}
	public string GenerateLane (GetViewWorkTableDataResponse response, DBLane lane, DBHost host, DBCommand command)
	{
		StringBuilder matrix = new StringBuilder ();
		List<DBWorkView2> steps;
		DateTime beginning = new DateTime (2001, 1, 1, 0, 0, 0);

		steps = response.WorkViews;

		matrix.AppendLine ("<table class='buildstatus'>");
		matrix.AppendLine ("<tr>");
		matrix.AppendLine ("\t<th>Revision</th>");
		matrix.AppendLine ("\t<th>Start Time</th>");
		matrix.AppendLine ("\t<th>Duration</th>");;
		matrix.AppendLine ("\t<th>Html report</th>");
		matrix.AppendLine ("\t<th>Summary</th>");
		matrix.AppendLine ("\t<th>Files</th>");
		matrix.AppendLine ("</tr>");


		for (int i = 0; i < steps.Count; i++) {
			DBWorkView2 view = steps [i];
			List<DBWorkFileView> files = response.WorkFileViews [i];
			DBState state = (DBState) view.state;

			matrix.Append ("<tr>");

			// revision
			string result;
			switch (state) {
			case DBState.NotDone:
				result = "queued"; break;
			case DBState.Executing:
				result = "running"; break;
			case DBState.Failed:
				result = view.nonfatal ? "issues" : "failure"; break;
			case DBState.Success:
			case DBState.Aborted:
			case DBState.Timeout:
			case DBState.Paused:
			default:
				result =state.ToString ().ToLowerInvariant ();
				break;
			}

			// result

			int file_id = 0;
			foreach (DBWorkFileView file in files) {
				if (!file.filename.StartsWith (view.command))
					continue;
				file_id = file.id;
				break;
			}
			if (file_id == 0) {
				matrix.AppendFormat ("\t<td class='{0}'>{1}</td>", result, view.revision);
			} else {
				matrix.AppendFormat ("\t<td class='{0}'><a href='GetFile.aspx?id={2}'>{1}</a></td>", result, view.revision, file_id);
			}

			if (state > DBState.NotDone && state != DBState.Paused) {
				matrix.AppendFormat ("<td>{0}</td>", view.starttime.ToString ("yyyy/MM/dd HH:mm:ss UTC"));
			} else {
				matrix.AppendLine ("<td>-</td>");
			}
			// duration
			DateTime starttime = view.starttime.ToLocalTime ();
			DateTime endtime = view.endtime.ToLocalTime ();
			int duration = (int) (endtime - starttime).TotalSeconds;
			matrix.Append ("\t<td>");
			if (state >= DBState.Executing && state != DBState.Paused) {
				matrix.Append ("[");
				matrix.Append (TimeSpan.FromSeconds (duration).ToString ());
				matrix.Append ("]");
			} else {
				matrix.Append ("-");
			}
			matrix.AppendLine ("</td>");

			// html report
			matrix.AppendLine ("<td>");
			DBWorkFileView index_html = null;
			foreach (DBWorkFileView file in files) {
				if (file.filename == "index.html") {
					index_html = file;
					break;
				}
			}
			if (index_html != null) {
				matrix.AppendFormat ("<a href='ViewHtmlReport.aspx?workfile_id={0}'>View html report</a>", index_html.id);
			} else {
				matrix.AppendLine ("-");
			}
			matrix.AppendLine ("</td>");

			// summary
			matrix.AppendLine ("<td>");
			matrix.AppendLine (view.summary);
			matrix.AppendLine ("</td>");


			matrix.AppendLine ("</tr>");
		}
		
		matrix.AppendLine ("</table>");
		
		return matrix.ToString ();
	}