final NewHeapSubscription newHeapSubscription;
try {
newHeapSubscription = (NewHeapSubscription) in.getResult();
} catch (Exception e) {
logger.log(Level.WARNING, "Error unpacking subscription result", e);
observer.onResult(new ExecutionResult(new CougarServiceException(ServerFaultCode.FrameworkError, "Error unpacking subscription result", e)));
return;
}
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Received a subscription response for heapId %s with subscriptionId %s", newHeapSubscription.getHeapId(), newHeapSubscription.getSubscriptionId());
final String sessionId = NioUtils.getSessionId(currentSession);
ConnectedHeaps heaps;
heapSubMutationLock.lock();
try {
heaps = heapsByServer.get(sessionId);
if (heaps == null) {
heaps = new ConnectedHeaps();
heapsByServer.put(sessionId, heaps);
}
} finally {
heapSubMutationLock.unlock();
}
// new heap
boolean newHeap = false;
if (newHeapSubscription.getUri() != null) {
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Received a new heap definition, heapId = %s, heapUrl = %s", newHeapSubscription.getHeapId(), newHeapSubscription.getUri());
newHeap = heaps.addHeap(newHeapSubscription.getHeapId(), newHeapSubscription.getUri());
if (!newHeap) {
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Received a new heap definition, heapId = %s, even though we know about the heap already!", newHeapSubscription.getHeapId());
}
}
final boolean preExistingHeap = !newHeap;
// find heap uri
final HeapState heapState = heaps.getHeapState(newHeapSubscription.getHeapId());
if (heapState == null) {
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Couldn't find heap definition, heapId = %s", newHeapSubscription.getHeapId());
logger.log(Level.WARNING, "Can't find the heap for this subscription result. Heap id = " + newHeapSubscription.getHeapId());
observer.onResult(new ExecutionResult(new CougarServiceException(ServerFaultCode.FrameworkError, "Can't find the heap for this subscription result. Heap id = " + newHeapSubscription.getHeapId())));
} else {
if (preExistingHeap && heapState.haveSeenInitialUpdate()) {
Subscription sub = heapState.addSubscription(this, currentSession, newHeapSubscription.getHeapId(), newHeapSubscription.getSubscriptionId());
if (sub != null) {
observer.onResult(new ExecutionResult(new ConnectedResponseImpl(heapState.getHeap(), sub)));
} else {
// null sub means we already had a subscription with that id, something's not in a good state in the server, so kill this connection as we don't know what's going on
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Duplicate subscription returned by the server, id = %s - closing session", newHeapSubscription.getSubscriptionId());
logger.log(Level.WARNING, "Duplicate subscription returned by the server, id = " + newHeapSubscription.getSubscriptionId() + " - closing session");
observer.onResult(new ExecutionResult(new CougarServiceException(ServerFaultCode.FrameworkError, "Duplicate subscription returned by the server, id = " + newHeapSubscription.getSubscriptionId())));
currentSession.close();
}
} else {
// split this off into it's own thread since the mina docs lie and we only have one ioprocessor thread and if we don't fork we'd block forever
final ConnectedHeaps finalHeaps = heaps;
new Thread(new Runnable() {
@Override
public void run() {
boolean resultSent = false;
// now we've got the heap
CountDownLatch initialPopulationLatch = finalHeaps.getInitialPopulationLatch(newHeapSubscription.getHeapId());
try {
boolean populated = false;
if (initialPopulationLatch != null) {
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Waiting for initial heap population, heapUrl = %s", newHeapSubscription.getUri());
populated = initialPopulationLatch.await(maxInitialPopulationWait, TimeUnit.MILLISECONDS);
finalHeaps.removeInitialPopulationLatch(newHeapSubscription.getHeapId());
} else {
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Initial heap population, heapUrl = %s", newHeapSubscription.getUri());
}
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Returning heap to client, heapUrl = %s", newHeapSubscription.getUri());
if (populated) {
observer.onResult(new ExecutionResult(new ConnectedResponseImpl(heapState.getHeap(), heapState.addSubscription(ClientConnectedObjectManager.this, currentSession, newHeapSubscription.getHeapId(), newHeapSubscription.getSubscriptionId()))));
resultSent = true;
}
} catch (InterruptedException e) {
// we got interrupted waiting for the response, oh well..
} catch (RuntimeException e) {
logger.log(Level.WARNING, "Error processing initial heap population, treating as a failure", e);
} finally {
if (!resultSent) {
nioLogger.log(NioLogger.LoggingLevel.TRANSPORT, currentSession, "Didn't get initial population message for heap, heapUrl = %s", newHeapSubscription.getUri());
// we don't worry about the case where it was a preExisting heap since the thread where it wasn't received will deal with it
if (!preExistingHeap) {
terminateSubscriptions(currentSession, newHeapSubscription.getHeapId(), Subscription.CloseReason.INTERNAL_ERROR);
}
logger.log(Level.WARNING, "Didn't get initial population message for heap id = " + newHeapSubscription.getHeapId());
observer.onResult(new ExecutionResult(new CougarServiceException(ServerFaultCode.FrameworkError, "Didn't get initial population message for heap id = " + newHeapSubscription.getHeapId())));
}
}
}
}, "SubscriptionResponseHandler-InitialPopulation-" + initialPopulationThreadIdSource.incrementAndGet() + "-" + heapState.getHeapUri()).start();
}