Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 87 additions & 23 deletions src/groups/mqb/mqbblp/mqbblp_domain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <bsls_nullptr.h>

Check failure on line 16 in src/groups/mqb/mqbblp/mqbblp_domain.cpp

View workflow job for this annotation

GitHub Actions / C++ Linter Check

src/groups/mqb/mqbblp/mqbblp_domain.cpp:16:10 [clang-diagnostic-error]

'bsls_nullptr.h' file not found

Check failure on line 16 in src/groups/mqb/mqbblp/mqbblp_domain.cpp

View workflow job for this annotation

GitHub Actions / C++ Linter Check

src/groups/mqb/mqbblp/mqbblp_domain.cpp:16:10 [clang-diagnostic-error]

'bsls_nullptr.h' file not found
#include <mqbblp_domain.h>

#include <mqbscm_version.h>
Expand Down Expand Up @@ -211,6 +211,55 @@
return updatedValues;
}

/// @brief Function object that reconfigures a snapshot of queues.
class QueueReconfigureFunctor {
public:
// TYPES

/// Snapshot of queues held by weak pointer.
typedef bsl::vector<bsl::weak_ptr<mqbi::Queue> > QueueWeakPtrVector;

private:
// DATA

/// Shared snapshot of the queues to reconfigure.
bsl::shared_ptr<QueueWeakPtrVector> d_queues_sp;

public:
// CREATORS

/// @brief Create a functor owning the specified `queues_sp` snapshot.
///
/// @param queues_sp The queues to reconfigure, held by weak pointer.
explicit QueueReconfigureFunctor(
const bsl::shared_ptr<QueueWeakPtrVector>& queues_sp)
: d_queues_sp(queues_sp)
{
// PRECONDITIONS
BSLS_ASSERT(queues_sp);
}

// ACCESSORS

/// @brief Reconfigure every queue in the snapshot that is still alive.
void operator()() const
{
// Thread: CLUSTER DISPATCHER

for (QueueWeakPtrVector::const_iterator it = d_queues_sp->begin();
it != d_queues_sp->end();
++it) {
bsl::shared_ptr<mqbi::Queue> queue = it->lock();
if (queue) {
queue->configure(
static_cast<bsl::ostream*>(0), // errorDescription
true, // isReconfigure
false); // wait
}
}
}
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each one of these queue->configure enqueues an event to its dispatcher thread, it is the existing behavior and I decided not to change it in this PR


} // close unnamed namespace

