public void sendContinuations( final int packetSize, final long messageBodySize, final byte[] body, final boolean continues) throws Exception { if (currentLargeMessage == null) { throw HornetQMessageBundle.BUNDLE.largeMessageNotInitialised(); } // Immediately release the credits for the continuations- these don't contribute to the // in-memory size // of the message currentLargeMessage.addBytes(body); if (!continues) { currentLargeMessage.releaseResources(); if (messageBodySize >= 0) { currentLargeMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, messageBodySize); } doSend(currentLargeMessage, false); currentLargeMessage = null; } }
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; } }
private synchronized void doClose(final boolean failed) throws Exception { if (tx != null && tx.getXid() == null) { // We only rollback local txs on close, not XA tx branches try { rollback(failed, false); } catch (Exception e) { HornetQLogger.LOGGER.warn(e.getMessage(), e); } } Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values()); for (ServerConsumer consumer : consumersClone) { consumer.close(failed); } consumers.clear(); server.removeSession(name); if (currentLargeMessage != null) { try { currentLargeMessage.deleteFile(); } catch (Throwable error) { HornetQLogger.LOGGER.errorDeletingLargeMessageFile(error); } } remotingConnection.removeFailureListener(this); callback.closed(); }
public LargeMessageDeliverer(final LargeServerMessage message, final MessageReference ref) throws Exception { largeMessage = message; largeMessage.incrementDelayDeletionCount(); this.ref = ref; }
public void sendInternalLarge(ServerMessageImpl message, boolean direct) throws Exception { int headerSize = message.getHeadersAndPropertiesEncodeSize(); if (headerSize >= connection.getMinLargeMessageSize()) { throw BUNDLE.headerTooBig(); } StorageManager storageManager = ((ServerSessionImpl) session).getStorageManager(); long id = storageManager.generateUniqueID(); LargeServerMessage largeMessage = storageManager.createLargeMessage(id, message); byte[] bytes = new byte[message.getBodyBuffer().writerIndex() - MessageImpl.BODY_OFFSET]; message.getBodyBuffer().readBytes(bytes); largeMessage.addBytes(bytes); largeMessage.releaseResources(); largeMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, bytes.length); session.send(largeMessage, direct); largeMessage = null; }
public boolean delete(final PagedMessage[] messages) throws Exception { if (storageManager != null) { storageManager.pageDeleted(storeName, pageId); } if (isDebug) { HornetQServerLogger.LOGGER.debug("Deleting pageId=" + pageId + " on store " + storeName); } if (messages != null) { for (PagedMessage msg : messages) { if (msg.getMessage().isLargeMessage()) { LargeServerMessage lmsg = (LargeServerMessage) msg.getMessage(); // Remember, cannot call delete directly here // Because the large-message may be linked to another message // or it may still being delivered even though it has been acked already lmsg.decrementDelayDeletionCount(); } } } try { if (suspiciousRecords) { HornetQServerLogger.LOGGER.pageInvalid(file.getFileName(), file.getFileName()); file.renameTo(file.getFileName() + ".invalidPage"); } else { file.delete(); } return true; } catch (Exception e) { HornetQServerLogger.LOGGER.pageDeleteError(e); return false; } }
public void sendLarge(final MessageInternal message) throws Exception { // need to create the LargeMessage before continue long id = storageManager.generateUniqueID(); LargeServerMessage largeMsg = storageManager.createLargeMessage(id, message); if (HornetQLogger.LOGGER.isTraceEnabled()) { HornetQLogger.LOGGER.trace("sendLarge::" + largeMsg); } if (currentLargeMessage != null) { HornetQLogger.LOGGER.replacingIncompleteLargeMessage(currentLargeMessage.getMessageID()); } currentLargeMessage = largeMsg; }
private void doClose(final boolean failed) throws Exception { synchronized (this) { if (closed) return; if (tx != null && tx.getXid() == null) { // We only rollback local txs on close, not XA tx branches try { rollback(failed, false); } catch (Exception e) { HornetQServerLogger.LOGGER.warn(e.getMessage(), e); } } server.removeSession(name); remotingConnection.removeFailureListener(this); callback.closed(); closed = true; } // putting closing of consumers outside the sync block // https://issues.jboss.org/browse/HORNETQ-1141 Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values()); for (ServerConsumer consumer : consumersClone) { consumer.close(failed); } consumers.clear(); if (currentLargeMessage != null) { try { currentLargeMessage.deleteFile(); } catch (Throwable error) { HornetQServerLogger.LOGGER.errorDeletingLargeMessageFile(error); } } }
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 HandleStatus handle(final MessageReference ref) throws Exception { if (availableCredits != null && availableCredits.get() <= 0) { if (HornetQServerLogger.LOGGER.isDebugEnabled()) { HornetQServerLogger.LOGGER.debug( this + " is busy for the lack of credits. Current credits = " + availableCredits + " Can't receive reference " + ref); } return HandleStatus.BUSY; } // TODO - https://jira.jboss.org/browse/HORNETQ-533 // if (!writeReady.get()) // { // return HandleStatus.BUSY; // } synchronized (lock) { // If the consumer is stopped then we don't accept the message, it // should go back into the // queue for delivery later. if (!started || transferring) { return HandleStatus.BUSY; } // If there is a pendingLargeMessage we can't take another message // This has to be checked inside the lock as the set to null is done inside the lock if (largeMessageDeliverer != null) { if (HornetQServerLogger.LOGGER.isDebugEnabled()) { HornetQServerLogger.LOGGER.debug( this + " is busy delivering large message " + largeMessageDeliverer + ", can't deliver reference " + ref); } return HandleStatus.BUSY; } final ServerMessage message = ref.getMessage(); if (filter != null && !filter.match(message)) { if (HornetQServerLogger.LOGGER.isTraceEnabled()) { HornetQServerLogger.LOGGER.trace( "Reference " + ref + " is a noMatch on consumer " + this); } return HandleStatus.NO_MATCH; } if (HornetQServerLogger.LOGGER.isTraceEnabled()) { HornetQServerLogger.LOGGER.trace("Handling reference " + ref); } if (!browseOnly) { if (!preAcknowledge) { deliveringRefs.add(ref); } ref.handled(); ref.incrementDeliveryCount(); // If updateDeliveries = false (set by strict-update), // the updateDeliveryCount would still be updated after c if (strictUpdateDeliveryCount && !ref.isPaged()) { if (ref.getMessage().isDurable() && ref.getQueue().isDurable() && !ref.getQueue().isInternalQueue() && !ref.isPaged()) { storageManager.updateDeliveryCount(ref); } } if (preAcknowledge) { if (message.isLargeMessage()) { // we must hold one reference, or the file will be deleted before it could be delivered ((LargeServerMessage) message).incrementDelayDeletionCount(); } // With pre-ack, we ack *before* sending to the client ref.getQueue().acknowledge(ref); } } if (message.isLargeMessage()) { largeMessageDeliverer = new LargeMessageDeliverer((LargeServerMessage) message, ref); } lockDelivery.readLock().lock(); return HandleStatus.HANDLED; } }