public void finish() throws Exception { synchronized (lock) { if (largeMessage == null) { // handleClose could be calling close while handle is also calling finish. // As a result one of them could get here after the largeMessage is already gone. // On that case we just ignore this call return; } if (context != null) { context.close(); } largeMessage.releaseResources(); largeMessage.decrementDelayDeletionCount(); if (preAcknowledge && !browseOnly) { // PreAck will have an extra reference largeMessage.decrementDelayDeletionCount(); } largeMessageDeliverer = null; largeMessage = null; } }
public boolean deliver() throws Exception { lockDelivery.readLock().lock(); try { if (largeMessage == null) { return true; } if (availableCredits != null && availableCredits.get() <= 0) { if (HornetQServerLogger.LOGGER.isTraceEnabled()) { HornetQServerLogger.LOGGER.trace( this + "::FlowControl::delivery largeMessage interrupting as there are no more credits, available=" + availableCredits); } return false; } if (!sentInitialPacket) { context = largeMessage.getBodyEncoder(); sizePendingLargeMessage = context.getLargeBodySize(); context.open(); sentInitialPacket = true; int packetSize = callback.sendLargeMessage( largeMessage, id, context.getLargeBodySize(), ref.getDeliveryCount()); if (availableCredits != null) { availableCredits.addAndGet(-packetSize); if (HornetQServerLogger.LOGGER.isTraceEnabled()) { HornetQServerLogger.LOGGER.trace( this + "::FlowControl::" + " deliver initialpackage with " + packetSize + " delivered, available now = " + availableCredits); } } // Execute the rest of the large message on a different thread so as not to tie up the // delivery thread // for too long resumeLargeMessage(); return false; } else { if (availableCredits != null && availableCredits.get() <= 0) { if (ServerConsumerImpl.isTrace) { HornetQServerLogger.LOGGER.trace( this + "::FlowControl::deliverLargeMessage Leaving loop of send LargeMessage because of credits, available=" + availableCredits); } return false; } int localChunkLen = 0; localChunkLen = (int) Math.min( sizePendingLargeMessage - positionPendingLargeMessage, minLargeMessageSize); HornetQBuffer bodyBuffer = HornetQBuffers.fixedBuffer(localChunkLen); context.encode(bodyBuffer, localChunkLen); byte[] body = bodyBuffer.toByteBuffer().array(); int packetSize = callback.sendLargeMessageContinuation( id, body, positionPendingLargeMessage + localChunkLen < sizePendingLargeMessage, false); int chunkLen = body.length; if (availableCredits != null) { availableCredits.addAndGet(-packetSize); if (HornetQServerLogger.LOGGER.isTraceEnabled()) { HornetQServerLogger.LOGGER.trace( this + "::FlowControl::largeMessage deliver continuation, packetSize=" + packetSize + " available now=" + availableCredits); } } positionPendingLargeMessage += chunkLen; if (positionPendingLargeMessage < sizePendingLargeMessage) { resumeLargeMessage(); return false; } } if (ServerConsumerImpl.isTrace) { HornetQServerLogger.LOGGER.trace("Finished deliverLargeMessage"); } finish(); return true; } finally { lockDelivery.readLock().unlock(); } }
public int sendMessage(ServerMessage serverMessage, long consumerID, int deliveryCount) { LargeServerMessageImpl largeMessage = null; ServerMessage newServerMessage = serverMessage; try { StompSubscription subscription = subscriptions.get(consumerID); StompFrame frame = null; if (serverMessage.isLargeMessage()) { newServerMessage = serverMessage.copy(); largeMessage = (LargeServerMessageImpl) serverMessage; BodyEncoder encoder = largeMessage.getBodyEncoder(); encoder.open(); int bodySize = (int) encoder.getLargeBodySize(); // large message doesn't have a body. ((ServerMessageImpl) newServerMessage).createBody(bodySize); encoder.encode(newServerMessage.getBodyBuffer(), bodySize); encoder.close(); } if (serverMessage.getBooleanProperty(Message.HDR_LARGE_COMPRESSED)) { // decompress HornetQBuffer qbuff = newServerMessage.getBodyBuffer(); int bytesToRead = qbuff.writerIndex() - MessageImpl.BODY_OFFSET; Inflater inflater = new Inflater(); inflater.setInput(qbuff.readBytes(bytesToRead).toByteBuffer().array()); // get the real size of large message long sizeBody = newServerMessage.getLongProperty(Message.HDR_LARGE_BODY_SIZE); byte[] data = new byte[(int) sizeBody]; inflater.inflate(data); inflater.end(); qbuff.resetReaderIndex(); qbuff.resetWriterIndex(); qbuff.writeBytes(data); } frame = connection.createStompMessage(newServerMessage, subscription, deliveryCount); int length = frame.getEncodedSize(); if (subscription.getAck().equals(Stomp.Headers.Subscribe.AckModeValues.AUTO)) { if (manager.send(connection, frame)) { // we ack and commit only if the send is successful session.acknowledge(consumerID, newServerMessage.getMessageID()); session.commit(); } } else { messagesToAck.put( newServerMessage.getMessageID(), new Pair<Long, Integer>(consumerID, length)); // Must send AFTER adding to messagesToAck - or could get acked from client BEFORE it's been // added! manager.send(connection, frame); } return length; } catch (Exception e) { return 0; } finally { if (largeMessage != null) { largeMessage.releaseResources(); largeMessage = null; } } }