forked from huawei/openGauss-server
!466 MOT fixes and code cleanup
Merge pull request !466 from Vinoth Veeraraghavan/master
This commit is contained in:
commit
db55fa203c
|
|
@ -13802,6 +13802,22 @@ static void dumpForeignDataWrapper(Archive* fout, FdwInfo* fdwinfo)
|
|||
destroyPQExpBuffer(labelq);
|
||||
}
|
||||
|
||||
static inline bool IsDefaultForeignServer(const char* serverName)
|
||||
{
|
||||
/*
|
||||
* gsmpp_server, gsmpp_errorinfo_server, mot_server are created by default at the time of initdb.
|
||||
*/
|
||||
if ((0 == strncmp(serverName, "gsmpp_server", strlen("gsmpp_server") + 1)) ||
|
||||
(0 == strncmp(serverName, "\"gsmpp_server\"", strlen("\"gsmpp_server\"") + 1)) ||
|
||||
(0 == strncmp(serverName, "gsmpp_errorinfo_server", strlen("gsmpp_errorinfo_server") + 1)) ||
|
||||
(0 == strncmp(serverName, "\"gsmpp_errorinfo_server\"", strlen("\"gsmpp_errorinfo_server\"") + 1)) ||
|
||||
(0 == strncmp(serverName, "mot_server", strlen("mot_server") + 1)) ||
|
||||
(0 == strncmp(serverName, "\"mot_server\"", strlen("\"mot_server\"") + 1))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* dumpForeignServer
|
||||
* write out a foreign server definition
|
||||
|
|
@ -13823,17 +13839,13 @@ static void dumpForeignServer(Archive* fout, ForeignServerInfo* srvinfo)
|
|||
|
||||
if (isExecUserNotObjectOwner(fout, srvinfo->rolname))
|
||||
return;
|
||||
|
||||
/*
|
||||
* gsmpp_server, gsmpp_errorinfo_server, mot_server are created by default at the time of initdb,
|
||||
* so. skip it.
|
||||
* so skip it.
|
||||
*/
|
||||
qsrvname = gs_strdup(fmtId(srvinfo->dobj.name));
|
||||
if ((0 == strncmp(qsrvname, "gsmpp_server", strlen("gsmpp_server") + 1)) ||
|
||||
(0 == strncmp(qsrvname, "\"gsmpp_server\"", strlen("\"gsmpp_server\"") + 1)) ||
|
||||
(0 == strncmp(qsrvname, "gsmpp_errorinfo_server", strlen("gsmpp_errorinfo_server") + 1)) ||
|
||||
(0 == strncmp(qsrvname, "\"gsmpp_errorinfo_server\"", strlen("\"gsmpp_errorinfo_server\"") + 1)) ||
|
||||
(0 == strncmp(qsrvname, "mot_server", strlen("mot_server") + 1)) ||
|
||||
(0 == strncmp(qsrvname, "\"mot_server\"", strlen("\"mot_server\"") + 1))) {
|
||||
if (IsDefaultForeignServer(qsrvname)) {
|
||||
free(qsrvname);
|
||||
qsrvname = NULL;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1474,7 +1474,7 @@ static void MotFdwDropForeignIndex(Relation userHeapRelation, Relation userIndex
|
|||
{
|
||||
/* Forward drop stmt to MOT FDW. */
|
||||
if (RelationIsForeignTable(userHeapRelation) && isMOTFromTblOid(RelationGetRelid(userHeapRelation))) {
|
||||
FdwRoutine* fdwroutine = GetFdwRoutineByRelId(userHeapRelation->rd_id);
|
||||
FdwRoutine* fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(userHeapRelation));
|
||||
if (fdwroutine->ValidateTableDef != NULL) {
|
||||
DropForeignStmt stmt;
|
||||
stmt.type = T_DropForeignStmt;
|
||||
|
|
@ -3885,13 +3885,13 @@ static void MotFdwReindex(Relation heapRelation, Relation iRel)
|
|||
{
|
||||
/* Forward reindex stmt to MOT FDW. */
|
||||
if (RelationIsForeignTable(heapRelation) && isMOTFromTblOid(RelationGetRelid(heapRelation))) {
|
||||
FdwRoutine* fdwroutine = GetFdwRoutineByRelId(heapRelation->rd_id);
|
||||
FdwRoutine* fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(heapRelation));
|
||||
if (fdwroutine->ValidateTableDef != NULL) {
|
||||
ReindexForeignStmt stmt;
|
||||
stmt.type = T_ReindexStmt;
|
||||
stmt.relkind = RELKIND_INDEX;
|
||||
stmt.reloid = heapRelation->rd_id;
|
||||
stmt.indexoid = iRel->rd_id;
|
||||
stmt.reloid = RelationGetRelid(heapRelation);
|
||||
stmt.indexoid = RelationGetRelid(iRel);
|
||||
stmt.name = iRel->rd_rel->relname.data;
|
||||
|
||||
fdwroutine->ValidateTableDef((Node*)&stmt);
|
||||
|
|
|
|||
|
|
@ -340,6 +340,11 @@ static void knl_g_bgworker_init(knl_g_bgworker_context* bgworker_cxt)
|
|||
bgworker_cxt->have_crashed_worker = false;
|
||||
}
|
||||
|
||||
static void knl_g_mot_init(knl_g_mot_context* mot_cxt)
|
||||
{
|
||||
mot_cxt->jitExecMode = JitExec::JIT_EXEC_MODE_INVALID;
|
||||
}
|
||||
|
||||
void knl_instance_init()
|
||||
{
|
||||
g_instance.binaryupgrade = false;
|
||||
|
|
@ -388,6 +393,7 @@ void knl_instance_init()
|
|||
knl_g_dw_init(&g_instance.dw_cxt);
|
||||
knl_g_xlog_init(&g_instance.xlog_cxt);
|
||||
knl_g_numa_init(&g_instance.numa_cxt);
|
||||
knl_g_mot_init(&g_instance.mot_cxt);
|
||||
knl_g_bgworker_init(&g_instance.bgworker_cxt);
|
||||
|
||||
MemoryContextSwitchTo(old_cxt);
|
||||
|
|
|
|||
|
|
@ -1405,7 +1405,6 @@ static void knl_t_mot_init(knl_t_mot_context* mot_cxt)
|
|||
mot_cxt->log_line_overflow = false;
|
||||
mot_cxt->log_line_buf = NULL;
|
||||
mot_cxt->log_level = 3; // the equivalent of MOT::LogLevel::LL_INFO
|
||||
mot_cxt->init_codegen_once = false;
|
||||
|
||||
mot_cxt->currentThreadId = (uint16_t)-1;
|
||||
mot_cxt->currentNumaNodeId = (-2);
|
||||
|
|
|
|||
|
|
@ -91,6 +91,25 @@ OpFusion::OpFusion(MemoryContext context, CachedPlanSource* psrc, List* plantree
|
|||
m_tmpisnull = NULL;
|
||||
}
|
||||
|
||||
FusionType OpFusion::GetMotFusionType(PlannedStmt* plannedStmt)
|
||||
{
|
||||
FusionType result;
|
||||
switch (plannedStmt->commandType) {
|
||||
case CMD_SELECT:
|
||||
result = MOT_JIT_SELECT_FUSION;
|
||||
break;
|
||||
case CMD_INSERT:
|
||||
case CMD_UPDATE:
|
||||
case CMD_DELETE:
|
||||
result = MOT_JIT_MODIFY_FUSION;
|
||||
break;
|
||||
default:
|
||||
result = NOBYPASS_NO_QUERY_TYPE;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FusionType OpFusion::getFusionType(CachedPlan* plan, ParamListInfo params, List* plantree_list)
|
||||
{
|
||||
if (IsInitdb == true) {
|
||||
|
|
@ -130,17 +149,7 @@ FusionType OpFusion::getFusionType(CachedPlan* plan, ParamListInfo params, List*
|
|||
|
||||
FusionType result = NONE_FUSION;
|
||||
if (plan && plan->mot_jit_context && JitExec::IsMotCodegenEnabled()) {
|
||||
if (((PlannedStmt*)st)->commandType == CMD_SELECT) {
|
||||
result = MOT_JIT_SELECT_FUSION;
|
||||
} else if (((PlannedStmt*)st)->commandType == CMD_INSERT) {
|
||||
result = MOT_JIT_MODIFY_FUSION;
|
||||
} else if (((PlannedStmt*)st)->commandType == CMD_UPDATE) {
|
||||
result = MOT_JIT_MODIFY_FUSION;
|
||||
} else if (((PlannedStmt*)st)->commandType == CMD_DELETE) {
|
||||
result = MOT_JIT_MODIFY_FUSION;
|
||||
} else {
|
||||
result = NOBYPASS_NO_QUERY_TYPE;
|
||||
}
|
||||
result = GetMotFusionType(planned_stmt);
|
||||
} else {
|
||||
if (planned_stmt->subplans != NULL || planned_stmt->initPlan != NULL) {
|
||||
return NOBYPASS_NO_SIMPLE_PLAN;
|
||||
|
|
|
|||
|
|
@ -103,9 +103,8 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CC_VERSION), 8.2.0)
|
||||
CFLAGS += -faligned-new
|
||||
endif
|
||||
CFLAGS += -faligned-new
|
||||
|
||||
# turn on some warnings
|
||||
CFLAGS += -Wwrite-strings -Wcast-align -Wreturn-type
|
||||
CFLAGS += -Wpointer-arith -Wlogical-op -Waddress -Wsizeof-pointer-memaccess -Winit-self
|
||||
|
|
@ -143,9 +142,7 @@ endif
|
|||
|
||||
|
||||
LDFLAGS += $(CFLAGS)
|
||||
ifeq ($(CC_VERSION), 8.2.0)
|
||||
LDFLAGS += -latomic
|
||||
endif
|
||||
LDFLAGS += -latomic
|
||||
|
||||
INCLUDE += -I$(JEMALLOC_INCLUDE_PATH)
|
||||
PYREPLICA :=
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ bool OccTransactionManager::Init()
|
|||
|
||||
bool OccTransactionManager::QuickVersionCheck(const Access* access)
|
||||
{
|
||||
// We always validate on commited rows!
|
||||
// We always validate on committed rows!
|
||||
const Row* row = access->GetRowFromHeader();
|
||||
return (row->m_rowHeader.GetCSN() == access->m_tid);
|
||||
}
|
||||
|
|
@ -77,13 +77,25 @@ bool OccTransactionManager::QuickHeaderValidation(const Access* access)
|
|||
// For upgrade we verify the row
|
||||
// csn has not changed!
|
||||
Sentinel* sent = access->m_origSentinel;
|
||||
if (access->m_params.IsUpgradeInsert() and access->m_params.IsDummyDeletedRow() == false) {
|
||||
if (sent->GetData()->GetCommitSequenceNumber() != access->m_tid) {
|
||||
return false;
|
||||
if (access->m_params.IsUpgradeInsert()) {
|
||||
if (access->m_params.IsDummyDeletedRow()) {
|
||||
// Check is sentinel is deleted and CSN is VALID - ABA problem
|
||||
if (sent->IsCommited() == false) {
|
||||
if (sent->GetData()->GetCommitSequenceNumber() != access->m_tid) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// We deleted internally!, we only need to check version
|
||||
if (sent->GetData()->GetCommitSequenceNumber() != access->m_tid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if the sent is commited we abort!
|
||||
if (sent->IsCommited()) {
|
||||
// If the sent is committed or inserted-deleted we abort!
|
||||
if (sent->IsCommited() or sent->GetData() != nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -113,11 +125,11 @@ bool OccTransactionManager::ValidateWriteSet(TxnManager* txMan)
|
|||
TxnOrderedSet_t& orderedSet = txMan->m_accessMgr->GetOrderedRowSet();
|
||||
for (const auto& raPair : orderedSet) {
|
||||
const Access* ac = raPair.second;
|
||||
if (ac->m_type == RD or !ac->m_params.IsPrimarySentinel()) {
|
||||
if (ac->m_type == RD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ac->GetRowFromHeader()->m_rowHeader.ValidateWrite(ac->m_tid)) {
|
||||
if (!QuickHeaderValidation(ac)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -167,8 +179,8 @@ RC OccTransactionManager::LockHeaders(TxnManager* txMan, uint32_t& numSentinelsL
|
|||
if (ac->m_params.IsPrimaryUpgrade()) {
|
||||
ac->m_auxRow->m_rowHeader.Lock();
|
||||
}
|
||||
// New insert row is already commited!
|
||||
// Check if row has chainged in sentinel
|
||||
// New insert row is already committed!
|
||||
// Check if row has changed in sentinel
|
||||
if (!QuickHeaderValidation(ac)) {
|
||||
rc = RC_ABORT;
|
||||
goto final;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc)
|
|||
mot_string key;
|
||||
mot_string value;
|
||||
bool parseError = false;
|
||||
int arrayIndex = 0;
|
||||
uint64_t arrayIndex = 0;
|
||||
bool hasArrayIndex = false;
|
||||
|
||||
for (int i = 0; i < argc && !parseError; ++i) {
|
||||
if (!line.assign(argv[i])) {
|
||||
|
|
@ -114,12 +115,13 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc)
|
|||
currentSection = itr->second;
|
||||
|
||||
// parse the key-value part
|
||||
if (!ConfigFileParser::ParseKeyValue(keyValuePart, sectionFullName, key, value, arrayIndex)) {
|
||||
if (!ConfigFileParser::ParseKeyValue(
|
||||
keyValuePart, sectionFullName, key, value, arrayIndex, hasArrayIndex)) {
|
||||
// key-value line malformed
|
||||
parseError = true;
|
||||
} else {
|
||||
// check for array item
|
||||
if (arrayIndex == -1) {
|
||||
if (!hasArrayIndex) {
|
||||
ConfigItem* configItem = ConfigFileParser::MakeConfigValue(sectionFullName, key, value);
|
||||
if (configItem == nullptr) {
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_INTERNAL,
|
||||
|
|
@ -142,14 +144,14 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc)
|
|||
}
|
||||
}
|
||||
// create item and add it to array
|
||||
if ((uint32_t)arrayIndex != configArray->GetConfigItemCount()) {
|
||||
if (arrayIndex != configArray->GetConfigItemCount()) {
|
||||
// array items must be ordered
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_INVALID_CFG,
|
||||
"Failed to parse command line arguments: array %s items not well-ordered, "
|
||||
"expecting %u, got %u (command line argument: %s)",
|
||||
"expecting %u, got %" PRIu64 " (command line argument: %s)",
|
||||
configArray->GetName(),
|
||||
configArray->GetConfigItemCount(),
|
||||
(uint32_t)arrayIndex,
|
||||
arrayIndex,
|
||||
argv[i]);
|
||||
} else {
|
||||
ConfigItem* configItem =
|
||||
|
|
@ -160,7 +162,7 @@ ConfigTree* CmdLineConfigLoader::ParseCmdLine(char** argv, int argc)
|
|||
value.c_str());
|
||||
} else if (!configArray->AddConfigItem(configItem)) {
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_OOM,
|
||||
"Failed to add %dth item to configuration array %s",
|
||||
"Failed to add %" PRIu64 "th item to configuration array %s",
|
||||
arrayIndex,
|
||||
configArray->GetName());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ static void FormatTime(uint64_t timeVal, char* buf, uint32_t len)
|
|||
struct tm t;
|
||||
|
||||
if (localtime_r(&(ts.tv_sec), &t) != NULL) {
|
||||
int ret = strftime(buf, len, "%F %T", &t);
|
||||
size_t ret = strftime(buf, len, "%F %T", &t);
|
||||
if (ret != 0) {
|
||||
len -= ret - 1;
|
||||
errno_t erc = snprintf_s(&buf[strlen(buf)], len, len - 1, ".%09ld", ts.tv_nsec);
|
||||
len -= ret;
|
||||
errno_t erc = snprintf_s(buf + ret, len, len - 1, ".%09ld", ts.tv_nsec);
|
||||
securec_check_ss(erc, "\0", "\0");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,10 +58,11 @@ bool ConfigFileParser::BreakSectionName(const mot_string& sectionFullName, mot_s
|
|||
return result;
|
||||
}
|
||||
|
||||
bool ConfigFileParser::ParseKeyValue(
|
||||
const mot_string& keyValuePart, const mot_string& section, mot_string& key, mot_string& value, int& arrayIndex)
|
||||
bool ConfigFileParser::ParseKeyValue(const mot_string& keyValuePart, const mot_string& section, mot_string& key,
|
||||
mot_string& value, uint64_t& arrayIndex, bool& hasArrayIndex)
|
||||
{
|
||||
bool result = false;
|
||||
hasArrayIndex = false;
|
||||
uint32_t equalPos = keyValuePart.find('=');
|
||||
if (equalPos == mot_string::npos) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
||||
|
|
@ -73,7 +74,6 @@ bool ConfigFileParser::ParseKeyValue(
|
|||
} else {
|
||||
key.trim();
|
||||
value.trim();
|
||||
arrayIndex = -1;
|
||||
result = true;
|
||||
|
||||
// check for array item
|
||||
|
|
@ -85,9 +85,8 @@ bool ConfigFileParser::ParseKeyValue(
|
|||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_INTERNAL, "Load Configuration", "Failed to parse integer part from array item specifier");
|
||||
} else {
|
||||
uint64_t intValue = 0;
|
||||
if (ParseUIntValue(section, key, intPart, intValue, true)) {
|
||||
arrayIndex = (int)intValue;
|
||||
if (ParseUIntValue(section, key, intPart, arrayIndex, true)) {
|
||||
hasArrayIndex = true;
|
||||
key.substr_inplace(0, poundPos);
|
||||
result = true;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -53,11 +53,12 @@ public:
|
|||
* @param section The containing section (for error message in case of failure).
|
||||
* @param[out] key The resulting key.
|
||||
* @param[out] value The resulting value.
|
||||
* @param[out] arrayIndex The array index in case of array item, or -1 if not.
|
||||
* @param[out] arrayIndex The array index in case of array item.
|
||||
* @param[out] hasArrayIndex Returns true if the key specifies an array item.
|
||||
* @return True if parsing was successful.
|
||||
*/
|
||||
static bool ParseKeyValue(
|
||||
const mot_string& keyValuePart, const mot_string& section, mot_string& key, mot_string& value, int& arrayIndex);
|
||||
static bool ParseKeyValue(const mot_string& keyValuePart, const mot_string& section, mot_string& key,
|
||||
mot_string& value, uint64_t& arrayIndex, bool& hasArrayIndex);
|
||||
|
||||
/**
|
||||
* @brief Creates a typed configuration value.
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath)
|
|||
mot_string key;
|
||||
mot_string value;
|
||||
bool parseError = false;
|
||||
int arrayIndex = 0;
|
||||
uint64_t arrayIndex = 0;
|
||||
bool hasArrayIndex = false;
|
||||
|
||||
// unsupported yet
|
||||
FileLineReader reader(configFilePath);
|
||||
|
|
@ -131,7 +132,8 @@ ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath)
|
|||
currentSection = itr->second;
|
||||
|
||||
// parse the key-value part
|
||||
if (!ConfigFileParser::ParseKeyValue(keyValuePart, sectionFullName, key, value, arrayIndex)) {
|
||||
if (!ConfigFileParser::ParseKeyValue(
|
||||
keyValuePart, sectionFullName, key, value, arrayIndex, hasArrayIndex)) {
|
||||
// key-value line malformed
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_INVALID_CFG,
|
||||
"Failed to parse configuration file %s at line %d: %s (key/value malformed)",
|
||||
|
|
@ -140,7 +142,7 @@ ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath)
|
|||
line.c_str());
|
||||
} else {
|
||||
// check for array item
|
||||
if (arrayIndex == -1) {
|
||||
if (!hasArrayIndex) {
|
||||
ConfigItem* configItem = ConfigFileParser::MakeConfigValue(sectionFullName, key, value);
|
||||
if (configItem == nullptr) {
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_INTERNAL,
|
||||
|
|
@ -162,17 +164,17 @@ ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath)
|
|||
MOT_ERROR_OOM, "Failed to add configuration array to parent section");
|
||||
}
|
||||
}
|
||||
if ((uint32_t)arrayIndex != configArray->GetConfigItemCount()) {
|
||||
if (arrayIndex != configArray->GetConfigItemCount()) {
|
||||
// array items must be ordered
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_INVALID_CFG,
|
||||
"Failed to parse configuration file %s at line %d: %s (array %s items not "
|
||||
"well-ordered, expecting %u, got %u)",
|
||||
"well-ordered, expecting %u, got %" PRIu64 ")",
|
||||
configFilePath,
|
||||
reader.GetLineNumber(),
|
||||
line.c_str(),
|
||||
configArray->GetName(),
|
||||
configArray->GetConfigItemCount(),
|
||||
(uint32_t)arrayIndex);
|
||||
arrayIndex);
|
||||
} else {
|
||||
ConfigItem* configItem =
|
||||
ConfigFileParser::MakeArrayConfigValue(sectionFullName, arrayIndex, value);
|
||||
|
|
@ -180,7 +182,7 @@ ConfigTree* PropsConfigFileLoader::LoadConfigFile(const char* configFilePath)
|
|||
REPORT_PARSE_ERROR(MOT_ERROR_INTERNAL, "Failed to create configuration array value");
|
||||
} else if (!configArray->AddConfigItem(configItem)) {
|
||||
REPORT_PARSE_ERROR(MOT_ERROR_OOM,
|
||||
"Failed to add %dth item to configuration array %s",
|
||||
"Failed to add %" PRIu64 "th item to configuration array %s",
|
||||
arrayIndex,
|
||||
configArray->GetName());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,14 +102,11 @@ mot_string GlobalStatistics::MakeName(const char* baseName, NamingScheme namingS
|
|||
return result;
|
||||
}
|
||||
|
||||
bool GlobalStatistics::RegisterStatistics(StatisticVariable* statVar)
|
||||
void GlobalStatistics::RegisterStatistics(StatisticVariable* statVar)
|
||||
{
|
||||
bool result = true;
|
||||
if (!m_statVars.push_back(statVar)) {
|
||||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_OOM, "Register Statistics", "Failed to register statistics variable %s", statVar->GetName());
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace MOT
|
||||
|
|
|
|||
|
|
@ -125,9 +125,10 @@ protected:
|
|||
/**
|
||||
* Allows derived classes to register their statistic variables.
|
||||
* @param stat_var The statistic variable to register.
|
||||
* @return True if registration succeeded, otherwise false.
|
||||
* @note In case of failure the system continues to operate, but the
|
||||
* statistics variable will not be periodically reported to the log.
|
||||
*/
|
||||
bool RegisterStatistics(StatisticVariable* statVar);
|
||||
void RegisterStatistics(StatisticVariable* statVar);
|
||||
|
||||
private:
|
||||
/** @var The set of managed statistic variables. */
|
||||
|
|
|
|||
|
|
@ -128,9 +128,8 @@ mot_string ThreadStatistics::MakeName(const char* baseName, uint64_t threadId)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool ThreadStatistics::RegisterStatistics(StatisticVariable* statVar)
|
||||
void ThreadStatistics::RegisterStatistics(StatisticVariable* statVar)
|
||||
{
|
||||
bool result = false;
|
||||
if (!m_statVars.push_back(statVar)) {
|
||||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_OOM, "Register Statistics", "Failed to add statistic variable %s", statVar->GetName());
|
||||
|
|
@ -139,9 +138,6 @@ bool ThreadStatistics::RegisterStatistics(StatisticVariable* statVar)
|
|||
"Register Statistics",
|
||||
"Failed to add valid thread slot for statistic variable %s",
|
||||
statVar->GetName());
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace MOT
|
||||
|
|
|
|||
|
|
@ -170,9 +170,10 @@ protected:
|
|||
/**
|
||||
* @brief Allows derived classes to register their statistic variables.
|
||||
* @param statVar The statistic variable to register.
|
||||
* @return True if registration succeede, otherwise false.
|
||||
* @note In case of failure the system continues to operate, but the
|
||||
* statistics variable will not be periodically reported to the log.
|
||||
*/
|
||||
bool RegisterStatistics(StatisticVariable* statVar);
|
||||
void RegisterStatistics(StatisticVariable* statVar);
|
||||
|
||||
private:
|
||||
/** @var The logical identifier of the thread to which this set of statistic variables belong. */
|
||||
|
|
|
|||
|
|
@ -940,6 +940,7 @@ static inline uint32_t PushSuperChunk(MemRawChunkPool* chunkPool, MemRawChunkHea
|
|||
chunkPool->m_poolName,
|
||||
chunksPushed,
|
||||
count);
|
||||
FreeChunk(chunkPool, chunk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* object_pool.cpp
|
||||
* Object pool implementation.
|
||||
* Object pool interfaces.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/storage/mot/core/src/memory/object_pool.cpp
|
||||
|
|
@ -25,143 +25,7 @@
|
|||
#include "object_pool.h"
|
||||
|
||||
namespace MOT {
|
||||
IMPLEMENT_CLASS_LOGGER(ObjAllocInterface, Memory)
|
||||
IMPLEMENT_CLASS_LOGGER(SlabAllocator, Memory)
|
||||
IMPLEMENT_CLASS_LOGGER(ObjPool, Memory)
|
||||
|
||||
ObjPoolPtr::ObjPoolPtr(ObjPool* target)
|
||||
{
|
||||
m_data.m_ptr = target;
|
||||
if (target != NULL)
|
||||
m_data.m_slice[LIST_PTR_SLICE_IX] = target->m_listCounter;
|
||||
}
|
||||
|
||||
ObjPoolPtr& ObjPoolPtr::operator=(ObjPool* right)
|
||||
{
|
||||
m_data.m_ptr = right;
|
||||
if (right != NULL)
|
||||
m_data.m_slice[LIST_PTR_SLICE_IX] = right->m_listCounter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjAllocInterface* ObjAllocInterface::GetObjPool(uint16_t size, bool local, uint8_t align)
|
||||
{
|
||||
ObjAllocInterface* result = NULL;
|
||||
if (local) {
|
||||
result = new (std::nothrow) LocalObjPool(size, align);
|
||||
} else {
|
||||
result = new (std::nothrow) GlobalObjPool(size, align);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
||||
"Allocate Object Pool",
|
||||
"Failed to allocate memory for %s object pool",
|
||||
local ? "local" : "global");
|
||||
} else if (!result->Initialize()) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
||||
"Allocate Object Pool",
|
||||
"Failed to pre-allocate memory for %s object pool",
|
||||
local ? "local" : "global");
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ObjAllocInterface::FreeObjPool(ObjAllocInterface** pool)
|
||||
{
|
||||
if (pool != NULL && *pool != NULL) {
|
||||
delete *pool;
|
||||
*pool = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ObjAllocInterface::~ObjAllocInterface()
|
||||
{
|
||||
ObjPool* p = m_objList;
|
||||
while (p != NULL) {
|
||||
ObjPool* tmp = p;
|
||||
p = p->m_next;
|
||||
ObjPool::DelObjPool(tmp, m_type, m_global);
|
||||
}
|
||||
}
|
||||
|
||||
inline MemBufferClass ObjAllocInterface::CalcBufferClass(uint16_t size)
|
||||
{
|
||||
int pool_size = sizeof(ObjPool) + NUM_OBJS * size;
|
||||
// 1KB has 11 bit set (starting from less significant)
|
||||
// we use 32 bit int for size, so first 1 bit will 32 - __builtin_clz(pool_size)
|
||||
// the buffer classes start from 1KB
|
||||
return MemBufferClassLowerBound(pool_size);
|
||||
}
|
||||
|
||||
void ObjAllocInterface::GetStats(PoolStatsSt& stats)
|
||||
{
|
||||
ObjPoolPtr p;
|
||||
|
||||
if (stats.m_type == PoolStatsT::POOL_STATS_ALL)
|
||||
p = m_objList;
|
||||
else
|
||||
p = m_nextFree;
|
||||
|
||||
stats.m_objSize = m_size;
|
||||
stats.m_poolGrossSize = (1024 * MemBufferClassToSizeKb(m_type));
|
||||
|
||||
if (p.Get()) {
|
||||
stats.m_perPoolTotalCount = p->m_totalCount;
|
||||
stats.m_perPoolOverhead = p->m_overheadBytes;
|
||||
stats.m_perPoolWaist = p->m_notUsedBytes;
|
||||
}
|
||||
while (p.Get() != NULL) {
|
||||
stats.m_poolCount++;
|
||||
if (p->m_totalCount == p->m_freeCount)
|
||||
stats.m_poolFreeCount++;
|
||||
stats.m_totalObjCount += p->m_totalCount;
|
||||
stats.m_freeObjCount += p->m_freeCount;
|
||||
if (stats.m_type == PoolStatsT::POOL_STATS_ALL)
|
||||
p = p->m_next;
|
||||
else
|
||||
p = p->m_objNext;
|
||||
}
|
||||
|
||||
if (stats.m_poolCount > 0)
|
||||
stats.m_fragmentationPercent = (int16_t)(stats.m_poolFreeCount * 100 / stats.m_poolCount);
|
||||
else
|
||||
stats.m_fragmentationPercent = 0;
|
||||
}
|
||||
|
||||
void ObjAllocInterface::PrintStats(PoolStatsSt& stats, const char* prefix, LogLevel level)
|
||||
{
|
||||
const char* hist_str = "";
|
||||
|
||||
MOT_LOG(level,
|
||||
"%s: type: %d, size: %d, pools: %u(%u), total objects: %lu, free objects: %lu"
|
||||
", overhead: %lu, waist: %lu"
|
||||
"\n%s",
|
||||
prefix,
|
||||
m_type,
|
||||
m_size,
|
||||
stats.m_poolCount,
|
||||
stats.m_poolFreeCount,
|
||||
stats.m_totalObjCount,
|
||||
stats.m_freeObjCount,
|
||||
stats.m_poolCount * stats.m_perPoolOverhead,
|
||||
stats.m_poolCount * stats.m_perPoolWaist,
|
||||
hist_str);
|
||||
}
|
||||
|
||||
void ObjAllocInterface::Print(const char* prefix, LogLevel level)
|
||||
{
|
||||
PoolStatsSt stats;
|
||||
|
||||
errno_t erc = memset_s(&stats, sizeof(PoolStatsSt), 0, sizeof(PoolStatsSt));
|
||||
securec_check(erc, "\0", "\0");
|
||||
stats.m_type = PoolStatsT::POOL_STATS_ALL;
|
||||
|
||||
GetStats(stats);
|
||||
PrintStats(stats, prefix, level);
|
||||
}
|
||||
|
||||
PoolStatsSt* SlabAllocator::GetStats()
|
||||
{
|
||||
|
|
@ -184,16 +48,18 @@ PoolStatsSt* SlabAllocator::GetStats()
|
|||
|
||||
void SlabAllocator::FreeStats(PoolStatsSt* stats)
|
||||
{
|
||||
if (stats != NULL)
|
||||
if (stats != NULL) {
|
||||
free(stats);
|
||||
}
|
||||
}
|
||||
|
||||
void SlabAllocator::GetSize(uint64_t& size, uint64_t& netto)
|
||||
{
|
||||
PoolStatsSt* stats = GetStats();
|
||||
|
||||
if (stats == NULL)
|
||||
if (stats == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= SLUB_MAX_BIN; i++) {
|
||||
if (m_bins[i] != NULL) {
|
||||
|
|
@ -207,8 +73,9 @@ void SlabAllocator::GetSize(uint64_t& size, uint64_t& netto)
|
|||
|
||||
void SlabAllocator::PrintStats(PoolStatsSt* stats, const char* prefix, LogLevel level)
|
||||
{
|
||||
if (stats == NULL)
|
||||
if (stats == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= SLUB_MAX_BIN; i++) {
|
||||
if (m_bins[i] != NULL) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* object_pool.h
|
||||
* Object pool implementation.
|
||||
* Object pool interfaces.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/storage/mot/core/src/memory/object_pool.h
|
||||
|
|
@ -25,511 +25,9 @@
|
|||
#ifndef OBJECT_POOL_H
|
||||
#define OBJECT_POOL_H
|
||||
|
||||
#include <new>
|
||||
#include <atomic>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "global.h"
|
||||
#include "mot_atomic_ops.h"
|
||||
#include "utilities.h"
|
||||
#include "cycles.h"
|
||||
#include "thread_id.h"
|
||||
#include "mm_def.h"
|
||||
#include "mm_buffer_api.h"
|
||||
#include "mm_session_api.h"
|
||||
#include "memory_statistics.h"
|
||||
#include "mm_api.h"
|
||||
#include "spin_lock.h"
|
||||
#include "object_pool_impl.h"
|
||||
|
||||
namespace MOT {
|
||||
#define MAX_THR_NUM 4096
|
||||
#define INITIAL_NUM_OBJPOOL 1
|
||||
#define NUM_OBJS (uint8_t)(255)
|
||||
#define NOT_VALID (uint8_t)(-1)
|
||||
#define G_THREAD_ID ((int16_t)MOTCurrThreadId)
|
||||
#define OBJ_INDEX_SIZE 1
|
||||
#define MEMORY_BARRIER asm volatile("" ::: "memory");
|
||||
|
||||
#define OBJ_RELEASE_START_NOMARK(ptr, size) \
|
||||
uint8_t* p = (uint8_t*)ptr; \
|
||||
uint8_t* oix_ptr = (p + size - 1); \
|
||||
uint8_t oix = *oix_ptr; \
|
||||
if (oix == NOT_VALID) { \
|
||||
printf("Detected double free of pointer or corruption: 0x%lx\n", (uint64_t)ptr); \
|
||||
MOTAbort((void*)ptr); \
|
||||
} \
|
||||
ObjPoolPtr op = (ObjPool*)(p - sizeof(ObjPool) - oix * size);
|
||||
|
||||
#define OBJ_RELEASE_MARK(ptr) (*(uint8_t*)ptr = NOT_VALID)
|
||||
|
||||
#define OBJ_RELEASE_START(ptr, size) \
|
||||
uint8_t* p = (uint8_t*)ptr; \
|
||||
uint8_t* oix_ptr = (p + size - 1); \
|
||||
uint8_t oix = *oix_ptr; \
|
||||
if (oix == NOT_VALID) { \
|
||||
printf("Detected double free of pointer or corruption: 0x%lx\n", (uint64_t)ptr); \
|
||||
MOTAbort(ptr); \
|
||||
} else { \
|
||||
if (!__sync_bool_compare_and_swap(oix_ptr, oix, NOT_VALID)) { \
|
||||
printf("Detected double free of pointer or corruption: 0x%lx\n", (uint64_t)ptr); \
|
||||
MOTAbort(ptr); \
|
||||
} \
|
||||
} \
|
||||
ObjPoolPtr op = (ObjPool*)(p - sizeof(ObjPool) - oix * size);
|
||||
|
||||
#define CAS(ptr, oldval, newval) \
|
||||
__sync_bool_compare_and_swap((uint64_t*)&ptr, *(uint64_t*)&(oldval), *(uint64_t*)&newval)
|
||||
|
||||
#define PUSH_NOLOCK(list, obj) \
|
||||
{ \
|
||||
obj->m_objNext = list; \
|
||||
list = obj; \
|
||||
}
|
||||
|
||||
#define POP_NOLOCK(list) \
|
||||
{ \
|
||||
if (list.Get() != nullptr) { \
|
||||
list = (list)->m_objNext; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PUSH(list, obj) \
|
||||
{ \
|
||||
++obj; \
|
||||
do { \
|
||||
obj->m_objNext = list; \
|
||||
} while (!CAS(list, obj->m_objNext, obj)); \
|
||||
}
|
||||
|
||||
#define POP(list, obj) \
|
||||
{ \
|
||||
do { \
|
||||
obj = list; \
|
||||
if (obj.Get() == nullptr) \
|
||||
break; \
|
||||
} while (!CAS(list, obj, obj->m_objNext)); \
|
||||
}
|
||||
|
||||
#define ADD_TO_LIST_NOLOCK(list, obj) \
|
||||
{ \
|
||||
obj->m_next = list; \
|
||||
if (list != nullptr) \
|
||||
list->m_prev = obj; \
|
||||
list = obj; \
|
||||
}
|
||||
|
||||
#define DEL_FROM_LIST_NOLOCK(list, obj) \
|
||||
{ \
|
||||
if (obj->m_prev != nullptr) { \
|
||||
obj->m_prev->m_next = obj->m_next; \
|
||||
} \
|
||||
if (obj->m_next != nullptr) { \
|
||||
obj->m_next->m_prev = obj->m_prev; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ADD_TO_LIST(list, obj) \
|
||||
{ \
|
||||
do { \
|
||||
obj->m_next = list; \
|
||||
} while (!CAS(list, obj->m_next, obj)); \
|
||||
if (likely(obj->m_next != nullptr)) \
|
||||
obj->m_next->m_prev = obj; \
|
||||
}
|
||||
|
||||
#define DEL_FROM_LIST(locker, list, obj) \
|
||||
{ \
|
||||
do { \
|
||||
if (list == obj) { \
|
||||
if (CAS(list, obj, obj->m_next)) { \
|
||||
obj->m_next = nullptr; \
|
||||
obj->m_prev = nullptr; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
locker.lock(); \
|
||||
DEL_FROM_LIST_NOLOCK(list, obj) \
|
||||
locker.unlock(); \
|
||||
} while (0); \
|
||||
}
|
||||
|
||||
typedef enum PoolAllocState { PAS_FIRST, PAS_EMPTY, PAS_NONE } PoolAllocStateT;
|
||||
|
||||
class ObjPool;
|
||||
|
||||
// DO NOT CHANGE ORDER OF THE MEMBERS
|
||||
typedef struct PACKED ObjPool_st {
|
||||
public:
|
||||
friend ObjPool;
|
||||
uint8_t m_nextFreeObj;
|
||||
|
||||
private:
|
||||
uint8_t m_fill1[7];
|
||||
|
||||
public:
|
||||
uint8_t m_objIndexArr[NUM_OBJS + 1];
|
||||
uint8_t m_nextOccupiedObj;
|
||||
|
||||
private:
|
||||
uint8_t m_fill2[7];
|
||||
|
||||
public:
|
||||
uint8_t m_data[0];
|
||||
} ObjPoolSt;
|
||||
|
||||
typedef enum PoolStatsType : uint8_t { POOL_STATS_ALL = 0, POOL_STATS_FREE } PoolStatsT;
|
||||
|
||||
typedef struct PoolStats_st {
|
||||
PoolStatsT m_type;
|
||||
uint16_t m_objSize;
|
||||
uint16_t m_perPoolTotalCount;
|
||||
uint32_t m_poolCount;
|
||||
uint32_t m_poolFreeCount;
|
||||
uint64_t m_totalObjCount;
|
||||
uint64_t m_freeObjCount;
|
||||
uint64_t m_poolGrossSize;
|
||||
int16_t m_fragmentationPercent;
|
||||
uint32_t m_perPoolOverhead;
|
||||
uint32_t m_perPoolWaist;
|
||||
} PoolStatsSt;
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define LIST_PTR_SLICE_IX 3
|
||||
#else
|
||||
#define LIST_PTR_SLICE_IX 0
|
||||
#endif
|
||||
#define LIST_PTR_MASK 0xffffffffffff // usable address space is 48 bits
|
||||
|
||||
class PACKED ObjPoolPtr {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor for a NULL pointer.
|
||||
*/
|
||||
ObjPoolPtr()
|
||||
{
|
||||
m_data.m_ptr = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructs an objects on pre-allocated memory buffer.
|
||||
* @param target Address of an object.
|
||||
*/
|
||||
ObjPoolPtr(ObjPool* target);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
* @param other The object.
|
||||
*/
|
||||
ObjPoolPtr(ObjPoolPtr& other)
|
||||
{
|
||||
m_data.m_ptr = other.m_data.m_ptr;
|
||||
}
|
||||
|
||||
ObjPoolPtr(const ObjPoolPtr& other)
|
||||
{
|
||||
m_data.m_ptr = other.m_data.m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a pointer to the managed object.
|
||||
* @return A pointer to the object.
|
||||
*/
|
||||
inline ObjPool* Get()
|
||||
{
|
||||
return (ObjPool*)(((uint64_t)m_data.m_ptr) & LIST_PTR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Member access operator implementation.
|
||||
* @return Retrieves a pointer to the managed object.
|
||||
*/
|
||||
inline ObjPool* operator->()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a pointer to the managed object.
|
||||
* @return A pointer to the object.
|
||||
*/
|
||||
inline ObjPool* Get() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Member access operator implementation.
|
||||
* @return Retrieves a pointer to the managed object.
|
||||
*/
|
||||
inline ObjPool* operator->() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
inline void operator++();
|
||||
|
||||
ObjPoolPtr& operator=(const ObjPoolPtr& right)
|
||||
{
|
||||
m_data.m_ptr = right.m_data.m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjPoolPtr& operator=(ObjPool* right);
|
||||
|
||||
bool operator==(const ObjPoolPtr& right) const
|
||||
{
|
||||
return (m_data.m_ptr == right.m_data.m_ptr);
|
||||
}
|
||||
|
||||
bool operator==(ObjPoolPtr& right) const
|
||||
{
|
||||
return (m_data.m_ptr == right.m_data.m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor. Deallocates the object.
|
||||
*/
|
||||
~ObjPoolPtr()
|
||||
{}
|
||||
|
||||
private:
|
||||
union {
|
||||
ObjPool* m_ptr;
|
||||
uint16_t m_slice[4];
|
||||
} m_data;
|
||||
};
|
||||
|
||||
class ObjAllocInterface {
|
||||
public:
|
||||
friend class ObjPool;
|
||||
spin_lock m_listLock;
|
||||
ObjPool* m_objList;
|
||||
ObjPoolPtr m_nextFree;
|
||||
uint16_t m_size;
|
||||
uint16_t m_oixOffset;
|
||||
MemBufferClass m_type;
|
||||
bool m_global;
|
||||
|
||||
static ObjAllocInterface* GetObjPool(uint16_t size, bool local, uint8_t align = 8);
|
||||
static void FreeObjPool(ObjAllocInterface** pool);
|
||||
|
||||
explicit ObjAllocInterface(bool isGlobal) : m_global(isGlobal)
|
||||
{}
|
||||
|
||||
virtual ~ObjAllocInterface();
|
||||
|
||||
virtual bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void* Alloc() = 0;
|
||||
template <typename T, class... Args>
|
||||
inline T* Alloc(Args&&... args)
|
||||
{
|
||||
void* buf = Alloc();
|
||||
if (unlikely(buf == nullptr))
|
||||
return nullptr;
|
||||
return new (buf) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
virtual void Release(void* ptr) = 0;
|
||||
template <typename T>
|
||||
inline void Release(T* obj)
|
||||
{
|
||||
if (likely(obj != nullptr)) {
|
||||
obj->~T();
|
||||
Release((void*)obj);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ClearThreadCache() = 0;
|
||||
virtual void ClearFreeCache() = 0;
|
||||
|
||||
void GetStats(PoolStatsSt& stats);
|
||||
void PrintStats(PoolStatsSt& stats, const char* prefix = "", LogLevel level = LogLevel::LL_DEBUG);
|
||||
void Print(const char* prefix, LogLevel level = LogLevel::LL_DEBUG);
|
||||
|
||||
protected:
|
||||
static MemBufferClass CalcBufferClass(uint16_t size);
|
||||
DECLARE_CLASS_LOGGER();
|
||||
};
|
||||
|
||||
// DO NOT CHANGE ORDER OF THE MEMBERS
|
||||
class PACKED ObjPool {
|
||||
public:
|
||||
ObjPool* m_next;
|
||||
ObjPool* m_prev;
|
||||
uint16_t m_freeCount;
|
||||
uint16_t m_totalCount;
|
||||
int16_t m_owner;
|
||||
uint16_t m_listCounter;
|
||||
ObjPoolPtr m_objNext;
|
||||
ObjAllocInterface* m_parent;
|
||||
int m_notUsedBytes;
|
||||
int m_overheadBytes;
|
||||
ObjPoolSt m_head;
|
||||
|
||||
ObjPool(uint16_t size, MemBufferClass type, ObjAllocInterface* app)
|
||||
{
|
||||
m_parent = app;
|
||||
m_owner = -1;
|
||||
m_objNext = nullptr;
|
||||
m_next = m_prev = nullptr;
|
||||
*(uint32_t*)(&m_head.m_fill1[3]) = 0xDEADBEEF;
|
||||
*(uint32_t*)(&m_head.m_fill2[3]) = 0xDEADBEEF;
|
||||
m_overheadBytes = sizeof(ObjPool);
|
||||
uint8_t* ptr = m_head.m_data;
|
||||
uint8_t* end = ptr + (1024 * MemBufferClassToSizeKb(type)) - sizeof(ObjPool);
|
||||
|
||||
m_freeCount = m_totalCount = (uint16_t)((end - m_head.m_data) / m_parent->m_size);
|
||||
uint8_t i = 0;
|
||||
for (; i < m_totalCount; i++) {
|
||||
m_head.m_objIndexArr[i] = i;
|
||||
ptr += m_parent->m_size;
|
||||
ptr[-1] = i;
|
||||
}
|
||||
for (; i < NUM_OBJS; i++) {
|
||||
m_head.m_objIndexArr[i] = NOT_VALID;
|
||||
}
|
||||
m_head.m_objIndexArr[i] = NOT_VALID;
|
||||
m_head.m_nextFreeObj = -1;
|
||||
m_head.m_nextOccupiedObj = m_totalCount - 1;
|
||||
m_overheadBytes += m_totalCount * OBJ_INDEX_SIZE;
|
||||
m_notUsedBytes = (int)(end - ptr);
|
||||
}
|
||||
|
||||
~ObjPool()
|
||||
{}
|
||||
|
||||
inline void AllocNoLock(void** ret, PoolAllocStateT* state)
|
||||
{
|
||||
uint8_t ix = ++(m_head.m_nextFreeObj);
|
||||
uint8_t oix = m_head.m_objIndexArr[ix];
|
||||
m_head.m_objIndexArr[ix] = NOT_VALID;
|
||||
*ret = (m_head.m_data + oix * m_parent->m_size);
|
||||
((uint8_t*)(*ret))[m_parent->m_oixOffset] = oix;
|
||||
--m_freeCount;
|
||||
if (m_freeCount == 0)
|
||||
*state = PAS_EMPTY;
|
||||
}
|
||||
|
||||
inline void Alloc(void** ret, PoolAllocStateT* state)
|
||||
{
|
||||
uint8_t ix = ++(m_head.m_nextFreeObj);
|
||||
while (m_head.m_objIndexArr[ix] == NOT_VALID) {
|
||||
PAUSE
|
||||
}
|
||||
uint8_t oix = m_head.m_objIndexArr[ix];
|
||||
m_head.m_objIndexArr[ix] = NOT_VALID;
|
||||
*ret = (m_head.m_data + oix * m_parent->m_size);
|
||||
((uint8_t*)(*ret))[m_parent->m_oixOffset] = oix;
|
||||
uint16_t c = __sync_sub_and_fetch(&m_freeCount, 1);
|
||||
if (c == 0)
|
||||
*state = PAS_EMPTY;
|
||||
}
|
||||
|
||||
inline void ReleaseNoLock(uint8_t oix, PoolAllocStateT* state)
|
||||
{
|
||||
++(m_head.m_nextOccupiedObj);
|
||||
m_head.m_objIndexArr[m_head.m_nextOccupiedObj] = oix;
|
||||
++m_freeCount;
|
||||
|
||||
if (m_freeCount == 1) {
|
||||
*state = PAS_FIRST;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Release(uint8_t oix, PoolAllocStateT* state)
|
||||
{
|
||||
uint8_t ix = __sync_add_and_fetch(&m_head.m_nextOccupiedObj, 1);
|
||||
m_head.m_objIndexArr[ix] = oix;
|
||||
uint16_t c = __sync_add_and_fetch(&m_freeCount, 1);
|
||||
|
||||
if (c == 1) {
|
||||
*state = PAS_FIRST;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static ObjPool* GetObjPool(uint16_t size, ObjAllocInterface* app, MemBufferClass type, bool global)
|
||||
{
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t start_time = GetSysClock();
|
||||
#endif
|
||||
#ifndef MEM_ACTIVE
|
||||
void* p = (void*)malloc((1024 * MemBufferClassToSizeKb(type)));
|
||||
#else
|
||||
void* p;
|
||||
|
||||
if (global == true)
|
||||
p = MemBufferAllocGlobal(type);
|
||||
else
|
||||
#ifdef MEM_SESSION_ACTIVE
|
||||
{
|
||||
uint32_t buffer_size = 1024 * MemBufferClassToSizeKb(type);
|
||||
p = MemSessionAlloc(buffer_size);
|
||||
if (p) {
|
||||
DetailedMemoryStatisticsProvider::m_provider->AddLocalBuffersUsed(MOTCurrentNumaNodeId, type);
|
||||
}
|
||||
}
|
||||
#else
|
||||
p = MemBufferAllocLocal(type);
|
||||
#endif // MEM_SESSION_ACTIVE
|
||||
#endif // MEM_ACTIVE
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t end_time = GetSysClock();
|
||||
MemoryStatisticsProvider::m_provider->AddMallocTime(
|
||||
CpuCyclesLevelTime::CyclesToNanoseconds(end_time - start_time));
|
||||
#endif
|
||||
ObjPool* o = nullptr;
|
||||
if (p) {
|
||||
o = new (p) ObjPool(size, type, app);
|
||||
} else {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
||||
"N/A",
|
||||
"Failed to allocate %s %s buffer for object pool",
|
||||
MemBufferClassToString(type),
|
||||
global ? "global" : "local");
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static void DelObjPool(void* ptr, MemBufferClass type, bool global)
|
||||
{
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t start_time = GetSysClock();
|
||||
#endif
|
||||
#ifndef MEM_ACTIVE
|
||||
free(ptr);
|
||||
#else
|
||||
if (global == true)
|
||||
MemBufferFreeGlobal(ptr, type);
|
||||
else
|
||||
#ifdef MEM_SESSION_ACTIVE
|
||||
{
|
||||
MemSessionFree(ptr);
|
||||
DetailedMemoryStatisticsProvider::m_provider->AddLocalBuffersFreed(MOTCurrentNumaNodeId, type);
|
||||
}
|
||||
#else
|
||||
MemBufferFreeLocal(ptr, type);
|
||||
#endif // MEM_SESSION_ACTIVE
|
||||
#endif // MEM_ACTIVE
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t end_time = GetSysClock();
|
||||
MemoryStatisticsProvider::m_provider->AddFreeTime(
|
||||
CpuCyclesLevelTime::CyclesToNanoseconds(end_time - start_time));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
DECLARE_CLASS_LOGGER();
|
||||
};
|
||||
|
||||
class LocalObjPool : public ObjAllocInterface {
|
||||
public:
|
||||
LocalObjPool(uint16_t sz, uint8_t align) : ObjAllocInterface(false)
|
||||
|
|
@ -552,7 +50,7 @@ public:
|
|||
for (int i = 0; i < INITIAL_NUM_OBJPOOL; i++) {
|
||||
ObjPool* op = ObjPool::GetObjPool(m_size, this, m_type, false);
|
||||
if (op == nullptr) {
|
||||
// memory deallocated when object is destroyed (see ~ObjAllocInterface())
|
||||
// memory de-allocated when object is destroyed (see ~ObjAllocInterface())
|
||||
MOT_REPORT_ERROR(MOT_ERROR_OOM, "N/A", "Failed to initialize local object pool");
|
||||
result = false;
|
||||
break;
|
||||
|
|
@ -936,13 +434,6 @@ private:
|
|||
|
||||
DECLARE_CLASS_LOGGER();
|
||||
};
|
||||
|
||||
inline void ObjPoolPtr::operator++()
|
||||
{
|
||||
Get()->m_listCounter++;
|
||||
m_data.m_slice[LIST_PTR_SLICE_IX] = Get()->m_listCounter;
|
||||
MEMORY_BARRIER;
|
||||
}
|
||||
} // namespace MOT
|
||||
|
||||
#endif /* OBJECT_POOL_H */
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#define OBJECT_POOL_COMPACT_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include "object_pool.h"
|
||||
#include "object_pool_impl.h"
|
||||
|
||||
namespace MOT {
|
||||
#define PTR_MASK (((uint64_t)-1) << 10)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss 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.
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* object_pool_impl.cpp
|
||||
* Object pool implementation.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/storage/mot/core/src/memory/object_pool_impl.cpp
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "object_pool_impl.h"
|
||||
#include "object_pool.h"
|
||||
|
||||
namespace MOT {
|
||||
IMPLEMENT_CLASS_LOGGER(ObjAllocInterface, Memory)
|
||||
IMPLEMENT_CLASS_LOGGER(ObjPool, Memory)
|
||||
|
||||
ObjPoolPtr::ObjPoolPtr(ObjPool* target)
|
||||
{
|
||||
m_data.m_ptr = target;
|
||||
if (target != NULL)
|
||||
m_data.m_slice[LIST_PTR_SLICE_IX] = target->m_listCounter;
|
||||
}
|
||||
|
||||
ObjPoolPtr& ObjPoolPtr::operator=(ObjPool* right)
|
||||
{
|
||||
m_data.m_ptr = right;
|
||||
if (right != NULL)
|
||||
m_data.m_slice[LIST_PTR_SLICE_IX] = right->m_listCounter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjAllocInterface* ObjAllocInterface::GetObjPool(uint16_t size, bool local, uint8_t align)
|
||||
{
|
||||
ObjAllocInterface* result = NULL;
|
||||
if (local) {
|
||||
result = new (std::nothrow) LocalObjPool(size, align);
|
||||
} else {
|
||||
result = new (std::nothrow) GlobalObjPool(size, align);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
||||
"Allocate Object Pool",
|
||||
"Failed to allocate memory for %s object pool",
|
||||
local ? "local" : "global");
|
||||
} else if (!result->Initialize()) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
||||
"Allocate Object Pool",
|
||||
"Failed to pre-allocate memory for %s object pool",
|
||||
local ? "local" : "global");
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ObjAllocInterface::FreeObjPool(ObjAllocInterface** pool)
|
||||
{
|
||||
if (pool != NULL && *pool != NULL) {
|
||||
delete *pool;
|
||||
*pool = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ObjAllocInterface::~ObjAllocInterface()
|
||||
{
|
||||
ObjPool* p = m_objList;
|
||||
while (p != NULL) {
|
||||
ObjPool* tmp = p;
|
||||
p = p->m_next;
|
||||
ObjPool::DelObjPool(tmp, m_type, m_global);
|
||||
}
|
||||
}
|
||||
|
||||
inline MemBufferClass ObjAllocInterface::CalcBufferClass(uint16_t size)
|
||||
{
|
||||
int pool_size = sizeof(ObjPool) + NUM_OBJS * size;
|
||||
// 1KB has 11 bit set (starting from less significant)
|
||||
// we use 32 bit int for size, so first 1 bit will 32 - __builtin_clz(pool_size)
|
||||
// the buffer classes start from 1KB
|
||||
return MemBufferClassLowerBound(pool_size);
|
||||
}
|
||||
|
||||
void ObjAllocInterface::GetStats(PoolStatsSt& stats)
|
||||
{
|
||||
ObjPoolPtr p;
|
||||
|
||||
if (stats.m_type == PoolStatsT::POOL_STATS_ALL)
|
||||
p = m_objList;
|
||||
else
|
||||
p = m_nextFree;
|
||||
|
||||
stats.m_objSize = m_size;
|
||||
stats.m_poolGrossSize = (1024 * MemBufferClassToSizeKb(m_type));
|
||||
|
||||
if (p.Get()) {
|
||||
stats.m_perPoolTotalCount = p->m_totalCount;
|
||||
stats.m_perPoolOverhead = p->m_overheadBytes;
|
||||
stats.m_perPoolWaist = p->m_notUsedBytes;
|
||||
}
|
||||
while (p.Get() != NULL) {
|
||||
stats.m_poolCount++;
|
||||
if (p->m_totalCount == p->m_freeCount)
|
||||
stats.m_poolFreeCount++;
|
||||
stats.m_totalObjCount += p->m_totalCount;
|
||||
stats.m_freeObjCount += p->m_freeCount;
|
||||
if (stats.m_type == PoolStatsT::POOL_STATS_ALL)
|
||||
p = p->m_next;
|
||||
else
|
||||
p = p->m_objNext;
|
||||
}
|
||||
|
||||
if (stats.m_poolCount > 0)
|
||||
stats.m_fragmentationPercent = (int16_t)(stats.m_poolFreeCount * 100 / stats.m_poolCount);
|
||||
else
|
||||
stats.m_fragmentationPercent = 0;
|
||||
}
|
||||
|
||||
void ObjAllocInterface::PrintStats(PoolStatsSt& stats, const char* prefix, LogLevel level)
|
||||
{
|
||||
const char* hist_str = "";
|
||||
|
||||
MOT_LOG(level,
|
||||
"%s: type: %d, size: %d, pools: %u(%u), total objects: %lu, free objects: %lu"
|
||||
", overhead: %lu, waist: %lu"
|
||||
"\n%s",
|
||||
prefix,
|
||||
m_type,
|
||||
m_size,
|
||||
stats.m_poolCount,
|
||||
stats.m_poolFreeCount,
|
||||
stats.m_totalObjCount,
|
||||
stats.m_freeObjCount,
|
||||
stats.m_poolCount * stats.m_perPoolOverhead,
|
||||
stats.m_poolCount * stats.m_perPoolWaist,
|
||||
hist_str);
|
||||
}
|
||||
|
||||
void ObjAllocInterface::Print(const char* prefix, LogLevel level)
|
||||
{
|
||||
PoolStatsSt stats;
|
||||
|
||||
errno_t erc = memset_s(&stats, sizeof(PoolStatsSt), 0, sizeof(PoolStatsSt));
|
||||
securec_check(erc, "\0", "\0");
|
||||
stats.m_type = PoolStatsT::POOL_STATS_ALL;
|
||||
|
||||
GetStats(stats);
|
||||
PrintStats(stats, prefix, level);
|
||||
}
|
||||
} // namespace MOT
|
||||
|
|
@ -0,0 +1,541 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss 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.
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* object_pool_impl.h
|
||||
* Object pool implementation.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/storage/mot/core/src/memory/object_pool_impl.h
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef OBJECT_POOL_IMPL_H
|
||||
#define OBJECT_POOL_IMPL_H
|
||||
|
||||
#include <new>
|
||||
#include <atomic>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "global.h"
|
||||
#include "mot_atomic_ops.h"
|
||||
#include "utilities.h"
|
||||
#include "cycles.h"
|
||||
#include "thread_id.h"
|
||||
#include "mm_def.h"
|
||||
#include "mm_buffer_api.h"
|
||||
#include "mm_session_api.h"
|
||||
#include "memory_statistics.h"
|
||||
#include "mm_api.h"
|
||||
#include "spin_lock.h"
|
||||
|
||||
namespace MOT {
|
||||
#define MAX_THR_NUM 4096
|
||||
#define INITIAL_NUM_OBJPOOL 1
|
||||
#define NUM_OBJS (uint8_t)(255)
|
||||
#define NOT_VALID (uint8_t)(-1)
|
||||
#define G_THREAD_ID ((int16_t)MOTCurrThreadId)
|
||||
#define OBJ_INDEX_SIZE 1
|
||||
#define MEMORY_BARRIER asm volatile("" ::: "memory");
|
||||
|
||||
#define OBJ_RELEASE_START_NOMARK(ptr, size) \
|
||||
uint8_t* p = (uint8_t*)ptr; \
|
||||
uint8_t* oix_ptr = (p + size - 1); \
|
||||
uint8_t oix = *oix_ptr; \
|
||||
if (oix == NOT_VALID) { \
|
||||
printf("Detected double free of pointer or corruption: 0x%lx\n", (uint64_t)ptr); \
|
||||
MOTAbort((void*)ptr); \
|
||||
} \
|
||||
ObjPoolPtr op = (ObjPool*)(p - sizeof(ObjPool) - oix * size);
|
||||
|
||||
#define OBJ_RELEASE_MARK(ptr) (*(uint8_t*)ptr = NOT_VALID)
|
||||
|
||||
#define OBJ_RELEASE_START(ptr, size) \
|
||||
uint8_t* p = (uint8_t*)ptr; \
|
||||
uint8_t* oix_ptr = (p + size - 1); \
|
||||
uint8_t oix = *oix_ptr; \
|
||||
if (oix == NOT_VALID) { \
|
||||
printf("Detected double free of pointer or corruption: 0x%lx\n", (uint64_t)ptr); \
|
||||
MOTAbort(ptr); \
|
||||
} else { \
|
||||
if (!__sync_bool_compare_and_swap(oix_ptr, oix, NOT_VALID)) { \
|
||||
printf("Detected double free of pointer or corruption: 0x%lx\n", (uint64_t)ptr); \
|
||||
MOTAbort(ptr); \
|
||||
} \
|
||||
} \
|
||||
ObjPoolPtr op = (ObjPool*)(p - sizeof(ObjPool) - oix * size);
|
||||
|
||||
#define CAS(ptr, oldval, newval) \
|
||||
__sync_bool_compare_and_swap((uint64_t*)&ptr, *(uint64_t*)&(oldval), *(uint64_t*)&newval)
|
||||
|
||||
#define PUSH_NOLOCK(list, obj) \
|
||||
{ \
|
||||
obj->m_objNext = list; \
|
||||
list = obj; \
|
||||
}
|
||||
|
||||
#define POP_NOLOCK(list) \
|
||||
{ \
|
||||
if (list.Get() != nullptr) { \
|
||||
list = (list)->m_objNext; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PUSH(list, obj) \
|
||||
{ \
|
||||
++obj; \
|
||||
do { \
|
||||
obj->m_objNext = list; \
|
||||
} while (!CAS(list, obj->m_objNext, obj)); \
|
||||
}
|
||||
|
||||
#define POP(list, obj) \
|
||||
{ \
|
||||
do { \
|
||||
obj = list; \
|
||||
if (obj.Get() == nullptr) \
|
||||
break; \
|
||||
} while (!CAS(list, obj, obj->m_objNext)); \
|
||||
}
|
||||
|
||||
#define ADD_TO_LIST_NOLOCK(list, obj) \
|
||||
{ \
|
||||
obj->m_next = list; \
|
||||
if (list != nullptr) \
|
||||
list->m_prev = obj; \
|
||||
list = obj; \
|
||||
}
|
||||
|
||||
#define DEL_FROM_LIST_NOLOCK(list, obj) \
|
||||
{ \
|
||||
if (obj->m_prev != nullptr) { \
|
||||
obj->m_prev->m_next = obj->m_next; \
|
||||
} \
|
||||
if (obj->m_next != nullptr) { \
|
||||
obj->m_next->m_prev = obj->m_prev; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ADD_TO_LIST(list, obj) \
|
||||
{ \
|
||||
do { \
|
||||
obj->m_next = list; \
|
||||
} while (!CAS(list, obj->m_next, obj)); \
|
||||
if (likely(obj->m_next != nullptr)) \
|
||||
obj->m_next->m_prev = obj; \
|
||||
}
|
||||
|
||||
#define DEL_FROM_LIST(locker, list, obj) \
|
||||
{ \
|
||||
do { \
|
||||
if (list == obj) { \
|
||||
if (CAS(list, obj, obj->m_next)) { \
|
||||
obj->m_next = nullptr; \
|
||||
obj->m_prev = nullptr; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
locker.lock(); \
|
||||
DEL_FROM_LIST_NOLOCK(list, obj) \
|
||||
locker.unlock(); \
|
||||
} while (0); \
|
||||
}
|
||||
|
||||
typedef enum PoolAllocState { PAS_FIRST, PAS_EMPTY, PAS_NONE } PoolAllocStateT;
|
||||
|
||||
class ObjPool;
|
||||
|
||||
// DO NOT CHANGE ORDER OF THE MEMBERS
|
||||
typedef struct PACKED tagObjPoolSt {
|
||||
public:
|
||||
friend ObjPool;
|
||||
uint8_t m_nextFreeObj;
|
||||
|
||||
private:
|
||||
uint8_t m_fill1[7];
|
||||
|
||||
public:
|
||||
uint8_t m_objIndexArr[NUM_OBJS + 1];
|
||||
uint8_t m_nextOccupiedObj;
|
||||
|
||||
private:
|
||||
uint8_t m_fill2[7];
|
||||
|
||||
public:
|
||||
uint8_t m_data[0];
|
||||
} ObjPoolSt;
|
||||
|
||||
typedef enum PoolStatsType : uint8_t { POOL_STATS_ALL = 0, POOL_STATS_FREE } PoolStatsT;
|
||||
|
||||
typedef struct tagPoolStatsSt {
|
||||
PoolStatsT m_type;
|
||||
uint16_t m_objSize;
|
||||
uint16_t m_perPoolTotalCount;
|
||||
uint32_t m_poolCount;
|
||||
uint32_t m_poolFreeCount;
|
||||
uint64_t m_totalObjCount;
|
||||
uint64_t m_freeObjCount;
|
||||
uint64_t m_poolGrossSize;
|
||||
int16_t m_fragmentationPercent;
|
||||
uint32_t m_perPoolOverhead;
|
||||
uint32_t m_perPoolWaist;
|
||||
} PoolStatsSt;
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define LIST_PTR_SLICE_IX 3
|
||||
#else
|
||||
#define LIST_PTR_SLICE_IX 0
|
||||
#endif
|
||||
#define LIST_PTR_MASK 0xffffffffffff // usable address space is 48 bits
|
||||
|
||||
class PACKED ObjPoolPtr {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor for a NULL pointer.
|
||||
*/
|
||||
ObjPoolPtr()
|
||||
{
|
||||
m_data.m_ptr = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructs an objects on pre-allocated memory buffer.
|
||||
* @param target Address of an object.
|
||||
*/
|
||||
ObjPoolPtr(ObjPool* target);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
* @param other The object.
|
||||
*/
|
||||
ObjPoolPtr(ObjPoolPtr& other)
|
||||
{
|
||||
m_data.m_ptr = other.m_data.m_ptr;
|
||||
}
|
||||
|
||||
ObjPoolPtr(const ObjPoolPtr& other)
|
||||
{
|
||||
m_data.m_ptr = other.m_data.m_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a pointer to the managed object.
|
||||
* @return A pointer to the object.
|
||||
*/
|
||||
inline ObjPool* Get()
|
||||
{
|
||||
return (ObjPool*)(((uint64_t)m_data.m_ptr) & LIST_PTR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Member access operator implementation.
|
||||
* @return Retrieves a pointer to the managed object.
|
||||
*/
|
||||
inline ObjPool* operator->()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves a pointer to the managed object.
|
||||
* @return A pointer to the object.
|
||||
*/
|
||||
inline ObjPool* Get() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Member access operator implementation.
|
||||
* @return Retrieves a pointer to the managed object.
|
||||
*/
|
||||
inline ObjPool* operator->() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
inline void operator++();
|
||||
|
||||
ObjPoolPtr& operator=(const ObjPoolPtr& right)
|
||||
{
|
||||
m_data.m_ptr = right.m_data.m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjPoolPtr& operator=(ObjPool* right);
|
||||
|
||||
bool operator==(const ObjPoolPtr& right) const
|
||||
{
|
||||
return (m_data.m_ptr == right.m_data.m_ptr);
|
||||
}
|
||||
|
||||
bool operator==(ObjPoolPtr& right) const
|
||||
{
|
||||
return (m_data.m_ptr == right.m_data.m_ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor. Deallocates the object.
|
||||
*/
|
||||
~ObjPoolPtr()
|
||||
{}
|
||||
|
||||
private:
|
||||
union {
|
||||
ObjPool* m_ptr;
|
||||
uint16_t m_slice[4];
|
||||
} m_data;
|
||||
};
|
||||
|
||||
class ObjAllocInterface {
|
||||
public:
|
||||
friend class ObjPool;
|
||||
spin_lock m_listLock;
|
||||
ObjPool* m_objList;
|
||||
ObjPoolPtr m_nextFree;
|
||||
uint16_t m_size;
|
||||
uint16_t m_oixOffset;
|
||||
MemBufferClass m_type;
|
||||
bool m_global;
|
||||
|
||||
static ObjAllocInterface* GetObjPool(uint16_t size, bool local, uint8_t align = 8);
|
||||
static void FreeObjPool(ObjAllocInterface** pool);
|
||||
|
||||
explicit ObjAllocInterface(bool isGlobal) : m_global(isGlobal)
|
||||
{}
|
||||
|
||||
virtual ~ObjAllocInterface();
|
||||
|
||||
virtual bool Initialize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void* Alloc() = 0;
|
||||
template <typename T, class... Args>
|
||||
inline T* Alloc(Args&&... args)
|
||||
{
|
||||
void* buf = Alloc();
|
||||
if (unlikely(buf == nullptr))
|
||||
return nullptr;
|
||||
return new (buf) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
virtual void Release(void* ptr) = 0;
|
||||
template <typename T>
|
||||
inline void Release(T* obj)
|
||||
{
|
||||
if (likely(obj != nullptr)) {
|
||||
obj->~T();
|
||||
Release((void*)obj);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ClearThreadCache() = 0;
|
||||
virtual void ClearFreeCache() = 0;
|
||||
|
||||
void GetStats(PoolStatsSt& stats);
|
||||
void PrintStats(PoolStatsSt& stats, const char* prefix = "", LogLevel level = LogLevel::LL_DEBUG);
|
||||
void Print(const char* prefix, LogLevel level = LogLevel::LL_DEBUG);
|
||||
|
||||
protected:
|
||||
static MemBufferClass CalcBufferClass(uint16_t size);
|
||||
DECLARE_CLASS_LOGGER();
|
||||
};
|
||||
|
||||
// DO NOT CHANGE ORDER OF THE MEMBERS
|
||||
class PACKED ObjPool {
|
||||
public:
|
||||
ObjPool* m_next;
|
||||
ObjPool* m_prev;
|
||||
uint16_t m_freeCount;
|
||||
uint16_t m_totalCount;
|
||||
int16_t m_owner;
|
||||
uint16_t m_listCounter;
|
||||
ObjPoolPtr m_objNext;
|
||||
ObjAllocInterface* m_parent;
|
||||
int m_notUsedBytes;
|
||||
int m_overheadBytes;
|
||||
ObjPoolSt m_head;
|
||||
|
||||
ObjPool(uint16_t size, MemBufferClass type, ObjAllocInterface* app)
|
||||
{
|
||||
m_parent = app;
|
||||
m_owner = -1;
|
||||
m_objNext = nullptr;
|
||||
m_next = m_prev = nullptr;
|
||||
*(uint32_t*)(&m_head.m_fill1[3]) = 0xDEADBEEF;
|
||||
*(uint32_t*)(&m_head.m_fill2[3]) = 0xDEADBEEF;
|
||||
m_overheadBytes = sizeof(ObjPool);
|
||||
uint8_t* ptr = m_head.m_data;
|
||||
uint8_t* end = ptr + (1024 * MemBufferClassToSizeKb(type)) - sizeof(ObjPool);
|
||||
|
||||
m_freeCount = m_totalCount = (uint16_t)((end - m_head.m_data) / m_parent->m_size);
|
||||
uint8_t i = 0;
|
||||
for (; i < m_totalCount; i++) {
|
||||
m_head.m_objIndexArr[i] = i;
|
||||
ptr += m_parent->m_size;
|
||||
ptr[-1] = i;
|
||||
}
|
||||
for (; i < NUM_OBJS; i++) {
|
||||
m_head.m_objIndexArr[i] = NOT_VALID;
|
||||
}
|
||||
m_head.m_objIndexArr[i] = NOT_VALID;
|
||||
m_head.m_nextFreeObj = -1;
|
||||
m_head.m_nextOccupiedObj = m_totalCount - 1;
|
||||
m_overheadBytes += m_totalCount * OBJ_INDEX_SIZE;
|
||||
m_notUsedBytes = (int)(end - ptr);
|
||||
}
|
||||
|
||||
~ObjPool()
|
||||
{}
|
||||
|
||||
inline void AllocNoLock(void** ret, PoolAllocStateT* state)
|
||||
{
|
||||
uint8_t ix = ++(m_head.m_nextFreeObj);
|
||||
uint8_t oix = m_head.m_objIndexArr[ix];
|
||||
m_head.m_objIndexArr[ix] = NOT_VALID;
|
||||
*ret = (m_head.m_data + oix * m_parent->m_size);
|
||||
((uint8_t*)(*ret))[m_parent->m_oixOffset] = oix;
|
||||
--m_freeCount;
|
||||
if (m_freeCount == 0) {
|
||||
*state = PAS_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Alloc(void** ret, PoolAllocStateT* state)
|
||||
{
|
||||
uint8_t ix = ++(m_head.m_nextFreeObj);
|
||||
while (m_head.m_objIndexArr[ix] == NOT_VALID) {
|
||||
PAUSE
|
||||
}
|
||||
uint8_t oix = m_head.m_objIndexArr[ix];
|
||||
m_head.m_objIndexArr[ix] = NOT_VALID;
|
||||
*ret = (m_head.m_data + oix * m_parent->m_size);
|
||||
((uint8_t*)(*ret))[m_parent->m_oixOffset] = oix;
|
||||
uint16_t c = __sync_sub_and_fetch(&m_freeCount, 1);
|
||||
if (c == 0) {
|
||||
*state = PAS_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ReleaseNoLock(uint8_t oix, PoolAllocStateT* state)
|
||||
{
|
||||
++(m_head.m_nextOccupiedObj);
|
||||
m_head.m_objIndexArr[m_head.m_nextOccupiedObj] = oix;
|
||||
++m_freeCount;
|
||||
|
||||
if (m_freeCount == 1) {
|
||||
*state = PAS_FIRST;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Release(uint8_t oix, PoolAllocStateT* state)
|
||||
{
|
||||
uint8_t ix = __sync_add_and_fetch(&m_head.m_nextOccupiedObj, 1);
|
||||
m_head.m_objIndexArr[ix] = oix;
|
||||
uint16_t c = __sync_add_and_fetch(&m_freeCount, 1);
|
||||
|
||||
if (c == 1) {
|
||||
*state = PAS_FIRST;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static ObjPool* GetObjPool(uint16_t size, ObjAllocInterface* app, MemBufferClass type, bool global)
|
||||
{
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t start_time = GetSysClock();
|
||||
#endif
|
||||
#ifndef MEM_ACTIVE
|
||||
void* p = (void*)malloc((1024 * MemBufferClassToSizeKb(type)));
|
||||
#else
|
||||
void* p;
|
||||
|
||||
if (global == true) {
|
||||
p = MemBufferAllocGlobal(type);
|
||||
} else {
|
||||
#ifdef MEM_SESSION_ACTIVE
|
||||
uint32_t bufferSize = 1024 * MemBufferClassToSizeKb(type);
|
||||
p = MemSessionAlloc(bufferSize);
|
||||
if (p) {
|
||||
DetailedMemoryStatisticsProvider::m_provider->AddLocalBuffersUsed(MOTCurrentNumaNodeId, type);
|
||||
}
|
||||
#else
|
||||
p = MemBufferAllocLocal(type);
|
||||
#endif // MEM_SESSION_ACTIVE
|
||||
}
|
||||
#endif // MEM_ACTIVE
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t end_time = GetSysClock();
|
||||
MemoryStatisticsProvider::m_provider->AddMallocTime(
|
||||
CpuCyclesLevelTime::CyclesToNanoseconds(end_time - start_time));
|
||||
#endif
|
||||
ObjPool* o = nullptr;
|
||||
if (p) {
|
||||
o = new (p) ObjPool(size, type, app);
|
||||
} else {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
||||
"N/A",
|
||||
"Failed to allocate %s %s buffer for object pool",
|
||||
MemBufferClassToString(type),
|
||||
global ? "global" : "local");
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static void DelObjPool(void* ptr, MemBufferClass type, bool global)
|
||||
{
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t start_time = GetSysClock();
|
||||
#endif
|
||||
#ifndef MEM_ACTIVE
|
||||
free(ptr);
|
||||
#else
|
||||
if (global == true) {
|
||||
MemBufferFreeGlobal(ptr, type);
|
||||
} else {
|
||||
#ifdef MEM_SESSION_ACTIVE
|
||||
MemSessionFree(ptr);
|
||||
DetailedMemoryStatisticsProvider::m_provider->AddLocalBuffersFreed(MOTCurrentNumaNodeId, type);
|
||||
#else
|
||||
MemBufferFreeLocal(ptr, type);
|
||||
#endif // MEM_SESSION_ACTIVE
|
||||
}
|
||||
#endif // MEM_ACTIVE
|
||||
#ifdef TEST_STAT_ALLOC
|
||||
uint64_t end_time = GetSysClock();
|
||||
MemoryStatisticsProvider::m_provider->AddFreeTime(
|
||||
CpuCyclesLevelTime::CyclesToNanoseconds(end_time - start_time));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
DECLARE_CLASS_LOGGER();
|
||||
};
|
||||
|
||||
inline void ObjPoolPtr::operator++()
|
||||
{
|
||||
Get()->m_listCounter++;
|
||||
m_data.m_slice[LIST_PTR_SLICE_IX] = Get()->m_listCounter;
|
||||
MEMORY_BARRIER;
|
||||
}
|
||||
} // namespace MOT
|
||||
|
||||
#endif /* OBJECT_POOL_IMPL_H */
|
||||
|
|
@ -137,10 +137,7 @@ public:
|
|||
* @brief Retrieves the currently iterated primary sentinel.
|
||||
* @return The primary sentinel.
|
||||
*/
|
||||
virtual Sentinel* GetPrimarySentinel() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual Sentinel* GetPrimarySentinel() const = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -111,18 +111,12 @@ public:
|
|||
m_keyLen = newLen;
|
||||
}
|
||||
|
||||
inline bool CpKey(const uint8_t* buf, uint16_t len)
|
||||
inline void CpKey(const uint8_t* buf, uint16_t len)
|
||||
{
|
||||
if (unlikely(len > m_keyLen)) {
|
||||
MOT_LOG_ERROR("Key length is too big");
|
||||
return false;
|
||||
} else {
|
||||
errno_t erc = memcpy_s(const_cast<uint8_t*>(m_keyBuf), m_keyLen, buf, len);
|
||||
securec_check(erc, "\0", "\0");
|
||||
}
|
||||
MOT_ASSERT(len <= m_keyLen);
|
||||
errno_t erc = memcpy_s(const_cast<uint8_t*>(m_keyBuf), m_keyLen, buf, len);
|
||||
securec_check(erc, "\0", "\0");
|
||||
m_keyLen = len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -168,9 +162,9 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool CpKey(const Key& key)
|
||||
inline void CpKey(const Key& key)
|
||||
{
|
||||
return CpKey(key.GetKeyBuf(), key.GetKeyLength());
|
||||
CpKey(key.GetKeyBuf(), key.GetKeyLength());
|
||||
}
|
||||
|
||||
void PrintKey() const
|
||||
|
|
|
|||
|
|
@ -581,9 +581,11 @@ Row* Table::RemoveKeyFromIndex(Row* row, Sentinel* sentinel, uint64_t tid, GcMan
|
|||
MOT_ASSERT(currSentinel->GetCounter() == 0);
|
||||
#endif
|
||||
currSentinel = ix->IndexRemove(&key, tid);
|
||||
MOT_ASSERT(currSentinel == sentinel);
|
||||
if (likely(gc != nullptr)) {
|
||||
if (ix->GetIndexOrder() == IndexOrder::INDEX_ORDER_PRIMARY) {
|
||||
OutputRow = currSentinel->GetData();
|
||||
MOT_ASSERT(OutputRow != nullptr);
|
||||
gc->GcRecordObject(ix->GetIndexId(), currSentinel, nullptr, Index::SentinelDtor, SENTINEL_SIZE(ix));
|
||||
gc->GcRecordObject(ix->GetIndexId(), OutputRow, nullptr, Row::RowDtor, ROW_SIZE_FROM_POOL(this));
|
||||
} else {
|
||||
|
|
@ -1108,7 +1110,10 @@ void Table::Deserialize(const char* in)
|
|||
CommonColumnMeta col;
|
||||
for (uint32_t i = 0; i < saveFieldCount; i++) {
|
||||
dataIn = DesrializeMeta(dataIn, col);
|
||||
AddColumn(col.m_name, col.m_size, col.m_type, col.m_isNotNull);
|
||||
if (AddColumn(col.m_name, col.m_size, col.m_type, col.m_isNotNull) != RC_OK) {
|
||||
MOT_LOG_ERROR("Table::deserialize - failed to add column %u", i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!InitRowPool()) {
|
||||
|
|
|
|||
|
|
@ -133,7 +133,6 @@ int CheckpointWorkerPool::Checkpoint(Buffer* buffer, Sentinel* sentinel, int fd,
|
|||
|
||||
if (mainRow != nullptr) {
|
||||
bool headerLocked = sentinel->TryLock(threadId);
|
||||
|
||||
if (headerLocked == false) {
|
||||
if (mainRow->GetTwoPhaseMode() == true) {
|
||||
MOT_LOG_DEBUG("checkpoint: row %p is 2pc", mainRow);
|
||||
|
|
@ -209,8 +208,9 @@ int CheckpointWorkerPool::Checkpoint(Buffer* buffer, Sentinel* sentinel, int fd,
|
|||
sentinel->SetStable(nullptr);
|
||||
}
|
||||
|
||||
if (mainRow != nullptr)
|
||||
if (mainRow != nullptr) {
|
||||
sentinel->Release();
|
||||
}
|
||||
return wrote;
|
||||
}
|
||||
|
||||
|
|
@ -516,8 +516,7 @@ CheckpointWorkerPool::ErrCodes CheckpointWorkerPool::WriteTableDataFile(Table* t
|
|||
curSegLen += table->GetTupleSize() + sizeof(CheckpointUtils::EntryHeader);
|
||||
if (m_checkpointSegsize > 0 && curSegLen >= m_checkpointSegsize) {
|
||||
if (buffer->Size() > 0) { // there is data in the buffer that needs to be written
|
||||
if (CheckpointUtils::WriteFile(fd, (char*)buffer->Data(), buffer->Size()) !=
|
||||
buffer->Size()) {
|
||||
if (CheckpointUtils::WriteFile(fd, (char*)buffer->Data(), buffer->Size()) != buffer->Size()) {
|
||||
MOT_LOG_ERROR(
|
||||
"CheckpointWorkerPool::WriteTableDataFile: failed to write data file %u for table %u",
|
||||
maxSegId,
|
||||
|
|
|
|||
|
|
@ -99,8 +99,7 @@ private:
|
|||
void WorkerFunc();
|
||||
|
||||
/**
|
||||
* @brief Appends checkpoint data into a buffer. the buffer will
|
||||
* be flushed in case it is full
|
||||
* @brief Appends a row to the buffer. The buffer will be flushed in case it is full.
|
||||
* @param buffer The buffer to fill.
|
||||
* @param row The row to write.
|
||||
* @param fd The file descriptor to write to.
|
||||
|
|
@ -109,14 +108,13 @@ private:
|
|||
bool Write(Buffer* buffer, Row* row, int fd);
|
||||
|
||||
/**
|
||||
* @brief Checkpoints a row, according to whether a stable version
|
||||
* exists or not.
|
||||
* @brief Checkpoints a row, according to whether a stable version exists or not.
|
||||
* @param buffer The buffer to fill.
|
||||
* @param sentinel The sentinel that holds to row.
|
||||
* @param fd The file descriptor to write to.
|
||||
* @param threadId The thread id.
|
||||
* @param isDeleted The row delete status.
|
||||
* @return Int equal to -1 on error, 0 if nothing was written and 1 if the row was written.
|
||||
* @return -1 on error, 0 if nothing was written and 1 if the row was written.
|
||||
*/
|
||||
int Checkpoint(Buffer* buffer, Sentinel* sentinel, int fd, uint16_t threadId, bool& isDeleted);
|
||||
|
||||
|
|
|
|||
|
|
@ -290,6 +290,8 @@ inline void Prefetch(const void* ptr)
|
|||
#define MAX_KEY_COLUMNS (10U)
|
||||
#define MAX_TUPLE_SIZE 16384 // in bytes
|
||||
|
||||
#define MAX_VARCHAR_LEN 1024
|
||||
|
||||
// Do not change this. Masstree assumes 15 for optimization purposes
|
||||
#define BTREE_ORDER 15
|
||||
|
||||
|
|
|
|||
|
|
@ -945,9 +945,8 @@ uint64_t MOTEngine::GetHardMemoryLimitBytes()
|
|||
return g_memGlobalCfg.m_maxGlobalMemoryMb * MEGA_BYTE;
|
||||
}
|
||||
|
||||
bool MOTEngine::CheckPolicies()
|
||||
void MOTEngine::CheckPolicies()
|
||||
{
|
||||
bool result = false;
|
||||
std::ifstream inFile;
|
||||
inFile.open("/proc/sys/kernel/numa_balancing");
|
||||
|
||||
|
|
@ -955,8 +954,6 @@ bool MOTEngine::CheckPolicies()
|
|||
if ((inFile >> flagValue) && (flagValue != 0)) {
|
||||
MOT_LOG_WARN(
|
||||
"NUMA policy in the system is set to automatic. (/proc/sys/kernel/numa_balancing is %u)", flagValue);
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace MOT
|
||||
|
|
|
|||
|
|
@ -593,9 +593,8 @@ private:
|
|||
/**
|
||||
* @brief This function is a checker of OS policies to locate if something is potentially not configured properly.
|
||||
* System will proceed but print a message.
|
||||
* @return True if the system is configured properly.
|
||||
*/
|
||||
bool CheckPolicies();
|
||||
void CheckPolicies();
|
||||
|
||||
// logger macro
|
||||
DECLARE_CLASS_LOGGER();
|
||||
|
|
|
|||
|
|
@ -79,9 +79,10 @@ bool CheckpointRecovery::Recover()
|
|||
|
||||
int taskFillStat = FillTasksFromMapFile();
|
||||
if (taskFillStat < 0) {
|
||||
MOT_LOG_INFO("CheckpointRecovery:: failed to read map file");
|
||||
return false; // error was already set
|
||||
} else if (taskFillStat == 0) { // fresh install
|
||||
MOT_LOG_ERROR("CheckpointRecovery:: failed to read map file");
|
||||
return false;
|
||||
} else if (taskFillStat == 0) {
|
||||
// fresh install
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -125,13 +126,16 @@ bool CheckpointRecovery::Recover()
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!RecoverInProcessTxns()) {
|
||||
MOT_LOG_ERROR("Failed to recover the in-process transactions from the checkpoint");
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the current valid id in the checkpoint manager in case
|
||||
// we will need to retrieve it before a new checkpoint is created
|
||||
/*
|
||||
* Set the current valid id in the checkpoint manager in case
|
||||
* we will need to retrieve it before a new checkpoint is created.
|
||||
*/
|
||||
engine->GetCheckpointManager()->SetId(m_checkpointId);
|
||||
|
||||
MOT_LOG_INFO("Checkpoint Recovery: finished recovering %lu tables from checkpoint id: %lu",
|
||||
|
|
|
|||
|
|
@ -71,13 +71,24 @@ bool RecoveryManager::RecoverDbStart()
|
|||
MOT_LOG_INFO("Starting MOT recovery");
|
||||
|
||||
if (m_recoverFromCkptDone) {
|
||||
/*
|
||||
* This is switchover case.
|
||||
* In case of CASCADE switchover (CASCADE node switchover with STANDBY node), we need to
|
||||
* set the correct m_lsn to make sure that we skip any redo which are already replayed.
|
||||
* After switchover, envelope will start sync from the previous ckpt position.
|
||||
* In MOT engine, we should skip any redo before m_lastReplayLsn.
|
||||
*/
|
||||
if (m_lsn < m_lastReplayLsn) {
|
||||
m_lsn = m_lastReplayLsn;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_checkpointRecovery.Recover()) {
|
||||
return false;
|
||||
}
|
||||
SetLsn(m_checkpointRecovery.GetLsn());
|
||||
|
||||
m_lsn = m_checkpointRecovery.GetLsn();
|
||||
m_recoverFromCkptDone = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -302,7 +313,7 @@ bool RecoveryManager::LogStats::FindIdx(uint64_t tableId, uint64_t& id)
|
|||
{
|
||||
id = m_numEntries;
|
||||
std::map<uint64_t, int>::iterator it;
|
||||
m_slock.lock();
|
||||
std::lock_guard<spin_lock> lock(m_slock);
|
||||
it = m_idToIdx.find(tableId);
|
||||
if (it == m_idToIdx.end()) {
|
||||
Entry* newEntry = new (std::nothrow) Entry(tableId);
|
||||
|
|
@ -315,7 +326,6 @@ bool RecoveryManager::LogStats::FindIdx(uint64_t tableId, uint64_t& id)
|
|||
} else {
|
||||
id = it->second;
|
||||
}
|
||||
m_slock.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -481,7 +491,7 @@ bool RecoveryManager::IsTransactionIdCommitted(uint64_t xid)
|
|||
|
||||
bool RecoveryManager::IsRecoveryMemoryLimitReached(uint32_t numThreads)
|
||||
{
|
||||
uint64_t memoryRequiredBytes = numThreads * MEM_CHUNK_SIZE_MB * MEGA_BYTE;
|
||||
uint64_t memoryRequiredBytes = (uint64_t)numThreads * MEM_CHUNK_SIZE_MB * MEGA_BYTE;
|
||||
if (MOTEngine::GetInstance()->GetCurrentMemoryConsumptionBytes() + memoryRequiredBytes >=
|
||||
MOTEngine::GetInstance()->GetHardMemoryLimitBytes()) {
|
||||
MOT_LOG_WARN("IsRecoveryMemoryLimitReached: recovery memory limit reached "
|
||||
|
|
|
|||
|
|
@ -341,11 +341,6 @@ private:
|
|||
*/
|
||||
void ApplySurrogate();
|
||||
|
||||
void SetLsn(uint64_t lsn)
|
||||
{
|
||||
m_lsn = lsn;
|
||||
}
|
||||
|
||||
bool m_initialized;
|
||||
|
||||
bool m_recoverFromCkptDone;
|
||||
|
|
|
|||
|
|
@ -40,10 +40,12 @@ TypedStatisticsGenerator<ThreadStatistics, EmptyGlobalStatistics> SystemStatisti
|
|||
SystemStatisticsProvider* SystemStatisticsProvider::m_provider = nullptr;
|
||||
|
||||
SystemStatisticsProvider::SystemStatisticsProvider()
|
||||
: StatisticsProvider("System", &m_generator, GetGlobalConfiguration().m_enableSystemStatistics, true)
|
||||
{
|
||||
SnapshotCpuStats(m_lastTotalUser, m_lastTotalUserLow, m_lastTotalSys, m_lastTotalIdle);
|
||||
}
|
||||
: StatisticsProvider("System", &m_generator, GetGlobalConfiguration().m_enableSystemStatistics, true),
|
||||
m_lastTotalUser(0),
|
||||
m_lastTotalUserLow(0),
|
||||
m_lastTotalSys(0),
|
||||
m_lastTotalIdle(0)
|
||||
{}
|
||||
|
||||
void SystemStatisticsProvider::RegisterProvider()
|
||||
{
|
||||
|
|
@ -71,14 +73,22 @@ bool SystemStatisticsProvider::CreateInstance()
|
|||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_OOM, "Load Statistics", "Failed to allocate memory for System Statistics Provider, aborting");
|
||||
} else {
|
||||
result = m_provider->Initialize();
|
||||
if (!result) {
|
||||
if (!m_provider->Initialize()) {
|
||||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_INTERNAL, "Load Statistics", "Failed to initialize System Statistics Provider, aborting");
|
||||
delete m_provider;
|
||||
m_provider = nullptr;
|
||||
} else {
|
||||
m_provider->RegisterProvider();
|
||||
result = m_provider->SnapshotInitialMetrics();
|
||||
if (!result) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
||||
"Load Statistics",
|
||||
"Failed to take initial metrics snapshot in System Statistics Provider, aborting");
|
||||
delete m_provider;
|
||||
m_provider = nullptr;
|
||||
} else {
|
||||
m_provider->RegisterProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -100,6 +110,11 @@ SystemStatisticsProvider& SystemStatisticsProvider::GetInstance()
|
|||
return *m_provider;
|
||||
}
|
||||
|
||||
bool SystemStatisticsProvider::SnapshotInitialMetrics()
|
||||
{
|
||||
return SnapshotCpuStats(m_lastTotalUser, m_lastTotalUserLow, m_lastTotalSys, m_lastTotalIdle);
|
||||
}
|
||||
|
||||
void SystemStatisticsProvider::OnConfigChange()
|
||||
{
|
||||
if (m_enable != GetGlobalConfiguration().m_enableSystemStatistics) {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ public:
|
|||
*/
|
||||
static SystemStatisticsProvider& GetInstance();
|
||||
|
||||
/** @brief Takes an initial snapshot of monitored system metrics. */
|
||||
bool SnapshotInitialMetrics();
|
||||
|
||||
/**
|
||||
* @brief Derives classes should react to a notification that configuration changed. New
|
||||
* configuration is accessible via the ConfigManager.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "../storage/table.h" // explicit path in order to solve collision with B header file with the same name
|
||||
#include "table.h"
|
||||
#include "mot_engine.h"
|
||||
#include "redo_log_writer.h"
|
||||
#include "sentinel.h"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include "../storage/table.h"
|
||||
#include "table.h"
|
||||
#include "row.h"
|
||||
#include "txn.h"
|
||||
#include "txn_access.h"
|
||||
|
|
@ -450,6 +450,17 @@ RC TxnAccess::AccessLookup(const AccessType type, Sentinel* const originalSentin
|
|||
// Filter rows
|
||||
switch (curr_acc->m_type) {
|
||||
case AccessType::RD:
|
||||
if (m_txnManager->GetTxnIsoLevel() == READ_COMMITED) {
|
||||
// If Cached row is not valid, remove it!!
|
||||
if (type == RD and curr_acc->m_stmtCount != m_txnManager->GetStmtCount()) {
|
||||
auto it = m_rowsSet->find(curr_acc->m_origSentinel);
|
||||
MOT_ASSERT(it != m_rowsSet->end());
|
||||
m_rowsSet->erase(it);
|
||||
ReleaseAccess(curr_acc);
|
||||
return RC::RC_LOCAL_ROW_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AccessType::RD_FOR_UPDATE:
|
||||
case AccessType::WR:
|
||||
break;
|
||||
|
|
@ -525,11 +536,7 @@ Row* TxnAccess::AddInsertToLocalAccess(Sentinel* org_sentinel, Row* org_row, RC&
|
|||
auto search = m_rowsSet->find(org_sentinel);
|
||||
if (likely(search == m_rowsSet->end())) {
|
||||
if (isUpgrade == true) {
|
||||
if (org_sentinel->IsPrimaryIndex()) {
|
||||
curr_access = GetNewRowAccess(org_sentinel->GetData(), INS, rc);
|
||||
} else {
|
||||
curr_access = GetNewRowAccess(org_row, INS, rc);
|
||||
}
|
||||
curr_access = GetNewRowAccess(org_sentinel->GetData(), INS, rc);
|
||||
// Check if draft is valid
|
||||
if (curr_access == nullptr) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public:
|
|||
{}
|
||||
|
||||
inline RedoLogBuffer(uint32_t size)
|
||||
: m_bufferSize(size), m_nextFree(sizeof(uint32_t)), m_allocated(false), m_next(nullptr)
|
||||
: m_bufferSize(size), m_nextFree(sizeof(uint32_t)), m_buffer(nullptr), m_allocated(false), m_next(nullptr)
|
||||
{
|
||||
if (size == 0) {
|
||||
size = REDO_DEFAULT_BUFFER_SIZE;
|
||||
|
|
|
|||
|
|
@ -38,20 +38,18 @@ ENGINE_INC = $(top_builddir)/src/gausskernel/storage/mot/core/src
|
|||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJ_DIR = ../obj
|
||||
OBJS = $(OBJ_DIR)/mot_fdw.o $(OBJ_DIR)/mot_internal.o $(OBJ_DIR)/mot_fdw_xlog.o $(OBJ_DIR)/mot_match_index.o
|
||||
OBJS = $(OBJ_DIR)/mot_fdw.o $(OBJ_DIR)/mot_internal.o $(OBJ_DIR)/mot_fdw_xlog.o $(OBJ_DIR)/mot_match_index.o $(OBJ_DIR)/mot_fdw_error.o
|
||||
|
||||
DATA = mot_fdw.control mot_fdw--1.0.sql
|
||||
|
||||
DEPS := $(OBJ_DIR)/mot_fdw.d $(OBJ_DIR)/mot_internal.d $(OBJ_DIR)/mot_fdx_xlog.d $(OBJ_DIR)/mot_match_index.d
|
||||
DEPS := $(OBJ_DIR)/mot_fdw.d $(OBJ_DIR)/mot_internal.d $(OBJ_DIR)/mot_fdx_xlog.d $(OBJ_DIR)/mot_match_index.d $(OBJ_DIR)/mot_fdw_error.d
|
||||
|
||||
# Shared library stuff
|
||||
include $(top_srcdir)/src/gausskernel/common.mk
|
||||
override CXXFLAGS += -DMOT_SECURE -I$(top_builddir)/src/gausskernel/storage/mot/jit_exec/src -I$(top_builddir)/src/gausskernel/storage/mot/fdw_adapter/src -I$(ENGINE_INC) -I$(ENGINE_INC)/storage -I$(ENGINE_INC)/system -I$(ENGINE_INC)/memory -I$(ENGINE_INC)/memory/garbage_collector
|
||||
override CXXFLAGS += -I$(ENGINE_INC)/infra -I$(ENGINE_INC)/infra/config -I$(ENGINE_INC)/infra/containers -I$(ENGINE_INC)/infra/stats -I$(ENGINE_INC)/infra/synchronization -I$(ENGINE_INC)/concurrency_control -I$(ENGINE_INC)/storage/index -I$(ENGINE_INC)/system/transaction -I$(ENGINE_INC)/system/common -I$(ENGINE_INC)/system/statistics -I$(ENGINE_INC)/system/transaction_logger -I$(ENGINE_INC)/system/transaction_logger/asynchronous_redo_log -I$(ENGINE_INC)/system/transaction_logger/synchronous_redo_log -I$(ENGINE_INC)/system/transaction_logger/group_synchronous_redo_log -I$(ENGINE_INC)/system/checkpoint -I$(ENGINE_INC)/system/recovery -I$(ENGINE_INC)/utils
|
||||
|
||||
ifeq ($(CC_VERSION), 8.2.0)
|
||||
override CXXFLAGS += -faligned-new
|
||||
endif
|
||||
override CXXFLAGS += -faligned-new
|
||||
|
||||
$(OBJS): | buildrepo
|
||||
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ private:
|
|||
memCfg.format("%" PRIu64 " MB", newLocalMemoryMb);
|
||||
result = AddExtStringConfigItem("", "max_mot_local_memory", memCfg.c_str());
|
||||
}
|
||||
if (result) {
|
||||
if (result && (motCfg.m_sessionLargeBufferStoreSizeMB != newSessionLargeStoreMemoryMb)) {
|
||||
memCfg.format("%" PRIu64 " MB", newSessionLargeStoreMemoryMb);
|
||||
result = AddExtStringConfigItem("", "session_large_buffer_store_size", memCfg.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
#include "foreign/fdwapi.h"
|
||||
#include "foreign/foreign.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "optimizer/cost.h"
|
||||
|
|
@ -189,22 +188,6 @@ static int MOTGetFdwType()
|
|||
return MOT_ORC;
|
||||
}
|
||||
|
||||
static inline void BitmapDeSerialize(uint8_t* bitmap, int16_t len, ListCell** cell)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
bitmap[i] = (uint8_t)((Const*)lfirst(*cell))->constvalue;
|
||||
*cell = lnext(*cell);
|
||||
}
|
||||
}
|
||||
|
||||
static inline List* BitmapSerialize(List* result, uint8_t* bitmap, int16_t len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
result = lappend(result, makeConst(INT1OID, -1, InvalidOid, 1, Int8GetDatum(bitmap[i]), false, true));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MOTRecover()
|
||||
{
|
||||
if (!MOTAdaptor::m_initialized) {
|
||||
|
|
@ -1035,7 +1018,6 @@ static TupleTableSlot* MOTIterateForeignScan(ForeignScanState* node)
|
|||
}
|
||||
CleanQueryStatesOnError(festate->m_currTxn);
|
||||
report_pg_error(rc,
|
||||
festate->m_currTxn,
|
||||
(void*)(festate->m_currTxn->m_errIx != nullptr ? festate->m_currTxn->m_errIx->GetName().c_str()
|
||||
: "unknown"),
|
||||
(void*)festate->m_currTxn->m_errMsgBuf);
|
||||
|
|
@ -1083,7 +1065,6 @@ static TupleTableSlot* MOTIterateForeignScan(ForeignScanState* node)
|
|||
|
||||
CleanQueryStatesOnError(festate->m_currTxn);
|
||||
report_pg_error(rc,
|
||||
festate->m_currTxn,
|
||||
(void*)(festate->m_currTxn->m_errIx != NULL ? festate->m_currTxn->m_errIx->GetName().c_str()
|
||||
: "unknown"),
|
||||
(void*)festate->m_currTxn->m_errMsgBuf);
|
||||
|
|
@ -1410,7 +1391,7 @@ static TupleTableSlot* MOTExecForeignInsert(
|
|||
fdwState->m_table = fdwState->m_currTxn->GetTableByExternalId(RelationGetRelid(resultRelInfo->ri_RelationDesc));
|
||||
if (fdwState->m_table == nullptr) {
|
||||
pfree(fdwState);
|
||||
report_pg_error(MOT::RC_TABLE_NOT_FOUND, fdwState->m_currTxn);
|
||||
report_pg_error(MOT::RC_TABLE_NOT_FOUND);
|
||||
return nullptr;
|
||||
}
|
||||
fdwState->m_numAttrs = RelationGetNumberOfAttributes(resultRelInfo->ri_RelationDesc);
|
||||
|
|
@ -1437,7 +1418,6 @@ static TupleTableSlot* MOTExecForeignInsert(
|
|||
elog(DEBUG2, "Abort parent transaction from MOT insert, id %lu", fdwState->m_txnId);
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(rc,
|
||||
fdwState->m_currTxn,
|
||||
(void*)(fdwState->m_currTxn->m_errIx != nullptr ? fdwState->m_currTxn->m_errIx->GetName().c_str()
|
||||
: "unknown"),
|
||||
(void*)fdwState->m_currTxn->m_errMsgBuf);
|
||||
|
|
@ -1470,14 +1450,14 @@ static TupleTableSlot* MOTExecForeignUpdate(
|
|||
planSlot->tts_nvalid,
|
||||
(planSlot->tts_isnull[num] ? "NULL" : "NOT NULL"));
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(MOT::RC_ERROR, fdwState->m_currTxn);
|
||||
report_pg_error(MOT::RC_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (currRow == nullptr) {
|
||||
elog(ERROR, "MOTExecForeignUpdate failed to fetch row");
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(((rc == MOT::RC_OK) ? MOT::RC_ERROR : rc), fdwState->m_currTxn);
|
||||
report_pg_error(((rc == MOT::RC_OK) ? MOT::RC_ERROR : rc));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -1496,7 +1476,6 @@ static TupleTableSlot* MOTExecForeignUpdate(
|
|||
elog(DEBUG2, "Abort parent transaction from MOT update, id %lu", fdwState->m_txnId);
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(rc,
|
||||
fdwState->m_currTxn,
|
||||
(void*)(fdwState->m_currTxn->m_errIx != nullptr ? fdwState->m_currTxn->m_errIx->GetName().c_str()
|
||||
: "unknown"),
|
||||
(void*)fdwState->m_currTxn->m_errMsgBuf);
|
||||
|
|
@ -1524,7 +1503,7 @@ static TupleTableSlot* MOTExecForeignDelete(
|
|||
planSlot->tts_nvalid,
|
||||
(planSlot->tts_isnull[num] ? "NULL" : "NOT NULL"));
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(MOT::RC_ERROR, fdwState->m_currTxn);
|
||||
report_pg_error(MOT::RC_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -1535,7 +1514,7 @@ static TupleTableSlot* MOTExecForeignDelete(
|
|||
}
|
||||
elog(ERROR, "MOTExecForeignDelete failed to fetch row");
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(((rc == MOT::RC_OK) ? MOT::RC_ERROR : rc), fdwState->m_currTxn);
|
||||
report_pg_error(((rc == MOT::RC_OK) ? MOT::RC_ERROR : rc));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -1553,7 +1532,6 @@ static TupleTableSlot* MOTExecForeignDelete(
|
|||
elog(DEBUG2, "Abort parent transaction from MOT delete, id %lu", fdwState->m_txnId);
|
||||
CleanQueryStatesOnError(fdwState->m_currTxn);
|
||||
report_pg_error(rc,
|
||||
fdwState->m_currTxn,
|
||||
(void*)(fdwState->m_currTxn->m_errIx != nullptr ? fdwState->m_currTxn->m_errIx->GetName().c_str()
|
||||
: "unknown"),
|
||||
(void*)fdwState->m_currTxn->m_errMsgBuf);
|
||||
|
|
@ -1692,7 +1670,7 @@ static void MOTXactCallback(XactEvent event, void* arg)
|
|||
// commit this transaction. So we need to save the prepared transaction for further instructions from
|
||||
// CN or gs_clean. If we failed to save it, it's a panic situation.
|
||||
report_pg_error(
|
||||
MOT::RC_PANIC, txn, (char*)"Failed to save prepared transaction data (FailedCommitPrepared)");
|
||||
MOT::RC_PANIC, (char*)"Failed to save prepared transaction data (FailedCommitPrepared)");
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
|
|
@ -1903,7 +1881,7 @@ static void MOTTruncateForeignTable(TruncateStmt* stmt, Relation rel)
|
|||
errmodule(MOD_MOT),
|
||||
errmsg("A checkpoint is in progress - cannot truncate table.")));
|
||||
} else {
|
||||
report_pg_error(rc, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
report_pg_error(rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1985,129 +1963,6 @@ static void InitMOTHandler()
|
|||
}
|
||||
}
|
||||
|
||||
MOTFdwStateSt* InitializeFdwState(void* fdwState, List** fdwExpr, uint64_t exTableID)
|
||||
{
|
||||
MOTFdwStateSt* state = (MOTFdwStateSt*)palloc0(sizeof(MOTFdwStateSt));
|
||||
List* values = (List*)fdwState;
|
||||
ListCell* cell = list_head(values);
|
||||
|
||||
state->m_allocInScan = true;
|
||||
state->m_cmdOper = (CmdType)((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_order = (SORTDIR_ENUM)((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_hasForUpdate = (bool)((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_foreignTableId = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_numAttrs = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_ctidNum = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_numExpr = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
|
||||
int len = BITMAP_GETLEN(state->m_numAttrs);
|
||||
state->m_attrsUsed = (uint8_t*)palloc0(len);
|
||||
state->m_attrsModified = (uint8_t*)palloc0(len);
|
||||
BitmapDeSerialize(state->m_attrsUsed, len, &cell);
|
||||
|
||||
if (cell != NULL) {
|
||||
state->m_bestIx = &state->m_bestIxBuf;
|
||||
state->m_bestIx->Deserialize(cell, exTableID);
|
||||
}
|
||||
|
||||
if (fdwExpr != NULL && *fdwExpr != NULL) {
|
||||
ListCell* c = NULL;
|
||||
int i = 0;
|
||||
|
||||
// divide fdw expr to param list and original expr
|
||||
state->m_remoteCondsOrig = NULL;
|
||||
|
||||
foreach (c, *fdwExpr) {
|
||||
if (i < state->m_numExpr) {
|
||||
i++;
|
||||
continue;
|
||||
} else {
|
||||
state->m_remoteCondsOrig = lappend(state->m_remoteCondsOrig, lfirst(c));
|
||||
}
|
||||
}
|
||||
|
||||
*fdwExpr = list_truncate(*fdwExpr, state->m_numExpr);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void* SerializeFdwState(MOTFdwStateSt* state)
|
||||
{
|
||||
List* result = NULL;
|
||||
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_cmdOper), false, true));
|
||||
result = lappend(result, makeConst(INT1OID, -1, InvalidOid, 4, Int8GetDatum(state->m_order), false, true));
|
||||
result = lappend(result, makeConst(BOOLOID, -1, InvalidOid, 1, BoolGetDatum(state->m_hasForUpdate), false, true));
|
||||
result =
|
||||
lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_foreignTableId), false, true));
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_numAttrs), false, true));
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_ctidNum), false, true));
|
||||
result = lappend(result, makeConst(INT2OID, -1, InvalidOid, 2, Int16GetDatum(state->m_numExpr), false, true));
|
||||
int len = BITMAP_GETLEN(state->m_numAttrs);
|
||||
result = BitmapSerialize(result, state->m_attrsUsed, len);
|
||||
|
||||
if (state->m_bestIx != nullptr) {
|
||||
state->m_bestIx->Serialize(&result);
|
||||
}
|
||||
ReleaseFdwState(state);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CleanCursors(MOTFdwStateSt* state)
|
||||
{
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (state->m_cursor[i]) {
|
||||
state->m_cursor[i]->Invalidate();
|
||||
state->m_cursor[i]->Destroy();
|
||||
delete state->m_cursor[i];
|
||||
state->m_cursor[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CleanQueryStatesOnError(MOT::TxnManager* txn)
|
||||
{
|
||||
if (txn != nullptr) {
|
||||
for (auto& itr : txn->m_queryState) {
|
||||
MOTFdwStateSt* state = (MOTFdwStateSt*)itr.second;
|
||||
if (state != nullptr) {
|
||||
CleanCursors(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseFdwState(MOTFdwStateSt* state)
|
||||
{
|
||||
CleanCursors(state);
|
||||
|
||||
if (state->m_currTxn) {
|
||||
state->m_currTxn->m_queryState.erase((uint64_t)state);
|
||||
}
|
||||
|
||||
if (state->m_bestIx && state->m_bestIx != &state->m_bestIxBuf)
|
||||
pfree(state->m_bestIx);
|
||||
|
||||
if (state->m_remoteCondsOrig != nullptr)
|
||||
list_free(state->m_remoteCondsOrig);
|
||||
|
||||
if (state->m_attrsUsed != NULL)
|
||||
pfree(state->m_attrsUsed);
|
||||
|
||||
if (state->m_attrsModified != NULL)
|
||||
pfree(state->m_attrsModified);
|
||||
|
||||
state->m_table = NULL;
|
||||
pfree(state);
|
||||
}
|
||||
|
||||
void MOTCheckpointFetchLock()
|
||||
{
|
||||
MOT::MOTEngine* engine = MOT::MOTEngine::GetInstance();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss 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.
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* mot_fdw_error.cpp
|
||||
* MOT Foreign Data Wrapper error reporting interfaces.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/storage/mot/fdw_adapter/src/mot_fdw_error.cpp
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "mot_fdw_error.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "utils/elog.h"
|
||||
|
||||
#include "column.h"
|
||||
#include "table.h"
|
||||
|
||||
// Error code mapping array from MOT to PG
|
||||
static const MotErrToPGErrSt MM_ERRCODE_TO_PG[] = {
|
||||
// RC_OK
|
||||
{ERRCODE_SUCCESSFUL_COMPLETION, "Success", nullptr},
|
||||
// RC_ERROR
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_ABORT
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_UNSUPPORTED_COL_TYPE
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column type %s is not supported yet"},
|
||||
// RC_UNSUPPORTED_COL_TYPE_ARR
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column type Array of %s is not supported yet"},
|
||||
// RC_EXCEEDS_MAX_ROW_SIZE
|
||||
{ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||
"Column definition of %s is not supported",
|
||||
"Column size %d exceeds max tuple size %u"},
|
||||
// RC_COL_NAME_EXCEEDS_MAX_SIZE
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column name %s exceeds max name size %u"},
|
||||
// RC_COL_SIZE_INVALID
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column size %d exceeds max size %u"},
|
||||
// RC_TABLE_EXCEEDS_MAX_DECLARED_COLS
|
||||
{ERRCODE_FEATURE_NOT_SUPPORTED, "Can't create table", "Can't add column %s, number of declared columns is less"},
|
||||
// RC_INDEX_EXCEEDS_MAX_SIZE
|
||||
{ERRCODE_FDW_KEY_SIZE_EXCEEDS_MAX_ALLOWED,
|
||||
"Can't create index",
|
||||
"Total columns size is greater than maximum index size %u"},
|
||||
// RC_TABLE_EXCEEDS_MAX_INDEXES,
|
||||
{ERRCODE_FDW_TOO_MANY_INDEXES,
|
||||
"Can't create index",
|
||||
"Total number of indexes for table %s is greater than the maximum number if indexes allowed %u"},
|
||||
// RC_TXN_EXCEEDS_MAX_DDLS,
|
||||
{ERRCODE_FDW_TOO_MANY_DDL_CHANGES_IN_TRANSACTION_NOT_ALLOWED,
|
||||
"Cannot execute statement",
|
||||
"Maximum number of DDLs per transactions reached the maximum %u"},
|
||||
// RC_UNIQUE_VIOLATION
|
||||
{ERRCODE_UNIQUE_VIOLATION, "duplicate key value violates unique constraint \"%s\"", "Key %s already exists."},
|
||||
// RC_TABLE_NOT_FOUND
|
||||
{ERRCODE_UNDEFINED_TABLE, "Table \"%s\" doesn't exist", nullptr},
|
||||
// RC_INDEX_NOT_FOUND
|
||||
{ERRCODE_UNDEFINED_TABLE, "Index \"%s\" doesn't exist", nullptr},
|
||||
// RC_LOCAL_ROW_FOUND
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_LOCAL_ROW_NOT_FOUND
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_LOCAL_ROW_DELETED
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_INSERT_ON_EXIST
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_INDEX_RETRY_INSERT
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_INDEX_DELETE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_LOCAL_ROW_NOT_VISIBLE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_MEMORY_ALLOCATION_ERROR
|
||||
{ERRCODE_OUT_OF_LOGICAL_MEMORY, "Memory is temporarily unavailable", nullptr},
|
||||
// RC_ILLEGAL_ROW_STATE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_NULL_VOILATION
|
||||
{ERRCODE_FDW_ERROR,
|
||||
"Null constraint violated",
|
||||
"NULL value cannot be inserted into non-null column %s at table %s"},
|
||||
// RC_PANIC
|
||||
{ERRCODE_FDW_ERROR, "Critical error", "Critical error: %s"},
|
||||
// RC_NA
|
||||
{ERRCODE_FDW_OPERATION_NOT_SUPPORTED, "A checkpoint is in progress - cannot truncate table.", nullptr},
|
||||
// RC_MAX_VALUE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr}
|
||||
};
|
||||
|
||||
static_assert(sizeof(MM_ERRCODE_TO_PG) / sizeof(MotErrToPGErrSt) == MOT::RC_MAX_VALUE + 1,
|
||||
"Not all MOT engine error codes (RC) is mapped to PG error codes");
|
||||
|
||||
void report_pg_error(MOT::RC rc, void* arg1, void* arg2, void* arg3, void* arg4, void* arg5)
|
||||
{
|
||||
const MotErrToPGErrSt* err = &MM_ERRCODE_TO_PG[rc];
|
||||
|
||||
switch (rc) {
|
||||
case MOT::RC_OK:
|
||||
break;
|
||||
case MOT::RC_ERROR:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_ABORT:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_UNSUPPORTED_COL_TYPE: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, NameListToString(col->typname->names))));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_UNSUPPORTED_COL_TYPE_ARR: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, strVal(llast(col->typname->names)))));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_COL_NAME_EXCEEDS_MAX_SIZE: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, col->colname, (uint32_t)MOT::Column::MAX_COLUMN_NAME_LEN)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_COL_SIZE_INVALID: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, (uint32_t)(uint64_t)arg2, (uint32_t)MAX_VARCHAR_LEN)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_EXCEEDS_MAX_ROW_SIZE: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, (uint32_t)(uint64_t)arg2, (uint32_t)MAX_TUPLE_SIZE)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_TABLE_EXCEEDS_MAX_DECLARED_COLS: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, col->colname)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_INDEX_EXCEEDS_MAX_SIZE:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, MAX_KEY_SIZE)));
|
||||
break;
|
||||
case MOT::RC_TABLE_EXCEEDS_MAX_INDEXES:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, ((MOT::Table*)arg1)->GetTableName(), MAX_NUM_INDEXES)));
|
||||
break;
|
||||
case MOT::RC_TXN_EXCEEDS_MAX_DDLS:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, MAX_DDL_ACCESS_SIZE)));
|
||||
break;
|
||||
case MOT::RC_UNIQUE_VIOLATION:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, (char*)arg1),
|
||||
errdetail(err->m_detail, (char*)arg2)));
|
||||
break;
|
||||
|
||||
case MOT::RC_TABLE_NOT_FOUND:
|
||||
case MOT::RC_INDEX_NOT_FOUND:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg(err->m_msg, (char*)arg1)));
|
||||
break;
|
||||
|
||||
// following errors are internal and should not get to an upper layer
|
||||
case MOT::RC_LOCAL_ROW_FOUND:
|
||||
case MOT::RC_LOCAL_ROW_NOT_FOUND:
|
||||
case MOT::RC_LOCAL_ROW_DELETED:
|
||||
case MOT::RC_INSERT_ON_EXIST:
|
||||
case MOT::RC_INDEX_RETRY_INSERT:
|
||||
case MOT::RC_INDEX_DELETE:
|
||||
case MOT::RC_LOCAL_ROW_NOT_VISIBLE:
|
||||
case MOT::RC_ILLEGAL_ROW_STATE:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_MEMORY_ALLOCATION_ERROR:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_NULL_VIOLATION: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
MOT::Table* table = (MOT::Table*)arg2;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, col->colname, table->GetLongTableName().c_str())));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_PANIC: {
|
||||
char* msg = (char*)arg1;
|
||||
ereport(PANIC,
|
||||
(errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg), errdetail(err->m_detail, msg)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_NA:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_MAX_VALUE:
|
||||
default:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss 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.
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* mot_fdw_error.h
|
||||
* MOT Foreign Data Wrapper error reporting interfaces.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/gausskernel/storage/mot/fdw_adapter/src/mot_fdw_error.h
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MOT_FDW_ERROR_H
|
||||
#define MOT_FDW_ERROR_H
|
||||
|
||||
#include "global.h"
|
||||
|
||||
typedef struct tagMotErrToPGErrSt {
|
||||
int m_pgErr;
|
||||
const char* m_msg;
|
||||
const char* m_detail;
|
||||
} MotErrToPGErrSt;
|
||||
|
||||
void report_pg_error(MOT::RC rc, void* arg1 = nullptr, void* arg2 = nullptr, void* arg3 = nullptr, void* arg4 = nullptr,
|
||||
void* arg5 = nullptr);
|
||||
|
||||
#endif /* MOT_FDW_ERROR_H */
|
||||
|
|
@ -241,227 +241,6 @@ static void CancelSessionCleanup()
|
|||
|
||||
static GaussdbConfigLoader* gaussdbConfigLoader = nullptr;
|
||||
|
||||
// Error code mapping array from MOT to PG
|
||||
static const MotErrToPGErrSt MM_ERRCODE_TO_PG[] = {
|
||||
// RC_OK
|
||||
{ERRCODE_SUCCESSFUL_COMPLETION, "Success", nullptr},
|
||||
// RC_ERROR
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_ABORT
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_UNSUPPORTED_COL_TYPE
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column type %s is not supported yet"},
|
||||
// RC_UNSUPPORTED_COL_TYPE_ARR
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column type Array of %s is not supported yet"},
|
||||
// RC_EXCEEDS_MAX_ROW_SIZE
|
||||
{ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||
"Column definition of %s is not supported",
|
||||
"Column size %d exceeds max tuple size %u"},
|
||||
// RC_COL_NAME_EXCEEDS_MAX_SIZE
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column name %s exceeds max name size %u"},
|
||||
// RC_COL_SIZE_INVALID
|
||||
{ERRCODE_INVALID_COLUMN_DEFINITION,
|
||||
"Column definition of %s is not supported",
|
||||
"Column size %d exceeds max size %u"},
|
||||
// RC_TABLE_EXCEEDS_MAX_DECLARED_COLS
|
||||
{ERRCODE_FEATURE_NOT_SUPPORTED, "Can't create table", "Can't add column %s, number of declared columns is less"},
|
||||
// RC_INDEX_EXCEEDS_MAX_SIZE
|
||||
{ERRCODE_FDW_KEY_SIZE_EXCEEDS_MAX_ALLOWED,
|
||||
"Can't create index",
|
||||
"Total columns size is greater than maximum index size %u"},
|
||||
// RC_TABLE_EXCEEDS_MAX_INDEXES,
|
||||
{ERRCODE_FDW_TOO_MANY_INDEXES,
|
||||
"Can't create index",
|
||||
"Total number of indexes for table %s is greater than the maximum number if indexes allowed %u"},
|
||||
// RC_TXN_EXCEEDS_MAX_DDLS,
|
||||
{ERRCODE_FDW_TOO_MANY_DDL_CHANGES_IN_TRANSACTION_NOT_ALLOWED,
|
||||
"Cannot execute statement",
|
||||
"Maximum number of DDLs per transactions reached the maximum %u"},
|
||||
// RC_UNIQUE_VIOLATION
|
||||
{ERRCODE_UNIQUE_VIOLATION, "duplicate key value violates unique constraint \"%s\"", "Key %s already exists."},
|
||||
// RC_TABLE_NOT_FOUND
|
||||
{ERRCODE_UNDEFINED_TABLE, "Table \"%s\" doesn't exist", nullptr},
|
||||
// RC_INDEX_NOT_FOUND
|
||||
{ERRCODE_UNDEFINED_TABLE, "Index \"%s\" doesn't exist", nullptr},
|
||||
// RC_LOCAL_ROW_FOUND
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_LOCAL_ROW_NOT_FOUND
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_LOCAL_ROW_DELETED
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_INSERT_ON_EXIST
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_INDEX_RETRY_INSERT
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_INDEX_DELETE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_LOCAL_ROW_NOT_VISIBLE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_MEMORY_ALLOCATION_ERROR
|
||||
{ERRCODE_OUT_OF_LOGICAL_MEMORY, "Memory is temporarily unavailable", nullptr},
|
||||
// RC_ILLEGAL_ROW_STATE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr},
|
||||
// RC_NULL_VOILATION
|
||||
{ERRCODE_FDW_ERROR,
|
||||
"Null constraint violated",
|
||||
"NULL value cannot be inserted into non-null column %s at table %s"},
|
||||
// RC_PANIC
|
||||
{ERRCODE_FDW_ERROR, "Critical error", "Critical error: %s"},
|
||||
// RC_NA
|
||||
{ERRCODE_FDW_OPERATION_NOT_SUPPORTED, "A checkpoint is in progress - cannot truncate table.", nullptr},
|
||||
// RC_MAX_VALUE
|
||||
{ERRCODE_FDW_ERROR, "Unknown error has occurred", nullptr}};
|
||||
|
||||
static_assert(sizeof(MM_ERRCODE_TO_PG) / sizeof(MotErrToPGErrSt) == MOT::RC_MAX_VALUE + 1,
|
||||
"Not all MOT engine error codes (RC) is mapped to PG error codes");
|
||||
|
||||
void report_pg_error(MOT::RC rc, MOT::TxnManager* txn, void* arg1, void* arg2, void* arg3, void* arg4, void* arg5)
|
||||
{
|
||||
const MotErrToPGErrSt* err = &MM_ERRCODE_TO_PG[rc];
|
||||
|
||||
switch (rc) {
|
||||
case MOT::RC_OK:
|
||||
break;
|
||||
case MOT::RC_ERROR:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_ABORT:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_UNSUPPORTED_COL_TYPE: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, NameListToString(col->typname->names))));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_UNSUPPORTED_COL_TYPE_ARR: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, strVal(llast(col->typname->names)))));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_COL_NAME_EXCEEDS_MAX_SIZE: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, col->colname, (uint32_t)MOT::Column::MAX_COLUMN_NAME_LEN)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_COL_SIZE_INVALID: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, (uint32_t)(uint64_t)arg2, (uint32_t)MAX_VARCHAR_LEN)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_EXCEEDS_MAX_ROW_SIZE: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, col->colname),
|
||||
errdetail(err->m_detail, (uint32_t)(uint64_t)arg2, (uint32_t)MAX_TUPLE_SIZE)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_TABLE_EXCEEDS_MAX_DECLARED_COLS: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, col->colname)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_INDEX_EXCEEDS_MAX_SIZE:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, MAX_KEY_SIZE)));
|
||||
break;
|
||||
case MOT::RC_TABLE_EXCEEDS_MAX_INDEXES:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, ((MOT::Table*)arg1)->GetTableName(), MAX_NUM_INDEXES)));
|
||||
break;
|
||||
case MOT::RC_TXN_EXCEEDS_MAX_DDLS:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, MAX_DDL_ACCESS_SIZE)));
|
||||
break;
|
||||
case MOT::RC_UNIQUE_VIOLATION:
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg(err->m_msg, (char*)arg1),
|
||||
errdetail(err->m_detail, (char*)arg2)));
|
||||
break;
|
||||
|
||||
case MOT::RC_TABLE_NOT_FOUND:
|
||||
case MOT::RC_INDEX_NOT_FOUND:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg(err->m_msg, (char*)arg1)));
|
||||
break;
|
||||
|
||||
// following errors are internal and should not get to an upper layer
|
||||
case MOT::RC_LOCAL_ROW_FOUND:
|
||||
case MOT::RC_LOCAL_ROW_NOT_FOUND:
|
||||
case MOT::RC_LOCAL_ROW_DELETED:
|
||||
case MOT::RC_INSERT_ON_EXIST:
|
||||
case MOT::RC_INDEX_RETRY_INSERT:
|
||||
case MOT::RC_INDEX_DELETE:
|
||||
case MOT::RC_LOCAL_ROW_NOT_VISIBLE:
|
||||
case MOT::RC_ILLEGAL_ROW_STATE:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_MEMORY_ALLOCATION_ERROR:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_NULL_VIOLATION: {
|
||||
ColumnDef* col = (ColumnDef*)arg1;
|
||||
MOT::Table* table = (MOT::Table*)arg2;
|
||||
ereport(ERROR,
|
||||
(errmodule(MOD_MOT),
|
||||
errcode(err->m_pgErr),
|
||||
errmsg("%s", err->m_msg),
|
||||
errdetail(err->m_detail, col->colname, table->GetLongTableName().c_str())));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_PANIC: {
|
||||
char* msg = (char*)arg1;
|
||||
ereport(PANIC,
|
||||
(errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg), errdetail(err->m_detail, msg)));
|
||||
break;
|
||||
}
|
||||
case MOT::RC_NA:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
case MOT::RC_MAX_VALUE:
|
||||
default:
|
||||
ereport(ERROR, (errmodule(MOD_MOT), errcode(err->m_pgErr), errmsg("%s", err->m_msg)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MOTAdaptor::m_initialized = false;
|
||||
bool MOTAdaptor::m_callbacks_initialized = false;
|
||||
|
||||
|
|
@ -1328,7 +1107,7 @@ MOT::RC MOTAdaptor::CreateIndex(IndexStmt* index, ::TransactionId tid)
|
|||
|
||||
ix = MOT::IndexFactory::CreateIndex(index_order, indexing_method, flavor);
|
||||
if (ix == nullptr) {
|
||||
report_pg_error(MOT::RC_ABORT, txn);
|
||||
report_pg_error(MOT::RC_ABORT);
|
||||
return MOT::RC_ABORT;
|
||||
}
|
||||
ix->SetExtId(index->indexOid);
|
||||
|
|
@ -1392,7 +1171,7 @@ MOT::RC MOTAdaptor::CreateIndex(IndexStmt* index, ::TransactionId tid)
|
|||
|
||||
if ((res = ix->IndexInit(keyLength, index->unique, index->idxname, nullptr)) != MOT::RC_OK) {
|
||||
delete ix;
|
||||
report_pg_error(res, txn);
|
||||
report_pg_error(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1406,7 +1185,7 @@ MOT::RC MOTAdaptor::CreateIndex(IndexStmt* index, ::TransactionId tid)
|
|||
errmsg("Can not create index, max number of indexes %u reached", MAX_NUM_INDEXES)));
|
||||
return MOT::RC_TABLE_EXCEEDS_MAX_INDEXES;
|
||||
} else {
|
||||
report_pg_error(txn->m_err, txn, index->idxname, txn->m_errMsgBuf);
|
||||
report_pg_error(txn->m_err, index->idxname, txn->m_errMsgBuf);
|
||||
return MOT::RC_UNIQUE_VIOLATION;
|
||||
}
|
||||
}
|
||||
|
|
@ -1464,7 +1243,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
table->base.relation->relname, tname.c_str(), columnCount, table->base.relation->foreignOid)) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR, txn);
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1474,7 +1253,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
if (res != MOT::RC_OK) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR, txn);
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1501,7 +1280,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
if (res != MOT::RC_OK) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(res, txn, colDef, (void*)(int64)typeLen);
|
||||
report_pg_error(res, colDef, (void*)(int64)typeLen);
|
||||
break;
|
||||
}
|
||||
hasBlob |= isBlob;
|
||||
|
|
@ -1555,7 +1334,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
if (res != MOT::RC_OK) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(res, txn, colDef, (void*)(int64)typeLen);
|
||||
report_pg_error(res, colDef, (void*)(int64)typeLen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1583,7 +1362,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
if (!currentTable->InitRowPool()) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR, txn);
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1598,7 +1377,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
if (res != MOT::RC_OK) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(res, txn);
|
||||
report_pg_error(res);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1613,7 +1392,7 @@ MOT::RC MOTAdaptor::CreateTable(CreateForeignTableStmt* table, ::TransactionId t
|
|||
if (rc != MOT::RC_OK) {
|
||||
delete currentTable;
|
||||
currentTable = nullptr;
|
||||
report_pg_error(rc, txn);
|
||||
report_pg_error(rc);
|
||||
break;
|
||||
}
|
||||
primaryIdx->SetExtId(table->base.relation->foreignOid + 1);
|
||||
|
|
@ -2168,6 +1947,137 @@ void MOTAdaptor::DatumToMOT(MOT::Column* col, Datum datum, Oid type, uint8_t* da
|
|||
}
|
||||
}
|
||||
|
||||
inline void MOTAdaptor::VarcharToMOTKey(
|
||||
MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill)
|
||||
{
|
||||
if (expr != nullptr) { // LLVM passes nullptr for expr parameter
|
||||
bool noValue = false;
|
||||
switch (expr->resultType) {
|
||||
case BYTEAOID:
|
||||
case TEXTOID:
|
||||
case VARCHAROID:
|
||||
case CLOBOID:
|
||||
case BPCHAROID:
|
||||
break;
|
||||
default:
|
||||
noValue = true;
|
||||
errno_t erc = memset_s(data, len, 0x00, len);
|
||||
securec_check(erc, "\0", "\0");
|
||||
break;
|
||||
}
|
||||
if (noValue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bytea* txt = DatumGetByteaP(datum);
|
||||
size_t size = VARSIZE(txt); // includes header len VARHDRSZ
|
||||
char* src = VARDATA(txt);
|
||||
|
||||
if (size > len) {
|
||||
size = len;
|
||||
}
|
||||
|
||||
size -= VARHDRSZ;
|
||||
if (oper == KEY_OPER::READ_KEY_LIKE) {
|
||||
if (src[size - 1] == '%') {
|
||||
size -= 1;
|
||||
} else {
|
||||
// switch to equal
|
||||
if (type == BPCHAROID) {
|
||||
fill = 0x20; // space ' ' == 0x20
|
||||
} else {
|
||||
fill = 0x00;
|
||||
}
|
||||
}
|
||||
} else if (type == BPCHAROID) { // handle padding for blank-padded type
|
||||
fill = 0x20;
|
||||
}
|
||||
col->PackKey(data, (uintptr_t)src, size, fill);
|
||||
|
||||
if ((char*)datum != (char*)txt) {
|
||||
pfree(txt);
|
||||
}
|
||||
}
|
||||
|
||||
inline void MOTAdaptor::FloatToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data)
|
||||
{
|
||||
if (expr != nullptr) { // LLVM passes nullptr for expr parameter
|
||||
if (expr->resultType == FLOAT8OID) {
|
||||
MOT::DoubleConvT dc;
|
||||
MOT::FloatConvT fc;
|
||||
dc.m_r = (uint64_t)datum;
|
||||
fc.m_v = (float)dc.m_v;
|
||||
uint64_t u = (uint64_t)fc.m_r;
|
||||
col->PackKey(data, u, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
}
|
||||
|
||||
inline void MOTAdaptor::NumericToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data)
|
||||
{
|
||||
Numeric n = DatumGetNumeric(datum);
|
||||
char buf[DECIMAL_MAX_SIZE];
|
||||
MOT::DecimalSt* d = (MOT::DecimalSt*)buf;
|
||||
PGNumericToMOT(n, *d);
|
||||
col->PackKey(data, (uintptr_t)d, DECIMAL_SIZE(d));
|
||||
}
|
||||
|
||||
inline void MOTAdaptor::TimestampToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data)
|
||||
{
|
||||
if (expr != nullptr) {
|
||||
if (expr->resultType == TIMESTAMPTZOID) {
|
||||
Timestamp result = DatumGetTimestamp(DirectFunctionCall1(timestamptz_timestamp, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else if (expr->resultType == DATEOID) {
|
||||
Timestamp result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
}
|
||||
|
||||
inline void MOTAdaptor::TimestampTzToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data)
|
||||
{
|
||||
if (expr != nullptr) {
|
||||
if (expr->resultType == TIMESTAMPOID) {
|
||||
TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(timestamp_timestamptz, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else if (expr->resultType == DATEOID) {
|
||||
TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(date_timestamptz, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
}
|
||||
|
||||
inline void MOTAdaptor::DateToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data)
|
||||
{
|
||||
if (expr != nullptr) {
|
||||
if (expr->resultType == TIMESTAMPOID) {
|
||||
DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamp_date, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else if (expr->resultType == TIMESTAMPTZOID) {
|
||||
DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamptz_date, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
}
|
||||
|
||||
void MOTAdaptor::DatumToMOTKey(
|
||||
MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill)
|
||||
{
|
||||
|
|
@ -2177,132 +2087,135 @@ void MOTAdaptor::DatumToMOTKey(
|
|||
case TEXTOID:
|
||||
case VARCHAROID:
|
||||
case CLOBOID:
|
||||
case BPCHAROID: {
|
||||
if (expr != nullptr) { // LLVM passes nullptr for expr parameter
|
||||
bool noValue = false;
|
||||
switch (expr->resultType) {
|
||||
case BYTEAOID:
|
||||
case TEXTOID:
|
||||
case VARCHAROID:
|
||||
case CLOBOID:
|
||||
case BPCHAROID:
|
||||
break;
|
||||
default:
|
||||
noValue = true;
|
||||
errno_t erc = memset_s(data, len, 0x00, len);
|
||||
securec_check(erc, "\0", "\0");
|
||||
break;
|
||||
}
|
||||
if (noValue) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bytea* txt = DatumGetByteaP(datum);
|
||||
size_t size = VARSIZE(txt); // includes header len VARHDRSZ
|
||||
char* src = VARDATA(txt);
|
||||
|
||||
if (size > len)
|
||||
size = len;
|
||||
|
||||
size -= VARHDRSZ;
|
||||
if (oper == KEY_OPER::READ_KEY_LIKE) {
|
||||
if (src[size - 1] == '%') {
|
||||
size -= 1;
|
||||
} else {
|
||||
// switch to equal
|
||||
if (type == BPCHAROID) {
|
||||
fill = 0x20; // space ' ' == 0x20
|
||||
} else {
|
||||
fill = 0x00;
|
||||
}
|
||||
}
|
||||
} else if (type == BPCHAROID) { // handle padding for blank-padded type
|
||||
fill = 0x20;
|
||||
}
|
||||
col->PackKey(data, (uintptr_t)src, size, fill);
|
||||
|
||||
if ((char*)datum != (char*)txt) {
|
||||
pfree(txt);
|
||||
}
|
||||
|
||||
case BPCHAROID:
|
||||
VarcharToMOTKey(col, expr, datum, type, data, len, oper, fill);
|
||||
break;
|
||||
}
|
||||
case FLOAT4OID: {
|
||||
if (expr != nullptr) { // LLVM passes nullptr for expr parameter
|
||||
if (expr->resultType == FLOAT8OID) {
|
||||
MOT::DoubleConvT dc;
|
||||
MOT::FloatConvT fc;
|
||||
dc.m_r = (uint64_t)datum;
|
||||
fc.m_v = (float)dc.m_v;
|
||||
uint64_t u = (uint64_t)fc.m_r;
|
||||
col->PackKey(data, u, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
case FLOAT4OID:
|
||||
FloatToMOTKey(col, expr, datum, data);
|
||||
break;
|
||||
}
|
||||
case NUMERICOID: {
|
||||
Numeric n = DatumGetNumeric(datum);
|
||||
char buf[DECIMAL_MAX_SIZE];
|
||||
MOT::DecimalSt* d = (MOT::DecimalSt*)buf;
|
||||
PGNumericToMOT(n, *d);
|
||||
col->PackKey(data, (uintptr_t)d, DECIMAL_SIZE(d));
|
||||
|
||||
case NUMERICOID:
|
||||
NumericToMOTKey(col, expr, datum, data);
|
||||
break;
|
||||
}
|
||||
case TIMESTAMPOID: {
|
||||
if (expr != nullptr) {
|
||||
if (expr->resultType == TIMESTAMPTZOID) {
|
||||
Timestamp result = DatumGetTimestamp(DirectFunctionCall1(timestamptz_timestamp, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else if (expr->resultType == DATEOID) {
|
||||
Timestamp result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
case TIMESTAMPOID:
|
||||
TimestampToMOTKey(col, expr, datum, data);
|
||||
break;
|
||||
}
|
||||
case TIMESTAMPTZOID: {
|
||||
if (expr != nullptr) {
|
||||
if (expr->resultType == TIMESTAMPOID) {
|
||||
TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(timestamp_timestamptz, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else if (expr->resultType == DATEOID) {
|
||||
TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(date_timestamptz, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
case TIMESTAMPTZOID:
|
||||
TimestampTzToMOTKey(col, expr, datum, data);
|
||||
break;
|
||||
}
|
||||
case DATEOID: {
|
||||
if (expr != nullptr) {
|
||||
if (expr->resultType == TIMESTAMPOID) {
|
||||
DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamp_date, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else if (expr->resultType == TIMESTAMPTZOID) {
|
||||
DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamptz_date, datum));
|
||||
col->PackKey(data, result, col->m_size);
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
} else {
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
}
|
||||
case DATEOID:
|
||||
DateToMOTKey(col, expr, datum, data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
col->PackKey(data, datum, col->m_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MOTFdwStateSt* InitializeFdwState(void* fdwState, List** fdwExpr, uint64_t exTableID)
|
||||
{
|
||||
MOTFdwStateSt* state = (MOTFdwStateSt*)palloc0(sizeof(MOTFdwStateSt));
|
||||
List* values = (List*)fdwState;
|
||||
|
||||
state->m_allocInScan = true;
|
||||
state->m_foreignTableId = exTableID;
|
||||
if (list_length(values) > 0) {
|
||||
ListCell* cell = list_head(values);
|
||||
int type = ((Const*)lfirst(cell))->constvalue;
|
||||
if (type != FDW_LIST_STATE) {
|
||||
return state;
|
||||
}
|
||||
cell = lnext(cell);
|
||||
state->m_cmdOper = (CmdType)((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_order = (SORTDIR_ENUM)((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_hasForUpdate = (bool)((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_foreignTableId = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_numAttrs = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_ctidNum = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
state->m_numExpr = ((Const*)lfirst(cell))->constvalue;
|
||||
cell = lnext(cell);
|
||||
|
||||
int len = BITMAP_GETLEN(state->m_numAttrs);
|
||||
state->m_attrsUsed = (uint8_t*)palloc0(len);
|
||||
state->m_attrsModified = (uint8_t*)palloc0(len);
|
||||
BitmapDeSerialize(state->m_attrsUsed, len, &cell);
|
||||
|
||||
if (cell != NULL) {
|
||||
state->m_bestIx = &state->m_bestIxBuf;
|
||||
state->m_bestIx->Deserialize(cell, exTableID);
|
||||
}
|
||||
|
||||
if (fdwExpr != NULL && *fdwExpr != NULL) {
|
||||
ListCell* c = NULL;
|
||||
int i = 0;
|
||||
|
||||
// divide fdw expr to param list and original expr
|
||||
state->m_remoteCondsOrig = NULL;
|
||||
|
||||
foreach (c, *fdwExpr) {
|
||||
if (i < state->m_numExpr) {
|
||||
i++;
|
||||
continue;
|
||||
} else {
|
||||
state->m_remoteCondsOrig = lappend(state->m_remoteCondsOrig, lfirst(c));
|
||||
}
|
||||
}
|
||||
|
||||
*fdwExpr = list_truncate(*fdwExpr, state->m_numExpr);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void* SerializeFdwState(MOTFdwStateSt* state)
|
||||
{
|
||||
List* result = NULL;
|
||||
|
||||
// set list type to FDW_LIST_STATE
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, FDW_LIST_STATE, false, true));
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_cmdOper), false, true));
|
||||
result = lappend(result, makeConst(INT1OID, -1, InvalidOid, 4, Int8GetDatum(state->m_order), false, true));
|
||||
result = lappend(result, makeConst(BOOLOID, -1, InvalidOid, 1, BoolGetDatum(state->m_hasForUpdate), false, true));
|
||||
result =
|
||||
lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_foreignTableId), false, true));
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_numAttrs), false, true));
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, Int32GetDatum(state->m_ctidNum), false, true));
|
||||
result = lappend(result, makeConst(INT2OID, -1, InvalidOid, 2, Int16GetDatum(state->m_numExpr), false, true));
|
||||
int len = BITMAP_GETLEN(state->m_numAttrs);
|
||||
result = BitmapSerialize(result, state->m_attrsUsed, len);
|
||||
|
||||
if (state->m_bestIx != nullptr) {
|
||||
state->m_bestIx->Serialize(&result);
|
||||
}
|
||||
ReleaseFdwState(state);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ReleaseFdwState(MOTFdwStateSt* state)
|
||||
{
|
||||
CleanCursors(state);
|
||||
|
||||
if (state->m_currTxn) {
|
||||
state->m_currTxn->m_queryState.erase((uint64_t)state);
|
||||
}
|
||||
|
||||
if (state->m_bestIx && state->m_bestIx != &state->m_bestIxBuf)
|
||||
pfree(state->m_bestIx);
|
||||
|
||||
if (state->m_remoteCondsOrig != nullptr)
|
||||
list_free(state->m_remoteCondsOrig);
|
||||
|
||||
if (state->m_attrsUsed != NULL)
|
||||
pfree(state->m_attrsUsed);
|
||||
|
||||
if (state->m_attrsModified != NULL)
|
||||
pfree(state->m_attrsModified);
|
||||
|
||||
state->m_table = NULL;
|
||||
pfree(state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,18 +22,20 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MOT_INT_H
|
||||
#define MOT_INT_H
|
||||
#ifndef MOT_INTERNAL_H
|
||||
#define MOT_INTERNAL_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "catalog_column_types.h"
|
||||
#include "foreign/fdwapi.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "utils/numeric.h"
|
||||
#include "utils/numeric_gs.h"
|
||||
#include "pgstat.h"
|
||||
#include "global.h"
|
||||
#include "mot_fdw_error.h"
|
||||
#include "mot_fdw_xlog.h"
|
||||
#include "system/mot_engine.h"
|
||||
#include "bitmapset.h"
|
||||
|
|
@ -92,18 +94,8 @@ class MOTEngine;
|
|||
typedef struct MOTFdwState_St MOTFdwStateSt;
|
||||
#endif
|
||||
|
||||
typedef struct MotErrToPGErr_St {
|
||||
int m_pgErr;
|
||||
const char* m_msg;
|
||||
const char* m_detail;
|
||||
} MotErrToPGErrSt;
|
||||
|
||||
void report_pg_error(MOT::RC rc, MOT::TxnManager* txn, void* arg1 = nullptr, void* arg2 = nullptr, void* arg3 = nullptr,
|
||||
void* arg4 = nullptr, void* arg5 = nullptr);
|
||||
|
||||
#define MAX_VARCHAR_LEN 1024
|
||||
|
||||
typedef enum : uint8_t { SORTDIR_NONE = 0, SORTDIR_ASC = 1, SORTDIR_DESC = 2 } SORTDIR_ENUM;
|
||||
typedef enum : uint8_t { FDW_LIST_STATE = 1, FDW_LIST_BITMAP = 2 } FDW_LIST_TYPE;
|
||||
|
||||
typedef struct Order_St {
|
||||
SORTDIR_ENUM m_order;
|
||||
|
|
@ -311,6 +303,15 @@ public:
|
|||
static MOT::MOTEngine* m_engine;
|
||||
static bool m_initialized;
|
||||
static bool m_callbacks_initialized;
|
||||
|
||||
private:
|
||||
static void VarcharToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len,
|
||||
KEY_OPER oper, uint8_t fill);
|
||||
static void FloatToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data);
|
||||
static void NumericToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data);
|
||||
static void TimestampToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data);
|
||||
static void TimestampTzToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data);
|
||||
static void DateToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data);
|
||||
};
|
||||
|
||||
inline MOT::TxnManager* GetSafeTxn(const char* callerSrc, ::TransactionId txn_id = 0)
|
||||
|
|
@ -322,7 +323,7 @@ inline MOT::TxnManager* GetSafeTxn(const char* callerSrc, ::TransactionId txn_id
|
|||
u_sess->mot_cxt.txn_manager->SetTransactionId(txn_id);
|
||||
}
|
||||
} else {
|
||||
report_pg_error(MOT_GET_ROOT_ERROR_RC(), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
report_pg_error(MOT_GET_ROOT_ERROR_RC());
|
||||
}
|
||||
}
|
||||
return u_sess->mot_cxt.txn_manager;
|
||||
|
|
@ -330,4 +331,56 @@ inline MOT::TxnManager* GetSafeTxn(const char* callerSrc, ::TransactionId txn_id
|
|||
|
||||
extern void EnsureSafeThreadAccess();
|
||||
|
||||
#endif // MOT_INT_H
|
||||
inline List* BitmapSerialize(List* result, uint8_t* bitmap, int16_t len)
|
||||
{
|
||||
// set list type to FDW_LIST_BITMAP
|
||||
result = lappend(result, makeConst(INT4OID, -1, InvalidOid, 4, FDW_LIST_BITMAP, false, true));
|
||||
for (int i = 0; i < len; i++)
|
||||
result = lappend(result, makeConst(INT1OID, -1, InvalidOid, 1, Int8GetDatum(bitmap[i]), false, true));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void BitmapDeSerialize(uint8_t* bitmap, int16_t len, ListCell** cell)
|
||||
{
|
||||
if (cell != nullptr && *cell != nullptr) {
|
||||
int type = ((Const*)lfirst(*cell))->constvalue;
|
||||
if (type == FDW_LIST_BITMAP) {
|
||||
*cell = lnext(*cell);
|
||||
for (int i = 0; i < len; i++) {
|
||||
bitmap[i] = (uint8_t)((Const*)lfirst(*cell))->constvalue;
|
||||
*cell = lnext(*cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void CleanCursors(MOTFdwStateSt* state)
|
||||
{
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (state->m_cursor[i]) {
|
||||
state->m_cursor[i]->Invalidate();
|
||||
state->m_cursor[i]->Destroy();
|
||||
delete state->m_cursor[i];
|
||||
state->m_cursor[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void CleanQueryStatesOnError(MOT::TxnManager* txn)
|
||||
{
|
||||
if (txn != nullptr) {
|
||||
for (auto& itr : txn->m_queryState) {
|
||||
MOTFdwStateSt* state = (MOTFdwStateSt*)itr.second;
|
||||
if (state != nullptr) {
|
||||
CleanCursors(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOTFdwStateSt* InitializeFdwState(void* fdwState, List** fdwExpr, uint64_t exTableID);
|
||||
void* SerializeFdwState(MOTFdwStateSt* state);
|
||||
void ReleaseFdwState(MOTFdwStateSt* state);
|
||||
|
||||
#endif // MOT_INTERNAL_H
|
||||
|
|
|
|||
|
|
@ -44,9 +44,7 @@ include $(top_srcdir)/src/gausskernel/common.mk
|
|||
override CXXFLAGS += -DMOT_SECURE -I$(top_builddir)/src/gausskernel/storage/mot/jit_exec/src -I$(top_builddir)/src/gausskernel/storage/mot/fdw_adapter/src -I$(ENGINE_INC) -I$(ENGINE_INC)/storage -I$(ENGINE_INC)/system -I$(ENGINE_INC)/memory -I$(ENGINE_INC)/memory/garbage_collector
|
||||
override CXXFLAGS += -I$(ENGINE_INC)/infra -I$(ENGINE_INC)/infra/config -I$(ENGINE_INC)/infra/containers -I$(ENGINE_INC)/infra/stats -I$(ENGINE_INC)/infra/synchronization -I$(ENGINE_INC)/concurrency_control -I$(ENGINE_INC)/storage/index -I$(ENGINE_INC)/system/transaction -I$(ENGINE_INC)/system/common -I$(ENGINE_INC)/system/statistics -I$(ENGINE_INC)/system/transaction_logger -I$(ENGINE_INC)/system/transaction_logger/asynchronous_redo_log -I$(ENGINE_INC)/system/transaction_logger/synchronous_redo_log -I$(ENGINE_INC)/system/transaction_logger/group_synchronous_redo_log -I$(ENGINE_INC)/system/checkpoint -I$(ENGINE_INC)/system/recovery -I$(ENGINE_INC)/utils
|
||||
|
||||
ifeq ($(CC_VERSION), 8.2.0)
|
||||
override CXXFLAGS += -faligned-new -fno-rtti
|
||||
endif
|
||||
override CXXFLAGS += -faligned-new -fno-rtti
|
||||
|
||||
override CXXFLAGS += -D__STDC_FORMAT_MACROS
|
||||
|
||||
|
|
@ -74,7 +72,7 @@ buildrepo:
|
|||
@$(call make-repo)
|
||||
|
||||
$(OBJ_DIR)/%.o: %.cpp
|
||||
$(COMPILE.cpp) -std=c++11 -MMD -MP -MF"$(patsubst %.o,%.d,$@)" -MT"$@" -o $@ $<
|
||||
$(COMPILE.cpp) -MMD -MP -MF"$(patsubst %.o,%.d,$@)" -MT"$@" -o $@ $<
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(DEPS)
|
||||
|
|
|
|||
|
|
@ -22,9 +22,16 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "postgres.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "global.h"
|
||||
#include "jit_common.h"
|
||||
#include "utilities.h"
|
||||
#include "jit_plan.h"
|
||||
|
|
@ -247,7 +254,7 @@ static bool IsEqualsWhereOperator(int whereOp)
|
|||
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
||||
|| (whereOp == INT24EQOID) || (whereOp == INT42EQOID) || (whereOp == INT84EQOID) || (whereOp == INT48EQOID) ||
|
||||
(whereOp == INT82EQOID) || (whereOp == INT28EQOID) || (whereOp == FLOAT48EQOID) || (whereOp == FLOAT84EQOID) ||
|
||||
(whereOp == 1108 /* time_eq */) || (whereOp == TIMETZEQOID)(whereOp == 5550 /* smalldatetime_eq */) ||
|
||||
(whereOp == 1108 /* time_eq */) || (whereOp == TIMETZEQOID) || (whereOp == 5550 /* smalldatetime_eq */) ||
|
||||
(whereOp == 2347 /* date_eq_timestamp */) || (whereOp == 2373 /* timestamp_eq_date */) ||
|
||||
(whereOp == 2360 /* date_eq_timestamptz */) || (whereOp == 2386 /* timestamptz_eq_date */) ||
|
||||
(whereOp == 2536 /* timestamp_eq_timestamptz */) || (whereOp == 2542 /* timestamptz_eq_timestamp */) ||
|
||||
|
|
@ -272,11 +279,11 @@ static bool IsLessThanWhereOperator(int whereOp)
|
|||
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
||||
|| (whereOp == INT24LTOID) || (whereOp == INT42LTOID) || (whereOp == INT84LTOID) || (whereOp == INT48LTOID) ||
|
||||
(whereOp == INT82LTOID) || (whereOp == INT28LTOID) || (whereOp == FLOAT48LTOID) || (whereOp == FLOAT84LTOID) ||
|
||||
(whereOp == 1108 /* time_lt */) || (whereOp == 1552 /* timetz_lt */)(whereOp == 5550 /* smalldatetime_lt */) ||
|
||||
(whereOp == 2347 /* date_lt_timestamp */) || (whereOp == 2373 /* timestamp_lt_date */) ||
|
||||
(whereOp == 2360 /* date_lt_timestamptz */) || (whereOp == 2386 /* timestamptz_lt_date */) ||
|
||||
(whereOp == 2536 /* timestamp_lt_timestamptz */) || (whereOp == 2542 /* timestamptz_lt_timestamp */) ||
|
||||
(whereOp == 1332 /* interval_lt */)
|
||||
(whereOp == 1108 /* time_lt */) || (whereOp == 1552 /* timetz_lt */) ||
|
||||
(whereOp == 5550 /* smalldatetime_lt */) || (whereOp == 2347 /* date_lt_timestamp */) ||
|
||||
(whereOp == 2373 /* timestamp_lt_date */) || (whereOp == 2360 /* date_lt_timestamptz */) ||
|
||||
(whereOp == 2386 /* timestamptz_lt_date */) || (whereOp == 2536 /* timestamp_lt_timestamptz */) ||
|
||||
(whereOp == 2542 /* timestamptz_lt_timestamp */) || (whereOp == 1332 /* interval_lt */)
|
||||
#endif
|
||||
) {
|
||||
result = true;
|
||||
|
|
@ -297,11 +304,11 @@ static bool IsGreaterThanWhereOperator(int whereOp)
|
|||
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
||||
|| (whereOp == INT24GTOID) || (whereOp == INT42GTOID) || (whereOp == INT84GTOID) || (whereOp == INT48GTOID) ||
|
||||
(whereOp == INT82GTOID) || (whereOp == INT28GTOID) || (whereOp == FLOAT48GTOID) || (whereOp == FLOAT84GTOID) ||
|
||||
(whereOp == 1112 /* time_gt */) || (whereOp == 1554 /* timetz_gt */)(whereOp == 5554 /* smalldatetime_gt */) ||
|
||||
(whereOp == 2349 /* date_gt_timestamp */) || (whereOp == 2375 /* timestamp_gt_date */) ||
|
||||
(whereOp == 2362 /* date_gt_timestamptz */) || (whereOp == 2388 /* timestamptz_gt_date */) ||
|
||||
(whereOp == 2538 /* timestamp_gt_timestamptz */) || (whereOp == 2544 /* timestamptz_gt_timestamp */) ||
|
||||
(whereOp == 1334 /* interval_gt */)
|
||||
(whereOp == 1112 /* time_gt */) || (whereOp == 1554 /* timetz_gt */) ||
|
||||
(whereOp == 5554 /* smalldatetime_gt */) || (whereOp == 2349 /* date_gt_timestamp */) ||
|
||||
(whereOp == 2375 /* timestamp_gt_date */) || (whereOp == 2362 /* date_gt_timestamptz */) ||
|
||||
(whereOp == 2388 /* timestamptz_gt_date */) || (whereOp == 2538 /* timestamp_gt_timestamptz */) ||
|
||||
(whereOp == 2544 /* timestamptz_gt_timestamp */) || (whereOp == 1334 /* interval_gt */)
|
||||
#endif
|
||||
) {
|
||||
result = true;
|
||||
|
|
@ -322,11 +329,11 @@ static bool IsLessEqualsWhereOperator(int whereOp)
|
|||
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
||||
|| (whereOp == INT24LEOID) || (whereOp == INT42LEOID) || (whereOp == INT84LEOID) || (whereOp == INT48LEOID) ||
|
||||
(whereOp == INT82LEOID) || (whereOp == INT28LEOID) || (whereOp == FLOAT48LEOID) || (whereOp == FLOAT84LEOID) ||
|
||||
(whereOp == 1111 /* time_le */) || (whereOp == 1553 /* timetz_le */)(whereOp == 5553 /* smalldatetime_le */) ||
|
||||
(whereOp == 2346 /* date_le_timestamp */) || (whereOp == 2372 /* timestamp_le_date */) ||
|
||||
(whereOp == 2359 /* date_le_timestamptz */) || (whereOp == 2385 /* timestamptz_le_date */) ||
|
||||
(whereOp == 2535 /* timestamp_le_timestamptz */) || (whereOp == 2541 /* timestamptz_le_timestamp */) ||
|
||||
(whereOp == 1333 /* interval_le */)
|
||||
(whereOp == 1111 /* time_le */) || (whereOp == 1553 /* timetz_le */) ||
|
||||
(whereOp == 5553 /* smalldatetime_le */) || (whereOp == 2346 /* date_le_timestamp */) ||
|
||||
(whereOp == 2372 /* timestamp_le_date */) || (whereOp == 2359 /* date_le_timestamptz */) ||
|
||||
(whereOp == 2385 /* timestamptz_le_date */) || (whereOp == 2535 /* timestamp_le_timestamptz */) ||
|
||||
(whereOp == 2541 /* timestamptz_le_timestamp */) || (whereOp == 1333 /* interval_le */)
|
||||
#endif
|
||||
) {
|
||||
result = true;
|
||||
|
|
@ -347,11 +354,11 @@ static bool IsGreaterEqualsWhereOperator(int whereOp)
|
|||
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
||||
|| (whereOp == INT24GEOID) || (whereOp == INT42GEOID) || (whereOp == INT84GEOID) || (whereOp == INT48GEOID) ||
|
||||
(whereOp == INT82GEOID) || (whereOp == INT28GEOID) || (whereOp == FLOAT48GEOID) || (whereOp == FLOAT84GEOID) ||
|
||||
(whereOp == 1113 /* time_ge */) || (whereOp == 1555 /* timetz_ge */)(whereOp == 5549 /* smalldatetime_ge */) ||
|
||||
(whereOp == 2348 /* date_ge_timestamp */) || (whereOp == 2374 /* timestamp_ge_date */) ||
|
||||
(whereOp == 2361 /* date_ge_timestamptz */) || (whereOp == 2387 /* timestamptz_ge_date */) ||
|
||||
(whereOp == 2537 /* timestamp_ge_timestamptz */) || (whereOp == 2543 /* timestamptz_ge_timestamp */) ||
|
||||
(whereOp == 1335 /* interval_ge */)
|
||||
(whereOp == 1113 /* time_ge */) || (whereOp == 1555 /* timetz_ge */) ||
|
||||
(whereOp == 5549 /* smalldatetime_ge */) || (whereOp == 2348 /* date_ge_timestamp */) ||
|
||||
(whereOp == 2374 /* timestamp_ge_date */) || (whereOp == 2361 /* date_ge_timestamptz */) ||
|
||||
(whereOp == 2387 /* timestamptz_ge_date */) || (whereOp == 2537 /* timestamp_ge_timestamptz */) ||
|
||||
(whereOp == 2543 /* timestamptz_ge_timestamp */) || (whereOp == 1335 /* interval_ge */)
|
||||
#endif
|
||||
) {
|
||||
result = true;
|
||||
|
|
|
|||
|
|
@ -22,10 +22,17 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "postgres.h"
|
||||
#include "knl/knl_session.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "global.h"
|
||||
#include "jit_context.h"
|
||||
#include "jit_context_pool.h"
|
||||
#include "jit_common.h"
|
||||
|
|
|
|||
|
|
@ -62,7 +62,9 @@ extern bool InitJitContextPool(JitContextPool* contextPool, JitContextUsage usag
|
|||
poolSize,
|
||||
allocSize,
|
||||
usage == JIT_CONTEXT_GLOBAL ? "global" : "session-local");
|
||||
pthread_spin_destroy(&contextPool->m_lock);
|
||||
if (usage == JIT_CONTEXT_GLOBAL) {
|
||||
pthread_spin_destroy(&contextPool->m_lock);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
errno_t erc = memset_s(contextPool->m_contextPool, allocSize, 0, allocSize);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// be careful to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h
|
||||
#include "global.h"
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "codegen/builtinscodegen.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
|
|
@ -51,11 +55,9 @@
|
|||
|
||||
#include "mot_engine.h"
|
||||
#include "utilities.h"
|
||||
#include "mot_internal.h"
|
||||
#include "catalog_column_types.h"
|
||||
#include "mot_error.h"
|
||||
#include "utilities.h"
|
||||
#include "mot_internal.h"
|
||||
#include "cycles.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
|
@ -191,7 +193,7 @@ static void ProcessJitResult(MOT::RC result, JitContext* jitContext, int newScan
|
|||
} else {
|
||||
JitStatisticsProvider::GetInstance().AddFailExecQuery();
|
||||
}
|
||||
report_pg_error(result, currTxn, (void*)arg1, (void*)arg2);
|
||||
report_pg_error(result, (void*)arg1, (void*)arg2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,10 +203,11 @@ static JitContext* GenerateJitContext(Query* query, const char* queryString, Jit
|
|||
JitContext* sourceJitContext = nullptr;
|
||||
|
||||
uint64_t startTime = GetSysClock();
|
||||
if (JitCanInitThreadCodeGen() && !IsMotPseudoCodegenForced()) {
|
||||
if (g_instance.mot_cxt.jitExecMode == JIT_EXEC_MODE_LLVM) {
|
||||
MOT_LOG_TRACE("Generating LLVM JIT context for query: %s", queryString);
|
||||
sourceJitContext = JitCodegenLlvmQuery(query, queryString, jitPlan);
|
||||
} else {
|
||||
MOT_ASSERT(g_instance.mot_cxt.jitExecMode == JIT_EXEC_MODE_TVM);
|
||||
MOT_LOG_TRACE("Generating TVM JIT context for query: %s", queryString);
|
||||
sourceJitContext = JitCodegenTvmQuery(query, queryString, jitPlan);
|
||||
}
|
||||
|
|
@ -365,7 +368,7 @@ extern int JitExecQuery(
|
|||
"Execute JIT",
|
||||
"Cannot execute jitted function: function is null. Aborting transaction.");
|
||||
JitStatisticsProvider::GetInstance().AddFailExecQuery();
|
||||
report_pg_error(MOT::RC_ERROR, NULL); // execution control ends, calls ereport(error,...)
|
||||
report_pg_error(MOT::RC_ERROR); // execution control ends, calls ereport(error,...)
|
||||
}
|
||||
|
||||
// when running under thread-pool, it is possible to be executed from a thread that hasn't yet executed any MOT code
|
||||
|
|
@ -380,7 +383,7 @@ extern int JitExecQuery(
|
|||
"Execute JIT",
|
||||
"Cannot execute jitted code: Current transaction is undefined. Aborting transaction.");
|
||||
JitStatisticsProvider::GetInstance().AddFailExecQuery();
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR, NULL); // execution control ends, calls ereport(error,...)
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR); // execution control ends, calls ereport(error,...)
|
||||
}
|
||||
|
||||
// during the very first invocation of the query we need to setup the reusable search keys
|
||||
|
|
@ -391,7 +394,7 @@ extern int JitExecQuery(
|
|||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_OOM, "Execute JIT", "Failed to prepare for executing jitted code, aborting transaction");
|
||||
JitStatisticsProvider::GetInstance().AddFailExecQuery();
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR, NULL); // execution control ends, calls ereport(error,...)
|
||||
report_pg_error(MOT::RC_MEMORY_ALLOCATION_ERROR); // execution control ends, calls ereport(error,...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -494,35 +497,26 @@ extern bool JitInitialize()
|
|||
|
||||
if (JitCanInitThreadCodeGen()) {
|
||||
if (IsMotPseudoCodegenForced()) {
|
||||
MOT_LOG_INFO("Forcing TVM on LLVM natively supported platform");
|
||||
MOT_LOG_INFO("Forcing TVM on LLVM natively supported platform by user configuration");
|
||||
g_instance.mot_cxt.jitExecMode = JIT_EXEC_MODE_TVM;
|
||||
} else {
|
||||
PrintNativeLlvmStartupInfo();
|
||||
g_instance.mot_cxt.jitExecMode = JIT_EXEC_MODE_LLVM;
|
||||
}
|
||||
} else {
|
||||
MOT_LOG_INFO("Using TVM on LLVM natively unsupported platform");
|
||||
if (IsMotPseudoCodegenForced()) {
|
||||
MOT_LOG_INFO("Forcing TVM on LLVM natively unsupported platform by user configuration");
|
||||
} else {
|
||||
MOT_LOG_WARN("Defaulting to TVM on LLVM natively unsupported platform");
|
||||
}
|
||||
g_instance.mot_cxt.jitExecMode = JIT_EXEC_MODE_TVM;
|
||||
}
|
||||
|
||||
enum InitState {
|
||||
JIT_INIT,
|
||||
JIT_ARM_LOCK_INIT,
|
||||
JIT_CTX_POOL_INIT,
|
||||
JIT_SRC_POOL_INIT,
|
||||
JIT_INIT_DONE
|
||||
} initState = JIT_INIT;
|
||||
enum InitState { JIT_INIT, JIT_CTX_POOL_INIT, JIT_SRC_POOL_INIT, JIT_INIT_DONE } initState = JIT_INIT;
|
||||
bool result = true;
|
||||
|
||||
// instead of goto
|
||||
do {
|
||||
// initialize ARM compile lock
|
||||
#ifdef __aarch64__
|
||||
result = InitArmCompileLock();
|
||||
#endif
|
||||
if (!result) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "JIT Initialization", "Failed to initialize compilation lock for ARM");
|
||||
break;
|
||||
}
|
||||
initState = JIT_ARM_LOCK_INIT;
|
||||
|
||||
// initialize global JIT context pool
|
||||
result = InitGlobalJitContextPool();
|
||||
if (!result) {
|
||||
|
|
@ -565,11 +559,6 @@ extern bool JitInitialize()
|
|||
case JIT_CTX_POOL_INIT:
|
||||
DestroyGlobalJitContextPool();
|
||||
// fall through
|
||||
case JIT_ARM_LOCK_INIT:
|
||||
#ifdef __aarch64__
|
||||
DestroyArmCompileLock();
|
||||
#endif
|
||||
// fall through
|
||||
case JIT_INIT:
|
||||
default:
|
||||
break;
|
||||
|
|
@ -583,14 +572,11 @@ extern void JitDestroy()
|
|||
DestroyJitSourceMap();
|
||||
DestroyJitSourcePool();
|
||||
DestroyGlobalJitContextPool();
|
||||
#ifdef __aarch64__
|
||||
DestroyArmCompileLock();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern bool IsMotCodegenEnabled()
|
||||
{
|
||||
return MOT_ATOMIC_LOAD(MOT::GetGlobalConfiguration().m_enableCodegen);
|
||||
return MOT::GetGlobalConfiguration().m_enableCodegen;
|
||||
}
|
||||
|
||||
extern bool IsMotPseudoCodegenForced()
|
||||
|
|
@ -607,9 +593,4 @@ extern uint32_t GetMotCodegenLimit()
|
|||
{
|
||||
return MOT::GetGlobalConfiguration().m_codegenLimit;
|
||||
}
|
||||
|
||||
extern void DisableMotCodegen()
|
||||
{
|
||||
MOT_ATOMIC_STORE(MOT::GetGlobalConfiguration().m_enableCodegen, false);
|
||||
}
|
||||
} // namespace JitExec
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// be careful to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h
|
||||
#include "global.h"
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "access/xact.h"
|
||||
#include "utils/array.h"
|
||||
|
|
|
|||
|
|
@ -22,11 +22,12 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
// and c.h (included in postgres.h).
|
||||
#include "global.h"
|
||||
|
||||
// be careful to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "pgxc/pgxc.h"
|
||||
#include "storage/mot/jit_exec.h"
|
||||
|
|
@ -42,83 +43,20 @@ DECLARE_LOGGER(JitLlvm, JitExec);
|
|||
|
||||
using namespace dorado;
|
||||
|
||||
#ifdef __aarch64__
|
||||
// on ARM platforms we experienced instability during concurrent JIT compilation, so we use a spin-lock
|
||||
/** @var The global ARM compilation lock. */
|
||||
static pthread_spinlock_t _arm_compile_lock;
|
||||
|
||||
/** @var Denotes whether the global ARM compilation lock initialization was already attempted. */
|
||||
static int _arm_compile_lock_initialized = 0;
|
||||
|
||||
/** @var Denote the global ARM compilation lock is initialized and ready for use. */
|
||||
static bool _arm_compile_lock_ready = false;
|
||||
|
||||
/** @brief Initializes the global ARM compilation lock. */
|
||||
bool InitArmCompileLock()
|
||||
{
|
||||
bool result = true;
|
||||
if (MOT_ATOMIC_CAS(_arm_compile_lock_initialized, 0, 1)) {
|
||||
int res = pthread_spin_init(&_arm_compile_lock, 0);
|
||||
if (res != 0) {
|
||||
MOT_REPORT_SYSTEM_ERROR_CODE(
|
||||
res, pthread_spin_init, "Initialize LLVM", "Failed to initialize compile spin-lock for ARM platform");
|
||||
// turn off JIT
|
||||
DisableMotCodegen();
|
||||
result = false;
|
||||
} else {
|
||||
_arm_compile_lock_ready = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @brief Destroys the global ARM compilation lock. */
|
||||
void DestroyArmCompileLock()
|
||||
{
|
||||
if (_arm_compile_lock_ready) {
|
||||
int res = pthread_spin_destroy(&_arm_compile_lock);
|
||||
if (res != 0) {
|
||||
MOT_REPORT_SYSTEM_ERROR_CODE(
|
||||
res, pthread_spin_init, "Initialize LLVM", "Failed to destroy compile spin-lock for ARM platform");
|
||||
} else {
|
||||
_arm_compile_lock_ready = false;
|
||||
MOT_ATOMIC_STORE(_arm_compile_lock_initialized, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Locks the global ARM compilation lock. */
|
||||
bool AcquireArmCompileLock()
|
||||
{
|
||||
bool result = false;
|
||||
int res = pthread_spin_lock(&_arm_compile_lock);
|
||||
if (res != 0) {
|
||||
MOT_REPORT_SYSTEM_ERROR_CODE(
|
||||
res, pthread_spin_init, "Compile LLVM", "Failed to acquire compile spin-lock for ARM platform");
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @brief Unlocks the global ARM compilation lock. */
|
||||
bool ReleaseArmCompileLock()
|
||||
{
|
||||
bool result = false;
|
||||
int res = pthread_spin_unlock(&_arm_compile_lock);
|
||||
if (res != 0) {
|
||||
MOT_REPORT_SYSTEM_ERROR_CODE(
|
||||
res, pthread_spin_init, "Compile LLVM", "Failed to release compile spin-lock for ARM platform");
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @brief Checks whether the current platforms natively supports LLVM. */
|
||||
extern bool JitCanInitThreadCodeGen()
|
||||
bool JitCanInitThreadCodeGen()
|
||||
{
|
||||
// Make sure that system type is not generic.
|
||||
llvm::StringRef hostCPUName = llvm::sys::getHostCPUName();
|
||||
MOT_LOG_INFO("LLVM library detected CPU: %s", hostCPUName.str().c_str());
|
||||
if (hostCPUName.empty() || hostCPUName.equals("generic")) {
|
||||
MOT_LOG_WARN("LLVM library detected unknown generic system: disabling native LLVM");
|
||||
MOT_LOG_WARN("LLVM default target triple is: %s, process triple is: %s",
|
||||
llvm::sys::getDefaultTargetTriple().c_str(),
|
||||
llvm::sys::getProcessTriple().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
return true; // Using native llvm on ARM
|
||||
#else
|
||||
|
|
@ -126,9 +64,7 @@ extern bool JitCanInitThreadCodeGen()
|
|||
if (IS_PGXC_DATANODE && IsMotCodegenEnabled()) {
|
||||
canInit = GlobalCodeGenEnvironmentSuccess;
|
||||
if (!canInit) {
|
||||
// turn off JIT
|
||||
DisableMotCodegen();
|
||||
MOT_LOG_WARN("SSE4.2 is not supported, disable codegen.");
|
||||
MOT_LOG_WARN("LLVM environment is not initialized, native LLVM will not be used.");
|
||||
}
|
||||
}
|
||||
return canInit;
|
||||
|
|
@ -138,23 +74,7 @@ extern bool JitCanInitThreadCodeGen()
|
|||
/** @brief Prepares for code generation. */
|
||||
GsCodeGen* SetupCodegenEnv()
|
||||
{
|
||||
// verify that native LLVM is supported
|
||||
if (!t_thrd.mot_cxt.init_codegen_once) {
|
||||
t_thrd.mot_cxt.init_codegen_once = true;
|
||||
if (!JitCanInitThreadCodeGen()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// on ARM platform we need to make sure that the compile lock was initialized properly
|
||||
#ifdef __aarch64__
|
||||
if (!_arm_compile_lock_ready) {
|
||||
MOT_LOG_TRACE("Previous attempt to initialize compilation lock on ARM failed. Code generation is disabled.");
|
||||
// turn off JIT
|
||||
DisableMotCodegen();
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
MOT_ASSERT(g_instance.mot_cxt.jitExecMode == JIT_EXEC_MODE_LLVM);
|
||||
|
||||
// create GsCodeGen object for LLVM code generation
|
||||
GsCodeGen* code_gen = New(g_instance.instance_context) GsCodeGen();
|
||||
|
|
|
|||
|
|
@ -62,28 +62,11 @@ typedef int (*JitFunc)(MOT::Table* table, MOT::Index* index, MOT::Key* key, MOT:
|
|||
// the number of arguments in the jitted function
|
||||
#define MOT_JIT_FUNC_ARG_COUNT 14
|
||||
|
||||
#ifdef __aarch64__
|
||||
/**
|
||||
* @brief Initializes the global spin-lock used for synchronizing native-LLVM compilation.
|
||||
* @return True if operation succeeded, otherwise false.
|
||||
*/
|
||||
bool InitArmCompileLock();
|
||||
|
||||
/** @brief Destroys the global spin-lock used for synchronizing native-LLVM compilation. */
|
||||
void DestroyArmCompileLock();
|
||||
|
||||
/** @brief Locks the global ARM compilation lock. */
|
||||
bool AcquireArmCompileLock();
|
||||
|
||||
/** @brief Unlocks the global ARM compilation lock. */
|
||||
bool ReleaseArmCompileLock();
|
||||
#endif
|
||||
|
||||
/** @brief Prints startup information regarding LLVM version. */
|
||||
void PrintNativeLlvmStartupInfo();
|
||||
|
||||
/** @brief Checks whether the current platforms natively supports LLVM. */
|
||||
extern bool JitCanInitThreadCodeGen();
|
||||
bool JitCanInitThreadCodeGen();
|
||||
|
||||
/** @brief Allocates a GsCodeGen object. */
|
||||
dorado::GsCodeGen* SetupCodegenEnv();
|
||||
|
|
|
|||
|
|
@ -22,14 +22,33 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "jit_llvm_funcs.h"
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_llvm_query.h before anything else because of gscodegen.h
|
||||
* (jit_llvm_blocks.h includes jit_llvm_query.h before anything else).
|
||||
* See jit_llvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_llvm_blocks.h"
|
||||
#include "jit_llvm_funcs.h"
|
||||
#include "jit_util.h"
|
||||
#include "mot_error.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "catalog/pg_aggregate.h"
|
||||
|
||||
using namespace dorado;
|
||||
|
||||
namespace JitExec {
|
||||
DECLARE_LOGGER(JitLlvmBlocks, JitExec)
|
||||
|
||||
static bool ProcessJoinOpExpr(
|
||||
JitLlvmCodeGenContext* ctx, const OpExpr* op_expr, int* column_count, int* column_array, int* max_arg);
|
||||
static bool ProcessJoinBoolExpr(
|
||||
JitLlvmCodeGenContext* ctx, const BoolExpr* boolexpr, int* column_count, int* column_array, int* max_arg);
|
||||
static llvm::Value* ProcessFilterExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg);
|
||||
static llvm::Value* ProcessExpr(
|
||||
JitLlvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
static llvm::Value* ProcessExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitExpr* expr, int* max_arg);
|
||||
|
||||
/*--------------------------- Helpers to generate compound LLVM code ---------------------------*/
|
||||
/** @brief Builds a code segment for checking if soft memory limit has been reached. */
|
||||
void buildIsSoftMemoryLimitReached(JitLlvmCodeGenContext* ctx)
|
||||
|
|
@ -45,7 +64,7 @@ void buildIsSoftMemoryLimitReached(JitLlvmCodeGenContext* ctx)
|
|||
}
|
||||
|
||||
/** @brief Builds a code segment for writing datum value to a column. */
|
||||
void buildWriteDatumColumn(JitLlvmCodeGenContext* ctx, llvm::Value* row, int colid, llvm::Value* datum_value)
|
||||
static void buildWriteDatumColumn(JitLlvmCodeGenContext* ctx, llvm::Value* row, int colid, llvm::Value* datum_value)
|
||||
{
|
||||
llvm::Value* set_null_bit_res = AddSetExprResultNullBit(ctx, row, colid);
|
||||
IssueDebugLog("Set null bit");
|
||||
|
|
@ -85,7 +104,7 @@ void buildWriteRow(JitLlvmCodeGenContext* ctx, llvm::Value* row, bool isPKey, Ji
|
|||
}
|
||||
|
||||
/** @brief Process a join expression (WHERE clause) and generate code to build a search key. */
|
||||
bool ProcessJoinExpr(JitLlvmCodeGenContext* ctx, Expr* expr, int* column_count, int* column_array, int* max_arg)
|
||||
static bool ProcessJoinExpr(JitLlvmCodeGenContext* ctx, Expr* expr, int* column_count, int* column_array, int* max_arg)
|
||||
{
|
||||
bool result = false;
|
||||
if (expr->type == T_OpExpr) {
|
||||
|
|
@ -99,7 +118,7 @@ bool ProcessJoinExpr(JitLlvmCodeGenContext* ctx, Expr* expr, int* column_count,
|
|||
}
|
||||
|
||||
/** @brief Process an operator expression (process only "COLUMN equals EXPR" operators). */
|
||||
bool ProcessJoinOpExpr(
|
||||
static bool ProcessJoinOpExpr(
|
||||
JitLlvmCodeGenContext* ctx, const OpExpr* op_expr, int* column_count, int* column_array, int* max_arg)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -171,7 +190,7 @@ bool ProcessJoinOpExpr(
|
|||
|
||||
/** @brief Process a boolean operator (process only AND operators, since we handle only point queries, or full-prefix
|
||||
* range update). */
|
||||
bool ProcessJoinBoolExpr(
|
||||
static bool ProcessJoinBoolExpr(
|
||||
JitLlvmCodeGenContext* ctx, const BoolExpr* boolexpr, int* column_count, int* column_array, int* max_arg)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -289,7 +308,7 @@ llvm::Value* buildSearchRow(JitLlvmCodeGenContext* ctx, MOT::AccessType access_t
|
|||
return row;
|
||||
}
|
||||
|
||||
llvm::Value* buildFilter(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg)
|
||||
static llvm::Value* buildFilter(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
llvm::Value* lhs_expr = ProcessExpr(ctx, row, filter->_lhs_operand, max_arg);
|
||||
|
|
@ -365,8 +384,8 @@ void buildDeleteRow(JitLlvmCodeGenContext* ctx)
|
|||
}
|
||||
|
||||
/** @brief Adds code to search for an iterator. */
|
||||
llvm::Value* buildSearchIterator(JitLlvmCodeGenContext* ctx, JitIndexScanDirection index_scan_direction,
|
||||
JitRangeBoundMode range_bound_mode, JitRangeScanType range_scan_type, int subQueryIndex /* = -1 */)
|
||||
static llvm::Value* buildSearchIterator(JitLlvmCodeGenContext* ctx, JitIndexScanDirection index_scan_direction,
|
||||
JitRangeBoundMode range_bound_mode, JitRangeScanType range_scan_type, int subQueryIndex = -1)
|
||||
{
|
||||
// search the row
|
||||
IssueDebugLog("Searching range start");
|
||||
|
|
@ -383,8 +402,8 @@ llvm::Value* buildSearchIterator(JitLlvmCodeGenContext* ctx, JitIndexScanDirecti
|
|||
}
|
||||
|
||||
/** @brief Adds code to search for an iterator. */
|
||||
llvm::Value* buildBeginIterator(
|
||||
JitLlvmCodeGenContext* ctx, JitRangeScanType rangeScanType, int subQueryIndex /* = -1 */)
|
||||
static llvm::Value* buildBeginIterator(
|
||||
JitLlvmCodeGenContext* ctx, JitRangeScanType rangeScanType, int subQueryIndex = -1)
|
||||
{
|
||||
// search the row
|
||||
IssueDebugLog("Getting begin iterator for full-scan");
|
||||
|
|
@ -421,7 +440,7 @@ llvm::Value* buildGetRowFromIterator(JitLlvmCodeGenContext* ctx, llvm::BasicBloc
|
|||
}
|
||||
|
||||
/** @brief Process constant expression. */
|
||||
llvm::Value* ProcessConstExpr(
|
||||
static llvm::Value* ProcessConstExpr(
|
||||
JitLlvmCodeGenContext* ctx, const Const* const_value, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
|
@ -446,7 +465,7 @@ llvm::Value* ProcessConstExpr(
|
|||
}
|
||||
|
||||
/** @brief Process Param expression. */
|
||||
llvm::Value* ProcessParamExpr(
|
||||
static llvm::Value* ProcessParamExpr(
|
||||
JitLlvmCodeGenContext* ctx, const Param* param, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
|
@ -470,7 +489,7 @@ llvm::Value* ProcessParamExpr(
|
|||
}
|
||||
|
||||
/** @brief Process Relabel expression as Param expression. */
|
||||
llvm::Value* ProcessRelabelExpr(
|
||||
static llvm::Value* ProcessRelabelExpr(
|
||||
JitLlvmCodeGenContext* ctx, RelabelType* relabel_type, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
|
@ -486,7 +505,7 @@ llvm::Value* ProcessRelabelExpr(
|
|||
}
|
||||
|
||||
/** @brief Proess Var expression. */
|
||||
llvm::Value* ProcessVarExpr(
|
||||
static llvm::Value* ProcessVarExpr(
|
||||
JitLlvmCodeGenContext* ctx, const Var* var, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
|
@ -511,7 +530,7 @@ llvm::Value* ProcessVarExpr(
|
|||
}
|
||||
|
||||
/** @brief Adds call to PG unary operator. */
|
||||
llvm::Value* AddExecUnaryOperator(
|
||||
static llvm::Value* AddExecUnaryOperator(
|
||||
JitLlvmCodeGenContext* ctx, llvm::Value* param, llvm::Constant* unary_operator, int arg_pos)
|
||||
{
|
||||
llvm::Constant* arg_pos_value = llvm::ConstantInt::get(ctx->INT32_T, arg_pos, true);
|
||||
|
|
@ -519,7 +538,7 @@ llvm::Value* AddExecUnaryOperator(
|
|||
}
|
||||
|
||||
/** @brief Adds call to PG binary operator. */
|
||||
llvm::Value* AddExecBinaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* lhs_param, llvm::Value* rhs_param,
|
||||
static llvm::Value* AddExecBinaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* lhs_param, llvm::Value* rhs_param,
|
||||
llvm::Constant* binary_operator, int arg_pos)
|
||||
{
|
||||
llvm::Constant* arg_pos_value = llvm::ConstantInt::get(ctx->INT32_T, arg_pos, true);
|
||||
|
|
@ -527,7 +546,7 @@ llvm::Value* AddExecBinaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* lhs_
|
|||
}
|
||||
|
||||
/** @brief Adds call to PG ternary operator. */
|
||||
llvm::Value* AddExecTernaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* param1, llvm::Value* param2,
|
||||
static llvm::Value* AddExecTernaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* param1, llvm::Value* param2,
|
||||
llvm::Value* param3, llvm::Constant* ternary_operator, int arg_pos)
|
||||
{
|
||||
llvm::Constant* arg_pos_value = llvm::ConstantInt::get(ctx->INT32_T, arg_pos, true);
|
||||
|
|
@ -557,7 +576,7 @@ llvm::Value* AddExecTernaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* par
|
|||
#define APPLY_TERNARY_CAST_OPERATOR(funcid, name) APPLY_TERNARY_OPERATOR(funcid, name)
|
||||
|
||||
/** @brief Process operator expression. */
|
||||
llvm::Value* ProcessOpExpr(
|
||||
static llvm::Value* ProcessOpExpr(
|
||||
JitLlvmCodeGenContext* ctx, const OpExpr* op_expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
|
@ -568,7 +587,7 @@ llvm::Value* ProcessOpExpr(
|
|||
}
|
||||
|
||||
if (list_length(op_expr->args) > 3) {
|
||||
MOT_LOG_TRACE("Unsupported operator %d: too many arguments", op_expr->opno);
|
||||
MOT_LOG_TRACE("Unsupported operator %u: too many arguments", op_expr->opno);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -605,7 +624,7 @@ llvm::Value* ProcessOpExpr(
|
|||
}
|
||||
|
||||
/** @brief Process function expression. */
|
||||
llvm::Value* ProcessFuncExpr(
|
||||
static llvm::Value* ProcessFuncExpr(
|
||||
JitLlvmCodeGenContext* ctx, const FuncExpr* func_expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
|
@ -678,7 +697,7 @@ llvm::Value* ProcessFuncExpr(
|
|||
MOT_LOG_TRACE("Unexpected call in filter expression to ternary cast builtin: " #name); \
|
||||
break;
|
||||
|
||||
llvm::Value* ProcessFilterExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg)
|
||||
static llvm::Value* ProcessFilterExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
||||
|
|
@ -716,7 +735,8 @@ llvm::Value* ProcessFilterExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, Jit
|
|||
#undef APPLY_TERNARY_CAST_OPERATOR
|
||||
|
||||
/** @brief Process an expression. Generates code to evaluate the expression. */
|
||||
llvm::Value* ProcessExpr(JitLlvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
static llvm::Value* ProcessExpr(
|
||||
JitLlvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
MOT_LOG_DEBUG("%*s --> Processing expression %d", depth, "", (int)expr->type);
|
||||
|
|
@ -747,7 +767,7 @@ llvm::Value* ProcessExpr(JitLlvmCodeGenContext* ctx, Expr* expr, int& result_typ
|
|||
return result;
|
||||
}
|
||||
|
||||
llvm::Value* ProcessConstExpr(JitLlvmCodeGenContext* ctx, const JitConstExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessConstExpr(JitLlvmCodeGenContext* ctx, const JitConstExpr* expr, int* max_arg)
|
||||
{
|
||||
AddSetExprArgIsNull(ctx, expr->_arg_pos, expr->_is_null); // mark expression null status
|
||||
llvm::Value* result = llvm::ConstantInt::get(ctx->INT64_T, expr->_value, true);
|
||||
|
|
@ -757,7 +777,7 @@ llvm::Value* ProcessConstExpr(JitLlvmCodeGenContext* ctx, const JitConstExpr* ex
|
|||
return result;
|
||||
}
|
||||
|
||||
llvm::Value* ProcessParamExpr(JitLlvmCodeGenContext* ctx, const JitParamExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessParamExpr(JitLlvmCodeGenContext* ctx, const JitParamExpr* expr, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = AddGetDatumParam(ctx, expr->_param_id, expr->_arg_pos);
|
||||
if (max_arg && (expr->_arg_pos > *max_arg)) {
|
||||
|
|
@ -766,7 +786,7 @@ llvm::Value* ProcessParamExpr(JitLlvmCodeGenContext* ctx, const JitParamExpr* ex
|
|||
return result;
|
||||
}
|
||||
|
||||
llvm::Value* ProcessVarExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, const JitVarExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessVarExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, const JitVarExpr* expr, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
if (row == nullptr) {
|
||||
|
|
@ -804,7 +824,7 @@ llvm::Value* ProcessVarExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, const
|
|||
#define APPLY_BINARY_CAST_OPERATOR(funcid, name) APPLY_BINARY_OPERATOR(funcid, name)
|
||||
#define APPLY_TERNARY_CAST_OPERATOR(funcid, name) APPLY_TERNARY_OPERATOR(funcid, name)
|
||||
|
||||
llvm::Value* ProcessOpExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitOpExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessOpExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitOpExpr* expr, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
||||
|
|
@ -830,7 +850,7 @@ llvm::Value* ProcessOpExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitOpEx
|
|||
return result;
|
||||
}
|
||||
|
||||
llvm::Value* ProcessFuncExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFuncExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessFuncExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFuncExpr* expr, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
||||
|
|
@ -863,12 +883,12 @@ llvm::Value* ProcessFuncExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFu
|
|||
#undef APPLY_BINARY_CAST_OPERATOR
|
||||
#undef APPLY_TERNARY_CAST_OPERATOR
|
||||
|
||||
llvm::Value* ProcessSubLinkExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitSubLinkExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessSubLinkExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitSubLinkExpr* expr, int* max_arg)
|
||||
{
|
||||
return AddSelectSubQueryResult(ctx, expr->_sub_query_index);
|
||||
}
|
||||
|
||||
llvm::Value* ProcessBoolExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitBoolExpr* expr, int* maxArg)
|
||||
static llvm::Value* ProcessBoolExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitBoolExpr* expr, int* maxArg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
||||
|
|
@ -909,7 +929,7 @@ llvm::Value* ProcessBoolExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitBo
|
|||
return result;
|
||||
}
|
||||
|
||||
llvm::Value* ProcessExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitExpr* expr, int* max_arg)
|
||||
static llvm::Value* ProcessExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitExpr* expr, int* max_arg)
|
||||
{
|
||||
llvm::Value* result = nullptr;
|
||||
|
||||
|
|
@ -1064,7 +1084,7 @@ bool selectRowColumns(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitSelectExp
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildClosedRangeScan(JitLlvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
static bool buildClosedRangeScan(JitLlvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, llvm::Value* outer_row, int subQueryIndex)
|
||||
{
|
||||
// a closed range scan starts just like a point scan (without enough search expressions) and then adds key patterns
|
||||
|
|
@ -1699,7 +1719,7 @@ bool prepareAggregateCount(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool prepareDistinctSet(JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
static bool prepareDistinctSet(JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
{
|
||||
// we need a hash-set according to the aggregated type (preferably but not necessarily linear-probing hash)
|
||||
// we use an opaque datum type, with a tailor-made hash-function and equals function
|
||||
|
|
@ -1746,7 +1766,7 @@ bool prepareAggregate(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate)
|
|||
return result;
|
||||
}
|
||||
|
||||
llvm::Value* buildAggregateAvg(
|
||||
static llvm::Value* buildAggregateAvg(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr)
|
||||
{
|
||||
llvm::Value* aggregate_expr = nullptr;
|
||||
|
|
@ -1802,7 +1822,7 @@ llvm::Value* buildAggregateAvg(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
llvm::Value* buildAggregateSum(
|
||||
static llvm::Value* buildAggregateSum(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr)
|
||||
{
|
||||
llvm::Value* aggregate_expr = nullptr;
|
||||
|
|
@ -1845,7 +1865,7 @@ llvm::Value* buildAggregateSum(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
llvm::Value* buildAggregateMax(
|
||||
static llvm::Value* buildAggregateMax(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr)
|
||||
{
|
||||
llvm::Value* aggregate_expr = nullptr;
|
||||
|
|
@ -1913,7 +1933,7 @@ llvm::Value* buildAggregateMax(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
llvm::Value* buildAggregateMin(
|
||||
static llvm::Value* buildAggregateMin(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr)
|
||||
{
|
||||
llvm::Value* aggregate_expr = nullptr;
|
||||
|
|
@ -1977,7 +1997,7 @@ llvm::Value* buildAggregateMin(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
llvm::Value* buildAggregateCount(
|
||||
static llvm::Value* buildAggregateCount(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* count_aggregate)
|
||||
{
|
||||
llvm::Value* aggregate_expr = nullptr;
|
||||
|
|
@ -2000,7 +2020,7 @@ llvm::Value* buildAggregateCount(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
bool buildAggregateMaxMin(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* var_expr)
|
||||
static bool buildAggregateMaxMin(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* var_expr)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
|
|
@ -2033,7 +2053,7 @@ bool buildAggregateMaxMin(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, l
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildAggregateTuple(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* var_expr)
|
||||
static bool buildAggregateTuple(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* var_expr)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,32 +25,21 @@
|
|||
#ifndef JIT_LLVM_BLOCKS_H
|
||||
#define JIT_LLVM_BLOCKS_H
|
||||
|
||||
// Be sure to include jit_llvm_query.h before anything else because of global.h.
|
||||
// See jit_llvm_query.h for more details.
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_llvm_query.h before anything else because of gscodegen.h
|
||||
* See jit_llvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_llvm_query.h"
|
||||
#include "jit_plan.h"
|
||||
#include "jit_llvm_util.h"
|
||||
|
||||
namespace JitExec {
|
||||
/** @brief Builds a code segment for checking if soft memory limit has been reached. */
|
||||
void buildIsSoftMemoryLimitReached(JitLlvmCodeGenContext* ctx);
|
||||
|
||||
/** @brief Builds a code segment for writing datum value to a column. */
|
||||
void buildWriteDatumColumn(JitLlvmCodeGenContext* ctx, llvm::Value* row, int colid, llvm::Value* datum_value);
|
||||
|
||||
/** @brief Builds a code segment for writing a row. */
|
||||
void buildWriteRow(JitLlvmCodeGenContext* ctx, llvm::Value* row, bool isPKey, JitLlvmRuntimeCursor* cursor);
|
||||
|
||||
/** @brief Process a join expression (WHERE clause) and generate code to build a search key. */
|
||||
bool ProcessJoinExpr(JitLlvmCodeGenContext* ctx, Expr* expr, int* column_count, int* column_array, int* max_arg);
|
||||
|
||||
/** @brief Process an operator expression (process only "COLUMN equals EXPR" operators). */
|
||||
bool ProcessJoinOpExpr(
|
||||
JitLlvmCodeGenContext* ctx, const OpExpr* op_expr, int* column_count, int* column_array, int* max_arg);
|
||||
|
||||
/** @brief Process a boolean operator (process only AND operators, since we handle only point queries, or full-prefix
|
||||
* range update). */
|
||||
bool ProcessJoinBoolExpr(
|
||||
JitLlvmCodeGenContext* ctx, const BoolExpr* boolexpr, int* column_count, int* column_array, int* max_arg);
|
||||
|
||||
/** @brief Creates a jitted function for code generation. Builds prototype and entry block. */
|
||||
void CreateJittedFunction(JitLlvmCodeGenContext* ctx, const char* function_name);
|
||||
|
||||
|
|
@ -67,8 +56,6 @@ llvm::Value* buildCreateNewRow(JitLlvmCodeGenContext* ctx);
|
|||
llvm::Value* buildSearchRow(
|
||||
JitLlvmCodeGenContext* ctx, MOT::AccessType access_type, JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
llvm::Value* buildFilter(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg);
|
||||
|
||||
bool buildFilterRow(
|
||||
JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilterArray* filters, int* max_arg, llvm::BasicBlock* next_block);
|
||||
|
||||
|
|
@ -78,76 +65,11 @@ void buildInsertRow(JitLlvmCodeGenContext* ctx, llvm::Value* row);
|
|||
/** @brief Adds code to delete a row. */
|
||||
void buildDeleteRow(JitLlvmCodeGenContext* ctx);
|
||||
|
||||
/** @brief Adds code to search for an iterator. */
|
||||
llvm::Value* buildSearchIterator(JitLlvmCodeGenContext* ctx, JitIndexScanDirection index_scan_direction,
|
||||
JitRangeBoundMode range_bound_mode, JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
/** @brief Adds code to search for an iterator. */
|
||||
llvm::Value* buildBeginIterator(JitLlvmCodeGenContext* ctx, JitRangeScanType rangeScanType, int subQueryIndex = -1);
|
||||
|
||||
/** @brief Adds code to get row from iterator. */
|
||||
llvm::Value* buildGetRowFromIterator(JitLlvmCodeGenContext* ctx, llvm::BasicBlock* endLoopBlock,
|
||||
MOT::AccessType access_mode, JitIndexScanDirection index_scan_direction, JitLlvmRuntimeCursor* cursor,
|
||||
JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
/** @brief Process constant expression. */
|
||||
llvm::Value* ProcessConstExpr(
|
||||
JitLlvmCodeGenContext* ctx, const Const* const_value, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
/** @brief Process Param expression. */
|
||||
llvm::Value* ProcessParamExpr(
|
||||
JitLlvmCodeGenContext* ctx, const Param* param, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
/** @brief Process Relabel expression as Param expression. */
|
||||
llvm::Value* ProcessRelabelExpr(
|
||||
JitLlvmCodeGenContext* ctx, RelabelType* relabel_type, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
/** @brief Proess Var expression. */
|
||||
llvm::Value* ProcessVarExpr(
|
||||
JitLlvmCodeGenContext* ctx, const Var* var, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
/** @brief Adds call to PG unary operator. */
|
||||
llvm::Value* AddExecUnaryOperator(
|
||||
JitLlvmCodeGenContext* ctx, llvm::Value* param, llvm::Constant* unary_operator, int arg_pos);
|
||||
|
||||
/** @brief Adds call to PG binary operator. */
|
||||
llvm::Value* AddExecBinaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* lhs_param, llvm::Value* rhs_param,
|
||||
llvm::Constant* binary_operator, int arg_pos);
|
||||
|
||||
/** @brief Adds call to PG ternary operator. */
|
||||
llvm::Value* AddExecTernaryOperator(JitLlvmCodeGenContext* ctx, llvm::Value* param1, llvm::Value* param2,
|
||||
llvm::Value* param3, llvm::Constant* ternary_operator, int arg_pos);
|
||||
|
||||
/** @brief Process operator expression. */
|
||||
llvm::Value* ProcessOpExpr(
|
||||
JitLlvmCodeGenContext* ctx, const OpExpr* op_expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
/** @brief Process function expression. */
|
||||
llvm::Value* ProcessFuncExpr(
|
||||
JitLlvmCodeGenContext* ctx, const FuncExpr* func_expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessFilterExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFilter* filter, int* max_arg);
|
||||
|
||||
/** @brief Process an expression. Generates code to evaluate the expression. */
|
||||
llvm::Value* ProcessExpr(
|
||||
JitLlvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessConstExpr(JitLlvmCodeGenContext* ctx, const JitConstExpr* expr, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessParamExpr(JitLlvmCodeGenContext* ctx, const JitParamExpr* expr, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessVarExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, const JitVarExpr* expr, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessOpExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitOpExpr* expr, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessFuncExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitFuncExpr* expr, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessSubLinkExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitSubLinkExpr* expr, int* max_arg);
|
||||
|
||||
llvm::Value* ProcessBoolExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitBoolExpr* expr, int* maxArg);
|
||||
|
||||
llvm::Value* ProcessExpr(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitExpr* expr, int* max_arg);
|
||||
|
||||
bool buildScanExpression(JitLlvmCodeGenContext* ctx, JitColumnExpr* expr, int* max_arg,
|
||||
JitRangeIteratorType range_itr_type, JitRangeScanType range_scan_type, llvm::Value* outer_row, int subQueryIndex);
|
||||
|
||||
|
|
@ -160,9 +82,6 @@ bool writeRowColumns(
|
|||
bool selectRowColumns(JitLlvmCodeGenContext* ctx, llvm::Value* row, JitSelectExprArray* expr_array, int* max_arg,
|
||||
JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
bool buildClosedRangeScan(JitLlvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, llvm::Value* outer_row, int subQueryIndex);
|
||||
|
||||
bool buildSemiOpenRangeScan(JitLlvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg,
|
||||
JitRangeScanType rangeScanType, JitRangeBoundMode* beginRangeBound, JitRangeBoundMode* endRangeBound,
|
||||
llvm::Value* outerRow, int subQueryIndex);
|
||||
|
|
@ -197,29 +116,8 @@ bool prepareAggregateMaxMin(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate)
|
|||
|
||||
bool prepareAggregateCount(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate);
|
||||
|
||||
bool prepareDistinctSet(JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate);
|
||||
|
||||
bool prepareAggregate(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate);
|
||||
|
||||
llvm::Value* buildAggregateAvg(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr);
|
||||
|
||||
llvm::Value* buildAggregateSum(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr);
|
||||
|
||||
llvm::Value* buildAggregateMax(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr);
|
||||
|
||||
llvm::Value* buildAggregateMin(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* current_aggregate, llvm::Value* var_expr);
|
||||
|
||||
llvm::Value* buildAggregateCount(
|
||||
JitLlvmCodeGenContext* ctx, const JitAggregate* aggregate, llvm::Value* count_aggregate);
|
||||
|
||||
bool buildAggregateMaxMin(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* var_expr);
|
||||
|
||||
bool buildAggregateTuple(JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* var_expr);
|
||||
|
||||
bool buildAggregateRow(
|
||||
JitLlvmCodeGenContext* ctx, JitAggregate* aggregate, llvm::Value* row, llvm::BasicBlock* next_block);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,14 @@
|
|||
#ifndef JIT_LLVM_FUNCS_H
|
||||
#define JIT_LLVM_FUNCS_H
|
||||
|
||||
// Be sure to include jit_llvm_query.h before anything else because of global.h.
|
||||
// See jit_llvm_query.h for more details.
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_llvm_query.h before anything else because of gscodegen.h
|
||||
* See jit_llvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_llvm_query.h"
|
||||
#include "jit_plan.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace JitExec {
|
||||
/** @brief Gets a key from the execution context. */
|
||||
|
|
@ -664,7 +669,7 @@ inline void AddInitSearchKey(JitLlvmCodeGenContext* ctx, JitRangeScanType rangeS
|
|||
AddInitKey(ctx, ctx->inner_key_value, ctx->inner_index_value);
|
||||
} else if (rangeScanType == JIT_RANGE_SCAN_MAIN) {
|
||||
AddInitKey(ctx, ctx->key_value, ctx->index_value);
|
||||
} else if (rangeScanType == JIT_RANGE_SCAN_MAIN) {
|
||||
} else if (rangeScanType == JIT_RANGE_SCAN_SUB_QUERY) {
|
||||
AddInitKey(ctx, ctx->m_subQueryData[subQueryIndex].m_searchKey, ctx->m_subQueryData[subQueryIndex].m_index);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,44 +25,19 @@
|
|||
#ifndef JIT_LLVM_QUERY_H
|
||||
#define JIT_LLVM_QUERY_H
|
||||
|
||||
// Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
// and c.h (included in postgres.h).
|
||||
#include "global.h"
|
||||
|
||||
// be careful to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "codegen/builtinscodegen.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "codegen/datecodegen.h"
|
||||
#include "codegen/timestampcodegen.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "tcop/dest.h"
|
||||
#include "utils/numeric.h"
|
||||
#include "utils/numeric_gs.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
|
||||
#include "mot_internal.h"
|
||||
#include "storage/mot/jit_exec.h"
|
||||
#include "jit_common.h"
|
||||
#include "jit_plan.h"
|
||||
#include "jit_llvm_util.h"
|
||||
#include "jit_util.h"
|
||||
|
||||
#include "mot_engine.h"
|
||||
#include "utilities.h"
|
||||
#include "mot_internal.h"
|
||||
#include "catalog_column_types.h"
|
||||
#include "mot_error.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
// for checking if LLVM_ENABLE_DUMP is defined and for using LLVM_VERSION_STRING
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
|
||||
namespace JitExec {
|
||||
/** @struct Holds instructions that evaluate in runtime to begin and end iterators of a cursor. */
|
||||
|
|
|
|||
|
|
@ -22,13 +22,21 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Be sure to include jit_llvm_query.h before anything else because of global.h.
|
||||
// See jit_llvm_query.h for more details.
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_llvm_query.h before anything else because of gscodegen.h
|
||||
* See jit_llvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_llvm_query.h"
|
||||
#include "jit_llvm_query_codegen.h"
|
||||
#include "jit_llvm.h"
|
||||
#include "jit_llvm_funcs.h"
|
||||
#include "jit_llvm_blocks.h"
|
||||
#include "jit_util.h"
|
||||
#include "mot_error.h"
|
||||
#include "utilities.h"
|
||||
|
||||
// for checking if LLVM_ENABLE_DUMP is defined and for using LLVM_VERSION_STRING
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
|
||||
namespace JitExec {
|
||||
DECLARE_LOGGER(JitLlvmQueryCodegen, JitExec)
|
||||
|
|
@ -274,7 +282,7 @@ static bool InitCompoundCodeGenContext(JitLlvmCodeGenContext* ctx, GsCodeGen* co
|
|||
"Failed to allocate %u bytes for %u sub-query table information objects in code-generation context",
|
||||
allocSize,
|
||||
(unsigned)ctx->m_subQueryCount);
|
||||
DestroyTableInfo(&ctx->_table_info);
|
||||
DestroyCodeGenContext(ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -302,12 +310,7 @@ static bool InitCompoundCodeGenContext(JitLlvmCodeGenContext* ctx, GsCodeGen* co
|
|||
result = false;
|
||||
}
|
||||
if (!result) {
|
||||
for (uint32_t j = 0; j < i; ++j) {
|
||||
DestroyTableInfo(&ctx->m_subQueryTableInfo[j]);
|
||||
}
|
||||
MOT::MemSessionFree(ctx->m_subQueryTableInfo);
|
||||
ctx->m_subQueryTableInfo = nullptr;
|
||||
DestroyTableInfo(&ctx->_table_info);
|
||||
DestroyCodeGenContext(ctx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -322,6 +325,7 @@ static bool InitCompoundCodeGenContext(JitLlvmCodeGenContext* ctx, GsCodeGen* co
|
|||
allocSize,
|
||||
(unsigned)ctx->m_subQueryCount);
|
||||
DestroyCodeGenContext(ctx);
|
||||
return false;
|
||||
}
|
||||
errno_t erc = memset_s(ctx->m_subQueryData, allocSize, 0, allocSize);
|
||||
securec_check(erc, "\0", "\0");
|
||||
|
|
@ -341,6 +345,10 @@ static void DestroyCodeGenContext(JitLlvmCodeGenContext* ctx)
|
|||
MOT::MemSessionFree(ctx->m_subQueryData);
|
||||
ctx->m_subQueryData = nullptr;
|
||||
}
|
||||
if (ctx->m_subQueryTableInfo != nullptr) {
|
||||
MOT::MemSessionFree(ctx->m_subQueryTableInfo);
|
||||
ctx->m_subQueryTableInfo = nullptr;
|
||||
}
|
||||
if (ctx->_code_gen != nullptr) {
|
||||
ctx->_code_gen->releaseResource();
|
||||
delete ctx->_code_gen;
|
||||
|
|
@ -381,30 +389,12 @@ static JitContext* FinalizeCodegen(JitLlvmCodeGenContext* ctx, int max_arg, JitC
|
|||
MOT_LOG_DEBUG("Adding function to MCJit");
|
||||
ctx->_code_gen->addFunctionToMCJit(ctx->m_jittedQuery, (void**)&jit_context->m_llvmFunction);
|
||||
|
||||
// on ARM platform we must ensure compilation is synchronized
|
||||
#ifdef __aarch64__
|
||||
if (!AcquireArmCompileLock()) {
|
||||
MOT_LOG_TRACE("Failed to acquire compilation lock on ARM platform");
|
||||
FreeJitContext(jit_context);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
MOT_LOG_DEBUG("Generating code...");
|
||||
ctx->_code_gen->enableOptimizations(true);
|
||||
ctx->_code_gen->compileCurrentModule(false);
|
||||
MOT_LOG_DEBUG(
|
||||
"MOT jitted query: code generated at %p --> %p", &jit_context->m_llvmFunction, jit_context->m_llvmFunction);
|
||||
|
||||
// on ARM platform we must ensure compilation is synchronized
|
||||
#ifdef __aarch64__
|
||||
if (!ReleaseArmCompileLock()) {
|
||||
MOT_LOG_TRACE("Failed to release compilation lock on ARM platform");
|
||||
FreeJitContext(jit_context);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// setup execution details
|
||||
jit_context->m_table = ctx->_table_info.m_table;
|
||||
jit_context->m_index = ctx->_table_info.m_index;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "jit_llvm_util.h"
|
||||
#include "global.h"
|
||||
#include "utilities.h"
|
||||
#include "knl/knl_session.h"
|
||||
#include "utils/elog.h"
|
||||
|
|
@ -125,7 +125,12 @@ void JitStatement::EvalNot(llvm::Value* value, llvm::BasicBlock* successBlock, l
|
|||
|
||||
bool JitStatement::CurrentBlockEndsInBranch()
|
||||
{
|
||||
return m_builder->GetInsertBlock()->back().isTerminator();
|
||||
bool result = false;
|
||||
llvm::BasicBlock* currentBlock = m_builder->GetInsertBlock();
|
||||
if (!currentBlock->empty()) {
|
||||
result = currentBlock->back().isTerminator();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
JitIf::JitIf(
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
#ifndef JIT_LLVM_UTIL_H
|
||||
#define JIT_LLVM_UTIL_H
|
||||
|
||||
/*
|
||||
* ATTENTION:
|
||||
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
||||
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "jit_common.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@
|
|||
#ifndef JIT_PGPROC_H
|
||||
#define JIT_PGPROC_H
|
||||
|
||||
// make sure to include these headers when using APPLY_OPERATORS macro.
|
||||
// due to collision with LLVM definitions, make sure to include the following files in this order:
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/date.h"
|
||||
#include "utils/int8.h"
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
// and c.h (included in postgres.h).
|
||||
/*
|
||||
* ATTENTION: Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
* and c.h (included in postgres.h).
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "jit_plan.h"
|
||||
#include "jit_common.h"
|
||||
|
|
@ -34,6 +34,8 @@
|
|||
#include "nodes/pg_list.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace JitExec {
|
||||
DECLARE_LOGGER(JitPlan, JitExec)
|
||||
|
||||
|
|
@ -1571,6 +1573,7 @@ static JitPlan* JitPrepareCompoundPlan(Query* query, Query* subQuery)
|
|||
// verify plan yields a single result
|
||||
if (!IsSingleResultPlan(sub_query_plan)) {
|
||||
MOT_LOG_TRACE("Disqualifying sub-query plan: yielding more than one result");
|
||||
JitDestroyPlan(sub_query_plan);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
// and c.h (included in postgres.h).
|
||||
/*
|
||||
* ATTENTION: Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
* and c.h (included in postgres.h).
|
||||
*/
|
||||
#include "global.h"
|
||||
#include "jit_plan_expr.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "jit_common.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace JitExec {
|
||||
/** @enum Index scan direction constants. */
|
||||
enum JitIndexScanDirection {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "utilities.h"
|
||||
#include "mot_error.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
DECLARE_LOGGER(TVM, JitExec)
|
||||
|
||||
namespace tvm {
|
||||
|
|
@ -996,6 +998,9 @@ Instruction* Builder::addInstruction(Instruction* instruction)
|
|||
if (instruction->GetType() == Instruction::Regular) {
|
||||
instruction->SetRegisterRef(_next_register_ref);
|
||||
result = new (std::nothrow) RegisterRefInstruction(_next_register_ref);
|
||||
if (result == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
_current_block->recordRegisterReferenceDefinition(_next_register_ref); // for later validation
|
||||
_current_function->addInstruction(result); // for cleanup only
|
||||
++_next_register_ref;
|
||||
|
|
|
|||
|
|
@ -22,23 +22,42 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Be sure to include jit_tvm_query.h before anything else because of global.h.
|
||||
// See jit_tvm_query.h for more details.
|
||||
#include "jit_tvm_funcs.h"
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_tvm_query.h before anything else because of libintl.h
|
||||
* (jit_tvm_blocks.h includes jit_tvm_query.h before anything else).
|
||||
* See jit_tvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_tvm_blocks.h"
|
||||
#include "jit_tvm_funcs.h"
|
||||
#include "jit_tvm_util.h"
|
||||
#include "jit_util.h"
|
||||
#include "mot_error.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "catalog/pg_aggregate.h"
|
||||
|
||||
using namespace tvm;
|
||||
|
||||
namespace JitExec {
|
||||
DECLARE_LOGGER(JitTvmBlocks, JitExec)
|
||||
|
||||
static bool ProcessJoinOpExpr(
|
||||
JitTvmCodeGenContext* ctx, const OpExpr* op_expr, int* column_count, int* column_array, int* max_arg);
|
||||
static bool ProcessJoinBoolExpr(
|
||||
JitTvmCodeGenContext* ctx, const BoolExpr* boolexpr, int* column_count, int* column_array, int* max_arg);
|
||||
static Instruction* buildExpression(JitTvmCodeGenContext* ctx, Expression* expr);
|
||||
static Expression* ProcessExpr(
|
||||
JitTvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
static Expression* ProcessFilterExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFilter* filter, int* max_arg);
|
||||
static Expression* ProcessExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitExpr* expr, int* max_arg);
|
||||
|
||||
void CreateJittedFunction(JitTvmCodeGenContext* ctx, const char* function_name, const char* query_string)
|
||||
{
|
||||
ctx->m_jittedQuery = ctx->_builder->createFunction(function_name, query_string);
|
||||
IssueDebugLog("Starting execution of jitted function");
|
||||
}
|
||||
|
||||
bool ProcessJoinExpr(JitTvmCodeGenContext* ctx, Expr* expr, int* column_count, int* column_array, int* max_arg)
|
||||
static bool ProcessJoinExpr(JitTvmCodeGenContext* ctx, Expr* expr, int* column_count, int* column_array, int* max_arg)
|
||||
{
|
||||
bool result = false;
|
||||
if (expr->type == T_OpExpr) {
|
||||
|
|
@ -51,7 +70,7 @@ bool ProcessJoinExpr(JitTvmCodeGenContext* ctx, Expr* expr, int* column_count, i
|
|||
return result;
|
||||
}
|
||||
|
||||
bool ProcessJoinOpExpr(
|
||||
static bool ProcessJoinOpExpr(
|
||||
JitTvmCodeGenContext* ctx, const OpExpr* op_expr, int* column_count, int* column_array, int* max_arg)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -123,7 +142,7 @@ bool ProcessJoinOpExpr(
|
|||
return result;
|
||||
}
|
||||
|
||||
bool ProcessJoinBoolExpr(
|
||||
static bool ProcessJoinBoolExpr(
|
||||
JitTvmCodeGenContext* ctx, const BoolExpr* boolexpr, int* column_count, int* column_array, int* max_arg)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -161,7 +180,7 @@ void buildIsSoftMemoryLimitReached(JitTvmCodeGenContext* ctx)
|
|||
JIT_IF_END()
|
||||
}
|
||||
|
||||
Instruction* buildExpression(JitTvmCodeGenContext* ctx, Expression* expr)
|
||||
static Instruction* buildExpression(JitTvmCodeGenContext* ctx, Expression* expr)
|
||||
{
|
||||
Instruction* expr_value = ctx->_builder->addExpression(expr);
|
||||
|
||||
|
|
@ -181,7 +200,7 @@ Instruction* buildExpression(JitTvmCodeGenContext* ctx, Expression* expr)
|
|||
return expr_value;
|
||||
}
|
||||
|
||||
void buildWriteDatumColumn(JitTvmCodeGenContext* ctx, Instruction* row, int colid, Instruction* datum_value)
|
||||
static void buildWriteDatumColumn(JitTvmCodeGenContext* ctx, Instruction* row, int colid, Instruction* datum_value)
|
||||
{
|
||||
// ATTENTION: The datum_value expression-instruction MUST be already evaluated before this code is executed
|
||||
// That is the reason why the expression-instruction was added to the current block and now we
|
||||
|
|
@ -261,7 +280,7 @@ Instruction* buildSearchRow(JitTvmCodeGenContext* ctx, MOT::AccessType access_ty
|
|||
return row;
|
||||
}
|
||||
|
||||
Expression* buildFilter(JitTvmCodeGenContext* ctx, Instruction* row, JitFilter* filter, int* max_arg)
|
||||
static Expression* buildFilter(JitTvmCodeGenContext* ctx, Instruction* row, JitFilter* filter, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
Expression* lhs_expr = ProcessExpr(ctx, row, filter->_lhs_operand, max_arg);
|
||||
|
|
@ -339,8 +358,8 @@ void buildDeleteRow(JitTvmCodeGenContext* ctx)
|
|||
IssueDebugLog("Row deleted");
|
||||
}
|
||||
|
||||
Instruction* buildSearchIterator(JitTvmCodeGenContext* ctx, JitIndexScanDirection index_scan_direction,
|
||||
JitRangeBoundMode range_bound_mode, JitRangeScanType range_scan_type, int subQueryIndex /* = -1 */)
|
||||
static Instruction* buildSearchIterator(JitTvmCodeGenContext* ctx, JitIndexScanDirection index_scan_direction,
|
||||
JitRangeBoundMode range_bound_mode, JitRangeScanType range_scan_type, int subQueryIndex = -1)
|
||||
{
|
||||
// search the row
|
||||
IssueDebugLog("Searching range start");
|
||||
|
|
@ -357,7 +376,8 @@ Instruction* buildSearchIterator(JitTvmCodeGenContext* ctx, JitIndexScanDirectio
|
|||
}
|
||||
|
||||
/** @brief Adds code to search for an iterator. */
|
||||
Instruction* buildBeginIterator(JitTvmCodeGenContext* ctx, JitRangeScanType rangeScanType, int subQueryIndex /* = -1 */)
|
||||
static Instruction* buildBeginIterator(
|
||||
JitTvmCodeGenContext* ctx, JitRangeScanType rangeScanType, int subQueryIndex = -1)
|
||||
{
|
||||
// search the row
|
||||
IssueDebugLog("Getting begin iterator for full-scan");
|
||||
|
|
@ -392,7 +412,7 @@ Instruction* buildGetRowFromIterator(JitTvmCodeGenContext* ctx, BasicBlock* endL
|
|||
return row;
|
||||
}
|
||||
|
||||
Expression* ProcessConstExpr(
|
||||
static Expression* ProcessConstExpr(
|
||||
JitTvmCodeGenContext* ctx, const Const* const_value, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
|
@ -416,7 +436,7 @@ Expression* ProcessConstExpr(
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessParamExpr(
|
||||
static Expression* ProcessParamExpr(
|
||||
JitTvmCodeGenContext* ctx, const Param* param, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
|
@ -440,7 +460,7 @@ Expression* ProcessParamExpr(
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessRelabelExpr(
|
||||
static Expression* ProcessRelabelExpr(
|
||||
JitTvmCodeGenContext* ctx, RelabelType* relabel_type, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
MOT_LOG_DEBUG("Processing RELABEL expression");
|
||||
|
|
@ -448,7 +468,7 @@ Expression* ProcessRelabelExpr(
|
|||
return ProcessParamExpr(ctx, param, result_type, arg_pos, depth, max_arg);
|
||||
}
|
||||
|
||||
Expression* ProcessVarExpr(
|
||||
static Expression* ProcessVarExpr(
|
||||
JitTvmCodeGenContext* ctx, const Var* var, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
|
@ -509,7 +529,7 @@ Expression* ProcessVarExpr(
|
|||
result = new (std::nothrow) name##Operator(args[0], args[1], args[2], arg_pos); \
|
||||
break;
|
||||
|
||||
Expression* ProcessOpExpr(
|
||||
static Expression* ProcessOpExpr(
|
||||
JitTvmCodeGenContext* ctx, const OpExpr* op_expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
|
@ -555,7 +575,7 @@ Expression* ProcessOpExpr(
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessFuncExpr(
|
||||
static Expression* ProcessFuncExpr(
|
||||
JitTvmCodeGenContext* ctx, const FuncExpr* func_expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
|
@ -608,7 +628,8 @@ Expression* ProcessFuncExpr(
|
|||
#undef APPLY_BINARY_CAST_OPERATOR
|
||||
#undef APPLY_TERNARY_CAST_OPERATOR
|
||||
|
||||
Expression* ProcessExpr(JitTvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
static Expression* ProcessExpr(
|
||||
JitTvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
MOT_LOG_DEBUG("%*s --> Processing expression %d", depth, "", (int)expr->type);
|
||||
|
|
@ -639,7 +660,7 @@ Expression* ProcessExpr(JitTvmCodeGenContext* ctx, Expr* expr, int& result_type,
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessConstExpr(JitTvmCodeGenContext* ctx, const JitConstExpr* expr, int* max_arg)
|
||||
static Expression* ProcessConstExpr(JitTvmCodeGenContext* ctx, const JitConstExpr* expr, int* max_arg)
|
||||
{
|
||||
AddSetExprArgIsNull(ctx, expr->_arg_pos, (expr->_is_null ? 1 : 0)); // mark expression null status
|
||||
Expression* result = new (std::nothrow) ConstExpression(expr->_value, expr->_arg_pos, (int)(expr->_is_null));
|
||||
|
|
@ -649,7 +670,7 @@ Expression* ProcessConstExpr(JitTvmCodeGenContext* ctx, const JitConstExpr* expr
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessParamExpr(JitTvmCodeGenContext* ctx, const JitParamExpr* expr, int* max_arg)
|
||||
static Expression* ProcessParamExpr(JitTvmCodeGenContext* ctx, const JitParamExpr* expr, int* max_arg)
|
||||
{
|
||||
Expression* result = AddGetDatumParam(ctx, expr->_param_id, expr->_arg_pos);
|
||||
if (max_arg && (expr->_arg_pos > *max_arg)) {
|
||||
|
|
@ -658,7 +679,7 @@ Expression* ProcessParamExpr(JitTvmCodeGenContext* ctx, const JitParamExpr* expr
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessVarExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitVarExpr* expr, int* max_arg)
|
||||
static Expression* ProcessVarExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitVarExpr* expr, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
if (row == nullptr) {
|
||||
|
|
@ -708,7 +729,7 @@ Expression* ProcessVarExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitVarEx
|
|||
result = new (std::nothrow) name##Operator(args[0], args[1], args[2], arg_pos); \
|
||||
break;
|
||||
|
||||
Expression* ProcessOpExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitOpExpr* expr, int* max_arg)
|
||||
static Expression* ProcessOpExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitOpExpr* expr, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
||||
|
|
@ -737,7 +758,7 @@ Expression* ProcessOpExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitOpExpr
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessFuncExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFuncExpr* expr, int* max_arg)
|
||||
static Expression* ProcessFuncExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFuncExpr* expr, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
||||
|
|
@ -792,7 +813,7 @@ Expression* ProcessFuncExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFunc
|
|||
MOT_LOG_TRACE("Unexpected call in filter expression to ternary cast builtin: " #name); \
|
||||
break;
|
||||
|
||||
Expression* ProcessFilterExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFilter* filter, int* max_arg)
|
||||
static Expression* ProcessFilterExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFilter* filter, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
||||
|
|
@ -830,12 +851,12 @@ Expression* ProcessFilterExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitFi
|
|||
#undef APPLY_BINARY_CAST_OPERATOR
|
||||
#undef APPLY_TERNARY_CAST_OPERATOR
|
||||
|
||||
Expression* ProcessSubLinkExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitSubLinkExpr* expr, int* max_arg)
|
||||
static Expression* ProcessSubLinkExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitSubLinkExpr* expr, int* max_arg)
|
||||
{
|
||||
return AddSelectSubQueryResult(ctx, expr->_sub_query_index);
|
||||
}
|
||||
|
||||
Expression* ProcessBoolExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitBoolExpr* expr, int* maxArg)
|
||||
static Expression* ProcessBoolExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitBoolExpr* expr, int* maxArg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
||||
|
|
@ -871,7 +892,7 @@ Expression* ProcessBoolExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitBool
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* ProcessExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitExpr* expr, int* max_arg)
|
||||
static Expression* ProcessExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitExpr* expr, int* max_arg)
|
||||
{
|
||||
Expression* result = nullptr;
|
||||
|
||||
|
|
@ -897,7 +918,7 @@ Expression* ProcessExpr(JitTvmCodeGenContext* ctx, Instruction* row, JitExpr* ex
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildScanExpression(JitTvmCodeGenContext* ctx, JitColumnExpr* expr, int* max_arg,
|
||||
static bool buildScanExpression(JitTvmCodeGenContext* ctx, JitColumnExpr* expr, int* max_arg,
|
||||
JitRangeIteratorType range_itr_type, JitRangeScanType range_scan_type, Instruction* outer_row, int subQueryIndex)
|
||||
{
|
||||
Expression* value_expr = ProcessExpr(ctx, outer_row, expr->_expr, max_arg);
|
||||
|
|
@ -1025,7 +1046,7 @@ bool selectRowColumns(JitTvmCodeGenContext* ctx, Instruction* row, JitSelectExpr
|
|||
return true;
|
||||
}
|
||||
|
||||
bool buildClosedRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg,
|
||||
static bool buildClosedRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg,
|
||||
JitRangeScanType rangeScanType, Instruction* outerRow, int subQueryIndex)
|
||||
{
|
||||
// a closed range scan starts just like a point scan (with not enough search expressions) and then adds key patterns
|
||||
|
|
@ -1079,7 +1100,7 @@ bool buildClosedRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, in
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildSemiOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
static bool buildSemiOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, JitRangeBoundMode* begin_range_bound, JitRangeBoundMode* end_range_bound,
|
||||
Instruction* outer_row, int subQueryIndex)
|
||||
{
|
||||
|
|
@ -1205,7 +1226,7 @@ bool buildSemiOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan,
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
static bool buildOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, JitRangeBoundMode* begin_range_bound, JitRangeBoundMode* end_range_bound,
|
||||
Instruction* outer_row, int subQueryIndex)
|
||||
{
|
||||
|
|
@ -1368,9 +1389,9 @@ bool buildOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg, JitRangeScanType rangeScanType,
|
||||
JitRangeBoundMode* beginRangeBound, JitRangeBoundMode* endRangeBound, Instruction* outerRow,
|
||||
int subQueryIndex /* = -1 */)
|
||||
static bool buildRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg,
|
||||
JitRangeScanType rangeScanType, JitRangeBoundMode* beginRangeBound, JitRangeBoundMode* endRangeBound,
|
||||
Instruction* outerRow, int subQueryIndex = -1)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
|
@ -1402,7 +1423,7 @@ bool buildRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* max
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildPrepareStateScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
static bool buildPrepareStateScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, Instruction* outer_row)
|
||||
{
|
||||
JitRangeBoundMode begin_range_bound = JIT_RANGE_BOUND_NONE;
|
||||
|
|
@ -1445,7 +1466,7 @@ bool buildPrepareStateScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool buildPrepareStateRow(JitTvmCodeGenContext* ctx, MOT::AccessType access_mode, JitIndexScan* index_scan,
|
||||
static bool buildPrepareStateRow(JitTvmCodeGenContext* ctx, MOT::AccessType access_mode, JitIndexScan* index_scan,
|
||||
int* max_arg, JitRangeScanType range_scan_type, BasicBlock* next_block)
|
||||
{
|
||||
MOT_LOG_DEBUG("Generating select code for stateful range select");
|
||||
|
|
@ -1570,7 +1591,7 @@ JitTvmRuntimeCursor buildRangeCursor(JitTvmCodeGenContext* ctx, JitIndexScan* in
|
|||
return result;
|
||||
}
|
||||
|
||||
bool prepareAggregateAvg(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
static bool prepareAggregateAvg(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
{
|
||||
// although we already have this information in the aggregate descriptor, we still check again
|
||||
switch (aggregate->_func_id) {
|
||||
|
|
@ -1601,7 +1622,7 @@ bool prepareAggregateAvg(JitTvmCodeGenContext* ctx, const JitAggregate* aggregat
|
|||
return true;
|
||||
}
|
||||
|
||||
bool prepareAggregateSum(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
static bool prepareAggregateSum(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
{
|
||||
switch (aggregate->_func_id) {
|
||||
case INT8SUMFUNCOID:
|
||||
|
|
@ -1637,13 +1658,13 @@ bool prepareAggregateSum(JitTvmCodeGenContext* ctx, const JitAggregate* aggregat
|
|||
return true;
|
||||
}
|
||||
|
||||
bool prepareAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate)
|
||||
static bool prepareAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate)
|
||||
{
|
||||
AddResetAggMaxMinNull(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool prepareAggregateCount(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
static bool prepareAggregateCount(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
{
|
||||
switch (aggregate->_func_id) {
|
||||
case 2147: // int8inc_any
|
||||
|
|
@ -1659,7 +1680,7 @@ bool prepareAggregateCount(JitTvmCodeGenContext* ctx, const JitAggregate* aggreg
|
|||
return true;
|
||||
}
|
||||
|
||||
bool prepareDistinctSet(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
static bool prepareDistinctSet(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate)
|
||||
{
|
||||
// we need a hash-set according to the aggregated type (preferably but not necessarily linear-probing hash)
|
||||
// we use an opaque datum type, with a tailor-made hash-function and equals function
|
||||
|
|
@ -1706,7 +1727,7 @@ bool prepareAggregate(JitTvmCodeGenContext* ctx, JitAggregate* aggregate)
|
|||
return result;
|
||||
}
|
||||
|
||||
Expression* buildAggregateAvg(
|
||||
static Expression* buildAggregateAvg(
|
||||
JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, Expression* current_aggregate, Expression* var_expr)
|
||||
{
|
||||
Expression* aggregate_expr = nullptr;
|
||||
|
|
@ -1761,7 +1782,7 @@ Expression* buildAggregateAvg(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
Expression* buildAggregateSum(
|
||||
static Expression* buildAggregateSum(
|
||||
JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, Expression* current_aggregate, Expression* var_expr)
|
||||
{
|
||||
Expression* aggregate_expr = nullptr;
|
||||
|
|
@ -1804,7 +1825,7 @@ Expression* buildAggregateSum(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
Expression* buildAggregateMax(
|
||||
static Expression* buildAggregateMax(
|
||||
JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, Expression* current_aggregate, Expression* var_expr)
|
||||
{
|
||||
Expression* aggregate_expr = nullptr;
|
||||
|
|
@ -1872,7 +1893,7 @@ Expression* buildAggregateMax(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
Expression* buildAggregateMin(
|
||||
static Expression* buildAggregateMin(
|
||||
JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, Expression* current_aggregate, Expression* var_expr)
|
||||
{
|
||||
Expression* aggregate_expr = nullptr;
|
||||
|
|
@ -1935,7 +1956,8 @@ Expression* buildAggregateMin(
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
Expression* buildAggregateCount(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, Expression* count_aggregate)
|
||||
static Expression* buildAggregateCount(
|
||||
JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, Expression* count_aggregate)
|
||||
{
|
||||
Expression* aggregate_expr = nullptr;
|
||||
switch (aggregate->_func_id) {
|
||||
|
|
@ -1957,7 +1979,7 @@ Expression* buildAggregateCount(JitTvmCodeGenContext* ctx, const JitAggregate* a
|
|||
return aggregate_expr;
|
||||
}
|
||||
|
||||
bool buildAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, Expression* var_expr)
|
||||
static bool buildAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, Expression* var_expr)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
|
|
@ -1990,7 +2012,7 @@ bool buildAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, Ex
|
|||
return result;
|
||||
}
|
||||
|
||||
bool buildAggregateTuple(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, Expression* var_expr)
|
||||
static bool buildAggregateTuple(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, Expression* var_expr)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,27 +25,18 @@
|
|||
#ifndef JIT_TVM_BLOCKS_H
|
||||
#define JIT_TVM_BLOCKS_H
|
||||
|
||||
// Be sure to include jit_tvm_query.h before anything else because of global.h.
|
||||
// See jit_tvm_query.h for more details.
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_tvm_query.h before anything else because of libintl.h
|
||||
* See jit_tvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_tvm_query.h"
|
||||
#include "jit_plan.h"
|
||||
|
||||
namespace JitExec {
|
||||
void CreateJittedFunction(JitTvmCodeGenContext* ctx, const char* function_name, const char* query_string);
|
||||
|
||||
bool ProcessJoinExpr(JitTvmCodeGenContext* ctx, Expr* expr, int* column_count, int* column_array, int* max_arg);
|
||||
|
||||
bool ProcessJoinOpExpr(
|
||||
JitTvmCodeGenContext* ctx, const OpExpr* op_expr, int* column_count, int* column_array, int* max_arg);
|
||||
|
||||
bool ProcessJoinBoolExpr(
|
||||
JitTvmCodeGenContext* ctx, const BoolExpr* boolexpr, int* column_count, int* column_array, int* max_arg);
|
||||
|
||||
void buildIsSoftMemoryLimitReached(JitTvmCodeGenContext* ctx);
|
||||
|
||||
tvm::Instruction* buildExpression(JitTvmCodeGenContext* ctx, tvm::Expression* expr);
|
||||
|
||||
void buildWriteDatumColumn(JitTvmCodeGenContext* ctx, tvm::Instruction* row, int colid, tvm::Instruction* datum_value);
|
||||
|
||||
void buildWriteRow(JitTvmCodeGenContext* ctx, tvm::Instruction* row, bool isPKey, JitTvmRuntimeCursor* cursor);
|
||||
|
||||
void buildResetRowsProcessed(JitTvmCodeGenContext* ctx);
|
||||
|
|
@ -57,8 +48,6 @@ tvm::Instruction* buildCreateNewRow(JitTvmCodeGenContext* ctx);
|
|||
tvm::Instruction* buildSearchRow(
|
||||
JitTvmCodeGenContext* ctx, MOT::AccessType access_type, JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
tvm::Expression* buildFilter(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitFilter* filter, int* max_arg);
|
||||
|
||||
bool buildFilterRow(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitFilterArray* filters, int* max_arg,
|
||||
tvm::BasicBlock* next_block);
|
||||
|
||||
|
|
@ -66,60 +55,10 @@ void buildInsertRow(JitTvmCodeGenContext* ctx, tvm::Instruction* row);
|
|||
|
||||
void buildDeleteRow(JitTvmCodeGenContext* ctx);
|
||||
|
||||
tvm::Instruction* buildSearchIterator(JitTvmCodeGenContext* ctx, JitIndexScanDirection index_scan_direction,
|
||||
JitRangeBoundMode range_bound_mode, JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
/** @brief Adds code to search for an iterator. */
|
||||
tvm::Instruction* buildBeginIterator(JitTvmCodeGenContext* ctx, JitRangeScanType rangeScanType, int subQueryIndex = -1);
|
||||
|
||||
tvm::Instruction* buildGetRowFromIterator(JitTvmCodeGenContext* ctx, tvm::BasicBlock* endLoopBlock,
|
||||
MOT::AccessType access_mode, JitIndexScanDirection index_scan_direction, JitTvmRuntimeCursor* cursor,
|
||||
JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
tvm::Expression* ProcessConstExpr(
|
||||
JitTvmCodeGenContext* ctx, const Const* const_value, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessParamExpr(
|
||||
JitTvmCodeGenContext* ctx, const Param* param, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessRelabelExpr(
|
||||
JitTvmCodeGenContext* ctx, RelabelType* relabel_type, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessVarExpr(
|
||||
JitTvmCodeGenContext* ctx, const Var* var, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessOpExpr(
|
||||
JitTvmCodeGenContext* ctx, const OpExpr* op_expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessFuncExpr(
|
||||
JitTvmCodeGenContext* ctx, const FuncExpr* func_expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessExpr(
|
||||
JitTvmCodeGenContext* ctx, Expr* expr, int& result_type, int arg_pos, int depth, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessConstExpr(JitTvmCodeGenContext* ctx, const JitConstExpr* expr, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessParamExpr(JitTvmCodeGenContext* ctx, const JitParamExpr* expr, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessVarExpr(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitVarExpr* expr, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessOpExpr(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitOpExpr* expr, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessFuncExpr(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitFuncExpr* expr, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessFilterExpr(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitFilter* filter, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessSubLinkExpr(
|
||||
JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitSubLinkExpr* expr, int* max_arg);
|
||||
|
||||
tvm::Expression* ProcessBoolExpr(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitBoolExpr* expr, int* maxArg);
|
||||
|
||||
tvm::Expression* ProcessExpr(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitExpr* expr, int* max_arg);
|
||||
|
||||
bool buildScanExpression(JitTvmCodeGenContext* ctx, JitColumnExpr* expr, int* max_arg,
|
||||
JitRangeIteratorType range_itr_type, JitRangeScanType range_scan_type, tvm::Instruction* outer_row,
|
||||
int subQueryIndex);
|
||||
|
||||
bool buildPointScan(JitTvmCodeGenContext* ctx, JitColumnExprArray* expr_array, int* max_arg,
|
||||
JitRangeScanType range_scan_type, tvm::Instruction* outer_row, int expr_count = -1, int subQueryIndex = -1);
|
||||
|
||||
|
|
@ -129,27 +68,6 @@ bool writeRowColumns(
|
|||
bool selectRowColumns(JitTvmCodeGenContext* ctx, tvm::Instruction* row, JitSelectExprArray* expr_array, int* max_arg,
|
||||
JitRangeScanType range_scan_type, int subQueryIndex = -1);
|
||||
|
||||
bool buildClosedRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg,
|
||||
JitRangeScanType rangeScanType, tvm::Instruction* outerRow, int subQueryIndex);
|
||||
|
||||
bool buildSemiOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, JitRangeBoundMode* begin_range_bound, JitRangeBoundMode* end_range_bound,
|
||||
tvm::Instruction* outer_row, int subQueryIndex);
|
||||
|
||||
bool buildOpenRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, JitRangeBoundMode* begin_range_bound, JitRangeBoundMode* end_range_bound,
|
||||
tvm::Instruction* outer_row, int subQueryIndex);
|
||||
|
||||
bool buildRangeScan(JitTvmCodeGenContext* ctx, JitIndexScan* indexScan, int* maxArg, JitRangeScanType rangeScanType,
|
||||
JitRangeBoundMode* beginRangeBound, JitRangeBoundMode* endRangeBound, tvm::Instruction* outerRow,
|
||||
int subQueryIndex = -1);
|
||||
|
||||
bool buildPrepareStateScan(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan, int* max_arg,
|
||||
JitRangeScanType range_scan_type, tvm::Instruction* outer_row);
|
||||
|
||||
bool buildPrepareStateRow(JitTvmCodeGenContext* ctx, MOT::AccessType access_mode, JitIndexScan* index_scan,
|
||||
int* max_arg, JitRangeScanType range_scan_type, tvm::BasicBlock* next_block);
|
||||
|
||||
tvm::Instruction* buildPrepareStateScanRow(JitTvmCodeGenContext* ctx, JitIndexScan* index_scan,
|
||||
JitRangeScanType range_scan_type, MOT::AccessType access_mode, int* max_arg, tvm::Instruction* outer_row,
|
||||
tvm::BasicBlock* next_block, tvm::BasicBlock** loop_block);
|
||||
|
|
@ -158,37 +76,8 @@ JitTvmRuntimeCursor buildRangeCursor(JitTvmCodeGenContext* ctx, JitIndexScan* in
|
|||
JitRangeScanType rangeScanType, JitIndexScanDirection indexScanDirection, tvm::Instruction* outerRow,
|
||||
int subQueryIndex = -1);
|
||||
|
||||
bool prepareAggregateAvg(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate);
|
||||
|
||||
bool prepareAggregateSum(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate);
|
||||
|
||||
bool prepareAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate);
|
||||
|
||||
bool prepareAggregateCount(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate);
|
||||
|
||||
bool prepareDistinctSet(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate);
|
||||
|
||||
bool prepareAggregate(JitTvmCodeGenContext* ctx, JitAggregate* aggregate);
|
||||
|
||||
tvm::Expression* buildAggregateAvg(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate,
|
||||
tvm::Expression* current_aggregate, tvm::Expression* var_expr);
|
||||
|
||||
tvm::Expression* buildAggregateSum(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate,
|
||||
tvm::Expression* current_aggregate, tvm::Expression* var_expr);
|
||||
|
||||
tvm::Expression* buildAggregateMax(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate,
|
||||
tvm::Expression* current_aggregate, tvm::Expression* var_expr);
|
||||
|
||||
tvm::Expression* buildAggregateMin(JitTvmCodeGenContext* ctx, const JitAggregate* aggregate,
|
||||
tvm::Expression* current_aggregate, tvm::Expression* var_expr);
|
||||
|
||||
tvm::Expression* buildAggregateCount(
|
||||
JitTvmCodeGenContext* ctx, const JitAggregate* aggregate, tvm::Expression* count_aggregate);
|
||||
|
||||
bool buildAggregateMaxMin(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, tvm::Expression* var_expr);
|
||||
|
||||
bool buildAggregateTuple(JitTvmCodeGenContext* ctx, JitAggregate* aggregate, tvm::Expression* var_expr);
|
||||
|
||||
bool buildAggregateRow(
|
||||
JitTvmCodeGenContext* ctx, JitAggregate* aggregate, tvm::Instruction* row, tvm::BasicBlock* next_block);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,12 @@
|
|||
#ifndef JIT_TVM_FUNCS_H
|
||||
#define JIT_TVM_FUNCS_H
|
||||
|
||||
// Be sure to include jit_tvm_query.h before anything else because of global.h.
|
||||
// See jit_tvm_query.h for more details.
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_tvm_query.h before anything else because of libintl.h
|
||||
* See jit_tvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_tvm_query.h"
|
||||
#include "jit_plan_expr.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace JitExec {
|
||||
|
|
|
|||
|
|
@ -25,42 +25,12 @@
|
|||
#ifndef JIT_TVM_QUERY_H
|
||||
#define JIT_TVM_QUERY_H
|
||||
|
||||
// Be sure to include global.h before postgres.h to avoid conflict between libintl.h (included in global.h)
|
||||
// and c.h (included in postgres.h).
|
||||
#include "global.h"
|
||||
|
||||
// be careful to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h
|
||||
#include "codegen/gscodegen.h"
|
||||
#include "postgres.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/numeric.h"
|
||||
#include "utils/numeric_gs.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
|
||||
#include "mot_internal.h"
|
||||
#include "storage/mot/jit_exec.h"
|
||||
/*
|
||||
* ATTENTION: Be sure to include libintl.h before anything else to avoid problem with gettext.
|
||||
*/
|
||||
#include "libintl.h"
|
||||
#include "jit_common.h"
|
||||
#include "jit_tvm.h"
|
||||
#include "jit_tvm_util.h"
|
||||
#include "jit_util.h"
|
||||
#include "jit_plan.h"
|
||||
|
||||
#include "mot_engine.h"
|
||||
#include "utilities.h"
|
||||
#include "mot_internal.h"
|
||||
#include "catalog_column_types.h"
|
||||
#include "mot_error.h"
|
||||
#include "utilities.h"
|
||||
#include "mm_session_api.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
namespace JitExec {
|
||||
/** @struct Holds instructions that evaluate in runtime to begin and end iterators of a cursor. */
|
||||
|
|
|
|||
|
|
@ -22,12 +22,17 @@
|
|||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Be sure to include jit_tvm_query.h before anything else because of global.h.
|
||||
// See jit_tvm_query.h for more details.
|
||||
/*
|
||||
* ATTENTION: Be sure to include jit_tvm_query.h before anything else because of libintl.h
|
||||
* See jit_tvm_query.h for more details.
|
||||
*/
|
||||
#include "jit_tvm_query.h"
|
||||
#include "jit_tvm_query_codegen.h"
|
||||
#include "jit_tvm_funcs.h"
|
||||
#include "jit_tvm_blocks.h"
|
||||
#include "storage/mot/jit_exec.h"
|
||||
#include "jit_tvm_util.h"
|
||||
#include "jit_util.h"
|
||||
|
||||
using namespace tvm;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
#include "access/redo_statistic_msg.h"
|
||||
#include "portability/instr_time.h"
|
||||
#include "replication/rto_statistic.h"
|
||||
|
||||
#include "storage/mot/jit_def.h"
|
||||
|
||||
const int NUM_PERCENTILE_COUNT = 2;
|
||||
const int INIT_NUMA_ALLOC_COUNT = 32;
|
||||
|
|
@ -544,6 +544,10 @@ typedef struct knl_g_bgworker_context {
|
|||
volatile bool have_crashed_worker;
|
||||
} knl_g_bgworker_context;
|
||||
|
||||
typedef struct knl_g_mot_context {
|
||||
JitExec::JitExecMode jitExecMode;
|
||||
} knl_g_mot_context;
|
||||
|
||||
typedef struct knl_instance_context {
|
||||
knl_virtual_role role;
|
||||
volatile int status;
|
||||
|
|
@ -616,6 +620,7 @@ typedef struct knl_instance_context {
|
|||
knl_g_rto_context rto_cxt;
|
||||
knl_g_xlog_context xlog_cxt;
|
||||
knl_g_numa_context numa_cxt;
|
||||
knl_g_mot_context mot_cxt;
|
||||
knl_g_bgworker_context bgworker_cxt;
|
||||
} knl_instance_context;
|
||||
|
||||
|
|
|
|||
|
|
@ -2731,7 +2731,6 @@ typedef struct knl_t_mot_context {
|
|||
|
||||
// misc
|
||||
uint8_t log_level;
|
||||
bool init_codegen_once;
|
||||
|
||||
uint16_t currentThreadId;
|
||||
int currentNumaNodeId;
|
||||
|
|
|
|||
|
|
@ -159,6 +159,8 @@ public:
|
|||
bool m_isCompleted;
|
||||
|
||||
long m_position;
|
||||
private:
|
||||
static FusionType GetMotFusionType(PlannedStmt* plannedStmt);
|
||||
};
|
||||
|
||||
class SelectFusion : public OpFusion {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,18 @@ namespace JitExec {
|
|||
// To use advanced WHERE clause operators, #define MOT_JIT_ADVANCED_WHERE_OP
|
||||
// To enable features required for JIT testing, #define MOT_JIT_TEST
|
||||
|
||||
/** @enum JIT execution mode constants. */
|
||||
enum JitExecMode : uint32_t {
|
||||
/** @var Invalid execution mode. */
|
||||
JIT_EXEC_MODE_INVALID,
|
||||
|
||||
/** @var LLVM execution mode. */
|
||||
JIT_EXEC_MODE_LLVM,
|
||||
|
||||
/** @var TVM execution mode. */
|
||||
JIT_EXEC_MODE_TVM
|
||||
};
|
||||
|
||||
/** @enum JitCommandType Command types supported by jitted queries. */
|
||||
enum JitCommandType : uint8_t {
|
||||
/** @var Invalid command type. */
|
||||
|
|
|
|||
|
|
@ -57,9 +57,6 @@ extern bool IsMotCodegenPrintEnabled();
|
|||
/** @brief Queries for the per-session limit of JIT queries. */
|
||||
extern uint32_t GetMotCodegenLimit();
|
||||
|
||||
/** @brief Turn off MOT JIT compilation and execution. */
|
||||
extern void DisableMotCodegen();
|
||||
|
||||
/**
|
||||
* @brief Queries whether a SQL query to be executed by MM Engine is jittable.
|
||||
* @param query The parsed SQL query to examine.
|
||||
|
|
|
|||
Loading…
Reference in New Issue