Browse code

ndb_redis: add sentinel support to reconnection logic

- cc8e621 added sentinel support in initial redis connection.

- this commit replicates the logic into reconnection function.

Carlos Cruz authored on 08/05/2020 15:37:30
Showing 1 changed files
... ...
@@ -408,8 +408,11 @@ redisc_server_t *redisc_get_server(str *name)
408 408
  */
409 409
 int redisc_reconnect_server(redisc_server_t *rsrv)
410 410
 {
411
-	char addr[256], pass[256], unix_sock_path[256];
412
-	unsigned int port, db, sock = 0, haspass = 0;
411
+	char addr[256], pass[256], unix_sock_path[256], sentinel_group[256];
412
+	unsigned int port, db, sock = 0, haspass = 0, sentinel_master = 1;
413
+	char sentinels[MAXIMUM_SENTINELS][256];
414
+	uint8_t sentinels_count = 0;
415
+	int i, row;
413 416
 	param_t *pit = NULL;
414 417
 	struct timeval tv_conn;
415 418
 	struct timeval tv_cmd;
... ...
@@ -442,6 +445,84 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
442 445
 		} else if(pit->name.len==4 && strncmp(pit->name.s, "pass", 4)==0) {
443 446
 			snprintf(pass, sizeof(pass)-1, "%.*s", pit->body.len, pit->body.s);
444 447
 			haspass = 1;
448
+		} else if(pit->name.len==14 && strncmp(pit->name.s,
449
+					"sentinel_group", 14)==0) {
450
+			snprintf(sentinel_group, sizeof(sentinel_group)-1, "%.*s",
451
+					pit->body.len, pit->body.s);
452
+		} else if(pit->name.len==15 && strncmp(pit->name.s,
453
+					"sentinel_master", 15)==0) {
454
+			if(str2int(&pit->body, &sentinel_master) < 0)
455
+				sentinel_master = 1;
456
+		} else if(pit->name.len==8 && strncmp(pit->name.s,
457
+					"sentinel", 8)==0) {
458
+			if( sentinels_count < MAXIMUM_SENTINELS ){
459
+				snprintf(sentinels[sentinels_count],
460
+						sizeof(sentinels[sentinels_count])-1, "%.*s",
461
+						pit->body.len, pit->body.s);
462
+				sentinels_count++;
463
+			}
464
+			else {
465
+				LM_ERR("too many sentinels, maximum %d supported.\n",
466
+						MAXIMUM_SENTINELS);
467
+				return -1;
468
+			}
469
+		}
470
+	}
471
+
472
+	// if sentinels are provided, we need to connect to them and retrieve the redis server
473
+	// address / port
474
+	if(sentinels_count > 0) {
475
+		for(i= 0; i< sentinels_count; i++) {
476
+			char *sentinelAddr = sentinels[i];
477
+			char *pos;
478
+			redisContext *redis;
479
+			redisReply *res, *res2;
480
+
481
+			port = 6379;
482
+			if( (pos = strchr(sentinelAddr, ':')) != NULL ) {
483
+				port = atoi(pos+1);
484
+				pos[i] = '\0';
485
+			}
486
+
487
+			redis = redisConnectWithTimeout(sentinelAddr, port, tv_conn);
488
+			if( redis ) {
489
+				if(sentinel_master != 0) {
490
+					res = redisCommand(redis,
491
+							"SENTINEL get-master-addr-by-name %s",
492
+							sentinel_group);
493
+					if( res && (res->type == REDIS_REPLY_ARRAY)
494
+							&& (res->elements == 2) ) {
495
+						strncpy(addr, res->element[0]->str,
496
+								res->element[0]->len + 1);
497
+						port = atoi(res->element[1]->str);
498
+						LM_DBG("sentinel replied: %s:%d\n", addr, port);
499
+					}
500
+				}
501
+				else {
502
+					res = redisCommand(redis, "SENTINEL slaves %s",
503
+							sentinel_group);
504
+					if( res && (res->type == REDIS_REPLY_ARRAY) ) {
505
+						for(row = 0; row< res->elements; row++){
506
+							res2 = res->element[row];
507
+							for(i= 0; i< res2->elements; i+= 2) {
508
+								if( strncmp(res2->element[i]->str,
509
+											"ip", 2) == 0 ) {
510
+									strncpy(addr, res2->element[i+1]->str,
511
+											res2->element[i+1]->len);
512
+									addr[res2->element[i+1]->len] = '\0';
513
+								}
514
+								else if( strncmp(res2->element[i]->str,
515
+											"port", 4) == 0) {
516
+									port = atoi(res2->element[i+1]->str);
517
+									break;
518
+								}
519
+							}
520
+						}
521
+						LM_DBG("slave for %s: %s:%d\n", sentinel_group,
522
+								addr, port);
523
+					}
524
+				}
525
+			}
445 526
 		}
446 527
 	}
447 528