diff --git a/src/inc/mnode.h b/src/inc/mnode.h index adb1f2788522b81fbd025e393c7bbc8a4fe156e7..cd667064341e7523c5c63cd3cb2a9554ca84da6a 100644 --- a/src/inc/mnode.h +++ b/src/inc/mnode.h @@ -102,9 +102,8 @@ typedef struct { } SVnodeGid; typedef struct { - char tableId[TSDB_TABLE_ID_LEN]; + char tableId[TSDB_TABLE_ID_LEN + 1]; int8_t type; - int8_t dirty; } STableInfo; typedef struct SSuperTableObj { diff --git a/src/mnode/inc/mgmtAcct.h b/src/mnode/inc/mgmtAcct.h index 967aeb1b3fbce1a35c77ab89f4434ccba7564ed1..36758c19ebe441d16ce02443792edd556d57f013 100644 --- a/src/mnode/inc/mgmtAcct.h +++ b/src/mnode/inc/mgmtAcct.h @@ -32,10 +32,10 @@ void acctCleanUp(); SAcctObj *acctGetAcct(char *acctName); int32_t acctCheck(SAcctObj *pAcct, EAcctGrantType type); -int32_t acctAddDb(SAcctObj *pAcct, SDbObj *pDb); -int32_t acctRemoveDb(SAcctObj *pAcct, SDbObj *pDb); -int32_t acctAddUser(SAcctObj *pAcct, SUserObj *pUser); -int32_t acctRemoveUser(SAcctObj *pAcct, SUserObj *pUser); +void acctAddDb(SAcctObj *pAcct, SDbObj *pDb); +void acctRemoveDb(SAcctObj *pAcct, SDbObj *pDb); +void acctAddUser(SAcctObj *pAcct, SUserObj *pUser); +void acctRemoveUser(SAcctObj *pAcct, SUserObj *pUser); #ifdef __cplusplus } diff --git a/src/mnode/inc/mgmtChildTable.h b/src/mnode/inc/mgmtChildTable.h deleted file mode 100644 index 3f6b1d8b858a8e9bcbee8f59a65ab07b87c99965..0000000000000000000000000000000000000000 --- a/src/mnode/inc/mgmtChildTable.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef TBASE_MNODE_CHILD_TABLE_H -#define TBASE_MNODE_CHILD_TABLE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "taosdef.h" -#include "mnode.h" - -int32_t mgmtInitChildTables(); -void mgmtCleanUpChildTables(); -void * mgmtGetChildTable(char *tableId); - -void mgmtCreateChildTable(SQueuedMsg *pMsg); -void mgmtDropChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable); -void mgmtGetChildTableMeta(SQueuedMsg *pMsg, SChildTableObj *pTable); -void mgmtAlterChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable); -void mgmtDropAllChildTables(SDbObj *pDropDb); -void mgmtDropAllChildTablesInStable(SSuperTableObj *pStable); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/mnode/inc/mgmtDb.h b/src/mnode/inc/mgmtDb.h index decf25a5c183c9ff56176dbb63558fff3350be38..f043211c8cd56159379f334ea132f934d4ab9909 100644 --- a/src/mnode/inc/mgmtDb.h +++ b/src/mnode/inc/mgmtDb.h @@ -27,6 +27,8 @@ int32_t mgmtInitDbs(); void mgmtCleanUpDbs(); SDbObj *mgmtGetDb(char *db); SDbObj *mgmtGetDbByTableId(char *db); +void mgmtIncDbRef(SDbObj *pDb); +void mgmtDecDbRef(SDbObj *pDb) bool mgmtCheckIsMonitorDB(char *db, char *monitordb); void mgmtDropAllDbs(SAcctObj *pAcct); diff --git a/src/mnode/inc/mgmtSdb.h b/src/mnode/inc/mgmtSdb.h index a598a21173f7c3f9d37752f163925a3b27f60c8f..d986170d0ae2fecd326ea9bb94b74654810dd46a 100644 --- a/src/mnode/inc/mgmtSdb.h +++ b/src/mnode/inc/mgmtSdb.h @@ -62,6 +62,8 @@ int32_t sdbUpdateRow(SSdbOperDesc *pOper); void *sdbGetRow(void *handle, void *key); void *sdbFetchRow(void *handle, void *pNode, void **ppRow); +void sdbIncRef(void *thandle, void *pRow); +void sdbDecRef(void *thandle, void *pRow); int64_t sdbGetNumOfRows(void *handle); int64_t sdbGetId(void *handle); uint64_t sdbGetVersion(); diff --git a/src/mnode/inc/mgmtSuperTable.h b/src/mnode/inc/mgmtSuperTable.h deleted file mode 100644 index 73809148dec89f0e5c97a59164baa6490d0c4689..0000000000000000000000000000000000000000 --- a/src/mnode/inc/mgmtSuperTable.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#ifndef TBASE_MNODE_SUPER_TABLE_H -#define TBASE_MNODE_SUPER_TABLE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "taosdef.h" -#include "mnode.h" - -int32_t mgmtInitSuperTables(); -void mgmtCleanUpSuperTables(); -void * mgmtGetSuperTable(char *tableId); - -void mgmtCreateSuperTable(SQueuedMsg *pMsg); -void mgmtDropSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pTable); -void mgmtGetSuperTableMeta(SQueuedMsg *pMsg, SSuperTableObj *pTable); -void mgmtAlterSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pTable); -void mgmtDropAllSuperTables(SDbObj *pDropDb); -int32_t mgmtSetSchemaFromSuperTable(SSchema *pSchema, SSuperTableObj *pTable); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/mnode/inc/mgmtTable.h b/src/mnode/inc/mgmtTable.h index 66557b33621bc1b3d950491009e02cf2799e042a..41ddb3b9f3281fcb6fce2797c99391dd47f4644e 100644 --- a/src/mnode/inc/mgmtTable.h +++ b/src/mnode/inc/mgmtTable.h @@ -28,7 +28,10 @@ extern "C" { int32_t mgmtInitTables(); void mgmtCleanUpTables(); STableInfo* mgmtGetTable(char* tableId); -void mgmtExtractTableName(char* tableId, char* tableName); +void mgmtIncTableRef(STableInfo *pTable); +void mgmtDecTableRef(STableInfo *pTable); +void mgmtDropAllChildTables(SDbObj *pDropDb); +void mgmtDropAllSuperTables(SDbObj *pDropDb); #ifdef __cplusplus } diff --git a/src/mnode/inc/mgmtUser.h b/src/mnode/inc/mgmtUser.h index ff3bfa3be6f5b1e21302a71f48f29b9177a1231d..f5c9b96f03b078ff1c55ef70fc7211aa8a27af31 100644 --- a/src/mnode/inc/mgmtUser.h +++ b/src/mnode/inc/mgmtUser.h @@ -24,6 +24,8 @@ extern "C" { int32_t mgmtInitUsers(); void mgmtCleanUpUsers(); SUserObj *mgmtGetUser(char *name); +void mgmtIncUserRef(SUserObj *pUser); +void mgmtDecUserRef(SUserObj *pUser); SUserObj *mgmtGetUserFromConn(void *pConn, bool *usePublicIp); int32_t mgmtCreateUser(SAcctObj *pAcct, char *name, char *pass); void mgmtDropAllUsers(SAcctObj *pAcct); diff --git a/src/mnode/src/mgmtAcct.c b/src/mnode/src/mgmtAcct.c index d3d2ec697d070ca68ab33d7c73210e263bfc72a3..602c924a0c7ca8e4e79d1b9576e0a3c98e682f68 100644 --- a/src/mnode/src/mgmtAcct.c +++ b/src/mnode/src/mgmtAcct.c @@ -33,7 +33,7 @@ SAcctObj *acctGetAcct(char *acctName) { return &tsAcctObj; } int32_t acctCheck(SAcctObj *pAcct, EAcctGrantType type) { return TSDB_CODE_SUCCESS; } #endif -int32_t acctAddDb(SAcctObj *pAcct, SDbObj *pDb) { +void acctAddDb(SAcctObj *pAcct, SDbObj *pDb) { pthread_mutex_lock(&pAcct->mutex); pDb->next = pAcct->pHead; pDb->prev = NULL; @@ -46,11 +46,9 @@ int32_t acctAddDb(SAcctObj *pAcct, SDbObj *pDb) { pAcct->pHead = pDb; pAcct->acctInfo.numOfDbs++; pthread_mutex_unlock(&pAcct->mutex); - - return 0; } -int32_t acctRemoveDb(SAcctObj *pAcct, SDbObj *pDb) { +void acctRemoveDb(SAcctObj *pAcct, SDbObj *pDb) { pthread_mutex_lock(&pAcct->mutex); if (pDb->prev) { pDb->prev->next = pDb->next; @@ -66,11 +64,9 @@ int32_t acctRemoveDb(SAcctObj *pAcct, SDbObj *pDb) { pAcct->acctInfo.numOfDbs--; pthread_mutex_unlock(&pAcct->mutex); - - return 0; } -int32_t acctAddUser(SAcctObj *pAcct, SUserObj *pUser) { +void acctAddUser(SAcctObj *pAcct, SUserObj *pUser) { pthread_mutex_lock(&pAcct->mutex); pUser->next = pAcct->pUser; pUser->prev = NULL; @@ -83,11 +79,9 @@ int32_t acctAddUser(SAcctObj *pAcct, SUserObj *pUser) { pAcct->acctInfo.numOfUsers++; pUser->pAcct = pAcct; pthread_mutex_unlock(&pAcct->mutex); - - return 0; } -int32_t acctRemoveUser(SAcctObj *pAcct, SUserObj *pUser) { +void acctRemoveUser(SAcctObj *pAcct, SUserObj *pUser) { pthread_mutex_lock(&pAcct->mutex); if (pUser->prev) { pUser->prev->next = pUser->next; @@ -103,6 +97,4 @@ int32_t acctRemoveUser(SAcctObj *pAcct, SUserObj *pUser) { pAcct->acctInfo.numOfUsers--; pthread_mutex_unlock(&pAcct->mutex); - - return 0; } \ No newline at end of file diff --git a/src/mnode/src/mgmtChildTable.c b/src/mnode/src/mgmtChildTable.c deleted file mode 100644 index 48abae3e9df6f5a061c5816607bb729f764b44e7..0000000000000000000000000000000000000000 --- a/src/mnode/src/mgmtChildTable.c +++ /dev/null @@ -1,1226 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#define _DEFAULT_SOURCE -#include "os.h" -#include "taosmsg.h" -#include "tscompression.h" -#include "tskiplist.h" -#include "ttime.h" -#include "tstatus.h" -#include "tutil.h" -#include "qast.h" -#include "qextbuffer.h" -#include "taoserror.h" -#include "taosmsg.h" -#include "tscompression.h" -#include "tskiplist.h" -#include "tsqlfunction.h" -#include "tstatus.h" -#include "ttime.h" -#include "name.h" -#include "mnode.h" -#include "mgmtAcct.h" -#include "mgmtChildTable.h" -#include "mgmtDb.h" -#include "mgmtDClient.h" -#include "mgmtDnode.h" -#include "mgmtDServer.h" -#include "mgmtGrant.h" -#include "mgmtMnode.h" -#include "mgmtProfile.h" -#include "mgmtSdb.h" -#include "mgmtShell.h" -#include "mgmtSuperTable.h" -#include "mgmtTable.h" -#include "mgmtVgroup.h" -#include "mgmtUser.h" - -void *tsChildTableSdb; -static int32_t tsChildTableUpdateSize; -static void mgmtProcessMultiTableMetaMsg(SQueuedMsg *queueMsg); -static void mgmtProcessCreateTableRsp(SRpcMsg *rpcMsg); -static void mgmtProcessAlterTableRsp(SRpcMsg *rpcMsg); -static void mgmtProcessDropTableRsp(SRpcMsg *rpcMsg); -static void mgmtProcessTableCfgMsg(SRpcMsg *rpcMsg); -static int32_t mgmtGetShowTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); -static int32_t mgmtRetrieveShowTables(SShowObj *pShow, char *data, int32_t rows, void *pConn); - -static void mgmtDestroyChildTable(SChildTableObj *pTable) { - tfree(pTable->schema); - tfree(pTable->sql); - tfree(pTable); -} - -static int32_t mgmtChildTableActionDestroy(SSdbOperDesc *pOper) { - mgmtDestroyChildTable(pOper->pObj); - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtChildTableActionInsert(SSdbOperDesc *pOper) { - SChildTableObj *pTable = pOper->pObj; - - SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); - if (pVgroup == NULL) { - mError("ctable:%s, not in vgroup:%d", pTable->info.tableId, pTable->vgId); - return TSDB_CODE_INVALID_VGROUP_ID; - } - - SDbObj *pDb = mgmtGetDb(pVgroup->dbName); - if (pDb == NULL) { - mError("ctable:%s, vgroup:%d not in db:%s", pTable->info.tableId, pVgroup->vgId, pVgroup->dbName); - return TSDB_CODE_INVALID_DB; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("ctable:%s, account:%s not exists", pTable->info.tableId, pDb->cfg.acct); - return TSDB_CODE_INVALID_ACCT; - } - - if (pTable->info.type == TSDB_CHILD_TABLE) { - pTable->superTable = mgmtGetSuperTable(pTable->superTableId); - pTable->superTable->numOfTables++; - grantAdd(TSDB_GRANT_TIMESERIES, pTable->superTable->numOfColumns - 1); - pAcct->acctInfo.numOfTimeSeries += (pTable->superTable->numOfColumns - 1); - } else { - grantAdd(TSDB_GRANT_TIMESERIES, pTable->numOfColumns - 1); - pAcct->acctInfo.numOfTimeSeries += (pTable->numOfColumns - 1); - } - mgmtAddTableIntoDb(pDb); - mgmtAddTableIntoVgroup(pVgroup, pTable); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtChildTableActionDelete(SSdbOperDesc *pOper) { - SChildTableObj *pTable = pOper->pObj; - if (pTable->vgId == 0) { - return TSDB_CODE_INVALID_VGROUP_ID; - } - - SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); - if (pVgroup == NULL) { - return TSDB_CODE_INVALID_VGROUP_ID; - } - - SDbObj *pDb = mgmtGetDb(pVgroup->dbName); - if (pDb == NULL) { - mError("ctable:%s, vgroup:%d not in DB:%s", pTable->info.tableId, pVgroup->vgId, pVgroup->dbName); - return TSDB_CODE_INVALID_DB; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("ctable:%s, account:%s not exists", pTable->info.tableId, pDb->cfg.acct); - return TSDB_CODE_INVALID_ACCT; - } - - if (pTable->info.type == TSDB_CHILD_TABLE) { - grantRestore(TSDB_GRANT_TIMESERIES, pTable->superTable->numOfColumns - 1); - pAcct->acctInfo.numOfTimeSeries -= (pTable->superTable->numOfColumns - 1); - pTable->superTable->numOfTables--; - } else { - grantRestore(TSDB_GRANT_TIMESERIES, pTable->numOfColumns - 1); - pAcct->acctInfo.numOfTimeSeries -= (pTable->numOfColumns - 1); - } - mgmtRemoveTableFromDb(pDb); - mgmtRemoveTableFromVgroup(pVgroup, pTable); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtChildTableActionUpdate(SSdbOperDesc *pOper) { - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtChildTableActionEncode(SSdbOperDesc *pOper) { - SChildTableObj *pTable = pOper->pObj; - assert(pTable != NULL && pOper->rowData != NULL); - - if (pTable->info.type == TSDB_CHILD_TABLE) { - memcpy(pOper->rowData, pTable, tsChildTableUpdateSize); - pOper->rowSize = tsChildTableUpdateSize; - } else { - int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); - if (pOper->maxRowSize < tsChildTableUpdateSize + schemaSize) { - return TSDB_CODE_INVALID_MSG_LEN; - } - memcpy(pOper->rowData, pTable, tsChildTableUpdateSize); - memcpy(pOper->rowData + tsChildTableUpdateSize, pTable->schema, schemaSize); - memcpy(pOper->rowData + tsChildTableUpdateSize + schemaSize, pTable->sql, pTable->sqlLen); - pOper->rowSize = tsChildTableUpdateSize + schemaSize + pTable->sqlLen; - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtChildTableActionDecode(SSdbOperDesc *pOper) { - assert(pOper->rowData != NULL); - SChildTableObj *pTable = calloc(1, sizeof(SChildTableObj)); - if (pTable == NULL) { - return TSDB_CODE_SERV_OUT_OF_MEMORY; - } - - memcpy(pTable, pOper->rowData, tsChildTableUpdateSize); - - if (pTable->info.type != TSDB_CHILD_TABLE) { - int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); - pTable->schema = (SSchema *)malloc(schemaSize); - if (pTable->schema == NULL) { - mgmtDestroyChildTable(pTable); - return TSDB_CODE_SERV_OUT_OF_MEMORY; - } - memcpy(pTable->schema, pOper->rowData + tsChildTableUpdateSize, schemaSize); - - pTable->sql = (char *)malloc(pTable->sqlLen); - if (pTable->sql == NULL) { - mgmtDestroyChildTable(pTable); - return TSDB_CODE_SERV_OUT_OF_MEMORY; - } - memcpy(pTable->sql, pOper->rowData + tsChildTableUpdateSize + schemaSize, pTable->sqlLen); - } - - pOper->pObj = pTable; - return TSDB_CODE_SUCCESS; -} - -int32_t mgmtInitChildTables() { - void *pNode = NULL; - void *pLastNode = NULL; - SChildTableObj *pTable = NULL; - - SChildTableObj tObj; - tsChildTableUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - - SSdbTableDesc tableDesc = { - .tableName = "ctables", - .hashSessions = tsMaxTables, - .maxRowSize = sizeof(SChildTableObj) + sizeof(SSchema) * TSDB_MAX_COLUMNS, - .keyType = SDB_KEY_TYPE_STRING, - .insertFp = mgmtChildTableActionInsert, - .deleteFp = mgmtChildTableActionDelete, - .updateFp = mgmtChildTableActionUpdate, - .encodeFp = mgmtChildTableActionEncode, - .decodeFp = mgmtChildTableActionDecode, - .destroyFp = mgmtChildTableActionDestroy, - }; - - tsChildTableSdb = sdbOpenTable(&tableDesc); - if (tsChildTableSdb == NULL) { - mError("failed to init child table data"); - return -1; - } - - pNode = NULL; - while (1) { - pLastNode = pNode; - pNode = sdbFetchRow(tsChildTableSdb, pNode, (void **)&pTable); - if (pTable == NULL) { - break; - } - - SDbObj *pDb = mgmtGetDbByTableId(pTable->info.tableId); - if (pDb == NULL) { - mError("ctable:%s, failed to get db, discard it", pTable->info.tableId); - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_LOCAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - sdbDeleteRow(&desc); - pNode = pLastNode; - continue; - } - - SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); - if (pVgroup == NULL) { - mError("ctable:%s, failed to get vgroup:%d sid:%d, discard it", pTable->info.tableId, pTable->vgId, pTable->sid); - pTable->vgId = 0; - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_LOCAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - sdbDeleteRow(&desc); - pNode = pLastNode; - continue; - } - - if (strcmp(pVgroup->dbName, pDb->name) != 0) { - mError("ctable:%s, db:%s not match with vgroup:%d db:%s sid:%d, discard it", - pTable->info.tableId, pDb->name, pTable->vgId, pVgroup->dbName, pTable->sid); - pTable->vgId = 0; - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_LOCAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - sdbDeleteRow(&desc); - pNode = pLastNode; - continue; - } - - if (pVgroup->tableList == NULL) { - mError("ctable:%s, vgroup:%d tableList is null", pTable->info.tableId, pTable->vgId); - pTable->vgId = 0; - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_LOCAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - sdbDeleteRow(&desc); - pNode = pLastNode; - continue; - } - - if (pTable->info.type == TSDB_CHILD_TABLE) { - SSuperTableObj *pSuperTable = mgmtGetSuperTable(pTable->superTableId); - if (pSuperTable == NULL) { - mError("ctable:%s, stable:%s not exist", pTable->info.tableId, pTable->superTableId); - pTable->vgId = 0; - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_LOCAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - sdbDeleteRow(&desc); - pNode = pLastNode; - continue; - } - } - } - - mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_TABLES_META, mgmtProcessMultiTableMetaMsg); - mgmtAddShellShowMetaHandle(TSDB_MGMT_TABLE_TABLE, mgmtGetShowTableMeta); - mgmtAddShellShowRetrieveHandle(TSDB_MGMT_TABLE_TABLE, mgmtRetrieveShowTables); - mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_CREATE_TABLE_RSP, mgmtProcessCreateTableRsp); - mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_DROP_TABLE_RSP, mgmtProcessDropTableRsp); - mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_ALTER_TABLE_RSP, mgmtProcessAlterTableRsp); - mgmtAddDServerMsgHandle(TSDB_MSG_TYPE_DM_CONFIG_TABLE, mgmtProcessTableCfgMsg); - - mTrace("child table is initialized"); - return 0; -} - -void mgmtCleanUpChildTables() { - sdbCloseTable(tsChildTableSdb); -} - -static void *mgmtBuildCreateChildTableMsg(SCMCreateTableMsg *pMsg, SChildTableObj *pTable) { - char * pTagData = NULL; - int32_t tagDataLen = 0; - int32_t totalCols = 0; - int32_t contLen = 0; - if (pTable->info.type == TSDB_CHILD_TABLE && pMsg != NULL) { - pTagData = pMsg->schema + TSDB_TABLE_ID_LEN + 1; - tagDataLen = htonl(pMsg->contLen) - sizeof(SCMCreateTableMsg) - TSDB_TABLE_ID_LEN - 1; - totalCols = pTable->superTable->numOfColumns + pTable->superTable->numOfTags; - contLen = sizeof(SMDCreateTableMsg) + totalCols * sizeof(SSchema) + tagDataLen + pTable->sqlLen; - } else { - totalCols = pTable->numOfColumns; - contLen = sizeof(SMDCreateTableMsg) + totalCols * sizeof(SSchema) + pTable->sqlLen; - } - - SMDCreateTableMsg *pCreate = rpcMallocCont(contLen); - if (pCreate == NULL) { - terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; - return NULL; - } - - memcpy(pCreate->tableId, pTable->info.tableId, TSDB_TABLE_ID_LEN + 1); - pCreate->contLen = htonl(contLen); - pCreate->vgId = htonl(pTable->vgId); - pCreate->tableType = pTable->info.type; - pCreate->createdTime = htobe64(pTable->createdTime); - pCreate->sid = htonl(pTable->sid); - pCreate->sqlDataLen = htonl(pTable->sqlLen); - pCreate->uid = htobe64(pTable->uid); - - if (pTable->info.type == TSDB_CHILD_TABLE) { - memcpy(pCreate->superTableId, pTable->superTable->info.tableId, TSDB_TABLE_ID_LEN + 1); - pCreate->numOfColumns = htons(pTable->superTable->numOfColumns); - pCreate->numOfTags = htons(pTable->superTable->numOfTags); - pCreate->sversion = htonl(pTable->superTable->sversion); - pCreate->tagDataLen = htonl(tagDataLen); - pCreate->superTableUid = htobe64(pTable->superTable->uid); - } else { - pCreate->numOfColumns = htons(pTable->numOfColumns); - pCreate->numOfTags = 0; - pCreate->sversion = htonl(pTable->sversion); - pCreate->tagDataLen = 0; - pCreate->superTableUid = 0; - } - - SSchema *pSchema = (SSchema *) pCreate->data; - if (pTable->info.type == TSDB_CHILD_TABLE) { - memcpy(pSchema, pTable->superTable->schema, totalCols * sizeof(SSchema)); - } else { - memcpy(pSchema, pTable->schema, totalCols * sizeof(SSchema)); - } - for (int32_t col = 0; col < totalCols; ++col) { - pSchema->bytes = htons(pSchema->bytes); - pSchema->colId = htons(pSchema->colId); - pSchema++; - } - - if (pTable->info.type == TSDB_CHILD_TABLE && pMsg != NULL) { - memcpy(pCreate->data + totalCols * sizeof(SSchema), pTagData, tagDataLen); - memcpy(pCreate->data + totalCols * sizeof(SSchema) + tagDataLen, pTable->sql, pTable->sqlLen); - } - - return pCreate; -} - -static SChildTableObj* mgmtDoCreateChildTable(SCMCreateTableMsg *pCreate, SVgObj *pVgroup, int32_t tid) { - SChildTableObj *pTable = (SChildTableObj *) calloc(1, sizeof(SChildTableObj)); - if (pTable == NULL) { - mError("ctable:%s, failed to alloc memory", pCreate->tableId); - terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; - return NULL; - } - - if (pCreate->numOfColumns == 0) { - pTable->info.type = TSDB_CHILD_TABLE; - } else { - pTable->info.type = TSDB_NORMAL_TABLE; - } - - strcpy(pTable->info.tableId, pCreate->tableId); - pTable->createdTime = taosGetTimestampMs(); - pTable->sid = tid; - pTable->vgId = pVgroup->vgId; - - if (pTable->info.type == TSDB_CHILD_TABLE) { - char *pTagData = (char *) pCreate->schema; // it is a tag key - SSuperTableObj *pSuperTable = mgmtGetSuperTable(pTagData); - if (pSuperTable == NULL) { - mError("ctable:%s, corresponding super table does not exist", pCreate->tableId); - free(pTable); - terrno = TSDB_CODE_INVALID_TABLE; - return NULL; - } - - strcpy(pTable->superTableId, pSuperTable->info.tableId); - pTable->uid = (((uint64_t) pTable->vgId) << 40) + ((((uint64_t) pTable->sid) & ((1ul << 24) - 1ul)) << 16) + - (sdbGetVersion() & ((1ul << 16) - 1ul)); - pTable->superTable = pSuperTable; - } else { - pTable->uid = (((uint64_t) pTable->createdTime) << 16) + (sdbGetVersion() & ((1ul << 16) - 1ul)); - pTable->sversion = 0; - pTable->numOfColumns = htons(pCreate->numOfColumns); - pTable->sqlLen = htons(pCreate->sqlLen); - - int32_t numOfCols = pTable->numOfColumns; - int32_t schemaSize = numOfCols * sizeof(SSchema); - pTable->schema = (SSchema *) calloc(1, schemaSize); - if (pTable->schema == NULL) { - free(pTable); - terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; - return NULL; - } - memcpy(pTable->schema, pCreate->schema, numOfCols * sizeof(SSchema)); - - pTable->nextColId = 0; - for (int32_t col = 0; col < numOfCols; col++) { - SSchema *tschema = pTable->schema; - tschema[col].colId = pTable->nextColId++; - tschema[col].bytes = htons(tschema[col].bytes); - } - - if (pTable->sqlLen != 0) { - pTable->info.type = TSDB_STREAM_TABLE; - pTable->sql = calloc(1, pTable->sqlLen); - if (pTable->sql == NULL) { - free(pTable); - terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; - return NULL; - } - memcpy(pTable->sql, (char *) (pCreate->schema) + numOfCols * sizeof(SSchema), pTable->sqlLen); - pTable->sql[pTable->sqlLen - 1] = 0; - mTrace("table:%s, stream sql len:%d sql:%s", pTable->info.tableId, pTable->sqlLen, pTable->sql); - } - } - - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_GLOBAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - - if (sdbInsertRow(&desc) != TSDB_CODE_SUCCESS) { - free(pTable); - mError("ctable:%s, update sdb error", pCreate->tableId); - terrno = TSDB_CODE_SDB_ERROR; - return NULL; - } - - mTrace("ctable:%s, create ctable in vgroup, uid:%" PRIu64 , pTable->info.tableId, pTable->uid); - return pTable; -} - -void mgmtCreateChildTable(SQueuedMsg *pMsg) { - SCMCreateTableMsg *pCreate = pMsg->pCont; - - int32_t code = grantCheck(TSDB_GRANT_TIMESERIES); - if (code != TSDB_CODE_SUCCESS) { - mError("table:%s, failed to create, grant not", pCreate->tableId); - mgmtSendSimpleResp(pMsg->thandle, code); - return; - } - - SQueuedMsg *newMsg = malloc(sizeof(SQueuedMsg)); - memcpy(newMsg, pMsg, sizeof(SQueuedMsg)); - pMsg->pCont = NULL; - - SVgObj *pVgroup = mgmtGetAvailableVgroup(pMsg->pDb); - if (pVgroup == NULL) { - mTrace("table:%s, start to create a new vgroup", pCreate->tableId); - mgmtCreateVgroup(newMsg); - return; - } - - int32_t sid = taosAllocateId(pVgroup->idPool); - if (sid < 0) { - mTrace("tables:%s, no enough sid in vgroup:%d", pVgroup->vgId); - mgmtCreateVgroup(newMsg); - return; - } - - SChildTableObj *pTable = mgmtDoCreateChildTable(pCreate, pVgroup, sid); - if (pTable == NULL) { - mgmtSendSimpleResp(pMsg->thandle, terrno); - mgmtFreeQueuedMsg(newMsg); - return; - } - - SMDCreateTableMsg *pMDCreate = mgmtBuildCreateChildTableMsg(pCreate, (SChildTableObj *) pTable); - if (pMDCreate == NULL) { - mgmtSendSimpleResp(pMsg->thandle, terrno); - mgmtFreeQueuedMsg(newMsg); - return; - } - - SRpcIpSet ipSet = mgmtGetIpSetFromVgroup(pVgroup); - SRpcMsg rpcMsg = { - .handle = newMsg, - .pCont = pMDCreate, - .contLen = htonl(pMDCreate->contLen), - .code = 0, - .msgType = TSDB_MSG_TYPE_MD_CREATE_TABLE - }; - - newMsg->ahandle = pTable; - mgmtSendMsgToDnode(&ipSet, &rpcMsg); -} - -void mgmtDropChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable) { - SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); - if (pVgroup == NULL) { - mError("ctable:%s, failed to drop child table, vgroup not exist", pTable->info.tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_OTHERS); - return; - } - - SMDDropTableMsg *pDrop = rpcMallocCont(sizeof(SMDDropTableMsg)); - if (pDrop == NULL) { - mError("ctable:%s, failed to drop child table, no enough memory", pTable->info.tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); - return; - } - - strcpy(pDrop->tableId, pTable->info.tableId); - pDrop->vgId = htonl(pTable->vgId); - pDrop->contLen = htonl(sizeof(SMDDropTableMsg)); - pDrop->sid = htonl(pTable->sid); - pDrop->uid = htobe64(pTable->uid); - - SRpcIpSet ipSet = mgmtGetIpSetFromVgroup(pVgroup); - - mTrace("ctable:%s, send drop table msg", pDrop->tableId); - SRpcMsg rpcMsg = { - .handle = pMsg, - .pCont = pDrop, - .contLen = sizeof(SMDDropTableMsg), - .code = 0, - .msgType = TSDB_MSG_TYPE_MD_DROP_TABLE - }; - - pMsg->ahandle = pTable; - mgmtSendMsgToDnode(&ipSet, &rpcMsg); -} - -void* mgmtGetChildTable(char *tableId) { - return sdbGetRow(tsChildTableSdb, tableId); -} - -int32_t mgmtModifyChildTableTagValueByName(SChildTableObj *pTable, char *tagName, char *nContent) { -// TODO: send message to dnode -// int32_t col = mgmtFindSuperTableTagIndex(pTable->superTable, tagName); -// if (col < 0 || col > pTable->superTable->numOfTags) { -// return TSDB_CODE_APP_ERROR; -// } -// -// //TODO send msg to dnode -// mTrace("Succeed to modify tag column %d of table %s", col, pTable->info.tableId); -// return TSDB_CODE_SUCCESS; - -// int32_t rowSize = 0; -// SSchema *schema = (SSchema *)(pSuperTable->schema + (pSuperTable->numOfColumns + col) * sizeof(SSchema)); -// -// if (col == 0) { -// pTable->isDirty = 1; -// removeMeterFromMetricIndex(pSuperTable, pTable); -// } -// memcpy(pTable->pTagData + mgmtGetTagsLength(pMetric, col) + TSDB_TABLE_ID_LEN, nContent, schema->bytes); -// if (col == 0) { -// addMeterIntoMetricIndex(pMetric, pTable); -// } -// -// // Encode the string -// int32_t size = sizeof(STabObj) + TSDB_MAX_BYTES_PER_ROW + 1; -// char *msg = (char *)malloc(size); -// if (msg == NULL) { -// mError("failed to allocate message memory while modify tag value"); -// return TSDB_CODE_APP_ERROR; -// } -// memset(msg, 0, size); -// -// mgmtMeterActionEncode(pTable, msg, size, &rowSize); -// -// int32_t ret = sdbUpdateRow(tsChildTableSdb, msg, rowSize, 1); // Need callback function -// tfree(msg); -// -// if (pTable->isDirty) pTable->isDirty = 0; -// -// if (ret < 0) { -// mError("Failed to modify tag column %d of table %s", col, pTable->info.tableId); -// return TSDB_CODE_APP_ERROR; -// } -// -// mTrace("Succeed to modify tag column %d of table %s", col, pTable->info.tableId); -// return TSDB_CODE_SUCCESS; - return 0; -} - - -static int32_t mgmtFindNormalTableColumnIndex(SChildTableObj *pTable, char *colName) { - SSchema *schema = (SSchema *) pTable->schema; - for (int32_t i = 0; i < pTable->numOfColumns; i++) { - if (strcasecmp(schema[i].name, colName) == 0) { - return i; - } - } - - return -1; -} - -static int32_t mgmtAddNormalTableColumn(SChildTableObj *pTable, SSchema schema[], int32_t ncols) { - if (ncols <= 0) { - return TSDB_CODE_APP_ERROR; - } - - for (int32_t i = 0; i < ncols; i++) { - if (mgmtFindNormalTableColumnIndex(pTable, schema[i].name) > 0) { - return TSDB_CODE_APP_ERROR; - } - } - - SDbObj *pDb = mgmtGetDbByTableId(pTable->info.tableId); - if (pDb == NULL) { - mError("table: %s not belongs to any database", pTable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("DB: %s not belongs to andy account", pDb->name); - return TSDB_CODE_APP_ERROR; - } - - int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); - pTable->schema = realloc(pTable->schema, schemaSize + sizeof(SSchema) * ncols); - - memcpy(pTable->schema + schemaSize, schema, sizeof(SSchema) * ncols); - - SSchema *tschema = (SSchema *) (pTable->schema + sizeof(SSchema) * pTable->numOfColumns); - for (int32_t i = 0; i < ncols; i++) { - tschema[i].colId = pTable->nextColId++; - } - - pTable->numOfColumns += ncols; - pTable->sversion++; - pAcct->acctInfo.numOfTimeSeries += ncols; - - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_GLOBAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - desc.rowData = pTable; - desc.rowSize = tsChildTableUpdateSize; - sdbUpdateRow(&desc); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtDropNormalTableColumnByName(SChildTableObj *pTable, char *colName) { - int32_t col = mgmtFindNormalTableColumnIndex(pTable, colName); - if (col < 0) { - return TSDB_CODE_APP_ERROR; - } - - SDbObj *pDb = mgmtGetDbByTableId(pTable->info.tableId); - if (pDb == NULL) { - mError("table: %s not belongs to any database", pTable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("DB: %s not belongs to any account", pDb->name); - return TSDB_CODE_APP_ERROR; - } - - memmove(pTable->schema + sizeof(SSchema) * col, pTable->schema + sizeof(SSchema) * (col + 1), - sizeof(SSchema) * (pTable->numOfColumns - col - 1)); - - pTable->numOfColumns--; - pTable->sversion++; - - pAcct->acctInfo.numOfTimeSeries--; - - SSdbOperDesc desc = {0}; - desc.type = SDB_OPER_TYPE_GLOBAL; - desc.pObj = pTable; - desc.table = tsChildTableSdb; - desc.rowData = pTable; - desc.rowSize = tsChildTableUpdateSize; - sdbUpdateRow(&desc); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtSetSchemaFromNormalTable(SSchema *pSchema, SChildTableObj *pTable) { - int32_t numOfCols = pTable->numOfColumns; - for (int32_t i = 0; i < numOfCols; ++i) { - strcpy(pSchema->name, pTable->schema[i].name); - pSchema->type = pTable->schema[i].type; - pSchema->bytes = htons(pTable->schema[i].bytes); - pSchema->colId = htons(pTable->schema[i].colId); - pSchema++; - } - - return numOfCols * sizeof(SSchema); -} - -static int32_t mgmtDoGetChildTableMeta(SDbObj *pDb, SChildTableObj *pTable, STableMetaMsg *pMeta, bool usePublicIp) { - pMeta->uid = htobe64(pTable->uid); - pMeta->sid = htonl(pTable->sid); - pMeta->vgId = htonl(pTable->vgId); - pMeta->precision = pDb->cfg.precision; - pMeta->tableType = pTable->info.type; - strncpy(pMeta->tableId, pTable->info.tableId, tListLen(pTable->info.tableId)); - - if (pTable->info.type == TSDB_CHILD_TABLE) { - pMeta->sversion = htons(pTable->superTable->sversion); - pMeta->numOfTags = 0; - pMeta->numOfColumns = htons((int16_t)pTable->superTable->numOfColumns); - pMeta->contLen = sizeof(STableMetaMsg) + mgmtSetSchemaFromSuperTable(pMeta->schema, pTable->superTable); - strncpy(pMeta->stableId, pTable->superTable->info.tableId, tListLen(pMeta->stableId)); - } else { - pMeta->sversion = htons(pTable->sversion); - pMeta->numOfTags = 0; - pMeta->numOfColumns = htons((int16_t)pTable->numOfColumns); - pMeta->contLen = sizeof(STableMetaMsg) + mgmtSetSchemaFromNormalTable(pMeta->schema, pTable); - } - - SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); - if (pVgroup == NULL) { - mError("table:%s, failed to get table meta, db not selected", pTable->info.tableId); - return TSDB_CODE_INVALID_VGROUP_ID; - } - - for (int32_t i = 0; i < TSDB_VNODES_SUPPORT; ++i) { - if (usePublicIp) { - pMeta->vpeerDesc[i].ip = pVgroup->vnodeGid[i].publicIp; - } else { - pMeta->vpeerDesc[i].ip = pVgroup->vnodeGid[i].privateIp; - } - pMeta->vpeerDesc[i].vnode = htonl(pVgroup->vnodeGid[i].vnode); - } - pMeta->numOfVpeers = pVgroup->numOfVnodes; - - mTrace("table:%s, uid:%" PRIu64 " table meta is retrieved", pTable->info.tableId, pTable->uid); - - return TSDB_CODE_SUCCESS; -} - -void mgmtGetChildTableMeta(SQueuedMsg *pMsg, SChildTableObj *pTable) { - SCMTableInfoMsg *pInfo = pMsg->pCont; - SDbObj *pDb = mgmtGetDbByTableId(pInfo->tableId); - if (pDb == NULL || pDb->dirty) { - mError("table:%s, failed to get table meta, db not selected", pInfo->tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_DB_NOT_SELECTED); - return; - } - - if (pTable == NULL) { - if (htons(pInfo->createFlag) != 1) { - mError("table:%s, failed to get table meta, table not exist", pInfo->tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); - return; - } else { - //TODO: on demand create table from super table if table does not exists - int32_t contLen = sizeof(SCMCreateTableMsg) + sizeof(STagData); - SCMCreateTableMsg *pCreateMsg = rpcMallocCont(contLen); - if (pCreateMsg == NULL) { - mError("table:%s, failed to create table while get meta info, no enough memory", pInfo->tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); - return; - } - memcpy(pCreateMsg->schema, pInfo->tags, sizeof(STagData)); - strcpy(pCreateMsg->tableId, pInfo->tableId); - - SQueuedMsg *newMsg = malloc(sizeof(SQueuedMsg)); - memcpy(newMsg, pMsg, sizeof(SQueuedMsg)); - pMsg->pCont = NULL; - - newMsg->ahandle = newMsg->pCont; - newMsg->pCont = pCreateMsg; - mTrace("table:%s, start to create in demand", pInfo->tableId); - mgmtAddToShellQueue(newMsg); - return; - } - } - - STableMetaMsg *pMeta = rpcMallocCont(sizeof(STableMetaMsg) + sizeof(SSchema) * TSDB_MAX_COLUMNS); - if (pMeta == NULL) { - mError("table:%s, failed to get table meta, no enough memory", pTable->info.tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); - return; - } - - mgmtDoGetChildTableMeta(pDb, pTable, pMeta, pMsg->usePublicIp); - - SRpcMsg rpcRsp = { - .handle = pMsg->thandle, - .pCont = pMeta, - .contLen = pMeta->contLen, - }; - pMeta->contLen = htons(pMeta->contLen); - rpcSendResponse(&rpcRsp); -} - -void mgmtDropAllChildTables(SDbObj *pDropDb) { - void *pNode = NULL; - void *pLastNode = NULL; - int32_t numOfTables = 0; - int32_t dbNameLen = strlen(pDropDb->name); - SChildTableObj *pTable = NULL; - - while (1) { - pNode = sdbFetchRow(tsChildTableSdb, pNode, (void **)&pTable); - if (pTable == NULL) { - break; - } - - if (strncmp(pDropDb->name, pTable->info.tableId, dbNameLen) == 0) { - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_LOCAL, - .table = tsChildTableSdb, - .pObj = pTable, - }; - sdbDeleteRow(&oper); - pNode = pLastNode; - numOfTables++; - continue; - } - } - - mTrace("db:%s, all child tables:%d is dropped from sdb", pDropDb->name, numOfTables); -} - -void mgmtDropAllChildTablesInStable(SSuperTableObj *pStable) { - void *pNode = NULL; - void *pLastNode = NULL; - int32_t numOfTables = 0; - SChildTableObj *pTable = NULL; - - while (1) { - pNode = sdbFetchRow(tsChildTableSdb, pNode, (void **)&pTable); - if (pTable == NULL) { - break; - } - - if (pTable->superTable == pStable) { - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_LOCAL, - .table = tsChildTableSdb, - .pObj = pTable, - }; - sdbDeleteRow(&oper); - pNode = pLastNode; - numOfTables++; - continue; - } - } - - mTrace("stable:%s, all child tables:%d is dropped from sdb", pStable->info.tableId, numOfTables); -} - -static STableInfo* mgmtGetTableByPos(uint32_t dnodeId, int32_t vnode, int32_t sid) { - SDnodeObj *pObj = mgmtGetDnode(dnodeId); - SVgObj *pVgroup = mgmtGetVgroup(vnode); - - if (pObj == NULL || pVgroup == NULL) { - return NULL; - } - - return (STableInfo *)pVgroup->tableList[sid]; -} - -static void mgmtProcessTableCfgMsg(SRpcMsg *rpcMsg) { - if (mgmtCheckRedirect(rpcMsg->handle)) return; - - SDMConfigTableMsg *pCfg = (SDMConfigTableMsg *) rpcMsg->pCont; - pCfg->dnode = htonl(pCfg->dnode); - pCfg->vnode = htonl(pCfg->vnode); - pCfg->sid = htonl(pCfg->sid); - mTrace("dnode:%s, vnode:%d, sid:%d, receive table config msg", taosIpStr(pCfg->dnode), pCfg->vnode, pCfg->sid); - - STableInfo *pTable = mgmtGetTableByPos(pCfg->dnode, pCfg->vnode, pCfg->sid); - if (pTable == NULL) { - mError("dnode:%s, vnode:%d, sid:%d, table not found", taosIpStr(pCfg->dnode), pCfg->vnode, pCfg->sid); - mgmtSendSimpleResp(rpcMsg->handle, TSDB_CODE_NOT_ACTIVE_TABLE); - return; - } - - mgmtSendSimpleResp(rpcMsg->handle, TSDB_CODE_SUCCESS); - - SMDCreateTableMsg *pMDCreate = NULL; - pMDCreate = mgmtBuildCreateChildTableMsg(NULL, (SChildTableObj *) pTable); - if (pMDCreate == NULL) { - return; - } - - SRpcIpSet ipSet = mgmtGetIpSetFromIp(pCfg->dnode); - SRpcMsg rpcRsp = { - .handle = NULL, - .pCont = pMDCreate, - .contLen = htonl(pMDCreate->contLen), - .code = 0, - .msgType = TSDB_MSG_TYPE_MD_CREATE_TABLE - }; - mgmtSendMsgToDnode(&ipSet, &rpcRsp); -} - -static void mgmtProcessDropTableRsp(SRpcMsg *rpcMsg) { - if (rpcMsg->handle == NULL) return; - - SQueuedMsg *queueMsg = rpcMsg->handle; - queueMsg->received++; - - SChildTableObj *pTable = queueMsg->ahandle; - mTrace("table:%s, drop table rsp received, thandle:%p result:%s", pTable->info.tableId, queueMsg->thandle, tstrerror(rpcMsg->code)); - - if (rpcMsg->code != TSDB_CODE_SUCCESS) { - mError("table:%s, failed to drop in dnode, reason:%s", pTable->info.tableId, tstrerror(rpcMsg->code)); - mgmtSendSimpleResp(queueMsg->thandle, rpcMsg->code); - free(queueMsg); - return; - } - - SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); - if (pVgroup == NULL) { - mError("table:%s, failed to get vgroup", pTable->info.tableId); - mgmtSendSimpleResp(queueMsg->thandle, TSDB_CODE_INVALID_VGROUP_ID); - free(queueMsg); - return; - } - - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_GLOBAL, - .table = tsChildTableSdb, - .pObj = pTable - }; - int32_t code = sdbDeleteRow(&oper); - if (code != TSDB_CODE_SUCCESS) { - mError("table:%s, update ctables sdb error", pTable->info.tableId); - mgmtSendSimpleResp(queueMsg->thandle, TSDB_CODE_SDB_ERROR); - free(queueMsg); - return; - } - - if (pVgroup->numOfTables <= 0) { - mPrint("vgroup:%d, all tables is dropped, drop vgroup", pVgroup->vgId); - mgmtDropVgroup(pVgroup, NULL); - } - - mgmtSendSimpleResp(queueMsg->thandle, TSDB_CODE_SUCCESS); - free(queueMsg); -} - -static void mgmtProcessCreateTableRsp(SRpcMsg *rpcMsg) { - if (rpcMsg->handle == NULL) return; - - SQueuedMsg *queueMsg = rpcMsg->handle; - queueMsg->received++; - - SChildTableObj *pTable = queueMsg->ahandle; - mTrace("table:%s, create table rsp received, thandle:%p ahandle:%p result:%s", pTable->info.tableId, queueMsg->thandle, - rpcMsg->handle, tstrerror(rpcMsg->code)); - - if (rpcMsg->code != TSDB_CODE_SUCCESS) { - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_GLOBAL, - .table = tsChildTableSdb, - .pObj = pTable - }; - sdbDeleteRow(&oper); - - mError("table:%s, failed to create in dnode, reason:%s", pTable->info.tableId, tstrerror(rpcMsg->code)); - mgmtSendSimpleResp(queueMsg->thandle, rpcMsg->code); - } else { - mTrace("table:%s, created in dnode", pTable->info.tableId); - if (queueMsg->msgType != TSDB_MSG_TYPE_CM_CREATE_TABLE) { - SQueuedMsg *newMsg = calloc(1, sizeof(SQueuedMsg)); - newMsg->msgType = queueMsg->msgType; - newMsg->thandle = queueMsg->thandle; - newMsg->pDb = queueMsg->pDb; - newMsg->pUser = queueMsg->pUser; - newMsg->contLen = queueMsg->contLen; - newMsg->pCont = rpcMallocCont(newMsg->contLen); - memcpy(newMsg->pCont, queueMsg->pCont, newMsg->contLen); - mTrace("table:%s, start to get meta", pTable->info.tableId); - mgmtAddToShellQueue(newMsg); - } else { - mgmtSendSimpleResp(queueMsg->thandle, rpcMsg->code); - } - } - - free(queueMsg); -} - -static void mgmtProcessAlterTableRsp(SRpcMsg *rpcMsg) { - mTrace("alter table rsp received, handle:%p code:%d", rpcMsg->handle, rpcMsg->code); -} - -static void mgmtProcessMultiTableMetaMsg(SQueuedMsg *pMsg) { - SRpcConnInfo connInfo; - if (rpcGetConnInfo(pMsg->thandle, &connInfo) != 0) { - mError("conn:%p is already released while get mulit table meta", pMsg->thandle); - return; - } - - bool usePublicIp = (connInfo.serverIp == tsPublicIpInt); - SUserObj *pUser = mgmtGetUser(connInfo.user); - if (pUser == NULL) { - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_USER); - return; - } - - SCMMultiTableInfoMsg *pInfo = pMsg->pCont; - pInfo->numOfTables = htonl(pInfo->numOfTables); - - int32_t totalMallocLen = 4*1024*1024; // first malloc 4 MB, subsequent reallocation as twice - SMultiTableMeta *pMultiMeta = rpcMallocCont(totalMallocLen); - if (pMultiMeta == NULL) { - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); - return; - } - - pMultiMeta->contLen = sizeof(SMultiTableMeta); - pMultiMeta->numOfTables = 0; - - for (int t = 0; t < pInfo->numOfTables; ++t) { - char *tableId = (char*)(pInfo->tableIds + t * TSDB_TABLE_ID_LEN); - SChildTableObj *pTable = mgmtGetChildTable(tableId); - if (pTable == NULL) continue; - - SDbObj *pDb = mgmtGetDbByTableId(tableId); - if (pDb == NULL) continue; - - int availLen = totalMallocLen - pMultiMeta->contLen; - if (availLen <= sizeof(STableMetaMsg) + sizeof(SSchema) * TSDB_MAX_COLUMNS) { - //TODO realloc - //totalMallocLen *= 2; - //pMultiMeta = rpcReMalloc(pMultiMeta, totalMallocLen); - //if (pMultiMeta == NULL) { - /// rpcSendResponse(ahandle, TSDB_CODE_SERV_OUT_OF_MEMORY, NULL, 0); - // return TSDB_CODE_SERV_OUT_OF_MEMORY; - //} else { - // t--; - // continue; - //} - } - - STableMetaMsg *pMeta = (STableMetaMsg *)(pMultiMeta->metas + pMultiMeta->contLen); - int32_t code = mgmtDoGetChildTableMeta(pDb, pTable, pMeta, usePublicIp); - if (code == TSDB_CODE_SUCCESS) { - pMultiMeta->numOfTables ++; - pMultiMeta->contLen += pMeta->contLen; - } - } - - SRpcMsg rpcRsp = {0}; - rpcRsp.handle = pMsg->thandle; - rpcRsp.pCont = pMultiMeta; - rpcRsp.contLen = pMultiMeta->contLen; - rpcSendResponse(&rpcRsp); -} - -static int32_t mgmtGetShowTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { - SDbObj *pDb = mgmtGetDb(pShow->db); - if (pDb == NULL) { - return TSDB_CODE_DB_NOT_SELECTED; - } - - int32_t cols = 0; - SSchema *pSchema = pMeta->schema; - - pShow->bytes[cols] = TSDB_TABLE_NAME_LEN; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; - strcpy(pSchema[cols].name, "table name"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = 8; - pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; - strcpy(pSchema[cols].name, "create time"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = 2; - pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; - strcpy(pSchema[cols].name, "columns"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = TSDB_TABLE_NAME_LEN; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; - strcpy(pSchema[cols].name, "stable name"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pMeta->numOfColumns = htons(cols); - pShow->numOfColumns = cols; - - pShow->offset[0] = 0; - for (int32_t i = 1; i < cols; ++i) { - pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; - } - - pShow->numOfRows = pDb->numOfTables; - pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; - - return 0; -} - -static void mgmtVacuumResult(char *data, int32_t numOfCols, int32_t rows, int32_t capacity, SShowObj *pShow) { - if (rows < capacity) { - for (int32_t i = 0; i < numOfCols; ++i) { - memmove(data + pShow->offset[i] * rows, data + pShow->offset[i] * capacity, pShow->bytes[i] * rows); - } - } -} - -static int32_t mgmtRetrieveShowTables(SShowObj *pShow, char *data, int32_t rows, void *pConn) { - SDbObj *pDb = mgmtGetDb(pShow->db); - if (pDb == NULL) return 0; - - SUserObj *pUser = mgmtGetUserFromConn(pConn, NULL); - if (pUser == NULL) return 0; - - if (mgmtCheckIsMonitorDB(pDb->name, tsMonitorDbName)) { - if (strcmp(pUser->user, "root") != 0 && strcmp(pUser->user, "_root") != 0 && - strcmp(pUser->user, "monitor") != 0) { - return 0; - } - } - - int32_t numOfRows = 0; - SChildTableObj *pTable = NULL; - SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER; - - char prefix[64] = {0}; - strcpy(prefix, pDb->name); - strcat(prefix, TS_PATH_DELIMITER); - int32_t prefixLen = strlen(prefix); - - while (numOfRows < rows) { - pShow->pNode = sdbFetchRow(tsChildTableSdb, pShow->pNode, (void **) &pTable); - if (pTable == NULL) break; - - // not belong to current db - if (strncmp(pTable->info.tableId, prefix, prefixLen)) { - continue; - } - - char tableName[TSDB_TABLE_NAME_LEN] = {0}; - memset(tableName, 0, tListLen(tableName)); - - // pattern compare for meter name - mgmtExtractTableName(pTable->info.tableId, tableName); - - if (pShow->payloadLen > 0 && - patternMatch(pShow->payload, tableName, TSDB_TABLE_NAME_LEN, &info) != TSDB_PATTERN_MATCH) { - continue; - } - - int32_t cols = 0; - - char *pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - strncpy(pWrite, tableName, TSDB_TABLE_NAME_LEN); - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int64_t *) pWrite = pTable->createdTime; - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - if (pTable->info.type == TSDB_CHILD_TABLE) { - *(int16_t *)pWrite = pTable->superTable->numOfColumns; - } else { - *(int16_t *)pWrite = pTable->numOfColumns; - } - - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - if (pTable->info.type == TSDB_CHILD_TABLE) { - mgmtExtractTableName(pTable->superTableId, pWrite); - } - cols++; - - numOfRows++; - } - - pShow->numOfReads += numOfRows; - const int32_t NUM_OF_COLUMNS = 4; - - mgmtVacuumResult(data, NUM_OF_COLUMNS, numOfRows, rows, pShow); - - return numOfRows; -} - -void mgmtAlterChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable) { - int32_t code = TSDB_CODE_OPS_NOT_SUPPORT; - SCMAlterTableMsg *pAlter = pMsg->pCont;; - - if (pAlter->type == TSDB_ALTER_TABLE_UPDATE_TAG_VAL) { - code = mgmtModifyChildTableTagValueByName(pTable, pAlter->schema[0].name, pAlter->tagVal); - } else if (pAlter->type == TSDB_ALTER_TABLE_ADD_COLUMN) { - code = mgmtAddNormalTableColumn(pTable, pAlter->schema, 1); - } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_COLUMN) { - code = mgmtDropNormalTableColumnByName(pTable, pAlter->schema[0].name); - } else { - } - - mgmtSendSimpleResp(pMsg->thandle, code); -} \ No newline at end of file diff --git a/src/mnode/src/mgmtDb.c b/src/mnode/src/mgmtDb.c index 5f28c30423780be1c12b6478757248ad7fd7bcae..338eccf0611c15eb3857e70c333d98967b4cc460 100644 --- a/src/mnode/src/mgmtDb.c +++ b/src/mnode/src/mgmtDb.c @@ -22,15 +22,12 @@ #include "mnode.h" #include "mgmtAcct.h" #include "mgmtBalance.h" -#include "mgmtChildTable.h" #include "mgmtDb.h" #include "mgmtDnode.h" #include "mgmtGrant.h" #include "mgmtShell.h" #include "mgmtMnode.h" -#include "mgmtChildTable.h" #include "mgmtSdb.h" -#include "mgmtSuperTable.h" #include "mgmtTable.h" #include "mgmtUser.h" #include "mgmtVgroup.h" @@ -149,6 +146,14 @@ SDbObj *mgmtGetDb(char *db) { return (SDbObj *)sdbGetRow(tsDbSdb, db); } +void mgmtIncDbRef(SDbObj *pDb) { + return sdbIncRef(tsDbSdb, pDb); +} + +void mgmtDecDbRef(SDbObj *pDb) { + return sdbDecRef(tsDbSdb, pDb); +} + SDbObj *mgmtGetDbByTableId(char *tableId) { char db[TSDB_TABLE_ID_LEN], *pos; diff --git a/src/mnode/src/mgmtSdb.c b/src/mnode/src/mgmtSdb.c index 0b1ac3be9706ea8c7342914a4fa87e06ca7cb94c..7ab199611dc9337d17ab3cb72cdb1cc28ec89aa5 100644 --- a/src/mnode/src/mgmtSdb.c +++ b/src/mnode/src/mgmtSdb.c @@ -24,6 +24,7 @@ #include "tutil.h" #include "hashint.h" #include "hashstr.h" + #include "mgmtSdb.h" #define abs(x) (((x) < 0) ? -(x) : (x)) @@ -65,6 +66,7 @@ typedef struct { int64_t version; int64_t offset; int32_t rowSize; + int32_t refCount; void * row; } SRowMeta; @@ -322,6 +324,7 @@ static int32_t sdbInitTableByFile(SSdbTable *pTable) { .table = pTable, .pObj = pMetaRow }; + sdbDecRef(pTable, pMetaRow); (*pTable->destroyFp)(&oper); (*sdbDeleteIndexFp[pTable->keyType])(pTable->iHandle, rowHead->data); pTable->numOfRows--; @@ -338,13 +341,14 @@ static int32_t sdbInitTableByFile(SSdbTable *pTable) { .rowSize = rowHead->rowSize, .pObj = pMetaRow }; - + sdbDecRef(pTable, pMetaRow); (*pTable->destroyFp)(&oper); (*sdbDeleteIndexFp[pTable->keyType])(pTable->iHandle, rowHead->data); int32_t code = (*pTable->decodeFp)(&oper); if (code == TSDB_CODE_SUCCESS) { rowMeta.row = oper.pObj; + sdbIncRef(pTable, pMetaRow); (*sdbAddIndexFp[pTable->keyType])(pTable->iHandle, rowMeta.row, &rowMeta); sdbTrace("table:%s, version:%" PRId64 " numOfRows:%d, read updated record:%s", pTable->tableName, pTable->version, pTable->numOfRows, sdbGetkeyStr(pTable, rowHead->data)); @@ -433,6 +437,28 @@ static SRowMeta *sdbGetRowMeta(void *handle, void *key) { return pMeta; } +void sdbIncRef(void *handle, void *pRow) { + if (pRow) { + SSdbTable *pTable = handle; + SRowMeta *pMeta = (pRow - 4); + atomic_add_fetch_32(&pMeta->refCount, 1); + sdbTrace("table:%s, add ref:%d to record:%s", pTable->tableName, pMeta->refCount, sdbGetkeyStr(pTable, pRow)); + } +} + +void sdbDecRef(void *handle, void *pRow) { + if (pRow) { + SSdbTable *pTable = handle; + SRowMeta * pMeta = (pRow - 4); + int32_t refCount = atomic_sub_fetch_32(&pMeta->refCount, 1); + sdbTrace("table:%s, def ref:%d from record:%s", pTable->tableName, pMeta->refCount, sdbGetkeyStr(pTable, pRow)); + if (refCount <= 0) { + SSdbOperDesc oper = {.pObj = pRow}; + (*pTable->destroyFp)(&oper); + } + } +} + void *sdbGetRow(void *handle, void *key) { SSdbTable *pTable = (SSdbTable *)handle; SRowMeta * pMeta; @@ -441,6 +467,7 @@ void *sdbGetRow(void *handle, void *key) { pthread_mutex_lock(&pTable->mutex); pMeta = (*sdbGetIndexFp[pTable->keyType])(pTable->iHandle, key); + if (pMeta) sdbIncRef(pTable, pMeta->row); pthread_mutex_unlock(&pTable->mutex); if (pMeta == NULL) { @@ -459,6 +486,7 @@ int32_t sdbInsertRow(SSdbOperDesc *pOper) { if (sdbGetRow(pTable, pOper->pObj)) { sdbError("table:%s, failed to insert record:%s, already exist", pTable->tableName, sdbGetkeyStr(pTable, pOper->pObj)); + sdbDecRef(pTable, pOper->pObj); return TSDB_CODE_ALREADY_THERE; } @@ -526,6 +554,7 @@ int32_t sdbInsertRow(SSdbOperDesc *pOper) { rowMeta.rowSize = pOper->rowSize; rowMeta.row = pOper->pObj; (*sdbAddIndexFp[pTable->keyType])(pTable->iHandle, pOper->pObj, &rowMeta); + sdbIncRef(pTable, pOper->pObj); pTable->numOfRows++; @@ -626,8 +655,7 @@ int32_t sdbDeleteRow(SSdbOperDesc *pOper) { pthread_mutex_unlock(&pTable->mutex); (*pTable->deleteFp)(pOper); - (*pTable->destroyFp)(pOper); - + sdbDecRef(pTable, pOper->pObj); return 0; } @@ -762,6 +790,7 @@ void *sdbFetchRow(void *handle, void *pNode, void **ppRow) { if (pMeta == NULL) return NULL; *ppRow = pMeta->row; + sdbIncRef(handle, pMeta->row); return pNode; } diff --git a/src/mnode/src/mgmtShell.c b/src/mnode/src/mgmtShell.c index 5664fef5b5a4bb5b3ad8050fcf2c476437293df5..b5d45659c4694bbe67613d4302a847fe489d0c91 100644 --- a/src/mnode/src/mgmtShell.c +++ b/src/mnode/src/mgmtShell.c @@ -25,7 +25,6 @@ #include "mnode.h" #include "mgmtAcct.h" #include "mgmtBalance.h" -#include "mgmtChildTable.h" #include "mgmtDb.h" #include "mgmtDnode.h" #include "mgmtGrant.h" @@ -33,7 +32,6 @@ #include "mgmtProfile.h" #include "mgmtSdb.h" #include "mgmtShell.h" -#include "mgmtSuperTable.h" #include "mgmtTable.h" #include "mgmtUser.h" #include "mgmtVgroup.h" @@ -449,6 +447,7 @@ static bool mgmtCheckMeterMetaMsgType(void *pMsg) { mTrace("table:%s auto created task added", pInfo->tableId); } + mgmtDecTableRef(pTable); return addIntoTranQueue; } diff --git a/src/mnode/src/mgmtSuperTable.c b/src/mnode/src/mgmtSuperTable.c deleted file mode 100644 index a5e79fecf37ae9e8f7608d8016f901b0ab801241..0000000000000000000000000000000000000000 --- a/src/mnode/src/mgmtSuperTable.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#define _DEFAULT_SOURCE -#include "os.h" -#include "name.h" -#include "tsqlfunction.h" -#include "mgmtAcct.h" -#include "mgmtChildTable.h" -#include "mgmtDb.h" -#include "mgmtDClient.h" -#include "mgmtDnode.h" -#include "mgmtGrant.h" -#include "mgmtShell.h" -#include "mgmtSuperTable.h" -#include "mgmtSdb.h" -#include "mgmtTable.h" -#include "mgmtUser.h" -#include "mgmtVgroup.h" - -static void *tsSuperTableSdb; -static int32_t tsSuperTableUpdateSize; -static void mgmtProcessSuperTableVgroupMsg(SQueuedMsg *queueMsg); -static void mgmtProcessDropStableRsp(SRpcMsg *rpcMsg); -static int32_t mgmtRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows, void *pConn); -static int32_t mgmtGetShowSuperTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); - -static void mgmtDestroySuperTable(SSuperTableObj *pStable) { - tfree(pStable->schema); - tfree(pStable); -} - -static int32_t mgmtSuperTableActionDestroy(SSdbOperDesc *pOper) { - mgmtDestroySuperTable(pOper->pObj); - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtSuperTableActionInsert(SSdbOperDesc *pOper) { - SSuperTableObj *pStable = pOper->pObj; - SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); - if (pDb != NULL) { - mgmtAddSuperTableIntoDb(pDb); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtSuperTableActionDelete(SSdbOperDesc *pOper) { - SSuperTableObj *pStable = pOper->pObj; - SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); - if (pDb != NULL) { - mgmtRemoveSuperTableFromDb(pDb); - mgmtDropAllChildTablesInStable((SSuperTableObj *)pStable); - } - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtSuperTableActionUpdate(SSdbOperDesc *pOper) { - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtSuperTableActionEncode(SSdbOperDesc *pOper) { - SSuperTableObj *pStable = pOper->pObj; - assert(pOper->pObj != NULL && pOper->rowData != NULL); - - int32_t schemaSize = sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags); - - if (pOper->maxRowSize < tsSuperTableUpdateSize + schemaSize) { - return TSDB_CODE_INVALID_MSG_LEN; - } - - memcpy(pOper->rowData, pStable, tsSuperTableUpdateSize); - memcpy(pOper->rowData + tsSuperTableUpdateSize, pStable->schema, schemaSize); - pOper->rowSize = tsSuperTableUpdateSize + schemaSize; - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtSuperTableActionDecode(SSdbOperDesc *pOper) { - assert(pOper->rowData != NULL); - - SSuperTableObj *pStable = (SSuperTableObj *) calloc(1, sizeof(SSuperTableObj)); - if (pStable == NULL) return TSDB_CODE_SERV_OUT_OF_MEMORY; - - memcpy(pStable, pOper->rowData, tsSuperTableUpdateSize); - - int32_t schemaSize = sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags); - pStable->schema = malloc(schemaSize); - if (pStable->schema == NULL) { - mgmtDestroySuperTable(pStable); - return -1; - } - - memcpy(pStable->schema, pOper->rowData + tsSuperTableUpdateSize, schemaSize); - pOper->pObj = pStable; - - return TSDB_CODE_SUCCESS; -} - -int32_t mgmtInitSuperTables() { - SSuperTableObj tObj; - tsSuperTableUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; - - SSdbTableDesc tableDesc = { - .tableName = "stables", - .hashSessions = TSDB_MAX_SUPER_TABLES, - .maxRowSize = tsSuperTableUpdateSize + sizeof(SSchema) * TSDB_MAX_COLUMNS, - .keyType = SDB_KEY_TYPE_STRING, - .insertFp = mgmtSuperTableActionInsert, - .deleteFp = mgmtSuperTableActionDelete, - .updateFp = mgmtSuperTableActionUpdate, - .encodeFp = mgmtSuperTableActionEncode, - .decodeFp = mgmtSuperTableActionDecode, - .destroyFp = mgmtSuperTableActionDestroy, - }; - - tsSuperTableSdb = sdbOpenTable(&tableDesc); - if (tsSuperTableSdb == NULL) { - mError("failed to init stables data"); - return -1; - } - - mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_STABLE_VGROUP, mgmtProcessSuperTableVgroupMsg); - mgmtAddShellShowMetaHandle(TSDB_MGMT_TABLE_METRIC, mgmtGetShowSuperTableMeta); - mgmtAddShellShowRetrieveHandle(TSDB_MGMT_TABLE_METRIC, mgmtRetrieveShowSuperTables); - mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_DROP_STABLE_RSP, mgmtProcessDropStableRsp); - - mTrace("stables is initialized"); - return 0; -} - -void mgmtCleanUpSuperTables() { - sdbCloseTable(tsSuperTableSdb); -} - -void mgmtCreateSuperTable(SQueuedMsg *pMsg) { - SCMCreateTableMsg *pCreate = pMsg->pCont; - SSuperTableObj *pStable = (SSuperTableObj *)calloc(1, sizeof(SSuperTableObj)); - if (pStable == NULL) { - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); - return; - } - - strcpy(pStable->info.tableId, pCreate->tableId); - pStable->info.type = TSDB_SUPER_TABLE; - pStable->createdTime = taosGetTimestampMs(); - pStable->uid = (((uint64_t) pStable->createdTime) << 16) + (sdbGetVersion() & ((1ul << 16) - 1ul)); - pStable->sversion = 0; - pStable->numOfColumns = htons(pCreate->numOfColumns); - pStable->numOfTags = htons(pCreate->numOfTags); - - int32_t numOfCols = pCreate->numOfColumns + pCreate->numOfTags; - int32_t schemaSize = numOfCols * sizeof(SSchema); - pStable->schema = (SSchema *)calloc(1, schemaSize); - if (pStable->schema == NULL) { - free(pStable); - mError("stable:%s, no schema input", pCreate->tableId); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); - return; - } - memcpy(pStable->schema, pCreate->schema, numOfCols * sizeof(SSchema)); - - pStable->nextColId = 0; - for (int32_t col = 0; col < numOfCols; col++) { - SSchema *tschema = pStable->schema; - tschema[col].colId = pStable->nextColId++; - tschema[col].bytes = htons(tschema[col].bytes); - } - - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable, - .rowSize = sizeof(SSuperTableObj) + schemaSize - }; - - int32_t code = sdbInsertRow(&oper); - if (code != TSDB_CODE_SUCCESS) { - mgmtDestroySuperTable(pStable); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SDB_ERROR); - } else { - mLPrint("stable:%s, is created, tags:%d cols:%d", pStable->info.tableId, pStable->numOfTags, pStable->numOfColumns); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SUCCESS); - } -} - -void mgmtDropSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pStable) { - if (pStable->numOfTables != 0) { - mError("stable:%s, numOfTables:%d not 0", pStable->info.tableId, pStable->numOfTables); - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_OTHERS); - } else { - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_GLOBAL, - .table = tsSuperTableSdb, - .pObj = pStable - }; - int32_t code = sdbDeleteRow(&oper); - mLPrint("stable:%s, is dropped from sdb, result:%s", pStable->info.tableId, tstrerror(code)); - mgmtSendSimpleResp(pMsg->thandle, code); - } -} - -void* mgmtGetSuperTable(char *tableId) { - return sdbGetRow(tsSuperTableSdb, tableId); -} - -static void *mgmtGetSuperTableVgroup(SSuperTableObj *pStable) { - SCMSTableVgroupRspMsg *rsp = rpcMallocCont(sizeof(SCMSTableVgroupRspMsg) + sizeof(uint32_t) * mgmtGetDnodesNum()); - rsp->numOfDnodes = htonl(1); - rsp->dnodeIps[0] = htonl(inet_addr(tsPrivateIp)); - return rsp; -} - -static int32_t mgmtFindSuperTableTagIndex(SSuperTableObj *pStable, const char *tagName) { - for (int32_t i = 0; i < pStable->numOfTags; i++) { - SSchema *schema = (SSchema *)(pStable->schema + (pStable->numOfColumns + i) * sizeof(SSchema)); - if (strcasecmp(tagName, schema->name) == 0) { - return i; - } - } - - return -1; -} - -static int32_t mgmtAddSuperTableTag(SSuperTableObj *pStable, SSchema schema[], int32_t ntags) { - if (pStable->numOfTags + ntags > TSDB_MAX_TAGS) { - return TSDB_CODE_APP_ERROR; - } - - // check if schemas have the same name - for (int32_t i = 1; i < ntags; i++) { - for (int32_t j = 0; j < i; j++) { - if (strcasecmp(schema[i].name, schema[j].name) == 0) { - return TSDB_CODE_APP_ERROR; - } - } - } - - SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); - if (pDb == NULL) { - mError("meter: %s not belongs to any database", pStable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("DB: %s not belongs to andy account", pDb->name); - return TSDB_CODE_APP_ERROR; - } - - int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); - pStable->schema = realloc(pStable->schema, schemaSize + sizeof(SSchema) * ntags); - - memmove(pStable->schema + sizeof(SSchema) * (pStable->numOfColumns + ntags), - pStable->schema + sizeof(SSchema) * pStable->numOfColumns, sizeof(SSchema) * pStable->numOfTags); - memcpy(pStable->schema + sizeof(SSchema) * pStable->numOfColumns, schema, sizeof(SSchema) * ntags); - - SSchema *tschema = (SSchema *) (pStable->schema + sizeof(SSchema) * pStable->numOfColumns); - for (int32_t i = 0; i < ntags; i++) { - tschema[i].colId = pStable->nextColId++; - } - - pStable->numOfColumns += ntags; - pStable->sversion++; - - pAcct->acctInfo.numOfTimeSeries += (ntags * pStable->numOfTables); - // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); - - mTrace("Succeed to add tag column %s to table %s", schema[0].name, pStable->info.tableId); - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtDropSuperTableTag(SSuperTableObj *pStable, char *tagName) { - int32_t col = mgmtFindSuperTableTagIndex(pStable, tagName); - if (col <= 0 || col >= pStable->numOfTags) { - return TSDB_CODE_APP_ERROR; - } - - SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); - if (pDb == NULL) { - mError("table: %s not belongs to any database", pStable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("DB: %s not belongs to any account", pDb->name); - return TSDB_CODE_APP_ERROR; - } - - memmove(pStable->schema + sizeof(SSchema) * col, pStable->schema + sizeof(SSchema) * (col + 1), - sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags - col - 1)); - - pStable->numOfTags--; - pStable->sversion++; - - int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); - pStable->schema = realloc(pStable->schema, schemaSize); - - // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtModifySuperTableTagNameByName(SSuperTableObj *pStable, char *oldTagName, char *newTagName) { - int32_t col = mgmtFindSuperTableTagIndex(pStable, oldTagName); - if (col < 0) { - // Tag name does not exist - mError("Failed to modify table %s tag column, oname: %s, nname: %s", pStable->info.tableId, oldTagName, newTagName); - return TSDB_CODE_INVALID_MSG_TYPE; - } - - // int32_t rowSize = 0; - uint32_t len = strlen(newTagName); - - if (col >= pStable->numOfTags || len >= TSDB_COL_NAME_LEN || mgmtFindSuperTableTagIndex(pStable, newTagName) >= 0) { - return TSDB_CODE_APP_ERROR; - } - - // update - SSchema *schema = (SSchema *) (pStable->schema + (pStable->numOfColumns + col) * sizeof(SSchema)); - strncpy(schema->name, newTagName, TSDB_COL_NAME_LEN); - - // Encode string - int32_t size = 1 + sizeof(SSuperTableObj) + TSDB_MAX_BYTES_PER_ROW; - char *msg = (char *) malloc(size); - if (msg == NULL) return TSDB_CODE_APP_ERROR; - memset(msg, 0, size); - - // mgmtSuperTableActionEncode(pStable, msg, size, &rowSize); - - int32_t ret = 0; - // int32_t ret = sdbUpdateRow(tsSuperTableSdb, msg, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); - tfree(msg); - - if (ret < 0) { - mError("Failed to modify table %s tag column", pStable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - mTrace("Succeed to modify table %s tag column", pStable->info.tableId); - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtFindSuperTableColumnIndex(SSuperTableObj *pStable, char *colName) { - SSchema *schema = (SSchema *) pStable->schema; - for (int32_t i = 0; i < pStable->numOfColumns; i++) { - if (strcasecmp(schema[i].name, colName) == 0) { - return i; - } - } - - return -1; -} - -static int32_t mgmtAddSuperTableColumn(SSuperTableObj *pStable, SSchema schema[], int32_t ncols) { - if (ncols <= 0) { - return TSDB_CODE_APP_ERROR; - } - - for (int32_t i = 0; i < ncols; i++) { - if (mgmtFindSuperTableColumnIndex(pStable, schema[i].name) > 0) { - return TSDB_CODE_APP_ERROR; - } - } - - SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); - if (pDb == NULL) { - mError("meter: %s not belongs to any database", pStable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("DB: %s not belongs to andy account", pDb->name); - return TSDB_CODE_APP_ERROR; - } - - int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); - pStable->schema = realloc(pStable->schema, schemaSize + sizeof(SSchema) * ncols); - - memmove(pStable->schema + sizeof(SSchema) * (pStable->numOfColumns + ncols), - pStable->schema + sizeof(SSchema) * pStable->numOfColumns, sizeof(SSchema) * pStable->numOfTags); - memcpy(pStable->schema + sizeof(SSchema) * pStable->numOfColumns, schema, sizeof(SSchema) * ncols); - - SSchema *tschema = (SSchema *) (pStable->schema + sizeof(SSchema) * pStable->numOfColumns); - for (int32_t i = 0; i < ncols; i++) { - tschema[i].colId = pStable->nextColId++; - } - - pStable->numOfColumns += ncols; - pStable->sversion++; - - pAcct->acctInfo.numOfTimeSeries += (ncols * pStable->numOfTables); - // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtDropSuperTableColumnByName(SSuperTableObj *pStable, char *colName) { - int32_t col = mgmtFindSuperTableColumnIndex(pStable, colName); - if (col < 0) { - return TSDB_CODE_APP_ERROR; - } - - SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); - if (pDb == NULL) { - mError("table: %s not belongs to any database", pStable->info.tableId); - return TSDB_CODE_APP_ERROR; - } - - SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); - if (pAcct == NULL) { - mError("DB: %s not belongs to any account", pDb->name); - return TSDB_CODE_APP_ERROR; - } - - memmove(pStable->schema + sizeof(SSchema) * col, pStable->schema + sizeof(SSchema) * (col + 1), - sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags - col - 1)); - - pStable->numOfColumns--; - pStable->sversion++; - - int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); - pStable->schema = realloc(pStable->schema, schemaSize); - - pAcct->acctInfo.numOfTimeSeries -= (pStable->numOfTables); - // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); - - return TSDB_CODE_SUCCESS; -} - -static int32_t mgmtGetShowSuperTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { - SDbObj *pDb = mgmtGetDb(pShow->db); - if (pDb == NULL) { - return TSDB_CODE_DB_NOT_SELECTED; - } - - int32_t cols = 0; - SSchema *pSchema = pMeta->schema; - - pShow->bytes[cols] = TSDB_TABLE_NAME_LEN; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; - strcpy(pSchema[cols].name, "name"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = 8; - pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; - strcpy(pSchema[cols].name, "create_time"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = 2; - pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; - strcpy(pSchema[cols].name, "columns"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = 2; - pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; - strcpy(pSchema[cols].name, "tags"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pShow->bytes[cols] = 4; - pSchema[cols].type = TSDB_DATA_TYPE_INT; - strcpy(pSchema[cols].name, "tables"); - pSchema[cols].bytes = htons(pShow->bytes[cols]); - cols++; - - pMeta->numOfColumns = htons(cols); - pShow->numOfColumns = cols; - - pShow->offset[0] = 0; - for (int32_t i = 1; i < cols; ++i) pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; - - pShow->numOfRows = pDb->numOfSuperTables; - pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; - - return 0; -} - -int32_t mgmtRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows, void *pConn) { - int32_t numOfRows = 0; - char * pWrite; - int32_t cols = 0; - SSuperTableObj *pTable = NULL; - char prefix[20] = {0}; - int32_t prefixLen; - - SDbObj *pDb = mgmtGetDb(pShow->db); - if (pDb == NULL) return 0; - - SUserObj *pUser = mgmtGetUserFromConn(pConn, NULL); - - if (mgmtCheckIsMonitorDB(pDb->name, tsMonitorDbName)) { - if (strcmp(pUser->user, "root") != 0 && strcmp(pUser->user, "_root") != 0 && strcmp(pUser->user, "monitor") != 0 ) { - return 0; - } - } - - strcpy(prefix, pDb->name); - strcat(prefix, TS_PATH_DELIMITER); - prefixLen = strlen(prefix); - - SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER; - char stableName[TSDB_TABLE_NAME_LEN] = {0}; - - while (numOfRows < rows) { - pShow->pNode = sdbFetchRow(tsSuperTableSdb, pShow->pNode, (void **) &pTable); - if (pTable == NULL) break; - if (strncmp(pTable->info.tableId, prefix, prefixLen)) { - continue; - } - - memset(stableName, 0, tListLen(stableName)); - mgmtExtractTableName(pTable->info.tableId, stableName); - - if (pShow->payloadLen > 0 && - patternMatch(pShow->payload, stableName, TSDB_TABLE_NAME_LEN, &info) != TSDB_PATTERN_MATCH) - continue; - - cols = 0; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - strncpy(pWrite, stableName, TSDB_TABLE_NAME_LEN); - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int64_t *)pWrite = pTable->createdTime; - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int16_t *)pWrite = pTable->numOfColumns; - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int16_t *)pWrite = pTable->numOfTags; - cols++; - - pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int32_t *)pWrite = pTable->numOfTables; - cols++; - - numOfRows++; - } - - pShow->numOfReads += numOfRows; - return numOfRows; -} - -void mgmtDropAllSuperTables(SDbObj *pDropDb) { - void *pNode = NULL; - void *pLastNode = NULL; - int32_t numOfTables = 0; - int32_t dbNameLen = strlen(pDropDb->name); - SSuperTableObj *pTable = NULL; - - while (1) { - pNode = sdbFetchRow(tsSuperTableSdb, pNode, (void **)&pTable); - if (pTable == NULL) { - break; - } - - if (strncmp(pDropDb->name, pTable->info.tableId, dbNameLen) == 0) { - SSdbOperDesc oper = { - .type = SDB_OPER_TYPE_LOCAL, - .table = tsSuperTableSdb, - .pObj = pTable, - }; - sdbDeleteRow(&oper); - pNode = pLastNode; - numOfTables ++; - continue; - } - } - - mTrace("db:%s, all super tables:%d is dropped from sdb", pDropDb->name, numOfTables); -} - -int32_t mgmtSetSchemaFromSuperTable(SSchema *pSchema, SSuperTableObj *pTable) { - int32_t numOfCols = pTable->numOfColumns + pTable->numOfTags; - for (int32_t i = 0; i < numOfCols; ++i) { - strcpy(pSchema->name, pTable->schema[i].name); - pSchema->type = pTable->schema[i].type; - pSchema->bytes = htons(pTable->schema[i].bytes); - pSchema->colId = htons(pTable->schema[i].colId); - pSchema++; - } - - return (pTable->numOfColumns + pTable->numOfTags) * sizeof(SSchema); -} - -void mgmtGetSuperTableMeta(SQueuedMsg *pMsg, SSuperTableObj *pTable) { - SDbObj *pDb = pMsg->pDb; - - STableMetaMsg *pMeta = rpcMallocCont(sizeof(STableMetaMsg) + sizeof(SSchema) * TSDB_MAX_COLUMNS); - pMeta->uid = htobe64(pTable->uid); - pMeta->sversion = htons(pTable->sversion); - pMeta->precision = pDb->cfg.precision; - pMeta->numOfTags = (uint8_t)pTable->numOfTags; - pMeta->numOfColumns = htons((int16_t)pTable->numOfColumns); - pMeta->tableType = pTable->info.type; - pMeta->contLen = sizeof(STableMetaMsg) + mgmtSetSchemaFromSuperTable(pMeta->schema, pTable); - strcpy(pMeta->tableId, pTable->info.tableId); - - SRpcMsg rpcRsp = { - .handle = pMsg->thandle, - .pCont = pMeta, - .contLen = pMeta->contLen, - }; - pMeta->contLen = htons(pMeta->contLen); - rpcSendResponse(&rpcRsp); - - mTrace("stable:%%s, uid:%" PRIu64 " table meta is retrieved", pTable->info.tableId, pTable->uid); -} - -static void mgmtProcessSuperTableVgroupMsg(SQueuedMsg *pMsg) { - SCMSTableVgroupMsg *pInfo = pMsg->pCont; - STableInfo *pTable = mgmtGetSuperTable(pInfo->tableId); - if (pTable == NULL) { - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); - return; - } - - SCMSTableVgroupRspMsg *pRsp = mgmtGetSuperTableVgroup((SSuperTableObj *) pTable); - if (pRsp != NULL) { - int32_t msgLen = sizeof(SSuperTableObj) + htonl(pRsp->numOfDnodes) * sizeof(int32_t); - SRpcMsg rpcRsp = {0}; - rpcRsp.handle = pMsg->thandle; - rpcRsp.pCont = pRsp; - rpcRsp.contLen = msgLen; - rpcSendResponse(&rpcRsp); - } else { - mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); - } -} - -void mgmtAlterSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pTable) { - int32_t code = TSDB_CODE_OPS_NOT_SUPPORT; - SCMAlterTableMsg *pAlter = pMsg->pCont; - - if (pAlter->type == TSDB_ALTER_TABLE_ADD_TAG_COLUMN) { - code = mgmtAddSuperTableTag((SSuperTableObj *) pTable, pAlter->schema, 1); - } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_TAG_COLUMN) { - code = mgmtDropSuperTableTag((SSuperTableObj *) pTable, pAlter->schema[0].name); - } else if (pAlter->type == TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN) { - code = mgmtModifySuperTableTagNameByName((SSuperTableObj *) pTable, pAlter->schema[0].name, pAlter->schema[1].name); - } else if (pAlter->type == TSDB_ALTER_TABLE_ADD_COLUMN) { - code = mgmtAddSuperTableColumn((SSuperTableObj *) pTable, pAlter->schema, 1); - } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_COLUMN) { - code = mgmtDropSuperTableColumnByName((SSuperTableObj *) pTable, pAlter->schema[0].name); - } else {} - - mgmtSendSimpleResp(pMsg->thandle, code); -} - -static void mgmtProcessDropStableRsp(SRpcMsg *rpcMsg) { - mTrace("drop stable rsp received, handle:%p code:%d", rpcMsg->handle, rpcMsg->code); -} \ No newline at end of file diff --git a/src/mnode/src/mgmtTable.c b/src/mnode/src/mgmtTable.c index 5169f4a8174ae6d88d9a4741fcdfa8f8ac01d629..eff42ebdb22e5c78492450563281391318212eaf 100644 --- a/src/mnode/src/mgmtTable.c +++ b/src/mnode/src/mgmtTable.c @@ -15,8 +15,23 @@ #define _DEFAULT_SOURCE #include "os.h" +#include "taosmsg.h" +#include "tscompression.h" +#include "tskiplist.h" +#include "ttime.h" +#include "tstatus.h" +#include "tutil.h" +#include "qast.h" +#include "qextbuffer.h" +#include "taoserror.h" +#include "taosmsg.h" +#include "tscompression.h" +#include "tskiplist.h" +#include "tsqlfunction.h" +#include "tstatus.h" +#include "ttime.h" +#include "name.h" #include "mgmtAcct.h" -#include "mgmtChildTable.h" #include "mgmtDClient.h" #include "mgmtDb.h" #include "mgmtDnode.h" @@ -26,15 +41,399 @@ #include "mgmtProfile.h" #include "mgmtSdb.h" #include "mgmtShell.h" -#include "mgmtSuperTable.h" #include "mgmtTable.h" #include "mgmtUser.h" +#include "mgmtVgroup.h" + +static void * tsChildTableSdb; +static void * tsSuperTableSdb; +static int32_t tsChildTableUpdateSize; +static int32_t tsSuperTableUpdateSize; + +static void * mgmtGetChildTable(char *tableId); +static void * mgmtGetSuperTable(char *tableId); + +void mgmtCreateChildTable(SQueuedMsg *pMsg); +void mgmtDropChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable); +void mgmtGetChildTableMeta(SQueuedMsg *pMsg, SChildTableObj *pTable); +void mgmtAlterChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable); +void mgmtDropAllChildTables(SDbObj *pDropDb); +void mgmtDropAllChildTablesInStable(SSuperTableObj *pStable); + +void mgmtCreateSuperTable(SQueuedMsg *pMsg); +void mgmtDropSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pTable); +void mgmtGetSuperTableMeta(SQueuedMsg *pMsg, SSuperTableObj *pTable); +void mgmtAlterSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pTable); +void mgmtDropAllSuperTables(SDbObj *pDropDb); +int32_t mgmtSetSchemaFromSuperTable(SSchema *pSchema, SSuperTableObj *pTable); + +static void mgmtProcessSuperTableVgroupMsg(SQueuedMsg *queueMsg); +static void mgmtProcessDropStableRsp(SRpcMsg *rpcMsg); +static int32_t mgmtRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows, void *pConn); +static int32_t mgmtGetShowSuperTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); + +static void mgmtProcessMultiTableMetaMsg(SQueuedMsg *queueMsg); +static void mgmtProcessCreateTableRsp(SRpcMsg *rpcMsg); +static void mgmtProcessAlterTableRsp(SRpcMsg *rpcMsg); +static void mgmtProcessDropTableRsp(SRpcMsg *rpcMsg); +static void mgmtProcessTableCfgMsg(SRpcMsg *rpcMsg); +static int32_t mgmtGetShowTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); +static int32_t mgmtRetrieveShowTables(SShowObj *pShow, char *data, int32_t rows, void *pConn); static void mgmtProcessCreateTableMsg(SQueuedMsg *queueMsg); static void mgmtProcessDropTableMsg(SQueuedMsg *queueMsg); static void mgmtProcessAlterTableMsg(SQueuedMsg *queueMsg); static void mgmtProcessTableMetaMsg(SQueuedMsg *queueMsg); +static void mgmtDestroyChildTable(SChildTableObj *pTable) { + tfree(pTable->schema); + tfree(pTable->sql); + tfree(pTable); +} + +static int32_t mgmtChildTableActionDestroy(SSdbOperDesc *pOper) { + mgmtDestroyChildTable(pOper->pObj); + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtChildTableActionInsert(SSdbOperDesc *pOper) { + SChildTableObj *pTable = pOper->pObj; + + SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); + if (pVgroup == NULL) { + mError("ctable:%s, not in vgroup:%d", pTable->info.tableId, pTable->vgId); + return TSDB_CODE_INVALID_VGROUP_ID; + } + + SDbObj *pDb = mgmtGetDb(pVgroup->dbName); + if (pDb == NULL) { + mError("ctable:%s, vgroup:%d not in db:%s", pTable->info.tableId, pVgroup->vgId, pVgroup->dbName); + return TSDB_CODE_INVALID_DB; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("ctable:%s, account:%s not exists", pTable->info.tableId, pDb->cfg.acct); + return TSDB_CODE_INVALID_ACCT; + } + + if (pTable->info.type == TSDB_CHILD_TABLE) { + pTable->superTable = mgmtGetSuperTable(pTable->superTableId); + pTable->superTable->numOfTables++; + grantAdd(TSDB_GRANT_TIMESERIES, pTable->superTable->numOfColumns - 1); + pAcct->acctInfo.numOfTimeSeries += (pTable->superTable->numOfColumns - 1); + } else { + grantAdd(TSDB_GRANT_TIMESERIES, pTable->numOfColumns - 1); + pAcct->acctInfo.numOfTimeSeries += (pTable->numOfColumns - 1); + } + mgmtAddTableIntoDb(pDb); + mgmtAddTableIntoVgroup(pVgroup, pTable); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtChildTableActionDelete(SSdbOperDesc *pOper) { + SChildTableObj *pTable = pOper->pObj; + if (pTable->vgId == 0) { + return TSDB_CODE_INVALID_VGROUP_ID; + } + + SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); + if (pVgroup == NULL) { + return TSDB_CODE_INVALID_VGROUP_ID; + } + + SDbObj *pDb = mgmtGetDb(pVgroup->dbName); + if (pDb == NULL) { + mError("ctable:%s, vgroup:%d not in DB:%s", pTable->info.tableId, pVgroup->vgId, pVgroup->dbName); + return TSDB_CODE_INVALID_DB; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("ctable:%s, account:%s not exists", pTable->info.tableId, pDb->cfg.acct); + return TSDB_CODE_INVALID_ACCT; + } + + if (pTable->info.type == TSDB_CHILD_TABLE) { + grantRestore(TSDB_GRANT_TIMESERIES, pTable->superTable->numOfColumns - 1); + pAcct->acctInfo.numOfTimeSeries -= (pTable->superTable->numOfColumns - 1); + pTable->superTable->numOfTables--; + } else { + grantRestore(TSDB_GRANT_TIMESERIES, pTable->numOfColumns - 1); + pAcct->acctInfo.numOfTimeSeries -= (pTable->numOfColumns - 1); + } + mgmtRemoveTableFromDb(pDb); + mgmtRemoveTableFromVgroup(pVgroup, pTable); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtChildTableActionUpdate(SSdbOperDesc *pOper) { + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtChildTableActionEncode(SSdbOperDesc *pOper) { + SChildTableObj *pTable = pOper->pObj; + assert(pTable != NULL && pOper->rowData != NULL); + + if (pTable->info.type == TSDB_CHILD_TABLE) { + memcpy(pOper->rowData, pTable, tsChildTableUpdateSize); + pOper->rowSize = tsChildTableUpdateSize; + } else { + int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); + if (pOper->maxRowSize < tsChildTableUpdateSize + schemaSize) { + return TSDB_CODE_INVALID_MSG_LEN; + } + memcpy(pOper->rowData, pTable, tsChildTableUpdateSize); + memcpy(pOper->rowData + tsChildTableUpdateSize, pTable->schema, schemaSize); + memcpy(pOper->rowData + tsChildTableUpdateSize + schemaSize, pTable->sql, pTable->sqlLen); + pOper->rowSize = tsChildTableUpdateSize + schemaSize + pTable->sqlLen; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtChildTableActionDecode(SSdbOperDesc *pOper) { + assert(pOper->rowData != NULL); + SChildTableObj *pTable = calloc(1, sizeof(SChildTableObj)); + if (pTable == NULL) { + return TSDB_CODE_SERV_OUT_OF_MEMORY; + } + + memcpy(pTable, pOper->rowData, tsChildTableUpdateSize); + + if (pTable->info.type != TSDB_CHILD_TABLE) { + int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); + pTable->schema = (SSchema *)malloc(schemaSize); + if (pTable->schema == NULL) { + mgmtDestroyChildTable(pTable); + return TSDB_CODE_SERV_OUT_OF_MEMORY; + } + memcpy(pTable->schema, pOper->rowData + tsChildTableUpdateSize, schemaSize); + + pTable->sql = (char *)malloc(pTable->sqlLen); + if (pTable->sql == NULL) { + mgmtDestroyChildTable(pTable); + return TSDB_CODE_SERV_OUT_OF_MEMORY; + } + memcpy(pTable->sql, pOper->rowData + tsChildTableUpdateSize + schemaSize, pTable->sqlLen); + } + + pOper->pObj = pTable; + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtInitChildTables() { + void *pNode = NULL; + void *pLastNode = NULL; + SChildTableObj *pTable = NULL; + + SChildTableObj tObj; + tsChildTableUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; + + SSdbTableDesc tableDesc = { + .tableName = "ctables", + .hashSessions = tsMaxTables, + .maxRowSize = sizeof(SChildTableObj) + sizeof(SSchema) * TSDB_MAX_COLUMNS, + .keyType = SDB_KEY_TYPE_STRING, + .insertFp = mgmtChildTableActionInsert, + .deleteFp = mgmtChildTableActionDelete, + .updateFp = mgmtChildTableActionUpdate, + .encodeFp = mgmtChildTableActionEncode, + .decodeFp = mgmtChildTableActionDecode, + .destroyFp = mgmtChildTableActionDestroy, + }; + + tsChildTableSdb = sdbOpenTable(&tableDesc); + if (tsChildTableSdb == NULL) { + mError("failed to init child table data"); + return -1; + } + + pNode = NULL; + while (1) { + pLastNode = pNode; + pNode = sdbFetchRow(tsChildTableSdb, pNode, (void **)&pTable); + if (pTable == NULL) break; + + SDbObj *pDb = mgmtGetDbByTableId(pTable->info.tableId); + if (pDb == NULL) { + mError("ctable:%s, failed to get db, discard it", pTable->info.tableId); + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_LOCAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + sdbDeleteRow(&desc); + pNode = pLastNode; + continue; + } + + SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); + if (pVgroup == NULL) { + mError("ctable:%s, failed to get vgroup:%d sid:%d, discard it", pTable->info.tableId, pTable->vgId, pTable->sid); + pTable->vgId = 0; + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_LOCAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + sdbDeleteRow(&desc); + pNode = pLastNode; + continue; + } + + if (strcmp(pVgroup->dbName, pDb->name) != 0) { + mError("ctable:%s, db:%s not match with vgroup:%d db:%s sid:%d, discard it", + pTable->info.tableId, pDb->name, pTable->vgId, pVgroup->dbName, pTable->sid); + pTable->vgId = 0; + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_LOCAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + sdbDeleteRow(&desc); + pNode = pLastNode; + continue; + } + + if (pVgroup->tableList == NULL) { + mError("ctable:%s, vgroup:%d tableList is null", pTable->info.tableId, pTable->vgId); + pTable->vgId = 0; + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_LOCAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + sdbDeleteRow(&desc); + pNode = pLastNode; + continue; + } + + if (pTable->info.type == TSDB_CHILD_TABLE) { + SSuperTableObj *pSuperTable = mgmtGetSuperTable(pTable->superTableId); + if (pSuperTable == NULL) { + mError("ctable:%s, stable:%s not exist", pTable->info.tableId, pTable->superTableId); + pTable->vgId = 0; + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_LOCAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + sdbDeleteRow(&desc); + pNode = pLastNode; + continue; + } + } + } + + mTrace("child table is initialized"); + return 0; +} + +static void mgmtCleanUpChildTables() { + sdbCloseTable(tsChildTableSdb); +} + +static void mgmtDestroySuperTable(SSuperTableObj *pStable) { + tfree(pStable->schema); + tfree(pStable); +} + +static int32_t mgmtSuperTableActionDestroy(SSdbOperDesc *pOper) { + mgmtDestroySuperTable(pOper->pObj); + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtSuperTableActionInsert(SSdbOperDesc *pOper) { + SSuperTableObj *pStable = pOper->pObj; + SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); + if (pDb != NULL) { + mgmtAddSuperTableIntoDb(pDb); + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtSuperTableActionDelete(SSdbOperDesc *pOper) { + SSuperTableObj *pStable = pOper->pObj; + SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); + if (pDb != NULL) { + mgmtRemoveSuperTableFromDb(pDb); + mgmtDropAllChildTablesInStable((SSuperTableObj *)pStable); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtSuperTableActionUpdate(SSdbOperDesc *pOper) { + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtSuperTableActionEncode(SSdbOperDesc *pOper) { + SSuperTableObj *pStable = pOper->pObj; + assert(pOper->pObj != NULL && pOper->rowData != NULL); + + int32_t schemaSize = sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags); + + if (pOper->maxRowSize < tsSuperTableUpdateSize + schemaSize) { + return TSDB_CODE_INVALID_MSG_LEN; + } + + memcpy(pOper->rowData, pStable, tsSuperTableUpdateSize); + memcpy(pOper->rowData + tsSuperTableUpdateSize, pStable->schema, schemaSize); + pOper->rowSize = tsSuperTableUpdateSize + schemaSize; + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtSuperTableActionDecode(SSdbOperDesc *pOper) { + assert(pOper->rowData != NULL); + + SSuperTableObj *pStable = (SSuperTableObj *) calloc(1, sizeof(SSuperTableObj)); + if (pStable == NULL) return TSDB_CODE_SERV_OUT_OF_MEMORY; + + memcpy(pStable, pOper->rowData, tsSuperTableUpdateSize); + + int32_t schemaSize = sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags); + pStable->schema = malloc(schemaSize); + if (pStable->schema == NULL) { + mgmtDestroySuperTable(pStable); + return -1; + } + + memcpy(pStable->schema, pOper->rowData + tsSuperTableUpdateSize, schemaSize); + pOper->pObj = pStable; + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtInitSuperTables() { + SSuperTableObj tObj; + tsSuperTableUpdateSize = (int8_t *)tObj.updateEnd - (int8_t *)&tObj; + + SSdbTableDesc tableDesc = { + .tableName = "stables", + .hashSessions = TSDB_MAX_SUPER_TABLES, + .maxRowSize = tsSuperTableUpdateSize + sizeof(SSchema) * TSDB_MAX_COLUMNS, + .keyType = SDB_KEY_TYPE_STRING, + .insertFp = mgmtSuperTableActionInsert, + .deleteFp = mgmtSuperTableActionDelete, + .updateFp = mgmtSuperTableActionUpdate, + .encodeFp = mgmtSuperTableActionEncode, + .decodeFp = mgmtSuperTableActionDecode, + .destroyFp = mgmtSuperTableActionDestroy, + }; + + tsSuperTableSdb = sdbOpenTable(&tableDesc); + if (tsSuperTableSdb == NULL) { + mError("failed to init stables data"); + return -1; + } + + mTrace("stables is initialized"); + return 0; +} + +static void mgmtCleanUpSuperTables() { + sdbCloseTable(tsSuperTableSdb); +} + int32_t mgmtInitTables() { int32_t code = mgmtInitSuperTables(); if (code != TSDB_CODE_SUCCESS) { @@ -46,6 +445,19 @@ int32_t mgmtInitTables() { return code; } + mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_TABLES_META, mgmtProcessMultiTableMetaMsg); + mgmtAddShellShowMetaHandle(TSDB_MGMT_TABLE_TABLE, mgmtGetShowTableMeta); + mgmtAddShellShowRetrieveHandle(TSDB_MGMT_TABLE_TABLE, mgmtRetrieveShowTables); + mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_CREATE_TABLE_RSP, mgmtProcessCreateTableRsp); + mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_DROP_TABLE_RSP, mgmtProcessDropTableRsp); + mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_ALTER_TABLE_RSP, mgmtProcessAlterTableRsp); + mgmtAddDServerMsgHandle(TSDB_MSG_TYPE_DM_CONFIG_TABLE, mgmtProcessTableCfgMsg); + + mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_STABLE_VGROUP, mgmtProcessSuperTableVgroupMsg); + mgmtAddShellShowMetaHandle(TSDB_MGMT_TABLE_METRIC, mgmtGetShowSuperTableMeta); + mgmtAddShellShowRetrieveHandle(TSDB_MGMT_TABLE_METRIC, mgmtRetrieveShowSuperTables); + mgmtAddDClientRspHandle(TSDB_MSG_TYPE_MD_DROP_STABLE_RSP, mgmtProcessDropStableRsp); + mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_CREATE_TABLE, mgmtProcessCreateTableMsg); mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_DROP_TABLE, mgmtProcessDropTableMsg); mgmtAddShellMsgHandle(TSDB_MSG_TYPE_CM_ALTER_TABLE, mgmtProcessAlterTableMsg); @@ -54,13 +466,21 @@ int32_t mgmtInitTables() { return TSDB_CODE_SUCCESS; } +static void * mgmtGetChildTable(char *tableId) { + return sdbGetRow(tsChildTableSdb, tableId); +} + +static void * mgmtGetSuperTable(char *tableId) { + return sdbGetRow(tsSuperTableSdb, tableId); +} + STableInfo *mgmtGetTable(char *tableId) { - STableInfo *tableInfo = mgmtGetSuperTable(tableId); + STableInfo *tableInfo = sdbGetRow(tsSuperTableSdb, tableId); if (tableInfo != NULL) { return tableInfo; } - tableInfo = mgmtGetChildTable(tableId); + tableInfo = sdbGetRow(tsChildTableSdb, tableId); if (tableInfo != NULL) { return tableInfo; } @@ -68,6 +488,22 @@ STableInfo *mgmtGetTable(char *tableId) { return NULL; } +void mgmtIncTableRef(STableInfo *pTable) { + if (pTable->type == TSDB_SUPER_TABLE) { + sdbIncRef(tsSuperTableSdb, pTable); + } else { + sdbIncRef(tsChildTableSdb, pTable); + } +} + +void mgmtDecTableRef(STableInfo *pTable) { + if (pTable->type == TSDB_SUPER_TABLE) { + sdbDecRef(tsSuperTableSdb, pTable); + } else { + sdbDecRef(tsChildTableSdb, pTable); + } +} + void mgmtCleanUpTables() { mgmtCleanUpChildTables(); mgmtCleanUpSuperTables(); @@ -110,10 +546,12 @@ static void mgmtProcessCreateTableMsg(SQueuedMsg *pMsg) { if (pCreate->igExists) { mTrace("table:%s is already exist", pCreate->tableId); mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SUCCESS); + mgmtDecTableRef(pTable); return; } else { mError("table:%s, failed to create, table already exist", pCreate->tableId); mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_TABLE_ALREADY_EXIST); + mgmtDecTableRef(pTable); return; } } @@ -210,6 +648,7 @@ static void mgmtProcessAlterTableMsg(SQueuedMsg *pMsg) { if (pAlter->numOfCols > 2) { mError("table:%s, error numOfCols:%d in alter table", pAlter->tableId, pAlter->numOfCols); mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_APP_ERROR); + mgmtDecTableRef(pTable); return; } @@ -238,9 +677,1467 @@ static void mgmtProcessTableMetaMsg(SQueuedMsg *pMsg) { } STableInfo *pTable = mgmtGetTable(pInfo->tableId); - if (pTable == NULL || pTable->type != TSDB_SUPER_TABLE) { - mgmtGetChildTableMeta(pMsg, (SChildTableObj *)pTable); + if (pTable == NULL) { + mgmtGetChildTableMeta(pMsg, NULL); + } else { + if (pTable->type != TSDB_SUPER_TABLE) { + mgmtGetChildTableMeta(pMsg, (SChildTableObj *)pTable); + } else { + mgmtGetSuperTableMeta(pMsg, (SSuperTableObj *)pTable); + } + } +} + + +void mgmtCreateSuperTable(SQueuedMsg *pMsg) { + SCMCreateTableMsg *pCreate = pMsg->pCont; + SSuperTableObj *pStable = (SSuperTableObj *)calloc(1, sizeof(SSuperTableObj)); + if (pStable == NULL) { + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); + return; + } + + strcpy(pStable->info.tableId, pCreate->tableId); + pStable->info.type = TSDB_SUPER_TABLE; + pStable->createdTime = taosGetTimestampMs(); + pStable->uid = (((uint64_t) pStable->createdTime) << 16) + (sdbGetVersion() & ((1ul << 16) - 1ul)); + pStable->sversion = 0; + pStable->numOfColumns = htons(pCreate->numOfColumns); + pStable->numOfTags = htons(pCreate->numOfTags); + + int32_t numOfCols = pCreate->numOfColumns + pCreate->numOfTags; + int32_t schemaSize = numOfCols * sizeof(SSchema); + pStable->schema = (SSchema *)calloc(1, schemaSize); + if (pStable->schema == NULL) { + free(pStable); + mError("stable:%s, no schema input", pCreate->tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); + return; + } + memcpy(pStable->schema, pCreate->schema, numOfCols * sizeof(SSchema)); + + pStable->nextColId = 0; + for (int32_t col = 0; col < numOfCols; col++) { + SSchema *tschema = pStable->schema; + tschema[col].colId = pStable->nextColId++; + tschema[col].bytes = htons(tschema[col].bytes); + } + + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_GLOBAL, + .table = tsSuperTableSdb, + .pObj = pStable, + .rowSize = sizeof(SSuperTableObj) + schemaSize + }; + + int32_t code = sdbInsertRow(&oper); + if (code != TSDB_CODE_SUCCESS) { + mgmtDestroySuperTable(pStable); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SDB_ERROR); } else { - mgmtGetSuperTableMeta(pMsg, (SSuperTableObj *)pTable); + mLPrint("stable:%s, is created, tags:%d cols:%d", pStable->info.tableId, pStable->numOfTags, pStable->numOfColumns); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SUCCESS); + } +} + +void mgmtDropSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pStable) { + if (pStable->numOfTables != 0) { + mError("stable:%s, numOfTables:%d not 0", pStable->info.tableId, pStable->numOfTables); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_OTHERS); + mgmtDecTableRef((STableInfo *)pStable); + } else { + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_GLOBAL, + .table = tsSuperTableSdb, + .pObj = pStable + }; + int32_t code = sdbDeleteRow(&oper); + mLPrint("stable:%s, is dropped from sdb, result:%s", pStable->info.tableId, tstrerror(code)); + mgmtSendSimpleResp(pMsg->thandle, code); + mgmtDecTableRef((STableInfo *)pStable); + } +} + +static void *mgmtGetSuperTableVgroup(SSuperTableObj *pStable) { + SCMSTableVgroupRspMsg *rsp = rpcMallocCont(sizeof(SCMSTableVgroupRspMsg) + sizeof(uint32_t) * mgmtGetDnodesNum()); + rsp->numOfDnodes = htonl(1); + rsp->dnodeIps[0] = htonl(inet_addr(tsPrivateIp)); + return rsp; +} + +static int32_t mgmtFindSuperTableTagIndex(SSuperTableObj *pStable, const char *tagName) { + for (int32_t i = 0; i < pStable->numOfTags; i++) { + SSchema *schema = (SSchema *)(pStable->schema + (pStable->numOfColumns + i) * sizeof(SSchema)); + if (strcasecmp(tagName, schema->name) == 0) { + return i; + } + } + + return -1; +} + +static int32_t mgmtAddSuperTableTag(SSuperTableObj *pStable, SSchema schema[], int32_t ntags) { + if (pStable->numOfTags + ntags > TSDB_MAX_TAGS) { + return TSDB_CODE_APP_ERROR; + } + + // check if schemas have the same name + for (int32_t i = 1; i < ntags; i++) { + for (int32_t j = 0; j < i; j++) { + if (strcasecmp(schema[i].name, schema[j].name) == 0) { + return TSDB_CODE_APP_ERROR; + } + } + } + + SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); + if (pDb == NULL) { + mError("meter: %s not belongs to any database", pStable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("DB: %s not belongs to andy account", pDb->name); + return TSDB_CODE_APP_ERROR; + } + + int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); + pStable->schema = realloc(pStable->schema, schemaSize + sizeof(SSchema) * ntags); + + memmove(pStable->schema + sizeof(SSchema) * (pStable->numOfColumns + ntags), + pStable->schema + sizeof(SSchema) * pStable->numOfColumns, sizeof(SSchema) * pStable->numOfTags); + memcpy(pStable->schema + sizeof(SSchema) * pStable->numOfColumns, schema, sizeof(SSchema) * ntags); + + SSchema *tschema = (SSchema *) (pStable->schema + sizeof(SSchema) * pStable->numOfColumns); + for (int32_t i = 0; i < ntags; i++) { + tschema[i].colId = pStable->nextColId++; + } + + pStable->numOfColumns += ntags; + pStable->sversion++; + + pAcct->acctInfo.numOfTimeSeries += (ntags * pStable->numOfTables); + // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); + + mTrace("Succeed to add tag column %s to table %s", schema[0].name, pStable->info.tableId); + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtDropSuperTableTag(SSuperTableObj *pStable, char *tagName) { + int32_t col = mgmtFindSuperTableTagIndex(pStable, tagName); + if (col <= 0 || col >= pStable->numOfTags) { + return TSDB_CODE_APP_ERROR; } + + SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); + if (pDb == NULL) { + mError("table: %s not belongs to any database", pStable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("DB: %s not belongs to any account", pDb->name); + return TSDB_CODE_APP_ERROR; + } + + memmove(pStable->schema + sizeof(SSchema) * col, pStable->schema + sizeof(SSchema) * (col + 1), + sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags - col - 1)); + + pStable->numOfTags--; + pStable->sversion++; + + int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); + pStable->schema = realloc(pStable->schema, schemaSize); + + // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtModifySuperTableTagNameByName(SSuperTableObj *pStable, char *oldTagName, char *newTagName) { + int32_t col = mgmtFindSuperTableTagIndex(pStable, oldTagName); + if (col < 0) { + // Tag name does not exist + mError("Failed to modify table %s tag column, oname: %s, nname: %s", pStable->info.tableId, oldTagName, newTagName); + return TSDB_CODE_INVALID_MSG_TYPE; + } + + // int32_t rowSize = 0; + uint32_t len = strlen(newTagName); + + if (col >= pStable->numOfTags || len >= TSDB_COL_NAME_LEN || mgmtFindSuperTableTagIndex(pStable, newTagName) >= 0) { + return TSDB_CODE_APP_ERROR; + } + + // update + SSchema *schema = (SSchema *) (pStable->schema + (pStable->numOfColumns + col) * sizeof(SSchema)); + strncpy(schema->name, newTagName, TSDB_COL_NAME_LEN); + + // Encode string + int32_t size = 1 + sizeof(SSuperTableObj) + TSDB_MAX_BYTES_PER_ROW; + char *msg = (char *) malloc(size); + if (msg == NULL) return TSDB_CODE_APP_ERROR; + memset(msg, 0, size); + + // mgmtSuperTableActionEncode(pStable, msg, size, &rowSize); + + int32_t ret = 0; + // int32_t ret = sdbUpdateRow(tsSuperTableSdb, msg, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); + tfree(msg); + + if (ret < 0) { + mError("Failed to modify table %s tag column", pStable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + mTrace("Succeed to modify table %s tag column", pStable->info.tableId); + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtFindSuperTableColumnIndex(SSuperTableObj *pStable, char *colName) { + SSchema *schema = (SSchema *) pStable->schema; + for (int32_t i = 0; i < pStable->numOfColumns; i++) { + if (strcasecmp(schema[i].name, colName) == 0) { + return i; + } + } + + return -1; +} + +static int32_t mgmtAddSuperTableColumn(SSuperTableObj *pStable, SSchema schema[], int32_t ncols) { + if (ncols <= 0) { + return TSDB_CODE_APP_ERROR; + } + + for (int32_t i = 0; i < ncols; i++) { + if (mgmtFindSuperTableColumnIndex(pStable, schema[i].name) > 0) { + return TSDB_CODE_APP_ERROR; + } + } + + SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); + if (pDb == NULL) { + mError("meter: %s not belongs to any database", pStable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("DB: %s not belongs to andy account", pDb->name); + return TSDB_CODE_APP_ERROR; + } + + int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); + pStable->schema = realloc(pStable->schema, schemaSize + sizeof(SSchema) * ncols); + + memmove(pStable->schema + sizeof(SSchema) * (pStable->numOfColumns + ncols), + pStable->schema + sizeof(SSchema) * pStable->numOfColumns, sizeof(SSchema) * pStable->numOfTags); + memcpy(pStable->schema + sizeof(SSchema) * pStable->numOfColumns, schema, sizeof(SSchema) * ncols); + + SSchema *tschema = (SSchema *) (pStable->schema + sizeof(SSchema) * pStable->numOfColumns); + for (int32_t i = 0; i < ncols; i++) { + tschema[i].colId = pStable->nextColId++; + } + + pStable->numOfColumns += ncols; + pStable->sversion++; + + pAcct->acctInfo.numOfTimeSeries += (ncols * pStable->numOfTables); + // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtDropSuperTableColumnByName(SSuperTableObj *pStable, char *colName) { + int32_t col = mgmtFindSuperTableColumnIndex(pStable, colName); + if (col < 0) { + return TSDB_CODE_APP_ERROR; + } + + SDbObj *pDb = mgmtGetDbByTableId(pStable->info.tableId); + if (pDb == NULL) { + mError("table: %s not belongs to any database", pStable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("DB: %s not belongs to any account", pDb->name); + return TSDB_CODE_APP_ERROR; + } + + memmove(pStable->schema + sizeof(SSchema) * col, pStable->schema + sizeof(SSchema) * (col + 1), + sizeof(SSchema) * (pStable->numOfColumns + pStable->numOfTags - col - 1)); + + pStable->numOfColumns--; + pStable->sversion++; + + int32_t schemaSize = sizeof(SSchema) * (pStable->numOfTags + pStable->numOfColumns); + pStable->schema = realloc(pStable->schema, schemaSize); + + pAcct->acctInfo.numOfTimeSeries -= (pStable->numOfTables); + // sdbUpdateRow(tsSuperTableSdb, pStable, tsSuperTableUpdateSize, SDB_OPER_GLOBAL); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtGetShowSuperTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { + SDbObj *pDb = mgmtGetDb(pShow->db); + if (pDb == NULL) { + return TSDB_CODE_DB_NOT_SELECTED; + } + + int32_t cols = 0; + SSchema *pSchema = pMeta->schema; + + pShow->bytes[cols] = TSDB_TABLE_NAME_LEN; + pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + strcpy(pSchema[cols].name, "name"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 8; + pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; + strcpy(pSchema[cols].name, "create_time"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 2; + pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; + strcpy(pSchema[cols].name, "columns"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 2; + pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; + strcpy(pSchema[cols].name, "tags"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "tables"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pMeta->numOfColumns = htons(cols); + pShow->numOfColumns = cols; + + pShow->offset[0] = 0; + for (int32_t i = 1; i < cols; ++i) pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; + + pShow->numOfRows = pDb->numOfSuperTables; + pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; + + return 0; +} + +int32_t mgmtRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows, void *pConn) { + int32_t numOfRows = 0; + char * pWrite; + int32_t cols = 0; + SSuperTableObj *pTable = NULL; + char prefix[20] = {0}; + int32_t prefixLen; + + SDbObj *pDb = mgmtGetDb(pShow->db); + if (pDb == NULL) return 0; + + SUserObj *pUser = mgmtGetUserFromConn(pConn, NULL); + + if (mgmtCheckIsMonitorDB(pDb->name, tsMonitorDbName)) { + if (strcmp(pUser->user, "root") != 0 && strcmp(pUser->user, "_root") != 0 && strcmp(pUser->user, "monitor") != 0 ) { + return 0; + } + } + + strcpy(prefix, pDb->name); + strcat(prefix, TS_PATH_DELIMITER); + prefixLen = strlen(prefix); + + SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER; + char stableName[TSDB_TABLE_NAME_LEN] = {0}; + + while (numOfRows < rows) { + pShow->pNode = sdbFetchRow(tsSuperTableSdb, pShow->pNode, (void **) &pTable); + if (pTable == NULL) break; + if (strncmp(pTable->info.tableId, prefix, prefixLen)) { + continue; + } + + memset(stableName, 0, tListLen(stableName)); + mgmtExtractTableName(pTable->info.tableId, stableName); + + if (pShow->payloadLen > 0 && + patternMatch(pShow->payload, stableName, TSDB_TABLE_NAME_LEN, &info) != TSDB_PATTERN_MATCH) + continue; + + cols = 0; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + strncpy(pWrite, stableName, TSDB_TABLE_NAME_LEN); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int64_t *)pWrite = pTable->createdTime; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int16_t *)pWrite = pTable->numOfColumns; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int16_t *)pWrite = pTable->numOfTags; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int32_t *)pWrite = pTable->numOfTables; + cols++; + + numOfRows++; + } + + pShow->numOfReads += numOfRows; + return numOfRows; +} + +void mgmtDropAllSuperTables(SDbObj *pDropDb) { + void *pNode = NULL; + void *pLastNode = NULL; + int32_t numOfTables = 0; + int32_t dbNameLen = strlen(pDropDb->name); + SSuperTableObj *pTable = NULL; + + while (1) { + pNode = sdbFetchRow(tsSuperTableSdb, pNode, (void **)&pTable); + if (pTable == NULL) { + break; + } + + if (strncmp(pDropDb->name, pTable->info.tableId, dbNameLen) == 0) { + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_LOCAL, + .table = tsSuperTableSdb, + .pObj = pTable, + }; + sdbDeleteRow(&oper); + pNode = pLastNode; + numOfTables ++; + continue; + } + } + + mTrace("db:%s, all super tables:%d is dropped from sdb", pDropDb->name, numOfTables); +} + +int32_t mgmtSetSchemaFromSuperTable(SSchema *pSchema, SSuperTableObj *pTable) { + int32_t numOfCols = pTable->numOfColumns + pTable->numOfTags; + for (int32_t i = 0; i < numOfCols; ++i) { + strcpy(pSchema->name, pTable->schema[i].name); + pSchema->type = pTable->schema[i].type; + pSchema->bytes = htons(pTable->schema[i].bytes); + pSchema->colId = htons(pTable->schema[i].colId); + pSchema++; + } + + return (pTable->numOfColumns + pTable->numOfTags) * sizeof(SSchema); +} + +void mgmtGetSuperTableMeta(SQueuedMsg *pMsg, SSuperTableObj *pTable) { + SDbObj *pDb = pMsg->pDb; + + STableMetaMsg *pMeta = rpcMallocCont(sizeof(STableMetaMsg) + sizeof(SSchema) * TSDB_MAX_COLUMNS); + pMeta->uid = htobe64(pTable->uid); + pMeta->sversion = htons(pTable->sversion); + pMeta->precision = pDb->cfg.precision; + pMeta->numOfTags = (uint8_t)pTable->numOfTags; + pMeta->numOfColumns = htons((int16_t)pTable->numOfColumns); + pMeta->tableType = pTable->info.type; + pMeta->contLen = sizeof(STableMetaMsg) + mgmtSetSchemaFromSuperTable(pMeta->schema, pTable); + strcpy(pMeta->tableId, pTable->info.tableId); + + SRpcMsg rpcRsp = { + .handle = pMsg->thandle, + .pCont = pMeta, + .contLen = pMeta->contLen, + }; + pMeta->contLen = htons(pMeta->contLen); + rpcSendResponse(&rpcRsp); + + mTrace("stable:%%s, uid:%" PRIu64 " table meta is retrieved", pTable->info.tableId, pTable->uid); + mgmtDecTableRef((STableInfo *)pTable); +} + +static void mgmtProcessSuperTableVgroupMsg(SQueuedMsg *pMsg) { + SCMSTableVgroupMsg *pInfo = pMsg->pCont; + STableInfo *pTable = mgmtGetSuperTable(pInfo->tableId); + if (pTable == NULL) { + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); + return; + } + + SCMSTableVgroupRspMsg *pRsp = mgmtGetSuperTableVgroup((SSuperTableObj *) pTable); + if (pRsp != NULL) { + int32_t msgLen = sizeof(SSuperTableObj) + htonl(pRsp->numOfDnodes) * sizeof(int32_t); + SRpcMsg rpcRsp = {0}; + rpcRsp.handle = pMsg->thandle; + rpcRsp.pCont = pRsp; + rpcRsp.contLen = msgLen; + rpcSendResponse(&rpcRsp); + } else { + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); + } +} + +void mgmtAlterSuperTable(SQueuedMsg *pMsg, SSuperTableObj *pTable) { + int32_t code = TSDB_CODE_OPS_NOT_SUPPORT; + SCMAlterTableMsg *pAlter = pMsg->pCont; + + if (pAlter->type == TSDB_ALTER_TABLE_ADD_TAG_COLUMN) { + code = mgmtAddSuperTableTag((SSuperTableObj *) pTable, pAlter->schema, 1); + } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_TAG_COLUMN) { + code = mgmtDropSuperTableTag((SSuperTableObj *) pTable, pAlter->schema[0].name); + } else if (pAlter->type == TSDB_ALTER_TABLE_CHANGE_TAG_COLUMN) { + code = mgmtModifySuperTableTagNameByName((SSuperTableObj *) pTable, pAlter->schema[0].name, pAlter->schema[1].name); + } else if (pAlter->type == TSDB_ALTER_TABLE_ADD_COLUMN) { + code = mgmtAddSuperTableColumn((SSuperTableObj *) pTable, pAlter->schema, 1); + } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_COLUMN) { + code = mgmtDropSuperTableColumnByName((SSuperTableObj *) pTable, pAlter->schema[0].name); + } else {} + + mgmtSendSimpleResp(pMsg->thandle, code); +} + +static void mgmtProcessDropStableRsp(SRpcMsg *rpcMsg) { + mTrace("drop stable rsp received, handle:%p code:%d", rpcMsg->handle, rpcMsg->code); +} + + +static void *mgmtBuildCreateChildTableMsg(SCMCreateTableMsg *pMsg, SChildTableObj *pTable) { + char * pTagData = NULL; + int32_t tagDataLen = 0; + int32_t totalCols = 0; + int32_t contLen = 0; + if (pTable->info.type == TSDB_CHILD_TABLE && pMsg != NULL) { + pTagData = pMsg->schema + TSDB_TABLE_ID_LEN + 1; + tagDataLen = htonl(pMsg->contLen) - sizeof(SCMCreateTableMsg) - TSDB_TABLE_ID_LEN - 1; + totalCols = pTable->superTable->numOfColumns + pTable->superTable->numOfTags; + contLen = sizeof(SMDCreateTableMsg) + totalCols * sizeof(SSchema) + tagDataLen + pTable->sqlLen; + } else { + totalCols = pTable->numOfColumns; + contLen = sizeof(SMDCreateTableMsg) + totalCols * sizeof(SSchema) + pTable->sqlLen; + } + + SMDCreateTableMsg *pCreate = rpcMallocCont(contLen); + if (pCreate == NULL) { + terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; + return NULL; + } + + memcpy(pCreate->tableId, pTable->info.tableId, TSDB_TABLE_ID_LEN + 1); + pCreate->contLen = htonl(contLen); + pCreate->vgId = htonl(pTable->vgId); + pCreate->tableType = pTable->info.type; + pCreate->createdTime = htobe64(pTable->createdTime); + pCreate->sid = htonl(pTable->sid); + pCreate->sqlDataLen = htonl(pTable->sqlLen); + pCreate->uid = htobe64(pTable->uid); + + if (pTable->info.type == TSDB_CHILD_TABLE) { + memcpy(pCreate->superTableId, pTable->superTable->info.tableId, TSDB_TABLE_ID_LEN + 1); + pCreate->numOfColumns = htons(pTable->superTable->numOfColumns); + pCreate->numOfTags = htons(pTable->superTable->numOfTags); + pCreate->sversion = htonl(pTable->superTable->sversion); + pCreate->tagDataLen = htonl(tagDataLen); + pCreate->superTableUid = htobe64(pTable->superTable->uid); + } else { + pCreate->numOfColumns = htons(pTable->numOfColumns); + pCreate->numOfTags = 0; + pCreate->sversion = htonl(pTable->sversion); + pCreate->tagDataLen = 0; + pCreate->superTableUid = 0; + } + + SSchema *pSchema = (SSchema *) pCreate->data; + if (pTable->info.type == TSDB_CHILD_TABLE) { + memcpy(pSchema, pTable->superTable->schema, totalCols * sizeof(SSchema)); + } else { + memcpy(pSchema, pTable->schema, totalCols * sizeof(SSchema)); + } + for (int32_t col = 0; col < totalCols; ++col) { + pSchema->bytes = htons(pSchema->bytes); + pSchema->colId = htons(pSchema->colId); + pSchema++; + } + + if (pTable->info.type == TSDB_CHILD_TABLE && pMsg != NULL) { + memcpy(pCreate->data + totalCols * sizeof(SSchema), pTagData, tagDataLen); + memcpy(pCreate->data + totalCols * sizeof(SSchema) + tagDataLen, pTable->sql, pTable->sqlLen); + } + + return pCreate; +} + +static SChildTableObj* mgmtDoCreateChildTable(SCMCreateTableMsg *pCreate, SVgObj *pVgroup, int32_t tid) { + SChildTableObj *pTable = (SChildTableObj *) calloc(1, sizeof(SChildTableObj)); + if (pTable == NULL) { + mError("ctable:%s, failed to alloc memory", pCreate->tableId); + terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; + return NULL; + } + + if (pCreate->numOfColumns == 0) { + pTable->info.type = TSDB_CHILD_TABLE; + } else { + pTable->info.type = TSDB_NORMAL_TABLE; + } + + strcpy(pTable->info.tableId, pCreate->tableId); + pTable->createdTime = taosGetTimestampMs(); + pTable->sid = tid; + pTable->vgId = pVgroup->vgId; + + if (pTable->info.type == TSDB_CHILD_TABLE) { + char *pTagData = (char *) pCreate->schema; // it is a tag key + SSuperTableObj *pSuperTable = mgmtGetSuperTable(pTagData); + if (pSuperTable == NULL) { + mError("ctable:%s, corresponding super table does not exist", pCreate->tableId); + free(pTable); + terrno = TSDB_CODE_INVALID_TABLE; + return NULL; + } + + strcpy(pTable->superTableId, pSuperTable->info.tableId); + pTable->uid = (((uint64_t) pTable->vgId) << 40) + ((((uint64_t) pTable->sid) & ((1ul << 24) - 1ul)) << 16) + + (sdbGetVersion() & ((1ul << 16) - 1ul)); + pTable->superTable = pSuperTable; + } else { + pTable->uid = (((uint64_t) pTable->createdTime) << 16) + (sdbGetVersion() & ((1ul << 16) - 1ul)); + pTable->sversion = 0; + pTable->numOfColumns = htons(pCreate->numOfColumns); + pTable->sqlLen = htons(pCreate->sqlLen); + + int32_t numOfCols = pTable->numOfColumns; + int32_t schemaSize = numOfCols * sizeof(SSchema); + pTable->schema = (SSchema *) calloc(1, schemaSize); + if (pTable->schema == NULL) { + free(pTable); + terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; + return NULL; + } + memcpy(pTable->schema, pCreate->schema, numOfCols * sizeof(SSchema)); + + pTable->nextColId = 0; + for (int32_t col = 0; col < numOfCols; col++) { + SSchema *tschema = pTable->schema; + tschema[col].colId = pTable->nextColId++; + tschema[col].bytes = htons(tschema[col].bytes); + } + + if (pTable->sqlLen != 0) { + pTable->info.type = TSDB_STREAM_TABLE; + pTable->sql = calloc(1, pTable->sqlLen); + if (pTable->sql == NULL) { + free(pTable); + terrno = TSDB_CODE_SERV_OUT_OF_MEMORY; + return NULL; + } + memcpy(pTable->sql, (char *) (pCreate->schema) + numOfCols * sizeof(SSchema), pTable->sqlLen); + pTable->sql[pTable->sqlLen - 1] = 0; + mTrace("table:%s, stream sql len:%d sql:%s", pTable->info.tableId, pTable->sqlLen, pTable->sql); + } + } + + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_GLOBAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + + if (sdbInsertRow(&desc) != TSDB_CODE_SUCCESS) { + free(pTable); + mError("ctable:%s, update sdb error", pCreate->tableId); + terrno = TSDB_CODE_SDB_ERROR; + return NULL; + } + + mTrace("ctable:%s, create ctable in vgroup, uid:%" PRIu64 , pTable->info.tableId, pTable->uid); + return pTable; +} + +void mgmtCreateChildTable(SQueuedMsg *pMsg) { + SCMCreateTableMsg *pCreate = pMsg->pCont; + + int32_t code = grantCheck(TSDB_GRANT_TIMESERIES); + if (code != TSDB_CODE_SUCCESS) { + mError("table:%s, failed to create, grant not", pCreate->tableId); + mgmtSendSimpleResp(pMsg->thandle, code); + return; + } + + SQueuedMsg *newMsg = malloc(sizeof(SQueuedMsg)); + memcpy(newMsg, pMsg, sizeof(SQueuedMsg)); + pMsg->pCont = NULL; + + SVgObj *pVgroup = mgmtGetAvailableVgroup(pMsg->pDb); + if (pVgroup == NULL) { + mTrace("table:%s, start to create a new vgroup", pCreate->tableId); + mgmtCreateVgroup(newMsg); + return; + } + + int32_t sid = taosAllocateId(pVgroup->idPool); + if (sid < 0) { + mTrace("tables:%s, no enough sid in vgroup:%d", pVgroup->vgId); + mgmtCreateVgroup(newMsg); + return; + } + + SChildTableObj *pTable = mgmtDoCreateChildTable(pCreate, pVgroup, sid); + if (pTable == NULL) { + mgmtSendSimpleResp(pMsg->thandle, terrno); + mgmtFreeQueuedMsg(newMsg); + return; + } + + mgmtIncTableRef((STableInfo *)pTable); + SMDCreateTableMsg *pMDCreate = mgmtBuildCreateChildTableMsg(pCreate, (SChildTableObj *) pTable); + if (pMDCreate == NULL) { + mgmtSendSimpleResp(pMsg->thandle, terrno); + mgmtFreeQueuedMsg(newMsg); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + SRpcIpSet ipSet = mgmtGetIpSetFromVgroup(pVgroup); + SRpcMsg rpcMsg = { + .handle = newMsg, + .pCont = pMDCreate, + .contLen = htonl(pMDCreate->contLen), + .code = 0, + .msgType = TSDB_MSG_TYPE_MD_CREATE_TABLE + }; + + newMsg->ahandle = pTable; + mgmtSendMsgToDnode(&ipSet, &rpcMsg); +} + +void mgmtDropChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable) { + SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); + if (pVgroup == NULL) { + mError("ctable:%s, failed to drop child table, vgroup not exist", pTable->info.tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_OTHERS); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + SMDDropTableMsg *pDrop = rpcMallocCont(sizeof(SMDDropTableMsg)); + if (pDrop == NULL) { + mError("ctable:%s, failed to drop child table, no enough memory", pTable->info.tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + strcpy(pDrop->tableId, pTable->info.tableId); + pDrop->vgId = htonl(pTable->vgId); + pDrop->contLen = htonl(sizeof(SMDDropTableMsg)); + pDrop->sid = htonl(pTable->sid); + pDrop->uid = htobe64(pTable->uid); + + SRpcIpSet ipSet = mgmtGetIpSetFromVgroup(pVgroup); + + mTrace("ctable:%s, send drop table msg", pDrop->tableId); + SRpcMsg rpcMsg = { + .handle = pMsg, + .pCont = pDrop, + .contLen = sizeof(SMDDropTableMsg), + .code = 0, + .msgType = TSDB_MSG_TYPE_MD_DROP_TABLE + }; + + pMsg->ahandle = pTable; + mgmtSendMsgToDnode(&ipSet, &rpcMsg); +} + + +int32_t mgmtModifyChildTableTagValueByName(SChildTableObj *pTable, char *tagName, char *nContent) { +// TODO: send message to dnode +// int32_t col = mgmtFindSuperTableTagIndex(pTable->superTable, tagName); +// if (col < 0 || col > pTable->superTable->numOfTags) { +// return TSDB_CODE_APP_ERROR; +// } +// +// //TODO send msg to dnode +// mTrace("Succeed to modify tag column %d of table %s", col, pTable->info.tableId); +// return TSDB_CODE_SUCCESS; + +// int32_t rowSize = 0; +// SSchema *schema = (SSchema *)(pSuperTable->schema + (pSuperTable->numOfColumns + col) * sizeof(SSchema)); +// +// if (col == 0) { +// pTable->isDirty = 1; +// removeMeterFromMetricIndex(pSuperTable, pTable); +// } +// memcpy(pTable->pTagData + mgmtGetTagsLength(pMetric, col) + TSDB_TABLE_ID_LEN, nContent, schema->bytes); +// if (col == 0) { +// addMeterIntoMetricIndex(pMetric, pTable); +// } +// +// // Encode the string +// int32_t size = sizeof(STabObj) + TSDB_MAX_BYTES_PER_ROW + 1; +// char *msg = (char *)malloc(size); +// if (msg == NULL) { +// mError("failed to allocate message memory while modify tag value"); +// return TSDB_CODE_APP_ERROR; +// } +// memset(msg, 0, size); +// +// mgmtMeterActionEncode(pTable, msg, size, &rowSize); +// +// int32_t ret = sdbUpdateRow(tsChildTableSdb, msg, rowSize, 1); // Need callback function +// tfree(msg); +// +// if (pTable->isDirty) pTable->isDirty = 0; +// +// if (ret < 0) { +// mError("Failed to modify tag column %d of table %s", col, pTable->info.tableId); +// return TSDB_CODE_APP_ERROR; +// } +// +// mTrace("Succeed to modify tag column %d of table %s", col, pTable->info.tableId); +// return TSDB_CODE_SUCCESS; + return 0; +} + + +static int32_t mgmtFindNormalTableColumnIndex(SChildTableObj *pTable, char *colName) { + SSchema *schema = (SSchema *) pTable->schema; + for (int32_t i = 0; i < pTable->numOfColumns; i++) { + if (strcasecmp(schema[i].name, colName) == 0) { + return i; + } + } + + return -1; +} + +static int32_t mgmtAddNormalTableColumn(SChildTableObj *pTable, SSchema schema[], int32_t ncols) { + if (ncols <= 0) { + return TSDB_CODE_APP_ERROR; + } + + for (int32_t i = 0; i < ncols; i++) { + if (mgmtFindNormalTableColumnIndex(pTable, schema[i].name) > 0) { + return TSDB_CODE_APP_ERROR; + } + } + + SDbObj *pDb = mgmtGetDbByTableId(pTable->info.tableId); + if (pDb == NULL) { + mError("table: %s not belongs to any database", pTable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("DB: %s not belongs to andy account", pDb->name); + return TSDB_CODE_APP_ERROR; + } + + int32_t schemaSize = pTable->numOfColumns * sizeof(SSchema); + pTable->schema = realloc(pTable->schema, schemaSize + sizeof(SSchema) * ncols); + + memcpy(pTable->schema + schemaSize, schema, sizeof(SSchema) * ncols); + + SSchema *tschema = (SSchema *) (pTable->schema + sizeof(SSchema) * pTable->numOfColumns); + for (int32_t i = 0; i < ncols; i++) { + tschema[i].colId = pTable->nextColId++; + } + + pTable->numOfColumns += ncols; + pTable->sversion++; + pAcct->acctInfo.numOfTimeSeries += ncols; + + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_GLOBAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + desc.rowData = pTable; + desc.rowSize = tsChildTableUpdateSize; + sdbUpdateRow(&desc); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtDropNormalTableColumnByName(SChildTableObj *pTable, char *colName) { + int32_t col = mgmtFindNormalTableColumnIndex(pTable, colName); + if (col < 0) { + return TSDB_CODE_APP_ERROR; + } + + SDbObj *pDb = mgmtGetDbByTableId(pTable->info.tableId); + if (pDb == NULL) { + mError("table: %s not belongs to any database", pTable->info.tableId); + return TSDB_CODE_APP_ERROR; + } + + SAcctObj *pAcct = acctGetAcct(pDb->cfg.acct); + if (pAcct == NULL) { + mError("DB: %s not belongs to any account", pDb->name); + return TSDB_CODE_APP_ERROR; + } + + memmove(pTable->schema + sizeof(SSchema) * col, pTable->schema + sizeof(SSchema) * (col + 1), + sizeof(SSchema) * (pTable->numOfColumns - col - 1)); + + pTable->numOfColumns--; + pTable->sversion++; + + pAcct->acctInfo.numOfTimeSeries--; + + SSdbOperDesc desc = {0}; + desc.type = SDB_OPER_TYPE_GLOBAL; + desc.pObj = pTable; + desc.table = tsChildTableSdb; + desc.rowData = pTable; + desc.rowSize = tsChildTableUpdateSize; + sdbUpdateRow(&desc); + + return TSDB_CODE_SUCCESS; +} + +static int32_t mgmtSetSchemaFromNormalTable(SSchema *pSchema, SChildTableObj *pTable) { + int32_t numOfCols = pTable->numOfColumns; + for (int32_t i = 0; i < numOfCols; ++i) { + strcpy(pSchema->name, pTable->schema[i].name); + pSchema->type = pTable->schema[i].type; + pSchema->bytes = htons(pTable->schema[i].bytes); + pSchema->colId = htons(pTable->schema[i].colId); + pSchema++; + } + + return numOfCols * sizeof(SSchema); +} + +static int32_t mgmtDoGetChildTableMeta(SDbObj *pDb, SChildTableObj *pTable, STableMetaMsg *pMeta, bool usePublicIp) { + pMeta->uid = htobe64(pTable->uid); + pMeta->sid = htonl(pTable->sid); + pMeta->vgId = htonl(pTable->vgId); + pMeta->precision = pDb->cfg.precision; + pMeta->tableType = pTable->info.type; + strncpy(pMeta->tableId, pTable->info.tableId, tListLen(pTable->info.tableId)); + + if (pTable->info.type == TSDB_CHILD_TABLE) { + pMeta->sversion = htons(pTable->superTable->sversion); + pMeta->numOfTags = 0; + pMeta->numOfColumns = htons((int16_t)pTable->superTable->numOfColumns); + pMeta->contLen = sizeof(STableMetaMsg) + mgmtSetSchemaFromSuperTable(pMeta->schema, pTable->superTable); + strncpy(pMeta->stableId, pTable->superTable->info.tableId, tListLen(pMeta->stableId)); + } else { + pMeta->sversion = htons(pTable->sversion); + pMeta->numOfTags = 0; + pMeta->numOfColumns = htons((int16_t)pTable->numOfColumns); + pMeta->contLen = sizeof(STableMetaMsg) + mgmtSetSchemaFromNormalTable(pMeta->schema, pTable); + } + + SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); + if (pVgroup == NULL) { + mError("table:%s, failed to get table meta, db not selected", pTable->info.tableId); + return TSDB_CODE_INVALID_VGROUP_ID; + } + + for (int32_t i = 0; i < TSDB_VNODES_SUPPORT; ++i) { + if (usePublicIp) { + pMeta->vpeerDesc[i].ip = pVgroup->vnodeGid[i].publicIp; + } else { + pMeta->vpeerDesc[i].ip = pVgroup->vnodeGid[i].privateIp; + } + pMeta->vpeerDesc[i].vnode = htonl(pVgroup->vnodeGid[i].vnode); + } + pMeta->numOfVpeers = pVgroup->numOfVnodes; + + mTrace("table:%s, uid:%" PRIu64 " table meta is retrieved", pTable->info.tableId, pTable->uid); + + return TSDB_CODE_SUCCESS; +} + +void mgmtGetChildTableMeta(SQueuedMsg *pMsg, SChildTableObj *pTable) { + SCMTableInfoMsg *pInfo = pMsg->pCont; + SDbObj *pDb = mgmtGetDbByTableId(pInfo->tableId); + if (pDb == NULL || pDb->dirty) { + mError("table:%s, failed to get table meta, db not selected", pInfo->tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_DB_NOT_SELECTED); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + if (pTable == NULL) { + if (htons(pInfo->createFlag) != 1) { + mError("table:%s, failed to get table meta, table not exist", pInfo->tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_TABLE); + return; + } else { + //TODO: on demand create table from super table if table does not exists + int32_t contLen = sizeof(SCMCreateTableMsg) + sizeof(STagData); + SCMCreateTableMsg *pCreateMsg = rpcMallocCont(contLen); + if (pCreateMsg == NULL) { + mError("table:%s, failed to create table while get meta info, no enough memory", pInfo->tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); + return; + } + memcpy(pCreateMsg->schema, pInfo->tags, sizeof(STagData)); + strcpy(pCreateMsg->tableId, pInfo->tableId); + + SQueuedMsg *newMsg = malloc(sizeof(SQueuedMsg)); + memcpy(newMsg, pMsg, sizeof(SQueuedMsg)); + pMsg->pCont = NULL; + + newMsg->ahandle = newMsg->pCont; + newMsg->pCont = pCreateMsg; + mTrace("table:%s, start to create in demand", pInfo->tableId); + mgmtAddToShellQueue(newMsg); + return; + } + } + + STableMetaMsg *pMeta = rpcMallocCont(sizeof(STableMetaMsg) + sizeof(SSchema) * TSDB_MAX_COLUMNS); + if (pMeta == NULL) { + mError("table:%s, failed to get table meta, no enough memory", pTable->info.tableId); + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + mgmtDoGetChildTableMeta(pDb, pTable, pMeta, pMsg->usePublicIp); + + SRpcMsg rpcRsp = { + .handle = pMsg->thandle, + .pCont = pMeta, + .contLen = pMeta->contLen, + }; + pMeta->contLen = htons(pMeta->contLen); + rpcSendResponse(&rpcRsp); + mgmtDecTableRef((STableInfo *)pTable); +} + +void mgmtDropAllChildTables(SDbObj *pDropDb) { + void *pNode = NULL; + void *pLastNode = NULL; + int32_t numOfTables = 0; + int32_t dbNameLen = strlen(pDropDb->name); + SChildTableObj *pTable = NULL; + + while (1) { + pNode = sdbFetchRow(tsChildTableSdb, pNode, (void **)&pTable); + if (pTable == NULL) { + break; + } + + if (strncmp(pDropDb->name, pTable->info.tableId, dbNameLen) == 0) { + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_LOCAL, + .table = tsChildTableSdb, + .pObj = pTable, + }; + sdbDeleteRow(&oper); + pNode = pLastNode; + numOfTables++; + continue; + } + } + + mTrace("db:%s, all child tables:%d is dropped from sdb", pDropDb->name, numOfTables); +} + +void mgmtDropAllChildTablesInStable(SSuperTableObj *pStable) { + void *pNode = NULL; + void *pLastNode = NULL; + int32_t numOfTables = 0; + SChildTableObj *pTable = NULL; + + while (1) { + pNode = sdbFetchRow(tsChildTableSdb, pNode, (void **)&pTable); + if (pTable == NULL) { + break; + } + + if (pTable->superTable == pStable) { + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_LOCAL, + .table = tsChildTableSdb, + .pObj = pTable, + }; + sdbDeleteRow(&oper); + pNode = pLastNode; + numOfTables++; + continue; + } + } + + mTrace("stable:%s, all child tables:%d is dropped from sdb", pStable->info.tableId, numOfTables); +} + +static SChildTableObj* mgmtGetTableByPos(uint32_t dnodeId, int32_t vnode, int32_t sid) { + SDnodeObj *pObj = mgmtGetDnode(dnodeId); + SVgObj *pVgroup = mgmtGetVgroup(vnode); + + if (pObj == NULL || pVgroup == NULL) { + return NULL; + } + + SChildTableObj *pTable = pVgroup->tableList[sid]; + mgmtIncTableRef((STableInfo *)pTable); + return pTable; +} + +static void mgmtProcessTableCfgMsg(SRpcMsg *rpcMsg) { + if (mgmtCheckRedirect(rpcMsg->handle)) return; + + SDMConfigTableMsg *pCfg = (SDMConfigTableMsg *) rpcMsg->pCont; + pCfg->dnode = htonl(pCfg->dnode); + pCfg->vnode = htonl(pCfg->vnode); + pCfg->sid = htonl(pCfg->sid); + mTrace("dnode:%s, vnode:%d, sid:%d, receive table config msg", taosIpStr(pCfg->dnode), pCfg->vnode, pCfg->sid); + + SChildTableObj *pTable = mgmtGetTableByPos(pCfg->dnode, pCfg->vnode, pCfg->sid); + if (pTable == NULL) { + mError("dnode:%s, vnode:%d, sid:%d, table not found", taosIpStr(pCfg->dnode), pCfg->vnode, pCfg->sid); + mgmtSendSimpleResp(rpcMsg->handle, TSDB_CODE_NOT_ACTIVE_TABLE); + return; + } + + mgmtSendSimpleResp(rpcMsg->handle, TSDB_CODE_SUCCESS); + + SMDCreateTableMsg *pMDCreate = NULL; + pMDCreate = mgmtBuildCreateChildTableMsg(NULL, (SChildTableObj *) pTable); + if (pMDCreate == NULL) { + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + SRpcIpSet ipSet = mgmtGetIpSetFromIp(pCfg->dnode); + SRpcMsg rpcRsp = { + .handle = NULL, + .pCont = pMDCreate, + .contLen = htonl(pMDCreate->contLen), + .code = 0, + .msgType = TSDB_MSG_TYPE_MD_CREATE_TABLE + }; + mgmtSendMsgToDnode(&ipSet, &rpcRsp); + mgmtDecTableRef((STableInfo *)pTable); +} + +static void mgmtProcessDropTableRsp(SRpcMsg *rpcMsg) { + if (rpcMsg->handle == NULL) return; + + SQueuedMsg *queueMsg = rpcMsg->handle; + queueMsg->received++; + + SChildTableObj *pTable = queueMsg->ahandle; + mTrace("table:%s, drop table rsp received, thandle:%p result:%s", pTable->info.tableId, queueMsg->thandle, tstrerror(rpcMsg->code)); + + if (rpcMsg->code != TSDB_CODE_SUCCESS) { + mError("table:%s, failed to drop in dnode, reason:%s", pTable->info.tableId, tstrerror(rpcMsg->code)); + mgmtSendSimpleResp(queueMsg->thandle, rpcMsg->code); + free(queueMsg); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + SVgObj *pVgroup = mgmtGetVgroup(pTable->vgId); + if (pVgroup == NULL) { + mError("table:%s, failed to get vgroup", pTable->info.tableId); + mgmtSendSimpleResp(queueMsg->thandle, TSDB_CODE_INVALID_VGROUP_ID); + free(queueMsg); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_GLOBAL, + .table = tsChildTableSdb, + .pObj = pTable + }; + + int32_t code = sdbDeleteRow(&oper); + if (code != TSDB_CODE_SUCCESS) { + mError("table:%s, update ctables sdb error", pTable->info.tableId); + mgmtSendSimpleResp(queueMsg->thandle, TSDB_CODE_SDB_ERROR); + free(queueMsg); + mgmtDecTableRef((STableInfo *)pTable); + return; + } + + if (pVgroup->numOfTables <= 0) { + mPrint("vgroup:%d, all tables is dropped, drop vgroup", pVgroup->vgId); + mgmtDropVgroup(pVgroup, NULL); + } + + mgmtSendSimpleResp(queueMsg->thandle, TSDB_CODE_SUCCESS); + free(queueMsg); + mgmtDecTableRef((STableInfo *)pTable); +} + +static void mgmtProcessCreateTableRsp(SRpcMsg *rpcMsg) { + if (rpcMsg->handle == NULL) return; + + SQueuedMsg *queueMsg = rpcMsg->handle; + queueMsg->received++; + + SChildTableObj *pTable = queueMsg->ahandle; + mTrace("table:%s, create table rsp received, thandle:%p ahandle:%p result:%s", pTable->info.tableId, queueMsg->thandle, + rpcMsg->handle, tstrerror(rpcMsg->code)); + + if (rpcMsg->code != TSDB_CODE_SUCCESS) { + SSdbOperDesc oper = { + .type = SDB_OPER_TYPE_GLOBAL, + .table = tsChildTableSdb, + .pObj = pTable + }; + sdbDeleteRow(&oper); + + mError("table:%s, failed to create in dnode, reason:%s", pTable->info.tableId, tstrerror(rpcMsg->code)); + mgmtSendSimpleResp(queueMsg->thandle, rpcMsg->code); + mgmtDecTableRef((STableInfo *)pTable); + } else { + mTrace("table:%s, created in dnode", pTable->info.tableId); + if (queueMsg->msgType != TSDB_MSG_TYPE_CM_CREATE_TABLE) { + SQueuedMsg *newMsg = calloc(1, sizeof(SQueuedMsg)); + newMsg->msgType = queueMsg->msgType; + newMsg->thandle = queueMsg->thandle; + newMsg->pDb = queueMsg->pDb; + newMsg->pUser = queueMsg->pUser; + newMsg->contLen = queueMsg->contLen; + newMsg->pCont = rpcMallocCont(newMsg->contLen); + memcpy(newMsg->pCont, queueMsg->pCont, newMsg->contLen); + mTrace("table:%s, start to get meta", pTable->info.tableId); + mgmtAddToShellQueue(newMsg); + } else { + mgmtSendSimpleResp(queueMsg->thandle, rpcMsg->code); + mgmtDecTableRef((STableInfo *)pTable); + } + } + + free(queueMsg); +} + +static void mgmtProcessAlterTableRsp(SRpcMsg *rpcMsg) { + mTrace("alter table rsp received, handle:%p code:%d", rpcMsg->handle, rpcMsg->code); +} + +static void mgmtProcessMultiTableMetaMsg(SQueuedMsg *pMsg) { + SRpcConnInfo connInfo; + if (rpcGetConnInfo(pMsg->thandle, &connInfo) != 0) { + mError("conn:%p is already released while get mulit table meta", pMsg->thandle); + return; + } + + bool usePublicIp = (connInfo.serverIp == tsPublicIpInt); + SUserObj *pUser = mgmtGetUser(connInfo.user); + if (pUser == NULL) { + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_INVALID_USER); + return; + } + + SCMMultiTableInfoMsg *pInfo = pMsg->pCont; + pInfo->numOfTables = htonl(pInfo->numOfTables); + + int32_t totalMallocLen = 4*1024*1024; // first malloc 4 MB, subsequent reallocation as twice + SMultiTableMeta *pMultiMeta = rpcMallocCont(totalMallocLen); + if (pMultiMeta == NULL) { + mgmtSendSimpleResp(pMsg->thandle, TSDB_CODE_SERV_OUT_OF_MEMORY); + return; + } + + pMultiMeta->contLen = sizeof(SMultiTableMeta); + pMultiMeta->numOfTables = 0; + + for (int t = 0; t < pInfo->numOfTables; ++t) { + char *tableId = (char*)(pInfo->tableIds + t * TSDB_TABLE_ID_LEN); + SChildTableObj *pTable = mgmtGetChildTable(tableId); + if (pTable == NULL) continue; + + SDbObj *pDb = mgmtGetDbByTableId(tableId); + if (pDb == NULL) continue; + + int availLen = totalMallocLen - pMultiMeta->contLen; + if (availLen <= sizeof(STableMetaMsg) + sizeof(SSchema) * TSDB_MAX_COLUMNS) { + //TODO realloc + //totalMallocLen *= 2; + //pMultiMeta = rpcReMalloc(pMultiMeta, totalMallocLen); + //if (pMultiMeta == NULL) { + /// rpcSendResponse(ahandle, TSDB_CODE_SERV_OUT_OF_MEMORY, NULL, 0); + // return TSDB_CODE_SERV_OUT_OF_MEMORY; + //} else { + // t--; + // continue; + //} + } + + STableMetaMsg *pMeta = (STableMetaMsg *)(pMultiMeta->metas + pMultiMeta->contLen); + int32_t code = mgmtDoGetChildTableMeta(pDb, pTable, pMeta, usePublicIp); + if (code == TSDB_CODE_SUCCESS) { + pMultiMeta->numOfTables ++; + pMultiMeta->contLen += pMeta->contLen; + } + } + + SRpcMsg rpcRsp = {0}; + rpcRsp.handle = pMsg->thandle; + rpcRsp.pCont = pMultiMeta; + rpcRsp.contLen = pMultiMeta->contLen; + rpcSendResponse(&rpcRsp); +} + +static int32_t mgmtGetShowTableMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { + SDbObj *pDb = mgmtGetDb(pShow->db); + if (pDb == NULL) { + return TSDB_CODE_DB_NOT_SELECTED; + } + + int32_t cols = 0; + SSchema *pSchema = pMeta->schema; + + pShow->bytes[cols] = TSDB_TABLE_NAME_LEN; + pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + strcpy(pSchema[cols].name, "table name"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 8; + pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; + strcpy(pSchema[cols].name, "create time"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 2; + pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; + strcpy(pSchema[cols].name, "columns"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = TSDB_TABLE_NAME_LEN; + pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + strcpy(pSchema[cols].name, "stable name"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pMeta->numOfColumns = htons(cols); + pShow->numOfColumns = cols; + + pShow->offset[0] = 0; + for (int32_t i = 1; i < cols; ++i) { + pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; + } + + pShow->numOfRows = pDb->numOfTables; + pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; + + return 0; +} + +static void mgmtVacuumResult(char *data, int32_t numOfCols, int32_t rows, int32_t capacity, SShowObj *pShow) { + if (rows < capacity) { + for (int32_t i = 0; i < numOfCols; ++i) { + memmove(data + pShow->offset[i] * rows, data + pShow->offset[i] * capacity, pShow->bytes[i] * rows); + } + } +} + +static int32_t mgmtRetrieveShowTables(SShowObj *pShow, char *data, int32_t rows, void *pConn) { + SDbObj *pDb = mgmtGetDb(pShow->db); + if (pDb == NULL) return 0; + + SUserObj *pUser = mgmtGetUserFromConn(pConn, NULL); + if (pUser == NULL) return 0; + + if (mgmtCheckIsMonitorDB(pDb->name, tsMonitorDbName)) { + if (strcmp(pUser->user, "root") != 0 && strcmp(pUser->user, "_root") != 0 && + strcmp(pUser->user, "monitor") != 0) { + return 0; + } + } + + int32_t numOfRows = 0; + SChildTableObj *pTable = NULL; + SPatternCompareInfo info = PATTERN_COMPARE_INFO_INITIALIZER; + + char prefix[64] = {0}; + strcpy(prefix, pDb->name); + strcat(prefix, TS_PATH_DELIMITER); + int32_t prefixLen = strlen(prefix); + + while (numOfRows < rows) { + pShow->pNode = sdbFetchRow(tsChildTableSdb, pShow->pNode, (void **) &pTable); + if (pTable == NULL) break; + + // not belong to current db + if (strncmp(pTable->info.tableId, prefix, prefixLen)) { + continue; + } + + char tableName[TSDB_TABLE_NAME_LEN] = {0}; + memset(tableName, 0, tListLen(tableName)); + + // pattern compare for meter name + mgmtExtractTableName(pTable->info.tableId, tableName); + + if (pShow->payloadLen > 0 && + patternMatch(pShow->payload, tableName, TSDB_TABLE_NAME_LEN, &info) != TSDB_PATTERN_MATCH) { + continue; + } + + int32_t cols = 0; + + char *pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + strncpy(pWrite, tableName, TSDB_TABLE_NAME_LEN); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int64_t *) pWrite = pTable->createdTime; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + if (pTable->info.type == TSDB_CHILD_TABLE) { + *(int16_t *)pWrite = pTable->superTable->numOfColumns; + } else { + *(int16_t *)pWrite = pTable->numOfColumns; + } + + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + if (pTable->info.type == TSDB_CHILD_TABLE) { + mgmtExtractTableName(pTable->superTableId, pWrite); + } + cols++; + + numOfRows++; + } + + pShow->numOfReads += numOfRows; + const int32_t NUM_OF_COLUMNS = 4; + + mgmtVacuumResult(data, NUM_OF_COLUMNS, numOfRows, rows, pShow); + + return numOfRows; +} + +void mgmtAlterChildTable(SQueuedMsg *pMsg, SChildTableObj *pTable) { + int32_t code = TSDB_CODE_OPS_NOT_SUPPORT; + SCMAlterTableMsg *pAlter = pMsg->pCont;; + + if (pAlter->type == TSDB_ALTER_TABLE_UPDATE_TAG_VAL) { + code = mgmtModifyChildTableTagValueByName(pTable, pAlter->schema[0].name, pAlter->tagVal); + } else if (pAlter->type == TSDB_ALTER_TABLE_ADD_COLUMN) { + code = mgmtAddNormalTableColumn(pTable, pAlter->schema, 1); + } else if (pAlter->type == TSDB_ALTER_TABLE_DROP_COLUMN) { + code = mgmtDropNormalTableColumnByName(pTable, pAlter->schema[0].name); + } else { + } + + mgmtSendSimpleResp(pMsg->thandle, code); } \ No newline at end of file diff --git a/src/mnode/src/mgmtUser.c b/src/mnode/src/mgmtUser.c index c497fd6e8fd9182c9790a9f4b9e4c3507e468b92..d630f899b1b3b63c70af971d3bdc720abb0ae7cc 100644 --- a/src/mnode/src/mgmtUser.c +++ b/src/mnode/src/mgmtUser.c @@ -48,6 +48,7 @@ static int32_t mgmtUserActionInsert(SSdbOperDesc *pOper) { if (pAcct != NULL) { acctAddUser(pAcct, pUser); + mgmtIncUserRef(pUser); } else { mError("user:%s, acct:%s info not exist in sdb", pUser->user, pUser->acct); @@ -63,6 +64,7 @@ static int32_t mgmtUserActionDelete(SSdbOperDesc *pOper) { if (pAcct != NULL) { acctRemoveUser(pAcct, pUser); + mgmtDecUserRef(pUser); } return TSDB_CODE_SUCCESS; @@ -139,6 +141,14 @@ SUserObj *mgmtGetUser(char *name) { return (SUserObj *)sdbGetRow(tsUserSdb, name); } +void mgmtIncUserRef(SUserObj *pUser) { + return sdbIncRef(tsUserSdb, pUser); +} + +void mgmtDecUserRef(SUserObj *pUser) { + return sdbDecRef(tsUserSdb, pUser); +} + static int32_t mgmtUpdateUser(SUserObj *pUser) { SSdbOperDesc oper = { .type = SDB_OPER_TYPE_GLOBAL, diff --git a/src/mnode/src/mgmtVgroup.c b/src/mnode/src/mgmtVgroup.c index 59880d204dd7d945f4deae35757516361f6e9989..972f1c427cc84907188e0a9cbbeb4a3a45744819 100644 --- a/src/mnode/src/mgmtVgroup.c +++ b/src/mnode/src/mgmtVgroup.c @@ -20,7 +20,6 @@ #include "tstatus.h" #include "mnode.h" #include "mgmtBalance.h" -#include "mgmtChildTable.h" #include "mgmtDb.h" #include "mgmtDClient.h" #include "mgmtDnode.h" @@ -278,16 +277,16 @@ int32_t mgmtGetVgroupMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { int32_t maxReplica = 0; SVgObj *pVgroup = NULL; - SChildTableObj *pTable = NULL; + STableInfo *pTable = NULL; if (pShow->payloadLen > 0 ) { - pTable = mgmtGetChildTable(pShow->payload); - if (NULL == pTable) { + pTable = mgmtGetTable(pShow->payload); + if (NULL == pTable || pTable->type == TSDB_SUPER_TABLE) { return TSDB_CODE_INVALID_TABLE_ID; } - pVgroup = mgmtGetVgroup(pTable->vgId); + pVgroup = mgmtGetVgroup(((SChildTableObj*)pTable)->vgId); if (NULL == pVgroup) return TSDB_CODE_INVALID_TABLE_ID; - + mgmtDecTableRef(pTable); maxReplica = pVgroup->numOfVnodes > maxReplica ? pVgroup->numOfVnodes : maxReplica; } else { SVgObj *pVgroup = pDb->pHead;