/**
   * @param experimentId
   * @param sbName
   * @return
   */
  public ResultReport RetrieveResult(int experimentId, String sbName) {
    final String methodName = "RetrieveResult";
    Logfile.WriteCalled(
        logLevel,
        STR_ClassName,
        methodName,
        String.format(STRLOG_ExperimentIdSbName_arg2, experimentId, sbName));

    ResultReport resultReport;

    try {
      /*
       * Try getting the result of the completed experiment
       */
      resultReport =
          this.labManagement.getExperimentResultsDB().RetrieveResultReport(experimentId, sbName);
      if (resultReport.getStatusCode() == StatusCodes.Unknown) {
        /*
         * No results found for the experiment, check the queue to see if it ever existed
         */
        ExperimentQueueInfo experimentQueueInfo =
            this.labManagement.getExperimentQueueDB().RetrieveByExperimentId(experimentId, sbName);
        if (experimentQueueInfo != null) {
          resultReport.setStatusCode(experimentQueueInfo.getStatusCode());
        }
      }
    } catch (Exception ex) {
      Logfile.WriteError(ex.toString());
      resultReport = new ResultReport(StatusCodes.Unknown, ex.toString());
    }

    Logfile.WriteCompleted(
        logLevel,
        STR_ClassName,
        methodName,
        String.format(STRLOG_StatusCode_arg, resultReport.getStatusCode()));

    return resultReport;
  }
  /**
   * @param experimentId
   * @param sbName
   * @return
   */
  public synchronized LabExperimentStatus GetLabExperimentStatus(int experimentId, String sbName) {
    final String methodName = "GetLabExperimentStatus";
    Logfile.WriteCalled(
        Level.INFO,
        STR_ClassName,
        methodName,
        String.format(STRLOG_ExperimentIdSbName_arg2, experimentId, sbName));

    LabExperimentStatus labExperimentStatus = new LabExperimentStatus();

    try {
      /*
       * Check that parameters are valid
       */
      if (experimentId <= 0) {
        throw new RuntimeException(String.format(STRERR_InvalidExperimentId_arg, experimentId));
      }
      if (sbName == null) {
        throw new NullPointerException(STRERR_SbName);
      }

      /*
       * Get the status of the experiment from the queue
       */
      ExperimentQueueInfo experimentQueueInfo =
          this.labManagement.getExperimentQueueDB().RetrieveByExperimentId(experimentId, sbName);
      if (experimentQueueInfo == null) {
        throw new RuntimeException(
            String.format(STRERR_UnknownExperimentSbNameExperimentId_arg2, sbName, experimentId));
      }

      System.out.println(String.format("StatusCode: %s", experimentQueueInfo.getStatusCode()));

      /*
       * Experiment exists, check status
       */
      switch (experimentQueueInfo.getStatusCode()) {
        case Waiting:
          /*
           * Experiment is waiting on the queue, get the queue position and wait time
           */
          QueuedExperimentInfo queuedExperimentInfo =
              this.labManagement
                  .getExperimentQueueDB()
                  .GetQueuedExperimentInfo(experimentId, sbName);
          WaitEstimate waitEstimate = new WaitEstimate();
          waitEstimate.setEffectiveQueueLength(queuedExperimentInfo.getPosition());
          waitEstimate.setEstWait(
              queuedExperimentInfo.getWaitTime() + this.GetMinRemainingRuntime());

          System.out.println(
              String.format(
                  "WaitEstimate: QueueLength=%d  WaitTime=%f01",
                  waitEstimate.getEffectiveQueueLength(), waitEstimate.getEstWait()));

          /*
           * Set the experiment status and time it takes to run the experiment
           */
          ExperimentStatus experimentStatus =
              new ExperimentStatus(experimentQueueInfo.getStatusCode());
          experimentStatus.setEstRuntime(experimentQueueInfo.getEstimatedExecTime());
          experimentStatus.setEstRemainingRuntime(experimentQueueInfo.getEstimatedExecTime());
          experimentStatus.setWaitEstimate(waitEstimate);

          labExperimentStatus = new LabExperimentStatus(experimentStatus);

          Logfile.Write(
              logLevel,
              String.format(
                  STRLOG_ExperimentStatus_arg4,
                  waitEstimate.getEffectiveQueueLength(),
                  waitEstimate.getEstWait(),
                  experimentStatus.getEstRuntime(),
                  experimentStatus.getEstRemainingRuntime()));

          System.out.println(
              String.format(
                  STRLOG_ExperimentStatus_arg4,
                  waitEstimate.getEffectiveQueueLength(),
                  waitEstimate.getEstWait(),
                  experimentStatus.getEstRuntime(),
                  experimentStatus.getEstRemainingRuntime()));
          break;

        case Running:
          /*
           * Get the experiment status from the lab experiment engine
           */
          LabExperimentEngine labExperimentEngine =
              this.labExperimentEngines[experimentQueueInfo.getUnitId()];
          labExperimentStatus.setExperimentStatus(
              labExperimentEngine.GetExperimentStatus(experimentId, sbName));
          break;

        case Cancelled:
          /*
           * The experiment was cancelled while waiting on the queue
           */
          labExperimentStatus.setExperimentStatus(new ExperimentStatus(StatusCodes.Cancelled));
          break;

        default:
          /*
           * Experiment has completed, cancelled or failed so get the status from the experiment results
           */
          ResultReport resultReport =
              this.labManagement
                  .getExperimentResultsDB()
                  .RetrieveResultReport(experimentId, sbName);
          labExperimentStatus.setExperimentStatus(
              new ExperimentStatus(resultReport.getStatusCode()));
          break;
      }
    } catch (Exception ex) {
      Logfile.WriteError(ex.toString());
      labExperimentStatus.setExperimentStatus(new ExperimentStatus(StatusCodes.Unknown));
    }

    ExperimentStatus experimentStatus = labExperimentStatus.getExperimentStatus();

    Logfile.WriteCompleted(
        Level.INFO,
        STR_ClassName,
        methodName,
        String.format(
            STRLOG_ExperimentStatus_arg3,
            experimentStatus.getStatusCode(),
            experimentStatus.getEstRuntime(),
            experimentStatus.getEstRemainingRuntime()));

    return labExperimentStatus;
  }