}
/** {@inheritDoc} */
@Override
public void run(IRequest request, IResponse response, IResponderCallback responderCallback) throws Exception {
SCMPMessage reqMessage = request.getMessage();
String serviceName = reqMessage.getServiceName();
// check service is present and enabled
Service abstractService = this.getService(serviceName);
if (abstractService.isEnabled() == false) {
SCMPCommandException scmpCommandException = new SCMPCommandException(SCMPError.SERVICE_DISABLED, "service="
+ abstractService.getName() + " is disabled");
scmpCommandException.setMessageType(getKey());
throw scmpCommandException;
}
// enhance ipAddressList
String ipAddressList = reqMessage.getHeader(SCMPHeaderAttributeKey.IP_ADDRESS_LIST);
ipAddressList = ipAddressList + Constants.SLASH + request.getRemoteSocketAddress().getAddress().getHostAddress();
reqMessage.setHeader(SCMPHeaderAttributeKey.IP_ADDRESS_LIST, ipAddressList);
int oti = reqMessage.getHeaderInt(SCMPHeaderAttributeKey.OPERATION_TIMEOUT);
// create temporary Subscription for cascaded SC
String sessionInfo = reqMessage.getHeader(SCMPHeaderAttributeKey.SESSION_INFO);
int noiSecs = reqMessage.getHeaderInt(SCMPHeaderAttributeKey.NO_DATA_INTERVAL);
int noiInMillis = noiSecs * Constants.SEC_TO_MILLISEC_FACTOR;
String cscSCMaskString = reqMessage.getHeader(SCMPHeaderAttributeKey.CASCADED_MASK);
String cascSubscriptionId = reqMessage.getHeader(SCMPHeaderAttributeKey.CASCADED_SUBSCRIPTION_ID);
Subscription cscSubscription = this.subscriptionRegistry.getSubscription(cascSubscriptionId);
SubscriptionMask cscMask = new SubscriptionMask(cscSCMaskString);
Subscription tmpCascSCSubscription = new Subscription(cscMask, sessionInfo, ipAddressList, noiInMillis, AppContext
.getBasicConfiguration().getSubscriptionTimeoutMillis(), true);
tmpCascSCSubscription.setService(abstractService);
switch (abstractService.getType()) {
case CASCADED_PUBLISH_SERVICE:
// publish service is cascaded
CascadedPublishService cascadedPublishService = (CascadedPublishService) abstractService;
CascadedSC cascadedSC = cascadedPublishService.getCascadedSC();
// add server to subscription
tmpCascSCSubscription.setServer(cascadedSC);
ISubscriptionCallback callback = null;
if (cscSubscription == null) {
// cascaded SC not subscribed yet
callback = new SubscribeCommandCallback(request, response, responderCallback, tmpCascSCSubscription);
} else {
// subscribe is made by an active cascaded SC
callback = new CscChangeSubscriptionCallbackForCasc(request, response, responderCallback, cscSubscription,
cscSCMaskString);
}
cascadedSC.cascadedSCSubscribe(cascadedPublishService.getCascClient(), reqMessage, callback, oti);
return;
default:
// code for other types of services is below
break;
}
// modify message only if it goes to server
reqMessage.removeHeader(SCMPHeaderAttributeKey.NO_DATA_INTERVAL);
reqMessage.removeHeader(SCMPHeaderAttributeKey.CASCADED_MASK);
reqMessage.removeHeader(SCMPHeaderAttributeKey.CASCADED_SUBSCRIPTION_ID);
// check service is present
PublishService service = this.validatePublishService(abstractService);
int otiOnSCMillis = (int) (oti * basicConf.getOperationTimeoutMultiplier());
int tries = (otiOnSCMillis / Constants.WAIT_FOR_FREE_CONNECTION_INTERVAL_MILLIS);
int i = 0;
// Following loop implements the wait mechanism in case of a busy connection pool
do {
// reset ipList&msgType, might have been modified in below operation try
reqMessage.setHeader(SCMPHeaderAttributeKey.IP_ADDRESS_LIST, ipAddressList);
reqMessage.setMessageType(this.getKey());
try {
if (cscSubscription != null) {
// cascaded subscribe made by an active cascaded SC
CscChangeSubscriptionCallbackForCasc cascCallback = new CscChangeSubscriptionCallbackForCasc(request, response,
responderCallback, cscSubscription, cscSCMaskString);
((StatefulServer) cscSubscription.getServer()).subscribe(reqMessage, cascCallback, otiOnSCMillis);
break;
}
// cascaded subscribe made by an inactive cascaded SC - forward client subscribe to server
SubscribeCommandCallback callback = new SubscribeCommandCallback(request, response, responderCallback,
tmpCascSCSubscription);
service.allocateServerAndSubscribe(reqMessage, callback, tmpCascSCSubscription, otiOnSCMillis
- (i * Constants.WAIT_FOR_FREE_CONNECTION_INTERVAL_MILLIS));
// no exception has been thrown - get out of wait loop
break;
} catch (NoFreeServerException ex) {
LOGGER.debug("NoFreeServerException caught in wait mec of subscribe, tries left=" + tries);
if (i >= (tries - 1)) {
// only one loop outstanding - don't continue throw current exception
throw ex;
}
} catch (ConnectionPoolBusyException ex) {
LOGGER.debug("ConnectionPoolBusyException caught in wait mec of subscribe, tries left=" + tries);
if (i >= (tries - 1)) {
// only one loop outstanding - don't continue throw current exception
LOGGER.warn(SCMPError.NO_FREE_CONNECTION.getErrorText("service=" + reqMessage.getServiceName()));
SCMPCommandException scmpCommandException = new SCMPCommandException(SCMPError.NO_FREE_CONNECTION, "service="
+ reqMessage.getServiceName());
scmpCommandException.setMessageType(this.getKey());
throw scmpCommandException;
}
}
// sleep for a while and then try again