// Set the flag to indicate that the CAS been generated by CM
isNewCAS = true;
// Fetch the actual input CAS Reference Id from which the CAS being processed was generated from
inputCasReferenceId = aMessageContext.getMessageStringProperty(AsynchAEMessage.InputCasReference);
// Fetch input CAS Cache entry
CacheEntry inputCasCacheEntry = getController().
getInProcessCache().
getCacheEntryForCAS(inputCasReferenceId);
// This CAS came in from the CAS Multiplier. Treat it differently than the
// input CAS. First, in case the Aggregate needs to send this CAS to the
// client, retrieve the client destination by looking up the client endpoint
// using input CAS reference id. CASes generated by the CAS multiplier will have
// the same Cas Reference id.
Endpoint replyToEndpoint = inputCasCacheEntry.getMessageOrigin();
if ( getController() instanceof AggregateAnalysisEngineController )
{
newCASProducedBy = inputCasCacheEntry.getCasMultiplierKey();
// increment number of subordinate CASes that are currently being processed
// The input CAS (parent) will be held by the aggregate until all of its
// subordinate CASes are fully processed. Only then, the aggregate can return
// it back to the client
synchronized( inputCasCacheEntry )
{
inputCasCacheEntry.incrementSubordinateCasInPlayCount();
}
if ( ((AggregateAnalysisEngineController)getController()).sendRequestToReleaseCas() )
{
try
{
// Change the name of the queue where the request to free a CAS will be sent.
aMessageContext.getEndpoint().setEndpoint(aMessageContext.getEndpoint().getEndpoint()+"CasSync");
getController().getOutputChannel().sendRequest(AsynchAEMessage.ReleaseCAS, casReferenceId, aMessageContext.getEndpoint());
requestToFreeCasSent = true;
}
catch( Exception e){}
}
}
// MessageContext contains endpoint set by the CAS Multiplier service. Overwrite
// this with the endpoint of the client who sent the input CAS. In case this
// aggregate is configured to send new CASes to the client we know where to send them.
aMessageContext.getEndpoint().setEndpoint(replyToEndpoint.getEndpoint());
aMessageContext.getEndpoint().setServerURI(replyToEndpoint.getServerURI());
// Set this to null so that the new CAS gets its own Cas Reference Id below
casReferenceId = null;
}
else if ( getController().isTopLevelComponent())
{
Endpoint replyToEndpoint = aMessageContext.getEndpoint();
if ( getController() instanceof AggregateAnalysisEngineController )
{
((AggregateAnalysisEngineController)getController()).addMessageOrigin(casReferenceId, replyToEndpoint);
}
}
// To prevent processing multiple messages with the same CasReferenceId, check the CAS cache
// to see if the message with a given CasReferenceId is already being processed. It is, the
// message contains the same request possibly issued by the caller due to timeout. Also this
// mechanism helps with dealing with scenario when this service is not up when the client sends
// request. The client can keep re-sending the same request until its timeout thresholds are
// exceeded. By that time, there may be multiple messages in this service queue with the same
// CasReferenceId. When the service finally comes back up, it will have multiple messages in
// its queue possibly from the same client. Only the first message for any given CasReferenceId
// should be processed.
if ( casReferenceId == null || !getController().getInProcessCache().entryExists(casReferenceId) )
{
String xmi = aMessageContext.getStringMessage();
// *****************************************************************
// ***** NO XMI In Message. Kick this back to sender with exception
// *****************************************************************
if ( xmi == null )
{
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, CLASS_NAME.getName(),
"handleProcessRequestWithXMI", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_message_has_no_cargo__INFO",
new Object[] { aMessageContext.getEndpoint().getEndpoint() });
getController().
getOutputChannel().
sendReply(new InvalidMessageException("No XMI data in message"), casReferenceId, aMessageContext.getEndpoint(),AsynchAEMessage.Process);
// Dont process this empty message
return;
}
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINEST, CLASS_NAME.getName(),
"handleProcessRequestWithXMI", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_request_cas__FINEST",
new Object[] { aMessageContext.getEndpoint().getEndpoint() });
long t1 = System.nanoTime();
if ( isNewCAS )
{
cas = getController().getCasManagerWrapper().getNewCas(newCASProducedBy);
}
else
{
cas = getController().getCasManagerWrapper().getNewCas();
}
long timeWaitingForCAS = System.nanoTime() - t1;
if ( getController().isStopped() )
{
// The Controller is in shutdown state.
getController().dropCAS(cas);
return;
}
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
"handleProcessRequestWithXMI", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_request_cas_granted__FINE",
new Object[] { aMessageContext.getEndpoint().getEndpoint() });
t1 = System.nanoTime();
XmiSerializationSharedData deserSharedData = new XmiSerializationSharedData();
UimaSerializer.deserializeCasFromXmi(xmi, cas, deserSharedData, true, -1);
long timeToDeserializeCAS = System.nanoTime() - t1;
LongNumericStatistic statistic;
if ( (statistic = getController().getMonitor().getLongNumericStatistic("",Monitor.TotalDeserializeTime)) != null )
{
statistic.increment(timeToDeserializeCAS);
}
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
"handleProcessRequestWithXMI", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_deserialize_cas_time_FINE",
new Object[] { timeToDeserializeCAS / 1000 });
ServicePerformance casStats = null;
if (casReferenceId == null)
{
if (getController() instanceof PrimitiveAnalysisEngineController)
{
inputCasReferenceId = getController().getInProcessCache().register(cas, aMessageContext, deserSharedData);
}
else
{
casReferenceId = getController().getInProcessCache().register(cas, aMessageContext, deserSharedData);
if ( inputCasReferenceId == null )
{
inputCasReferenceId = casReferenceId;
}
}
casStats = getController().getCasStatistics(inputCasReferenceId);
}
else
{
getController().getInProcessCache().register(cas, aMessageContext, deserSharedData, casReferenceId);
/*
if ( aMessageContext.propertyExists(AsynchAEMessage.InputCasReference))
{
CacheEntry cacheEntry = getController().getInProcessCache().getCacheEntryForCAS(casReferenceId);
String parentCasId = aMessageContext.getMessageStringProperty(AsynchAEMessage.InputCasReference);
cacheEntry.setInputCasReferenceId(parentCasId);
}
*/
casStats = getController().getCasStatistics(casReferenceId);
}
casStats.incrementCasDeserializationTime(timeToDeserializeCAS);
if ( getController().isTopLevelComponent() )
{
getController().getServicePerformance().incrementCasDeserializationTime(timeToDeserializeCAS);
}
// Set a local flag to indicate that the CAS has been added to the cache. This will be usefull when handling an exception
// If an exception happens before the CAS is added to the cache, the CAS needs to be dropped immediately.
casRegistered = true;
if ( casReferenceId == null )
{
getController().saveTime(inTime, inputCasReferenceId, getController().getName());
}
else
{
getController().saveTime(inTime, casReferenceId, getController().getName());
}
CacheEntry entry = null;
if ( getController() instanceof AggregateAnalysisEngineController )
{
entry = getController().getInProcessCache().getCacheEntryForCAS(casReferenceId);
if ( isNewCAS )
{
if ( newCASProducedBy != null )
{
entry.setCasMultiplierKey(newCASProducedBy);
}
if ( remoteCasReferenceId != null )
{
entry.setRemoteCMCasReferenceId(remoteCasReferenceId);
}
if ( requestToFreeCasSent )
{
entry.setSendRequestToFreeCas(false);
}
// associate this subordinate CAS with the parent CAS
entry.setInputCasReferenceId(inputCasReferenceId);
entry.setReplyReceived();
}
DelegateStats stats = new DelegateStats();
if ( entry.getStat() == null )
{
entry.setStat(stats);
// Add entry for self (this aggregate). MessageContext.getEndpointName()
// returns the name of the queue receiving the message.
stats.put(getController().getServiceEndpointName(), new TimerStats());
}
else
{
if (!stats.containsKey(getController().getServiceEndpointName()))
{
stats.put(getController().getServiceEndpointName(), new DelegateStats());
}
}
}
cacheStats( inputCasReferenceId, timeWaitingForCAS, timeToDeserializeCAS);
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
"handleProcessRequestWithXMI", UIMAEE_Constants.JMS_LOG_RESOURCE_BUNDLE, "UIMAEE_deserialized_cas_ready_to_process_FINE",
new Object[] { aMessageContext.getEndpoint().getEndpoint() });
cacheProcessCommandInClientEndpoint();
if ( getController().isStopped() )
{
if ( entry != null )
{
// The Controller is in shutdown state.
getController().dropCAS( entry.getCasReferenceId(), true);
return;
}
}
invokeProcess(cas, inputCasReferenceId, casReferenceId, aMessageContext, newCASProducedBy);
}