Skip to content

Commit afbd8cf

Browse files
authored
FIX[BMQ]: send nego message before creating session (#886)
Signed-off-by: Emelia Lei <wlei29@bloomberg.net>
1 parent 4c40c5d commit afbd8cf

2 files changed

Lines changed: 117 additions & 66 deletions

File tree

src/groups/mqb/mqba/mqba_sessionnegotiator.cpp

Lines changed: 109 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -458,32 +458,36 @@ SessionNegotiator::onClientIdentityMessage(bsl::ostream& errorDescription,
458458
shouldExtendMessageProperties);
459459
}
460460

461-
// Create the session. That also calculates 'maxMissedHeartbeats'
462-
bsl::string description;
463-
loadSessionDescription(
464-
&description,
465-
clientIdentity,
466-
*(context->d_initialConnectionContext_p->channel().get()));
467-
468-
createSession(errorDescription, &session, context, description);
461+
// Populate the negotiation context based on the received client identity.
462+
int rc = populateNegotiationContext(errorDescription, context);
463+
if (rc != 0) {
464+
return session; // RETURN
465+
}
469466

470467
// Communicate heartbeat settings. Currently, only for SDK use
471468
const mqbcfg::NetworkInterfaces& niConfig = appConfig.networkInterfaces();
472-
473-
response.maxMissedHeartbeats() = context->d_maxMissedHeartbeat;
474-
469+
response.maxMissedHeartbeats() = context->d_maxMissedHeartbeat;
475470
if (niConfig.tcpInterface().has_value()) {
476471
response.heartbeatIntervalMs() =
477472
niConfig.tcpInterface().value().heartbeatIntervalMs();
478473
}
479474

480-
int rc = sendNegotiationMessage(errorDescription,
481-
negotiationResponse,
482-
context);
475+
rc = sendNegotiationMessage(errorDescription,
476+
negotiationResponse,
477+
context);
483478
if (rc != 0) {
484-
session.reset();
479+
return session; // RETURN
485480
}
486481

482+
// Create the session.
483+
bsl::string description;
484+
loadSessionDescription(
485+
&description,
486+
clientIdentity,
487+
*(context->d_initialConnectionContext_p->channel().get()));
488+
489+
createSession(&session, context, description);
490+
487491
return session;
488492
}
489493

@@ -522,7 +526,11 @@ SessionNegotiator::onBrokerResponseMessage(bsl::ostream& errorDescription,
522526
brokerResponse.brokerIdentity(),
523527
*(context->d_initialConnectionContext_p->channel().get()));
524528

525-
createSession(errorDescription, &session, context, description);
529+
const int rc = populateNegotiationContext(errorDescription, context);
530+
if (rc != 0) {
531+
return session; // RETURN
532+
}
533+
createSession(&session, context, description);
526534

527535
return session;
528536
}
@@ -592,16 +600,26 @@ int SessionNegotiator::sendNegotiationMessage(
592600
return rc_SUCCESS;
593601
}
594602

