File log_system_tran.cpp¶
File List > cubrid > src > transaction > log_system_tran.cpp
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
//
// System transactions - can make changes to storage without modifying the database view; it requires logging.
//
#include "log_system_tran.hpp"
#include "log_impl.h"
#include "thread_entry.hpp"
#include "thread_manager.hpp"
#include <forward_list>
#include <mutex>
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
std::mutex systb_Mutex;
std::forward_list<log_tdes *> systb_Free_tdes_list;
TRANID systb_Next_tranid = LOG_SYSTEM_WORKER_FIRST_TRANID;
// recovery - simulate the system workers from runtime
std::map<TRANID, log_tdes *> systb_System_tdes;
static log_tdes *
systdes_create_tdes ()
{
log_tdes *tdes = new log_tdes ();
logtb_initialize_tdes (tdes, LOG_SYSTEM_TRAN_INDEX);
return tdes;
}
static void
systdes_remove_tdes_from_map (TRANID trid)
{
auto it = systb_System_tdes.find (trid);
if (it != systb_System_tdes.end ())
{
(void) systb_System_tdes.erase (it);
}
else
{
assert (false);
}
}
static void
systdes_retire_tdes (log_tdes *tdes)
{
std::unique_lock<std::mutex> ulock (systb_Mutex);
if (tdes != NULL)
{
logtb_clear_tdes (NULL, tdes);
systb_Free_tdes_list.push_front (tdes);
systdes_remove_tdes_from_map (tdes->trid);
tdes = NULL;
}
}
log_tdes *
systdes_claim_tdes ()
{
assert (LOG_ISRESTARTED ()); // Recovery should not reuse tdeses
std::unique_lock<std::mutex> ulock (systb_Mutex);
log_tdes *tdes = NULL;
if (systb_Free_tdes_list.empty ())
{
// generate new log_tdes
tdes = systdes_create_tdes ();
tdes->trid = systb_Next_tranid;
systb_Next_tranid += LOG_SYSTEM_WORKER_INCR_TRANID;
}
else
{
tdes = systb_Free_tdes_list.front ();
systb_Free_tdes_list.pop_front ();
}
assert (tdes->trid < NULL_TRANID && tdes->trid > systb_Next_tranid);
tdes->state = TRAN_ACTIVE;
systb_System_tdes[tdes->trid] = tdes;
return tdes;
}
log_system_tdes::log_system_tdes ()
: m_tdes (NULL)
{
if (LOG_ISRESTARTED ())
{
m_tdes = systdes_claim_tdes ();
}
else
{
m_tdes = systdes_create_tdes ();
}
}
log_system_tdes::~log_system_tdes ()
{
if (LOG_ISRESTARTED ())
{
systdes_retire_tdes (m_tdes);
}
else
{
logtb_finalize_tdes (NULL, m_tdes);
delete m_tdes;
m_tdes = NULL;
}
}
log_system_tdes::log_system_tdes (log_tdes *tdes)
: m_tdes (tdes)
{
}
log_tdes *
log_system_tdes::get_tdes ()
{
return m_tdes;
}
void
log_system_tdes::on_sysop_start ()
{
assert (m_tdes != NULL);
if (m_tdes->topops.last < 0)
{
assert (m_tdes->topops.last == -1);
LSA_SET_NULL (&m_tdes->head_lsa);
LSA_SET_NULL (&m_tdes->tail_lsa);
LSA_SET_NULL (&m_tdes->undo_nxlsa);
LSA_SET_NULL (&m_tdes->tail_topresult_lsa);
LSA_SET_NULL (&m_tdes->rcv.tran_start_postpone_lsa);
LSA_SET_NULL (&m_tdes->rcv.sysop_start_postpone_lsa);
}
}
void
log_system_tdes::on_sysop_end ()
{
assert (m_tdes != NULL);
if (m_tdes->topops.last < 0)
{
assert (m_tdes->topops.last == -1);
LSA_SET_NULL (&m_tdes->head_lsa);
LSA_SET_NULL (&m_tdes->tail_lsa);
LSA_SET_NULL (&m_tdes->undo_nxlsa);
LSA_SET_NULL (&m_tdes->tail_topresult_lsa);
}
}
void
log_system_tdes::rv_simulate_system_tdes (TRANID trid)
{
auto it = systb_System_tdes.find (trid);
if (it == systb_System_tdes.end ())
{
assert (false);
}
else
{
cubthread::entry &thread_r = cubthread::get_entry ();
thread_r.set_system_tdes (new log_system_tdes (it->second));
}
}
void
log_system_tdes::rv_end_simulation ()
{
cubthread::entry &thread_r = cubthread::get_entry ();
thread_r.reset_system_tdes ();
}
void
log_system_tdes::init_system_transations ()
{
// nothing to do so far
}
void
log_system_tdes::destroy_system_transactions ()
{
log_tdes *tdes;
std::lock_guard<std::mutex> lg (systb_Mutex);
while (!systb_Free_tdes_list.empty ())
{
tdes = systb_Free_tdes_list.front ();
systb_Free_tdes_list.pop_front ();
logtb_finalize_tdes (NULL, tdes);
delete tdes;
}
assert (systb_System_tdes.empty ());
}
log_tdes *
log_system_tdes::rv_get_tdes (TRANID trid)
{
auto it = systb_System_tdes.find (trid);
if (it != systb_System_tdes.end ())
{
return it->second;
}
else
{
return NULL;
}
}
log_tdes *
log_system_tdes::rv_get_or_alloc_tdes (TRANID trid, const LOG_LSA &log_lsa)
{
log_tdes *tdes = rv_get_tdes (trid);
if (tdes == NULL)
{
log_tdes *tdes = systdes_create_tdes ();
tdes->state = TRAN_UNACTIVE_UNILATERALLY_ABORTED;
tdes->trid = trid;
tdes->head_lsa = log_lsa;
systb_System_tdes[trid] = tdes;
return tdes;
}
else
{
assert (tdes->trid == trid);
return tdes;
}
}
void
log_system_tdes::map_all_tdes (const map_func &func)
{
std::lock_guard<std::mutex> lg (systb_Mutex);
for (auto &el : systb_System_tdes)
{
log_tdes *tdes = el.second;
assert (tdes != NULL);
func (*tdes);
}
}
void
log_system_tdes::rv_delete_all_tdes_if (const rv_delete_if_func &func)
{
for (auto it = systb_System_tdes.begin (); it != systb_System_tdes.end ();)
{
if (func (* (it->second)))
{
it = systb_System_tdes.erase (it);
}
else
{
++it;
}
}
}
void
log_system_tdes::rv_delete_tdes (TRANID trid)
{
auto it = systb_System_tdes.find (trid);
if (it != systb_System_tdes.end ())
{
(void) systb_System_tdes.erase (it);
}
else
{
assert (false);
}
}
void
log_system_tdes::rv_final ()
{
assert (systb_System_tdes.empty ());
log_system_tdes::destroy_system_transactions ();
}