// ------------
Expand All @@ -224,7 +273,7 @@
const mqbi::OpenQueueConfirmationCookieSp& confirmationCookie,
const mqbi::Domain::OpenQueueCallback& callback)
{
// executed by *ANY* thread
// Thread: CLUSTER DISPATCHER

--d_pendingRequests;
if (status.category() == bmqp_ctrlmsg::StatusCategory::E_SUCCESS) {
Expand Down Expand Up @@ -287,6 +336,8 @@
int Domain::configure(bsl::ostream& errorDescription,
const mqbconfm::Domain& newConfig)
{
// Thread: ADMIN

enum RcEnum {
// Value for the various RC error categories
rc_SUCCESS = 0,
Expand Down Expand Up @@ -358,6 +409,22 @@
// any needed update-advisories to the CSL.
d_cluster_sp->onDomainReconfigured(*this, *oldConfig, finalConfig);

// Make a snapshot of weak queue pointers for reconfigure.
bsl::shared_ptr<QueueReconfigureFunctor::QueueWeakPtrVector>
queues_sp = bsl::allocate_shared<
QueueReconfigureFunctor::QueueWeakPtrVector>(d_allocator_p);
{
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); // LOCK
queues_sp->reserve(d_queues.size());
for (QueueMapCIter it = d_queues.begin(); it != d_queues.end();
++it) {
queues_sp->push_back(it->second);
}
}

BALL_LOG_INFO << "Reconfiguring " << queues_sp->size()
<< " queues from domain " << d_name;

// Note: Queues must only be reconfigured AFTER ensuring that virtual
// storage has been created for any new AppIds. This is done by the
// 'QueueEngine::afterAppIdRegistered' method, which is invoked on the
Expand All @@ -370,19 +437,7 @@
// that it happens after 'onDomainReconfigured'; since implementation
// of 'Queue::configure' dispatches to the Queue dispatcher thread, it
// will also happen after completion of 'afterAppIdRegistered' above.
BALL_LOG_INFO << "Reconfiguring " << d_queues.size()
<< " queues from domain " << d_name;

QueueMap::iterator it = d_queues.begin();
for (; it != d_queues.end(); it++) {
bsl::function<int()> reconfigureQueueFn = bdlf::BindUtil::bind(
&mqbi::Queue::configure,
it->second.get(),
static_cast<bsl::ostream*>(0), // errorDescription_p
true, // isReconfigure
false); // wait
d_dispatcher_p->execute(reconfigureQueueFn, cluster());
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it->second.get() was a raw ptr to a queue. What if a queue is destructed in between? To handle this, I changed the snapshot to take weak_ptr.

d_dispatcher_p->execute(QueueReconfigureFunctor(queues_sp), cluster());

@678098 678098 Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If domain has thousands of queues, we enqueued thousands of events here.
At least on this level I wanted to enqueue only one event and made functor for it, that owns queues snapshot

}
// 'wait==false', so the result of reconfiguration is not known

Expand Down Expand Up @@ -450,7 +505,7 @@
const bmqp_ctrlmsg::QueueHandleParameters& handleParameters,
const mqbi::Domain::OpenQueueCallback& callback)
{
// will execute in DomainManager's IO requester thread
// Thread: DomainManager's IO requester thread
// (TBD: for now, in client-session or cluster dispatcher thread)

// PRECONDITIONS
Expand Down Expand Up @@ -502,7 +557,7 @@

int Domain::registerQueue(const bsl::shared_ptr<mqbi::Queue>& queueSp)
{
// executed by the associated CLUSTER's DISPATCHER thread
// Thread: CLUSTER DISPATCHER

// PRECONDITIONS
BSLS_ASSERT_SAFE(d_cluster_sp->inDispatcherThread());
Expand All @@ -522,6 +577,8 @@
// invoke 'Queue.configure' outside of the lock scope, and in case it
// fails, we rollback.

size_t count = 0;

{
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); // LOCK

Expand All @@ -542,20 +599,22 @@
d_queues[queueSp->uri().queue()] = queueSp;

d_numQueues.add(1);

count = d_queues.size();
}

BALL_LOG_INFO << "Registered queue to domain '" << d_name << "' "
<< "[canonicalURI: " << queueSp->uri().canonical()
<< ", qId: " << bmqp::QueueId::QueueIdInt(queueSp->id())
<< "]. Total number of registered queues in the domain: "
<< d_queues.size() << ".";
<< count << ".";

return rc_SUCCESS;
}

void Domain::unregisterQueue(mqbi::Queue* queue)
{
// executed by the associated CLUSTER's DISPATCHER thread
// Thread: CLUSTER DISPATCHER

// PRECONDITIONS
BSLS_ASSERT_SAFE(d_cluster_sp->inDispatcherThread());
Expand Down Expand Up @@ -597,7 +656,7 @@
int Domain::processCommand(mqbcmd::DomainResult* result,
const mqbcmd::DomainCommand& command)
{
// executed by *any* thread
// Thread: ADMIN

if (command.isPurgeValue()) {
// Some queues might be inactive. They don't have associated
Expand Down Expand Up @@ -662,10 +721,15 @@
OrderedQueueMap;
typedef OrderedQueueMap::const_iterator OrderedQueueMapCIter;

// sort by queue name
OrderedQueueMap map(d_queues.cbegin(), d_queues.cend());
// Make a snapshot of queues.
OrderedQueueMap map(d_allocator_p);
{
bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); // LOCK
map.insert(d_queues.cbegin(), d_queues.cend());
}

OrderedQueueMapCIter cit;
domainInfo.queueUris().reserve(d_queues.size());
domainInfo.queueUris().reserve(map.size());
for (cit = map.cbegin(); cit != map.cend(); ++cit) {
domainInfo.queueUris().push_back(cit->second->uri().asString());
}
Expand Down Expand Up @@ -875,7 +939,7 @@
void Domain::loadRoutingConfiguration(
bmqp_ctrlmsg::RoutingConfiguration* config) const
{
// executed by the associated CLUSTER's DISPATCHER thread
// Thread: CLUSTER DISPATCHER

// PRECONDITIONS
BSLS_ASSERT_SAFE(d_cluster_sp->inDispatcherThread());
Expand Down
2 changes: 1 addition & 1 deletion src/groups/mqb/mqbblp/mqbblp_domain.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2023 Bloomberg Finance L.P.
// Copyright 2026 Bloomberg Finance L.P.
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
Loading
Loading