ClientRequestDispatcher
{
public OutputObject beginRequest(Object self, String opName,
boolean isOneWay, ContactInfo contactInfo)
{
ORB orb = null;
try {
CorbaContactInfo corbaContactInfo = (CorbaContactInfo) contactInfo;
orb = (ORB)contactInfo.getBroker();
if (orb.subcontractDebugFlag) {
dprint(".beginRequest->: op/" + opName);
}
//
// Portable Interceptor initialization.
//
orb.getPIHandler().initiateClientPIRequest( false );
//
// Connection.
//
CorbaConnection connection = null;
// This locking is done so that multiple connections are not created
// for the same endpoint
//6929137 - Synchronized on contactInfo to avoid blocking across multiple endpoints
synchronized (contactInfo) {
if (contactInfo.isConnectionBased()) {
if (contactInfo.shouldCacheConnection()) {
connection = (CorbaConnection)
orb.getTransportManager()
.getOutboundConnectionCache(contactInfo).get(contactInfo);
}
if (connection != null) {
if (orb.subcontractDebugFlag) {
dprint(".beginRequest: op/" + opName
+ ": Using cached connection: " + connection);
}
} else {
try {
connection = (CorbaConnection)
contactInfo.createConnection();
if (orb.subcontractDebugFlag) {
dprint(".beginRequest: op/" + opName
+ ": Using created connection: " + connection);
}
} catch (RuntimeException e) {
if (orb.subcontractDebugFlag) {
dprint(".beginRequest: op/" + opName
+ ": failed to create connection: " + e);
}
// REVISIT: this part similar to marshalingComplete below.
boolean retry = getContactInfoListIterator(orb)
.reportException(contactInfo, e);
// REVISIT:
// this part similar to Remarshal in this method below
if (retry) {
if(getContactInfoListIterator(orb).hasNext()) {
contactInfo = (ContactInfo)
getContactInfoListIterator(orb).next();
unregisterWaiter(orb);
return beginRequest(self, opName,
isOneWay, contactInfo);
} else {
throw e;
}
} else {
throw e;
}
}
if (connection.shouldRegisterReadEvent()) {
// REVISIT: cast
orb.getTransportManager().getSelector(0)
.registerForEvent(connection.getEventHandler());
connection.setState("ESTABLISHED");
}
// Do not do connection reclaim here since the connections
// are marked in use by registerWaiter() call and since this
// call happens later do it after that.
if (contactInfo.shouldCacheConnection()) {
OutboundConnectionCache connectionCache =
orb.getTransportManager()
.getOutboundConnectionCache(contactInfo);
connectionCache.stampTime(connection);
connectionCache.put(contactInfo, connection);
// connectionCache.reclaim();
}
}
}
}
CorbaMessageMediator messageMediator = (CorbaMessageMediator)
contactInfo.createMessageMediator(
orb, contactInfo, connection, opName, isOneWay);
if (orb.subcontractDebugFlag) {
dprint(".beginRequest: " + opAndId(messageMediator)
+ ": created message mediator: " + messageMediator);
}
// NOTE: Thread data so we can get the mediator in release reply
// in order to remove the waiter in CorbaConnection.
// We cannot depend on obtaining information in releaseReply
// via its InputStream argument since, on certain errors
// (e.g., client marshaling errors), the stream may be null.
// Likewise for releaseReply "self".
// NOTE: This must be done before initializing the message since
// that may start sending fragments which may end up in "early"
// replies or client marshaling exceptions.
orb.getInvocationInfo().setMessageMediator(messageMediator);
if (connection != null && connection.getCodeSetContext() == null) {
performCodeSetNegotiation(messageMediator);
}
addServiceContexts(messageMediator);
OutputObject outputObject =
contactInfo.createOutputObject(messageMediator);
if (orb.subcontractDebugFlag) {
dprint(".beginRequest: " + opAndId(messageMediator)
+ ": created output object: " + outputObject);
}
// NOTE: Not necessary for oneways, but useful for debugging.
// This must be done BEFORE message initialization since fragments
// may be sent at that time.
registerWaiter(messageMediator);
// Do connection reclaim now
synchronized (contactInfo) {
if (contactInfo.isConnectionBased()) {
if (contactInfo.shouldCacheConnection()) {
OutboundConnectionCache connectionCache =
orb.getTransportManager()
.getOutboundConnectionCache(contactInfo);
connectionCache.reclaim();
}
}
}
orb.getPIHandler().setClientPIInfo(messageMediator);
try {
// This MUST come before message is initialized so
// service contexts may be added by PI because
// initial fragments may be sent during message initialization.
orb.getPIHandler().invokeClientPIStartingPoint();
} catch( RemarshalException e ) {
if (orb.subcontractDebugFlag) {
dprint(".beginRequest: " + opAndId(messageMediator)
+ ": Remarshal");
}
// NOTE: We get here because an interceptor raised ForwardRequest
// and updated the IOR/Iterator. Since we have a fresh iterator
// hasNext should succeed.
// REVISIT: We should feed ALL interceptor exceptions to
// iterator.reportException so it can determine if it wants
// to retry. Right now, SystemExceptions will flow to the
// client code.
// REVISIT:
// This assumes that interceptors update
// ContactInfoList outside of subcontract.
// Want to move that update to here.
if (getContactInfoListIterator(orb).hasNext()) {
contactInfo = (ContactInfo)getContactInfoListIterator(orb).next();
if (orb.subcontractDebugFlag) {
dprint( "RemarshalException: hasNext true\ncontact info " + contactInfo );
}
// Fix for 6763340: Complete the first attempt before starting another.
orb.getPIHandler().makeCompletedClientRequest(
ReplyMessage.LOCATION_FORWARD, null ) ;
unregisterWaiter(orb);
orb.getPIHandler().cleanupClientPIRequest() ;
return beginRequest(self, opName, isOneWay, contactInfo);
} else {
if (orb.subcontractDebugFlag) {
dprint( "RemarshalException: hasNext false" );