// This must never called by more than one thread concurrently public boolean send(final Packet packet, final boolean flush, final boolean batch) { if (invokeInterceptors(packet, interceptors, connection) != null) { return false; } synchronized (sendLock) { packet.setChannelID(id); if (isTrace) { HornetQClientLogger.LOGGER.trace( "Sending packet nonblocking " + packet + " on channeID=" + id); } HornetQBuffer buffer = packet.encode(connection); lock.lock(); try { if (failingOver) { // TODO - don't hardcode this timeout try { failoverCondition.await(10000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new HornetQInterruptedException(e); } } // Sanity check if (transferring) { throw new IllegalStateException("Cannot send a packet while channel is doing failover"); } if (resendCache != null && packet.isRequiresConfirmations()) { resendCache.add(packet); } } finally { lock.unlock(); } if (isTrace) { HornetQClientLogger.LOGGER.trace("Writing buffer for channelID=" + id); } // The actual send must be outside the lock, or with OIO transport, the write can block if the // tcp // buffer is full, preventing any incoming buffers being handled and blocking failover connection.getTransportConnection().write(buffer, flush, batch); return true; } }
private void doWrite(final Packet packet) { final HornetQBuffer buffer = packet.encode(connection); connection.getTransportConnection().write(buffer, false, false); }
/** * Due to networking issues or server issues the server may take longer to answer than expected.. * the client may timeout the call throwing an exception and the client could eventually retry * another call, but the server could then answer a previous command issuing a * class-cast-exception. The expectedPacket will be used to filter out undesirable packets that * would belong to previous calls. */ public Packet sendBlocking(final Packet packet, byte expectedPacket) throws HornetQException { String interceptionResult = invokeInterceptors(packet, interceptors, connection); if (interceptionResult != null) { // if we don't throw an exception here the client might not unblock throw HornetQClientMessageBundle.BUNDLE.interceptorRejectedPacket(interceptionResult); } if (closed) { throw HornetQClientMessageBundle.BUNDLE.connectionDestroyed(); } if (connection.getBlockingCallTimeout() == -1) { throw new IllegalStateException( "Cannot do a blocking call timeout on a server side connection"); } // Synchronized since can't be called concurrently by more than one thread and this can occur // E.g. blocking acknowledge() from inside a message handler at some time as other operation on // main thread synchronized (sendBlockingLock) { packet.setChannelID(id); final HornetQBuffer buffer = packet.encode(connection); lock.lock(); try { if (failingOver) { try { if (connection.getBlockingCallFailoverTimeout() < 0) { while (failingOver) { failoverCondition.await(); } } else { if (!failoverCondition.await( connection.getBlockingCallFailoverTimeout(), TimeUnit.MILLISECONDS)) { HornetQClientLogger.LOGGER.debug("timed-out waiting for failover condition"); } } } catch (InterruptedException e) { throw new HornetQInterruptedException(e); } } response = null; if (resendCache != null && packet.isRequiresConfirmations()) { resendCache.add(packet); } connection.getTransportConnection().write(buffer, false, false); long toWait = connection.getBlockingCallTimeout(); long start = System.currentTimeMillis(); while (!closed && (response == null || (response.getType() != PacketImpl.EXCEPTION && response.getType() != expectedPacket)) && toWait > 0) { try { sendCondition.await(toWait, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { throw new HornetQInterruptedException(e); } if (response != null && response.getType() != PacketImpl.EXCEPTION && response.getType() != expectedPacket) { HornetQClientLogger.LOGGER.packetOutOfOrder(response, new Exception("trace")); } if (closed) { break; } final long now = System.currentTimeMillis(); toWait -= now - start; start = now; } if (response == null) { throw HornetQClientMessageBundle.BUNDLE.timedOutSendingPacket(packet.getType()); } if (response.getType() == PacketImpl.EXCEPTION) { final HornetQExceptionMessage mem = (HornetQExceptionMessage) response; HornetQException e = mem.getException(); e.fillInStackTrace(); throw e; } } finally { lock.unlock(); } return response; } }