[svn:dbd-oracle] r14813 - dbd-oracle/branches/TAF

[email protected] Mon, 4 Apr 2011 09:36:28 -0700 (PDT)
Newsgroups perl.dbd.oracle.changes
Message-ID <[email protected]>
Author: byterock
Date: Mon Apr  4 09:36:26 2011
New Revision: 14813

Modified:
   dbd-oracle/branches/TAF/Oracle.pm
   dbd-oracle/branches/TAF/Oracle.xs
   dbd-oracle/branches/TAF/dbdimp.c
   dbd-oracle/branches/TAF/dbdimp.h
   dbd-oracle/branches/TAF/oci8.c

Log:
working and pod all updated ready to go back into trunk

Modified: dbd-oracle/branches/TAF/Oracle.pm
==============================================================================
--- dbd-oracle/branches/TAF/Oracle.pm	(original)
+++ dbd-oracle/branches/TAF/Oracle.pm	Mon Apr  4 09:36:26 2011
@@ -71,22 +71,23 @@
 	    });
 	DBD::Oracle::dr::init_oci($drh) ;
 	$drh->STORE('ShowErrorStatement', 1);
-        DBD::Oracle::db->install_method("ora_lob_read");
-        DBD::Oracle::db->install_method("ora_lob_write");
-        DBD::Oracle::db->install_method("ora_lob_append");
-        DBD::Oracle::db->install_method("ora_lob_trim");
-        DBD::Oracle::db->install_method("ora_lob_length");
-        DBD::Oracle::db->install_method("ora_lob_chunk_size");
-        DBD::Oracle::db->install_method("ora_lob_is_init");
-        DBD::Oracle::db->install_method("ora_nls_parameters");
-        DBD::Oracle::db->install_method("ora_can_unicode");
- 	DBD::Oracle::st->install_method("ora_fetch_scroll");
- 	DBD::Oracle::st->install_method("ora_scroll_position");
- 	DBD::Oracle::st->install_method("ora_ping");
- 	DBD::Oracle::st->install_method("ora_stmt_type_name");
- 	DBD::Oracle::st->install_method("ora_stmt_type");
- 	$drh;
- 	
+	DBD::Oracle::db->install_method("ora_lob_read");
+	DBD::Oracle::db->install_method("ora_lob_write");
+	DBD::Oracle::db->install_method("ora_lob_append");
+	DBD::Oracle::db->install_method("ora_lob_trim");
+	DBD::Oracle::db->install_method("ora_lob_length");
+	DBD::Oracle::db->install_method("ora_lob_chunk_size");
+	DBD::Oracle::db->install_method("ora_lob_is_init");
+	DBD::Oracle::db->install_method("ora_nls_parameters");
+	DBD::Oracle::db->install_method("ora_can_unicode");
+	DBD::Oracle::db->install_method("ora_can_taf");
+	DBD::Oracle::st->install_method("ora_fetch_scroll");
+	DBD::Oracle::st->install_method("ora_scroll_position");
+	DBD::Oracle::st->install_method("ora_ping");
+	DBD::Oracle::st->install_method("ora_stmt_type_name");
+	DBD::Oracle::st->install_method("ora_stmt_type");
+	$drh;
+	
     }
 
 
@@ -1429,6 +1430,89 @@
 
 At this point in time this is just the first crack at DRCP and DBD::Oracle so the mechanics or its implementation are subject to change.
 
