| 500 | } |
| 501 | |
| 502 | static void readHandler(aeEventLoop *el, int fd, void *privdata, int mask) { |
| 503 | client c = (client)privdata; |
| 504 | void *reply = NULL; |
| 505 | UNUSED(el); |
| 506 | UNUSED(fd); |
| 507 | UNUSED(mask); |
| 508 | |
| 509 | /* Calculate latency only for the first read event. This means that the |
| 510 | * server already sent the reply and we need to parse it. Parsing overhead |
| 511 | * is not part of the latency, so calculate it only once, here. */ |
| 512 | if (c->latency < 0) c->latency = ustime()-(c->start); |
| 513 | |
| 514 | if (redisBufferRead(c->context) != REDIS_OK) { |
| 515 | fprintf(stderr,"Error: %s\n",c->context->errstr); |
| 516 | exit(1); |
| 517 | } else { |
| 518 | while(c->pending) { |
| 519 | if (redisGetReply(c->context,&reply) != REDIS_OK) { |
| 520 | fprintf(stderr,"Error: %s\n",c->context->errstr); |
| 521 | exit(1); |
| 522 | } |
| 523 | if (reply != NULL) { |
| 524 | if (reply == (void*)REDIS_REPLY_ERROR) { |
| 525 | fprintf(stderr,"Unexpected error reply, exiting...\n"); |
| 526 | exit(1); |
| 527 | } |
| 528 | redisReply *r = (redisReply*)reply; |
| 529 | if (r->type == REDIS_REPLY_ERROR) { |
| 530 | /* Try to update slots configuration if reply error is |
| 531 | * MOVED/ASK/CLUSTERDOWN and the key(s) used by the command |
| 532 | * contain(s) the slot hash tag. |
| 533 | * If the error is not topology-update related then we |
| 534 | * immediately exit to avoid false results. */ |
| 535 | if (c->cluster_node && c->staglen) { |
| 536 | int fetch_slots = 0, do_wait = 0; |
| 537 | if (!strncmp(r->str,"MOVED",5) || !strncmp(r->str,"ASK",3)) |
| 538 | fetch_slots = 1; |
| 539 | else if (!strncmp(r->str,"CLUSTERDOWN",11)) { |
| 540 | /* Usually the cluster is able to recover itself after |
| 541 | * a CLUSTERDOWN error, so try to sleep one second |
| 542 | * before requesting the new configuration. */ |
| 543 | fetch_slots = 1; |
| 544 | do_wait = 1; |
| 545 | printf("Error from server %s:%d: %s.\n", |
| 546 | c->cluster_node->ip, |
| 547 | c->cluster_node->port, |
| 548 | r->str); |
| 549 | } |
| 550 | if (do_wait) sleep(1); |
| 551 | if (fetch_slots && !fetchClusterSlotsConfiguration(c)) |
| 552 | exit(1); |
| 553 | } else { |
| 554 | if (c->cluster_node) { |
| 555 | printf("Error from server %s:%d: %s\n", |
| 556 | c->cluster_node->ip, |
| 557 | c->cluster_node->port, |
| 558 | r->str); |
| 559 | } else printf("Error from server: %s\n", r->str); |
nothing calls this directly
no test coverage detected