Do some actions after an error reply was sent (Log if needed, updates stats, etc.) */
| 417 | |
| 418 | /* Do some actions after an error reply was sent (Log if needed, updates stats, etc.) */ |
| 419 | void afterErrorReply(client *c, const char *s, size_t len) { |
| 420 | /* Increment the global error counter */ |
| 421 | server.stat_total_error_replies++; |
| 422 | /* Increment the error stats |
| 423 | * If the string already starts with "-..." then the error prefix |
| 424 | * is provided by the caller ( we limit the search to 32 chars). Otherwise we use "-ERR". */ |
| 425 | if (s[0] != '-') { |
| 426 | incrementErrorCount("ERR", 3); |
| 427 | } else { |
| 428 | char *spaceloc = memchr(s, ' ', len < 32 ? len : 32); |
| 429 | if (spaceloc) { |
| 430 | const size_t errEndPos = (size_t)(spaceloc - s); |
| 431 | incrementErrorCount(s+1, errEndPos-1); |
| 432 | } else { |
| 433 | /* Fallback to ERR if we can't retrieve the error prefix */ |
| 434 | incrementErrorCount("ERR", 3); |
| 435 | } |
| 436 | } |
| 437 | |
| 438 | /* Sometimes it could be normal that a slave replies to a master with |
| 439 | * an error and this function gets called. Actually the error will never |
| 440 | * be sent because addReply*() against master clients has no effect... |
| 441 | * A notable example is: |
| 442 | * |
| 443 | * EVAL 'redis.call("incr",KEYS[1]); redis.call("nonexisting")' 1 x |
| 444 | * |
| 445 | * Where the master must propagate the first change even if the second |
| 446 | * will produce an error. However it is useful to log such events since |
| 447 | * they are rare and may hint at errors in a script or a bug in Redis. */ |
| 448 | int ctype = getClientType(c); |
| 449 | if (ctype == CLIENT_TYPE_MASTER || ctype == CLIENT_TYPE_SLAVE || c->id == CLIENT_ID_AOF) { |
| 450 | char *to, *from; |
| 451 | |
| 452 | if (c->id == CLIENT_ID_AOF) { |
| 453 | to = "AOF-loading-client"; |
| 454 | from = "server"; |
| 455 | } else if (ctype == CLIENT_TYPE_MASTER) { |
| 456 | to = "master"; |
| 457 | from = "replica"; |
| 458 | } else { |
| 459 | to = "replica"; |
| 460 | from = "master"; |
| 461 | } |
| 462 | |
| 463 | if (len > 4096) len = 4096; |
| 464 | char *cmdname = c->lastcmd ? c->lastcmd->name : "<unknown>"; |
| 465 | serverLog(LL_WARNING,"== CRITICAL == This %s is sending an error " |
| 466 | "to its %s: '%.*s' after processing the command " |
| 467 | "'%s'", from, to, (int)len, s, cmdname); |
| 468 | if (ctype == CLIENT_TYPE_MASTER && server.repl_backlog && |
| 469 | server.repl_backlog_histlen > 0) |
| 470 | { |
| 471 | showLatestBacklog(); |
| 472 | } |
| 473 | server.stat_unexpected_error_replies++; |
| 474 | } |
| 475 | } |
| 476 |
no test coverage detected