feat: optimize partition by tbname
This commit is contained in:
parent
aca91eb831
commit
896c1b3a6d
|
@ -52,7 +52,7 @@ typedef struct SExprNode {
|
||||||
SArray* pAssociation;
|
SArray* pAssociation;
|
||||||
} SExprNode;
|
} SExprNode;
|
||||||
|
|
||||||
typedef enum EColumnType { COLUMN_TYPE_COLUMN = 1, COLUMN_TYPE_TAG } EColumnType;
|
typedef enum EColumnType { COLUMN_TYPE_COLUMN = 1, COLUMN_TYPE_TAG, COLUMN_TYPE_TBNAME } EColumnType;
|
||||||
|
|
||||||
typedef struct SColumnNode {
|
typedef struct SColumnNode {
|
||||||
SExprNode node; // QUERY_NODE_COLUMN
|
SExprNode node; // QUERY_NODE_COLUMN
|
||||||
|
|
|
@ -257,7 +257,7 @@ static int32_t checkAuth(SInsertParseContext* pCxt, char* pDbFname, bool* pPass)
|
||||||
if (pBasicCtx->async) {
|
if (pBasicCtx->async) {
|
||||||
return getUserAuthFromCache(pCxt->pMetaCache, pBasicCtx->pUser, pDbFname, AUTH_TYPE_WRITE, pPass);
|
return getUserAuthFromCache(pCxt->pMetaCache, pBasicCtx->pUser, pDbFname, AUTH_TYPE_WRITE, pPass);
|
||||||
}
|
}
|
||||||
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
||||||
.requestId = pBasicCtx->requestId,
|
.requestId = pBasicCtx->requestId,
|
||||||
.requestObjRefId = pBasicCtx->requestRid,
|
.requestObjRefId = pBasicCtx->requestRid,
|
||||||
.mgmtEps = pBasicCtx->mgmtEpSet};
|
.mgmtEps = pBasicCtx->mgmtEpSet};
|
||||||
|
@ -270,11 +270,11 @@ static int32_t getTableSchema(SInsertParseContext* pCxt, SName* pTbName, bool is
|
||||||
if (pBasicCtx->async) {
|
if (pBasicCtx->async) {
|
||||||
return getTableMetaFromCache(pCxt->pMetaCache, pTbName, pTableMeta);
|
return getTableMetaFromCache(pCxt->pMetaCache, pTbName, pTableMeta);
|
||||||
}
|
}
|
||||||
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
||||||
.requestId = pBasicCtx->requestId,
|
.requestId = pBasicCtx->requestId,
|
||||||
.requestObjRefId = pBasicCtx->requestRid,
|
.requestObjRefId = pBasicCtx->requestRid,
|
||||||
.mgmtEps = pBasicCtx->mgmtEpSet};
|
.mgmtEps = pBasicCtx->mgmtEpSet};
|
||||||
|
|
||||||
if (isStb) {
|
if (isStb) {
|
||||||
return catalogGetSTableMeta(pBasicCtx->pCatalog, &conn, pTbName, pTableMeta);
|
return catalogGetSTableMeta(pBasicCtx->pCatalog, &conn, pTbName, pTableMeta);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ static int32_t getTableVgroup(SInsertParseContext* pCxt, SName* pTbName, SVgroup
|
||||||
if (pBasicCtx->async) {
|
if (pBasicCtx->async) {
|
||||||
return getTableVgroupFromCache(pCxt->pMetaCache, pTbName, pVg);
|
return getTableVgroupFromCache(pCxt->pMetaCache, pTbName, pVg);
|
||||||
}
|
}
|
||||||
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
||||||
.requestId = pBasicCtx->requestId,
|
.requestId = pBasicCtx->requestId,
|
||||||
.requestObjRefId = pBasicCtx->requestRid,
|
.requestObjRefId = pBasicCtx->requestRid,
|
||||||
.mgmtEps = pBasicCtx->mgmtEpSet};
|
.mgmtEps = pBasicCtx->mgmtEpSet};
|
||||||
|
@ -322,7 +322,7 @@ static int32_t getDBCfg(SInsertParseContext* pCxt, const char* pDbFName, SDbCfgI
|
||||||
if (pBasicCtx->async) {
|
if (pBasicCtx->async) {
|
||||||
CHECK_CODE(getDbCfgFromCache(pCxt->pMetaCache, pDbFName, pInfo));
|
CHECK_CODE(getDbCfgFromCache(pCxt->pMetaCache, pDbFName, pInfo));
|
||||||
} else {
|
} else {
|
||||||
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
SRequestConnInfo conn = {.pTrans = pBasicCtx->pTransporter,
|
||||||
.requestId = pBasicCtx->requestId,
|
.requestId = pBasicCtx->requestId,
|
||||||
.requestObjRefId = pBasicCtx->requestRid,
|
.requestObjRefId = pBasicCtx->requestRid,
|
||||||
.mgmtEps = pBasicCtx->mgmtEpSet};
|
.mgmtEps = pBasicCtx->mgmtEpSet};
|
||||||
|
@ -1315,15 +1315,6 @@ static void destroyInsertParseContext(SInsertParseContext* pCxt) {
|
||||||
destroyBlockArrayList(pCxt->pVgDataBlocks);
|
destroyBlockArrayList(pCxt->pVgDataBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t checkSchemalessDb(SInsertParseContext* pCxt, char* pDbName) {
|
|
||||||
// SDbCfgInfo pInfo = {0};
|
|
||||||
// char fullName[TSDB_TABLE_FNAME_LEN];
|
|
||||||
// snprintf(fullName, sizeof(fullName), "%d.%s", pCxt->pComCxt->acctId, pDbName);
|
|
||||||
// CHECK_CODE(getDBCfg(pCxt, fullName, &pInfo));
|
|
||||||
// return pInfo.schemaless ? TSDB_CODE_SML_INVALID_DB_CONF : TSDB_CODE_SUCCESS;
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// tb_name
|
// tb_name
|
||||||
// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
|
// [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
|
||||||
// [(field1_name, ...)]
|
// [(field1_name, ...)]
|
||||||
|
@ -1377,8 +1368,6 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
|
||||||
SName name;
|
SName name;
|
||||||
CHECK_CODE(createSName(&name, &tbnameToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg));
|
CHECK_CODE(createSName(&name, &tbnameToken, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg));
|
||||||
|
|
||||||
CHECK_CODE(checkSchemalessDb(pCxt, name.dbname));
|
|
||||||
|
|
||||||
tNameExtractFullName(&name, tbFName);
|
tNameExtractFullName(&name, tbFName);
|
||||||
CHECK_CODE(taosHashPut(pCxt->pTableNameHashObj, tbFName, strlen(tbFName), &name, sizeof(SName)));
|
CHECK_CODE(taosHashPut(pCxt->pTableNameHashObj, tbFName, strlen(tbFName), &name, sizeof(SName)));
|
||||||
char dbFName[TSDB_DB_FNAME_LEN];
|
char dbFName[TSDB_DB_FNAME_LEN];
|
||||||
|
|
|
@ -56,8 +56,12 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
|
||||||
pCol->node.resType = pToBeRewrittenExpr->resType;
|
pCol->node.resType = pToBeRewrittenExpr->resType;
|
||||||
strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName);
|
strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName);
|
||||||
strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName);
|
strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName);
|
||||||
if (QUERY_NODE_FUNCTION == nodeType(pExpr) && FUNCTION_TYPE_WSTARTTS == ((SFunctionNode*)pExpr)->funcType) {
|
if (QUERY_NODE_FUNCTION == nodeType(pExpr)) {
|
||||||
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
if (FUNCTION_TYPE_WSTARTTS == ((SFunctionNode*)pExpr)->funcType) {
|
||||||
|
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
||||||
|
} else if (FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pExpr)->funcType) {
|
||||||
|
pCol->colType = COLUMN_TYPE_TBNAME;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nodesDestroyNode(*pNode);
|
nodesDestroyNode(*pNode);
|
||||||
*pNode = (SNode*)pCol;
|
*pNode = (SNode*)pCol;
|
||||||
|
|
|
@ -1042,7 +1042,7 @@ static int32_t smaOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan)
|
||||||
|
|
||||||
static EDealRes partTagsOptHasColImpl(SNode* pNode, void* pContext) {
|
static EDealRes partTagsOptHasColImpl(SNode* pNode, void* pContext) {
|
||||||
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||||
if (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType) {
|
if (COLUMN_TYPE_TAG != ((SColumnNode*)pNode)->colType && COLUMN_TYPE_TBNAME != ((SColumnNode*)pNode)->colType) {
|
||||||
*(bool*)pContext = true;
|
*(bool*)pContext = true;
|
||||||
return DEAL_RES_END;
|
return DEAL_RES_END;
|
||||||
}
|
}
|
||||||
|
@ -1080,6 +1080,28 @@ static bool partTagsOptMayBeOptimized(SLogicNode* pNode) {
|
||||||
return !partTagsOptHasCol(partTagsGetPartKeys(pNode));
|
return !partTagsOptHasCol(partTagsGetPartKeys(pNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EDealRes partTagsOptRebuildTbanmeImpl(SNode** pNode, void* pContext) {
|
||||||
|
if (QUERY_NODE_COLUMN == nodeType(*pNode) && COLUMN_TYPE_TBNAME == ((SColumnNode*)*pNode)->colType) {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
if (NULL == pFunc) {
|
||||||
|
*(int32_t*)pContext = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
return DEAL_RES_ERROR;
|
||||||
|
}
|
||||||
|
strcpy(pFunc->functionName, "tbname");
|
||||||
|
pFunc->funcType = FUNCTION_TYPE_TBNAME;
|
||||||
|
nodesDestroyNode(*pNode);
|
||||||
|
*pNode = (SNode*)pFunc;
|
||||||
|
return DEAL_RES_IGNORE_CHILD;
|
||||||
|
}
|
||||||
|
return DEAL_RES_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t partTagsOptRebuildTbanme(SNodeList* pPartKeys) {
|
||||||
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
nodesRewriteExprs(pPartKeys, partTagsOptRebuildTbanmeImpl, &code);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
|
||||||
SLogicNode* pNode = optFindPossibleNode(pLogicSubplan->pNode, partTagsOptMayBeOptimized);
|
SLogicNode* pNode = optFindPossibleNode(pLogicSubplan->pNode, partTagsOptMayBeOptimized);
|
||||||
if (NULL == pNode) {
|
if (NULL == pNode) {
|
||||||
|
@ -1096,7 +1118,18 @@ static int32_t partTagsOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSub
|
||||||
nodesDestroyNode((SNode*)pNode);
|
nodesDestroyNode((SNode*)pNode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TSWAP(((SAggLogicNode*)pNode)->pGroupKeys, pScan->pPartTags);
|
SNode* pGroupKey = NULL;
|
||||||
|
FOREACH(pGroupKey, ((SAggLogicNode*)pNode)->pGroupKeys) {
|
||||||
|
code = nodesListMakeStrictAppend(
|
||||||
|
&pScan->pPartTags, nodesCloneNode(nodesListGetNode(((SGroupingSetNode*)pGroupKey)->pParameterList, 0)));
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DESTORY_LIST(((SAggLogicNode*)pNode)->pGroupKeys);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = partTagsOptRebuildTbanme(pScan->pPartTags);
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -1184,7 +1217,7 @@ static const SOptimizeRule optimizeRuleSet[] = {
|
||||||
{.pName = "ConditionPushDown", .optimizeFunc = cpdOptimize},
|
{.pName = "ConditionPushDown", .optimizeFunc = cpdOptimize},
|
||||||
{.pName = "OrderByPrimaryKey", .optimizeFunc = opkOptimize},
|
{.pName = "OrderByPrimaryKey", .optimizeFunc = opkOptimize},
|
||||||
{.pName = "SmaIndex", .optimizeFunc = smaOptimize},
|
{.pName = "SmaIndex", .optimizeFunc = smaOptimize},
|
||||||
{.pName = "PartitionByTags", .optimizeFunc = partTagsOptimize},
|
{.pName = "PartitionTags", .optimizeFunc = partTagsOptimize},
|
||||||
{.pName = "EliminateProject", .optimizeFunc = eliminateProjOptimize}
|
{.pName = "EliminateProject", .optimizeFunc = eliminateProjOptimize}
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
@ -176,7 +176,7 @@ static bool stbSplNeedSplit(bool streamQuery, SLogicNode* pNode) {
|
||||||
return !stbSplHasGatherExecFunc(((SAggLogicNode*)pNode)->pAggFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
|
return !stbSplHasGatherExecFunc(((SAggLogicNode*)pNode)->pAggFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
|
||||||
case QUERY_NODE_LOGIC_PLAN_WINDOW: {
|
case QUERY_NODE_LOGIC_PLAN_WINDOW: {
|
||||||
SWindowLogicNode* pWindow = (SWindowLogicNode*)pNode;
|
SWindowLogicNode* pWindow = (SWindowLogicNode*)pNode;
|
||||||
if (WINDOW_TYPE_STATE == pWindow->winType || (!streamQuery && WINDOW_TYPE_SESSION == pWindow->winType) ) {
|
if (WINDOW_TYPE_STATE == pWindow->winType || (!streamQuery && WINDOW_TYPE_SESSION == pWindow->winType)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !stbSplHasGatherExecFunc(pWindow->pFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
|
return !stbSplHasGatherExecFunc(pWindow->pFuncs) && stbSplHasMultiTbScan(streamQuery, pNode);
|
||||||
|
@ -380,6 +380,7 @@ static int32_t stbSplCreateExchangeNode(SSplitContext* pCxt, SLogicNode* pParent
|
||||||
SExchangeLogicNode* pExchange = NULL;
|
SExchangeLogicNode* pExchange = NULL;
|
||||||
int32_t code = splCreateExchangeNode(pCxt, pPartChild, &pExchange);
|
int32_t code = splCreateExchangeNode(pCxt, pPartChild, &pExchange);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pExchange->node.pParent = pParent;
|
||||||
code = nodesListMakeAppend(&pParent->pChildren, (SNode*)pExchange);
|
code = nodesListMakeAppend(&pParent->pChildren, (SNode*)pExchange);
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
|
@ -484,7 +485,27 @@ static int32_t stbSplSplitSession(SSplitContext* pCxt, SStableSplitInfo* pInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t stbSplSplitWindowNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
static SNodeList* stbSplGetPartKeys(SLogicNode* pNode) {
|
||||||
|
if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
|
||||||
|
return ((SScanLogicNode*)pNode)->pPartTags;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool stbSplIsPartTbanme(SNodeList* pPartKeys) {
|
||||||
|
if (NULL == pPartKeys || 1 != LIST_LENGTH(pPartKeys)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SNode* pPartKey = nodesListGetNode(pPartKeys, 0);
|
||||||
|
return QUERY_NODE_FUNCTION == nodeType(pPartKey) && FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pPartKey)->funcType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool stbSplIsMultiTableWinodw(SWindowLogicNode* pWindow) {
|
||||||
|
return stbSplIsPartTbanme(stbSplGetPartKeys((SLogicNode*)nodesListGetNode(pWindow->node.pChildren, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t stbSplSplitWindowForMergeTable(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
||||||
switch (((SWindowLogicNode*)pInfo->pSplitNode)->winType) {
|
switch (((SWindowLogicNode*)pInfo->pSplitNode)->winType) {
|
||||||
case WINDOW_TYPE_INTERVAL:
|
case WINDOW_TYPE_INTERVAL:
|
||||||
return stbSplSplitInterval(pCxt, pInfo);
|
return stbSplSplitInterval(pCxt, pInfo);
|
||||||
|
@ -496,6 +517,34 @@ static int32_t stbSplSplitWindowNode(SSplitContext* pCxt, SStableSplitInfo* pInf
|
||||||
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t stbSplSplitWindowForMultiTable(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
||||||
|
if (pCxt->pPlanCxt->streamQuery) {
|
||||||
|
SPLIT_FLAG_SET_MASK(pInfo->pSubplan->splitFlag, SPLIT_FLAG_STABLE_SPLIT);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SExchangeLogicNode* pExchange = NULL;
|
||||||
|
int32_t code = splCreateExchangeNode(pCxt, pInfo->pSplitNode, &pExchange);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = replaceLogicNode(pInfo->pSubplan, pInfo->pSplitNode, (SLogicNode*)pExchange);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren,
|
||||||
|
(SNode*)splCreateScanSubplan(pCxt, pInfo->pSplitNode, SPLIT_FLAG_STABLE_SPLIT));
|
||||||
|
}
|
||||||
|
pInfo->pSubplan->subplanType = SUBPLAN_TYPE_MERGE;
|
||||||
|
++(pCxt->groupId);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t stbSplSplitWindowNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
||||||
|
if (stbSplIsMultiTableWinodw((SWindowLogicNode*)pInfo->pSplitNode)) {
|
||||||
|
return stbSplSplitWindowForMultiTable(pCxt, pInfo);
|
||||||
|
} else {
|
||||||
|
return stbSplSplitWindowForMergeTable(pCxt, pInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t stbSplCreatePartAggNode(SAggLogicNode* pMergeAgg, SLogicNode** pOutput) {
|
static int32_t stbSplCreatePartAggNode(SAggLogicNode* pMergeAgg, SLogicNode** pOutput) {
|
||||||
SNodeList* pFunc = pMergeAgg->pAggFuncs;
|
SNodeList* pFunc = pMergeAgg->pAggFuncs;
|
||||||
pMergeAgg->pAggFuncs = NULL;
|
pMergeAgg->pAggFuncs = NULL;
|
||||||
|
|
|
@ -37,7 +37,9 @@ TEST_F(PlanOtherTest, createStream) {
|
||||||
TEST_F(PlanOtherTest, createStreamUseSTable) {
|
TEST_F(PlanOtherTest, createStreamUseSTable) {
|
||||||
useDb("root", "test");
|
useDb("root", "test");
|
||||||
|
|
||||||
run("create stream if not exists s1 as select count(*) from st1 interval(10s)");
|
run("CREATE STREAM IF NOT EXISTS s1 as SELECT COUNT(*) FROM st1 INTERVAL(10s)");
|
||||||
|
|
||||||
|
run("CREATE STREAM IF NOT EXISTS s1 as SELECT COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PlanOtherTest, createSmaIndex) {
|
TEST_F(PlanOtherTest, createSmaIndex) {
|
||||||
|
|
|
@ -31,12 +31,12 @@
|
||||||
#define GET_HASH_NODE_DATA(_n) ((char *)(_n) + sizeof(SHashNode))
|
#define GET_HASH_NODE_DATA(_n) ((char *)(_n) + sizeof(SHashNode))
|
||||||
#define GET_HASH_PNODE(_n) ((SHashNode *)((char *)(_n) - sizeof(SHashNode)))
|
#define GET_HASH_PNODE(_n) ((SHashNode *)((char *)(_n) - sizeof(SHashNode)))
|
||||||
|
|
||||||
#define FREE_HASH_NODE(_fp, _n) \
|
#define FREE_HASH_NODE(_fp, _n) \
|
||||||
do { \
|
do { \
|
||||||
if (_fp != NULL) { \
|
if (_fp != NULL) { \
|
||||||
(_fp)(_n); \
|
(_fp)(GET_HASH_NODE_DATA(_n)); \
|
||||||
} \
|
} \
|
||||||
taosMemoryFreeClear(_n); \
|
taosMemoryFreeClear(_n); \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
struct SHashNode {
|
struct SHashNode {
|
||||||
|
@ -56,7 +56,7 @@ typedef struct SHashEntry {
|
||||||
} SHashEntry;
|
} SHashEntry;
|
||||||
|
|
||||||
struct SHashObj {
|
struct SHashObj {
|
||||||
SHashEntry ** hashList;
|
SHashEntry **hashList;
|
||||||
size_t capacity; // number of slots
|
size_t capacity; // number of slots
|
||||||
int64_t size; // number of elements in hash table
|
int64_t size; // number of elements in hash table
|
||||||
_hash_fn_t hashFp; // hash function
|
_hash_fn_t hashFp; // hash function
|
||||||
|
@ -65,7 +65,7 @@ struct SHashObj {
|
||||||
SRWLatch lock; // read-write spin lock
|
SRWLatch lock; // read-write spin lock
|
||||||
SHashLockTypeE type; // lock type
|
SHashLockTypeE type; // lock type
|
||||||
bool enableUpdate; // enable update
|
bool enableUpdate; // enable update
|
||||||
SArray * pMemBlock; // memory block allocated for SHashEntry
|
SArray *pMemBlock; // memory block allocated for SHashEntry
|
||||||
_hash_before_fn_t callbackFp; // function invoked before return the value to caller
|
_hash_before_fn_t callbackFp; // function invoked before return the value to caller
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -633,7 +633,7 @@ void taosHashTableResize(SHashObj *pHashObj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t st = taosGetTimestampUs();
|
int64_t st = taosGetTimestampUs();
|
||||||
void * pNewEntryList = taosMemoryRealloc(pHashObj->hashList, sizeof(void *) * newCapacity);
|
void *pNewEntryList = taosMemoryRealloc(pHashObj->hashList, sizeof(void *) * newCapacity);
|
||||||
if (pNewEntryList == NULL) {
|
if (pNewEntryList == NULL) {
|
||||||
// uDebug("cache resize failed due to out of memory, capacity remain:%zu", pHashObj->capacity);
|
// uDebug("cache resize failed due to out of memory, capacity remain:%zu", pHashObj->capacity);
|
||||||
return;
|
return;
|
||||||
|
@ -642,7 +642,7 @@ void taosHashTableResize(SHashObj *pHashObj) {
|
||||||
pHashObj->hashList = pNewEntryList;
|
pHashObj->hashList = pNewEntryList;
|
||||||
|
|
||||||
size_t inc = newCapacity - pHashObj->capacity;
|
size_t inc = newCapacity - pHashObj->capacity;
|
||||||
void * p = taosMemoryCalloc(inc, sizeof(SHashEntry));
|
void *p = taosMemoryCalloc(inc, sizeof(SHashEntry));
|
||||||
|
|
||||||
for (int32_t i = 0; i < inc; ++i) {
|
for (int32_t i = 0; i < inc; ++i) {
|
||||||
pHashObj->hashList[i + pHashObj->capacity] = (void *)((char *)p + i * sizeof(SHashEntry));
|
pHashObj->hashList[i + pHashObj->capacity] = (void *)((char *)p + i * sizeof(SHashEntry));
|
||||||
|
@ -653,9 +653,9 @@ void taosHashTableResize(SHashObj *pHashObj) {
|
||||||
pHashObj->capacity = newCapacity;
|
pHashObj->capacity = newCapacity;
|
||||||
for (int32_t idx = 0; idx < pHashObj->capacity; ++idx) {
|
for (int32_t idx = 0; idx < pHashObj->capacity; ++idx) {
|
||||||
SHashEntry *pe = pHashObj->hashList[idx];
|
SHashEntry *pe = pHashObj->hashList[idx];
|
||||||
SHashNode * pNode;
|
SHashNode *pNode;
|
||||||
SHashNode * pNext;
|
SHashNode *pNext;
|
||||||
SHashNode * pPrev = NULL;
|
SHashNode *pPrev = NULL;
|
||||||
|
|
||||||
if (pe->num == 0) {
|
if (pe->num == 0) {
|
||||||
assert(pe->next == NULL);
|
assert(pe->next == NULL);
|
||||||
|
|
Loading…
Reference in New Issue