use of org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage in project activemq-artemis by apache.
the class ServerSessionPacketHandler method slowPacketHandler.
// This is being separated from onMessagePacket as JIT was more efficient with a small method for the
// hot executions.
private void slowPacketHandler(final Packet packet) {
final byte type = packet.getType();
storageManager.setContext(session.getSessionContext());
Packet response = null;
boolean flush = false;
boolean closeChannel = false;
boolean requiresResponse = false;
try {
try {
switch(type) {
case SESS_SEND_LARGE:
{
SessionSendLargeMessage message = (SessionSendLargeMessage) packet;
sendLarge(message.getLargeMessage());
break;
}
case SESS_SEND_CONTINUATION:
{
SessionSendContinuationMessage message = (SessionSendContinuationMessage) packet;
requiresResponse = message.isRequiresResponse();
sendContinuations(message.getPacketSize(), message.getMessageBodySize(), message.getBody(), message.isContinues());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case SESS_CREATECONSUMER:
{
SessionCreateConsumerMessage request = (SessionCreateConsumerMessage) packet;
requiresResponse = request.isRequiresResponse();
session.createConsumer(request.getID(), request.getQueueName(), request.getFilterString(), request.isBrowseOnly());
if (requiresResponse) {
// We send back queue information on the queue as a response- this allows the queue to
// be automatically recreated on failover
QueueQueryResult queueQueryResult = session.executeQueueQuery(request.getQueueName());
if (channel.supports(PacketImpl.SESS_QUEUEQUERY_RESP_V3)) {
response = new SessionQueueQueryResponseMessage_V3(queueQueryResult);
} else if (channel.supports(PacketImpl.SESS_QUEUEQUERY_RESP_V2)) {
response = new SessionQueueQueryResponseMessage_V2(queueQueryResult);
} else {
response = new SessionQueueQueryResponseMessage(queueQueryResult);
}
}
break;
}
case CREATE_ADDRESS:
{
CreateAddressMessage request = (CreateAddressMessage) packet;
requiresResponse = request.isRequiresResponse();
session.createAddress(request.getAddress(), request.getRoutingTypes(), request.isAutoCreated());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case CREATE_QUEUE:
{
CreateQueueMessage request = (CreateQueueMessage) packet;
requiresResponse = request.isRequiresResponse();
session.createQueue(request.getAddress(), request.getQueueName(), RoutingType.MULTICAST, request.getFilterString(), request.isTemporary(), request.isDurable());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case CREATE_QUEUE_V2:
{
CreateQueueMessage_V2 request = (CreateQueueMessage_V2) packet;
requiresResponse = request.isRequiresResponse();
session.createQueue(request.getAddress(), request.getQueueName(), request.getRoutingType(), request.getFilterString(), request.isTemporary(), request.isDurable(), request.getMaxConsumers(), request.isPurgeOnNoConsumers(), request.isExclusive(), request.isLastValue(), request.isAutoCreated());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case CREATE_SHARED_QUEUE:
{
CreateSharedQueueMessage request = (CreateSharedQueueMessage) packet;
requiresResponse = request.isRequiresResponse();
session.createSharedQueue(request.getAddress(), request.getQueueName(), request.isDurable(), request.getFilterString());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case CREATE_SHARED_QUEUE_V2:
{
CreateSharedQueueMessage_V2 request = (CreateSharedQueueMessage_V2) packet;
requiresResponse = request.isRequiresResponse();
session.createSharedQueue(request.getAddress(), request.getQueueName(), request.getRoutingType(), request.getFilterString(), request.isDurable(), request.getMaxConsumers(), request.isPurgeOnNoConsumers(), request.isExclusive(), request.isLastValue());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case DELETE_QUEUE:
{
requiresResponse = true;
SessionDeleteQueueMessage request = (SessionDeleteQueueMessage) packet;
session.deleteQueue(request.getQueueName());
response = new NullResponseMessage();
break;
}
case SESS_QUEUEQUERY:
{
requiresResponse = true;
SessionQueueQueryMessage request = (SessionQueueQueryMessage) packet;
QueueQueryResult result = session.executeQueueQuery(request.getQueueName());
if (result.isExists() && remotingConnection.getChannelVersion() < PacketImpl.ADDRESSING_CHANGE_VERSION) {
result.setAddress(SessionQueueQueryMessage.getOldPrefixedAddress(result.getAddress(), result.getRoutingType()));
}
if (channel.supports(PacketImpl.SESS_QUEUEQUERY_RESP_V3)) {
response = new SessionQueueQueryResponseMessage_V3(result);
} else if (channel.supports(PacketImpl.SESS_QUEUEQUERY_RESP_V2)) {
response = new SessionQueueQueryResponseMessage_V2(result);
} else {
response = new SessionQueueQueryResponseMessage(result);
}
break;
}
case SESS_BINDINGQUERY:
{
requiresResponse = true;
SessionBindingQueryMessage request = (SessionBindingQueryMessage) packet;
final int clientVersion = remotingConnection.getChannelVersion();
BindingQueryResult result = session.executeBindingQuery(request.getAddress());
/* if the session is JMS and it's from an older client then we need to add the old prefix to the queue
* names otherwise the older client won't realize the queue exists and will try to create it and receive
* an error
*/
if (result.isExists() && clientVersion < PacketImpl.ADDRESSING_CHANGE_VERSION && session.getMetaData(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY) != null) {
final List<SimpleString> queueNames = result.getQueueNames();
if (!queueNames.isEmpty()) {
final List<SimpleString> convertedQueueNames = request.convertQueueNames(clientVersion, queueNames);
if (convertedQueueNames != queueNames) {
result = new BindingQueryResult(result.isExists(), result.getAddressInfo(), convertedQueueNames, result.isAutoCreateQueues(), result.isAutoCreateAddresses(), result.isDefaultPurgeOnNoConsumers(), result.getDefaultMaxConsumers(), result.isDefaultExclusive(), result.isDefaultLastValue());
}
}
}
if (channel.supports(PacketImpl.SESS_BINDINGQUERY_RESP_V4)) {
response = new SessionBindingQueryResponseMessage_V4(result.isExists(), result.getQueueNames(), result.isAutoCreateQueues(), result.isAutoCreateAddresses(), result.isDefaultPurgeOnNoConsumers(), result.getDefaultMaxConsumers(), result.isDefaultExclusive(), result.isDefaultLastValue());
} else if (channel.supports(PacketImpl.SESS_BINDINGQUERY_RESP_V3)) {
response = new SessionBindingQueryResponseMessage_V3(result.isExists(), result.getQueueNames(), result.isAutoCreateQueues(), result.isAutoCreateAddresses());
} else if (channel.supports(PacketImpl.SESS_BINDINGQUERY_RESP_V2)) {
response = new SessionBindingQueryResponseMessage_V2(result.isExists(), result.getQueueNames(), result.isAutoCreateQueues());
} else {
response = new SessionBindingQueryResponseMessage(result.isExists(), result.getQueueNames());
}
break;
}
case SESS_EXPIRED:
{
SessionExpireMessage message = (SessionExpireMessage) packet;
session.expire(message.getConsumerID(), message.getMessageID());
break;
}
case SESS_COMMIT:
{
requiresResponse = true;
session.commit();
response = new NullResponseMessage();
break;
}
case SESS_ROLLBACK:
{
requiresResponse = true;
session.rollback(((RollbackMessage) packet).isConsiderLastMessageAsDelivered());
response = new NullResponseMessage();
break;
}
case SESS_XA_COMMIT:
{
requiresResponse = true;
SessionXACommitMessage message = (SessionXACommitMessage) packet;
session.xaCommit(message.getXid(), message.isOnePhase());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_END:
{
requiresResponse = true;
SessionXAEndMessage message = (SessionXAEndMessage) packet;
session.xaEnd(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_FORGET:
{
requiresResponse = true;
SessionXAForgetMessage message = (SessionXAForgetMessage) packet;
session.xaForget(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_JOIN:
{
requiresResponse = true;
SessionXAJoinMessage message = (SessionXAJoinMessage) packet;
session.xaJoin(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_RESUME:
{
requiresResponse = true;
SessionXAResumeMessage message = (SessionXAResumeMessage) packet;
session.xaResume(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_ROLLBACK:
{
requiresResponse = true;
SessionXARollbackMessage message = (SessionXARollbackMessage) packet;
session.xaRollback(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_START:
{
requiresResponse = true;
SessionXAStartMessage message = (SessionXAStartMessage) packet;
session.xaStart(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_FAILED:
{
requiresResponse = true;
SessionXAAfterFailedMessage message = (SessionXAAfterFailedMessage) packet;
session.xaFailed(message.getXid());
// no response on this case
break;
}
case SESS_XA_SUSPEND:
{
requiresResponse = true;
session.xaSuspend();
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_PREPARE:
{
requiresResponse = true;
SessionXAPrepareMessage message = (SessionXAPrepareMessage) packet;
session.xaPrepare(message.getXid());
response = new SessionXAResponseMessage(false, XAResource.XA_OK, null);
break;
}
case SESS_XA_INDOUBT_XIDS:
{
requiresResponse = true;
List<Xid> xids = session.xaGetInDoubtXids();
response = new SessionXAGetInDoubtXidsResponseMessage(xids);
break;
}
case SESS_XA_GET_TIMEOUT:
{
requiresResponse = true;
int timeout = session.xaGetTimeout();
response = new SessionXAGetTimeoutResponseMessage(timeout);
break;
}
case SESS_XA_SET_TIMEOUT:
{
requiresResponse = true;
SessionXASetTimeoutMessage message = (SessionXASetTimeoutMessage) packet;
session.xaSetTimeout(message.getTimeoutSeconds());
response = new SessionXASetTimeoutResponseMessage(true);
break;
}
case SESS_START:
{
session.start();
break;
}
case SESS_STOP:
{
requiresResponse = true;
session.stop();
response = new NullResponseMessage();
break;
}
case SESS_CLOSE:
{
requiresResponse = true;
session.close(false);
// removeConnectionListeners();
response = new NullResponseMessage();
flush = true;
closeChannel = true;
break;
}
case SESS_INDIVIDUAL_ACKNOWLEDGE:
{
SessionIndividualAcknowledgeMessage message = (SessionIndividualAcknowledgeMessage) packet;
requiresResponse = message.isRequiresResponse();
session.individualAcknowledge(message.getConsumerID(), message.getMessageID());
if (requiresResponse) {
response = new NullResponseMessage();
}
break;
}
case SESS_CONSUMER_CLOSE:
{
requiresResponse = true;
SessionConsumerCloseMessage message = (SessionConsumerCloseMessage) packet;
session.closeConsumer(message.getConsumerID());
response = new NullResponseMessage();
break;
}
case SESS_FORCE_CONSUMER_DELIVERY:
{
SessionForceConsumerDelivery message = (SessionForceConsumerDelivery) packet;
session.forceConsumerDelivery(message.getConsumerID(), message.getSequence());
break;
}
case PacketImpl.SESS_ADD_METADATA:
{
response = new NullResponseMessage();
SessionAddMetaDataMessage message = (SessionAddMetaDataMessage) packet;
session.addMetaData(message.getKey(), message.getData());
break;
}
case PacketImpl.SESS_ADD_METADATA2:
{
requiresResponse = true;
SessionAddMetaDataMessageV2 message = (SessionAddMetaDataMessageV2) packet;
if (message.isRequiresConfirmations()) {
response = new NullResponseMessage();
}
session.addMetaData(message.getKey(), message.getData());
break;
}
case PacketImpl.SESS_UNIQUE_ADD_METADATA:
{
requiresResponse = true;
SessionUniqueAddMetaDataMessage message = (SessionUniqueAddMetaDataMessage) packet;
if (session.addUniqueMetaData(message.getKey(), message.getData())) {
response = new NullResponseMessage();
} else {
response = new ActiveMQExceptionMessage(ActiveMQMessageBundle.BUNDLE.duplicateMetadata(message.getKey(), message.getData()));
}
break;
}
}
} catch (ActiveMQIOErrorException e) {
response = onActiveMQIOErrorExceptionWhileHandlePacket(e, requiresResponse, response, this.session);
} catch (ActiveMQXAException e) {
response = onActiveMQXAExceptionWhileHandlePacket(e, requiresResponse, response);
} catch (ActiveMQQueueMaxConsumerLimitReached e) {
response = onActiveMQQueueMaxConsumerLimitReachedWhileHandlePacket(e, requiresResponse, response);
} catch (ActiveMQException e) {
response = onActiveMQExceptionWhileHandlePacket(e, requiresResponse, response);
} catch (Throwable t) {
response = onCatchThrowableWhileHandlePacket(t, requiresResponse, response, this.session);
}
sendResponse(packet, response, flush, closeChannel);
} finally {
storageManager.clearContext();
}
}
use of org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage in project activemq-artemis by apache.
the class ActiveMQSessionContext method sendSessionSendContinuationMessage.
private static int sendSessionSendContinuationMessage(Channel channel, Message msgI, long messageBodySize, boolean sendBlocking, boolean lastChunk, byte[] chunk, SendAcknowledgementHandler messageHandler) throws ActiveMQException {
final boolean requiresResponse = lastChunk && sendBlocking;
final SessionSendContinuationMessage chunkPacket = new SessionSendContinuationMessage(msgI, chunk, !lastChunk, requiresResponse, messageBodySize, messageHandler);
final int expectedEncodeSize = chunkPacket.expectedEncodeSize();
// perform a weak form of flow control to avoid OOM on tight loops
final CoreRemotingConnection connection = channel.getConnection();
final long blockingCallTimeoutMillis = Math.max(0, connection.getBlockingCallTimeout());
final long startFlowControl = System.nanoTime();
try {
final boolean isWritable = connection.blockUntilWritable(expectedEncodeSize, blockingCallTimeoutMillis);
if (!isWritable) {
final long endFlowControl = System.nanoTime();
final long elapsedFlowControl = endFlowControl - startFlowControl;
final long elapsedMillis = TimeUnit.NANOSECONDS.toMillis(elapsedFlowControl);
ActiveMQClientLogger.LOGGER.timeoutStreamingLargeMessage();
logger.debug("try to write " + expectedEncodeSize + " bytes after blocked " + elapsedMillis + " ms on a not writable connection: [" + connection.getID() + "]");
}
if (requiresResponse) {
// When sending it blocking, only the last chunk will be blocking.
channel.sendBlocking(chunkPacket, PacketImpl.NULL_RESPONSE);
} else {
channel.send(chunkPacket);
}
return chunkPacket.getPacketSize();
} catch (Throwable e) {
throw new ActiveMQException(e.getMessage());
}
}
use of org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage in project activemq-artemis by apache.
the class BridgeTest method internalTestMessageLoss.
/**
* This test will ignore messages
* What will cause the bridge to fail with a timeout
* The bridge should still recover the failure and reconnect on that case
*/
public void internalTestMessageLoss(final boolean largeMessage) throws Exception {
class MyInterceptor implements Interceptor {
public boolean ignoreSends = true;
public CountDownLatch latch;
MyInterceptor(int numberOfIgnores) {
latch = new CountDownLatch(numberOfIgnores);
}
@Override
public boolean intercept(Packet packet, RemotingConnection connection) throws ActiveMQException {
if (ignoreSends && packet instanceof SessionSendMessage || ignoreSends && packet instanceof SessionSendLargeMessage || ignoreSends && packet instanceof SessionSendContinuationMessage && !((SessionSendContinuationMessage) packet).isContinues()) {
IntegrationTestLogger.LOGGER.info("IGNORED: " + packet);
latch.countDown();
return false;
} else {
IntegrationTestLogger.LOGGER.info(packet);
return true;
}
}
}
MyInterceptor myInterceptor = new MyInterceptor(3);
Map<String, Object> server0Params = new HashMap<>();
server0 = createClusteredServerWithParams(isNetty(), 0, true, server0Params);
Map<String, Object> server1Params = new HashMap<>();
addTargetParameters(server1Params);
server1 = createClusteredServerWithParams(isNetty(), 1, true, server1Params);
final String testAddress = "testAddress";
final String queueName0 = "queue0";
final String forwardAddress = "forwardAddress";
final String queueName1 = "queue1";
TransportConfiguration server0tc = new TransportConfiguration(getConnector(), server0Params);
TransportConfiguration server1tc = new TransportConfiguration(getConnector(), server1Params);
HashMap<String, TransportConfiguration> connectors = new HashMap<>();
connectors.put(server1tc.getName(), server1tc);
server0.getConfiguration().setConnectorConfigurations(connectors);
final int messageSize = 1024;
final int numMessages = 1;
ArrayList<String> connectorConfig = new ArrayList<>();
connectorConfig.add(server1tc.getName());
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration().setName("bridge1").setQueueName(queueName0).setForwardingAddress(forwardAddress).setRetryInterval(100).setReconnectAttempts(-1).setReconnectAttemptsOnSameNode(-1).setUseDuplicateDetection(false).setConfirmationWindowSize(numMessages * messageSize / 2).setStaticConnectors(connectorConfig).setCallTimeout(500);
List<BridgeConfiguration> bridgeConfigs = new ArrayList<>();
bridgeConfigs.add(bridgeConfiguration);
server0.getConfiguration().setBridgeConfigurations(bridgeConfigs);
CoreQueueConfiguration queueConfig0 = new CoreQueueConfiguration().setAddress(testAddress).setName(queueName0);
List<CoreQueueConfiguration> queueConfigs0 = new ArrayList<>();
queueConfigs0.add(queueConfig0);
server0.getConfiguration().setQueueConfigurations(queueConfigs0);
CoreQueueConfiguration queueConfig1 = new CoreQueueConfiguration().setAddress(forwardAddress).setName(queueName1);
List<CoreQueueConfiguration> queueConfigs1 = new ArrayList<>();
queueConfigs1.add(queueConfig1);
server1.getConfiguration().setQueueConfigurations(queueConfigs1);
server1.start();
server1.getRemotingService().addIncomingInterceptor(myInterceptor);
server0.start();
locator = addServerLocator(ActiveMQClient.createServerLocatorWithoutHA(server0tc, server1tc));
ClientSessionFactory sf0 = addSessionFactory(locator.createSessionFactory(server0tc));
ClientSessionFactory sf1 = addSessionFactory(locator.createSessionFactory(server1tc));
ClientSession session0 = sf0.createSession(false, true, true);
ClientSession session1 = sf1.createSession(false, true, true);
ClientProducer producer0 = session0.createProducer(new SimpleString(testAddress));
ClientConsumer consumer1 = session1.createConsumer(queueName1);
session1.start();
final byte[] bytes = new byte[messageSize];
final SimpleString propKey = new SimpleString("testkey");
for (int i = 0; i < numMessages; i++) {
ClientMessage message = session0.createMessage(true);
if (largeMessage) {
message.setBodyInputStream(ActiveMQTestBase.createFakeLargeStream(10 * 1024));
}
message.putIntProperty(propKey, i);
message.getBodyBuffer().writeBytes(bytes);
producer0.send(message);
}
assertTrue("where is the countDown?", myInterceptor.latch.await(30, TimeUnit.SECONDS));
myInterceptor.ignoreSends = false;
server1.getRemotingService().removeIncomingInterceptor(myInterceptor);
IntegrationTestLogger.LOGGER.info("No longer ignoring packets.");
for (int i = 0; i < numMessages; i++) {
ClientMessage message = consumer1.receive(30000);
Assert.assertNotNull(message);
Assert.assertEquals(i, message.getObjectProperty(propKey));
if (largeMessage) {
readLargeMessages(message, 10);
}
message.acknowledge();
}
Assert.assertNull(consumer1.receiveImmediate());
session0.close();
session1.close();
sf0.close();
sf1.close();
closeFields();
assertEquals("there should be no queues", 0, loadQueues(server0).size());
}
Aggregations