oceanbase/unittest/logservice/test_ob_role_change_service.cpp
wangzelin.wzl 93a1074b0c patch 4.0
2022-10-24 17:57:12 +08:00

323 lines
9.6 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include <gtest/gtest.h>
#include "logservice/ob_log_handler.h"
#include "logservice/rcservice/ob_role_change_handler.h"
#include "logservice/rcservice/ob_role_change_service.h"
#include "logservice/replayservice/ob_log_replay_service.h"
#include "share/ob_ls_id.h"
#include "storage/tx_storage/ob_ls_service.h"
namespace oceanbase
{
using namespace common;
using namespace palf;
using namespace logservice;
using namespace logservice;
namespace unittest
{
class MockApplyService : public AppendCbWorker
{
public:
int is_apply_done(const share::ObLSID &id, bool &is_done, LSN &lsn)
{
is_done = true;
lsn = end_lsn_;
PALF_LOG(INFO, "MockApplyService is_apply_done", K(id), K(is_done), K(lsn));
return OB_SUCCESS;
}
int push_append_cb(const int64_t id, AppendCb *cb, const LSN &lsn)
{
UNUSED(id);
UNUSED(cb);
UNUSED(lsn);
return OB_SUCCESS;
}
void advance_end_lsn(const LSN &lsn)
{
end_lsn_ = lsn;
}
private:
LSN end_lsn_;
};
class MockReplayService : public logservice::ObILogReplayService
{
public:
virtual int is_replay_done(const share::ObLSID &id, const palf::LSN &end_lsn, bool &is_done)
{
is_done = end_lsn <= end_lsn_;
PALF_LOG(INFO, "MockReplayService is_replay_done", K(id), K(is_done), K(end_lsn));
return OB_SUCCESS;
}
virtual int switch_to_follower(const share::ObLSID &id, const palf::LSN &begin_lsn)
{
PALF_LOG(INFO, "MockReplayService switch_to_follower", K(id), K(begin_lsn));
return OB_SUCCESS;
}
virtual int switch_to_leader(const share::ObLSID &id)
{
PALF_LOG(INFO, "MockReplayService switch_to_leader", K(id));
return OB_SUCCESS;
}
void advance_end_lsn(const LSN &end_lsn)
{
end_lsn_ = end_lsn;
}
private:
LSN end_lsn_;
};
class MockObLogHandler : public logservice::ObILogHandler
{
public:
MockObLogHandler() : curr_role_(FOLLOWER),
curr_proposal_id_(-1),
new_role_(FOLLOWER),
new_proposal_id_(-1)
{}
virtual bool is_valid() const { return true; }
virtual int append(const void *buffer,
const int64_t nbytes,
const int64_t ref_ts_ns,
const bool need_nonblock,
logservice::AppendCb *cb,
palf::LSN &lsn,
int64_t &ts_ns)
{
UNUSED(need_nonblock);
UNUSED(buffer);
UNUSED(nbytes);
UNUSED(ref_ts_ns);
UNUSED(cb);
UNUSED(lsn);
UNUSED(ts_ns);
return OB_SUCCESS;
}
virtual int get_role(common::ObRole &role, int64_t &proposal_id) const
{
if (FOLLOWER == curr_role_) {
role = curr_role_;
proposal_id = curr_proposal_id_;
} else {
role = new_role_;
proposal_id = curr_proposal_id_;
}
return OB_SUCCESS;
}
virtual int prepare_switch_role(common::ObRole &curr_role,
int64_t &curr_proposal_id,
common::ObRole &new_role,
int64_t &new_proposal_id)
{
curr_role = curr_role_;
curr_proposal_id = curr_proposal_id_;
new_role = new_role_;
new_proposal_id = new_proposal_id_;
PALF_LOG(INFO, "MockObLogHandler prepare_switch_role", K(curr_role), K(curr_proposal_id), K(new_role), K(new_proposal_id));
return OB_SUCCESS;
}
virtual void switch_role(const common::ObRole &role, const int64_t proposal_id)
{
curr_role_ = role;
curr_proposal_id_ = proposal_id;
PALF_LOG(INFO, "MockObLogHandler switch_role", K(role), K(proposal_id));
}
virtual int change_leader_to(const common::ObAddr &dst_addr)
{
UNUSED(dst_addr);
return OB_SUCCESS;
}
virtual int revoke_leader()
{
curr_role_ = FOLLOWER;
new_role_ = FOLLOWER;
new_proposal_id_++;
return OB_SUCCESS;
}
virtual int get_end_lsn(palf::LSN &end_lsn) const
{
end_lsn = LSN(1, 0);
return OB_SUCCESS;
}
int seek(const palf::LSN &start_lsn, palf::PalfBufferIterator &iter)
{UNUSED(start_lsn); UNUSED(iter); return OB_SUCCESS;};
int seek(const palf::LSN &start_lsn, const int64_t iterate_size, palf::PalfGroupBufferIterator &iter)
{UNUSED(start_lsn); UNUSED(iterate_size); UNUSED(iter); return OB_SUCCESS;};
int seek(const int64_t start_ts_ns, palf::PalfGroupBufferIterator &iter)
{UNUSED(start_ts_ns); UNUSED(iter); return OB_SUCCESS;};
int set_initial_member_list(const common::ObMemberList &member_list, const int64_t paxos_replica_num)
{UNUSED(member_list); UNUSED(paxos_replica_num); return OB_SUCCESS;}
int locate_by_ts_ns_coarsely(const int64_t ts_ns, palf::LSN &lsn)
{UNUSED(ts_ns); UNUSED(lsn); return OB_SUCCESS;}
int locate_by_lsn_coarsely(const palf::LSN &lsn, int64_t &ts_ns)
{UNUSED(ts_ns); UNUSED(lsn); return OB_SUCCESS;}
int advance_base_lsn(const palf::LSN &lsn)
{UNUSED(lsn); return OB_SUCCESS;}
int get_base_lsn(palf::LSN &lsn)
{UNUSED(lsn); return OB_SUCCESS;}
int get_base_ts_ns(int64_t &base_lsn_ts_ns) const
{UNUSED(base_lsn_ts_ns); return OB_SUCCESS;}
int get_end_ts_ns(int64_t &ts) const
{UNUSED(ts); return OB_SUCCESS;}
int get_paxos_member_list(common::ObMemberList &member_list, int64_t &paxos_replica_num) const
{UNUSED(member_list); UNUSED(paxos_replica_num); return OB_SUCCESS;}
int get_palf_base_info(const palf::LSN &base_lsn, palf::PalfBaseInfo &palf_base_info)
{
UNUSED(base_lsn);
UNUSED(palf_base_info);
return OB_SUCCESS;
}
int is_in_sync(bool &is_log_sync, bool &is_need_rebuild) const
{
UNUSED(is_log_sync);
UNUSED(is_need_rebuild);
return OB_SUCCESS;
}
bool is_sync_enabled() const
{
return true;
}
bool is_replay_enabled() const
{
return true;
}
int enable_sync()
{
return OB_SUCCESS;
}
int disable_sync()
{
return OB_SUCCESS;
}
int advance_base_lsn_for_rebuild(const palf::PalfBaseInfo &palf_base_info)
{
UNUSED(palf_base_info);
return OB_SUCCESS;
}
TO_STRING_KV(K_(curr_role), K_(curr_proposal_id), K_(new_role), K_(new_proposal_id));
ObRole curr_role_;
int64_t curr_proposal_id_;
ObRole new_role_;
int64_t new_proposal_id_;
LSN end_lsn_;
};
class TestObRoleChangeService : public ::testing::Test {
public:
TestObRoleChangeService() {}
~TestObRoleChangeService() {}
protected:
virtual void SetUp()
{
auto get_log_handler = [&](const share::ObLSID &ls_id, ObILogHandler *&log_handler) -> int
{
log_handler = &log_handler_;
PALF_LOG(INFO, "get_log_handler", K(ls_id), KP(log_handler), K(log_handler_), KP(&log_handler_));
return OB_SUCCESS;
};
auto get_role_change_handler = [&](const share::ObLSID &ls_id, ObRoleChangeHandler *&role_change_handler) -> int
{
role_change_handler = &role_change_handler_;
PALF_LOG(INFO, "get_role_change_handler", K(ls_id), KP(role_change_handler));
return OB_SUCCESS;
};
role_change_service_.init(&ls_service_, &apply_service_, &replay_service_);
role_change_service_.start();
}
virtual void TearDown()
{
role_change_service_.destroy();
}
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
void palf_to_leader()
{
log_handler_.new_role_ = LEADER;
log_handler_.new_proposal_id_++;
PALF_LOG(INFO, "MockObLogHandler palf_to_leader", K(log_handler_), KP(&log_handler_));
}
void palf_to_follower()
{
log_handler_.new_role_ = FOLLOWER;
log_handler_.new_proposal_id_++;
PALF_LOG(INFO, "MockObLogHandler palf_to_follower", K(log_handler_), KP(&log_handler_));
}
MockApplyService apply_service_;
MockReplayService replay_service_;
ObLSService ls_service_;
ObRoleChangeService role_change_service_;
MockObLogHandler log_handler_;
ObRoleChangeHandler role_change_handler_;
};
TEST_F(TestObRoleChangeService, normal_case)
{
ObLSID ls_id(1);
EXPECT_EQ(OB_SUCCESS, role_change_service_.on_role_change(ls_id.id()));
usleep(10*1000);
// new_proposal_id_ == curr_proposal_id_, no need change role
EXPECT_EQ(FOLLOWER, log_handler_.curr_role_);
palf_to_leader();
EXPECT_EQ(OB_SUCCESS, role_change_service_.on_role_change(ls_id.id()));
LSN end_lsn(2, 0);
usleep(10*1000);
// before replay service replay done
EXPECT_EQ(FOLLOWER, log_handler_.curr_role_);
replay_service_.advance_end_lsn(end_lsn);
usleep(10 * 1000);
// follower to leader
EXPECT_EQ(LEADER, log_handler_.curr_role_);
palf_to_follower();
palf_to_leader();
// switch leader -> follower -> leader
EXPECT_EQ(OB_SUCCESS, role_change_service_.on_role_change(ls_id.id()));
usleep(10*1000);
EXPECT_EQ(LEADER, log_handler_.curr_role_);
palf_to_follower();
EXPECT_EQ(OB_SUCCESS, role_change_service_.on_role_change(ls_id.id()));
usleep(10*1000);
EXPECT_EQ(FOLLOWER, log_handler_.curr_role_);
EXPECT_EQ(OB_SUCCESS, role_change_service_.on_role_change(ls_id.id()));
palf_to_follower();
usleep(10*1000);
EXPECT_EQ(FOLLOWER, log_handler_.curr_role_);
}
} // end of unittest
} // end of oceanbase
int main(int argc, char **argv)
{
system("rm -rf test_ob_role_change_service.*");
OB_LOGGER.set_file_name("test_ob_role_change_service.log", true);
OB_LOGGER.set_log_level("INFO");
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}