Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a802461

Browse files
Merge branch 'feature/ra_mset_intkeys' into develop
2 parents ee571ea + 98bc9ec commit a802461

File tree

1 file changed

+60
-26
lines changed

1 file changed

+60
-26
lines changed

redis_array.c

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -831,18 +831,34 @@ PHP_METHOD(RedisArray, mget)
831831
for (i = 0, zend_hash_internal_pointer_reset_ex(h_keys, &pointer);
832832
zend_hash_get_current_data_ex(h_keys, (void**) &data,
833833
&pointer) == SUCCESS;
834-
zend_hash_move_forward_ex(h_keys, &pointer), ++i) {
835-
836-
if (Z_TYPE_PP(data) != IS_STRING) {
837-
php_error_docref(NULL TSRMLS_CC, E_ERROR, "MGET: all keys must be string.");
838-
efree(argv);
839-
efree(pos);
840-
efree(redis_instances);
841-
efree(argc_each);
842-
RETURN_FALSE;
843-
}
834+
zend_hash_move_forward_ex(h_keys, &pointer), ++i)
835+
{
836+
/* If we need to represent a long key as a string */
837+
unsigned int key_len;
838+
char kbuf[40], *key_lookup;
839+
840+
/* phpredis proper can only use string or long keys, so restrict to that here */
841+
if(Z_TYPE_PP(data) != IS_STRING && Z_TYPE_PP(data) != IS_LONG) {
842+
php_error_docref(NULL TSRMLS_CC, E_ERROR, "MGET: all keys must be strings or longs");
843+
efree(argv);
844+
efree(pos);
845+
efree(redis_instances);
846+
efree(argc_each);
847+
RETURN_FALSE;
848+
}
849+
850+
/* Convert to a string for hash lookup if it isn't one */
851+
if(Z_TYPE_PP(data) == IS_STRING) {
852+
key_len = Z_STRLEN_PP(data);
853+
key_lookup = Z_STRVAL_PP(data);
854+
} else {
855+
key_len = snprintf(kbuf, sizeof(kbuf), "%ld", Z_LVAL_PP(data));
856+
key_lookup = (char*)kbuf;
857+
}
858+
859+
/* Find our node */
860+
redis_instances[i] = ra_find_node(ra, key_lookup, key_len, &pos[i] TSRMLS_CC);
844861

845-
redis_instances[i] = ra_find_node(ra, Z_STRVAL_PP(data), Z_STRLEN_PP(data), &pos[i] TSRMLS_CC);
846862
argc_each[pos[i]]++; /* count number of keys per node */
847863
argv[i] = *data;
848864
}
@@ -935,8 +951,8 @@ PHP_METHOD(RedisArray, mset)
935951
int *pos, argc, *argc_each;
936952
HashTable *h_keys;
937953
zval **redis_instances, *redis_inst, **argv;
938-
char *key, **keys;
939-
unsigned int key_len;
954+
char *key, **keys, **key_free, kbuf[40];
955+
unsigned int key_len, free_idx = 0;
940956
int type, *key_lens;
941957
unsigned long idx;
942958

@@ -958,31 +974,43 @@ PHP_METHOD(RedisArray, mset)
958974
argv = emalloc(argc * sizeof(zval*));
959975
pos = emalloc(argc * sizeof(int));
960976
keys = emalloc(argc * sizeof(char*));
961-
key_lens = emalloc(argc * sizeof(int));
977+
key_lens = emalloc(argc * sizeof(int));
962978
redis_instances = emalloc(argc * sizeof(zval*));
963979
memset(redis_instances, 0, argc * sizeof(zval*));
964980

981+
/* Allocate an array holding the indexes of any keys that need freeing */
982+
key_free = emalloc(argc * sizeof(char*));
983+
965984
argc_each = emalloc(ra->count * sizeof(int));
966985
memset(argc_each, 0, ra->count * sizeof(int));
967986

968987
/* associate each key to a redis node */
969988
for(i = 0, zend_hash_internal_pointer_reset(h_keys);
970989
zend_hash_has_more_elements(h_keys) == SUCCESS;
971-
zend_hash_move_forward(h_keys), i++) {
972-
973-
type = zend_hash_get_current_key_ex(h_keys, &key, &key_len, &idx, 0, NULL);
974-
if(type != HASH_KEY_IS_STRING) { /* ignore non-string keys */
975-
continue;
976-
}
977-
if(zend_hash_get_current_data(h_keys, (void**)&data) == FAILURE) {
978-
continue;
979-
}
980-
981-
redis_instances[i] = ra_find_node(ra, key, (int)key_len - 1, &pos[i] TSRMLS_CC); /* -1 because of PHP assoc keys which count \0... */
990+
zend_hash_move_forward(h_keys), i++)
991+
{
992+
/* We have to skip the element if we can't get the array value */
993+
if(zend_hash_get_current_data(h_keys, (void**)&data) == FAILURE) {
994+
continue;
995+
}
996+
997+
/* Grab our key */
998+
type = zend_hash_get_current_key_ex(h_keys, &key, &key_len, &idx, 0, NULL);
999+
1000+
/* If the key isn't a string, make a string representation of it */
1001+
if(type != HASH_KEY_IS_STRING) {
1002+
key_len = snprintf(kbuf, sizeof(kbuf), "%ld", (long)idx);
1003+
key = estrndup(kbuf, key_len);
1004+
key_free[free_idx++]=key;
1005+
} else {
1006+
key_len--; /* We don't want the null terminator */
1007+
}
1008+
1009+
redis_instances[i] = ra_find_node(ra, key, (int)key_len, &pos[i] TSRMLS_CC);
9821010
argc_each[pos[i]]++; /* count number of keys per node */
9831011
argv[i] = *data;
9841012
keys[i] = key;
985-
key_lens[i] = (int)key_len - 1;
1013+
key_lens[i] = (int)key_len;
9861014
}
9871015

9881016

@@ -1035,8 +1063,14 @@ PHP_METHOD(RedisArray, mset)
10351063
zval_ptr_dtor(&z_argarray);
10361064
}
10371065

1066+
/* Free any keys that we needed to allocate memory for, because they weren't strings */
1067+
for(i=0; i<free_idx; i++) {
1068+
efree(key_free[i]);
1069+
}
1070+
10381071
/* cleanup */
10391072
efree(keys);
1073+
efree(key_free);
10401074
efree(key_lens);
10411075
efree(argv);
10421076
efree(pos);

0 commit comments

Comments
 (0)