/** * 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(); }
@Override public void decodeRest(final ActiveMQBuffer buffer) { consumerID = buffer.readLong(); deliveryCount = buffer.readInt(); largeMessageSize = buffer.readLong(); message.decodeHeadersAndProperties(buffer); }
@Override public void encodeRest(final ActiveMQBuffer buffer) { buffer.writeLong(consumerID); buffer.writeInt(deliveryCount); buffer.writeLong(largeMessageSize); message.encodeHeadersAndProperties(buffer); }
@Override public void encodeRest(final ActiveMQBuffer buffer) { buffer.writeLong(consumerID); buffer.writeLong(messageID); buffer.writeBoolean(requiresResponse); }
@Override public void decodeRest(final ActiveMQBuffer buffer) { consumerID = buffer.readLong(); messageID = buffer.readLong(); requiresResponse = buffer.readBoolean(); }
/** * Large message version of {@link #assertMessageBody(int, ClientMessage)}. * * @param i * @param message */ protected static void assertLargeMessageBody(final int i, final ClientMessage message) { ActiveMQBuffer buffer = message.getBodyBuffer(); for (int j = 0; j < LARGE_MESSAGE_SIZE; j++) { Assert.assertTrue( "msg " + i + ", expecting " + LARGE_MESSAGE_SIZE + " bytes, got " + j, buffer.readable()); Assert.assertEquals("equal at " + j, ActiveMQTestBase.getSamplebyte(j), buffer.readByte()); } }
@Override public void decode(ActiveMQBuffer buffer) { SimpleString policyStr = buffer.readNullableSimpleString(); if (policyStr != null) { addressFullMessagePolicy = AddressFullMessagePolicy.valueOf(policyStr.toString()); } else { addressFullMessagePolicy = null; } maxSizeBytes = BufferHelper.readNullableLong(buffer); pageSizeBytes = BufferHelper.readNullableLong(buffer); pageMaxCache = BufferHelper.readNullableInteger(buffer); dropMessagesWhenFull = BufferHelper.readNullableBoolean(buffer); maxDeliveryAttempts = BufferHelper.readNullableInteger(buffer); messageCounterHistoryDayLimit = BufferHelper.readNullableInteger(buffer); redeliveryDelay = BufferHelper.readNullableLong(buffer); redeliveryMultiplier = BufferHelper.readNullableDouble(buffer); maxRedeliveryDelay = BufferHelper.readNullableLong(buffer); deadLetterAddress = buffer.readNullableSimpleString(); expiryAddress = buffer.readNullableSimpleString(); expiryDelay = BufferHelper.readNullableLong(buffer); lastValueQueue = BufferHelper.readNullableBoolean(buffer); redistributionDelay = BufferHelper.readNullableLong(buffer); sendToDLAOnNoRoute = BufferHelper.readNullableBoolean(buffer); slowConsumerThreshold = BufferHelper.readNullableLong(buffer); slowConsumerCheckPeriod = BufferHelper.readNullableLong(buffer); policyStr = buffer.readNullableSimpleString(); if (policyStr != null) { slowConsumerPolicy = SlowConsumerPolicy.valueOf(policyStr.toString()); } else { slowConsumerPolicy = null; } autoCreateJmsQueues = BufferHelper.readNullableBoolean(buffer); autoDeleteJmsQueues = BufferHelper.readNullableBoolean(buffer); }
@Override public void encodeRest(final ActiveMQBuffer buffer) { buffer.writeByte(journalID); buffer.writeBoolean(operation.toBoolean()); buffer.writeLong(id); buffer.writeByte(journalRecordType); buffer.writeInt(encodingData.getEncodeSize()); encodingData.encode(buffer); }
@Test public void testCreateBuffer() throws Exception { EmbeddedChannel channel = createChannel(); NettyConnection conn = new NettyConnection(emptyMap, channel, new MyListener(), false, false); final int size = 1234; ActiveMQBuffer buff = conn.createTransportBuffer(size); buff.writeByte((byte) 0x00); // Netty buffer does lazy initialization. Assert.assertEquals(size, buff.capacity()); }
@Override public void handshake(NettyServerConnection connection, ActiveMQBuffer buffer) { // if we are not an old client then handshake if (buffer.getByte(0) == 'A' && buffer.getByte(1) == 'R' && buffer.getByte(2) == 'T' && buffer.getByte(3) == 'E' && buffer.getByte(4) == 'M' && buffer.getByte(5) == 'I' && buffer.getByte(6) == 'S') { // todo add some handshaking buffer.readBytes(7); } }
@Override public void encode(ActiveMQBuffer buffer) { buffer.writeNullableSimpleString( addressFullMessagePolicy != null ? new SimpleString(addressFullMessagePolicy.toString()) : null); BufferHelper.writeNullableLong(buffer, maxSizeBytes); BufferHelper.writeNullableLong(buffer, pageSizeBytes); BufferHelper.writeNullableInteger(buffer, pageMaxCache); BufferHelper.writeNullableBoolean(buffer, dropMessagesWhenFull); BufferHelper.writeNullableInteger(buffer, maxDeliveryAttempts); BufferHelper.writeNullableInteger(buffer, messageCounterHistoryDayLimit); BufferHelper.writeNullableLong(buffer, redeliveryDelay); BufferHelper.writeNullableDouble(buffer, redeliveryMultiplier); BufferHelper.writeNullableLong(buffer, maxRedeliveryDelay); buffer.writeNullableSimpleString(deadLetterAddress); buffer.writeNullableSimpleString(expiryAddress); BufferHelper.writeNullableLong(buffer, expiryDelay); BufferHelper.writeNullableBoolean(buffer, lastValueQueue); BufferHelper.writeNullableLong(buffer, redistributionDelay); BufferHelper.writeNullableBoolean(buffer, sendToDLAOnNoRoute); BufferHelper.writeNullableLong(buffer, slowConsumerThreshold); BufferHelper.writeNullableLong(buffer, slowConsumerCheckPeriod); buffer.writeNullableSimpleString( slowConsumerPolicy != null ? new SimpleString(slowConsumerPolicy.toString()) : null); BufferHelper.writeNullableBoolean(buffer, autoCreateJmsQueues); BufferHelper.writeNullableBoolean(buffer, autoDeleteJmsQueues); }
// This is called periodically to flush the batch buffer public void checkFlushBatchBuffer() { if (!batchingEnabled) { return; } if (writeLock.tryAcquire()) { try { if (batchBuffer != null && batchBuffer.readable()) { channel.writeAndFlush(batchBuffer.byteBuf()); batchBuffer = createTransportBuffer(BATCHING_BUFFER_SIZE); } } finally { writeLock.release(); } } }
@Benchmark public int encodeUnalignedWithGarbage() { outBuffer.clear(); final JournalAddRecord addRecord = new JournalAddRecord(true, 1, (byte) 1, ZeroEncodingSupport.Instance); addRecord.setFileID(1); addRecord.setCompactCount((short) 1); addRecord.encode(outBuffer); return addRecord.getEncodeSize(); }
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 } }
@Override public void decodeRest(final ActiveMQBuffer buffer) { journalID = buffer.readByte(); operation = ADD_OPERATION_TYPE.toOperation(buffer.readBoolean()); id = buffer.readLong(); journalRecordType = buffer.readByte(); final int recordDataSize = buffer.readInt(); recordData = new byte[recordDataSize]; buffer.readBytes(recordData); }
public StompFrame decode(ActiveMQBuffer buffer) throws ActiveMQStompException { StompFrame frame = null; try { frame = frameHandler.decode(buffer); } catch (ActiveMQStompException e) { switch (e.getCode()) { case ActiveMQStompException.INVALID_EOL_V10: if (version != null) throw e; frameHandler = new StompFrameHandlerV12(this); buffer.resetReaderIndex(); frame = decode(buffer); break; case ActiveMQStompException.INVALID_COMMAND: frameHandler.onError(e); break; default: throw e; } } return frame; }
public ActiveMQBuffer encode(final RemotingConnection connection) { ActiveMQBuffer buffer = connection.createTransportBuffer(PacketImpl.INITIAL_PACKET_SIZE); // The standard header fields buffer.writeInt(0); // The length gets filled in at the end buffer.writeByte(type); buffer.writeLong(channelID); encodeRest(buffer); size = buffer.writerIndex(); // The length doesn't include the actual length byte int len = size - DataConstants.SIZE_INT; buffer.setInt(0, len); return buffer; }
@Override public ServerMessage inbound(Object message) throws Exception { Message messageSend = (Message) message; ServerMessageImpl coreMessage = new ServerMessageImpl(-1, messageSend.getSize()); String type = messageSend.getType(); if (type != null) { coreMessage.putStringProperty(new SimpleString("JMSType"), new SimpleString(type)); } coreMessage.setDurable(messageSend.isPersistent()); coreMessage.setExpiration(messageSend.getExpiration()); coreMessage.setPriority(messageSend.getPriority()); coreMessage.setTimestamp(messageSend.getTimestamp()); byte coreType = toCoreType(messageSend.getDataStructureType()); coreMessage.setType(coreType); ActiveMQBuffer body = coreMessage.getBodyBuffer(); ByteSequence contents = messageSend.getContent(); if (contents == null && coreType == org.apache.activemq.artemis.api.core.Message.TEXT_TYPE) { body.writeNullableString(null); } else if (contents != null) { boolean messageCompressed = messageSend.isCompressed(); if (messageCompressed) { coreMessage.putBooleanProperty(AMQ_MSG_COMPRESSED, messageCompressed); } switch (coreType) { case org.apache.activemq.artemis.api.core.Message.TEXT_TYPE: InputStream tis = new ByteArrayInputStream(contents); if (messageCompressed) { tis = new InflaterInputStream(tis); } DataInputStream tdataIn = new DataInputStream(tis); String text = MarshallingSupport.readUTF8(tdataIn); tdataIn.close(); body.writeNullableSimpleString(new SimpleString(text)); break; case org.apache.activemq.artemis.api.core.Message.MAP_TYPE: InputStream mis = new ByteArrayInputStream(contents); if (messageCompressed) { mis = new InflaterInputStream(mis); } DataInputStream mdataIn = new DataInputStream(mis); Map<String, Object> map = MarshallingSupport.unmarshalPrimitiveMap(mdataIn); mdataIn.close(); TypedProperties props = new TypedProperties(); loadMapIntoProperties(props, map); props.encode(body); break; case org.apache.activemq.artemis.api.core.Message.OBJECT_TYPE: if (messageCompressed) { try (InputStream ois = new InflaterInputStream(new ByteArrayInputStream(contents)); org.apache.activemq.util.ByteArrayOutputStream decompressed = new org.apache.activemq.util.ByteArrayOutputStream()) { byte[] buf = new byte[1024]; int n = ois.read(buf); while (n != -1) { decompressed.write(buf, 0, n); n = ois.read(); } // read done contents = decompressed.toByteSequence(); } } body.writeInt(contents.length); body.writeBytes(contents.data, contents.offset, contents.length); break; case org.apache.activemq.artemis.api.core.Message.STREAM_TYPE: InputStream sis = new ByteArrayInputStream(contents); if (messageCompressed) { sis = new InflaterInputStream(sis); } DataInputStream sdis = new DataInputStream(sis); int stype = sdis.read(); while (stype != -1) { switch (stype) { case MarshallingSupport.BOOLEAN_TYPE: body.writeByte(DataConstants.BOOLEAN); body.writeBoolean(sdis.readBoolean()); break; case MarshallingSupport.BYTE_TYPE: body.writeByte(DataConstants.BYTE); body.writeByte(sdis.readByte()); break; case MarshallingSupport.BYTE_ARRAY_TYPE: body.writeByte(DataConstants.BYTES); int slen = sdis.readInt(); byte[] sbytes = new byte[slen]; sdis.read(sbytes); body.writeInt(slen); body.writeBytes(sbytes); break; case MarshallingSupport.CHAR_TYPE: body.writeByte(DataConstants.CHAR); char schar = sdis.readChar(); body.writeShort((short) schar); break; case MarshallingSupport.DOUBLE_TYPE: body.writeByte(DataConstants.DOUBLE); double sdouble = sdis.readDouble(); body.writeLong(Double.doubleToLongBits(sdouble)); break; case MarshallingSupport.FLOAT_TYPE: body.writeByte(DataConstants.FLOAT); float sfloat = sdis.readFloat(); body.writeInt(Float.floatToIntBits(sfloat)); break; case MarshallingSupport.INTEGER_TYPE: body.writeByte(DataConstants.INT); body.writeInt(sdis.readInt()); break; case MarshallingSupport.LONG_TYPE: body.writeByte(DataConstants.LONG); body.writeLong(sdis.readLong()); break; case MarshallingSupport.SHORT_TYPE: body.writeByte(DataConstants.SHORT); body.writeShort(sdis.readShort()); break; case MarshallingSupport.STRING_TYPE: body.writeByte(DataConstants.STRING); String sstring = sdis.readUTF(); body.writeNullableString(sstring); break; case MarshallingSupport.BIG_STRING_TYPE: body.writeByte(DataConstants.STRING); String sbigString = MarshallingSupport.readUTF8(sdis); body.writeNullableString(sbigString); break; case MarshallingSupport.NULL: body.writeByte(DataConstants.STRING); body.writeNullableString(null); break; default: // something we don't know, ignore break; } stype = sdis.read(); } sdis.close(); break; case org.apache.activemq.artemis.api.core.Message.BYTES_TYPE: if (messageCompressed) { Inflater inflater = new Inflater(); try (org.apache.activemq.util.ByteArrayOutputStream decompressed = new org.apache.activemq.util.ByteArrayOutputStream()) { int length = ByteSequenceData.readIntBig(contents); contents.offset = 0; byte[] data = Arrays.copyOfRange(contents.getData(), 4, contents.getLength()); inflater.setInput(data); byte[] buffer = new byte[length]; int count = inflater.inflate(buffer); decompressed.write(buffer, 0, count); contents = decompressed.toByteSequence(); } catch (Exception e) { throw new IOException(e); } finally { inflater.end(); } } body.writeBytes(contents.data, contents.offset, contents.length); break; default: if (messageCompressed) { try (org.apache.activemq.util.ByteArrayOutputStream decompressed = new org.apache.activemq.util.ByteArrayOutputStream(); OutputStream os = new InflaterOutputStream(decompressed)) { os.write(contents.data, contents.offset, contents.getLength()); contents = decompressed.toByteSequence(); } catch (Exception e) { throw new IOException(e); } } body.writeBytes(contents.data, contents.offset, contents.length); break; } } // amq specific coreMessage.putLongProperty(AMQ_MSG_ARRIVAL, messageSend.getArrival()); coreMessage.putLongProperty(AMQ_MSG_BROKER_IN_TIME, messageSend.getBrokerInTime()); BrokerId[] brokers = messageSend.getBrokerPath(); if (brokers != null) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < brokers.length; i++) { builder.append(brokers[i].getValue()); if (i != (brokers.length - 1)) { builder.append(","); // is this separator safe? } } coreMessage.putStringProperty(AMQ_MSG_BROKER_PATH, builder.toString()); } BrokerId[] cluster = messageSend.getCluster(); if (cluster != null) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < cluster.length; i++) { builder.append(cluster[i].getValue()); if (i != (cluster.length - 1)) { builder.append(","); // is this separator safe? } } coreMessage.putStringProperty(AMQ_MSG_CLUSTER, builder.toString()); } coreMessage.putIntProperty(AMQ_MSG_COMMAND_ID, messageSend.getCommandId()); String corrId = messageSend.getCorrelationId(); if (corrId != null) { coreMessage.putStringProperty("JMSCorrelationID", corrId); } DataStructure ds = messageSend.getDataStructure(); if (ds != null) { ByteSequence dsBytes = marshaller.marshal(ds); dsBytes.compact(); coreMessage.putBytesProperty(AMQ_MSG_DATASTRUCTURE, dsBytes.data); } String groupId = messageSend.getGroupID(); if (groupId != null) { coreMessage.putStringProperty(AMQ_MSG_GROUP_ID, groupId); } coreMessage.putIntProperty(AMQ_MSG_GROUP_SEQUENCE, messageSend.getGroupSequence()); MessageId messageId = messageSend.getMessageId(); ByteSequence midBytes = marshaller.marshal(messageId); midBytes.compact(); coreMessage.putBytesProperty(AMQ_MSG_MESSAGE_ID, midBytes.data); ProducerId producerId = messageSend.getProducerId(); if (producerId != null) { ByteSequence producerIdBytes = marshaller.marshal(producerId); producerIdBytes.compact(); coreMessage.putBytesProperty(AMQ_MSG_PRODUCER_ID, producerIdBytes.data); } ByteSequence propBytes = messageSend.getMarshalledProperties(); if (propBytes != null) { propBytes.compact(); coreMessage.putBytesProperty(AMQ_MSG_MARSHALL_PROP, propBytes.data); // unmarshall properties to core so selector will work Map<String, Object> props = messageSend.getProperties(); // Map<String, Object> props = MarshallingSupport.unmarshalPrimitiveMap(new // DataInputStream(new ByteArrayInputStream(propBytes))); for (Entry<String, Object> ent : props.entrySet()) { Object value = ent.getValue(); try { coreMessage.putObjectProperty(ent.getKey(), value); } catch (ActiveMQPropertyConversionException e) { coreMessage.putStringProperty(ent.getKey(), value.toString()); } } } ActiveMQDestination replyTo = messageSend.getReplyTo(); if (replyTo != null) { ByteSequence replyToBytes = marshaller.marshal(replyTo); replyToBytes.compact(); coreMessage.putBytesProperty(AMQ_MSG_REPLY_TO, replyToBytes.data); } ConsumerId consumerId = messageSend.getTargetConsumerId(); String userId = messageSend.getUserID(); if (userId != null) { coreMessage.putStringProperty(AMQ_MSG_USER_ID, userId); } coreMessage.putBooleanProperty(AMQ_MSG_DROPPABLE, messageSend.isDroppable()); ActiveMQDestination origDest = messageSend.getOriginalDestination(); if (origDest != null) { ByteSequence origDestBytes = marshaller.marshal(origDest); origDestBytes.compact(); coreMessage.putBytesProperty(AMQ_MSG_ORIG_DESTINATION, origDestBytes.data); } return coreMessage; }
@Override public void decodeRest(final ActiveMQBuffer buffer) { liveStopping = buffer.readInt() == 0 ? LiveStopping.STOP_CALLED : LiveStopping.FAIL_OVER; }
@Override public void encodeRest(final ActiveMQBuffer buffer) { buffer.writeInt(liveStopping.code); }
public static ActiveMQBuffer toActiveMQBuffer(ByteSequence bytes) { ActiveMQBuffer buffer = ActiveMQBuffers.fixedBuffer(bytes.length); buffer.writeBytes(bytes.data, bytes.offset, bytes.length); return buffer; }
@Override public void decodeRest(final ActiveMQBuffer buffer) { name = buffer.readString(); lastConfirmedCommandID = buffer.readInt(); }
@Override public void encodeRest(final ActiveMQBuffer buffer) { buffer.writeString(name); buffer.writeInt(lastConfirmedCommandID); }
@Override public void encodeRest(ActiveMQBuffer buffer) { buffer.writeSimpleString(targetNodeId); buffer.writeSimpleString(scaledDownNodeId); }
@Override public void decodeRest(ActiveMQBuffer buffer) { targetNodeId = buffer.readSimpleString(); scaledDownNodeId = buffer.readSimpleString(); }
@Benchmark public int encodeUnaligned() { outBuffer.clear(); record.encode(outBuffer); return record.getEncodeSize(); }
private void manualEncodeVertxMessageBody(ActiveMQBuffer bodyBuffer, Object body, int type) { switch (type) { case VertxConstants.TYPE_BOOLEAN: bodyBuffer.writeBoolean(((Boolean) body)); break; case VertxConstants.TYPE_BUFFER: Buffer buff = (Buffer) body; int len = buff.length(); bodyBuffer.writeInt(len); bodyBuffer.writeBytes(((Buffer) body).getBytes()); break; case VertxConstants.TYPE_BYTEARRAY: byte[] bytes = (byte[]) body; bodyBuffer.writeInt(bytes.length); bodyBuffer.writeBytes(bytes); break; case VertxConstants.TYPE_BYTE: bodyBuffer.writeByte((byte) body); break; case VertxConstants.TYPE_CHARACTER: bodyBuffer.writeChar((Character) body); break; case VertxConstants.TYPE_DOUBLE: bodyBuffer.writeDouble((double) body); break; case VertxConstants.TYPE_FLOAT: bodyBuffer.writeFloat((Float) body); break; case VertxConstants.TYPE_INT: bodyBuffer.writeInt((Integer) body); break; case VertxConstants.TYPE_LONG: bodyBuffer.writeLong((Long) body); break; case VertxConstants.TYPE_SHORT: bodyBuffer.writeShort((Short) body); break; case VertxConstants.TYPE_STRING: case VertxConstants.TYPE_PING: bodyBuffer.writeString((String) body); break; case VertxConstants.TYPE_JSON_OBJECT: bodyBuffer.writeString(((JsonObject) body).encode()); break; case VertxConstants.TYPE_JSON_ARRAY: bodyBuffer.writeString(((JsonArray) body).encode()); break; case VertxConstants.TYPE_REPLY_FAILURE: ReplyException except = (ReplyException) body; bodyBuffer.writeInt(except.failureType().toInt()); bodyBuffer.writeInt(except.failureCode()); bodyBuffer.writeString(except.getMessage()); break; default: throw new IllegalArgumentException("Invalid body type: " + type); } }
public void write( ActiveMQBuffer buffer, final boolean flush, final boolean batched, final ChannelFutureListener futureListener) { try { writeLock.acquire(); try { if (batchBuffer == null && batchingEnabled && batched && !flush) { // Lazily create batch buffer batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE); } if (batchBuffer != null) { batchBuffer.writeBytes(buffer, 0, buffer.writerIndex()); if (batchBuffer.writerIndex() >= BATCHING_BUFFER_SIZE || !batched || flush) { // If the batch buffer is full or it's flush param or not batched then flush the buffer buffer = batchBuffer; } else { return; } if (!batched || flush) { batchBuffer = null; } else { // Create a new buffer batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE); } } // depending on if we need to flush or not we can use a voidPromise or // use a normal promise final ByteBuf buf = buffer.byteBuf(); final ChannelPromise promise; if (flush || futureListener != null) { promise = channel.newPromise(); } else { promise = channel.voidPromise(); } EventLoop eventLoop = channel.eventLoop(); boolean inEventLoop = eventLoop.inEventLoop(); if (!inEventLoop) { if (futureListener != null) { channel.writeAndFlush(buf, promise).addListener(futureListener); } else { channel.writeAndFlush(buf, promise); } } else { // create a task which will be picked up by the eventloop and trigger the write. // This is mainly needed as this method is triggered by different threads for the same // channel. // if we not do this we may produce out of order writes. final Runnable task = new Runnable() { @Override public void run() { if (futureListener != null) { channel.writeAndFlush(buf, promise).addListener(futureListener); } else { channel.writeAndFlush(buf, promise); } } }; // execute the task on the eventloop eventLoop.execute(task); } // only try to wait if not in the eventloop otherwise we will produce a deadlock if (flush && !inEventLoop) { while (true) { try { boolean ok = promise.await(10000); if (!ok) { ActiveMQClientLogger.LOGGER.timeoutFlushingPacket(); } break; } catch (InterruptedException e) { throw new ActiveMQInterruptedException(e); } } } } finally { writeLock.release(); } } catch (InterruptedException e) { throw new ActiveMQInterruptedException(e); } }
private static ActiveMQMessage toAMQMessage( MessageReference reference, ServerMessage coreMessage, WireFormat marshaller, ActiveMQDestination actualDestination) throws IOException { ActiveMQMessage amqMsg = null; byte coreType = coreMessage.getType(); switch (coreType) { case org.apache.activemq.artemis.api.core.Message.BYTES_TYPE: amqMsg = new ActiveMQBytesMessage(); break; case org.apache.activemq.artemis.api.core.Message.MAP_TYPE: amqMsg = new ActiveMQMapMessage(); break; case org.apache.activemq.artemis.api.core.Message.OBJECT_TYPE: amqMsg = new ActiveMQObjectMessage(); break; case org.apache.activemq.artemis.api.core.Message.STREAM_TYPE: amqMsg = new ActiveMQStreamMessage(); break; case org.apache.activemq.artemis.api.core.Message.TEXT_TYPE: amqMsg = new ActiveMQTextMessage(); break; case org.apache.activemq.artemis.api.core.Message.DEFAULT_TYPE: amqMsg = new ActiveMQMessage(); break; default: throw new IllegalStateException("Unknown message type: " + coreMessage.getType()); } String type = coreMessage.getStringProperty(new SimpleString("JMSType")); if (type != null) { amqMsg.setJMSType(type); } amqMsg.setPersistent(coreMessage.isDurable()); amqMsg.setExpiration(coreMessage.getExpiration()); amqMsg.setPriority(coreMessage.getPriority()); amqMsg.setTimestamp(coreMessage.getTimestamp()); Long brokerInTime = (Long) coreMessage.getObjectProperty(AMQ_MSG_BROKER_IN_TIME); if (brokerInTime == null) { brokerInTime = 0L; } amqMsg.setBrokerInTime(brokerInTime); ActiveMQBuffer buffer = coreMessage.getBodyBufferDuplicate(); Boolean compressProp = (Boolean) coreMessage.getObjectProperty(AMQ_MSG_COMPRESSED); boolean isCompressed = compressProp == null ? false : compressProp.booleanValue(); amqMsg.setCompressed(isCompressed); if (buffer != null) { buffer.resetReaderIndex(); byte[] bytes = null; synchronized (buffer) { if (coreType == org.apache.activemq.artemis.api.core.Message.TEXT_TYPE) { SimpleString text = buffer.readNullableSimpleString(); if (text != null) { ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(text.length() + 4); OutputStream out = bytesOut; if (isCompressed) { out = new DeflaterOutputStream(out); } try (DataOutputStream dataOut = new DataOutputStream(out)) { MarshallingSupport.writeUTF8(dataOut, text.toString()); bytes = bytesOut.toByteArray(); } } } else if (coreType == org.apache.activemq.artemis.api.core.Message.MAP_TYPE) { TypedProperties mapData = new TypedProperties(); // it could be a null map if (buffer.readableBytes() > 0) { mapData.decode(buffer); Map<String, Object> map = mapData.getMap(); ByteArrayOutputStream out = new ByteArrayOutputStream(mapData.getEncodeSize()); OutputStream os = out; if (isCompressed) { os = new DeflaterOutputStream(os); } try (DataOutputStream dataOut = new DataOutputStream(os)) { MarshallingSupport.marshalPrimitiveMap(map, dataOut); } bytes = out.toByteArray(); } } else if (coreType == org.apache.activemq.artemis.api.core.Message.OBJECT_TYPE) { int len = buffer.readInt(); bytes = new byte[len]; buffer.readBytes(bytes); if (isCompressed) { ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); try (DeflaterOutputStream out = new DeflaterOutputStream(bytesOut)) { out.write(bytes); } bytes = bytesOut.toByteArray(); } } else if (coreType == org.apache.activemq.artemis.api.core.Message.STREAM_TYPE) { org.apache.activemq.util.ByteArrayOutputStream bytesOut = new org.apache.activemq.util.ByteArrayOutputStream(); OutputStream out = bytesOut; if (isCompressed) { out = new DeflaterOutputStream(bytesOut); } try (DataOutputStream dataOut = new DataOutputStream(out)) { boolean stop = false; while (!stop && buffer.readable()) { byte primitiveType = buffer.readByte(); switch (primitiveType) { case DataConstants.BOOLEAN: MarshallingSupport.marshalBoolean(dataOut, buffer.readBoolean()); break; case DataConstants.BYTE: MarshallingSupport.marshalByte(dataOut, buffer.readByte()); break; case DataConstants.BYTES: int len = buffer.readInt(); byte[] bytesData = new byte[len]; buffer.readBytes(bytesData); MarshallingSupport.marshalByteArray(dataOut, bytesData); break; case DataConstants.CHAR: char ch = (char) buffer.readShort(); MarshallingSupport.marshalChar(dataOut, ch); break; case DataConstants.DOUBLE: double doubleVal = Double.longBitsToDouble(buffer.readLong()); MarshallingSupport.marshalDouble(dataOut, doubleVal); break; case DataConstants.FLOAT: Float floatVal = Float.intBitsToFloat(buffer.readInt()); MarshallingSupport.marshalFloat(dataOut, floatVal); break; case DataConstants.INT: MarshallingSupport.marshalInt(dataOut, buffer.readInt()); break; case DataConstants.LONG: MarshallingSupport.marshalLong(dataOut, buffer.readLong()); break; case DataConstants.SHORT: MarshallingSupport.marshalShort(dataOut, buffer.readShort()); break; case DataConstants.STRING: String string = buffer.readNullableString(); if (string == null) { MarshallingSupport.marshalNull(dataOut); } else { MarshallingSupport.marshalString(dataOut, string); } break; default: // now we stop stop = true; break; } } } bytes = bytesOut.toByteArray(); } else if (coreType == org.apache.activemq.artemis.api.core.Message.BYTES_TYPE) { int n = buffer.readableBytes(); bytes = new byte[n]; buffer.readBytes(bytes); if (isCompressed) { int length = bytes.length; Deflater deflater = new Deflater(); try (org.apache.activemq.util.ByteArrayOutputStream compressed = new org.apache.activemq.util.ByteArrayOutputStream()) { compressed.write(new byte[4]); deflater.setInput(bytes); deflater.finish(); byte[] bytesBuf = new byte[1024]; while (!deflater.finished()) { int count = deflater.deflate(bytesBuf); compressed.write(bytesBuf, 0, count); } ByteSequence byteSeq = compressed.toByteSequence(); ByteSequenceData.writeIntBig(byteSeq, length); bytes = Arrays.copyOfRange(byteSeq.data, 0, byteSeq.length); } finally { deflater.end(); } } } else { int n = buffer.readableBytes(); bytes = new byte[n]; buffer.readBytes(bytes); if (isCompressed) { try (ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); DeflaterOutputStream out = new DeflaterOutputStream(bytesOut)) { out.write(bytes); bytes = bytesOut.toByteArray(); } } } buffer.resetReaderIndex(); // this is important for topics as the buffer // may be read multiple times } if (bytes != null) { ByteSequence content = new ByteSequence(bytes); amqMsg.setContent(content); } } // we need check null because messages may come from other clients // and those amq specific attribute may not be set. Long arrival = (Long) coreMessage.getObjectProperty(AMQ_MSG_ARRIVAL); if (arrival == null) { // messages from other sources (like core client) may not set this prop arrival = 0L; } amqMsg.setArrival(arrival); String brokerPath = (String) coreMessage.getObjectProperty(AMQ_MSG_BROKER_PATH); if (brokerPath != null && brokerPath.isEmpty()) { String[] brokers = brokerPath.split(","); BrokerId[] bids = new BrokerId[brokers.length]; for (int i = 0; i < bids.length; i++) { bids[i] = new BrokerId(brokers[i]); } amqMsg.setBrokerPath(bids); } String clusterPath = (String) coreMessage.getObjectProperty(AMQ_MSG_CLUSTER); if (clusterPath != null && clusterPath.isEmpty()) { String[] cluster = clusterPath.split(","); BrokerId[] bids = new BrokerId[cluster.length]; for (int i = 0; i < bids.length; i++) { bids[i] = new BrokerId(cluster[i]); } amqMsg.setCluster(bids); } Integer commandId = (Integer) coreMessage.getObjectProperty(AMQ_MSG_COMMAND_ID); if (commandId == null) { commandId = -1; } amqMsg.setCommandId(commandId); SimpleString corrId = (SimpleString) coreMessage.getObjectProperty("JMSCorrelationID"); if (corrId != null) { amqMsg.setCorrelationId(corrId.toString()); } byte[] dsBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_DATASTRUCTURE); if (dsBytes != null) { ByteSequence seq = new ByteSequence(dsBytes); DataStructure ds = (DataStructure) marshaller.unmarshal(seq); amqMsg.setDataStructure(ds); } amqMsg.setDestination(OpenWireUtil.toAMQAddress(coreMessage, actualDestination)); Object value = coreMessage.getObjectProperty(AMQ_MSG_GROUP_ID); if (value != null) { String groupId = value.toString(); amqMsg.setGroupID(groupId); } Integer groupSequence = (Integer) coreMessage.getObjectProperty(AMQ_MSG_GROUP_SEQUENCE); if (groupSequence == null) { groupSequence = -1; } amqMsg.setGroupSequence(groupSequence); MessageId mid = null; byte[] midBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_MESSAGE_ID); if (midBytes != null) { ByteSequence midSeq = new ByteSequence(midBytes); mid = (MessageId) marshaller.unmarshal(midSeq); } else { mid = new MessageId(UUIDGenerator.getInstance().generateStringUUID() + ":-1"); } amqMsg.setMessageId(mid); byte[] origDestBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_ORIG_DESTINATION); if (origDestBytes != null) { ActiveMQDestination origDest = (ActiveMQDestination) marshaller.unmarshal(new ByteSequence(origDestBytes)); amqMsg.setOriginalDestination(origDest); } byte[] origTxIdBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_ORIG_TXID); if (origTxIdBytes != null) { TransactionId origTxId = (TransactionId) marshaller.unmarshal(new ByteSequence(origTxIdBytes)); amqMsg.setOriginalTransactionId(origTxId); } byte[] producerIdBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_PRODUCER_ID); if (producerIdBytes != null) { ProducerId producerId = (ProducerId) marshaller.unmarshal(new ByteSequence(producerIdBytes)); amqMsg.setProducerId(producerId); } byte[] marshalledBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_MARSHALL_PROP); if (marshalledBytes != null) { amqMsg.setMarshalledProperties(new ByteSequence(marshalledBytes)); } amqMsg.setRedeliveryCounter(reference.getDeliveryCount() - 1); byte[] replyToBytes = (byte[]) coreMessage.getObjectProperty(AMQ_MSG_REPLY_TO); if (replyToBytes != null) { ActiveMQDestination replyTo = (ActiveMQDestination) marshaller.unmarshal(new ByteSequence(replyToBytes)); amqMsg.setReplyTo(replyTo); } String userId = (String) coreMessage.getObjectProperty(AMQ_MSG_USER_ID); if (userId != null) { amqMsg.setUserID(userId); } Boolean isDroppable = (Boolean) coreMessage.getObjectProperty(AMQ_MSG_DROPPABLE); if (isDroppable != null) { amqMsg.setDroppable(isDroppable); } SimpleString dlqCause = (SimpleString) coreMessage.getObjectProperty(AMQ_MSG_DLQ_DELIVERY_FAILURE_CAUSE_PROPERTY); if (dlqCause != null) { try { amqMsg.setStringProperty( ActiveMQMessage.DLQ_DELIVERY_FAILURE_CAUSE_PROPERTY, dlqCause.toString()); } catch (JMSException e) { throw new IOException("failure to set dlq property " + dlqCause, e); } } Set<SimpleString> props = coreMessage.getPropertyNames(); if (props != null) { for (SimpleString s : props) { String keyStr = s.toString(); if (keyStr.startsWith("_AMQ") || keyStr.startsWith("__HDR_")) { continue; } Object prop = coreMessage.getObjectProperty(s); try { if (prop instanceof SimpleString) { amqMsg.setObjectProperty(s.toString(), prop.toString()); } else { amqMsg.setObjectProperty(s.toString(), prop); } } catch (JMSException e) { throw new IOException("exception setting property " + s + " : " + prop, e); } } } try { amqMsg.onSend(); amqMsg.setCompressed(isCompressed); } catch (JMSException e) { throw new IOException("Failed to covert to Openwire message", e); } return amqMsg; }