595-
void SessionNegotiator::createSession(bsl::ostream& errorDescription,
596-
bsl::shared_ptr<mqbnet::Session>* out,
597-
const NegotiationContextSp& context,
598-
const bsl::string& description)
603+
int SessionNegotiator::populateNegotiationContext(
604+
bsl::ostream& errorDescription,
605+
const NegotiationContextSp& context)
599606
{
607+
enum RcEnum {
608+
// Value for the various RC error categories
609+
rc_SUCCESS = 0,
610+
rc_GET_CLUSTER_NODE_FAILED = -1
611+
};
612+
600613
// PRECONDITIONS
601614
BSLS_ASSERT_SAFE(context->d_connectionType !=
602615
mqbnet::ConnectionType::e_UNKNOWN);
603616
BSLS_ASSERT_SAFE(!context->d_negotiationMessage.isUndefinedValue());
604617

618+
if (context->d_connectionType == mqbnet::ConnectionType::e_ADMIN) {
619+
// Nothing to do for admin connection
620+
return rc_SUCCESS; // RETURN
621+
}
622+
605623
const bmqp_ctrlmsg::NegotiationMessage& negoMsg =
606624
context->d_negotiationMessage;
607625
const bmqp_ctrlmsg::ClientIdentity& peerIdentity =
@@ -612,41 +630,7 @@ void SessionNegotiator::createSession(bsl::ostream& errorDescription,
612630
const mqbcfg::NetworkInterfaces& niConfig = brkrCfg.networkInterfaces();
613631
int maxMissedHeartbeats = 0;
614632

615-
if (context->d_connectionType == mqbnet::ConnectionType::e_ADMIN) {
616-
mqba::AdminSession* session = new (*d_allocator_p)
617-
AdminSession(context->d_initialConnectionContext_p->channel(),
618-
negoMsg,
619-
description,
620-
d_dispatcher_p,
621-
d_blobSpPool_p,
622-
d_scheduler_p,
623-
d_adminCb,
624-
d_allocator_p);
625-
626-
out->reset(session, d_allocator_p);
627-
}
628-
else if (context->d_connectionType == mqbnet::ConnectionType::e_CLIENT) {
629-
// Create a dedicated stats subcontext for this client
630-
bmqst::StatContextConfiguration statContextCfg(description);
631-
statContextCfg.storeExpiredSubcontextValues(true);
632-
bslma::ManagedPtr<bmqst::StatContext> statContext =
633-
d_statContext_p->addSubcontext(statContextCfg);
634-
635-
mqba::ClientSession* session = new (*d_allocator_p)
636-
ClientSession(context->d_initialConnectionContext_p->channel(),
637-
negoMsg,
638-
description,
639-
d_dispatcher_p,
640-
d_clusterCatalog_p,
641-
d_domainFactory_p,
642-
statContext,
643-
d_blobSpPool_p,
644-
d_bufferFactory_p,
645-
d_scheduler_p,
646-
d_allocator_p);
647-
648-
out->reset(session, d_allocator_p);
649-
633+
if (context->d_connectionType == mqbnet::ConnectionType::e_CLIENT) {
650634
// Configure heartbeat
651635
if (negoMsg.clientIdentity().clientType() ==
652636
bmqp_ctrlmsg::ClientType::E_TCPCLIENT) {
@@ -683,17 +667,9 @@ void SessionNegotiator::createSession(bsl::ostream& errorDescription,
683667
peerIdentity.clusterNodeId());
684668

685669
if (!clusterNode) {
686-
return; // RETURN
670+
return rc_GET_CLUSTER_NODE_FAILED; // RETURN
687671
}
688672

689-
out->reset(new (*d_allocator_p) mqbnet::DummySession(
690-
context->d_initialConnectionContext_p->channel(),
691-
negoMsg,
692-
clusterNode,
693-
description,
694-
d_allocator_p),
695-
d_allocator_p);
696-
697673
// Configure heartbeat
698674
if (clusterNode->cluster()->selfNodeId() ==
699675
mqbnet::Cluster::k_INVALID_NODE_ID) {
@@ -705,6 +681,75 @@ void SessionNegotiator::createSession(bsl::ostream& errorDescription,
705681
}
706682

707683
context->d_maxMissedHeartbeat = maxMissedHeartbeats;
684+
685+
return rc_SUCCESS;
686+
}
687+
688+
void SessionNegotiator::createSession(bsl::shared_ptr<mqbnet::Session>* out,
689+
const NegotiationContextSp& context,
690+
const bsl::string& description)
691+
{
692+
// PRECONDITIONS
693+
BSLS_ASSERT_SAFE(context->d_connectionType !=
694+
mqbnet::ConnectionType::e_UNKNOWN);
695+
BSLS_ASSERT_SAFE(!context->d_negotiationMessage.isUndefinedValue());
696+
697+
const bmqp_ctrlmsg::NegotiationMessage& negoMsg =
698+
context->d_negotiationMessage;
699+
const bsl::shared_ptr<bmqio::Channel>& channel =
700+
context->d_initialConnectionContext_p->channel();
701+
702+
if (context->d_connectionType == mqbnet::ConnectionType::e_ADMIN) {
703+
mqba::AdminSession* session = new (*d_allocator_p)
704+
AdminSession(channel,
705+
negoMsg,
706+
description,
707+
d_dispatcher_p,
708+
d_blobSpPool_p,
709+
d_scheduler_p,
710+
d_adminCb,
711+
d_allocator_p);
712+
713+
out->reset(session, d_allocator_p);
714+
}
715+
else if (context->d_connectionType == mqbnet::ConnectionType::e_CLIENT) {
716+
// Create a dedicated stats subcontext for this client
717+
bmqst::StatContextConfiguration statContextCfg(description);
718+
statContextCfg.storeExpiredSubcontextValues(true);
719+
bslma::ManagedPtr<bmqst::StatContext> statContext =
720+
d_statContext_p->addSubcontext(statContextCfg);
721+
722+
mqba::ClientSession* session = new (*d_allocator_p)
723+
ClientSession(channel,
724+
negoMsg,
725+
description,
726+
d_dispatcher_p,
727+
d_clusterCatalog_p,
728+
d_domainFactory_p,
729+
statContext,
730+
d_blobSpPool_p,
731+
d_bufferFactory_p,
732+
d_scheduler_p,
733+
d_allocator_p);
734+
735+
out->reset(session, d_allocator_p);
736+
}
737+
else {
738+
const bmqp_ctrlmsg::ClientIdentity& peerIdentity =
739+
negoMsg.isClientIdentityValue()
740+
? negoMsg.clientIdentity()
741+
: negoMsg.brokerResponse().brokerIdentity();
742+
743+
mqbnet::ClusterNode* clusterNode = context->d_cluster_p->lookupNode(
744+
peerIdentity.clusterNodeId());
745+
746+
out->reset(new (*d_allocator_p) mqbnet::DummySession(channel,
747+
negoMsg,
748+
clusterNode,
749+
description,
750+
d_allocator_p),
751+
d_allocator_p);
752+
}
708753
}
709754

710755
bool SessionNegotiator::checkIsDeprecatedSdkVersion(

src/groups/mqb/mqba/mqba_sessionnegotiator.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,18 @@ class SessionNegotiator : public mqbnet::Negotiator {
160160
const bmqp_ctrlmsg::NegotiationMessage& message,
161161
const NegotiationContextSp& context);
162162

163+
/// Populate some other fields in `context` given the specified
164+
/// ConnectionType and NegotiationMessage. Return 0 on success, or
165+
/// return a non-zero code on error and populate the specified
166+
/// `errorDescription` with a description of the error.
167+
int populateNegotiationContext(bsl::ostream& errorDescription,
168+
const NegotiationContextSp& context);
169+
163170
/// Load into the specified `out` a new session created using the
164171
/// specified `context` and `description`; or leave `out` untouched and
165172
/// populate the specified `errorDescription` with a description of the
166173
/// error in case of failure.
167-
void createSession(bsl::ostream& errorDescription,
168-
bsl::shared_ptr<mqbnet::Session>* out,
174+
void createSession(bsl::shared_ptr<mqbnet::Session>* out,
169175
const NegotiationContextSp& context,
170176
const bsl::string& description);
171177

0 commit comments

Comments
 (0)