+=head2 TAF (Transparent Application Failover)
+Transparent Application Failover (TAF) is a longstanding default feature in OCI that allows for clients to automatically reconnect to 
+an instance in the event of a failure of an instance. The reconnect happens automatically from within the OCI (Oracle Call Interface) library.
+DBD::Oracle now supports a callback function that will fire when a callback event takes place. The main use of the callback is that it 
+gives the oppertunity for the program to inform the user that a failover is taking place.  
+
+You will have to set up TAF on your instance before you can use this callback.  You can test your instance to see if you can use TAF callback with 
+
+  $dbh->ora_can_taf();
+  
+If you try to set up a callback without it being enable DBD::Oracle will croak.
+
+It is outside the scope of this documents to go through all of the possiable TAF situations you might want to set up. Below is the simplest of examples;
+
+The TNS entry for the instace has had the following added to the CONNECT_DATA portion 
+
+   (FAILOVER_MODE=
+               (TYPE=select) 
+               (METHOD=basic)
+               (RETRIES=10)
+               (DELAY=10))
+
+You will also have to create your on perl function that will be called from the client.  You can name it anything you want and it will allways return
+two values, the failover event value and the failover type value.  You can also set a sleep value in case of failover error and the oci client will sleep 
+for the entered seconds before it attempts another event.
+
+  use DBD::Oracle(qw(:ora_fail_over));
+  #import the ora_fail_over constancts 
+  
+  #set up TAF on the conection
+  my $dbh = DBI->connect('dbi:Oracle:XE','hr','hr',{ora_taf=>1,taf_sleep=>5,ora_taf_function=>'handle_taft'});
+  
+  #create the perl TAF event function 
+  
+  sub handle_taf {
+    my ($fo_event,$fo_type) = @_;
+    if ($fo_event == OCI_FO_BEGIN){
+    
+      print(" Instance Unavailable Please stand by!! \n");
+      printf(" Your TAF type is %s \n",
+                       (($fo_type==OCI_FO_NONE) ? "NONE"
+                       :($fo_type==OCI_FO_SESSION) ? "SESSION"
+                       :($fo_type==OCI_FO_SELECT) ? "SELECT"
+                       : "UNKNOWN!"));
+    }
+    elsif ($fo_event == OCI_FO_ABORT){
+       printf(" Failover aborted. Failover will not take place.\n");
+    }
+    elsif ($fo_event == OCI_FO_END){
+       printf(" Failover ended ...Resuming your %s\n",(($fo_type==OCI_FO_NONE) ? "NONE"
+                                                      :($fo_type==OCI_FO_SESSION) ? "SESSION"
+                                                      :($fo_type==OCI_FO_SELECT) ? "SELECT"
+                                                      : "UNKNOWN!"));
+    }
+    elsif ($fo_event == OCI_FO_REAUTH){
+       printf(" Failed over user. Resuming services\n");
+    }
+    elsif ($fo_event == OCI_FO_ERROR){
+       printf(" Failover error Sleeping...\n");
+    }
+    else {
+       printf(" Bad Failover Event: %d.\n",  $fo_event);
+   
+    }
+    return 0;
+  }
+
+The TAF types are as follows
+
+  OCI_FO_SESSION which indicates the user has requested only session failover.
+  OCI_FO_SELECT which indicates the user has requested select failover.
+  OCI_FO_NONE which inicates the user has not requested a failover type.
+  OCI_FO_TXNAL which indicates the user has requested a transaction failover.
+
+The TAF events are as follows
+
+  OCI_FO_BEGIN indicates that failover has detected a lost connection and failover is starting.
+  OCI_FO_END   indicates successful completion of failover.
+  OCI_FO_ABORT indicates that failover was unsuccessful, and there is no option of retrying.
+  OCI_FO_ERROR also indicates that failover was unsuccessful, but it gives the application the opportunity to handle the error and retry failover.
+  OCI_FO_REAUTH indicates that you have multiple authentication handles and failover has occurred after the original authentication. It indicates that a user handle has been re-authenticated. To find out which, the application checks the OCI_ATTR_SESSION attribute of the service context handle (which is the first parameter).
+
+
 =head2 Optimizing Oracle's listener
 
 [By Lane Sharman <[email protected]>] I spent a LOT of time optimizing
@@ -1574,7 +1658,12 @@
 =item :ora_exe_modes
 
   OCI_STMT_SCROLLABLE_READONLY 
-  
+
+=item :ora_fail_over
+
+  OCI_FO_END OCI_FO_ABORT OCI_FO_REAUTH OCI_FO_BEGIN OCI_FO_ERROR 
+  OCI_FO_NONE OCI_FO_SESSION OCI_FO_SELECT OCI_FO_TXNAL
+
 =back
 
 =head1 Attributes

Modified: dbd-oracle/branches/TAF/Oracle.xs
==============================================================================
--- dbd-oracle/branches/TAF/Oracle.xs	(original)
+++ dbd-oracle/branches/TAF/Oracle.xs	Mon Apr  4 09:36:26 2011
@@ -70,6 +70,7 @@
 	OUTPUT:
 	RETVAL
 
+
 void
 ORA_OCI()
 	CODE:
@@ -266,6 +267,23 @@
 
 MODULE = DBD::Oracle	PACKAGE = DBD::Oracle::db
 
+void
+ora_can_taf(dbh)
+	SV 				*dbh
+	PREINIT:
+	D_imp_dbh(dbh);
+	sword status;
+	ub4 can_taf = 0;
+	CODE:
+	OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL,
+				OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status);
+	if (status != OCI_SUCCESS) {
+		oci_error(dbh, imp_dbh->errhp, status, "OCIAttrGet OCI_ATTR_TAF_ENABLED");
+		XSRETURN_IV(0);
+	}
+	else {
+		XSRETURN_IV(can_taf);
+	}
 
 void
 ora_ping(dbh)

