-
Notifications
You must be signed in to change notification settings - Fork 8k
oci8 - Implementation of Oracle TAF Callback (PHP5) #2405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
| PHP_FUNCTION(array_map) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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