docs: public void processNack(ControlNack nm) throws SIResourceException
    {
      if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
        SibTr.entry(this, tc, "processNack", nm);
  
      boolean sendPending = false;
      List 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();
  
      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
      {
        SibTr.debug(tc, "processNack from: " + startstamp + " to " + endstamp + " on Stream " +  stream);
      }
  
      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;
        
        inboundFlow = true;
        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))
            {
              break;
            }
            else if (tr.type == TickRange.Value)
            {
              // Do we have a previous Value message to add
              // to the list
              if (sendPending)
              {
                sendList.add(r);
              }
  
              // If message is inside sendWindow
              // copy the Value tick range into r 
              if (msgCanBeSent(tr.valuestamp, true))
              {
                r = (TickRange)tr.clone();
                sendPending = true;
              }
              else
              {
                // If this message is outside the sendWindow we should stop
                break;
              }
            }
            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)
              {
                // 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)
            {
              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 because the whole Nack range is Completed or
              // because the previous range was Uncommitted
              // or because the previous range was outside the sendWindow
              if (msgCanBeSent(tr2.startstamp, true))
              {
                sendTrailingSilence = true;
                tsstart = tr2.startstamp;
                tsend = tr2.endstamp;
              }
            }
          }
          if (sendPending)
          {
            sendList.add(r);
          }
        }
      } // end sync
  
      // Send any Silence at start of Nack range
      if (sendLeadingSilence)
      {
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
        {
          SibTr.debug(tc, "processNack sending Silence from: " + lsstart + " to " + lsend + " on Stream " +  stream);
        }
  
        try
        {
          downControl.sendSilenceMessage(lsstart, lsend, completedPrefix, true,
                                         nm.getPriority().intValue(),
                                         nm.getReliability(), stream);
        }
        catch (SIResourceException e)
        {
          // FFDC
          FFDCFilter.processException(
            e,
            "com.ibm.ws.sib.processor.gd.SourceStream.processNack",
            "1:1222:1.138",
            this);
  
          SibTr.exception(tc, e);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "processNack", e);
  
          throw e;
        }
      }
  
  
      // send and messages in Nack range
      if (sendList.size() != 0)
      {
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
        {
          SibTr.debug(tc, "processNack resending Value messages on Stream " +  stream);
        }
  
        // second parameter indicates that this is a resend in response to a Nack 
        sendMsgs( sendList, true );
      }
  
      // send any Silence at end of Nack range
      if (sendTrailingSilence)
      {
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
        {
          SibTr.debug(tc, "processNack sending Silence from: " + tsstart + " to " + tsend + " on Stream " +  stream);
        }
  
        try
        {
          downControl.sendSilenceMessage(tsstart, tsend, completedPrefix, true,
                                         nm.getPriority().intValue(), 
                                         nm.getReliability(), stream);
        }
        catch (SIResourceException e)
        {
          // FFDC
          FFDCFilter.processException(
            e,
            "com.ibm.ws.sib.processor.gd.SourceStream.processNack",
            "1:1267:1.138",
            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");
    }