docs: private void displayRecords(PrintStream outps, LogViewerFilter searchCriteria, RepositoryReaderImpl logRepository, Date requestedProcess, String requestedSubProcess) {
  
          // count records
          int recordcount = 0;
          long opStart = System.currentTimeMillis();
  
          //This flag determines whether a footer should be printed or not.  The footer should
          //only be printed when the header has been printed.
          boolean headerPrinted = false;
  
          Iterable<ServerInstanceLogRecordList> repResults = null;
          boolean needHeader = false;
  
          // If we are executing -tail command
          if (tailInterval > 0) {
  
              boolean firstIteration = true;
              String tailPid = null;
              RepositoryPointer logRepositoryPointer = null;
              RepositoryPointer traceRepositoryPointer = null;
  
              if (latestInstance) {
                  ServerInstanceLogRecordList silrl = logRepository.getLogListForCurrentServerInstance();
                  requestedSubProcess = getLatestKid(silrl);
                  requestedProcess = silrl.getStartTime();
              }
  
              do {
                  // For tail command need to read repository on each iteration in case log or trace were created later.
                  logRepository = new RepositoryReaderImpl(binaryRepositoryDir);
                  RepositoryReaderImpl logReader = null;
                  if (logRepository.getLogLocation() != null) {
                      logReader = new RepositoryReaderImpl(logRepository.getLogLocation());
                  }
                  RepositoryReaderImpl traceReader = null;
                  if (logRepository.getTraceLocation() != null) {
                      traceReader = new RepositoryReaderImpl(logRepository.getTraceLocation());
                  }
                  if (logReader == null && traceReader == null) {
                      return;
                  }
  
                  // Adjust requested process only if we didn't see either log or trace records yet.
                  if (requestedProcess != null && (logRepositoryPointer == null || traceRepositoryPointer == null)) {
                      // Adjust requestedProcess to use in both log and trace repositories
                      if (logReader != null && traceReader != null) {
                          ServerInstanceLogRecordList logSilrl = logReader.getLogListForServerInstance(requestedProcess);
                          ServerInstanceLogRecordList traceSilrl = traceReader.getLogListForServerInstance(requestedProcess);
                          if (logRepositoryPointer == null && (logSilrl.getStartTime() == null || !logSilrl.getStartTime().equals(requestedProcess))) {
                              // requestedProcess correspond to trace start time, see if there are logs for the same process.
                              if (logSilrl.getStartTime() == null) {
                                  // First log was generated after requested date. Check the first log
                                  logSilrl = logReader.getLogLists(requestedProcess, null).iterator().next();
                              } else if (logSilrl.getStartTime().before(requestedProcess)) {
                                  // Log record was generated before requested date. Check the next log after 'requested date.
                                  Iterator<ServerInstanceLogRecordList> it = logReader.getLogLists(requestedProcess, null).iterator();
                                  it.next();
                                  logSilrl = it.next();
                              } else {
                                  // requestedDate should correspond to the first record among logs and traces
                                  throw new RuntimeException("Internal Error! Log start time is after requested date");
                              }
                              if (logSilrl != null) {
                                  String logPid = logSilrl.getHeader().getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
  
                                  String tracePid = traceSilrl.getHeader().getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
                                  if (tracePid.equals(logPid)) {
                                      requestedProcess = logSilrl.getStartTime();
                                      //no need for null check on requestedProcess here as long as both logReader and traceReader have
                                      //been checked for non-null values.
                                  } else {
                                      logReader = null;
                                  }
                              } // No adjustment is necessary if logSilrl is 'null'. It can mean the requestedProcess was already adjusted for trace.
                          } else if (traceRepositoryPointer == null && (traceSilrl.getStartTime() == null || !traceSilrl.getStartTime().equals(requestedProcess))) {
                              // requestedProcess correspond to log start time, see if there are traces for the same process.
                              if (traceSilrl.getStartTime() == null) {
                                  // First trace was generated after requested date. Check the first trace
                                  traceSilrl = traceReader.getLogLists(requestedProcess, null).iterator().next();
                              } else if (traceSilrl.getStartTime().before(requestedProcess)) {
                                  // Trace record was generated before requested date. Check the next trace after 'requested date.
                                  Iterator<ServerInstanceLogRecordList> it = traceReader.getLogLists(requestedProcess, null).iterator();
                                  it.next();
                                  traceSilrl = it.next();
                              } else {
                                  // requestedDate should correspond to the first record among logs and traces
                                  throw new RuntimeException("Internal Error! Trace start time is after requested date");
                              }
                              if (traceSilrl != null) {
                                  String tracePid = traceSilrl.getHeader().getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
  
                                  String logPid = logSilrl.getHeader().getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
                                  if (logPid.equals(tracePid)) {
                                      requestedProcess = traceSilrl.getStartTime();
                                      //no need for null check on requestedProcess here as long as both logReader and traceReader have
                                      //been checked for non-null values.
                                  } else {
                                      traceReader = null;
                                  }
                              } // No adjustment is necessary if traceSilrl is 'null'. It can mean the requestedProcess was already adjusted for trace.
                          }
                      }
                  }
  
                  // set startDate or initialize first repository pointers only on the first iteration.
                  if (startDate == null && firstIteration) {
                      // we are tailing the log, don't want old messages.
                      if (requestedProcess != null) {
                          ServerInstanceLogRecordList silrl;
                          RepositoryLogRecord lastRecord;
  
                          if (logReader != null) {
                              // Initialize logRepositoryPointer with the last log record
                              silrl = logReader.getLogListForServerInstance(requestedProcess, searchCriteria);
                              if (requestedSubProcess != null && !requestedSubProcess.isEmpty()) {
                                  silrl = silrl.getChildren().get(requestedSubProcess);
                              }
                              // silrl can be 'null' if subprocess don't have log records.
                              if (silrl != null) {
                                  lastRecord = silrl.range(-1, 1).iterator().next();
                                  if (lastRecord != null) {
                                      logRepositoryPointer = lastRecord.getRepositoryPointer();
                                  }
                              }
                          }
  
                          if (traceReader != null) {
                              // Initialize traceRepositoryPointer with the last trace record
                              silrl = traceReader.getLogListForServerInstance(requestedProcess, searchCriteria);
                              if (requestedSubProcess != null && !requestedSubProcess.isEmpty()) {
                                  silrl = silrl.getChildren().get(requestedSubProcess);
                              }
                              // silrl can be 'null' if subprocess don't have trace records.
                              if (silrl != null) {
                                  lastRecord = silrl.range(-1, 1).iterator().next();
                                  if (lastRecord != null) {
                                      traceRepositoryPointer = lastRecord.getRepositoryPointer();
                                  }
                              }
                          }
                      } else {
                          startDate = new Date();
                      }
                  }
  
                  firstIteration = false;
  
                  //get all server instances
                  final Iterator<ServerInstanceLogRecordList> logResults;
                  ServerInstanceLogRecordList nextLogList = null;
                  final Iterator<ServerInstanceLogRecordList> traceResults;
                  ServerInstanceLogRecordList nextTraceList = null;
  
                  if (logReader != null) {
                      if (requestedProcess != null) {
                          if (logRepositoryPointer == null) {
                              nextLogList = logReader.getLogListForServerInstance(requestedProcess, searchCriteria);
                              if (requestedSubProcess != null && !requestedSubProcess.isEmpty()) {
                                  nextLogList = nextLogList.getChildren().get(requestedSubProcess);
                              }
                          } else {
                              nextLogList = logReader.getLogListForServerInstance(logRepositoryPointer, searchCriteria);
                              // Note that using pointer returns list for the same process/subprocess the pointer's record
                              // came from so we don't need to retrieve children here.
                          }
                          logResults = null;
                      } else {
                          if (logRepositoryPointer == null) {
                              logResults = logReader.getLogLists(startDate, stopDate, searchCriteria).iterator();
                          } else {
                              logResults = logReader.getLogLists(logRepositoryPointer, stopDate, searchCriteria).iterator();
                          }
  
                          nextLogList = logResults.next();
                      }
                  } else {
                      logResults = null;
                  }
                  if (traceReader != null) {
                      if (requestedProcess != null) {
                          if (traceRepositoryPointer == null) {
                              nextTraceList = traceReader.getLogListForServerInstance(requestedProcess, searchCriteria);
                              if (requestedSubProcess != null && !requestedSubProcess.isEmpty()) {
                                  nextTraceList = nextTraceList.getChildren().get(requestedSubProcess);
                              }
                          } else {
                              nextTraceList = traceReader.getLogListForServerInstance(traceRepositoryPointer, searchCriteria);
                              // Note that using pointer returns list for the same process/subprocess the pointer's record
                              // came from so we don't need to retrieve children here.
                          }
                          traceResults = null;
                      } else {
                          if (traceRepositoryPointer == null) {
                              traceResults = traceReader.getLogLists(startDate, stopDate, searchCriteria).iterator();
                          } else {
                              traceResults = traceReader.getLogLists(traceRepositoryPointer, stopDate, searchCriteria).iterator();
                          }
                          nextTraceList = traceResults.next();
                      }
                  } else {
                      traceResults = null;
                  }
  
                  while (nextLogList != null || nextTraceList != null) {
                      // Skip log instances with no records
                      RepositoryLogRecord log = null;
                      if (nextLogList != null) {
                          while ((log = nextLogList.iterator().next()) == null) {
                              nextLogList = logResults == null ? null : logResults.next();
                              if (nextLogList == null) {
                                  break;
                              }
                          }
                      }
                      // Skip trace instances with no records
                      RepositoryLogRecord trace = null;
                      if (nextTraceList != null) {
                          while ((trace = nextTraceList.iterator().next()) == null) {
                              nextTraceList = traceResults == null ? null : traceResults.next();
                              if (nextTraceList == null) {
                                  break;
                              }
                          }
                      }
                      // If no records in either log or trace we are done.
                      if (log == null && trace == null) {
                          break;
                      }
  
                      boolean useLog = false;
                      boolean useTrace = false;
                      // If there's no more trace instances use log
                      if (nextTraceList == null) {
                          useLog = true;
                          // If there's no more log instances use trace
                      } else if (nextLogList == null) {
                          useTrace = true;
                      } else {
                          String logPid = nextLogList.getHeader().getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
                          String tracePid = nextTraceList.getHeader().getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
                          // If both log and trace came from the same process use both
                          if ((logPid == null && tracePid == null) || (logPid != null && logPid.equals(tracePid))) {
                              useLog = true;
                              useTrace = true;
                              // If first log record written earlier than first trace record written by a different process use log
                          } else if (log.getMillis() < trace.getMillis()) {
                              useLog = true;
                          } else {
                              useTrace = true;
                          }
                      }
  
                      Iterable<RepositoryLogRecord> resultsList;
                      Properties pidHeaderProps;
                      if (!useTrace) {
                          pidHeaderProps = nextLogList.getHeader();
                          resultsList = nextLogList;
                          nextLogList = logResults == null ? null : logResults.next();
                      } else if (!useLog) {
                          pidHeaderProps = nextTraceList.getHeader();
                          resultsList = nextTraceList;
                          nextTraceList = traceResults == null ? null : traceResults.next();
                      } else {
                          pidHeaderProps = nextLogList.getHeader();
                          resultsList = new LocalMergedRepository(nextLogList, nextTraceList);
                          nextLogList = logResults == null ? null : logResults.next();
                          nextTraceList = traceResults == null ? null : traceResults.next();
                      }
  
                      String pid = pidHeaderProps.getProperty(ServerInstanceLogRecordList.HEADER_PROCESSID);
                      if (pid != null && !pid.equals(tailPid)) { // this is a new server instance.
                          needHeader = true;
                      }
                      tailPid = pid;
  
                      // For each record in this Pid's logs - write the record - to either text file or binary repository
                      for (RepositoryLogRecord record : resultsList) {
                          // we have a non-zero resultList set, so print header.
  
                          if (needHeader) {
                              theFormatter.setStartDatetime(record.getMillis());
                              printHeader(pidHeaderProps, outps, headerPrinted);
                              headerPrinted = true;
                              needHeader = false;
                          }
                          if (!useTrace) {
                              logRepositoryPointer = record.getRepositoryPointer();
                              //logRepositoryPointer = null;
                          } else if (!useLog) {
                              traceRepositoryPointer = record.getRepositoryPointer();
                          } else {
                              if (((LocalMergedRepository) resultsList).isLastLog()) {
                                  logRepositoryPointer = record.getRepositoryPointer();
                              } else {
                                  traceRepositoryPointer = record.getRepositoryPointer();
                              }
                          }
                          if (outputRepository != null) {
                              outputRepository.storeRecord(record);
                          } else {
                              outps.println(theFormatter.formatRecord(record));
                          }
  
                          recordcount++;
                      }
  
                  }
  
                  // If there's a new instance after the one we are monitoring we don't need to wait anymore.
                  if (requestedProcess != null && requestedProcess.before(logRepository.getLogListForCurrentServerInstance().getStartTime())) {
                      break;
                  }
  
                  // We are tailing the log, wait interval and pickup where we left off.
                  try {
                      Thread.sleep(tailInterval * 1000);
                  } catch (InterruptedException e) {
                      // User wants to exit.
                      break;
                  }
  
              } while (true);
  
              // If specific instance was selected
          } else if (latestInstance || requestedProcess != null) {
  
              ServerInstanceLogRecordList silrl = null;
              if (latestInstance) {
                  silrl = logRepository.getLogListForCurrentServerInstance();
                  requestedSubProcess = getLatestKid(silrl);
  
                  silrl = logRepository.getLogListForServerInstance((Date) null, searchCriteria);
              }
              //else instanceId was specified so get a specific silrl
              else {
                  //get specific ServerInstnace
                  silrl = logRepository.getLogListForServerInstance(requestedProcess, searchCriteria);
              }
              if (requestedSubProcess != null && !requestedSubProcess.isEmpty()) {
                  silrl = silrl.getChildren().get(requestedSubProcess);
              }
  
              //process all records in the requested process or the subprocess
              if (silrl != null) {
                  Properties pidHeaderProps = silrl.getHeader();
  
                  // For each record in this Pid's logs - write the record - to either text file or binary repository
                  for (RepositoryLogRecord record : silrl) {
                      // we have a non-zero resultList set, so print header.
                      if (!headerPrinted) {
                          //pidHeaderProps.put("headerStartDatetime", record.getMillis());
                          theFormatter.setStartDatetime(record.getMillis());
                          printHeader(pidHeaderProps, outps, false);
                          headerPrinted = true;
                      }
                      if (outputRepository != null) {
                          outputRepository.storeRecord(record);
                      } else {
                          outps.println(theFormatter.formatRecord(record));
                      }
                      recordcount++;
                  }
  
              }
  
              //if no instanceid was provided
          } else {
  
              repResults = logRepository.getLogLists(startDate, stopDate, searchCriteria);
  
              for (ServerInstanceLogRecordList resultsList : repResults) {
                  Properties pidHeaderProps = resultsList.getHeader();
                  needHeader = true;
  
                  // For each record in this Pid's logs - write the record - to either text file or binary repository
  
                  for (RepositoryLogRecord record : resultsList) {
                      // we have a non-zero resultList set, so print header.
                      if (needHeader) {
                          //pidHeaderProps.put("headerStartDatetime", record.getMillis());
                          theFormatter.setStartDatetime(record.getMillis());
                          printHeader(pidHeaderProps, outps, headerPrinted);
                          headerPrinted = true;
                          needHeader = false;
                      }
                      if (outputRepository != null) {
                          outputRepository.storeRecord(record);
                      } else {
                          outps.println(theFormatter.formatRecord(record));
                      }
                      recordcount++;
                  }
              }
          }
  
          if (outputRepository != null) {
              outputRepository.close();
          } else if (hasFooter && headerPrinted) {
              // need to print a CBE footer
              outps.println(theFormatter.getFooter());
          }
  
          if (!isSystemOut) {
              outps.flush();
              // close the file
              outps.close();
          }
  
          System.out.println(getLocalizedString("CWTRA0010I"));
          long opEnd = System.currentTimeMillis();
          double opSec = (opEnd - opStart) / 1000.0;
          double opAvg = recordcount / opSec;
  
          NumberFormat numFormat = null;
          if (locale == null) {
              numFormat = NumberFormat.getInstance(Locale.getDefault());
          } else {
              numFormat = NumberFormat.getInstance(locale);
          }
  
          System.out.println(getLocalizedParmString("CWTRA0018I",
                                                    new Object[] { numFormat.format(recordcount), numFormat.format(opSec), numFormat.format(opAvg) }));
  
      }