Skip to content

Commit d313b89

Browse files
committed
Pause state machine before pg_destroy
1 parent d60656a commit d313b89

4 files changed

Lines changed: 48 additions & 5 deletions

File tree

conanfile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class HomeObjectConan(ConanFile):
1111
name = "homeobject"
12-
version = "2.6.2"
12+
version = "2.6.3"
1313

1414
homepage = "https://github.com/eBay/HomeObject"
1515
description = "Blob Store built on HomeReplication"
@@ -49,7 +49,7 @@ def build_requirements(self):
4949

5050
def requirements(self):
5151
self.requires("sisl/[^12.2]@oss/master", transitive_headers=True)
52-
self.requires("homestore/[~6.18.0]@oss/master")
52+
self.requires("homestore/[~6.18.4]@oss/master")
5353
self.requires("iomgr/[^11.3]@oss/master")
5454
self.requires("lz4/1.9.4", override=True)
5555
self.requires("openssl/3.3.1", override=True)

src/lib/homestore_backend/hs_homeobject.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,11 @@ class HSHomeObject : public HomeObjectImpl {
764764
*
765765
* @param pg_id The ID of the PG to be destroyed.
766766
*/
767-
void pg_destroy(pg_id_t pg_id);
767+
bool pg_destroy(pg_id_t pg_id, bool need_to_pause_pg_state_machine = false);
768+
769+
bool pause_pg_state_machine(pg_id_t pg_id);
770+
771+
bool resume_pg_state_machine(pg_id_t pg_id);
768772

769773
/**
770774
* @brief Get HS_PG object from given pg_id.

src/lib/homestore_backend/hs_pg_manager.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,11 @@ std::optional< pg_id_t > HSHomeObject::get_pg_id_with_group_id(group_id_t group_
434434
}
435435
}
436436

437-
void HSHomeObject::pg_destroy(pg_id_t pg_id) {
437+
bool HSHomeObject::pg_destroy(pg_id_t pg_id, bool need_to_pause_pg_state_machine) {
438+
if (need_to_pause_pg_state_machine && !pause_pg_state_machine(pg_id)) {
439+
LOGI("Failed to pause pg state machine, pg_id={}", pg_id);
440+
return false;
441+
}
438442
LOGI("Destroying pg={}", pg_id);
439443
mark_pg_destroyed(pg_id);
440444
destroy_shards(pg_id);
@@ -448,6 +452,35 @@ void HSHomeObject::pg_destroy(pg_id_t pg_id) {
448452
RELEASE_ASSERT(res, "Failed to return pg={} chunks to dev_heap", pg_id);
449453

450454
LOGI("pg={} is destroyed", pg_id);
455+
return true;
456+
}
457+
458+
bool HSHomeObject::pause_pg_state_machine(pg_id_t pg_id) {
459+
LOGI("Pause pg state machine, pg={}", pg_id);
460+
auto hs_pg = const_cast< HS_PG* >(_get_hs_pg_unlocked(pg_id));
461+
auto repl_dev = hs_pg ? hs_pg->repl_dev_ : nullptr;
462+
auto max_wait_time_ms = 2000;
463+
for (auto i = 0; i < 2000 / 500; i++) {
464+
hs_pg->repl_dev_->pause_state_machine(500 /* ms */);
465+
if (repl_dev->is_state_machine_paused()) {
466+
LOGI("pg={} state machine is paused", pg_id);
467+
return true;
468+
}
469+
}
470+
LOGE("Failed to pause pg={} state machine after {} ms", pg_id, max_wait_time_ms);
471+
return false;
472+
}
473+
474+
bool HSHomeObject::resume_pg_state_machine(pg_id_t pg_id) {
475+
LOGI("Resuming pg state machine, pg={}", pg_id);
476+
auto hs_pg = const_cast< HS_PG* >(_get_hs_pg_unlocked(pg_id));
477+
auto repl_dev = hs_pg ? hs_pg->repl_dev_ : nullptr;
478+
while (repl_dev->is_state_machine_paused()) {
479+
hs_pg->repl_dev_->resume_state_machine();
480+
std::this_thread::sleep_for(std::chrono::milliseconds(500));
481+
}
482+
LOGE("Resumed pg state machine, pg=", pg_id);
483+
return true;
451484
}
452485

453486
void HSHomeObject::mark_pg_destroyed(pg_id_t pg_id) {

src/lib/homestore_backend/replication_state_machine.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ bool ReplicationStateMachine::apply_snapshot(std::shared_ptr< homestore::snapsho
311311
LOGI("Simulating apply snapshot with delay, delay={}", delay.get());
312312
std::this_thread::sleep_for(std::chrono::milliseconds(delay.get()));
313313
}
314+
// It's an inifinite loop until the state machine resumes.
315+
home_object_->resume_pg_state_machine(m_snp_rcv_handler->get_context_pg_id());
314316
#endif
315317
m_snp_rcv_handler->destroy_context_and_metrics();
316318

@@ -486,7 +488,11 @@ void ReplicationStateMachine::write_snapshot_obj(std::shared_ptr< homestore::sna
486488
// If PG already exists, clean the stale pg resources. Let's resync on a pristine base
487489
if (home_object_->pg_exists(pg_data->pg_id())) {
488490
LOGI("pg already exists, clean pg resources before snapshot, pg={} {}", pg_data->pg_id(), log_suffix);
489-
home_object_->pg_destroy(pg_data->pg_id());
491+
// Need to pause state machine before destroying the PG, if fail, let raft retry.
492+
if (!home_object_->pg_destroy(pg_data->pg_id(), true /* pause state machine */)) {
493+
LOGE("failed to destroy existing pg, let raft retry, pg={} {}", pg_data->pg_id(), log_suffix);
494+
return;
495+
}
490496
}
491497
LOGI("reset context from lsn={} to lsn={}", m_snp_rcv_handler->get_context_lsn(), context->get_lsn());
492498
m_snp_rcv_handler->reset_context_and_metrics(context->get_lsn(), pg_data->pg_id());

0 commit comments

Comments
 (0)