Remove the specified client from global lists where the client could * be referenced, not including the Pub/Sub channels. * This is used by freeClient() and replicationCacheMaster(). */
| 1516 | * be referenced, not including the Pub/Sub channels. |
| 1517 | * This is used by freeClient() and replicationCacheMaster(). */ |
| 1518 | void unlinkClient(client *c) { |
| 1519 | listNode *ln; |
| 1520 | AssertCorrectThread(c); |
| 1521 | serverAssert(c->conn == nullptr || GlobalLocksAcquired()); |
| 1522 | serverAssert(c->conn == nullptr || c->lock.fOwnLock()); |
| 1523 | |
| 1524 | /* If this is marked as current client unset it. */ |
| 1525 | if (serverTL && serverTL->current_client == c) serverTL->current_client = NULL; |
| 1526 | |
| 1527 | /* Certain operations must be done only if the client has an active connection. |
| 1528 | * If the client was already unlinked or if it's a "fake client" the |
| 1529 | * conn is already set to NULL. */ |
| 1530 | if (c->conn) { |
| 1531 | /* Remove from the list of active clients. */ |
| 1532 | if (c->client_list_node) { |
| 1533 | uint64_t id = htonu64(c->id); |
| 1534 | raxRemove(g_pserver->clients_index,(unsigned char*)&id,sizeof(id),NULL); |
| 1535 | listDelNode(g_pserver->clients,c->client_list_node); |
| 1536 | c->client_list_node = NULL; |
| 1537 | } |
| 1538 | |
| 1539 | /* Check if this is a replica waiting for diskless replication (rdb pipe), |
| 1540 | * in which case it needs to be cleaned from that list */ |
| 1541 | if (c->flags & CLIENT_SLAVE && |
| 1542 | c->replstate == SLAVE_STATE_WAIT_BGSAVE_END && |
| 1543 | g_pserver->rdb_pipe_conns) |
| 1544 | { |
| 1545 | int i; |
| 1546 | for (i=0; i < g_pserver->rdb_pipe_numconns; i++) { |
| 1547 | if (g_pserver->rdb_pipe_conns[i] == c->conn) { |
| 1548 | rdbPipeWriteHandlerConnRemoved(c->conn); |
| 1549 | g_pserver->rdb_pipe_conns[i] = NULL; |
| 1550 | break; |
| 1551 | } |
| 1552 | } |
| 1553 | } |
| 1554 | connClose(c->conn); |
| 1555 | c->conn = NULL; |
| 1556 | atomicDecr(g_pserver->rgthreadvar[c->iel].cclients, 1); |
| 1557 | } |
| 1558 | |
| 1559 | /* Remove from the list of pending writes if needed. */ |
| 1560 | if (c->flags & CLIENT_PENDING_WRITE) { |
| 1561 | std::unique_lock<fastlock> lockf(g_pserver->rgthreadvar[c->iel].lockPendingWrite); |
| 1562 | auto itr = std::find(g_pserver->rgthreadvar[c->iel].clients_pending_write.begin(), |
| 1563 | g_pserver->rgthreadvar[c->iel].clients_pending_write.end(), c); |
| 1564 | serverAssert(itr != g_pserver->rgthreadvar[c->iel].clients_pending_write.end()); |
| 1565 | g_pserver->rgthreadvar[c->iel].clients_pending_write.erase(itr); |
| 1566 | c->flags &= ~CLIENT_PENDING_WRITE; |
| 1567 | } |
| 1568 | |
| 1569 | /* When client was just unblocked because of a blocking operation, |
| 1570 | * remove it from the list of unblocked clients. */ |
| 1571 | if (c->flags & CLIENT_UNBLOCKED) { |
| 1572 | ln = listSearchKey(g_pserver->rgthreadvar[c->iel].unblocked_clients,c); |
| 1573 | serverAssert(ln != NULL); |
| 1574 | listDelNode(g_pserver->rgthreadvar[c->iel].unblocked_clients,ln); |
| 1575 | c->flags &= ~CLIENT_UNBLOCKED; |
no test coverage detected