log.warn ("Message send over " +sockString+ " got reception exception " + "(ignored for now): " +ex);
String node = pam.getReceptionNode(); String s = (sockString != null ? " over " +sockString : ""); log.warn ("Message reception exception from node " +node+s+ " (ignored for now): " +ex);
    private synchronized boolean sendMessage (AttributedMessage msg, SocketSpec spec) throws Exception    {      if (log.isDebugEnabled()) log.debug ("Sending " +MessageUtils.toString(msg));      //  Serialize the message into a byte array.  Depending on properties set, we possibly help      //  insure message integrity via a message digest (eg. an embedded MD5 hash of the message).      byte msgBytes[] = MessageSerializationUtils.writeMessageToByteArray (msg, getDigest());      if (msgBytes == null) return false;      //  It appears that the only way we can determine whether our socket      //  connection is still valid is to try using it.  So we try it,      //  and if it fails, we create a new connected socket and try again.      String sockString = null;      PureAckMessage pam = null;      long sendTime = 0, receiveTime = 0;            for (int tryN=1; tryN<=2; tryN++)  // try at most twice      {        try        {          //  Create socket if needed          if (socket == null)           {            tryN = 2;  // only try once with a new socket            if (log.isDebugEnabled()) log.debug ("Creating socket to " +destination+ " with " +spec);            socket = getSocket (spec);            if (log.isDebugEnabled()) log.debug ("Created socket " + (sockString = socket.toString()));            socketOut = new BufferedOutputStream (socket.getOutputStream());            if (doInbandAcking) socketIn = new BufferedInputStream (socket.getInputStream());          }          //  Send the message          if (log.isDebugEnabled()) log.debug ("Sending " +msgBytes.length+ " byte msg over " +sockString);          sendTime = now();          MessageSerializationUtils.writeByteArray (socketOut, msgBytes);          if (log.isDebugEnabled()) log.debug ("Sending " +msgBytes.length+ " byte msg done " +sockString);          break;        }        catch (Exception e)        {          //  If this is the second send try, go ahead and throw the exception          //  so that the caller can see it.          closeSocket();          if (tryN == 1) continue;          else throw (e);        }      }      //  Optionally do inband acking      if (doInbandAcking && MessageUtils.isAckableMessage (msg))      {        try        {          //  See if we get an ack          if (log.isDebugEnabled()) log.debug ("Waiting for ack over " +sockString);          byte[] ackBytes = MessageSerializationUtils.readByteArray (socketIn);          receiveTime = now();          if (log.isDebugEnabled()) log.debug ("Waiting for ack done " +sockString);          pam = processAck (ackBytes);          //  Send an ack-ack          //          //  The inband acking protocol is that if the ack back reports a message          //  reception exception then no ack-ack is sent for the ack.          if (!pam.hasReceptionException())          {            byte[] ackAckBytes = createAckAck (pam, receiveTime);            if (log.isDebugEnabled()) log.debug ("Sending ack-ack over " +sockString);            MessageSerializationUtils.writeByteArray (socketOut, ackAckBytes);            if (log.isDebugEnabled()) log.debug ("Sending ack-ack done " +sockString);          }          else          {            Exception ex = pam.getReceptionException();            if (log.isWarnEnabled())            {              log.warn ("Message send over " +sockString+ " got reception exception " +                        "(ignored for now): " +ex);            }          }        }        catch (Exception e)        {          //  Any acking that did not complete will be taken care of in later acking          if (log.isDebugEnabled()) log.debug ("Inband acking stopped for " +sockString+ ": " +e);          closeSocket();        }       }      //  Optionally close the socket      try      {        if (oneSendPerConnection) closeSocket(); // useful if retiring threads fast on receive side        else unscheduleSocketClose (socket);       }      catch (Exception e)      {        closeSocket();      }      //  Update the inband RTT if possible      if (rttService != null && pam != null)      {        DestinationLink sendLink = this;        String node = MessageUtils.getToAgentNode (msg);        int rtt = ((int)(receiveTime - sendTime)) - pam.getInbandNodeTime();        rttService.updateInbandRTT (sendLink, node, rtt);      }      return true;  // msg send successful    }