@@ -336,11 +336,13 @@ void StorageManager::dispatchEventToPartition(PartitionFSM::Event::Enum event,
336336 // PRECONDITIONS
337337 BSLS_ASSERT_SAFE (eventDataVec.size () >= 1 );
338338
339- // NOTE: it is assumed that all elements in 'eventDataVec' have the same
340- // 'partitionId'.
341339 const int partitionId = eventDataVec[0 ].partitionId ();
342340 BSLS_ASSERT_SAFE (0 <= partitionId &&
343341 partitionId < static_cast <int >(d_fileStores.size ()));
342+ // Verify other events with 0-indexed event's partitionId
343+ for (size_t i = 1 ; i < eventDataVec.size (); ++i) {
344+ BSLS_ASSERT_SAFE (partitionId == eventDataVec[i].partitionId ());
345+ }
344346
345347 if (d_cluster_p->isStopping ()) {
346348 BALL_LOG_WARN << d_clusterData_p->identity ().description ()
@@ -353,17 +355,88 @@ void StorageManager::dispatchEventToPartition(PartitionFSM::Event::Enum event,
353355 mqbs::FileStore* fs = d_fileStores[partitionId].get ();
354356 BSLS_ASSERT_SAFE (fs);
355357 if (fs->inDispatcherThread ()) {
356- d_partitionFSMVec[partitionId]->enqueueEvent (
357- PartitionFSM::EventWithData (event, eventDataVec));
358+ executeEventInPartitionThread (event, eventDataVec);
358359 }
359360 else {
360361 fs->execute (bdlf::BindUtil::bind (
361- &PartitionFSM::enqueueEvent,
362- d_partitionFSMVec[partitionId].get (),
363- PartitionFSM::EventWithData (event, eventDataVec)));
362+ &StorageManager::executeEventInPartitionThread,
363+ this ,
364+ event,
365+ eventDataVec));
364366 }
365367}
366368
369+ void StorageManager::executeEventInPartitionThread (
370+ PartitionFSM::Event::Enum event,
371+ const EventData& eventDataVec)
372+ {
373+ // Thread: QUEUE dispatcher
374+
375+ // PRECONDITIONS
376+ BSLS_ASSERT_SAFE (eventDataVec.size () >= 1 );
377+
378+ const int partitionId = eventDataVec[0 ].partitionId ();
379+ BSLS_ASSERT_SAFE (0 <= partitionId &&
380+ partitionId < static_cast <int >(d_fileStores.size ()));
381+ BSLS_ASSERT_SAFE (d_fileStores[partitionId]->inDispatcherThread ());
382+
383+ // Verify events
384+ if (eventDataVec.size () == 1 ) {
385+ const PartitionFSMEventData& evt = eventDataVec[0 ];
386+
387+ // Do not perform extra checks if primaryLeaseId is unspecified.
388+ if (PartitionFSMEventData::k_INVALID_LEASE_ID !=
389+ evt.primaryLeaseId ()) {
390+ const PartitionInfo& pinfo = d_partitionInfoVec[partitionId];
391+
392+ const bool isLeaseIdOutdated = evt.primaryLeaseId () <
393+ pinfo.primaryLeaseId ();
394+ const bool isPrimaryMismatch = evt.primaryLeaseId () ==
395+ pinfo.primaryLeaseId () &&
396+ evt.primary () && pinfo.primary () &&
397+ evt.primary ()->nodeId () !=
398+ pinfo.primary ()->nodeId ();
399+
400+ if (isLeaseIdOutdated || isPrimaryMismatch) {
401+ BALL_LOG_WARN
402+ << d_clusterData_p->identity ().description ()
403+ << " Partition [" << partitionId
404+ << " ]: dropping stale event: source "
405+ << evt.source ()->nodeDescription ()
406+ << " , event primaryLeaseId [" << evt.primaryLeaseId ()
407+ << " ], current primaryLeaseId [" << pinfo.primaryLeaseId ()
408+ << " ], event primary ["
409+ << (evt.primary () ? evt.primary ()->nodeDescription ()
410+ : " null" )
411+ << " ], current primary ["
412+ << (pinfo.primary () ? pinfo.primary ()->nodeDescription ()
413+ : " null" )
414+ << " ]" ;
415+
416+ if (0 <= evt.requestId ()) {
417+ bmqp_ctrlmsg::ControlMessage controlMsg;
418+ controlMsg.rId () = evt.requestId ();
419+ bmqp_ctrlmsg::Status& response =
420+ controlMsg.choice ().makeStatus ();
421+
422+ response.category () =
423+ bmqp_ctrlmsg::StatusCategory::E_REFUSED ;
424+ response.code () = mqbi::ClusterErrorCode::e_UNKNOWN;
425+ response.message () = " Primary mismatch" ;
426+
427+ d_clusterData_p->messageTransmitter ().sendMessageSafe (
428+ controlMsg,
429+ evt.source ());
430+ }
431+ return ;
432+ }
433+ }
434+ }
435+
436+ d_partitionFSMVec[partitionId]->enqueueEvent (
437+ PartitionFSM::EventWithData (event, eventDataVec));
438+ }
439+
367440void StorageManager::setPrimaryStatusForPartitionDispatched (
368441 int partitionId,
369442 bmqp_ctrlmsg::PrimaryStatus::Value value)
@@ -1580,10 +1653,13 @@ void StorageManager::do_replicaStateResponse(const EventWithData& event)
15801653 BSLS_ASSERT_SAFE (eventDataVec.size () == 1 );
15811654
15821655 const PartitionFSMEventData& eventData = eventDataVec[0 ];
1583- int partitionId = eventData.partitionId ();
1656+ const int partitionId = eventData.partitionId ();
15841657
15851658 BSLS_ASSERT_SAFE (0 <= partitionId &&
15861659 partitionId < static_cast <int >(d_fileStores.size ()));
1660+ BSLS_ASSERT_SAFE (eventData.source ());
1661+ BSLS_ASSERT_SAFE (eventData.source ()->nodeId () ==
1662+ d_partitionInfoVec[partitionId].primary ()->nodeId ());
15871663
15881664 bmqp_ctrlmsg::ControlMessage controlMsg;
15891665 controlMsg.rId () = eventData.requestId ();
@@ -1609,10 +1685,6 @@ void StorageManager::do_replicaStateResponse(const EventWithData& event)
16091685 response.partitionMaxFileSizes () = getSelfPartitionMaxFileSizes (
16101686 partitionId);
16111687
1612- BSLS_ASSERT_SAFE (eventData.source ());
1613- BSLS_ASSERT_SAFE (eventData.source ()->nodeId () ==
1614- d_partitionInfoVec[partitionId].primary ()->nodeId ());
1615-
16161688 fileStore (partitionId).sendMessage (controlMsg, eventData.source ());
16171689
16181690 BALL_LOG_INFO << d_clusterData_p->identity ().description ()
@@ -2795,6 +2867,36 @@ void StorageManager::do_processLiveData(const EventWithData& event)
27952867 source);
27962868}
27972869
2870+ void StorageManager::do_setPrimary (const EventWithData& event)
2871+ {
2872+ // executed by the *QUEUE DISPATCHER* thread associated with the
2873+ // paritionId contained in 'event'
2874+
2875+ const EventData& eventDataVec = event.second ;
2876+ BSLS_ASSERT_SAFE (eventDataVec.size () == 1 );
2877+
2878+ const PartitionFSMEventData& eventData = eventDataVec[0 ];
2879+ const int partitionId = eventData.partitionId ();
2880+ mqbnet::ClusterNode* primary = eventData.primary ();
2881+ const unsigned int leaseId = eventData.primaryLeaseId ();
2882+
2883+ // PRECONDITIONS
2884+ BSLS_ASSERT_SAFE (0 <= partitionId &&
2885+ partitionId < static_cast <int >(d_fileStores.size ()));
2886+ BSLS_ASSERT_SAFE (d_fileStores[partitionId]->inDispatcherThread ());
2887+ BSLS_ASSERT_SAFE (primary);
2888+
2889+ PartitionInfo& pinfo = d_partitionInfoVec[partitionId];
2890+ if (pinfo.primary () && (pinfo.primary ()->nodeId () == primary->nodeId ())) {
2891+ pinfo.setPrimaryLeaseId (leaseId);
2892+ return ; // RETURN
2893+ }
2894+
2895+ pinfo.setPrimary (primary);
2896+ pinfo.setPrimaryLeaseId (leaseId);
2897+ pinfo.setPrimaryStatus (bmqp_ctrlmsg::PrimaryStatus::E_PASSIVE );
2898+ }
2899+
27982900void StorageManager::do_cleanupMetadata (const EventWithData& event)
27992901{
28002902 // executed by the *QUEUE DISPATCHER* thread associated with the
@@ -2815,6 +2917,12 @@ void StorageManager::do_cleanupMetadata(const EventWithData& event)
28152917 d_partitionFSMVec[partitionId]->state () ==
28162918 PartitionFSM::State::e_STOPPED);
28172919
2920+ StorageUtil::clearPrimaryForPartition (
2921+ d_fileStores[partitionId].get (),
2922+ &d_partitionInfoVec[partitionId],
2923+ d_clusterData_p->identity ().description (),
2924+ partitionId);
2925+
28182926 d_nodeToContextMapVec[partitionId].clear ();
28192927 d_numReplicaDataResponsesReceivedVec[partitionId] = 0 ;
28202928 d_recoveryManager_mp->resetReceiveDataCtx (partitionId);
@@ -4905,6 +5013,8 @@ void StorageManager::processReplicaStateRequest(
49055013 message.rId ().isNull () ? -1 : message.rId ().value (),
49065014 partitionId,
49075015 1 ,
5016+ source,
5017+ replicaStateRequest.latestSequenceNumber ().primaryLeaseId (),
49085018 replicaStateRequest.latestSequenceNumber (),
49095019 replicaStateRequest.firstSyncPointAfterRolloverSequenceNumber (),
49105020 replicaStateRequest.partitionMaxFileSizes ());
0 commit comments