234 lines
5.6 KiB
C++
234 lines
5.6 KiB
C++
/* Copyright (c) 2018, 2021, Alibaba and/or its affiliates. All rights reserved.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL/PolarDB-X Engine hereby grant you an
|
|
additional permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with
|
|
MySQL/PolarDB-X Engine.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
|
|
/** @file trx/lizard0scn.cc
|
|
Lizard scn number implementation.
|
|
|
|
Created 2020-03-24 by Jianwei.zhao
|
|
*******************************************************/
|
|
|
|
#include "mtr0log.h"
|
|
#include "mtr0mtr.h"
|
|
#include "sync0types.h"
|
|
|
|
#include "lizard0scn.h"
|
|
#include "lizard0sys.h"
|
|
|
|
#ifdef UNIV_PFS_MUTEX
|
|
/* Lizard scn mutex PFS key */
|
|
mysql_pfs_key_t lizard_scn_mutex_key;
|
|
#endif
|
|
|
|
namespace lizard {
|
|
|
|
bool srv_snapshot_update_gcn = false;
|
|
|
|
/** Constructor of SCN */
|
|
SCN::SCN()
|
|
: m_scn(SCN_NULL),
|
|
m_gcn(GCN_NULL),
|
|
m_snapshot_gcn(GCN_NULL),
|
|
m_inited(false) {
|
|
mutex_create(LATCH_ID_LIZARD_SCN, &m_mutex);
|
|
}
|
|
|
|
/** Destructor of SCN */
|
|
SCN::~SCN() { mutex_free(&m_mutex); }
|
|
|
|
/** Assign the init value by reading from zesu tablespace */
|
|
void SCN::init() {
|
|
ut_ad(!m_inited);
|
|
ut_ad(m_scn == SCN_NULL);
|
|
|
|
lizard_sysf_t *lzd_hdr;
|
|
mtr_t mtr;
|
|
mtr.start();
|
|
|
|
lzd_hdr = lizard_sysf_get(&mtr);
|
|
|
|
m_scn = 2 * LIZARD_SCN_NUMBER_MAGIN +
|
|
ut_uint64_align_up(mach_read_from_8(lzd_hdr + LIZARD_SYS_SCN),
|
|
LIZARD_SCN_NUMBER_MAGIN);
|
|
|
|
m_gcn = mach_read_from_8(lzd_hdr + LIZARD_SYS_GCN);
|
|
m_snapshot_gcn = m_gcn.load();
|
|
|
|
lizard_sys->min_safe_scn = m_scn.load();
|
|
|
|
ut_a(m_scn > 0 && m_scn < SCN_NULL);
|
|
mtr.commit();
|
|
|
|
m_inited = true;
|
|
return;
|
|
}
|
|
|
|
/** Flush the scn number to tablepace every ZEUS_SCN_NUMBER_MAGIN */
|
|
void SCN::flush_scn() {
|
|
lizard_sysf_t *lzd_hdr;
|
|
mtr_t mtr;
|
|
|
|
ut_ad(m_mutex.is_owned());
|
|
ut_ad(m_inited);
|
|
ut_ad(m_scn != SCN_NULL);
|
|
|
|
mtr_start(&mtr);
|
|
lzd_hdr = lizard_sysf_get(&mtr);
|
|
mlog_write_ull(lzd_hdr + LIZARD_SYS_SCN, m_scn, &mtr);
|
|
mtr_commit(&mtr);
|
|
}
|
|
|
|
/** Flush the global commit number to system tablepace */
|
|
void SCN::flush_gcn() {
|
|
lizard_sysf_t *lzd_hdr;
|
|
mtr_t mtr;
|
|
|
|
ut_ad(m_mutex.is_owned());
|
|
ut_ad(m_inited);
|
|
ut_ad(m_gcn != SCN_NULL);
|
|
|
|
mtr_start(&mtr);
|
|
lzd_hdr = lizard_sysf_get(&mtr);
|
|
mlog_write_ull(lzd_hdr + LIZARD_SYS_GCN, m_gcn, &mtr);
|
|
mtr_commit(&mtr);
|
|
}
|
|
|
|
/** Calucalte a new scn number
|
|
@return scn */
|
|
scn_t SCN::new_scn() {
|
|
scn_t num;
|
|
ut_ad(m_inited);
|
|
|
|
ut_ad(mutex_own(&m_mutex));
|
|
|
|
/** flush scn every magin */
|
|
if (!(m_scn % LIZARD_SCN_NUMBER_MAGIN)) flush_scn();
|
|
|
|
num = ++m_scn;
|
|
|
|
ut_a(num > 0 && num < SCN_NULL);
|
|
|
|
return num;
|
|
}
|
|
|
|
/** Calculate a new scn number and consistent UTC time
|
|
@return <SCN, UTC, GCN, Error> */
|
|
std::pair<commit_scn_t, bool> SCN::new_commit_scn(gcn_t gcn) {
|
|
commit_scn_t cmmt = COMMIT_SCN_NULL;
|
|
|
|
if (gcn != GCN_NULL)
|
|
cmmt.gcn = gcn;
|
|
else
|
|
cmmt.gcn = acquire_gcn(true);
|
|
|
|
if (cmmt.gcn > m_gcn) {
|
|
m_gcn = cmmt.gcn;
|
|
flush_gcn();
|
|
}
|
|
|
|
cmmt.scn = new_scn();
|
|
|
|
ut_ad(cmmt.scn > SCN_RESERVERD_MAX);
|
|
|
|
return std::make_pair(cmmt, false);
|
|
}
|
|
|
|
/** Get current scn which is committed.
|
|
@param[in] true if m_mutex is hold
|
|
@return m_scn */
|
|
scn_t SCN::acquire_scn(bool mutex_hold) {
|
|
scn_t ret;
|
|
if (!mutex_hold) {
|
|
mutex_enter(&m_mutex);
|
|
}
|
|
|
|
ret = m_scn.load();
|
|
|
|
if (!mutex_hold) {
|
|
mutex_exit(&m_mutex);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/** Get current scn which is committed.
|
|
@param[in] true if m_mutex is hold
|
|
@return m_scn */
|
|
gcn_t SCN::acquire_gcn(bool mutex_hold) {
|
|
gcn_t ret;
|
|
if (!mutex_hold) {
|
|
mutex_enter(&m_mutex);
|
|
}
|
|
|
|
if (srv_snapshot_update_gcn)
|
|
ret = m_gcn > m_snapshot_gcn ? m_gcn.load() : m_snapshot_gcn.load();
|
|
else
|
|
ret = m_gcn.load();
|
|
|
|
if (!mutex_hold) {
|
|
mutex_exit(&m_mutex);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
scn_t SCN::get_scn() { return m_scn.load(); }
|
|
|
|
gcn_t SCN::get_gcn() { return m_gcn.load(); }
|
|
|
|
void SCN::set_snapshot_gcn(gcn_t gcn, bool mutex_hold) {
|
|
|
|
if(gcn == GCN_NULL || gcn == GCN_INITIAL)
|
|
return;
|
|
|
|
if (!mutex_hold) {
|
|
mutex_enter(&m_mutex);
|
|
}
|
|
|
|
if( gcn > m_snapshot_gcn )
|
|
m_snapshot_gcn = gcn;
|
|
|
|
if (!mutex_hold) {
|
|
mutex_exit(&m_mutex);
|
|
}
|
|
}
|
|
|
|
gcn_t SCN::get_snapshot_gcn() { return m_snapshot_gcn.load(); }
|
|
|
|
/**
|
|
Check the commit scn state
|
|
|
|
@param[in] scn commit scn
|
|
@return scn state SCN_STATE_INITIAL, SCN_STATE_ALLOCATED or
|
|
SCN_STATE_INVALID
|
|
*/
|
|
enum scn_state_t commit_scn_state(const commit_scn_t &cmmt) {
|
|
/** The init value */
|
|
if (cmmt.scn == SCN_NULL && cmmt.utc == UTC_NULL)
|
|
return SCN_STATE_INITIAL;
|
|
|
|
/** The assigned commit scn value */
|
|
if (cmmt.scn > 0 && cmmt.scn < SCN_MAX && cmmt.utc > 0 &&
|
|
cmmt.utc < UTC_MAX && cmmt.gcn > 0 && cmmt.gcn < GCN_MAX) {
|
|
/** TODO: Replace by real GCN in future */
|
|
return SCN_STATE_ALLOCATED;
|
|
}
|
|
return SCN_STATE_INVALID;
|
|
}
|
|
|
|
} // namespace lizard
|