diff --git a/src/modules/ndb_redis/redis_client.c b/src/modules/ndb_redis/redis_client.c index 44460aa2fd3..5ad063f89af 100644 --- a/src/modules/ndb_redis/redis_client.c +++ b/src/modules/ndb_redis/redis_client.c @@ -408,8 +408,11 @@ redisc_server_t *redisc_get_server(str *name) */ int redisc_reconnect_server(redisc_server_t *rsrv) { - char addr[256], pass[256], unix_sock_path[256]; - unsigned int port, db, sock = 0, haspass = 0; + char addr[256], pass[256], unix_sock_path[256], sentinel_group[256]; + unsigned int port, db, sock = 0, haspass = 0, sentinel_master = 1; + char sentinels[MAXIMUM_SENTINELS][256]; + uint8_t sentinels_count = 0; + int i, row; param_t *pit = NULL; struct timeval tv_conn; struct timeval tv_cmd; @@ -442,6 +445,84 @@ int redisc_reconnect_server(redisc_server_t *rsrv) } else if(pit->name.len==4 && strncmp(pit->name.s, "pass", 4)==0) { snprintf(pass, sizeof(pass)-1, "%.*s", pit->body.len, pit->body.s); haspass = 1; + } else if(pit->name.len==14 && strncmp(pit->name.s, + "sentinel_group", 14)==0) { + snprintf(sentinel_group, sizeof(sentinel_group)-1, "%.*s", + pit->body.len, pit->body.s); + } else if(pit->name.len==15 && strncmp(pit->name.s, + "sentinel_master", 15)==0) { + if(str2int(&pit->body, &sentinel_master) < 0) + sentinel_master = 1; + } else if(pit->name.len==8 && strncmp(pit->name.s, + "sentinel", 8)==0) { + if( sentinels_count < MAXIMUM_SENTINELS ){ + snprintf(sentinels[sentinels_count], + sizeof(sentinels[sentinels_count])-1, "%.*s", + pit->body.len, pit->body.s); + sentinels_count++; + } + else { + LM_ERR("too many sentinels, maximum %d supported.\n", + MAXIMUM_SENTINELS); + return -1; + } + } + } + + // if sentinels are provided, we need to connect to them and retrieve the redis server + // address / port + if(sentinels_count > 0) { + for(i= 0; i< sentinels_count; i++) { + char *sentinelAddr = sentinels[i]; + char *pos; + redisContext *redis; + redisReply *res, *res2; + + port = 6379; + if( (pos = strchr(sentinelAddr, ':')) != NULL ) { + port = atoi(pos+1); + pos[i] = '\0'; + } + + redis = redisConnectWithTimeout(sentinelAddr, port, tv_conn); + if( redis ) { + if(sentinel_master != 0) { + res = redisCommand(redis, + "SENTINEL get-master-addr-by-name %s", + sentinel_group); + if( res && (res->type == REDIS_REPLY_ARRAY) + && (res->elements == 2) ) { + strncpy(addr, res->element[0]->str, + res->element[0]->len + 1); + port = atoi(res->element[1]->str); + LM_DBG("sentinel replied: %s:%d\n", addr, port); + } + } + else { + res = redisCommand(redis, "SENTINEL slaves %s", + sentinel_group); + if( res && (res->type == REDIS_REPLY_ARRAY) ) { + for(row = 0; row< res->elements; row++){ + res2 = res->element[row]; + for(i= 0; i< res2->elements; i+= 2) { + if( strncmp(res2->element[i]->str, + "ip", 2) == 0 ) { + strncpy(addr, res2->element[i+1]->str, + res2->element[i+1]->len); + addr[res2->element[i+1]->len] = '\0'; + } + else if( strncmp(res2->element[i]->str, + "port", 4) == 0) { + port = atoi(res2->element[i+1]->str); + break; + } + } + } + LM_DBG("slave for %s: %s:%d\n", sentinel_group, + addr, port); + } + } + } } }