/** * This method deals with messages arrived as regular message but its contents are compressed. * Such messages come from message senders who are configured to compress large messages, and if * some of the messages are compressed below the min-large-message-size limit, they are sent as * regular messages. <br> * However when decompressing the message, we are not sure how large the message could be.. for * that reason we fake a large message controller that will deal with the message as it was a * large message <br> * Say that you sent a 1G message full of spaces. That could be just bellow 100K compressed but * you wouldn't have enough memory to decompress it */ private void handleCompressedMessage(final ClientMessageInternal clMessage) throws Exception { ClientLargeMessageImpl largeMessage = new ClientLargeMessageImpl(); largeMessage.retrieveExistingData(clMessage); File largeMessageCache = null; if (session.isCacheLargeMessageClient()) { largeMessageCache = File.createTempFile("tmp-large-message-" + largeMessage.getMessageID() + "-", ".tmp"); largeMessageCache.deleteOnExit(); } ClientSessionFactory sf = session.getSessionFactory(); ServerLocator locator = sf.getServerLocator(); long callTimeout = locator.getCallTimeout(); currentLargeMessageController = new LargeMessageControllerImpl( this, largeMessage.getLargeMessageSize(), callTimeout, largeMessageCache); currentLargeMessageController.setLocal(true); // sets the packet ActiveMQBuffer qbuff = clMessage.getBodyBuffer(); int bytesToRead = qbuff.writerIndex() - qbuff.readerIndex(); final byte[] body = qbuff.readBytes(bytesToRead).toByteBuffer().array(); largeMessage.setLargeMessageController( new CompressedLargeMessageControllerImpl(currentLargeMessageController)); currentLargeMessageController.addPacket(body, body.length, false); handleRegularMessage(largeMessage); }
public void decode(final ActiveMQBuffer buffer) { channelID = buffer.readLong(); decodeRest(buffer); size = buffer.readerIndex(); }
public void write( final ActiveMQBuffer buffer, final boolean flush, final boolean batch, final ChannelFutureListener futureListener) { final ActiveMQBuffer copied = buffer.copy(0, buffer.capacity()); copied.setIndex(buffer.readerIndex(), buffer.writerIndex()); try { executor.execute( new Runnable() { public void run() { try { if (!closed) { copied.readInt(); // read and discard if (isTrace) { ActiveMQServerLogger.LOGGER.trace( InVMConnection.this + "::Sending inVM packet"); } handler.bufferReceived(id, copied); if (futureListener != null) { // TODO BEFORE MERGE: (is null a good option here?) futureListener.operationComplete(null); } } } catch (Exception e) { final String msg = "Failed to write to handler on connector " + this; ActiveMQServerLogger.LOGGER.errorWritingToInvmConnector(e, this); throw new IllegalStateException(msg, e); } finally { if (isTrace) { ActiveMQServerLogger.LOGGER.trace(InVMConnection.this + "::packet sent done"); } } } }); if (flush && flushEnabled) { final CountDownLatch latch = new CountDownLatch(1); executor.execute( new Runnable() { public void run() { latch.countDown(); } }); try { if (!latch.await(10, TimeUnit.SECONDS)) { ActiveMQServerLogger.LOGGER.timedOutFlushingInvmChannel(); } } catch (InterruptedException e) { throw new ActiveMQInterruptedException(e); } } } catch (RejectedExecutionException e) { // Ignore - this can happen if server/client is shutdown and another request comes in } }