MCPcopy Create free account
hub / github.com/ceph/ceph / handle_existing_connection

Method handle_existing_connection

src/msg/async/ProtocolV2.cc:2659–2791  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2657}
2658
2659CtPtr ProtocolV2::handle_existing_connection(const AsyncConnectionRef& existing) {
2660 ldout(cct, 20) << __func__ << " existing=" << existing << dendl;
2661
2662 std::unique_lock<std::mutex> l(existing->lock);
2663
2664 ProtocolV2 *exproto = dynamic_cast<ProtocolV2 *>(existing->protocol.get());
2665 if (!exproto) {
2666 ldout(cct, 1) << __func__ << " existing=" << existing << dendl;
2667 ceph_assert(false);
2668 }
2669
2670 if (exproto->state == CLOSED) {
2671 ldout(cct, 1) << __func__ << " existing " << existing << " already closed."
2672 << dendl;
2673 l.unlock();
2674 return send_server_ident();
2675 }
2676
2677 if (exproto->replacing) {
2678 ldout(cct, 1) << __func__
2679 << " existing racing replace happened while replacing."
2680 << " existing=" << existing << dendl;
2681 auto wait = WaitFrame::Encode();
2682 return WRITE(wait, "wait", read_frame);
2683 }
2684 // Detect a peer (client) restart and prefer the new connection.
2685 // Rationale:
2686 // - The client cookie is regenerated in send_client_ident() on client startup.
2687 // - If the existing connection (exproto) has a strictly higher peer_global_seq
2688 // than the incoming one, the peer’s sequence appears to have reset on the new
2689 // connection (exproto->peer_global_seq > peer_global_seq).
2690 // - Both sides present non-zero cookies and they differ, which strongly indicates
2691 // a new client instance (exproto->client_cookie != client_cookie).
2692 // - We only do this when the existing connection is not in a benign terminal/idle
2693 // state (READY or STANDBY); otherwise we might drop a healthy/idle connection.
2694 // Action:
2695 // Drop the existing connection in favor of the incoming one, then continue the
2696 // handshake on the new connection.
2697 if (exproto->peer_global_seq > peer_global_seq &&
2698 exproto->client_cookie && client_cookie &&
2699 exproto->client_cookie != client_cookie &&
2700 exproto->state != READY && exproto->state != STANDBY) {
2701 ldout(cct, 1) << __func__ << " client has clearly restarted (ex_peer_global_seq="
2702 << exproto->peer_global_seq << " > peer_global_seq=" << peer_global_seq
2703 << " && cookie changed: client_cookie=" << client_cookie << " != ex_client_cookie="
2704 << exproto->client_cookie << "), "
2705 << "existing connection state is " << get_state_name(exproto->state)
2706 << " (not READY or STANDBY), dropping existing_connection=" << existing
2707 << " in favor of new_connection=" << connection << dendl;
2708 existing->protocol->stop();
2709 existing->dispatch_queue->queue_reset(existing.get());
2710 l.unlock();
2711 return send_server_ident();
2712 }
2713
2714 if (exproto->peer_global_seq > peer_global_seq) {
2715 ldout(cct, 1) << __func__ << " this is a stale connection, ex_peer_global_seq="
2716 << exproto->peer_global_seq

Callers

nothing calls this directly

Calls 9

queue_resetMethod · 0.80
msgr2_addrMethod · 0.80
stopFunction · 0.50
getMethod · 0.45
unlockMethod · 0.45
stopMethod · 0.45
reset_sessionMethod · 0.45
get_myaddrsMethod · 0.45
send_keepaliveMethod · 0.45

Tested by

no test coverage detected