/**
  * Send a notification to the client that their message (id specified) was accepted for delivery
  * (but not necessarily delivered) Doesn't do anything if i2cp.messageReliability = "none" or if
  * the nonce is 0.
  *
  * @param id OUR id for the message
  * @param nonce HIS id for the message
  */
 void ackSendMessage(MessageId id, long nonce) {
   if (_dontSendMSM || nonce == 0) return;
   SessionId sid = _sessionId;
   if (sid == null) return;
   if (_log.shouldLog(Log.DEBUG))
     _log.debug("Acking message send [accepted]" + id + " / " + nonce + " for sessionId " + sid);
   MessageStatusMessage status = new MessageStatusMessage();
   status.setMessageId(id.getMessageId());
   status.setSessionId(sid.getSessionId());
   status.setSize(0L);
   status.setNonce(nonce);
   status.setStatus(MessageStatusMessage.STATUS_SEND_ACCEPTED);
   try {
     doSend(status);
     _acceptedPending.remove(id);
   } catch (I2CPMessageException ime) {
     if (_log.shouldLog(Log.WARN)) _log.warn("Error writing out the message status message", ime);
   }
 }
    /**
     * Note that this sends the Guaranteed status codes, even though we only support best effort.
     */
    public void runJob() {
      if (_dead) return;

      MessageStatusMessage msg = new MessageStatusMessage();
      msg.setMessageId(_messageId.getMessageId());
      msg.setSessionId(_sessionId.getSessionId());
      // has to be >= 0, it is initialized to -1
      msg.setNonce(2);
      msg.setSize(0);
      msg.setStatus(_status);

      if (!alreadyAccepted(_messageId)) {
        if (_requeueCount++ > MAX_REQUEUE) {
          // bug requeueing forever? failsafe
          _log.error(
              "Abandon update for message "
                  + _messageId
                  + " to "
                  + MessageStatusMessage.getStatusString(msg.getStatus())
                  + " for session "
                  + _sessionId.getSessionId());
        } else {
          if (_log.shouldLog(Log.WARN))
            _log.warn(
                "Almost send an update for message "
                    + _messageId
                    + " to "
                    + MessageStatusMessage.getStatusString(msg.getStatus())
                    + " for session "
                    + _sessionId.getSessionId()
                    + " before they knew the messageId!  delaying .5s");
          _lastTried = _context.clock().now();
          requeue(REQUEUE_DELAY);
        }
        return;
      }

      boolean alreadyProcessed = false;
      long beforeLock = _context.clock().now();
      long inLock = 0;
      synchronized (_alreadyProcessed) {
        inLock = _context.clock().now();
        if (_alreadyProcessed.contains(_messageId)) {
          _log.warn("Status already updated");
          alreadyProcessed = true;
        } else {
          _alreadyProcessed.add(_messageId);
          while (_alreadyProcessed.size() > 10) _alreadyProcessed.remove(0);
        }
      }
      long afterLock = _context.clock().now();

      if (afterLock - beforeLock > 50) {
        _log.warn(
            "MessageDeliveryStatusUpdate.locking took too long: "
                + (afterLock - beforeLock)
                + " overall, synchronized took "
                + (inLock - beforeLock));
      }

      if (alreadyProcessed) return;

      if (_lastTried > 0) {
        if (_log.shouldLog(Log.DEBUG))
          _log.info(
              "Updating message status for message "
                  + _messageId
                  + " to "
                  + MessageStatusMessage.getStatusString(msg.getStatus())
                  + " for session "
                  + _sessionId.getSessionId()
                  + " (with nonce=2), retrying after "
                  + (_context.clock().now() - _lastTried));
      } else {
        if (_log.shouldLog(Log.DEBUG))
          _log.debug(
              "Updating message status for message "
                  + _messageId
                  + " to "
                  + MessageStatusMessage.getStatusString(msg.getStatus())
                  + " for session "
                  + _sessionId.getSessionId()
                  + " (with nonce=2)");
      }

      try {
        doSend(msg);
      } catch (I2CPMessageException ime) {
        if (_log.shouldLog(Log.WARN))
          _log.warn("Error updating the status for message ID " + _messageId, ime);
      }
    }