6 Replies Latest reply: Oct 19, 2005 5:58 AM by user455466 RSS

    OCI failover callback in a OCCI program

    user455401
      5. jose_luis_fdez_diaz_n...@yahoo.es      Oct 5, 12:47 pm show options
      Newsgroups: comp.databases.oracle.server
      From: jose_luis_fdez_diaz_n...@yahoo.es - Find messages by this author
      Date: 5 Oct 2005 03:47:09 -0700
      Local: Wed, Oct 5 2005 12:47 pm
      Subject: Re: OCCI Connection Pool on Oracle RAC
      Reply | Reply to Author | Forward | Print | Individual Message | Show original | Remove | Report Abuse

      Is it possible from OCCI program to use OCI's library failover callback
      as show in the code below:

      . . .
      conn = env->createConnection (user, passwd, db);
      . . .

      OCIFocbkStruct failover; /* failover callback
      structure */
      /* allocate memory for context */
      failover.fo_ctx = (dvoid *)malloc(strlen("my context."));

      /* initialize the context. */
      failover.callback_function = &callback_fn;

      /* do the registration */
      OCIAttrSet(conn->getOCIServer(), (ub4) OCI_HTYPE_SERVER,
      (dvoid *) &failover, (ub4) 0,
      (ub4) OCI_ATTR_FOCBK, errhp)
      . . .

      Thanks,
      Jose Luis
        • 1. Re: OCI failover callback in a OCCI program
          kmohan
          you can do it. But TAF callback registration has been added in 10.2 OCCI. Please see the documentation for more details
          http://download-east.oracle.com/docs/cd/B19306_01/appdev.102/b14294/whatsnew.htm#sthref11
          • 2. Re: OCI failover callback in a OCCI program
            user455401
            I am using Oracle 9.2.0, so I guess that I am forced to do it. Does anybody kwow where can I get an example?

            Thanks,
            Jose Luis.
            • 3. Re: OCI failover callback in a OCCI program
              kmohan
              #include <occi.h>

              using namespace std;
              using namespace oracle::occi;

              typedef struct
              {
              Connection *occiconn;
              char data[50];
              } CtxStruct;

              sb4 my_tafcb(dvoid svchp, dvoid envhp, dvoid *fo_ctx, ub4 fo_type, ub4 fo_event)
              {
              cout << "fo_type = " << fo_type << "," << "fo_event = " << fo_event << endl;

              switch (fo_event)
              {
              case OCI_FO_BEGIN :
              {
              cout << "Server down ... failover starting, type = " << fo_type << endl;
              CtxStruct ctx = (CtxStruct )fo_ctx;
              cout << "Context data = " << ctx->data << endl;
              break;
              }

              case OCI_FO_ERROR :
              {
              cout << "Retrying again..." << endl;
              //sleep(5);
              return OCI_FO_RETRY;
              }

              case OCI_FO_ABORT :
              {
              cout << "Failover not possible!Aborted" << endl;
              break;
              }

              case OCI_FO_END :
              {
              cout << "Failover completed successfully" << endl;
              cout << "Reexecuting Alter session commands" << endl;

              //get the OCCI connection object from the ctx
              CtxStruct ctx = (CtxStruct )fo_ctx;
              Connection *conn = ctx->occiconn;

              Statement *stmt2 = conn->createStatement("alter session set nls_date_format='dd-month'");
              stmt2->execute();
              conn->terminateStatement(stmt2);
              break;
              }
              //OCI_FO_REAUTH need not be handled since OCCI does not support
              //multiple sessions on a single server handle
              }
              return 0;

              }

              main()
              {
              try
              {
              Environment *env = Environment::createEnvironment();
              Connection *conn = env->createConnection("scott","tiger", "testtaf");

              Statement *stmt = conn->createStatement("alter session set nls_date_format='dd-month'");
              stmt->execute();

              //set the TAF handler
              //need Error handle for OCIAttrSet
              OCIEnv *envhp = env->getOCIEnvironment();
              OCIError errhp = (OCIError )0;
              OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp, OCI_HTYPE_ERROR, 0, 0);

              //set the TAF handler on the server handle
              CtxStruct ctx;
              ctx.occiconn = conn;
              strcpy(ctx.data, "CONNECTION 1");
              OCIServer *svrhp = conn->getOCIServer();

              OCIFocbkStruct foc;
              foc.callback_function = (OCICallbackFailover)my_tafcb;
              foc.fo_ctx = (void *)&ctx;
              OCIAttrSet(svrhp, (ub4)OCI_HTYPE_SERVER,
              (dvoid *)&foc, (ub4)0,
              (ub4)OCI_ATTR_FOCBK, errhp);

              stmt = conn->createStatement("Select to_char(sysdate) From Emp");
              ResultSet *rs = stmt->executeQuery();

              int r = 0;

              while (r++ < 5)
              {
              rs->next();
              cout << rs->getString(1) << endl;
              }

              cout << "5 rows fetched...Stop and restart instance" << endl;
              string s;
              cin >> s;

              cout << "Continuing fetch..." << endl;

              while (rs->next())
              cout << rs->getString(1) << endl;

              stmt->closeResultSet(rs);
              conn->terminateStatement(stmt);

              env->terminateConnection(conn);
              Environment::terminateEnvironment(env);

              } catch (SQLException &ex)
              {
              cout << ex.getMessage() << endl;
              }
              }
              • 4. Re: OCI failover callback in a OCCI program
                user455401
                Thank you. This is just what I need.

                I am using a Connection Pool. I guess that failover is transparent to the Pool. I mean, it is not necessary to recreate the pool (terminateConnectionPool, createConnectionPool).


                Regards,
                Jose Luis.
                • 5. Re: OCI failover callback in a OCCI program
                  kmohan
                  Sorry, the above works only for normal connections and StatelessConnectionPool only, till 10.1.0.4. TAF does not work for Connection pools (in OCI and OCCI) till 10.1.0.4. It is supported only from 10.2 onwards. I hope that is clear.

                  For ConnectionPools, if the instance goes down and you get and exception, you can terminate that connection and try for a new one. The bad ones go off the pool as you terminate them and new good ones get created as you ask for more and all the bad ones have gone off the pool. You don't have to terminate the pool.
                  • 6. Re: OCI failover callback in a OCCI program
                    user455466
                    Hi,

                    On RAC failover when I try to get a connection from the Pool, an exception is raised:

                    ORA-03113: end-of-file on communication channel

                    Then I try to terminate the Connection Pool, but the exception below is raised:

                    ORA-24397: error occured while trying to free connections

                    Why this expception is raised ?

                    Thanks,
                    Jose Luis