Modified: dbd-oracle/branches/TAF/dbdimp.c
==============================================================================
--- dbd-oracle/branches/TAF/dbdimp.c	(original)
+++ dbd-oracle/branches/TAF/dbdimp.c	Mon Apr  4 09:36:26 2011
@@ -1061,11 +1061,11 @@
 
     if (imp_dbh->using_taf){
 		bool	can_taf;
-        OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL,
+		OCIAttrGet_log_stat(imp_dbh->srvhp, OCI_HTYPE_SERVER, &can_taf, NULL,
 				OCI_ATTR_TAF_ENABLED, imp_dbh->errhp, status);
 
 		if (!can_taf){
-				croak("You are attempting to enable TAF on a server that is not TAF Enabled \n");
+			croak("You are attempting to enable TAF on a server that is not TAF Enabled \n");
 		}
 
 		if (DBIS->debug >= 4 || dbd_verbose >= 4 ) {
@@ -1244,6 +1244,15 @@
 			goto dbd_db_destroy_out;
 		if (!imp_dbh->proc_handles)	{
 			sword status;
+			if (imp_dbh->using_taf){
+				OCIFocbkStruct 	tafailover;
+				tafailover.fo_ctx = NULL;
+				tafailover.callback_function = NULL;
+				OCIAttrSet_log_stat(imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER,
+								(dvoid *) &tafailover, (ub4) 0,
+								(ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status);
+
+			}
 #ifdef ORA_OCI_112
 			if (imp_dbh->using_drcp) {
 				OCIHandleFree_log_stat(imp_dbh->authp, OCI_HTYPE_SESSION,status);

Modified: dbd-oracle/branches/TAF/dbdimp.h
==============================================================================
--- dbd-oracle/branches/TAF/dbdimp.h	(original)
+++ dbd-oracle/branches/TAF/dbdimp.h	Mon Apr  4 09:36:26 2011
@@ -60,7 +60,7 @@
 	char		*driver_name;/*driver name user defined*/
 	ub4			driver_namel;
 #endif
-/*	taf_callback_t  *taf_callback;*/
+	taf_callback_t  *taf_callback;
     bool		using_taf; /*TAF stuff*/
     char		*taf_function; /*User supplied TAF functiomn*/
     int			taf_sleep;

Modified: dbd-oracle/branches/TAF/oci8.c
==============================================================================
--- dbd-oracle/branches/TAF/oci8.c	(original)
+++ dbd-oracle/branches/TAF/oci8.c	Mon Apr  4 09:36:26 2011
@@ -1323,11 +1323,6 @@
 	XPUSHs(sv_2mortal(newSViv(fo_event)));
 	XPUSHs(sv_2mortal(newSViv(fo_type)));
 	PUTBACK;
-
-	PerlIO_printf(DBILOGFP, "taf_cbk mp_drh=%p\n",cb);
-PerlIO_printf(DBILOGFP, "taf_cbk ora_taf_function=%s\n",cb->function);
-
-PerlIO_printf(DBILOGFP, " taf_sleep=%d\n",cb->sleep);
 	call_pv(cb->function, G_DISCARD);
 
 	switch (fo_event){
@@ -1362,24 +1357,22 @@
 	OCIFocbkStruct 	tafailover;
 	sword 			status;
 	taf_callback_t  *cb = NULL;
+/*allocate space for the callback */
 	Newz(1, cb, 1, taf_callback_t);
 	cb->function= (char*)safemalloc(strlen(imp_dbh->taf_function));
 	cb->sleep   = imp_dbh->taf_sleep;
 	strcpy((char *)cb->function,imp_dbh->taf_function);
 
-  	if (dbd_verbose >= 5 ) {
-  		PerlIO_printf(DBILOGFP, " In reg_taf_callback\n");
+	if (dbd_verbose >= 5 ) {
+		PerlIO_printf(DBILOGFP, " In reg_taf_callback perl callback is %s\n",imp_dbh->taf_function);
 	}
+	imp_dbh->taf_callback = cb;
 
-/* set the context up as a pointer to the handle*/
-PerlIO_printf(DBILOGFP, " sizeof(imp_dbh)=%d\n",strlen(imp_dbh->taf_function));
-
+/* set the context up as a pointer to the taf callback struct*/
 	tafailover.fo_ctx = cb;
-
 	tafailover.callback_function = &taf_cbk;
 
-PerlIO_printf(DBILOGFP, " reg_taf_callback=%s\n",cb->function);
-PerlIO_printf(DBILOGFP, " reg_taf_callback=%p\n",imp_dbh);
+/* register the callback */
 	OCIAttrSet_log_stat(imp_dbh->srvhp, (ub4) OCI_HTYPE_SERVER,
 								(dvoid *) &tafailover, (ub4) 0,
 								(ub4) OCI_ATTR_FOCBK, imp_dbh->errhp, status);