未验证 提交 aea25b25 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

合并之前的持久化代码到mvcc (#194)

### What problem were solved in this pull request?

close issue: #186 

Problem:
实现MVCC代码后没有将持久化代码合并进来

### What is changed and how it works?
支持并发模式下落日志,并在异常停机后回复。

持久化是事务模块中最复杂的功能(没有之一),当前miniob实现的持久化简化了非常多,因此不能依赖持久化能力,仅仅作为一个学习测试的工具,在实际测试时也有一些限制。

### Other information
上级 1a2cf476
......@@ -3,6 +3,9 @@
./deps/googletest
./deps/jsoncpp
./deps/benchmark
.vscode
!.vscode/tasks.json
!.vscode/launch.json
./docs/doxy/
build/*
build_*
......
{
"files.associations": {
"typeinfo": "cpp"
}
}
\ No newline at end of file
......@@ -12,11 +12,10 @@ MESSAGE(STATUS "This is BINARY dir " ${test_BINARY_DIR})
MESSAGE(STATUS "This is Project source dir " ${PROJECT_SOURCE_DIR})
MESSAGE(STATUS "This is PROJECT_BINARY_DIR dir " ${PROJECT_BINARY_DIR})
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
#SET(LIBRARY_OUTPUT_PATH <路径>)
OPTION(ENABLE_ASAN "Enable build with address sanitizer" ON)
OPTION(ENABLE_ASAN "Enable build with address sanitizer" OFF)
OPTION(WITH_UNIT_TESTS "Compile miniob with unit tests" ON)
OPTION(CONCURRENCY "Support concurrency operations" OFF)
......@@ -81,9 +80,11 @@ MESSAGE("Install target dir is " ${CMAKE_INSTALL_PREFIX})
# ADD_SUBDIRECTORY(src bin) bin 为目标目录, 可以省略
ADD_SUBDIRECTORY(deps)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(src/obclient)
ADD_SUBDIRECTORY(src/observer)
ADD_SUBDIRECTORY(test/perf)
ADD_SUBDIRECTORY(benchmark)
ADD_SUBDIRECTORY(tools)
IF(WITH_UNIT_TESTS)
enable_testing()
......
......@@ -66,6 +66,15 @@ int getFileSize(const char *filePath, u64_t &fileLen);
* @return int 0 表示成功,否则返回errno
*/
int writen(int fd, const void *buf, int size);
/**
* @brief 一次性读取指定长度的数据
*
* @param fd 读取的描述符
* @param buf 读取到这里
* @param size 读取的数据长度
* @return int 返回0表示成功。-1 表示读取到文件尾,并且没有读到size大小数据,其它表示errno
*/
int readn(int fd, void *buf, int size);
} // namespace common
......@@ -262,12 +262,14 @@ void DebugMutex::lock()
{
#ifdef DEBUG
lock_.lock();
LOG_DEBUG("debug lock %p, lbt=%s", &lock_, lbt());
#endif
}
void DebugMutex::unlock()
{
#ifdef DEBUG
LOG_DEBUG("debug unlock %p, lbt=%s", &lock_, lbt());
lock_.unlock();
#endif
}
......@@ -277,13 +279,18 @@ void Mutex::lock()
{
#ifdef CONCURRENCY
lock_.lock();
LOG_DEBUG("lock %p, lbt=%s", &lock_, lbt());
#endif
}
bool Mutex::try_lock()
{
#ifdef CONCURRENCY
return lock_.try_lock();
bool result = lock_.try_lock();
if (result) {
LOG_DEBUG("try lock success %p, lbt=%s", &lock_, lbt());
}
return result;
#else
return true;
#endif
......@@ -292,6 +299,7 @@ bool Mutex::try_lock()
void Mutex::unlock()
{
#ifdef CONCURRENCY
LOG_DEBUG("unlock %p, lbt=%s", &lock_, lbt());
lock_.unlock();
#endif
}
......@@ -302,26 +310,38 @@ void Mutex::unlock()
void SharedMutex::lock()
{
lock_.lock();
LOG_DEBUG("shared lock %p, lbt=%s", &lock_, lbt());
}
bool SharedMutex::try_lock()
{
return lock_.try_lock();
bool result = lock_.try_lock();
if (result) {
LOG_DEBUG("try shared lock : %p, lbt=%s", &lock_, lbt());
}
return result;
}
void SharedMutex::unlock() // unlock exclusive
{
LOG_DEBUG("shared lock unlock %p, lbt=%s", &lock_, lbt());
lock_.unlock();
}
void SharedMutex::lock_shared()
{
lock_.lock_shared();
LOG_DEBUG("shared lock shared: %p lbt=%s", &lock_, lbt());
}
bool SharedMutex::try_lock_shared()
{
return lock_.try_lock_shared();
bool result = lock_.try_lock_shared();
if (result) {
LOG_DEBUG("shared lock try lock shared: %p, lbt=%s", &lock_, lbt());
}
return result;
}
void SharedMutex::unlock_shared()
{
LOG_DEBUG("shared lock unlock shared %p lbt=%s", &lock_, lbt());
lock_.unlock_shared();
}
......
......@@ -44,6 +44,8 @@ Log::Log(const std::string &log_file_name, const LOG_LEVEL log_level, const LOG_
rotate_type_ = LOG_ROTATE_BYDAY;
check_param_valid();
context_getter_ = []() { return 0; };
}
Log::~Log(void)
......@@ -311,6 +313,20 @@ int Log::rotate(const int year, const int month, const int day)
return result;
}
void Log::set_context_getter(std::function<intptr_t()> context_getter)
{
if (context_getter) {
context_getter_ = context_getter;
} else if (!context_getter_) {
context_getter_ = []() { return 0; };
}
}
intptr_t Log::context_id()
{
return context_getter_();
}
LoggerFactory::LoggerFactory()
{
// Auto-generated constructor stub
......
......@@ -25,6 +25,7 @@ See the Mulan PSL v2 for more details. */
#include <map>
#include <set>
#include <string>
#include <functional>
#include "common/defs.h"
......@@ -105,6 +106,9 @@ public:
int rotate(const int year = 0, const int month = 0, const int day = 0);
void set_context_getter(std::function<intptr_t()> context_getter);
intptr_t context_id();
private:
void check_param_valid();
......@@ -137,6 +141,8 @@ private:
typedef std::set<std::string> DefaultSet;
DefaultSet default_set_;
std::function<intptr_t()> context_getter_;
};
class LoggerFactory {
......@@ -157,7 +163,7 @@ extern Log *g_log;
#define __FILE_NAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
#define LOG_HEAD_SIZE 64
#define LOG_HEAD_SIZE 128
#define LOG_HEAD(prefix, level) \
if (common::g_log) { \
......@@ -168,7 +174,7 @@ extern Log *g_log;
if (p) { \
int usec = (int)tv.tv_usec; \
snprintf(sz_head, LOG_HEAD_SIZE, \
"%04d-%02d-%02d %02d:%02d:%02u.%06d pid:%u tid:%llx ", \
"%04d-%02d-%02d %02d:%02d:%02u.%06d pid:%u tid:%llx ctx:%lx", \
p->tm_year + 1900, \
p->tm_mon + 1, \
p->tm_mday, \
......@@ -177,17 +183,18 @@ extern Log *g_log;
p->tm_sec, \
usec, \
(u32_t)getpid(), \
gettid()); \
gettid(), \
common::g_log->context_id()); \
common::g_log->rotate(p->tm_year + 1900, p->tm_mon + 1, p->tm_mday); \
} \
snprintf(prefix, \
sizeof(prefix), \
"[%s %s %s:%u %s] >> ", \
"[%s %s %s@%s:%u] >> ", \
sz_head, \
(common::g_log)->prefix_msg(level), \
__FUNCTION__, \
__FILE_NAME__, \
(u32_t)__LINE__, \
__FUNCTION__ \
(u32_t)__LINE__ \
); \
}
......@@ -302,9 +309,7 @@ int Log::out(const LOG_LEVEL console_level, const LOG_LEVEL log_level, T &msg)
#else // DEBUG
#define ASSERT(expression, description, ...) \
do { \
if (!(expression)) { \
LOG_ERROR(description, ##__VA_ARGS__); \
} \
(void)(expression); \
} while (0)
#endif // DEBUG
......@@ -318,5 +323,13 @@ int Log::out(const LOG_LEVEL console_level, const LOG_LEVEL log_level, T &msg)
*/
const char *lbt();
} // namespace common
/**
* @brief 设置一个在日志中打印当前上下文信息的回调函数
* @details 比如设置一个获取当前session标识的函数,那么每次在打印日志时都会输出session信息。
* 这个回调函数返回了一个intptr_t类型的数据,可能返回字符串更好,但是现在够用了。
*/
void set_log_context_getter(std::function<intptr_t()> context_getter);
extern std::function<intptr_t()> g_context_getter;
} // namespace common
......@@ -12,8 +12,7 @@ See the Mulan PSL v2 for more details. */
// Created by Longda on 2010
//
#ifndef __COMMON_OS_PROCESS_PARAM_H__
#define __COMMON_OS_PROCESS_PARAM_H__
#pragma once
#include <string>
#include <vector>
......@@ -131,6 +130,16 @@ public:
return trx_kit_name_;
}
void set_buffer_pool_memory_size(int bytes)
{
buffer_pool_memory_size_ = bytes;
}
int buffer_pool_memory_size() const
{
return buffer_pool_memory_size_;
}
private:
std::string std_out_; // The output file
std::string std_err_; // The err output file
......@@ -142,9 +151,9 @@ private:
std::string unix_socket_path_;
std::string protocol_;
std::string trx_kit_name_;
int buffer_pool_memory_size_ = -1;
};
ProcessParam *&the_process_param();
} // namespace common
#endif //__COMMON_OS_PROCESS_PARAM_H__
......@@ -76,30 +76,22 @@ bool MetricsStage::set_properties()
// Initialize stage params and validate outputs
bool MetricsStage::initialize()
{
LOG_TRACE("Enter");
std::list<Stage *>::iterator stgp = next_stage_list_.begin();
timer_stage_ = *(stgp++);
MetricsReportEvent *report_event = new MetricsReportEvent();
add_event(report_event);
LOG_TRACE("Exit");
return true;
}
// Cleanup after disconnection
void MetricsStage::cleanup()
{
LOG_TRACE("Enter");
LOG_TRACE("Exit");
}
void MetricsStage::handle_event(StageEvent *event)
{
LOG_TRACE("Enter\n");
CompletionCallback *cb = new CompletionCallback(this, NULL);
if (cb == NULL) {
LOG_ERROR("Failed to new callback");
......@@ -123,14 +115,11 @@ void MetricsStage::handle_event(StageEvent *event)
event->push_callback(cb);
timer_stage_->add_event(tm_event);
LOG_TRACE("Exit\n");
return;
}
void MetricsStage::callback_event(StageEvent *event, CallbackContext *context)
{
LOG_TRACE("Enter\n");
MetricsRegistry &metrics_registry = get_metrics_registry();
metrics_registry.snapshot();
......@@ -139,6 +128,5 @@ void MetricsStage::callback_event(StageEvent *event, CallbackContext *context)
// do it again.
add_event(event);
LOG_TRACE("Exit\n");
return;
}
......@@ -36,14 +36,12 @@ namespace common {
*/
Stage::Stage(const char *tag) : next_stage_list_(), event_list_(), connected_(false), event_ref_(0)
{
LOG_TRACE("%s", "enter");
assert(tag != NULL);
MUTEX_INIT(&list_mutex_, NULL);
COND_INIT(&disconnect_cond_, NULL);
stage_name_ = new char[strlen(tag) + 1];
snprintf(stage_name_, strlen(tag) + 1, "%s", tag);
LOG_TRACE("%s", "exit");
}
/**
......@@ -53,7 +51,6 @@ Stage::Stage(const char *tag) : next_stage_list_(), event_list_(), connected_(fa
*/
Stage::~Stage()
{
LOG_TRACE("%s", "enter");
assert(!connected_);
MUTEX_LOCK(&list_mutex_);
while (event_list_.size() > 0) {
......@@ -66,7 +63,6 @@ Stage::~Stage()
MUTEX_DESTROY(&list_mutex_);
COND_DESTROY(&disconnect_cond_);
delete[] stage_name_;
LOG_TRACE("%s", "exit");
}
/**
......@@ -236,4 +232,4 @@ void Stage::release_event()
MUTEX_UNLOCK(&list_mutex_);
}
} // namespace common
\ No newline at end of file
} // namespace common
......@@ -255,7 +255,7 @@ void *Threadpool::run_thread(void *pool_ptr)
// this is not portable, but is easier to map to LWP
s64_t threadid = gettid();
LOG_INFO("threadid = %llx, threadname = %s\n", threadid, pool->get_name().c_str());
LOG_INFO("threadid = %llx, threadname = %s", threadid, pool->get_name().c_str());
#ifdef __APPLE__
pthread_setname_np(pool->get_name().c_str());
#else
......@@ -342,4 +342,4 @@ const Threadpool *Threadpool::get_thread_pool_ptr()
return (const Threadpool *)pthread_getspecific(pool_ptr_key_);
}
} // namespace common
\ No newline at end of file
} // namespace common
本文介绍 [MiniOB](https://github.com/oceanbase/miniob) 中的 clog 模块是如何工作的。
# 背景
持久化(Durability) 是事务中非常重要的一个模块,也是最复杂的一个模块,实现持久化才能保证数据不丢失。而持久化同时还要保证事务的原子性与数据完整性。如果对事务的一些概念不太了解,建议先学习了解事务的基本概念,比如学习[事务处理](lectures/lecture-6.md)章节,或者在网上搜索更多资料。
# MiniOB 中的持久化
## 实现简介
MiniOB 是一个学习使用的数据库,当前也在持续演进,持久化的功能是极不完善的,可以说实现了真正持久化功能的0.0001%。MiniOB 本身使用堆表保存数据,另外还有B+树当做索引,与传统数据库类似,会使用 buffer pool manager 管理堆表与索引数据在内存与磁盘中的存放。Buffer pool manager 会按照页来组织数据,在页上的修改,就会使用WAL(write append logging)记录日志,这里叫做clog。但是clog的实现是非常简化的,可以处理的异常场景也比较有限。希望大家通过这么简化的模块,了解一下数据库的日志与恢复的基本流程。
## 如何运行与测试
以mvcc模式启动miniob:
```bash
./bin/observer -f ../etc/observer.ini -s miniob.sock -t mvcc
```
客户端连接做操作,就可以看到 miniob/db/sys/clog 文件在增长。
如何测试日志恢复流程?
observer运行过程中产生了一些日志,这时执行 kill -9 `pidof observer` 将服务端进行强制杀死,然后再使用上面的启动命令将服务端启动起来即可。启动时,就会进入到恢复流程。
## CLog
CLog 的命名取自 [OceanBase](https://github.com/oceanbase/oceanbase) 中的日志模块,全称是 commit log。
当MiniOB启动时开启了mvcc模式,在运行时,如果有事务数据产生,就会生成日志,每一次操作对应一条日志(CLogRecord)。日志记录了当前操作的内容,比如插入一条数据、删除一条数据。
运行时生成的日志会先记录在内存中(CLogBuffer),当事务提交时,会将当前的事务以及之前的事务日志刷新到磁盘中。
刷新(写入)日志到磁盘时,并没有开启单独的线程,而是直接在调用刷盘(`CLogManager::sync`)的线程中直接写数据的。由于事务是并发运行的,会存在于多个线程中,因此`CLogBuffer::flush_buffer`做了简单粗暴的加锁控制,一次只有一个线程在刷日志。
对数据库比较了解的同学都知道,事务日志有逻辑日志、物理日志,或者混合类型的日志。那MiniOB的日志是什么?
日志中除了事务操作(提交、回滚)相关的日志,只有插入记录、删除记录两种日志,并且记录了操作的具体页面和槽位,因此算是混合日志。
**如何恢复的?**
在进程启动时,会初始化db对象,db对象会尝试加载日志(当然也是CLog模块干的),然后遍历这些日志调用事务模块的redo接口,将数据恢复出来。恢复的代码可以参考 `CLogManager::recover`
**当前的诸多缺陷**
当前CLog仅仅记录redo日志并没有undo日志,也没有记录每个页面的对应的日志编号,因此在使用相关的功能时会有很多限制。
在恢复时,默认是**初始状态**的buffer pool加载起来,然后从日志中恢复数据。当然,如果redo日志中没有提交的事务,可以回滚。最终redo完后,数据也没有问题。但是如果buffer pool中已经有了一部分数据,特别是有了没有提交事务的数据,那么这部分数据是无法回滚了。因为每个页面中没有日志编号,不知道自己记录的数据对应的哪个版本。
另外,日志记录时也没有处理各种异常情况,比如日志写一半失败了、磁盘满了,恢复时日志没有办法读取出来。
对于buffer pool中的数据,也没有办法保证一个页面是原子写入的,即一个页面要么都写入成功,要么都写入失败,文件系统没有这个保证,需要从应用层考虑解决这个问题。
**如何实现更完善的日志模块?**
日志不仅要考虑数据页面中数据的恢复,还要考虑一些元数据的操作,以及索引相关的操作。
元数据相关的操作包括buffer pool的管理,比如页面的分配、回收。索引当前使用的是B+树,那就需要考虑B+树页面的分配、回收,以及B+树的分裂、合并等操作。这些操作都需要记录日志,以便在恢复时能够恢复出来。这些操作不能完全对应着某一个事务,需要做一些特殊的处理。
**日志模块的性能瓶颈**
当前的日志实现非常低效,可以认为是单线程串行写日志,而且是每个事务完成都要刷新日志到磁盘,这个过程非常耗时。另外,生成日志的过程也是非常低效的,事务每增加一个操作,并且会追加到日志队列中。
**日志之外?**
日志系统是为了配合数据库做恢复,除了日志模块,还有一些需要做的事情,比如数据库的checkpoint,这个是为了减少恢复时的日志量,以及加快恢复速度。
**工具**
为了帮助定位与调试问题,写了一个简单的日志解析工具,可以在miniob编译后找到二进制文件clog_reader,使用方法如下:
```bash
clog_reader miniob/db/sys/
```
> 注意给的参数不是日志文件,而是日志文件所在的目录,工具会自动找到日志文件并解析。由于CLogFile设计缺陷,这里也不能指定文件名。
# 扩展
- [ARIES: A Transaction Recovery Method Supporting Fine-Granularity Locking and Partial Rollbacks Using Write-Ahead Logging](https://github.com/tpn/pdfs/blob/master/ARIES%20-%20A%20Transaction%20Recovery%20Method%20Supporting%20Fine-Granularity%20Locking%20and%20Partial%20Rollbacks%20Using%20Write-Ahead%20Logging%20(1992).pdf) 该论文提出了ARIES算法,这是一种基于日志记录的恢复算法,支持细粒度锁和部分回滚,可以在数据库崩溃时恢复事务。如果想要对steal/no-force的概念有比较详细的了解,可以直接阅读该论文相关部分。
- [Shadow paging](https://www.geeksforgeeks.org/shadow-paging-dbms/) 除了日志做恢复,Shadow paging 是另外一种做恢复的方法。
- [Aether: A Scalable Approach to Logging](http://www.pandis.net/resources/vldb10aether.pdf) 介绍可扩展日志系统的。
- [InnoDB之REDO LOG](http://catkang.github.io/2020/02/27/mysql-redo.html) 非常详细而且深入的介绍了一下InnoDB的redo日志。
- [B+树恢复](http://catkang.github.io/2022/10/05/btree-crash-recovery.html) 介绍如何恢复B+树。
- [CMU 15445 Logging](https://15445.courses.cs.cmu.edu/spring2023/slides/19-logging.pdf)
......@@ -183,12 +183,8 @@ MVCC很好的处理了只读事务与写事务的并发,只读事务可以在
- [A Critique of ANSI SQL Isolation Levels](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf) 该论文针对ANSI SQL标准中隔离级别的定义进行了深入的分析,提出了一些改进的建议。天天看到RC/RR名词的,可以看看这篇论文,了解更详细一点。
- [ARIES: A Transaction Recovery Method Supporting Fine-Granularity Locking and Partial Rollbacks Using Write-Ahead Logging](https://github.com/tpn/pdfs/blob/master/ARIES%20-%20A%20Transaction%20Recovery%20Method%20Supporting%20Fine-Granularity%20Locking%20and%20Partial%20Rollbacks%20Using%20Write-Ahead%20Logging%20(1992).pdf) 该论文提出了ARIES算法,这是一种基于日志记录的恢复算法,支持细粒度锁和部分回滚,可以在数据库崩溃时恢复事务。如果想要对steal/no-force的概念有比较详细的了解,可以直接阅读该论文相关部分。
- [Granularity of Locks and Degrees of Consistency in a Shared Data Base](https://web.stanford.edu/class/cs245/readings/granularity-of-locks.pdf) 这也是一个又老又香的论文,提出了基于锁的并发控制。
- [Aether: A Scalable Approach to Logging](http://www.pandis.net/resources/vldb10aether.pdf) 介绍可扩展日志系统的。
- [An Empirical Evaluation of InMemory Multi-Version Concurrency Control](https://www.vldb.org/pvldb/vol10/p781-Wu.pdf) 介绍MVCC可扩展性的。通过这篇论文可以对MVCC有非常清晰的认识。
- [Scalable Garbage Collection for In-Memory MVCC Systems](http://www.vldb.org/pvldb/vol13/p128-bottcher.pdf) 这里对各种垃圾回收算法做了说明,并且有些创新算法。
......
......@@ -4,7 +4,7 @@ MESSAGE("Begin to build " obclient)
INCLUDE(CheckIncludeFiles)
#INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
TARGET_INCLUDE_DIRECTORIES(obclient PRIVATE . ${PROJECT_SOURCE_DIR}/../deps /usr/local/include /usr/include)
TARGET_INCLUDE_DIRECTORIES(obclient PRIVATE . ${PROJECT_SOURCE_DIR}/deps /usr/local/include /usr/include)
# 父cmake 设置的include_directories 和link_directories并不传导到子cmake里面
#INCLUDE_DIRECTORIES(BEFORE ${CMAKE_INSTALL_PREFIX}/include)
......@@ -28,7 +28,7 @@ FOREACH (F ${ALL_SRC})
ENDFOREACH (F)
# 指定目标文件位置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
MESSAGE("Binary directory:" ${EXECUTABLE_OUTPUT_PATH})
TARGET_SOURCES(obclient PRIVATE ${PRJ_SRC})
TARGET_LINK_LIBRARIES(obclient common pthread dl)
......
......@@ -24,7 +24,7 @@ FOREACH (F ${ALL_SRC})
ENDFOREACH (F)
SET(LIBRARIES common pthread dl event_pthreads event libjsoncpp.a)
SET(LIBRARIES common pthread dl libevent_pthreads.a libevent.a libjsoncpp.a)
# 指定目标文件位置
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../../bin)
......@@ -38,7 +38,6 @@ ADD_LIBRARY(${PROJECT_NAME}_static STATIC ${LIB_SRC})
SET_TARGET_PROPERTIES(${PROJECT_NAME}_static PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
TARGET_LINK_LIBRARIES(${PROJECT_NAME}_static ${LIBRARIES})
# Target 必须在定义 ADD_EXECUTABLE 之后, programs 不受这个限制
# TARGETS和PROGRAMS 的默认权限是OWNER_EXECUTE, GROUP_EXECUTE, 和WORLD_EXECUTE,即755权限, programs 都是处理脚本类
# 类型分为RUNTIME/LIBRARY/ARCHIVE, prog
......
......@@ -14,5 +14,15 @@ See the Mulan PSL v2 for more details. */
#pragma once
/// 磁盘文件,包括存放数据的文件和索引(B+-Tree)文件,都按照页来组织
/// 每一页都有一个编号,称为PageNum
using PageNum = int32_t;
/// 数据文件中按照页来组织,每一页会存放一些行数据(row),或称为记录(record)
/// 每一行(row/record),都占用一个槽位(slot),这些槽有一个编号,称为SlotNum
using SlotNum = int32_t;
/// LSN for log sequence number
using LSN = int32_t;
......@@ -23,7 +23,8 @@ class SessionEvent;
class Stmt;
class Command;
class SQLStageEvent : public common::StageEvent {
class SQLStageEvent : public common::StageEvent
{
public:
SQLStageEvent(SessionEvent *event, const std::string &sql);
virtual ~SQLStageEvent() noexcept;
......
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
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 PSL v2 for more details. */
//
// Created by Wangyunlai on 2023/5/29.
//
#include "global_context.h"
static GlobalContext global_context;
GlobalContext &GlobalContext::instance()
{
return global_context;
}
/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
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 PSL v2 for more details. */
//
// Created by Wangyunlai on 2023/5/29.
//
#pragma once
class BufferPoolManager;
class DefaultHandler;
class TrxKit;
struct GlobalContext
{
BufferPoolManager *buffer_pool_manager_ = nullptr;
DefaultHandler *handler_ = nullptr;
TrxKit *trx_kit_ = nullptr;
static GlobalContext &instance();
};
#define GCTX GlobalContext::instance()
\ No newline at end of file
......@@ -27,6 +27,7 @@ See the Mulan PSL v2 for more details. */
#include "common/metrics/log_reporter.h"
#include "common/metrics/metrics_registry.h"
#include "session/session.h"
#include "session/session_stage.h"
#include "sql/executor/execute_stage.h"
#include "sql/optimizer/optimize_stage.h"
......@@ -39,6 +40,7 @@ See the Mulan PSL v2 for more details. */
#include "storage/default/disk_buffer_pool.h"
#include "storage/default/default_handler.h"
#include "storage/trx/trx.h"
#include "global_context.h"
using namespace common;
......@@ -79,6 +81,8 @@ int init_log(ProcessParam *process_cfg, Ini &properties)
return 0;
}
auto log_context_getter = []() { return reinterpret_cast<intptr_t>(Session::current_session()); };
const std::string log_section_name = "LOG";
std::map<std::string, std::string> log_section = properties.get(log_section_name);
......@@ -115,6 +119,7 @@ int init_log(ProcessParam *process_cfg, Ini &properties)
}
<