xref: /PHP-8.3/ext/oci8/oci8_failover.c (revision 01b3fc03)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Stig Sæther Bakken <ssb@php.net>                            |
14    |          Thies C. Arntzen <thies@thieso.net>                         |
15    |                                                                      |
16    | Collection support by Andy Sautins <asautins@veripost.net>           |
17    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
18    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
19    |                                                                      |
20    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
21    |                Andi Gutmans <andi@php.net>                           |
22    |                Wez Furlong <wez@omniti.com>                          |
23    +----------------------------------------------------------------------+
24 */
25 
26 
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include "php.h"
33 #include "ext/standard/info.h"
34 #include "php_ini.h"
35 
36 #ifdef HAVE_OCI8
37 
38 #include "php_oci8.h"
39 #include "php_oci8_int.h"
40 
41 /* {{{ callback_fn()
42    OCI TAF callback function, calling userspace function */
callback_fn(void * svchp,void * envhp,void * fo_ctx,ub4 fo_type,ub4 fo_event)43 sb4 callback_fn(void *svchp, void *envhp, void *fo_ctx, ub4 fo_type, ub4 fo_event)
44 {
45 	/* Create zval */
46 	zval retval, params[3];
47     php_oci_connection *connection = (php_oci_connection*)fo_ctx;
48 
49 	/* Default return value */
50 	sb4 returnValue = 0;
51 
52 	/* Check if userspace callback function was unregistered */
53 	if (Z_ISUNDEF(connection->taf_callback) || Z_ISNULL(connection->taf_callback)) {
54 		return 0;
55 	}
56 
57 	/* Initialize zval */
58 	ZVAL_RES(&params[0], connection->id);
59 	ZVAL_LONG(&params[1], fo_event);
60 	ZVAL_LONG(&params[2], fo_type);
61 
62 	/* Call user function (if possible) */
63 	if (call_user_function(NULL, NULL, &connection->taf_callback, &retval, 3, params) == FAILURE) {
64 		php_error_docref(NULL, E_WARNING, "Unable to call Oracle TAF callback function");
65 	}
66 
67 	/* Set return value */
68 	if (Z_TYPE(retval) == IS_LONG) {
69 		returnValue = (sb4) Z_LVAL(retval);
70 	}
71 
72 	/* Setting params[0] to null so resource isn't destroyed on zval_ptr_dtor */
73 	ZVAL_NULL(&params[0]);
74 
75 	/* Cleanup */
76 	zval_ptr_dtor(&retval);
77 	zval_ptr_dtor(&params[0]);
78 	zval_ptr_dtor(&params[1]);
79 	zval_ptr_dtor(&params[2]);
80 
81 	return returnValue;
82 }
83 /* }}} */
84 
85 /* {{{ php_oci_unregister_taf_callback()
86    Unregister the userspace callback function for Oracle TAF,
87    while keeping the OCI callback alive */
php_oci_unregister_taf_callback(php_oci_connection * connection)88 int php_oci_unregister_taf_callback(php_oci_connection *connection)
89 {
90 	return php_oci_register_taf_callback(connection, NULL);
91 }
92 /* }}} */
93 
94 /* {{{ php_oci_register_taf_callback()
95    Register a callback function for Oracle TAF */
php_oci_register_taf_callback(php_oci_connection * connection,zval * callback)96 int php_oci_register_taf_callback(php_oci_connection *connection, zval *callback)
97 {
98 	sword errstatus;
99 	int registered = 0;
100 
101 	/* temporary failover callback structure */
102 	OCIFocbkStruct failover;
103 
104 	if (!callback) {
105 		/* Unregister callback */
106 		if (Z_ISUNDEF(connection->taf_callback) || Z_ISNULL(connection->taf_callback)) {
107 			return 0; // Nothing to unregister
108 		}
109 
110 		registered = 1;
111 		zval_ptr_dtor(&connection->taf_callback);
112 		ZVAL_NULL(&connection->taf_callback);
113 	} else {
114 		if (!Z_ISUNDEF(connection->taf_callback)) {
115 			registered = 1;
116 			if (!Z_ISNULL(connection->taf_callback)) {
117 				zval_ptr_dtor(&connection->taf_callback);
118 				ZVAL_NULL(&connection->taf_callback);
119 			}
120 		}
121 
122 		/* Set userspace callback function */
123 		ZVAL_COPY(&connection->taf_callback, callback);
124 	}
125 
126 	/* OCI callback function already registered */
127 	if (registered) {
128 		return 0;
129 	}
130 
131 	/* set context */
132 	failover.fo_ctx = connection;
133 
134 	/* set callback function */
135 	failover.callback_function = &callback_fn;
136 
137 	/* do the registration */
138 	PHP_OCI_CALL_RETURN(errstatus, OCIAttrSet, (connection->server, (ub4) OCI_HTYPE_SERVER, (void *) &failover, (ub4) 0, (ub4) OCI_ATTR_FOCBK, connection->err));
139 
140 	if (errstatus  != OCI_SUCCESS) {
141 		zval_ptr_dtor(&connection->taf_callback);
142 		ZVAL_UNDEF(&connection->taf_callback);
143 		connection->errcode = php_oci_error(connection->err, errstatus);
144 		return 1;
145 	}
146 
147 	/* successful conclusion */
148 	return 0;
149 }
150 /* }}} */
151 
152 #endif /* HAVE_OCI8 */
153