[MDS] add check_transfer_in_redo_written() interface on tablet
This commit is contained in:
@ -24,12 +24,12 @@ bool FlushOp::operator()(const ObTabletID &, MdsTableBase *&mds_table)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (mds_table->is_switched_to_empty_shell()) {
|
||||
MDS_LOG_RET(INFO, ret, "skip empty shell tablet mds_table flush",
|
||||
KPC(mds_table), K(scan_mds_table_cnt_), K_(max_consequent_callbacked_scn));
|
||||
MDS_LOG(INFO, "skip empty shell tablet mds_table flush",
|
||||
KPC(mds_table), K(scan_mds_table_cnt_), K_(max_consequent_callbacked_scn));
|
||||
} else if (checkpoint::INVALID_TRACE_ID != trace_id_ && FALSE_IT(mds_table->set_trace_id(trace_id_))) {
|
||||
} else if (OB_FAIL(mds_table->flush(do_flush_limit_scn_, max_consequent_callbacked_scn_))) {
|
||||
MDS_LOG_RET(WARN, ret, "flush mds table failed",
|
||||
KR(ret), KPC(mds_table), K_(scan_mds_table_cnt), K_(max_consequent_callbacked_scn));
|
||||
MDS_LOG(WARN, "flush mds table failed",
|
||||
KR(ret), KPC(mds_table), K_(scan_mds_table_cnt), K_(max_consequent_callbacked_scn));
|
||||
if (OB_SIZE_OVERFLOW == ret) {
|
||||
is_dag_full_ = true;
|
||||
}
|
||||
|
||||
@ -143,6 +143,8 @@ public:
|
||||
ObFunction<int(void *)> &op,
|
||||
bool &is_committed,
|
||||
const int64_t read_seq) const = 0;
|
||||
virtual int get_tablet_status_node(ObFunction<int(void *)> &op,
|
||||
const int64_t read_seq) const = 0;
|
||||
virtual int get_snapshot(int64_t unit_id,
|
||||
void *key,
|
||||
ObFunction<int(void *)> &op,
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
#include "lib/ob_errno.h"
|
||||
#include "mds_table_impl.h"
|
||||
#include "lib/guard/ob_light_shared_gaurd.h"
|
||||
#include "storage/multi_data_source/compile_utility/mds_dummy_key.h"
|
||||
#include "storage/tablet/ob_tablet_create_delete_mds_user_data.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -54,6 +56,8 @@ public:
|
||||
int replay(T &&data, MdsCtx &ctx, const share::SCN &scn);
|
||||
template <typename T, typename OP, ENABLE_IF_LIKE_FUNCTION(OP, int(const T&))>
|
||||
int get_latest(OP &&read_op, bool &is_committed, const int64_t read_seq = 0) const;
|
||||
template <typename OP, ENABLE_IF_LIKE_FUNCTION(OP, int(const UserMdsNode<DummyKey, ObTabletCreateDeleteMdsUserData>&))>
|
||||
int get_tablet_status_node(OP &&read_op, const int64_t read_seq = 0) const;
|
||||
template <typename T, typename OP, ENABLE_IF_LIKE_FUNCTION(OP, int(const T&))>
|
||||
int get_snapshot(OP &&read_op,
|
||||
const share::SCN snapshot = share::SCN::max_scn(),
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#define STORAGE_MULTI_DATE_SOURCE_MDS_TABLE_HANDLE_IPP
|
||||
|
||||
#include "lib/ob_errno.h"
|
||||
#include "storage/multi_data_source/mds_node.h"
|
||||
#ifndef STORAGE_MULTI_DATE_SOURCE_MDS_TABLE_HANDLE_H_IPP
|
||||
#define STORAGE_MULTI_DATE_SOURCE_MDS_TABLE_HANDLE_H_IPP
|
||||
#include "mds_table_handle.h"
|
||||
@ -240,6 +241,30 @@ int MdsTableHandle::get_latest(OP &&read_op, bool &is_committed, const int64_t r
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename OP>
|
||||
struct GetTabletStatusNodeOpWrapper {
|
||||
GetTabletStatusNodeOpWrapper(OP &op) : op_(op) {}
|
||||
int operator()(void *tablet_status_node) {
|
||||
return op_(*reinterpret_cast<const UserMdsNode<DummyKey, ObTabletCreateDeleteMdsUserData> *>(tablet_status_node));
|
||||
}
|
||||
OP &op_;
|
||||
};
|
||||
template <typename OP,
|
||||
typename std::enable_if<OB_TRAIT_IS_FUNCTION_LIKE(OP,
|
||||
int(const UserMdsNode<DummyKey, ObTabletCreateDeleteMdsUserData>&)), bool>::type>
|
||||
int MdsTableHandle::get_tablet_status_node(OP &&read_op, const int64_t read_seq) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CHECK_MDS_TABLE_INIT();
|
||||
ObFunction<int(void *)> function = GetTabletStatusNodeOpWrapper<OP>(read_op);
|
||||
if (OB_FAIL(p_mds_table_base_->get_tablet_status_node(function, read_seq))) {
|
||||
if (OB_UNLIKELY(OB_SNAPSHOT_DISCARDED != ret)) {
|
||||
MDS_LOG(WARN, "fail to call get_latest", KR(ret), K(read_seq));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, typename OP,
|
||||
typename std::enable_if<OB_TRAIT_IS_FUNCTION_LIKE(OP, int(const T&)), bool>::type>
|
||||
int MdsTableHandle::get_snapshot(OP &&read_op,
|
||||
|
||||
@ -118,6 +118,8 @@ public:
|
||||
ObFunction<int(void *)> &op,
|
||||
bool &is_committed,
|
||||
const int64_t read_seq) const override;
|
||||
virtual int get_tablet_status_node(ObFunction<int(void *)> &op,
|
||||
const int64_t read_seq) const override;
|
||||
virtual int get_snapshot(int64_t unit_id,
|
||||
void *key,
|
||||
ObFunction<int(void *)> &op,
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "ob_clock_generator.h"
|
||||
#include "share/ob_errno.h"
|
||||
#include "storage/multi_data_source/mds_table_base.h"
|
||||
#include "storage/multi_data_source/mds_table_impl.h"
|
||||
#ifndef STORAGE_MULTI_DATA_SOURCE_MDS_TABLE_IMPL_H_IPP
|
||||
#define STORAGE_MULTI_DATA_SOURCE_MDS_TABLE_IMPL_H_IPP
|
||||
#include "mds_table_impl.h"
|
||||
@ -551,6 +552,26 @@ int MdsTableImpl<MdsTableType>::get_latest(int64_t unit_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// only normal mds table support this method, and only for transfer
|
||||
template <typename MdsTableType>
|
||||
int MdsTableImpl<MdsTableType>::get_tablet_status_node(ObFunction<int(void *)> &op, const int64_t read_seq) const
|
||||
{
|
||||
return OB_NOT_SUPPORTED;
|
||||
}
|
||||
struct GetTabletSetusNodeOpWrapper {
|
||||
GetTabletSetusNodeOpWrapper(ObFunction<int(void *)> &op) : op_(op) {}
|
||||
int operator()(const UserMdsNode<DummyKey, ObTabletCreateDeleteMdsUserData> &node) {
|
||||
return op_((void *)&node);
|
||||
}
|
||||
ObFunction<int(void *)> &op_;
|
||||
};
|
||||
template <>
|
||||
inline int MdsTableImpl<NormalMdsTable>::get_tablet_status_node(ObFunction<int(void *)> &op, const int64_t read_seq) const
|
||||
{
|
||||
return const_cast<NormalMdsTable &>(unit_tuple_).element<MdsUnit<DummyKey, ObTabletCreateDeleteMdsUserData>>().
|
||||
get_latest(GetTabletSetusNodeOpWrapper(op), read_seq);
|
||||
}
|
||||
|
||||
template <typename MdsTableImpl>
|
||||
struct GetSnapshotHelper {
|
||||
GetSnapshotHelper(const MdsTableImpl &mds_table_impl,
|
||||
|
||||
@ -64,6 +64,14 @@ public:
|
||||
"tablet_id", get_table_id_(), KP(get_tablet_pointer_()));
|
||||
int get_mds_table_rec_log_scn(share::SCN &rec_scn);
|
||||
int mds_table_flush(const share::SCN &recycle_scn);
|
||||
// get tablet status from MDS, and check whether state is TRANSFER_IN and redo scn is valid.
|
||||
// @param [in] written : if current tablet status is TRANSFER_IN, set true if redo_scn is valid, otherwise set fasle
|
||||
// @return OB_STATE_NOT_MATCH : tablet status is not TRANSFER_IN.
|
||||
// OB_EMPTY_RESULT : never has tablet status written.
|
||||
// OB_LS_OFFLINE : read meet ls offline
|
||||
// other error...
|
||||
// CAUTIONS: this interface is only for transfer! anyone else shouldn't call this!
|
||||
int check_transfer_in_redo_written(bool &written);
|
||||
protected:// implemented by ObTablet
|
||||
virtual bool check_is_inited_() const = 0;
|
||||
virtual const ObTabletMdsData &get_mds_data_() const = 0;
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
#ifndef INCLUDE_OB_TABLET_MDS_PART_IPP
|
||||
#define INCLUDE_OB_TABLET_MDS_PART_IPP
|
||||
#include "lib/ob_errno.h"
|
||||
#include "ob_i_tablet_mds_interface.h"
|
||||
#include "share/ob_errno.h"
|
||||
#include "storage/multi_data_source/compile_utility/mds_dummy_key.h"
|
||||
#include "storage/multi_data_source/mds_node.h"
|
||||
#include "storage/tablet/ob_tablet_status.h"
|
||||
#endif
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -227,6 +231,7 @@ inline int ObITabletMdsInterface::get_mds_data_from_tablet<ObTabletBindingMdsUse
|
||||
MDS_LOG_GET(WARN, "failed to load aux tablet info");
|
||||
} else if (!aux_tablet_info.is_valid()) {
|
||||
ret = OB_EMPTY_RESULT;
|
||||
MDS_LOG_GET(DEBUG, "get empty aux_tablet_info");
|
||||
} else if (CLICK_FAIL(read_op(aux_tablet_info))) {
|
||||
MDS_LOG_GET(WARN, "failed to read_op");
|
||||
}
|
||||
@ -779,5 +784,96 @@ inline int ObITabletMdsInterface::fill_virtual_info(ObIArray<mds::MdsNodeInfoFor
|
||||
#undef PRINT_WRAPPER
|
||||
}
|
||||
|
||||
/********************************************this is special logic*****************************************************/
|
||||
struct GetTabletStatuaNodeFromMdsTableOp {
|
||||
GetTabletStatuaNodeFromMdsTableOp(ObTabletCreateDeleteMdsUserData &tablet_status, share::SCN &redo_scn)
|
||||
: tablet_status_(tablet_status),
|
||||
redo_scn_(redo_scn) {}
|
||||
int operator()(const mds::UserMdsNode<mds::DummyKey, ObTabletCreateDeleteMdsUserData> &node) {
|
||||
tablet_status_.assign(node.user_data_);
|
||||
redo_scn_ = node.redo_scn_;
|
||||
MDS_LOG(TRACE, "read tablet status in mds_table", K(node));
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
ObTabletCreateDeleteMdsUserData &tablet_status_;
|
||||
share::SCN &redo_scn_;
|
||||
};
|
||||
struct GetTabletStatuaFromTabletOp {
|
||||
GetTabletStatuaFromTabletOp(ObTabletCreateDeleteMdsUserData &tablet_status)
|
||||
: tablet_status_(tablet_status) {}
|
||||
int operator()(const ObTabletCreateDeleteMdsUserData& data) {
|
||||
tablet_status_.assign(data);
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
ObTabletCreateDeleteMdsUserData &tablet_status_;
|
||||
};
|
||||
inline int ObITabletMdsInterface::check_transfer_in_redo_written(bool &written)
|
||||
{
|
||||
#define PRINT_WRAPPER KR(ret), K(*this), K(written)
|
||||
MDS_TG(10_ms);
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_online = false;
|
||||
ObTabletCreateDeleteMdsUserData tablet_status;
|
||||
share::SCN redo_scn;
|
||||
do {
|
||||
mds::MdsTableHandle handle;
|
||||
ObLSSwitchChecker ls_switch_checker;
|
||||
if (CLICK_FAIL(get_mds_table_handle_(handle, false))) {
|
||||
if (OB_ENTRY_NOT_EXIST != ret) {
|
||||
MDS_LOG_GET(WARN, "failed to get_mds_table");
|
||||
} else {
|
||||
MDS_LOG_GET(TRACE, "failed to get_mds_table");
|
||||
}
|
||||
} else if (!handle.is_valid()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
MDS_LOG_GET(WARN, "mds cannot be NULL");
|
||||
} else if (OB_ISNULL(get_tablet_pointer_())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
MDS_LOG_GET(WARN, "tablet pointer is null", K(ret), KPC(this));
|
||||
} else if (MDS_FAIL(ls_switch_checker.check_ls_switch_state(get_tablet_pointer_()->get_ls(), is_online))) {
|
||||
MDS_LOG_GET(WARN, "check ls online state failed", K(ret), KPC(this));
|
||||
} else if (CLICK_FAIL(handle.get_tablet_status_node(GetTabletStatuaNodeFromMdsTableOp(tablet_status, redo_scn)))) {
|
||||
if (OB_SNAPSHOT_DISCARDED != ret) {
|
||||
MDS_LOG_GET(WARN, "failed to get mds data");
|
||||
} else {
|
||||
MDS_LOG_GET(TRACE, "failed to get mds data");
|
||||
}
|
||||
} else {
|
||||
if (tablet_status.get_tablet_status() != ObTabletStatus::TRANSFER_IN) {
|
||||
ret = OB_STATE_NOT_MATCH;
|
||||
} else if (!redo_scn.is_valid() || redo_scn.is_max()) {
|
||||
written = false;
|
||||
MDS_LOG_GET(TRACE, "get transfer in status on mds_table, but redo scn is not valid");
|
||||
} else {
|
||||
written = true;
|
||||
MDS_LOG_GET(TRACE, "get transfer in status on mds_table, and redo scn is valid");
|
||||
}
|
||||
}
|
||||
if (CLICK_FAIL(ret)) {
|
||||
if (OB_ENTRY_NOT_EXIST == ret || OB_SNAPSHOT_DISCARDED == ret) {
|
||||
if (CLICK_FAIL(get_mds_data_from_tablet<ObTabletCreateDeleteMdsUserData>(GetTabletStatuaFromTabletOp(tablet_status)))) {
|
||||
MDS_LOG_GET(WARN, "failed to get latest data from tablet");
|
||||
} else if (tablet_status.get_tablet_status() != ObTabletStatus::TRANSFER_IN) {
|
||||
ret = OB_STATE_NOT_MATCH;
|
||||
} else {
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (is_online && MDS_FAIL(ls_switch_checker.double_check_epoch(is_online))) {
|
||||
if (!is_online) {
|
||||
ret = OB_LS_OFFLINE;
|
||||
}
|
||||
MDS_LOG_GET(WARN, "failed to double check ls online");
|
||||
} else {
|
||||
MDS_LOG_GET(TRACE, "success to check_transfer_in_redo_written");
|
||||
}
|
||||
}
|
||||
} while (ret == OB_VERSION_NOT_MATCH && is_online);
|
||||
return ret;
|
||||
#undef PRINT_WRAPPER
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user