/// <summary> /// Search through the list of imaging tasks and set an appropriate value of /// InQueue. This implementation sets InQueue to false for all tasks with /// state unsuitable for queuing and all tasks before DateTime.Now except /// the one with the latest IImagingTask.DateToImage before DateTime.Now. /// </summary> /// <param name="tasks">The array of IImagingTasks to process. Assumes that the tasks /// are actually the fully editable OPPF implementation of IImagingTask</param> private void setInQueue(IImagingTask[] iImagingTasks) { // Do nothing if tasks is null if (null == iImagingTasks) { return; } // Find latest task before or at now DateTime now = DateTime.Now; IImagingTask latestBeforeNow = null; for (int i = 0; i < iImagingTasks.GetLength(0); i++) { if (1 > iImagingTasks[i].DateToImage.CompareTo(now)) { if (null == latestBeforeNow) { latestBeforeNow = iImagingTasks[i]; } else if (1 == iImagingTasks[i].DateToImage.CompareTo(latestBeforeNow.DateToImage)) { latestBeforeNow = iImagingTasks[i]; } } } // Set inQueue for all unqueuable or before latestBeforeNow to false, otherwise true if (null != latestBeforeNow) { for (int i = 0; i < iImagingTasks.GetLength(0); i++) { if (isStateUnqueuable(iImagingTasks[i].State) || (-1 == iImagingTasks[i].DateToImage.CompareTo(latestBeforeNow.DateToImage))) { ((global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask)iImagingTasks[i]).SetInQueue(false); } else { ((global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask)iImagingTasks[i]).SetInQueue(true); } } } }
/// <summary> /// Returns all scheduled <c>IImagingTask</c>s for the <c>plateID</c>. /// </summary> public IImagingTask[] GetImagingTasks(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID) { // Check arguments - do it up front to avoid possible inconsistencies later if (null == robot) { throw new System.NullReferenceException("robot must not be null"); } if (null == plateID) { throw new System.NullReferenceException("plateID must not be null"); } // Log the call to the method if (_log.IsDebugEnabled) { string msg = "Called " + this + ".GetImagingTasks(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\")"; _log.Debug(msg); } // Declare the array that will be populated and returned - default to a zero-length array IImagingTask[] iImagingTasks = new IImagingTask[0]; // Bail out on test plates if ("ReliabilityTestPlate".Equals(plateID) || "ReservedSlot".Equals(plateID)) { return(iImagingTasks); } // Ensure connected to database - may throw an exception but we don't need/want to catch it if ((null == _dbConnection) || (System.Data.ConnectionState.Closed.Equals(_dbConnection.State))) { //connectToDB(); } // Try and read the imaging tasks from the db OdbcDataReader dataReader = null; try { // TODO - unnecessary check? Can connectToDB fail without throwing an exception? if (System.Data.ConnectionState.Open.Equals(_dbConnection.State)) { // Update the parameters _command.Parameters["@p1"].Value = plateID; // If we care which imager if (2 == _command.Parameters.Count) { _command.Parameters["@p2"].Value = robot.Name; } // Execute the select dataReader = _command.ExecuteReader(); // Read the data reader's rows into the ProjectList if (dataReader.HasRows) { // Get an ArrayList to hold the tasks System.Collections.ArrayList tasks = new System.Collections.ArrayList(); // Loop over all the returned rows while (dataReader.Read()) { // Create and populate a new ImagingTask global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask task = new global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask(); // .NET < 2.0 //task.DateToImage = dataReader.GetDateTime(0); // .NET >= 2.0 Only! task.SetDateToImage(DateTime.SpecifyKind(dataReader.GetDateTime(0), DateTimeKind.Utc)); if (dataReader.IsDBNull(1)) { task.SetDateImaged(DateTime.MinValue); } else { // .NET < 2.0 //task.DateImaged = dataReader.GetDateTime(1); // .NET >= 2.0 Only! task.SetDateImaged(DateTime.SpecifyKind(dataReader.GetDateTime(1), DateTimeKind.Utc)); //task.DateImaged = dataReader.GetDateTime(1).ToLocalTime(); } if (dataReader.IsDBNull(2)) { _log.Warn("Got null priority for plateID: " + plateID + " task: " + task.DateToImage.ToLongTimeString()); task.SetPriority(5); } else { task.SetPriority(dataReader.GetInt32(2)); } if (dataReader.IsDBNull(3)) { _log.Warn("Got null state for plateID: " + plateID + " task: " + task.DateToImage.ToLongTimeString()); if (dataReader.IsDBNull(1)) { task.SetState(Formulatrix.Integrations.ImagerLink.Scheduling.ImagingState.NotCompleted); } else { task.SetState(Formulatrix.Integrations.ImagerLink.Scheduling.ImagingState.Completed); } } else { task.SetState((Formulatrix.Integrations.ImagerLink.Scheduling.ImagingState)dataReader.GetInt32(3)); } task.SetInQueue(true); // Store this task in the ArrayList tasks.Add(task); //_log.Debug("> Got task: DateToImage=" + task.DateToImage + ", Priority=" + task.Priority + ", State=" + task.State + ", InQueue= " + task.InQueue); } // Convert ArrayList to IImagingTask[] iImagingTasks = (IImagingTask[])tasks.ToArray(typeof(IImagingTask)); } // Close the dataReader dataReader.Close(); } } catch (Exception e) { // Log it string msg = "Exception " + e.Message + " during direct db part of getImagingTasks() for plate " + plateID + " - will fail down to webservice call"; _log.Error(msg, e); try { // Clean up the dataReader if ((null != dataReader) && (!dataReader.IsClosed)) { dataReader.Close(); } dataReader = null; if (null != _dbConnection) { _dbConnection.Close(); } } catch (Exception e1) { // Log it string msg1 = "Exception " + e1.Message + " while handling exception during direct db part of direct db part of getImagingTasks() for plate " + plateID + " - will fail down to webservice call"; _log.Error(msg1, e1); } // Don't rethrow - fail down to webservice call } // If we got no or not enough tasks if ((null == iImagingTasks) || (iImagingTasks.GetLength(0) < MIN_IMAGING_TASKS)) { // Hit the webservice, which may cause a schedule to be created iImagingTasks = GetImagingTasksFromWebService(robot, plateID); } // Set an appropriate value for InQueue setInQueue(iImagingTasks); // Ensure we never return null if (null == iImagingTasks) { // Fix it iImagingTasks = new IImagingTask[0]; // Log it _log.Warn("Fixed null iImagingTasks at end of WSPlate.getImagingTasks() for plate " + plateID); } // Return the array of IImagingTasks return(iImagingTasks); }
/// <summary> /// Web service version of GetImagingTasks - useful because it will /// cause a full schedule to be written if one doesn't already /// exist. /// /// Warning - this is a lot slower than going straight to platedb! /// </summary> /// <param name="robot">The robot</param> /// <param name="plateID">The barcode of the plate</param> /// <returns></returns> public IImagingTask[] GetImagingTasksFromWebService(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID) { // Check arguments - do it up front to avoid possible inconsistencies later if (null == robot) { throw new System.NullReferenceException("robot must not be null"); } if (null == plateID) { throw new System.NullReferenceException("plateID must not be null"); } // Log the call if (_log.IsInfoEnabled) { string msg = "Calling WSPlate.getImagingTasks() for plate " + plateID + ", robot " + RobotUtils.iRobotToString(robot); _log.Info(msg); } // Declare the array that will be populated and returned // - default to a zero-length array IImagingTask[] iImagingTasks = new IImagingTask[0]; // Set the request getImagingTasks request = new getImagingTasks(); request.robot = global::OPPF.Utilities.Robot2Utils.createProxy(robot); request.plateID = plateID; // Make the call getImagingTasksResponse response = null; try { WSPlate wsPlate = WSPlateFactory.getWSPlate2(); wsPlate.Timeout = 10000; response = wsPlate.getImagingTasks(request); } catch (Exception e) { // Log it string msg = "WSPlate.getImagingTasks threw " + e.GetType() + ": " + e.Message + " for plateid \"" + plateID + "\" in robot \"" + robot.Name + "\" - returning empty IImagingTask[]"; msg = msg + WSPlateFactory.SoapExceptionToString(e); _log.Error(msg, e); // Don't rethrow - just return empty array return(iImagingTasks); } // If we got a response if (null != response) { // Get the array of ImagingTasks from the response global::OPPF.Proxies2.ImagingTask[] wrapper = response.wrapper; // Convert to IImagingTasks iImagingTasks = new IImagingTask[wrapper.GetLength(0)]; for (int i = 0; i < wrapper.GetLength(0); i++) { global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask task = new global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask(); if (wrapper[i].dateImaged.HasValue) { task.SetDateImaged(wrapper[i].dateImaged.Value); } task.SetDateToImage(wrapper[i].dateToImage); task.SetInQueue(wrapper[i].inQueue); task.SetPriority(wrapper[i].priority); task.SetState((Formulatrix.Integrations.ImagerLink.Scheduling.ImagingState)wrapper[i].state); iImagingTasks[i] = task; } } // Return the IImagingTask array return(iImagingTasks); }
/// <summary> /// Display the supplied imaging tasks /// </summary> /// <param name="tasks"></param> private void displayImagingTasks(IImagingTask[] tasks, DateTime currentDateToImage) { // Clear rows dt.Rows.Clear(); // If we got some tasks if (tasks != null) { // Declare a DataRow DataRow dr; // Get an enumerator System.Collections.IEnumerator enumerator = tasks.GetEnumerator(); // While we have more tasks while (enumerator.MoveNext()) { // Get this task IImagingTask task = (IImagingTask)enumerator.Current; // Get a new row dr = dt.NewRow(); // Populate the row dr[0] = task.DateToImage; dr[1] = task.Priority; dr[2] = task.InQueue; dr[3] = task.State; dr[4] = task.DateImaged.ToUniversalTime(); dr[5] = task.DateToImage.ToUniversalTime(); dr[6] = task.DateImaged.ToLocalTime(); dr[7] = task.DateToImage.ToLocalTime(); // Add the row to the table dt.Rows.Add(dr); } } // Use currentDateToImage to reselect current row if (DateTime.MinValue.Equals(currentDateToImage)) { dgImagingTasks.CurrentRowIndex = 0; } else { DataView dv = (DataView)dgImagingTasks.DataSource; System.Collections.IEnumerator enumerator = dv.GetEnumerator(); int i = 0; while (enumerator.MoveNext()) { DataRowView drv = (DataRowView)enumerator.Current; if (currentDateToImage.Equals(drv.Row.ItemArray[0])) { dgImagingTasks.CurrentRowIndex = i; break; } i++; } } // Update radio button labels rdbScheduled.Text = "Scheduled imaging tasks for " + barcode; rdbUnscheduled.Text = "Unscheduled imaging task for " + barcode; if (dgImagingTasks.CurrentRowIndex > -1) { rdbUnscheduled.Checked = false; rdbScheduled.Checked = true; } else { rdbScheduled.Checked = false; rdbUnscheduled.Checked = true; } updateActionButtonState(); }