Skip to content
This repository has been archived by the owner on Jun 23, 2022. It is now read-only.

feat(split): parent group update partition count #654

Merged
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
3 changes: 3 additions & 0 deletions src/replica/replica_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "replica_stub.h"

#include "duplication/replica_duplicator_manager.h"
#include "split/replica_split_manager.h"

#include <dsn/dist/fmt_logging.h>
#include <dsn/dist/replication/replication_app_base.h>
Expand Down Expand Up @@ -175,6 +176,8 @@ void replica::on_group_check(const group_check_request &request,
if (request.last_committed_decree > last_committed_decree()) {
_prepare_list->commit(request.last_committed_decree, COMMIT_TO_DECREE_HARD);
}
// the group check may trigger start/finish/cancel/pause a split on the secondary.
_split_mgr->trigger_secondary_parent_split(request, response);
break;
case partition_status::PS_POTENTIAL_SECONDARY:
init_learn(request.config.learner_signature);
Expand Down
19 changes: 18 additions & 1 deletion src/replica/split/replica_split_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,7 +1050,9 @@ void replica_split_manager::on_register_child_on_meta_reply(
_replica->_primary_states.register_child_task = nullptr;
_replica->_primary_states.sync_send_write_request = false;

// TODO(heyuchen): TBD - update parent group partition_count
// update primary parent group partition_count
update_local_partition_count(_replica->_app_info.partition_count * 2);
_replica->broadcast_group_check();

parent_cleanup_split_context();
}
Expand Down Expand Up @@ -1101,5 +1103,20 @@ void replica_split_manager::child_handle_async_learn_error() // on child partiti
_replica->_split_states.async_learn_task = nullptr;
}

// ThreadPool: THREAD_POOL_REPLICATION
void replica_split_manager::trigger_secondary_parent_split(
const group_check_request &request,
/*out*/ group_check_response &response) // on secondary parent partition
{
if (request.app.partition_count ==
_replica->_app_info.partition_count * 2) { // secondary update partition count
update_local_partition_count(request.app.partition_count);
parent_cleanup_split_context();
neverchanje marked this conversation as resolved.
Show resolved Hide resolved
return;
}

// TODO(heyuchen): add other split_status check, response will be used in future
}

} // namespace replication
} // namespace dsn
5 changes: 5 additions & 0 deletions src/replica/split/replica_split_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ class replica_split_manager : replica_base
// child handle error while async learn parent states
void child_handle_async_learn_error();

// called by `on_group_check` in `replica_check.cpp`
// secondary parent check whether should start or stop split
void trigger_secondary_parent_split(const group_check_request &request,
/*out*/ group_check_response &response);

//
// helper functions
//
Expand Down
57 changes: 53 additions & 4 deletions src/replica/split/test/replica_split_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,28 @@ class replica_split_test : public replica_test_base
_child_replica->tracker()->wait_outstanding_tasks();
}

group_check_response test_trigger_secondary_parent_split(split_status::type meta_split_status,
split_status::type local_split_status)
{
_parent_replica->set_partition_status(partition_status::PS_SECONDARY);
parent_set_split_status(local_split_status);

group_check_request req;
req.app = _parent_replica->_app_info;
req.config.ballot = INIT_BALLOT;
req.config.status = partition_status::PS_SECONDARY;
req.node = SECONDARY;
if (meta_split_status == split_status::NOT_SPLIT) {
req.app.partition_count *= 2;
}

group_check_response resp;
_parent_split_mgr->trigger_secondary_parent_split(req, resp);
_parent_replica->tracker()->wait_outstanding_tasks();

return resp;
}

/// helper functions
void cleanup_prepare_list(mock_replica_ptr rep) { rep->_prepare_list->reset(0); }
void cleanup_child_split_context()
Expand Down Expand Up @@ -691,17 +713,16 @@ TEST_F(replica_split_test, register_child_reply_test)
// - wrong partition status
// - response error = INVALID_STATE
// - response error = CHILD_REGISTERED
// - TODO(heyuchen): add response error = OK
// ({partition_status::PS_INACTIVE, ERR_OK, NEW_PARTITION_COUNT - 1})
// after implement parent update group partition count
// - response error = OK
struct register_child_reply_test
{
partition_status::type parent_partition_status;
error_code resp_err;
int32_t expected_parent_partition_version;
} tests[] = {{partition_status::PS_PRIMARY, ERR_OK, -1},
{partition_status::PS_INACTIVE, ERR_INVALID_STATE, -1},
{partition_status::PS_INACTIVE, ERR_CHILD_REGISTERED, -1}};
{partition_status::PS_INACTIVE, ERR_CHILD_REGISTERED, -1},
{partition_status::PS_INACTIVE, ERR_OK, NEW_PARTITION_COUNT - 1}};
for (auto test : tests) {
mock_child_split_context(true, true);
test_on_register_child_reply(test.parent_partition_status, test.resp_err);
Expand All @@ -714,5 +735,33 @@ TEST_F(replica_split_test, register_child_reply_test)
}
}

// trigger_secondary_parent_split unit test
TEST_F(replica_split_test, secondary_handle_split_test)
{
generate_child();

// Test cases:
// - secondary parent update partition_count
// TODO(heyuchen): add more cases
struct trigger_secondary_parent_split_test
{
split_status::type meta_split_status;
split_status::type local_split_status;
int32_t expected_partition_version;
} tests[]{{split_status::NOT_SPLIT, split_status::SPLITTING, NEW_PARTITION_COUNT - 1}};

for (auto test : tests) {
if (test.local_split_status == split_status::SPLITTING) {
mock_child_split_context(true, true);
mock_parent_split_context(partition_status::PS_SECONDARY);
}
auto resp =
test_trigger_secondary_parent_split(test.meta_split_status, test.local_split_status);
ASSERT_EQ(resp.err, ERR_OK);
ASSERT_TRUE(is_parent_not_in_split());
ASSERT_EQ(_parent_split_mgr->get_partition_version(), test.expected_partition_version);
}
}

} // namespace replication
} // namespace dsn