aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/php/ext/grpc/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/php/ext/grpc/channel.c')
-rw-r--r--src/php/ext/grpc/channel.c444
1 files changed, 287 insertions, 157 deletions
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index f3a03ace09..b17f3d9a61 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -18,13 +18,6 @@
#include "channel.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <php.h>
-#include <php_ini.h>
-#include <ext/standard/info.h>
#include <ext/standard/php_var.h>
#include <ext/standard/sha1.h>
#if PHP_MAJOR_VERSION < 7
@@ -33,68 +26,64 @@
#include <zend_smart_str.h>
#endif
#include <ext/spl/spl_exceptions.h>
-#include "php_grpc.h"
-
#include <zend_exceptions.h>
-#include <stdbool.h>
-
-#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/support/alloc.h>
#include "completion_queue.h"
#include "channel_credentials.h"
-#include "server.h"
#include "timeval.h"
zend_class_entry *grpc_ce_channel;
-#if PHP_MAJOR_VERSION >= 7
-static zend_object_handlers channel_ce_handlers;
-#endif
+PHP_GRPC_DECLARE_OBJECT_HANDLER(channel_ce_handlers)
static gpr_mu global_persistent_list_mu;
int le_plink;
+int le_bound;
extern HashTable grpc_persistent_list;
+extern HashTable grpc_target_upper_bound_map;
+
+void free_grpc_channel_wrapper(grpc_channel_wrapper* channel, bool free_channel) {
+ if (free_channel) {
+ grpc_channel_destroy(channel->wrapped);
+ channel->wrapped = NULL;
+ }
+ free(channel->target);
+ free(channel->args_hashstr);
+ free(channel->creds_hashstr);
+ free(channel->key);
+ channel->target = NULL;
+ channel->args_hashstr = NULL;
+ channel->creds_hashstr = NULL;
+ channel->key = NULL;
+}
+
+void php_grpc_channel_ref(grpc_channel_wrapper* wrapper) {
+ gpr_mu_lock(&wrapper->mu);
+ wrapper->ref_count += 1;
+ gpr_mu_unlock(&wrapper->mu);
+}
+
+void php_grpc_channel_unref(grpc_channel_wrapper* wrapper) {
+ gpr_mu_lock(&wrapper->mu);
+ wrapper->ref_count -= 1;
+ if (wrapper->ref_count == 0) {
+ free_grpc_channel_wrapper(wrapper, true);
+ gpr_mu_unlock(&wrapper->mu);
+ free(wrapper);
+ wrapper = NULL;
+ return;
+ }
+ gpr_mu_unlock(&wrapper->mu);
+}
/* Frees and destroys an instance of wrapped_grpc_channel */
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
// In_persistent_list is used when the user don't close the channel,
// In this case, channels not in the list should be freed.
- bool in_persistent_list = true;
if (p->wrapper != NULL) {
- gpr_mu_lock(&p->wrapper->mu);
- if (p->wrapper->wrapped != NULL) {
- if (p->wrapper->is_valid) {
- php_grpc_zend_resource *rsrc;
- php_grpc_int key_len = strlen(p->wrapper->key);
- // only destroy the channel here if not found in the persistent list
- gpr_mu_lock(&global_persistent_list_mu);
- if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, p->wrapper->key,
- key_len, rsrc))) {
- in_persistent_list = false;
- grpc_channel_destroy(p->wrapper->wrapped);
- free(p->wrapper->target);
- free(p->wrapper->args_hashstr);
- if (p->wrapper->creds_hashstr != NULL) {
- free(p->wrapper->creds_hashstr);
- p->wrapper->creds_hashstr = NULL;
- }
- free(p->wrapper->key);
- p->wrapper->wrapped = NULL;
- p->wrapper->target = NULL;
- p->wrapper->args_hashstr = NULL;
- p->wrapper->key = NULL;
- }
- gpr_mu_unlock(&global_persistent_list_mu);
- }
- }
- p->wrapper->ref_count -= 1;
- gpr_mu_unlock(&p->wrapper->mu);
- if (!in_persistent_list) {
- gpr_mu_destroy(&p->wrapper->mu);
- free(p->wrapper);
- p->wrapper = NULL;
- }
+ php_grpc_channel_unref(p->wrapper);
+ p->wrapper = NULL;
}
PHP_GRPC_FREE_WRAPPED_FUNC_END()
@@ -162,6 +151,67 @@ void generate_sha1_str(char *sha1str, char *str, php_grpc_int len) {
make_sha1_digest(sha1str, digest);
}
+bool php_grpc_persistent_list_delete_unused_channel(
+ char* target,
+ target_bound_le_t* target_bound_status TSRMLS_DC) {
+ zval *data;
+ PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
+ php_grpc_zend_resource *rsrc = (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
+ if (rsrc == NULL) {
+ break;
+ }
+ channel_persistent_le_t* le = rsrc->ptr;
+ // Find the channel sharing the same target.
+ if (strcmp(le->channel->target, target) == 0) {
+ // ref_count=1 means that only the map holds the reference to the channel.
+ if (le->channel->ref_count == 1) {
+ php_grpc_delete_persistent_list_entry(le->channel->key,
+ strlen(le->channel->key)
+ TSRMLS_CC);
+ target_bound_status->current_count -= 1;
+ if (target_bound_status->current_count < target_bound_status->upper_bound) {
+ return true;
+ }
+ }
+ }
+ PHP_GRPC_HASH_FOREACH_END()
+ return false;
+}
+
+target_bound_le_t* update_and_get_target_upper_bound(char* target, int bound) {
+ php_grpc_zend_resource *rsrc;
+ target_bound_le_t* target_bound_status;
+ php_grpc_int key_len = strlen(target);
+ if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_target_upper_bound_map, target,
+ key_len, rsrc))) {
+ // Target is not not persisted.
+ php_grpc_zend_resource new_rsrc;
+ target_bound_status = malloc(sizeof(target_bound_le_t));
+ if (bound == -1) {
+ // If the bound is not set, use 1 as default.s
+ bound = 1;
+ }
+ target_bound_status->upper_bound = bound;
+ // Init current_count with 1. It should be add 1 when the channel is successfully
+ // created and minus 1 when it is removed from the persistent list.
+ target_bound_status->current_count = 0;
+ new_rsrc.type = le_bound;
+ new_rsrc.ptr = target_bound_status;
+ gpr_mu_lock(&global_persistent_list_mu);
+ PHP_GRPC_PERSISTENT_LIST_UPDATE(&grpc_target_upper_bound_map,
+ target, key_len, (void *)&new_rsrc);
+ gpr_mu_unlock(&global_persistent_list_mu);
+ } else {
+ // The target already in the map recording the upper bound.
+ // If no newer bound set, use the original now.
+ target_bound_status = (target_bound_le_t *)rsrc->ptr;
+ if (bound != -1) {
+ target_bound_status->upper_bound = bound;
+ }
+ }
+ return target_bound_status;
+}
+
void create_channel(
wrapped_grpc_channel *channel,
char *target,
@@ -174,6 +224,8 @@ void create_channel(
channel->wrapper->wrapped =
grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
}
+ // There is an Grpc\Channel object refer to it.
+ php_grpc_channel_ref(channel->wrapper);
efree(args.args);
}
@@ -183,7 +235,28 @@ void create_and_add_channel_to_persistent_list(
grpc_channel_args args,
wrapped_grpc_channel_credentials *creds,
char *key,
- php_grpc_int key_len TSRMLS_DC) {
+ php_grpc_int key_len,
+ int target_upper_bound TSRMLS_DC) {
+ target_bound_le_t* target_bound_status =
+ update_and_get_target_upper_bound(target, target_upper_bound);
+ // Check the upper bound status before inserting to the persistent map.
+ if (target_bound_status->current_count >=
+ target_bound_status->upper_bound) {
+ if (!php_grpc_persistent_list_delete_unused_channel(
+ target, target_bound_status TSRMLS_CC)) {
+ // If no channel can be deleted from the persistent map,
+ // do not persist this one.
+ create_channel(channel, target, args, creds);
+ php_printf("[Warning] The number of channel for the"
+ " target %s is maxed out bounded.\n", target);
+ php_printf("[Warning] Target upper bound: %d. Current size: %d.\n",
+ target_bound_status->upper_bound,
+ target_bound_status->current_count);
+ php_printf("[Warning] Target %s will not be persisted.\n", target);
+ return;
+ }
+ }
+ // There is space in the persistent map.
php_grpc_zend_resource new_rsrc;
channel_persistent_le_t *le;
// this links each persistent list entry to a destructor
@@ -191,13 +264,15 @@ void create_and_add_channel_to_persistent_list(
le = malloc(sizeof(channel_persistent_le_t));
create_channel(channel, target, args, creds);
+ target_bound_status->current_count += 1;
le->channel = channel->wrapper;
- le->ref_count = 1;
new_rsrc.ptr = le;
gpr_mu_lock(&global_persistent_list_mu);
PHP_GRPC_PERSISTENT_LIST_UPDATE(&grpc_persistent_list, key, key_len,
(void *)&new_rsrc);
+ // Persistent map refer to it.
+ php_grpc_channel_ref(channel->wrapper);
gpr_mu_unlock(&global_persistent_list_mu);
}
@@ -220,7 +295,8 @@ void create_and_add_channel_to_persistent_list(
* @param array $args_array The arguments to pass to the Channel
*/
PHP_METHOD(Channel, __construct) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
zval *creds_obj = NULL;
char *target;
php_grpc_int target_length;
@@ -231,6 +307,7 @@ PHP_METHOD(Channel, __construct) {
php_grpc_zend_resource *rsrc;
bool force_new = false;
zval *force_new_obj = NULL;
+ int target_upper_bound = -1;
/* "sa" == 1 string, 1 array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target,
@@ -252,7 +329,8 @@ PHP_METHOD(Channel, __construct) {
1 TSRMLS_CC);
return;
} else {
- creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj);
+ creds = PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel_credentials,
+ creds_obj);
php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
}
}
@@ -264,6 +342,19 @@ PHP_METHOD(Channel, __construct) {
php_grpc_zend_hash_del(array_hash, "force_new", sizeof("force_new"));
}
+ if (php_grpc_zend_hash_find(array_hash, "grpc_target_persist_bound",
+ sizeof("grpc_target_persist_bound"),
+ (void **)&force_new_obj) == SUCCESS) {
+ if (Z_TYPE_P(force_new_obj) != IS_LONG) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
+ "plist_bound must be a number",
+ 1 TSRMLS_CC);
+ }
+ target_upper_bound = (int)Z_LVAL_P(force_new_obj);
+ php_grpc_zend_hash_del(array_hash, "grpc_target_persist_bound",
+ sizeof("grpc_target_persist_bound"));
+ }
+
// parse the rest of the channel args array
if (php_grpc_read_args_array(args_array, &args TSRMLS_CC) == FAILURE) {
efree(args.args);
@@ -297,12 +388,11 @@ PHP_METHOD(Channel, __construct) {
strcat(key, creds->hashstr);
}
channel->wrapper = malloc(sizeof(grpc_channel_wrapper));
+ channel->wrapper->ref_count = 0;
channel->wrapper->key = key;
channel->wrapper->target = strdup(target);
channel->wrapper->args_hashstr = strdup(sha1str);
channel->wrapper->creds_hashstr = NULL;
- channel->wrapper->ref_count = 1;
- channel->wrapper->is_valid = true;
if (creds != NULL && creds->hashstr != NULL) {
php_grpc_int creds_hashstr_len = strlen(creds->hashstr);
char *channel_creds_hashstr = malloc(creds_hashstr_len + 1);
@@ -320,7 +410,7 @@ PHP_METHOD(Channel, __construct) {
} else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, key,
key_len, rsrc))) {
create_and_add_channel_to_persistent_list(
- channel, target, args, creds, key, key_len TSRMLS_CC);
+ channel, target, args, creds, key, key_len, target_upper_bound TSRMLS_CC);
} else {
// Found a previously stored channel in the persistent list
channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
@@ -330,21 +420,17 @@ PHP_METHOD(Channel, __construct) {
strcmp(creds->hashstr, le->channel->creds_hashstr) != 0)) {
// somehow hash collision
create_and_add_channel_to_persistent_list(
- channel, target, args, creds, key, key_len TSRMLS_CC);
+ channel, target, args, creds, key, key_len, target_upper_bound TSRMLS_CC);
} else {
efree(args.args);
- if (channel->wrapper->creds_hashstr != NULL) {
- free(channel->wrapper->creds_hashstr);
- channel->wrapper->creds_hashstr = NULL;
- }
- free(channel->wrapper->creds_hashstr);
- free(channel->wrapper->key);
- free(channel->wrapper->target);
- free(channel->wrapper->args_hashstr);
+ free_grpc_channel_wrapper(channel->wrapper, false);
+ gpr_mu_destroy(&channel->wrapper->mu);
free(channel->wrapper);
- le->ref_count += 1;
+ channel->wrapper = NULL;
channel->wrapper = le->channel;
- channel->wrapper->ref_count += 1;
+ // One more Grpc\Channel object refer to it.
+ php_grpc_channel_ref(channel->wrapper);
+ update_and_get_target_upper_bound(target, target_upper_bound);
}
}
}
@@ -354,14 +440,15 @@ PHP_METHOD(Channel, __construct) {
* @return string The URI of the endpoint
*/
PHP_METHOD(Channel, getTarget) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ if (channel->wrapper == NULL) {
zend_throw_exception(spl_ce_RuntimeException,
- "Channel already closed", 1 TSRMLS_CC);
- gpr_mu_unlock(&channel->wrapper->mu);
+ "getTarget error."
+ "Channel is already closed.", 1 TSRMLS_CC);
return;
}
+ gpr_mu_lock(&channel->wrapper->mu);
char *target = grpc_channel_get_target(channel->wrapper->wrapped);
gpr_mu_unlock(&channel->wrapper->mu);
PHP_GRPC_RETVAL_STRING(target, 1);
@@ -374,17 +461,16 @@ PHP_METHOD(Channel, getTarget) {
* @return long The grpc connectivity state
*/
PHP_METHOD(Channel, getConnectivityState) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ if (channel->wrapper == NULL) {
zend_throw_exception(spl_ce_RuntimeException,
- "Channel already closed", 1 TSRMLS_CC);
- gpr_mu_unlock(&channel->wrapper->mu);
+ "getConnectivityState error."
+ "Channel is already closed.", 1 TSRMLS_CC);
return;
}
-
+ gpr_mu_lock(&channel->wrapper->mu);
bool try_to_connect = false;
-
/* "|b" == 1 optional bool */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect)
== FAILURE) {
@@ -395,11 +481,6 @@ PHP_METHOD(Channel, getConnectivityState) {
}
int state = grpc_channel_check_connectivity_state(channel->wrapper->wrapped,
(int)try_to_connect);
- // this can happen if another shared Channel object close the underlying
- // channel
- if (state == GRPC_CHANNEL_SHUTDOWN) {
- channel->wrapper->wrapped = NULL;
- }
gpr_mu_unlock(&channel->wrapper->mu);
RETURN_LONG(state);
}
@@ -412,15 +493,15 @@ PHP_METHOD(Channel, getConnectivityState) {
* before deadline
*/
PHP_METHOD(Channel, watchConnectivityState) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped == NULL) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ if (channel->wrapper == NULL) {
zend_throw_exception(spl_ce_RuntimeException,
- "Channel already closed", 1 TSRMLS_CC);
- gpr_mu_unlock(&channel->wrapper->mu);
+ "watchConnectivityState error"
+ "Channel is already closed.", 1 TSRMLS_CC);
return;
}
-
+ gpr_mu_lock(&channel->wrapper->mu);
php_grpc_long last_state;
zval *deadline_obj;
@@ -435,7 +516,8 @@ PHP_METHOD(Channel, watchConnectivityState) {
return;
}
- wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
+ wrapped_grpc_timeval *deadline =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_timeval, deadline_obj);
grpc_channel_watch_connectivity_state(channel->wrapper->wrapped,
(grpc_connectivity_state)last_state,
deadline->wrapped, completion_queue,
@@ -452,47 +534,12 @@ PHP_METHOD(Channel, watchConnectivityState) {
* @return void
*/
PHP_METHOD(Channel, close) {
- wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
- bool is_last_wrapper = false;
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
if (channel->wrapper != NULL) {
- // Channel_wrapper hasn't call close before.
- gpr_mu_lock(&channel->wrapper->mu);
- if (channel->wrapper->wrapped != NULL) {
- if (channel->wrapper->is_valid) {
- // Wrapped channel hasn't been destoryed by other wrapper.
- grpc_channel_destroy(channel->wrapper->wrapped);
- free(channel->wrapper->target);
- free(channel->wrapper->args_hashstr);
- free(channel->wrapper->creds_hashstr);
- channel->wrapper->creds_hashstr = NULL;
- channel->wrapper->target = NULL;
- channel->wrapper->args_hashstr = NULL;
- channel->wrapper->wrapped = NULL;
- channel->wrapper->is_valid = false;
-
- php_grpc_delete_persistent_list_entry(channel->wrapper->key,
- strlen(channel->wrapper->key)
- TSRMLS_CC);
- }
- }
- channel->wrapper->ref_count -= 1;
- if (channel->wrapper->ref_count == 0) {
- // Mark that the wrapper can be freed because mu should be
- // destroyed outside the lock.
- is_last_wrapper = true;
- }
- gpr_mu_unlock(&channel->wrapper->mu);
- }
- gpr_mu_lock(&global_persistent_list_mu);
- if (is_last_wrapper) {
- gpr_mu_destroy(&channel->wrapper->mu);
- free(channel->wrapper->key);
- free(channel->wrapper);
+ php_grpc_channel_unref(channel->wrapper);
+ channel->wrapper = NULL;
}
- // Set channel->wrapper to NULL to avoid call close twice for the same
- // channel.
- channel->wrapper = NULL;
- gpr_mu_unlock(&global_persistent_list_mu);
}
// Delete an entry from the persistent list
@@ -503,11 +550,7 @@ void php_grpc_delete_persistent_list_entry(char *key, php_grpc_int key_len
gpr_mu_lock(&global_persistent_list_mu);
if (PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, key,
key_len, rsrc)) {
- channel_persistent_le_t *le;
- le = (channel_persistent_le_t *)rsrc->ptr;
- le->channel = NULL;
php_grpc_zend_hash_del(&grpc_persistent_list, key, key_len+1);
- free(le);
}
gpr_mu_unlock(&global_persistent_list_mu);
}
@@ -520,32 +563,93 @@ static void php_grpc_channel_plink_dtor(php_grpc_zend_resource *rsrc
return;
}
if (le->channel != NULL) {
- gpr_mu_lock(&le->channel->mu);
- if (le->channel->wrapped != NULL) {
- grpc_channel_destroy(le->channel->wrapped);
- free(le->channel->args_hashstr);
- le->channel->wrapped = NULL;
- le->channel->target = NULL;
- le->channel->args_hashstr = NULL;
- free(le->channel->key);
- le->channel->key = NULL;
- }
- gpr_mu_unlock(&le->channel->mu);
+ php_grpc_channel_unref(le->channel);
+ le->channel = NULL;
+ }
+ free(le);
+ le = NULL;
+}
+
+// A destructor associated with each list entry from the target_bound map
+static void php_grpc_target_bound_dtor(php_grpc_zend_resource *rsrc
+ TSRMLS_DC) {
+ target_bound_le_t *le = (target_bound_le_t *) rsrc->ptr;
+ if (le == NULL) {
+ return;
}
+ free(le);
+ le = NULL;
}
+#ifdef GRPC_PHP_DEBUG
+
/**
- * Clean all channels in the persistent.
- * @return void
- */
+* Clean all channels in the persistent. Test only.
+* @return void
+*/
PHP_METHOD(Channel, cleanPersistentList) {
zend_hash_clean(&grpc_persistent_list);
+ zend_hash_clean(&grpc_target_upper_bound_map);
+}
+
+char *grpc_connectivity_state_name(grpc_connectivity_state state) {
+ switch (state) {
+ case GRPC_CHANNEL_IDLE:
+ return "IDLE";
+ case GRPC_CHANNEL_CONNECTING:
+ return "CONNECTING";
+ case GRPC_CHANNEL_READY:
+ return "READY";
+ case GRPC_CHANNEL_TRANSIENT_FAILURE:
+ return "TRANSIENT_FAILURE";
+ case GRPC_CHANNEL_SHUTDOWN:
+ return "SHUTDOWN";
+ }
+ return "UNKNOWN";
}
/**
- * Return an array of persistent list.
- * @return array
- */
+* Return the info about the current channel. Test only.
+* @return array
+*/
+PHP_METHOD(Channel, getChannelInfo) {
+ wrapped_grpc_channel *channel =
+ PHP_GRPC_GET_WRAPPED_OBJECT(wrapped_grpc_channel, getThis());
+ array_init(return_value);
+ // Info about the target
+ PHP_GRPC_ADD_STRING_TO_ARRAY(return_value, "target",
+ sizeof("target"), channel->wrapper->target, true);
+ // Info about the upper bound for the target
+ target_bound_le_t* target_bound_status =
+ update_and_get_target_upper_bound(channel->wrapper->target, -1);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "target_upper_bound",
+ sizeof("target_upper_bound"), target_bound_status->upper_bound);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "target_current_size",
+ sizeof("target_current_size"), target_bound_status->current_count);
+ // Info about key
+ PHP_GRPC_ADD_STRING_TO_ARRAY(return_value, "key",
+ sizeof("key"), channel->wrapper->key, true);
+ // Info about persistent channel ref_count
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "ref_count",
+ sizeof("ref_count"), channel->wrapper->ref_count);
+ // Info about connectivity status
+ int state =
+ grpc_channel_check_connectivity_state(channel->wrapper->wrapped, (int)0);
+ // It should be set to 'true' in PHP 5.6.33
+ PHP_GRPC_ADD_LONG_TO_ARRAY(return_value, "connectivity_status",
+ sizeof("connectivity_status"), state);
+ PHP_GRPC_ADD_STRING_TO_ARRAY(return_value, "ob",
+ sizeof("ob"),
+ grpc_connectivity_state_name(state), true);
+ // Info about the channel is closed or not
+ PHP_GRPC_ADD_BOOL_TO_ARRAY(return_value, "is_valid",
+ sizeof("is_valid"), (channel->wrapper == NULL));
+}
+
+/**
+* Return an array of all channels in the persistent list. Test only.
+* @return array
+*/
PHP_METHOD(Channel, getPersistentList) {
array_init(return_value);
zval *data;
@@ -562,24 +666,34 @@ PHP_METHOD(Channel, getPersistentList) {
// Info about the target
PHP_GRPC_ADD_STRING_TO_ARRAY(ret_arr, "target",
sizeof("target"), le->channel->target, true);
+ // Info about the upper bound for the target
+ target_bound_le_t* target_bound_status =
+ update_and_get_target_upper_bound(le->channel->target, -1);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "target_upper_bound",
+ sizeof("target_upper_bound"), target_bound_status->upper_bound);
+ PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "target_current_size",
+ sizeof("target_current_size"), target_bound_status->current_count);
// Info about key
PHP_GRPC_ADD_STRING_TO_ARRAY(ret_arr, "key",
sizeof("key"), le->channel->key, true);
// Info about persistent channel ref_count
PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "ref_count",
- sizeof("ref_count"), le->ref_count);
+ sizeof("ref_count"), le->channel->ref_count);
// Info about connectivity status
int state =
grpc_channel_check_connectivity_state(le->channel->wrapped, (int)0);
// It should be set to 'true' in PHP 5.6.33
PHP_GRPC_ADD_LONG_TO_ARRAY(ret_arr, "connectivity_status",
sizeof("connectivity_status"), state);
- // Info about the channel is closed or not
- PHP_GRPC_ADD_BOOL_TO_ARRAY(ret_arr, "is_valid",
- sizeof("is_valid"), le->channel->is_valid);
- add_assoc_zval(return_value, le->channel->target, ret_arr);
+ PHP_GRPC_ADD_STRING_TO_ARRAY(ret_arr, "ob",
+ sizeof("ob"),
+ grpc_connectivity_state_name(state), true);
+ add_assoc_zval(return_value, le->channel->key, ret_arr);
+ PHP_GRPC_FREE_STD_ZVAL(ret_arr);
PHP_GRPC_HASH_FOREACH_END()
}
+#endif
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
ZEND_ARG_INFO(0, target)
@@ -601,11 +715,17 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_close, 0, 0, 0)
ZEND_END_ARG_INFO()
+#ifdef GRPC_PHP_DEBUG
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getChannelInfo, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_cleanPersistentList, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_getPersistentList, 0, 0, 0)
ZEND_END_ARG_INFO()
+#endif
+
static zend_function_entry channel_methods[] = {
PHP_ME(Channel, __construct, arginfo_construct,
@@ -618,10 +738,14 @@ static zend_function_entry channel_methods[] = {
ZEND_ACC_PUBLIC)
PHP_ME(Channel, close, arginfo_close,
ZEND_ACC_PUBLIC)
+ #ifdef GRPC_PHP_DEBUG
+ PHP_ME(Channel, getChannelInfo, arginfo_getChannelInfo,
+ ZEND_ACC_PUBLIC)
PHP_ME(Channel, cleanPersistentList, arginfo_cleanPersistentList,
ZEND_ACC_PUBLIC)
PHP_ME(Channel, getPersistentList, arginfo_getPersistentList,
ZEND_ACC_PUBLIC)
+ #endif
PHP_FE_END
};
@@ -635,6 +759,12 @@ GRPC_STARTUP_FUNCTION(channel) {
NULL, php_grpc_channel_plink_dtor, "Persistent Channel", module_number);
zend_hash_init_ex(&grpc_persistent_list, 20, NULL,
EG(persistent_list).pDestructor, 1, 0);
+ // Register the target->upper_bound map.
+ le_bound = zend_register_list_destructors_ex(
+ NULL, php_grpc_target_bound_dtor, "Target Bound", module_number);
+ zend_hash_init_ex(&grpc_target_upper_bound_map, 20, NULL,
+ EG(persistent_list).pDestructor, 1, 0);
+
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);
return SUCCESS;
}