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