oci8 - Implementation of Oracle TAF Callback (PHP5)#2405
oci8 - Implementation of Oracle TAF Callback (PHP5)#2405KoenigsKind wants to merge 2 commits intophp:PHP-5.6.30from
Conversation
Adds support for the Transparent Application Failover Callback. The php_oci_connection struct got a char* added which will contain the callback function, it should be set to PHP_OCI_TAF_DISABLE_CALLBACK at the end of a php request for permanent connections so that, if a TAF callback occurs, no userspace function will be called. Maybe add support for registering object functions (via array), currently the register function only accepts a string. I didn't know how to implement it correctly. As a failover occurs very rarely it might be better to not keep the cache when saving the zend_fcall_info. Things to do [ ] config.m4 needs to compile oci8_failover.c [ ] Check if correctly implemented (especially for multithreading) [ ] Add support for object functions
|
PHP 5.6 is no longer actively supported, so this change cannot go into PHP 5.6. As this is a feature addition, the correct branch to target would be |
|
Tagging @tianfyang |
|
The implementation looks good! I just have a question on php_oci_disable_taf_callback(). It seems to unset the user's callback function but callback_fn() in OCI8 driver will still be called. It might be better to set failover.fo_ctx and failover.callback_function to NULL to completely unregister TAF. Also, as nikic mentioned, the new feature will be merged to master. With PHP7 , MAKE_STD_ZVAL() needs to be removed and ZVAL_RESOURCE needs to replaced by ZVAL_RES. Can you please add a test to demonstrate the usage of TAF in PHP? Meantime, I will do more testing to ensure the behavior is expected. |
| char *callback = NULL; | ||
| int callback_len = 0; | ||
|
|
||
| if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!", &z_connection, &callback, &callback_len) == FAILURE) { |
There was a problem hiding this comment.
Currently this restricts the callback to being a string. It would be preferable to accept a general "callable" here (such as a closure). For this the f modifier is used together with zend_fcall_info * and zend_fcall_info_cache * arguments. A look at
Line 5997 in edfa87e
There was a problem hiding this comment.
Right, I just didn't know how to properly store the zend_fcall_info for later. Also a callback rarely occurs so it probably would be better to store the zend_fcall_info without the cache.
I'm fairly new to PHP extension writing and still don't fully understand the zval reference counter; as the zend_fcall_info contains multiple zval, would I have to increase all of them? And do I actually have to increase the counter after receiving the zend_fcall_info? It's hard to find answers to such questions - or maybe I'm just looking at the wrong locations ^^
There was a problem hiding this comment.
I don't have a great answer here -- fcall_info is a bit of a mess. The simplest way to handle this is probably to not bother: Instead accept a zval, use zend_is_callable to make sure it's callable and store that zval (with ZVAL_COPY). Then pass it to call_user_function the way you do now. As you say, this callback will not be commonly invoked, so there is no performance advantage to properly managing fci/fcc here.
Thanks :)
I will try to implement it for PHP7 :)
Do you mean a phpt test? I’ll try to create one, though I don’t know how to cause a failover via PHP. |
|
I don't think committing a phpt test makes a lot of sense since the tests have to run cleanly in lots of different environments. We can add some tests to our not-at-all-portable release suite. However knowing what you've tested, and how, will be helpful. |
Added a short and a more detailed example of how to use the TAF Callback. I wasn't able to check if the scripts run through, but the basic concept should be understandable.
The basic concept: The PHP files I used got lost through some unfortunate events, but I wrote two example files which should show the way I did it. I wasn't able to test the scripts, so there might still be some typos in them. Things I've tested
|
tianfyang
left a comment
There was a problem hiding this comment.
Just went back to TAF today from a few other escalated works. Thanks a lot for the examples. I can successfully enable TAF with your implementation now.
I saw a memory leak. Please see my comment inline.
I will do more testing, including threading mode.
| #endif /* HAVE_OCI8_DTRACE */ | ||
|
|
||
| if (connection->taf_callback) { | ||
| pefree(connection->taf_callback, connection->is_persistent); |
There was a problem hiding this comment.
connection->taf_callback needs to be set to NULL, otherwise a memory leak may occur. While disconnecting from a normal connection, php_oci_connection_close() gets called before php_oci_disable_taf_callback(). If connection->taf_callback is not set to NULL, it gets reallocated and filled with PHP_OCI_TAF_DISABLE_CALLBACK in the last call of php_oci_disable_taf_callback(). However, php_oci_connection_close() has already been called at this point and connection->taf_callback will not be freed. Thus, a memory leak occurs.
|
@nikic Would this work? And then do a commit with my new implementation for PHP 7. |
|
@KoenigsKind In this case a new probably PR makes more sense, if only to preserve the PHP 5.6 implementation for future reference. (But force push + change of base branch on github is also fine) |
|
Created new pull request for PHP 7: #2459 |
|
@KoenigsKind FYI @tianfyang will be busy/away for a bit, so have patience. |
|
Closing this in favor of PR #2459 for PHP 7. |
Adds support for the Transparent Application Failover Callback.
The php_oci_connection struct got a char* added which will contain the callback function, it should be set to PHP_OCI_TAF_DISABLE_CALLBACK at the end of a php request for permanent connections so that, if a TAF callback occurs, no userspace function will be called.
Maybe add support for registering object functions (via array), currently the register function only accepts a string. I didn't know how to implement it correctly. As a failover occurs very rarely it might be better to not keep the cache when saving the zend_fcall_info.
Things to do
New pull request
Created a new pull request for PHP 7: #2459