docs: public List processNack(ControlNack nm)
                      throws SIResourceException
      {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.entry(tc, "processNack", new Object[] { nm, Boolean.valueOf(false) });
  
          boolean sendPending = false;
          ArrayList sendList = new ArrayList();
  
          boolean sendLeadingSilence = false;
          long lsstart = 0;
          long lsend = 0;
          boolean sendTrailingSilence = false;
          long tsstart = 0;
          long tsend = 0;
  
          long startstamp = nm.getStartTick();
          long endstamp = nm.getEndTick();
  
          long completedPrefix;
  
          // the TickRange to hold information discovered as we traverse stream
          TickRange r = null;
  
          // Go through oststream and see which ticks in the Nack range are
          // Completed or Value or Uncommitted and send appropriate messages
          // for these ticks. 
          synchronized (this)
          {
              // SIB0105
              // Update the health state of this stream 
              getControlAdapter().getHealthState().updateHealth(HealthStateListener.NACK_RECEIVED_STATE,
                                                                HealthState.AMBER);
              lastNackReceivedTick = endstamp;
  
              completedPrefix = oststream.getCompletedPrefix();
  
              // If some of the ticks in the Nack range are before the completedPrefix
              // of our Stream we send a Silence message from the startstamp 
              // to the completedPrefix.
              if (startstamp <= completedPrefix)
              {
                  sendLeadingSilence = true;
                  lsstart = startstamp;
                  lsend = completedPrefix;
  
                  //Some of the ticks in the Nack range are before the completedPrefix
                  //of our Stream so start from there
                  startstamp = completedPrefix + 1;
              }
  
              // If there are any tick in the Nack range which are not yet
              // complete process these now
              if (endstamp > completedPrefix)
              {
                  oststream.setCursor(startstamp);
  
                  // Get the first TickRange
                  TickRange tr = oststream.getNext();
  
                  TickRange tr2 = null;
                  while ((tr.startstamp <= endstamp) && (tr != tr2))
                  {
                      if ((tr.type == TickRange.Unknown)
                          || (tr.type == TickRange.Requested))
                      {
                          // send Nack to parent and if Unknown change to Requested
                          long ss, es;
                          ss = max(tr.startstamp, startstamp);
                          es = min(endstamp, tr.endstamp);
                          TickRange ntr = new TickRange(TickRange.Requested, ss, es);
                          if (tr.type == TickRange.Unknown)
                          {
                              oststream.writeRange(ntr);
                          }
  
                          // Some syncronization issues b/w Source Stream and InternalOutputStream. 
                          //  So, We get Source Stream completed prefix and decide whether to mark this tick range(i.e ss to es) as COMPLETED or not
  
                          long sourceStream_completedPrefix = upControl.sendNackMessageWithReturnValue(null, null, null, ss, es, priority, reliability, streamID);
                          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                              SibTr.debug(tc, "sourceStream_completedPrefix : " + sourceStream_completedPrefix + "  es :" + es);
                          if (es <= sourceStream_completedPrefix) {
                              //if end stamp  is less than or equal to Source Stream completed prefix, then it means
                              //Source Stream is not having any information regarding these ticks (already COMPLETED)
                              // then forcefully send silence in these ticks and change InternalOutputStream completedPrefix
                              TickRange ctr = new TickRange(TickRange.Completed, ss, es);
                              writeSilenceForced(ctr); //this should change InternalOutputStream completedPrefix
                              downControl.sendSilenceMessage(
                                                             ss,
                                                             es,
                                                             oststream.getCompletedPrefix(),
                                                             true,
                                                             nm.getPriority().intValue(),
                                                             nm.getReliability(),
                                                             streamID);
                              /* PM62615.dev- Start */
                          } else {
  
                              if (sourceStream_completedPrefix != -1) {
                                  // we are not IME..
  
                                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
                                      SibTr.debug(tc, "NACK Range is Unknown and greater than completed prefix ");
  
                                  if (oststream.getCompletedPrefix() <= _lastTickWhenStreamCreated) {
                                      // If completedPrefix is less than
                                      // _lastMessageTickWhenStreamCreated means gap exits
  
                                      if (gapMap.get(tr) == null) {
                                          if ((tr.startstamp > _streamStartTick)
                                              && (tr.endstamp <= _lastTickWhenStreamCreated)) {
                                              // igonre of tick range object, i.e ignore tick
                                              // range objects whcih are outside of gap
                                              gapMap.put(tr, new Integer(1));
  
                                              if (TraceComponent.isAnyTracingEnabled()
                                                  && tc.isDebugEnabled())
                                                  SibTr.debug(tc,
                                                              "Adding Tickrange object into Gap map : "
                                                                              + Integer.toHexString(tr
                                                                                              .hashCode()));
                                          }
                                      } else {
                                          if (gapMap.get(tr).intValue() > 9) {
                                              if (TraceComponent.isAnyTracingEnabled()
                                                  && tc.isDebugEnabled())
                                                  SibTr
                                                                  .debug(tc,
                                                                         "Reached max nack tolerance(10) for mesages in gap ");
                                              // This is 10th time NACK coming for same tick
                                              // range. Go ahead and send silence
                                              TickRange ctr = new TickRange(
                                                              TickRange.Completed, ss, es);
                                              writeSilenceForced(ctr); // this should change
                                                                       // InternalOutputStream
                                                                       // completedPrefix
                                              downControl.sendSilenceMessage(ss, es,
                                                                             oststream.getCompletedPrefix(), true, nm
                                                                                             .getPriority().intValue(), nm
                                                                                             .getReliability(), streamID);
  
                                              // remove entry from tickRangeMap
                                              gapMap.remove(tr);
                                              if (TraceComponent.isAnyTracingEnabled()
                                                  && tc.isDebugEnabled())
                                                  SibTr.debug(tc,
                                                              "Removing TickRange object from Gap map : "
                                                                              + Integer.toHexString(tr
                                                                                              .hashCode()));
                                          } else {
                                              // Add number of NACK occurances into
                                              // tickRangeMap
                                              gapMap.put(tr, new Integer(gapMap.get(tr)
                                                              .intValue() + 1));
                                          }
                                      }
                                  } else {
                                      // oststream.getCompletedPrefix() <
                                      // this._lastMessageTickWhenStreamCreated .. means
                                      // gap either filled up or not exists at first place.
                                      // so just empty out tickRangeMap .. as no furhter
                                      // use of this map.
                                      gapMap.clear();
                                  }
                              }
                          }
                      }
                      else {
                          //remove entry from tickRangeMap. if tr is not there in map, then it is harmless operation.
                          removeTickRangeObjectFromHashmap(tr);
  
                          /* PM62615.dev- End */if (tr.type == TickRange.Value)
                          {
                              // Do we have a previous Value message to add
                              // to the list
                              if (sendPending == true)
                              {
                                  sendList.add(r);
                              }
  
                              // Copy the Value tick range into r 
                              r = (TickRange) tr.clone();
                              sendPending = true;
  
                          }
                          else if (tr.type == TickRange.Uncommitted)
                          {
                              // If there is a previous Value message in the list
                              // we can put any Completed ticks between that and this
                              // Uncommitted tick into it.
                              if (sendPending == true)
                              {
                                  // If there are Completed ticks between
                                  // the Value and Uncommitted ticks
                                  // Add them to the end of the Value message
                                  if (tr.valuestamp > (r.valuestamp + 1))
                                  {
                                      r.endstamp = tr.valuestamp - 1;
                                  }
                                  sendList.add(r);
                                  sendPending = false;
                              }
                          }
                      }
                      tr2 = tr;
                      tr = oststream.getNext();
                  } // end while
  
                  // If we finish on a Completed range then add this to the 
                  // last Value in our list
                  // Check for null as we may have dropped out first time round loop
                  // above without ever initialising tr2
                  if ((tr2 != null) && (tr2.type == TickRange.Completed))
                  {
                      if (sendPending == true)
                      {
                          r.endstamp = tr2.endstamp;
                      }
                      else
                      {
                          // Need to send this Completed range in a Silence
                          // message as there is no Value to add it to
                          // This may be beacuse the whole Nack range is Completed or
                          // because the previous range was Uncommitted
                          sendTrailingSilence = true;
                          tsstart = tr2.startstamp;
                          tsend = tr2.endstamp;
  
                      }
                  }
                  if (sendPending == true)
                  {
                      sendList.add(r);
                  }
              }
          } // end sync
  
          if (sendLeadingSilence == true)
          {
              try
              {
                  downControl.sendSilenceMessage(
                                                 lsstart,
                                                 lsend,
                                                 completedPrefix,
                                                 true, // requestedOnly
                                                 nm.getPriority().intValue(),
                                                 nm.getReliability(),
                                                 streamID);
              } catch (SIResourceException e)
              {
                  // FFDC
                  FFDCFilter.processException(
                                              e,
                                              "com.ibm.ws.sib.processor.gd.InternalOutputStream.processNack",
                                              "1:1096:1.83.1.1",
                                              this);
  
                  SibTr.exception(tc, e);
  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                      SibTr.exit(tc, "processNack", e);
  
                  throw e;
              }
          }
  
          // send list 
          if (sendList.size() != 0)
          {
              // This will return a list of expired Messages 
              // If there are any we have to replace them with Silence in the stream
              List expiredMsgs = null;
              try
              {
                  expiredMsgs = downControl.sendValueMessages(sendList,
                                                              getCompletedPrefix(),
                                                              true, // requestedOnly
                                                              priority,
                                                              reliability,
                                                              streamID);
              } catch (SIResourceException e)
              {
                  // FFDC
                  FFDCFilter.processException(
                                              e,
                                              "com.ibm.ws.sib.processor.gd.InternalOutputStream.processNack",
                                              "1:1129:1.83.1.1",
                                              this);
  
                  SibTr.exception(tc, e);
  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                      SibTr.exit(tc, "processNack", e);
  
                  throw e;
              }
  
              // If we were told to remove some messages from the stream do it now
              if (expiredMsgs != null)
              {
                  TickRange vtr = null;
                  for (int i = 0; i < expiredMsgs.size(); i++)
                  {
                      vtr = (TickRange) expiredMsgs.get(i);
                      writeSilenceForced(vtr);
                  }
              }
  
          }
  
          if (sendTrailingSilence == true)
          {
              try
              {
                  downControl.sendSilenceMessage(
                                                 tsstart,
                                                 tsend,
                                                 completedPrefix,
                                                 true, // requestedOnly
                                                 nm.getPriority().intValue(),
                                                 nm.getReliability(),
                                                 streamID);
              } catch (SIResourceException e)
              {
                  // FFDC
                  FFDCFilter.processException(
                                              e,
                                              "com.ibm.ws.sib.processor.gd.InternalOutputStream.processNack",
                                              "1:1172:1.83.1.1",
                                              this);
  
                  SibTr.exception(tc, e);
  
                  if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
                      SibTr.exit(tc, "processNack", e);
  
                  throw e;
              }
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
              SibTr.exit(tc, "processNack");
  
          return null;
      }