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

Skip to content

Commit 850027f

Browse files
committed
Different key hashing algorithms from hash extension.
1 parent 71922bf commit 850027f

5 files changed

Lines changed: 53 additions & 9 deletions

File tree

redis.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extern zend_function_entry redis_cluster_functions[];
5555

5656
PHP_INI_BEGIN()
5757
/* redis arrays */
58+
PHP_INI_ENTRY("redis.arrays.algorithm", "", PHP_INI_ALL, NULL)
5859
PHP_INI_ENTRY("redis.arrays.autorehash", "0", PHP_INI_ALL, NULL)
5960
PHP_INI_ENTRY("redis.arrays.connecttimeout", "0", PHP_INI_ALL, NULL)
6061
PHP_INI_ENTRY("redis.arrays.distributor", "", PHP_INI_ALL, NULL)

redis_array.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ redis_array_free(RedisArray *ra)
159159
/* Distributor */
160160
zval_dtor(&ra->z_dist);
161161

162+
/* Hashing algorithm */
163+
zval_dtor(&ra->z_algo);
164+
162165
/* Delete pur commands */
163166
zend_hash_destroy(ra->pure_cmds);
164167
FREE_HASHTABLE(ra->pure_cmds);
@@ -269,7 +272,7 @@ redis_array_get(zval *id TSRMLS_DC)
269272
Public constructor */
270273
PHP_METHOD(RedisArray, __construct)
271274
{
272-
zval *z0, z_fun, z_dist, *zpData, *z_opts = NULL;
275+
zval *z0, z_fun, z_dist, z_algo, *zpData, *z_opts = NULL;
273276
RedisArray *ra = NULL;
274277
zend_bool b_index = 0, b_autorehash = 0, b_pconnect = 0, consistent = 0;
275278
HashTable *hPrev = NULL, *hOpts = NULL;
@@ -284,6 +287,7 @@ PHP_METHOD(RedisArray, __construct)
284287

285288
ZVAL_NULL(&z_fun);
286289
ZVAL_NULL(&z_dist);
290+
ZVAL_NULL(&z_algo);
287291
/* extract options */
288292
if(z_opts) {
289293
hOpts = Z_ARRVAL_P(z_opts);
@@ -306,6 +310,11 @@ PHP_METHOD(RedisArray, __construct)
306310
ZVAL_ZVAL(&z_dist, zpData, 1, 0);
307311
}
308312

313+
/* extract function name. */
314+
if ((zpData = zend_hash_str_find(hOpts, "algorithm", sizeof("algorithm") - 1)) != NULL && Z_TYPE_P(zpData) == IS_STRING) {
315+
ZVAL_ZVAL(&z_algo, zpData, 1, 0);
316+
}
317+
309318
/* extract index option. */
310319
if ((zpData = zend_hash_str_find(hOpts, "index", sizeof("index") - 1)) != NULL) {
311320
b_index = zval_is_true(zpData);
@@ -370,12 +379,13 @@ PHP_METHOD(RedisArray, __construct)
370379
break;
371380

372381
case IS_ARRAY:
373-
ra = ra_make_array(Z_ARRVAL_P(z0), &z_fun, &z_dist, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect, d_connect_timeout, read_timeout, consistent TSRMLS_CC);
382+
ra = ra_make_array(Z_ARRVAL_P(z0), &z_fun, &z_dist, &z_algo, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect, d_connect_timeout, read_timeout, consistent TSRMLS_CC);
374383
break;
375384

376385
default:
377386
WRONG_PARAM_COUNT;
378387
}
388+
zval_dtor(&z_algo);
379389
zval_dtor(&z_dist);
380390
zval_dtor(&z_fun);
381391

redis_array.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef struct RedisArray_ {
5959
zend_bool pconnect; /* should we use pconnect */
6060
zval z_fun; /* key extractor, callable */
6161
zval z_dist; /* key distributor, callable */
62+
zval z_algo; /* key hashing algorithm name */
6263
HashTable *pure_cmds; /* hash table */
6364
double connect_timeout; /* socket connect timeout */
6465
double read_timeout; /* socket read timeout */

redis_array_impl.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "ext/standard/crc32.h"
2727
#include "ext/standard/md5.h"
2828

29+
#include "ext/hash/php_hash.h"
30+
2931
#define PHPREDIS_INDEX_NAME "__phpredis_array_index__"
3032

3133
extern zend_class_entry *redis_ce;
@@ -162,11 +164,12 @@ ra_find_name(const char *name) {
162164
/* laod array from INI settings */
163165
RedisArray *ra_load_array(const char *name TSRMLS_DC) {
164166

165-
zval *z_data, z_fun, z_dist;
167+
zval *z_data, z_fun, z_dist, z_algo;
166168
zval z_params_hosts;
167169
zval z_params_prev;
168170
zval z_params_funs;
169171
zval z_params_dist;
172+
zval z_params_algo;
170173
zval z_params_index;
171174
zval z_params_autorehash;
172175
zval z_params_retry_interval;
@@ -227,6 +230,16 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
227230
ZVAL_ZVAL(&z_dist, z_data, 1, 0);
228231
}
229232

233+
/* find hash algorithm */
234+
array_init(&z_params_algo);
235+
if ((iptr = INI_STR("redis.arrays.algorithm")) != NULL) {
236+
sapi_module.treat_data(PARSE_STRING, estrdup(iptr), &z_params_algo TSRMLS_CC);
237+
}
238+
ZVAL_NULL(&z_algo);
239+
if ((z_data = zend_hash_str_find(Z_ARRVAL(z_params_algo), name, name_len)) != NULL) {
240+
ZVAL_ZVAL(&z_algo, z_data, 1, 0);
241+
}
242+
230243
/* find index option */
231244
array_init(&z_params_index);
232245
if ((iptr = INI_STR("redis.arrays.index")) != NULL) {
@@ -327,7 +340,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
327340

328341

329342
/* create RedisArray object */
330-
ra = ra_make_array(hHosts, &z_fun, &z_dist, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect, d_connect_timeout, read_timeout, consistent TSRMLS_CC);
343+
ra = ra_make_array(hHosts, &z_fun, &z_dist, &z_algo, hPrev, b_index, b_pconnect, l_retry_interval, b_lazy_connect, d_connect_timeout, read_timeout, consistent TSRMLS_CC);
331344
if (ra) {
332345
ra->auto_rehash = b_autorehash;
333346
if(ra->prev) ra->prev->auto_rehash = b_autorehash;
@@ -338,6 +351,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
338351
zval_dtor(&z_params_prev);
339352
zval_dtor(&z_params_funs);
340353
zval_dtor(&z_params_dist);
354+
zval_dtor(&z_params_algo);
341355
zval_dtor(&z_params_index);
342356
zval_dtor(&z_params_autorehash);
343357
zval_dtor(&z_params_retry_interval);
@@ -346,6 +360,7 @@ RedisArray *ra_load_array(const char *name TSRMLS_DC) {
346360
zval_dtor(&z_params_read_timeout);
347361
zval_dtor(&z_params_lazy_connect);
348362
zval_dtor(&z_params_consistent);
363+
zval_dtor(&z_algo);
349364
zval_dtor(&z_dist);
350365
zval_dtor(&z_fun);
351366

@@ -393,7 +408,7 @@ ra_make_continuum(zend_string **hosts, int nb_hosts)
393408
}
394409

395410
RedisArray *
396-
ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect, double connect_timeout, double read_timeout, zend_bool consistent TSRMLS_DC) {
411+
ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, zval *z_algo, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect, double connect_timeout, double read_timeout, zend_bool consistent TSRMLS_DC) {
397412

398413
int i, count;
399414
RedisArray *ra;
@@ -423,14 +438,15 @@ ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev
423438
efree(ra);
424439
return NULL;
425440
}
426-
ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, NULL, b_index, b_pconnect, retry_interval, b_lazy_connect, connect_timeout, read_timeout, consistent TSRMLS_CC) : NULL;
441+
ra->prev = hosts_prev ? ra_make_array(hosts_prev, z_fun, z_dist, z_algo, NULL, b_index, b_pconnect, retry_interval, b_lazy_connect, connect_timeout, read_timeout, consistent TSRMLS_CC) : NULL;
427442

428443
/* init array data structures */
429444
ra_init_function_table(ra);
430445

431446
/* Set hash function and distribtor if provided */
432447
ZVAL_ZVAL(&ra->z_fun, z_fun, 1, 0);
433448
ZVAL_ZVAL(&ra->z_dist, z_dist, 1, 0);
449+
ZVAL_ZVAL(&ra->z_algo, z_algo, 1, 0);
434450

435451
/* init continuum */
436452
if (consistent) {
@@ -533,10 +549,26 @@ ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_D
533549
if (Z_TYPE(ra->z_dist) == IS_NULL) {
534550
int i;
535551
unsigned long ret = 0xffffffff;
552+
const php_hash_ops *ops;
536553

537554
/* hash */
538-
for (i = 0; i < ZSTR_LEN(out); ++i) {
539-
CRC32(ret, ZSTR_VAL(out)[i]);
555+
if (Z_TYPE(ra->z_algo) == IS_STRING && (ops = php_hash_fetch_ops(Z_STRVAL(ra->z_algo), Z_STRLEN(ra->z_algo))) != NULL) {
556+
void *ctx = emalloc(ops->context_size);
557+
unsigned char *digest = emalloc(ops->digest_size);
558+
559+
ops->hash_init(ctx);
560+
ops->hash_update(ctx, ZSTR_VAL(out), ZSTR_LEN(out));
561+
ops->hash_final(digest, ctx);
562+
563+
memcpy(&ret, digest, MIN(sizeof(ret), ops->digest_size));
564+
ret %= 0xffffffff;
565+
566+
efree(digest);
567+
efree(ctx);
568+
} else {
569+
for (i = 0; i < ZSTR_LEN(out); ++i) {
570+
CRC32(ret, ZSTR_VAL(out)[i]);
571+
}
540572
}
541573

542574
/* get position on ring */

redis_array_impl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
RedisArray *ra_load_hosts(RedisArray *ra, HashTable *hosts, long retry_interval, zend_bool b_lazy_connect TSRMLS_DC);
1313
RedisArray *ra_load_array(const char *name TSRMLS_DC);
14-
RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect, double connect_timeout, double read_timeout, zend_bool consistent TSRMLS_DC);
14+
RedisArray *ra_make_array(HashTable *hosts, zval *z_fun, zval *z_dist, zval *z_algo, HashTable *hosts_prev, zend_bool b_index, zend_bool b_pconnect, long retry_interval, zend_bool b_lazy_connect, double connect_timeout, double read_timeout, zend_bool consistent TSRMLS_DC);
1515
zval *ra_find_node_by_name(RedisArray *ra, const char *host, int host_len TSRMLS_DC);
1616
zval *ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos TSRMLS_DC);
1717
void ra_init_function_table(RedisArray *ra);

0 commit comments

Comments
 (0)