Skip to main content

VBJ 5.2.1: How to get ORB to close a connection that is dead due to network problems?

  • February 16, 2013
  • 0 replies
  • 1 view

Problem:

  • Product Name: VisiBroker for Java
  • Product Version: 5.2.1
  • Product Component: ORB
  • Platform/OS Version: AIX 5.2

When the connection is lost due to network failure, Unix systems take up to 9 minutes to determine that the connection is invalid and close it. The ORB will continue to try to use that connection while it is still cached and so even with round trip timeouts settings requests can be delayed indefinitely with the ORB repeatedly trying to use an invalid connection.

How can the ORB be made to close this connection or forced to open a new connection in response to the RTT timeout exception?

Resolution:

There are two possibilities:
1) Using client engine connectionMaxIdle properties and a sleep to allow connection to idle out and be closed by ORB.

In VBJ only if the connectionMaxIdle is set then once the connection had been idle to that time the socket object may be garbage collected. Thus the application should wait for the gcTimeout period (which is 30 secs by default) and then ORB should automatically close the connection. The application could sleep for at least the connectionMaxIdle gcTimeout after the TIMEOUT exception has been thrown. The ORB will seamlessly create a new connection when required. Another related article is found at [[knowledge_base: VBJ - How to close the client connection programmatically]].

This is not 100% reliable since the application programmer must ensure that the ORB makes no attempt to use the connection in another thread. It will not work at all if the client allows BiDirectional GIOP messages.


2) Use the ExclusiveConnectionPolicy QoS policy at object level to force the request to be sent on a new connection.

The following example demonstrates how to use the exclusive connection policy after an RTT timeout has been caught. It can be used with the QoS examples provided with VisiBroker.

Also, connection timeout can be set for RelativeConnectionTimeoutPolicy Qos policy at the ORB level, without requiring explicit code to be written. The connection timeout value should be specified in milliseconds. This does not close existing dead connection, but will open a new one.

// class connClient.java

import org.omg.CORBA.*;
import org.omg.Messaging.*;
import com.inprise.vbroker.qos.*;
import com.inprise.vbroker.QoSExt.*;

public class connClient {

  public static void main(String[] args) {
    try {
    // Initialize the ORB.
    org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
    // Get the manager Id
    byte[] managerId = "BankManager".getBytes();
    // Locate an account manager. Give the full POA name and
    // the servant ID.
    Bank.AccountManager source =
	Bank.AccountManagerHelper.bind(orb, "/qos_poa", managerId);
    String name = "Jack B. Quick";

    // Specify the timeout in 100s of Nanosecs.
    // To set a timeout of 20 secs, set 20 * 10^7 nanosecs
    int connTimeout = 2;
    Any ctopolicyValue =  orb.create_any();  
    ctopolicyValue.insert_ulonglong(connTimeout * 10000000);
    org.omg.CORBA.Policy ctoPolicy = orb.create_policy(
                  RELATIVE_CONN_TIMEOUT_POLICY_TYPE.value
                  , ctopolicyValue);

    int rttTimeout = 100;
    Any rttpolicyValue =  orb.create_any();
    rttpolicyValue.insert_ulonglong(rttTimeout * 10000000);
    org.omg.CORBA.Policy rttPolicy = orb.create_policy(
                     RELATIVE_RT_TIMEOUT_POLICY_TYPE.value
                     , rttpolicyValue);

	// Set Orb level policies
    PolicyManager orbManager = PolicyManagerHelper.narrow(
                   orb.resolve_initial_references("ORBPolicyManager"));
    orbManager.set_policy_overrides(
                  new Policy[] {ctoPolicy, rttPolicy}
                  , SetOverrideType.SET_OVERRIDE);


    Bank.Account account = source.open(name);
    float balance = 0;
    balance = account.balance();
    System.out.println ("The first invocation balance in "   name 
                           "'s account is $"   balance);
    System.out.println("Putting the client to 20 sec sleep - unplug the cable");
    Thread.sleep(20 * 1000);
    System.out.println("Sleep time is over - attempting to invoke balance");

    try {
      // We try to make another invocation on the account object
      // This should fail after the RoundTripTimeout expires	
      balance = account.balance();
      
    } catch (Exception e) { // to catch the timeout exception
    
      System.out.println("The first call on cached socket failed\\nHere's why:");
      e.printStackTrace();
      System.out.println("Sleeping waiting for cable to be plugged back in");
      Thread.sleep(20 * 1000);
      
      try {
        System.out.println("Ttrying with exclusive connection policy");
        Any exconnpolicyValue = orb.create_any();
        exconnpolicyValue.insert_boolean(true);
        org.omg.CORBA.Policy exconnPolicy = orb.create_policy(
            EXCLUSIVE_CONNECTION_POLICY_TYPE.value, exconnpolicyValue);
            
        // New account object with Exclusive policy but same as existing object
        // This is required for object level QoS policies which is appropriate here.
        // Here when a call is made using this object a new connection should be opened
        // to the server.
        org.omg.CORBA.Object newObj = account._set_policy_overrides(
                                        new Policy[] {exconnPolicy},
                                        SetOverrideType.SET_OVERRIDE);
        Bank.Account newAccount = Bank.AccountHelper.narrow(newObj);
        
        System.out.println("Making the second call");
        balance = newAccount.balance();
        
        // Note the tcp stack should eliminate the bad connection eventually.
      } catch (org.omg.CORBA.TIMEOUT rttEx) {
      	// If you get a TIMEOUT exception here it should indicate a RoundTrip timeout
      	// not a Connection problem since the ConnectionTimeout should not throw 
      	// a TIMEOUT exception
      	rttEx.printStackTrace();
      } catch (Exception ex) {
      	// If this catch block is entered then the ORB was unable to 
      	// make a connection and so you would have the application do 
      	// something to indicate that a required endpoint was unreachable.
      	// Possible exceptions include OBJECT_NOT_EXIST, COMM_FAILURE, TRANSIENT
      	
        System.out.println("This indicates that there is some kind of network problem");
        ex.printStackTrace();
      	// You could rethrow the exception here if required for correct logging
      }
    }
    System.out.println ("The final invocation balance in "   name 
                             "'s account is $"   balance);

    } catch (Exception e) {
       e.printStackTrace();
    }
  }
}

 


#Security
#VisiBroker