/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.spi.core.remoting;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.Executor;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.SendAcknowledgementHandler;
import org.apache.activemq.artemis.core.client.impl.ClientConsumerInternal;
import org.apache.activemq.artemis.core.client.impl.ClientLargeMessageInternal;
import org.apache.activemq.artemis.core.client.impl.ClientMessageInternal;
import org.apache.activemq.artemis.core.client.impl.ClientProducerCreditsImpl;
import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.utils.IDGenerator;
import org.apache.activemq.artemis.utils.SimpleIDGenerator;
public abstract class SessionContext {
protected ClientSessionInternal session;
protected SendAcknowledgementHandler sendAckHandler;
protected volatile RemotingConnection remotingConnection;
protected final IDGenerator idGenerator = new SimpleIDGenerator(0);
public SessionContext(RemotingConnection remotingConnection) {
this.remotingConnection = remotingConnection;
}
public ClientSessionInternal getSession() {
return session;
}
public void setSession(ClientSessionInternal session) {
this.session = session;
}
public abstract void resetName(String name);
public abstract int getReconnectID();
/**
* it will either reattach or reconnect, preferably reattaching it.
*
* @param newConnection
* @return true if it was possible to reattach
* @throws ActiveMQException
*/
public abstract boolean reattachOnNewConnection(RemotingConnection newConnection) throws ActiveMQException;
public RemotingConnection getRemotingConnection() {
return remotingConnection;
}
public abstract void closeConsumer(ClientConsumer consumer) throws ActiveMQException;
public abstract void sendConsumerCredits(ClientConsumer consumer, int credits);
public abstract boolean supportsLargeMessage();
protected void handleReceiveLargeMessage(ConsumerContext consumerID,
ClientLargeMessageInternal clientLargeMessage,
long largeMessageSize) throws Exception {
ClientSessionInternal session = this.session;
if (session != null) {
session.handleReceiveLargeMessage(consumerID, clientLargeMessage, largeMessageSize);
}
}
protected void handleReceiveMessage(ConsumerContext consumerID,
final ClientMessageInternal message) throws Exception {
ClientSessionInternal session = this.session;
if (session != null) {
session.handleReceiveMessage(consumerID, message);
}
}
protected void handleReceiveContinuation(final ConsumerContext consumerID,
byte[] chunk,
int flowControlSize,
boolean isContinues) throws Exception {
ClientSessionInternal session = this.session;
if (session != null) {
session.handleReceiveContinuation(consumerID, chunk, flowControlSize, isContinues);
}
}
protected void handleReceiveProducerCredits(SimpleString address, int credits) {
ClientSessionInternal session = this.session;
if (session != null) {
session.handleReceiveProducerCredits(address, credits);
}
}
protected void handleReceiveProducerFailCredits(SimpleString address, int credits) {
ClientSessionInternal session = this.session;
if (session != null) {
session.handleReceiveProducerFailCredits(address, credits);
}
}
public abstract int getCreditsOnSendingFull(Message msgI);
public abstract void sendFullMessage(ICoreMessage msgI,
boolean sendBlocking,
SendAcknowledgementHandler handler,
SimpleString defaultAddress) throws ActiveMQException;
/**
* it should return the number of credits (or bytes) used to send this packet
*
* @param msgI
* @return
* @throws ActiveMQException
*/
public abstract int sendInitialChunkOnLargeMessage(Message msgI) throws ActiveMQException;
public abstract int sendLargeMessageChunk(Message msgI,
long messageBodySize,
boolean sendBlocking,
boolean lastChunk,
byte[] chunk,
int reconnectID,
SendAcknowledgementHandler messageHandler) throws ActiveMQException;
public abstract int sendServerLargeMessageChunk(Message msgI,
long messageBodySize,
boolean sendBlocking,
boolean lastChunk,
byte[] chunk,
SendAcknowledgementHandler messageHandler) throws ActiveMQException;
public abstract void setSendAcknowledgementHandler(final SendAcknowledgementHandler handler);
/**
* Creates a shared queue using the routing type set by the Address. If the Address supports more than one type of delivery
* then the default delivery mode (MULTICAST) is used.
*
* @param address
* @param queueName
* @param routingType
* @param filterString
* @param durable
* @throws ActiveMQException
*/
public abstract void createSharedQueue(SimpleString address,
SimpleString queueName,
RoutingType routingType,
SimpleString filterString,
boolean durable) throws ActiveMQException;
public abstract void createSharedQueue(SimpleString address,
SimpleString queueName,
SimpleString filterString,
boolean durable) throws ActiveMQException;
public abstract void deleteQueue(SimpleString queueName) throws ActiveMQException;
public abstract void createAddress(SimpleString address, Set<RoutingType> routingTypes, boolean autoCreated) throws ActiveMQException;
@Deprecated
public abstract void createQueue(SimpleString address,
SimpleString queueName,
SimpleString filterString,
boolean durable,
boolean temp,
boolean autoCreated) throws ActiveMQException;
public abstract void createQueue(SimpleString address,
RoutingType routingType,
SimpleString queueName,
SimpleString filterString,
boolean durable,
boolean temp,
int maxConsumers,
boolean purgeOnNoConsumers,
boolean autoCreated) throws ActiveMQException;
public abstract ClientSession.QueueQuery queueQuery(SimpleString queueName) throws ActiveMQException;
public abstract void forceDelivery(ClientConsumer consumer, long sequence) throws ActiveMQException;
public abstract ClientSession.AddressQuery addressQuery(final SimpleString address) throws ActiveMQException;
public abstract void simpleCommit() throws ActiveMQException;
/**
* If we are doing a simple rollback on the RA, we need to ack the last message sent to the consumer,
* otherwise DLQ won't work.
* <p>
* this is because we only ACK after on the RA, We may review this if we always acked earlier.
*
* @param lastMessageAsDelivered
* @throws ActiveMQException
*/
public abstract void simpleRollback(boolean lastMessageAsDelivered) throws ActiveMQException;
public abstract void sessionStart() throws ActiveMQException;
public abstract void sessionStop() throws ActiveMQException;
public abstract void sendACK(boolean individual,
boolean block,
final ClientConsumer consumer,
final Message message) throws ActiveMQException;
public abstract void expireMessage(final ClientConsumer consumer, Message message) throws ActiveMQException;
public abstract void sessionClose() throws ActiveMQException;
public abstract void addSessionMetadata(String key, String data) throws ActiveMQException;
public abstract void addUniqueMetaData(String key, String data) throws ActiveMQException;
public abstract void sendProducerCreditsMessage(final int credits, final SimpleString address);
public abstract void xaCommit(Xid xid, boolean onePhase) throws XAException, ActiveMQException;
public abstract void xaEnd(Xid xid, int flags) throws XAException, ActiveMQException;
public abstract void xaForget(Xid xid) throws XAException, ActiveMQException;
public abstract int xaPrepare(Xid xid) throws XAException, ActiveMQException;
public abstract Xid[] xaScan() throws ActiveMQException;
public abstract void xaRollback(Xid xid, boolean wasStarted) throws ActiveMQException, XAException;
public abstract void xaStart(Xid xid, int flags) throws XAException, ActiveMQException;
public abstract boolean configureTransactionTimeout(int seconds) throws ActiveMQException;
public abstract ClientConsumerInternal createConsumer(SimpleString queueName,
SimpleString filterString,
int windowSize,
int maxRate,
int ackBatchSize,
boolean browseOnly,
Executor executor,
Executor flowControlExecutor) throws ActiveMQException;
/**
* Performs a round trip to the server requesting what is the current tx timeout on the session
*
* @return
*/
public abstract int recoverSessionTimeout() throws ActiveMQException;
public abstract int getServerVersion();
public abstract void recreateSession(final String username,
final String password,
final int minLargeMessageSize,
final boolean xa,
final boolean autoCommitSends,
final boolean autoCommitAcks,
final boolean preAcknowledge) throws ActiveMQException;
public abstract void recreateConsumerOnServer(ClientConsumerInternal consumerInternal) throws ActiveMQException;
public abstract void xaFailed(Xid xid) throws ActiveMQException;
public abstract void restartSession() throws ActiveMQException;
public abstract void resetMetadata(HashMap<String, String> metaDataToSend);
// Failover utility classes
/**
* Interrupt and return any blocked calls
*/
public abstract void returnBlocking(ActiveMQException cause);
/**
* it will lock the communication channel of the session avoiding anything to come while failover is happening.
* It happens on preFailover from ClientSessionImpl
*/
public abstract void lockCommunications();
public abstract void releaseCommunications();
public abstract void cleanup();
public abstract void linkFlowControl(SimpleString address, ClientProducerCreditsImpl clientProducerCredits);
public abstract boolean isWritable(ReadyListener callback);
}