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 3 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 starting/canceling/pausing 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::secondary_parent_handle_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 secondary_parent_handle_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 @@ -340,6 +340,28 @@ class replica_split_test : public replica_test_base
_parent_replica->tracker()->wait_outstanding_tasks();
}

group_check_response test_secondary_parent_handle_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->secondary_parent_handle_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 @@ -690,17 +712,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 @@ -713,5 +734,33 @@ TEST_F(replica_split_test, register_child_reply_test)
}
}

// secondary_parent_handle_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 secondary_parent_handle_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_secondary_parent_handle_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