Skip to content

Instantly share code, notes, and snippets.

@michael-grunder
Created September 9, 2012 20:38
Show Gist options
  • Save michael-grunder/3687125 to your computer and use it in GitHub Desktop.
Save michael-grunder/3687125 to your computer and use it in GitHub Desktop.
Different way of detecting callback
PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd)
zval *object, *array, **data;
HashTable *arr_hash;
HashPosition pointer;
RedisSock *redis_sock;
char *cmd = "", *old_cmd = NULL;
int cmd_len, array_count;
zval *z_tab, **tmp;
char *type_response;
// Function call information
zend_fcall_info z_callback;
zend_fcall_info_cache z_callback_cache;
zval *z_ret, **z_args[4];
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oaf",
&object, redis_ce, &array, &z_callback, &z_callback_cache) == FAILURE) {
RETURN_FALSE;
}
if (redis_sock_get(object, &redis_sock TSRMLS_CC, 0) < 0) {
RETURN_FALSE;
}
arr_hash = Z_ARRVAL_P(array);
array_count = zend_hash_num_elements(arr_hash);
if (array_count == 0) {
RETURN_FALSE;
}
for (zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
zend_hash_get_current_data_ex(arr_hash, (void**) &data,
&pointer) == SUCCESS;
zend_hash_move_forward_ex(arr_hash, &pointer)) {
if (Z_TYPE_PP(data) == IS_STRING) {
char *old_cmd = NULL;
if(*cmd) {
old_cmd = cmd;
}
cmd_len = spprintf(&cmd, 0, "%s %s", cmd, Z_STRVAL_PP(data));
if(old_cmd) {
efree(old_cmd);
}
}
}
old_cmd = cmd;
cmd_len = spprintf(&cmd, 0, "%s %s\r\n", sub_cmd, cmd);
efree(old_cmd);
if (redis_sock_write(redis_sock, cmd, cmd_len TSRMLS_CC) < 0) {
efree(cmd);
RETURN_FALSE;
}
efree(cmd);
/* read the status of the execution of the command `subscribe` */
z_tab = redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
if(z_tab == NULL) {
RETURN_FALSE;
}
if (zend_hash_index_find(Z_ARRVAL_P(z_tab), 0, (void**)&tmp) == SUCCESS) {
type_response = Z_STRVAL_PP(tmp);
if(strcmp(type_response, sub_cmd) != 0) {
efree(tmp);
efree(z_tab);
RETURN_FALSE;
}
} else {
efree(z_tab);
RETURN_FALSE;
}
efree(z_tab);
// Set a pointer to our return value and to our arguments.
z_callback.retval_ptr_ptr = &z_ret;
z_callback.params = z_args;
z_callback.no_separation = 0;
/* Multibulk Response, format : {message type, originating channel, message payload} */
while(1) {
/* call the callback with this z_tab in argument */
zval **type, **channel, **pattern, **data;
z_tab = redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock);
int is_pmsg, tab_idx = 1;
if(z_tab == NULL || Z_TYPE_P(z_tab) != IS_ARRAY) {
//ERROR
break;
}
if (zend_hash_index_find(Z_ARRVAL_P(z_tab), 0, (void**)&type) == FAILURE || Z_TYPE_PP(type) != IS_STRING) {
break;
}
// Make sure we have a message or pmessage
if(!strncmp(Z_STRVAL_PP(type), "message", 7) || !strncmp(Z_STRVAL_PP(type), "pmessage", 8)) {
// Is this a pmessage
is_pmsg = *Z_STRVAL_PP(type) == 'p';
} else {
continue; // It's not a message or pmessage
}
// If this is a pmessage, we'll want to extract the pattern first
if(is_pmsg) {
// Extract pattern
if(zend_hash_index_find(Z_ARRVAL_P(z_tab), tab_idx++, (void**)&pattern) == FAILURE) {
break;
}
}
// Extract channel and data
if (zend_hash_index_find(Z_ARRVAL_P(z_tab), tab_idx++, (void**)&channel) == FAILURE) {
break;
}
if (zend_hash_index_find(Z_ARRVAL_P(z_tab), tab_idx++, (void**)&data) == FAILURE) {
break;
}
// Always pass the Redis object through
z_args[0] = &getThis();
// Set up our callback args depending on the message type
if(is_pmsg) {
z_args[1] = pattern;
z_args[2] = channel;
z_args[3] = data;
} else {
z_args[1] = channel;
z_args[2] = data;
}
// Set our argument information
z_callback.param_count = tab_idx;
// Break if we can't call the function
if(zend_call_function(&z_callback, &z_callback_cache TSRMLS_CC) != SUCCESS) {
break;
}
// If we have a return value, free it. Note, we could use the return value to break the subscribe loop
if(z_ret) zval_ptr_dtor(&z_ret);
/* TODO: provide a way to break out of the loop. */
zval_dtor(z_tab);
efree(z_tab);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment