From b4fce76b27167489dea1c71a5198685848e2db26 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 00:04:07 +0800 Subject: [PATCH 01/47] [td-225] fix bugs in query. and refactor some codes. --- src/client/inc/tsclient.h | 2 +- src/client/src/tscSystem.c | 2 +- src/query/inc/qExecutor.h | 2 +- src/query/inc/qResultbuf.h | 19 ++- src/query/inc/{qsqlparser.h => qSqlparser.h} | 0 src/query/src/qAst.c | 2 +- src/query/src/qExecutor.c | 14 +- src/query/src/qParserImpl.c | 2 +- src/query/src/qResultbuf.c | 28 ++-- src/query/src/sql.c | 2 +- src/tsdb/src/tsdbRead.c | 162 ++++++++++--------- src/util/src/tcache.c | 1 + 12 files changed, 127 insertions(+), 109 deletions(-) rename src/query/inc/{qsqlparser.h => qSqlparser.h} (100%) diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 17840df4a4..7efcd54cfd 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -31,8 +31,8 @@ extern "C" { #include "tutil.h" #include "qExecutor.h" +#include "qSqlparser.h" #include "qTsbuf.h" -#include "qsqlparser.h" #include "tcmdtype.h" // forward declaration diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index 5662b4a885..42bf27c45a 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -148,7 +148,7 @@ void taos_init_imp() { refreshTime = refreshTime < 10 ? 10 : refreshTime; if (tscCacheHandle == NULL) { - tscCacheHandle = taosCacheInit(TSDB_DATA_TYPE_BINARY, refreshTime, false, NULL, "client"); + tscCacheHandle = taosCacheInit(TSDB_DATA_TYPE_BINARY, refreshTime, false, NULL, "tableMeta"); } tscDebug("client is initialized successfully"); diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index 127c38a6f8..92fe078c3f 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -20,8 +20,8 @@ #include "hash.h" #include "qFill.h" #include "qResultbuf.h" +#include "qSqlparser.h" #include "qTsbuf.h" -#include "qsqlparser.h" #include "query.h" #include "taosdef.h" #include "tarray.h" diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index 8c8afb0957..d9da6bb63e 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -13,8 +13,8 @@ * along with this program. If not, see . */ -#ifndef TDENGINE_VNODEQUERYUTIL_H -#define TDENGINE_VNODEQUERYUTIL_H +#ifndef TDENGINE_QRESULTBUF_H +#define TDENGINE_QRESULTBUF_H #ifdef __cplusplus extern "C" { @@ -26,11 +26,18 @@ extern "C" { typedef struct SArray* SIDList; +typedef struct SPageInfo { + int32_t pageId; + int32_t offset; + int32_t lengthOnDisk; +} SPageInfo; + typedef struct SDiskbasedResultBuf { int32_t numOfRowsPerPage; int32_t numOfPages; int64_t totalBufSize; - int32_t fd; // data file fd + FILE* file; +// int32_t fd; // data file fd int32_t allocateId; // allocated page id int32_t incStep; // minimum allocated pages void* pBuf; // mmap buffer pointer @@ -43,6 +50,8 @@ typedef struct SDiskbasedResultBuf { void* iBuf; // inmemory buf void* handle; // for debug purpose void* emptyDummyIdList; // dummy id list + bool comp; + } SDiskbasedResultBuf; #define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) @@ -56,7 +65,7 @@ typedef struct SDiskbasedResultBuf { * @return */ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t numOfPages, int32_t rowSize, int32_t pagesize, - int32_t inMemPages, void* handle); + int32_t inMemPages, const void* handle); /** * @@ -126,4 +135,4 @@ int32_t getLastPageId(SIDList pList); } #endif -#endif // TDENGINE_VNODEQUERYUTIL_H +#endif // TDENGINE_QRESULTBUF_H diff --git a/src/query/inc/qsqlparser.h b/src/query/inc/qSqlparser.h similarity index 100% rename from src/query/inc/qsqlparser.h rename to src/query/inc/qSqlparser.h diff --git a/src/query/src/qAst.c b/src/query/src/qAst.c index c2578c15c0..e3c0c1dbb0 100644 --- a/src/query/src/qAst.c +++ b/src/query/src/qAst.c @@ -18,8 +18,8 @@ #include "exception.h" #include "qAst.h" +#include "qSqlparser.h" #include "qSyntaxtreefunction.h" -#include "qsqlparser.h" #include "taosdef.h" #include "taosmsg.h" #include "tarray.h" diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 906d0cfe67..30d6cc288f 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6617,14 +6617,16 @@ void* qOpenQueryMgmt(int32_t vgId) { char cacheName[128] = {0}; sprintf(cacheName, "qhandle_%d", vgId); - SQueryMgmt* pQueryHandle = calloc(1, sizeof(SQueryMgmt)); + SQueryMgmt* pQueryMgmt = calloc(1, sizeof(SQueryMgmt)); - pQueryHandle->qinfoPool = taosCacheInit(TSDB_DATA_TYPE_BIGINT, REFRESH_HANDLE_INTERVAL, true, freeqinfoFn, cacheName); - pQueryHandle->closed = false; - pthread_mutex_init(&pQueryHandle->lock, NULL); + pQueryMgmt->qinfoPool = taosCacheInit(TSDB_DATA_TYPE_BIGINT, REFRESH_HANDLE_INTERVAL, true, freeqinfoFn, cacheName); + pQueryMgmt->closed = false; + pQueryMgmt->vgId = vgId; + + pthread_mutex_init(&pQueryMgmt->lock, NULL); qDebug("vgId:%d, open querymgmt success", vgId); - return pQueryHandle; + return pQueryMgmt; } static void queryMgmtKillQueryFn(void* handle) { @@ -6664,7 +6666,7 @@ void qCleanupQueryMgmt(void* pQMgmt) { pthread_mutex_destroy(&pQueryMgmt->lock); tfree(pQueryMgmt); - qDebug("vgId:%d querymgmt cleanup completed", vgId); + qDebug("vgId:%d queryMgmt cleanup completed", vgId); } void** qRegisterQInfo(void* pMgmt, uint64_t qInfo) { diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index ecc11f8f4d..1e58dbbe0b 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -14,7 +14,7 @@ */ #include "os.h" -#include "qsqlparser.h" +#include "qSqlparser.h" #include "queryLog.h" #include "taosdef.h" #include "taosmsg.h" diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index de59676e59..2443381194 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -5,7 +5,7 @@ #include "taoserror.h" int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t numOfPages, int32_t rowSize, - int32_t pagesize, int32_t inMemPages, void* handle) { + int32_t pagesize, int32_t inMemPages, const void* handle) { *pResultBuf = calloc(1, sizeof(SDiskbasedResultBuf)); SDiskbasedResultBuf* pResBuf = *pResultBuf; @@ -24,6 +24,7 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu pResBuf->incStep = 4; pResBuf->allocateId = -1; + // todo opt perf by on demand create in memory buffer pResBuf->iBuf = calloc(pResBuf->inMemPages, pResBuf->pageSize); // init id hash table @@ -31,10 +32,10 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu pResBuf->list = taosArrayInit(numOfPages, POINTER_BYTES); char path[PATH_MAX] = {0}; - getTmpfilePath("tsdb_qbuf", path); + getTmpfilePath("qbuf", path); pResBuf->path = strdup(path); - pResBuf->fd = FD_INITIALIZER; + pResBuf->file = NULL; pResBuf->pBuf = NULL; pResBuf->emptyDummyIdList = taosArrayInit(1, sizeof(int32_t)); @@ -52,8 +53,9 @@ int32_t getResBufSize(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->tota #define FILE_SIZE_ON_DISK(_r) (NUM_OF_PAGES_ON_DISK(_r) * (_r)->pageSize) static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { - pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); - if (!FD_VALID(pResultBuf->fd)) { +// pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); + pResultBuf->file = fopen(pResultBuf->path, "r+"); + if (pResultBuf->file == NULL) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); } @@ -61,13 +63,15 @@ static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { assert(pResultBuf->numOfPages == pResultBuf->inMemPages); pResultBuf->numOfPages += pResultBuf->incStep; - int32_t ret = ftruncate(pResultBuf->fd, NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); + int32_t ret = ftruncate(fileno(pResultBuf->file), NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); if (ret != TSDB_CODE_SUCCESS) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); } - pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, pResultBuf->fd, 0); + pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, + fileno(pResultBuf->file), 0); + if (pResultBuf->pBuf == MAP_FAILED) { qError("QInfo:%p failed to map temp file: %s. %s", pResultBuf->handle, pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); @@ -82,7 +86,7 @@ static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNu int32_t ret = TSDB_CODE_SUCCESS; if (pResultBuf->pBuf == NULL) { - assert(pResultBuf->fd == FD_INITIALIZER); + assert(pResultBuf->file == NULL); if ((ret = createDiskResidesBuf(pResultBuf)) != TSDB_CODE_SUCCESS) { return ret; @@ -95,7 +99,7 @@ static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNu * disk-based output buffer is exhausted, try to extend the disk-based buffer, the available disk space may * be insufficient */ - ret = ftruncate(pResultBuf->fd, NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); + ret = ftruncate(fileno(pResultBuf->file), NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); if (ret != TSDB_CODE_SUCCESS) { // dError("QInfo:%p failed to create intermediate result output file:%s. %s", pQInfo, pSupporter->extBufFile, // strerror(errno)); @@ -103,7 +107,7 @@ static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNu } pResultBuf->totalBufSize = pResultBuf->numOfPages * pResultBuf->pageSize; - pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, pResultBuf->fd, 0); + pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, fileno(pResultBuf->file), 0); if (pResultBuf->pBuf == MAP_FAILED) { // dError("QInfo:%p failed to map temp file: %s. %s", pQInfo, pSupporter->extBufFile, strerror(errno)); @@ -185,11 +189,11 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { return; } - if (FD_VALID(pResultBuf->fd)) { + if (pResultBuf->file != NULL) { qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, file created:%s, file size:%d", handle, pResultBuf->totalBufSize, pResultBuf->path, FILE_SIZE_ON_DISK(pResultBuf)); - close(pResultBuf->fd); + fclose(pResultBuf->file); munmap(pResultBuf->pBuf, FILE_SIZE_ON_DISK(pResultBuf)); pResultBuf->pBuf = NULL; } else { diff --git a/src/query/src/sql.c b/src/query/src/sql.c index ac9952bb97..307d5203b3 100644 --- a/src/query/src/sql.c +++ b/src/query/src/sql.c @@ -30,7 +30,7 @@ #include #include #include -#include "qsqlparser.h" +#include "qSqlparser.h" #include "tcmdtype.h" #include "tstoken.h" #include "ttokendef.h" diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 37784577c4..3eeca85db7 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -654,8 +654,9 @@ static bool doLoadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlo int64_t elapsedTime = (taosGetTimestampUs() - st); pQueryHandle->cost.blockLoadTime += elapsedTime; - tsdbDebug("%p load file block into buffer, elapsed time:%"PRId64 " us", pQueryHandle, elapsedTime); + tsdbDebug("%p load file block into buffer, brange:%"PRId64"-%"PRId64" , rows:%d, elapsed time:%"PRId64 " us", + pQueryHandle, pBlock->keyFirst, pBlock->keyLast, pBlock->numOfRows, elapsedTime); return blockLoaded; } @@ -971,6 +972,52 @@ static void copyOneRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, } } +static void moveDataToFront(STsdbQueryHandle* pQueryHandle, int32_t numOfRows, int32_t numOfCols) { + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + return; + } + + // if the buffer is not full in case of descending order query, move the data in the front of the buffer + if (numOfRows < pQueryHandle->outputCapacity) { + int32_t emptySize = pQueryHandle->outputCapacity - numOfRows; + for(int32_t i = 0; i < numOfCols; ++i) { + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); + } + } +} + +static void getQualifiedRowsPos(STsdbQueryHandle* pQueryHandle, int32_t startPos, int32_t endPos, + int32_t numOfExisted, int32_t *start, int32_t *end) { + *start = -1; + + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + int32_t remain = endPos - startPos + 1; + if (remain + numOfExisted > pQueryHandle->outputCapacity) { + *end = (pQueryHandle->outputCapacity - numOfExisted) + startPos - 1; + } + + *start = startPos; + } else { + int32_t remain = (startPos - endPos) + 1; + if (remain + numOfExisted > pQueryHandle->outputCapacity) { + *end = startPos + 1 - (pQueryHandle->outputCapacity - numOfExisted); + } + + *start = *end; + *end = startPos; + } +} + +static void updateInfoAfterMerge(STsdbQueryHandle* pQueryHandle, STableCheckInfo* pCheckInfo, int32_t numOfRows, int32_t endPos) { + SQueryFilePos* cur = &pQueryHandle->cur; + + pCheckInfo->lastKey = cur->lastKey; + pQueryHandle->realNumOfRows = numOfRows; + cur->rows = numOfRows; + cur->pos = endPos; +} + // only return the qualified data to client in terms of query time window, data rows in the same block but do not // be included in the query time window will be discarded static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* pCheckInfo, SCompBlock* pBlock) { @@ -978,7 +1025,10 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* SDataBlockInfo blockInfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock); initTableMemIterator(pQueryHandle, pCheckInfo); + SDataCols* pCols = pQueryHandle->rhelper.pDataCols[0]; + assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == PRIMARYKEY_TIMESTAMP_COL_INDEX); + TSKEY* tsArray = pCols->cols[0].pData; // for search the endPos, so the order needs to reverse int32_t order = (pQueryHandle->order == TSDB_ORDER_ASC)? TSDB_ORDER_DESC:TSDB_ORDER_ASC; @@ -1004,9 +1054,6 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* // compared with the data from in-memory buffer, to generate the correct timestamp array list int32_t pos = cur->pos; - assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == 0); - TSKEY* tsArray = pCols->cols[0].pData; - int32_t numOfRows = 0; pQueryHandle->cur.win = TSWINDOW_INITIALIZER; @@ -1014,34 +1061,22 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* if (pCheckInfo->iiter == NULL && pCheckInfo->iter == NULL) { int32_t start = cur->pos; int32_t end = endPos; - if (!ASCENDING_TRAVERSE(pQueryHandle->order)) { - end = cur->pos; - start = endPos; - } - - cur->win.skey = tsArray[start]; - cur->win.ekey = tsArray[end]; - - // todo opt in case of no data in buffer - numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); - - // if the buffer is not full in case of descending order query, move the data in the front of the buffer - if (!ASCENDING_TRAVERSE(pQueryHandle->order) && numOfRows < pQueryHandle->outputCapacity) { - int32_t emptySize = pQueryHandle->outputCapacity - numOfRows; - for(int32_t i = 0; i < numOfCols; ++i) { - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); - memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); - } + if (!ASCENDING_TRAVERSE(pQueryHandle->order)) { + SWAP(start, end, int32_t); } - + + numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); + cur->win = (STimeWindow) {.skey = tsArray[start], .ekey = tsArray[end]}; + pos += (end - start + 1) * step; cur->blockCompleted = (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || ((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))); - - pCheckInfo->lastKey = cur->lastKey; - pQueryHandle->realNumOfRows = numOfRows; - cur->rows = numOfRows; + + // if the buffer is not full in case of descending order query, move the data in the front of the buffer + moveDataToFront(pQueryHandle, numOfRows, numOfCols); + updateInfoAfterMerge(pQueryHandle, pCheckInfo, numOfRows, pos); + return; } else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) { SSkipListNode* node = NULL; @@ -1087,27 +1122,15 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* if (tsArray[end] == key) { // the value of key in cache equals to the end timestamp value, ignore it moveToNextRowInMem(pCheckInfo); } - - int32_t start = -1; - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - int32_t remain = end - pos + 1; - if (remain + numOfRows > pQueryHandle->outputCapacity) { - end = (pQueryHandle->outputCapacity - numOfRows) + pos - 1; - } - start = pos; - } else { - int32_t remain = (pos - end) + 1; - if (remain + numOfRows > pQueryHandle->outputCapacity) { - end = pos + 1 - (pQueryHandle->outputCapacity - numOfRows); - } + int32_t qstart = 0, qend = 0; + getQualifiedRowsPos(pQueryHandle, pos, end, numOfRows, &qstart, &qend); - start = end; - end = pos; - } + numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, qstart, qend); + pos += (qend - qstart + 1) * step; - numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); - pos += (end - start + 1) * step; + cur->win.ekey = tsArray[end]; + cur->lastKey = cur->win.ekey + step; } } while (numOfRows < pQueryHandle->outputCapacity); @@ -1124,30 +1147,14 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* cur->win.skey = tsArray[pos]; } - int32_t start = -1; - int32_t end = -1; - - // all remain data are qualified, but check the remain capacity in the first place. - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - int32_t remain = endPos - pos + 1; - if (remain + numOfRows > pQueryHandle->outputCapacity) { - endPos = (pQueryHandle->outputCapacity - numOfRows) + pos - 1; - } - - start = pos; - end = endPos; - } else { - int32_t remain = pos + 1; - if (remain + numOfRows > pQueryHandle->outputCapacity) { - endPos = pos + 1 - (pQueryHandle->outputCapacity - numOfRows); - } - - start = endPos; - end = pos; - } + int32_t start = -1, end = -1; + getQualifiedRowsPos(pQueryHandle, pos, endPos, numOfRows, &start, &end); numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); pos += (end - start + 1) * step; + + cur->win.ekey = tsArray[end]; + cur->lastKey = cur->win.ekey + step; } } } @@ -1157,21 +1164,16 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* if (!ASCENDING_TRAVERSE(pQueryHandle->order)) { SWAP(cur->win.skey, cur->win.ekey, TSKEY); - - // if the buffer is not full in case of descending order query, move the data in the front of the buffer - if (numOfRows < pQueryHandle->outputCapacity) { - int32_t emptySize = pQueryHandle->outputCapacity - numOfRows; - for(int32_t i = 0; i < numOfCols; ++i) { - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); - memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); - } - } } - - pCheckInfo->lastKey = cur->lastKey; - pQueryHandle->realNumOfRows = numOfRows; - cur->rows = numOfRows; - cur->pos = pos; + + moveDataToFront(pQueryHandle, numOfRows, numOfCols); + updateInfoAfterMerge(pQueryHandle, pCheckInfo, numOfRows, pos); + + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + assert(cur->win.skey >= pQueryHandle->window.skey && cur->win.ekey <= pQueryHandle->window.ekey); + } else { + assert(cur->win.skey >= pQueryHandle->window.ekey && cur->win.ekey <= pQueryHandle->window.skey); + } tsdbDebug("%p uid:%" PRIu64",tid:%d data block created, brange:%"PRIu64"-%"PRIu64" rows:%d, %p", pQueryHandle, pCheckInfo->tableId.uid, pCheckInfo->tableId.tid, cur->win.skey, cur->win.ekey, cur->rows, pQueryHandle->qinfo); diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 92d4b2caac..89199f035d 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -674,6 +674,7 @@ void* taosCacheTimedRefresh(void *handle) { // check if current cache object will be deleted every 500ms. if (pCacheObj->deleting) { + uDebug("%s refresh threads quit", pCacheObj->name); break; } From 431945fa2def3ed582d35a51846136cf9516df55 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 00:37:12 +0800 Subject: [PATCH 02/47] [td-225] fix bugs in query. --- src/query/inc/qResultbuf.h | 1 - src/tsdb/src/tsdbRead.c | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index d9da6bb63e..e8b3af7ccf 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -37,7 +37,6 @@ typedef struct SDiskbasedResultBuf { int32_t numOfPages; int64_t totalBufSize; FILE* file; -// int32_t fd; // data file fd int32_t allocateId; // allocated page id int32_t incStep; // minimum allocated pages void* pBuf; // mmap buffer pointer diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 3eeca85db7..71d3fd9cc4 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -995,6 +995,8 @@ static void getQualifiedRowsPos(STsdbQueryHandle* pQueryHandle, int32_t startPos int32_t remain = endPos - startPos + 1; if (remain + numOfExisted > pQueryHandle->outputCapacity) { *end = (pQueryHandle->outputCapacity - numOfExisted) + startPos - 1; + } else { + *end = endPos; } *start = startPos; @@ -1002,6 +1004,8 @@ static void getQualifiedRowsPos(STsdbQueryHandle* pQueryHandle, int32_t startPos int32_t remain = (startPos - endPos) + 1; if (remain + numOfExisted > pQueryHandle->outputCapacity) { *end = startPos + 1 - (pQueryHandle->outputCapacity - numOfExisted); + } else { + *end = endPos; } *start = *end; From ae65941ce8945f0c21c550260c43292f9e5449be Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 11:33:31 +0800 Subject: [PATCH 03/47] [td-225] add check --- src/tsdb/src/tsdbRead.c | 344 ++++++++++++++++++++-------------------- 1 file changed, 175 insertions(+), 169 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 71d3fd9cc4..1d15860912 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -198,38 +198,38 @@ TsdbQueryHandleT* tsdbQueryTables(TSDB_REPO_T* tsdb, STsdbQueryCond* pCond, STab // allocate buffer in order to load data blocks from file int32_t numOfCols = pCond->numOfCols; - + pQueryHandle->statis = calloc(numOfCols, sizeof(SDataStatis)); pQueryHandle->pColumns = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); // todo: use list instead of array? - + for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData colInfo = {{0}, 0}; - + colInfo.info = pCond->colList[i]; colInfo.pData = calloc(1, EXTRA_BYTES + pQueryHandle->outputCapacity * pCond->colList[i].bytes); taosArrayPush(pQueryHandle->pColumns, &colInfo); pQueryHandle->statis[i].colId = colInfo.info.colId; } - + pQueryHandle->pTableCheckInfo = taosArrayInit(groupList->numOfTables, sizeof(STableCheckInfo)); STsdbMeta* pMeta = tsdbGetMeta(tsdb); assert(pMeta != NULL); - + for (int32_t i = 0; i < sizeOfGroup; ++i) { SArray* group = *(SArray**) taosArrayGet(groupList->pGroupList, i); - + size_t gsize = taosArrayGetSize(group); assert(gsize > 0); - + for (int32_t j = 0; j < gsize; ++j) { STable* pTable = (STable*) taosArrayGetP(group, j); - + STableCheckInfo info = { .lastKey = pQueryHandle->window.skey, .tableId = pTable->tableId, .pTableObj = pTable, }; - + assert(info.pTableObj != NULL && (info.pTableObj->type == TSDB_NORMAL_TABLE || info.pTableObj->type == TSDB_CHILD_TABLE || info.pTableObj->type == TSDB_STREAM_TABLE)); @@ -259,17 +259,17 @@ TsdbQueryHandleT tsdbQueryLastRow(TSDB_REPO_T *tsdb, STsdbQueryCond *pCond, STab SArray* tsdbGetQueriedTableList(TsdbQueryHandleT *pHandle) { assert(pHandle != NULL); - + STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) pHandle; - + size_t size = taosArrayGetSize(pQueryHandle->pTableCheckInfo); SArray* res = taosArrayInit(size, POINTER_BYTES); - + for(int32_t i = 0; i < size; ++i) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); taosArrayPush(res, &pCheckInfo->pTableObj); } - + return res; } @@ -285,11 +285,11 @@ TsdbQueryHandleT tsdbQueryRowsInExternalWindow(TSDB_REPO_T *tsdb, STsdbQueryCond static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCheckInfo) { STable* pTable = pCheckInfo->pTableObj; assert(pTable != NULL); - + if (pCheckInfo->initBuf) { return true; } - + pCheckInfo->initBuf = true; int32_t order = pHandle->order; @@ -297,34 +297,34 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh if (pHandle->mem == NULL && pHandle->imem == NULL) { return false; } - + assert(pCheckInfo->iter == NULL && pCheckInfo->iiter == NULL); - + if (pHandle->mem && pHandle->mem->tData[pCheckInfo->tableId.tid] != NULL) { pCheckInfo->iter = tSkipListCreateIterFromVal(pHandle->mem->tData[pCheckInfo->tableId.tid]->pData, (const char*) &pCheckInfo->lastKey, TSDB_DATA_TYPE_TIMESTAMP, order); } - + if (pHandle->imem && pHandle->imem->tData[pCheckInfo->tableId.tid] != NULL) { pCheckInfo->iiter = tSkipListCreateIterFromVal(pHandle->imem->tData[pCheckInfo->tableId.tid]->pData, (const char*) &pCheckInfo->lastKey, TSDB_DATA_TYPE_TIMESTAMP, order); } - + // both iterators are NULL, no data in buffer right now if (pCheckInfo->iter == NULL && pCheckInfo->iiter == NULL) { return false; } - + bool memEmpty = (pCheckInfo->iter == NULL) || (pCheckInfo->iter != NULL && !tSkipListIterNext(pCheckInfo->iter)); bool imemEmpty = (pCheckInfo->iiter == NULL) || (pCheckInfo->iiter != NULL && !tSkipListIterNext(pCheckInfo->iiter)); if (memEmpty && imemEmpty) { // buffer is empty return false; } - + if (!memEmpty) { SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter); assert(node != NULL); - + SDataRow row = SL_GET_NODE_DATA(node); TSKEY key = dataRowKey(row); // first timestamp in buffer tsdbDebug("%p uid:%" PRId64", tid:%d check data in mem from skey:%" PRId64 ", order:%d, %p", pHandle, @@ -333,11 +333,11 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh tsdbDebug("%p uid:%"PRId64", tid:%d no data in mem, %p", pHandle, pCheckInfo->tableId.uid, pCheckInfo->tableId.tid, pHandle->qinfo); } - + if (!imemEmpty) { SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter); assert(node != NULL); - + SDataRow row = SL_GET_NODE_DATA(node); TSKEY key = dataRowKey(row); // first timestamp in buffer tsdbDebug("%p uid:%" PRId64", tid:%d check data in imem from skey:%" PRId64 ", order:%d, %p", pHandle, @@ -346,7 +346,7 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh tsdbDebug("%p uid:%"PRId64", tid:%d no data in imem, %p", pHandle, pCheckInfo->tableId.uid, pCheckInfo->tableId.tid, pHandle->qinfo); } - + return true; } @@ -449,7 +449,7 @@ static bool hasMoreDataInCache(STsdbQueryHandle* pHandle) { size_t size = taosArrayGetSize(pHandle->pTableCheckInfo); assert(pHandle->activeIndex < size && pHandle->activeIndex >= 0 && size >= 1); pHandle->cur.fid = -1; - + STableCheckInfo* pCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex); STable* pTable = pCheckInfo->pTableObj; @@ -467,17 +467,17 @@ static bool hasMoreDataInCache(STsdbQueryHandle* pHandle) { pCheckInfo->lastKey = dataRowKey(row); // first timestamp in buffer tsdbDebug("%p uid:%" PRId64", tid:%d check data in buffer from skey:%" PRId64 ", order:%d, %p", pHandle, pCheckInfo->tableId.uid, pCheckInfo->tableId.tid, pCheckInfo->lastKey, pHandle->order, pHandle->qinfo); - + // all data in mem are checked already. if ((pCheckInfo->lastKey > pHandle->window.ekey && ASCENDING_TRAVERSE(pHandle->order)) || (pCheckInfo->lastKey < pHandle->window.ekey && !ASCENDING_TRAVERSE(pHandle->order))) { return false; } - + int32_t step = ASCENDING_TRAVERSE(pHandle->order)? 1:-1; STimeWindow* win = &pHandle->cur.win; pHandle->cur.rows = tsdbReadRowsFromCache(pCheckInfo, pHandle->window.ekey, pHandle->outputCapacity, win, pHandle); - + // update the last key value pCheckInfo->lastKey = win->ekey + step; pHandle->cur.lastKey = win->ekey + step; @@ -486,7 +486,7 @@ static bool hasMoreDataInCache(STsdbQueryHandle* pHandle) { if (!ASCENDING_TRAVERSE(pHandle->order)) { SWAP(win->skey, win->ekey, TSKEY); } - + return true; } @@ -495,31 +495,31 @@ static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precisio if (key == TSKEY_INITIAL_VAL) { return INT32_MIN; } - + int64_t fid = (int64_t)(key / (daysPerFile * tsMsPerDay[precision])); // set the starting fileId if (fid < 0L && llabs(fid) > INT32_MAX) { // data value overflow for INT32 fid = INT32_MIN; } - + if (fid > 0L && fid > INT32_MAX) { fid = INT32_MAX; } - + return fid; } static int32_t binarySearchForBlock(SCompBlock* pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) { int32_t firstSlot = 0; int32_t lastSlot = numOfBlocks - 1; - + int32_t midSlot = firstSlot; - + while (1) { numOfBlocks = lastSlot - firstSlot + 1; midSlot = (firstSlot + (numOfBlocks >> 1)); - + if (numOfBlocks == 1) break; - + if (skey > pBlock[midSlot].keyLast) { if (numOfBlocks == 2) break; if ((order == TSDB_ORDER_DESC) && (skey < pBlock[midSlot + 1].keyFirst)) break; @@ -531,7 +531,7 @@ static int32_t binarySearchForBlock(SCompBlock* pBlock, int32_t numOfBlocks, TSK break; // got the slot } } - + return midSlot; } @@ -669,10 +669,10 @@ static void handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SCompBlock* TSKEY key = (row != NULL)? dataRowKey(row):TSKEY_INITIAL_VAL; cur->pos = ASCENDING_TRAVERSE(pQueryHandle->order)? 0:(binfo.rows-1); - + if ((ASCENDING_TRAVERSE(pQueryHandle->order) && (key != TSKEY_INITIAL_VAL && key <= binfo.window.ekey)) || (!ASCENDING_TRAVERSE(pQueryHandle->order) && (key != TSKEY_INITIAL_VAL && key >= binfo.window.skey))) { - + if ((ASCENDING_TRAVERSE(pQueryHandle->order) && (key != TSKEY_INITIAL_VAL && key < binfo.window.skey)) || (!ASCENDING_TRAVERSE(pQueryHandle->order) && (key != TSKEY_INITIAL_VAL && key > binfo.window.ekey))) { @@ -688,12 +688,12 @@ static void handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SCompBlock* if (!ASCENDING_TRAVERSE(pQueryHandle->order)) { SWAP(cur->win.skey, cur->win.ekey, TSKEY); } - + cur->mixBlock = true; cur->blockCompleted = false; return; } - + doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo); doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock); } else { @@ -727,14 +727,14 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock SDataCols* pTSCol = pQueryHandle->rhelper.pDataCols[0]; assert(pTSCol->cols->type == TSDB_DATA_TYPE_TIMESTAMP && pTSCol->numOfRows == pBlock->numOfRows); - + if (pCheckInfo->lastKey > pBlock->keyFirst) { cur->pos = binarySearchForKey(pTSCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pQueryHandle->order); } else { cur->pos = 0; } - + doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock); } else { // the whole block is loaded in to buffer handleDataMergeIfNeeded(pQueryHandle, pBlock, pCheckInfo); @@ -744,14 +744,14 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock if (!doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo)) { return false; } - + SDataCols* pTSCol = pQueryHandle->rhelper.pDataCols[0]; if (pCheckInfo->lastKey < pBlock->keyLast) { cur->pos = binarySearchForKey(pTSCol->cols[0].pData, pBlock->numOfRows, pCheckInfo->lastKey, pQueryHandle->order); } else { cur->pos = pBlock->numOfRows - 1; } - + doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock); } else { handleDataMergeIfNeeded(pQueryHandle, pBlock, pCheckInfo); @@ -767,7 +767,7 @@ static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) { TSKEY* keyList; assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC); - + if (num <= 0) return -1; keyList = (TSKEY*)pValue; @@ -826,13 +826,13 @@ static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) { static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, int32_t start, int32_t end) { char* pData = NULL; int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1 : -1; - + SDataCols* pCols = pQueryHandle->rhelper.pDataCols[0]; TSKEY* tsArray = pCols->cols[0].pData; - + int32_t num = end - start + 1; int32_t requiredNumOfCols = taosArrayGetSize(pQueryHandle->pColumns); - + //data in buffer has greater timestamp, copy data in file block int32_t i = 0, j = 0; while(i < requiredNumOfCols && j < pCols->numOfCols) { @@ -905,7 +905,7 @@ static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t cap i++; } - + pQueryHandle->cur.win.ekey = tsArray[end]; pQueryHandle->cur.lastKey = tsArray[end] + step; @@ -1027,7 +1027,7 @@ static void updateInfoAfterMerge(STsdbQueryHandle* pQueryHandle, STableCheckInfo static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* pCheckInfo, SCompBlock* pBlock) { SQueryFilePos* cur = &pQueryHandle->cur; SDataBlockInfo blockInfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlock); - + initTableMemIterator(pQueryHandle, pCheckInfo); SDataCols* pCols = pQueryHandle->rhelper.pDataCols[0]; @@ -1038,7 +1038,7 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* int32_t order = (pQueryHandle->order == TSDB_ORDER_ASC)? TSDB_ORDER_DESC:TSDB_ORDER_ASC; int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; - int32_t numOfCols = taosArrayGetSize(pQueryHandle->pColumns); + int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); STable* pTable = pCheckInfo->pTableObj; @@ -1054,12 +1054,11 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* endPos = doBinarySearchKey(pCols->cols[0].pData, pCols->numOfRows, pQueryHandle->window.ekey, order); cur->mixBlock = true; } - + // compared with the data from in-memory buffer, to generate the correct timestamp array list - int32_t pos = cur->pos; - int32_t numOfRows = 0; - pQueryHandle->cur.win = TSWINDOW_INITIALIZER; + int32_t pos = cur->pos; + cur->win = TSWINDOW_INITIALIZER; // no data in buffer, load data from file directly if (pCheckInfo->iiter == NULL && pCheckInfo->iter == NULL) { @@ -1069,13 +1068,16 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* if (!ASCENDING_TRAVERSE(pQueryHandle->order)) { SWAP(start, end, int32_t); } - - numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); - cur->win = (STimeWindow) {.skey = tsArray[start], .ekey = tsArray[end]}; + numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); + + // the time window should always be right order: skey <= ekey + cur->win = (STimeWindow) {.skey = tsArray[start], .ekey = tsArray[end]}; pos += (end - start + 1) * step; - cur->blockCompleted = (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || - ((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))); + + cur->blockCompleted = + (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || + ((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))); // if the buffer is not full in case of descending order query, move the data in the front of the buffer moveDataToFront(pQueryHandle, numOfRows, numOfCols); @@ -1133,11 +1135,11 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, qstart, qend); pos += (qend - qstart + 1) * step; - cur->win.ekey = tsArray[end]; + cur->win.ekey = ASCENDING_TRAVERSE(pQueryHandle->order)? tsArray[qend]:tsArray[qstart]; cur->lastKey = cur->win.ekey + step; } } while (numOfRows < pQueryHandle->outputCapacity); - + if (numOfRows < pQueryHandle->outputCapacity) { /** * if cache is empty, load remain file block data. In contrast, if there are remain data in cache, do NOT @@ -1157,14 +1159,15 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* numOfRows = copyDataFromFileBlock(pQueryHandle, pQueryHandle->outputCapacity, numOfRows, start, end); pos += (end - start + 1) * step; - cur->win.ekey = tsArray[end]; + cur->win.ekey = ASCENDING_TRAVERSE(pQueryHandle->order)? tsArray[end]:tsArray[start]; cur->lastKey = cur->win.ekey + step; } } } - - cur->blockCompleted = (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || - ((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))); + + cur->blockCompleted = + (((pos >= endPos || cur->lastKey > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || + ((pos <= endPos || cur->lastKey < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))); if (!ASCENDING_TRAVERSE(pQueryHandle->order)) { SWAP(cur->win.skey, cur->win.ekey, TSKEY); @@ -1179,6 +1182,9 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* assert(cur->win.skey >= pQueryHandle->window.ekey && cur->win.ekey <= pQueryHandle->window.skey); } + SColumnInfoData* pColInfoData = taosArrayGet(pQueryHandle->pColumns, 0); + assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] && cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows-1]); + tsdbDebug("%p uid:%" PRIu64",tid:%d data block created, brange:%"PRIu64"-%"PRIu64" rows:%d, %p", pQueryHandle, pCheckInfo->tableId.uid, pCheckInfo->tableId.tid, cur->win.skey, cur->win.ekey, cur->rows, pQueryHandle->qinfo); } @@ -1314,16 +1320,16 @@ static int32_t createDataBlocksInfo(STsdbQueryHandle* pQueryHandle, int32_t numO cleanBlockOrderSupporter(&sup, 0); return TSDB_CODE_TDB_OUT_OF_MEMORY; } - + int32_t cnt = 0; int32_t numOfQualTables = 0; - + for (int32_t j = 0; j < numOfTables; ++j) { STableCheckInfo* pTableCheck = (STableCheckInfo*)taosArrayGet(pQueryHandle->pTableCheckInfo, j); if (pTableCheck->numOfBlocks <= 0) { continue; } - + SCompBlock* pBlock = pTableCheck->pCompInfo->blocks; sup.numOfBlocksPerTable[numOfQualTables] = pTableCheck->numOfBlocks; @@ -1428,26 +1434,26 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex if ((code = getFileCompInfo(pQueryHandle, &numOfBlocks)) != TSDB_CODE_SUCCESS) { break; } - + tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %p", pQueryHandle, numOfBlocks, numOfTables, pQueryHandle->pFileGroup->fileId, pQueryHandle->qinfo); - + assert(numOfBlocks >= 0); if (numOfBlocks == 0) { continue; } - + // todo return error code to query engine if (createDataBlocksInfo(pQueryHandle, numOfBlocks, &pQueryHandle->numOfBlocks) != TSDB_CODE_SUCCESS) { break; } - + assert(numOfBlocks >= pQueryHandle->numOfBlocks); if (pQueryHandle->numOfBlocks > 0) { break; } } - + // no data in file anymore if (pQueryHandle->numOfBlocks <= 0) { if (code == TSDB_CODE_SUCCESS) { @@ -1458,10 +1464,10 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex *exists = false; return code; } - + cur->slot = ASCENDING_TRAVERSE(pQueryHandle->order)? 0:pQueryHandle->numOfBlocks-1; cur->fid = pQueryHandle->pFileGroup->fileId; - + STableBlockInfo* pBlockInfo = &pQueryHandle->pDataBlockInfo[cur->slot]; *exists = loadFileDataBlock(pQueryHandle, pBlockInfo->compBlock, pBlockInfo->pTableCheckInfo); @@ -1477,7 +1483,7 @@ static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists pQueryHandle->locateStart = true; STsdbCfg* pCfg = &pQueryHandle->pTsdb->config; int32_t fid = getFileIdFromKey(pQueryHandle->window.skey, pCfg->daysPerFile, pCfg->precision); - + tsdbInitFileGroupIter(pFileHandle, &pQueryHandle->fileIter, pQueryHandle->order); tsdbSeekFileGroupIter(&pQueryHandle->fileIter, fid); @@ -1486,7 +1492,7 @@ static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists // check if current file block is all consumed STableBlockInfo* pBlockInfo = &pQueryHandle->pDataBlockInfo[cur->slot]; STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo; - + // current block is done, try next if (!cur->mixBlock || cur->blockCompleted) { if ((cur->slot == pQueryHandle->numOfBlocks - 1 && ASCENDING_TRAVERSE(pQueryHandle->order)) || @@ -1497,10 +1503,10 @@ static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists // next block of the same file int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order) ? 1 : -1; cur->slot += step; - + cur->mixBlock = false; cur->blockCompleted = false; - + STableBlockInfo* pNext = &pQueryHandle->pDataBlockInfo[cur->slot]; *exists = loadFileDataBlock(pQueryHandle, pNext->compBlock, pNext->pTableCheckInfo); @@ -1518,15 +1524,15 @@ static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists static bool doHasDataInBuffer(STsdbQueryHandle* pQueryHandle) { size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); assert(numOfTables <= ((STsdbRepo*)pQueryHandle->pTsdb)->config.maxTables); - + while (pQueryHandle->activeIndex < numOfTables) { if (hasMoreDataInCache(pQueryHandle)) { return true; } - + pQueryHandle->activeIndex += 1; } - + return false; } @@ -1544,14 +1550,14 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { if (pQueryHandle->type == TSDB_QUERY_TYPE_EXTERNAL) { pQueryHandle->type = TSDB_QUERY_TYPE_ALL; pQueryHandle->order = TSDB_ORDER_DESC; - + if (!tsdbNextDataBlock(pHandle)) { return false; } - + /*SDataBlockInfo* pBlockInfo =*/ tsdbRetrieveDataBlockInfo(pHandle, &blockInfo); /*SArray *pDataBlock = */tsdbRetrieveDataBlock(pHandle, pQueryHandle->defaultLoadColumn); - + if (pQueryHandle->cur.win.ekey == pQueryHandle->window.skey) { // data already retrieve, discard other data rows and return int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); @@ -1559,7 +1565,7 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { SColumnInfoData* pCol = taosArrayGet(pQueryHandle->pColumns, i); memcpy(pCol->pData, pCol->pData + pCol->info.bytes * (pQueryHandle->cur.rows-1), pCol->info.bytes); } - + pQueryHandle->cur.win = (STimeWindow){pQueryHandle->window.skey, pQueryHandle->window.skey}; pQueryHandle->window = pQueryHandle->cur.win; pQueryHandle->cur.rows = 1; @@ -1576,7 +1582,7 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { pSecQueryHandle->checkFiles = true; pSecQueryHandle->activeIndex = 0; pSecQueryHandle->outputCapacity = ((STsdbRepo*)pSecQueryHandle->pTsdb)->config.maxRowsPerFileBlock; - + if (tsdbInitReadHelper(&pSecQueryHandle->rhelper, (STsdbRepo*) pSecQueryHandle->pTsdb) != 0) { free(pSecQueryHandle); return false; @@ -1586,24 +1592,24 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { // allocate buffer in order to load data blocks from file int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); - + pSecQueryHandle->statis = calloc(numOfCols, sizeof(SDataStatis)); pSecQueryHandle->pColumns = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData colInfo = {{0}, 0}; SColumnInfoData* pCol = taosArrayGet(pQueryHandle->pColumns, i); - + colInfo.info = pCol->info; colInfo.pData = calloc(1, EXTRA_BYTES + pQueryHandle->outputCapacity * pCol->info.bytes); taosArrayPush(pSecQueryHandle->pColumns, &colInfo); } - + size_t si = taosArrayGetSize(pQueryHandle->pTableCheckInfo); pSecQueryHandle->pTableCheckInfo = taosArrayInit(si, sizeof(STableCheckInfo)); STsdbMeta* pMeta = tsdbGetMeta(pQueryHandle->pTsdb); assert(pMeta != NULL); - + for (int32_t j = 0; j < si; ++j) { STableCheckInfo* pCheckInfo = (STableCheckInfo*) taosArrayGet(pQueryHandle->pTableCheckInfo, j); STableCheckInfo info = { @@ -1611,10 +1617,10 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { .tableId = pCheckInfo->tableId, .pTableObj = pCheckInfo->pTableObj, }; - + taosArrayPush(pSecQueryHandle->pTableCheckInfo, &info); } - + tsdbInitDataBlockLoadInfo(&pSecQueryHandle->dataBlockLoadInfo); tsdbInitCompBlockLoadInfo(&pSecQueryHandle->compBlockLoadInfo); pSecQueryHandle->defaultLoadColumn = taosArrayClone(pQueryHandle->defaultLoadColumn); @@ -1624,17 +1630,17 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { tsdbRetrieveDataBlockInfo((void*) pSecQueryHandle, &blockInfo); tsdbRetrieveDataBlock((void*) pSecQueryHandle, pSecQueryHandle->defaultLoadColumn); - + for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData* pCol = taosArrayGet(pQueryHandle->pColumns, i); memcpy(pCol->pData, pCol->pData + pCol->info.bytes * (pQueryHandle->cur.rows-1), pCol->info.bytes); - + SColumnInfoData* pCol1 = taosArrayGet(pSecQueryHandle->pColumns, i); assert(pCol->info.colId == pCol1->info.colId); - + memcpy(pCol->pData + pCol->info.bytes, pCol1->pData, pCol1->info.bytes); } - + SColumnInfoData* pTSCol = taosArrayGet(pQueryHandle->pColumns, 0); // it is ascending order @@ -1658,7 +1664,7 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { pQueryHandle->checkFiles = false; return true; } - + if (pQueryHandle->checkFiles) { bool exists = true; int32_t code = getDataBlocksInFiles(pQueryHandle, &exists); @@ -1671,11 +1677,11 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { pQueryHandle->cost.checkForNextTime += elapsedTime; return exists; } - + pQueryHandle->activeIndex = 0; pQueryHandle->checkFiles = false; } - + // TODO: opt by consider the scan order bool ret = doHasDataInBuffer(pQueryHandle); terrno = TSDB_CODE_SUCCESS; @@ -1688,15 +1694,15 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { void changeQueryHandleForLastrowQuery(TsdbQueryHandleT pqHandle) { STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pqHandle; assert(!ASCENDING_TRAVERSE(pQueryHandle->order)); - + // starts from the buffer in case of descending timestamp order check data blocks - + // todo consider the query time window, current last_row does not apply the query time window size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - + TSKEY key = TSKEY_INITIAL_VAL; int32_t index = -1; - + for(int32_t i = 0; i < numOfTables; ++i) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); if (pCheckInfo->pTableObj->lastKey > key) { @@ -1704,36 +1710,36 @@ void changeQueryHandleForLastrowQuery(TsdbQueryHandleT pqHandle) { index = i; } } - + if (index == -1) { // todo add failure test cases return; } - + // erase all other elements in array list size_t size = taosArrayGetSize(pQueryHandle->pTableCheckInfo); for (int32_t i = 0; i < size; ++i) { if (i == index) { continue; } - + STableCheckInfo* pTableCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); tSkipListDestroyIter(pTableCheckInfo->iter); - + if (pTableCheckInfo->pDataCols != NULL) { tfree(pTableCheckInfo->pDataCols->buf); } - + tfree(pTableCheckInfo->pDataCols); tfree(pTableCheckInfo->pCompInfo); } - + STableCheckInfo info = *(STableCheckInfo*) taosArrayGet(pQueryHandle->pTableCheckInfo, index); taosArrayClear(pQueryHandle->pTableCheckInfo); - + info.lastKey = key; taosArrayPush(pQueryHandle->pTableCheckInfo, &info); - + // update the query time window according to the chosen last timestamp pQueryHandle->window = (STimeWindow) {key, key}; } @@ -1742,13 +1748,13 @@ static void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle) { // filter the queried time stamp in the first place STsdbQueryHandle* pQueryHandle = (STsdbQueryHandle*) pHandle; pQueryHandle->order = TSDB_ORDER_DESC; - + assert(pQueryHandle->window.skey == pQueryHandle->window.ekey); - + // starts from the buffer in case of descending timestamp order check data blocks // todo consider the query time window, current last_row does not apply the query time window size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - + int32_t i = 0; while(i < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); @@ -1756,21 +1762,21 @@ static void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle) { pCheckInfo->pTableObj->lastKey != TSKEY_INITIAL_VAL) { break; } - + i++; } - + // there are no data in all the tables if (i == numOfTables) { return; } - + STableCheckInfo info = *(STableCheckInfo*) taosArrayGet(pQueryHandle->pTableCheckInfo, i); taosArrayClear(pQueryHandle->pTableCheckInfo); - + info.lastKey = pQueryHandle->window.skey; taosArrayPush(pQueryHandle->pTableCheckInfo, &info); - + // update the query time window according to the chosen last timestamp pQueryHandle->window = (STimeWindow) {info.lastKey, TSKEY_INITIAL_VAL}; } @@ -1794,7 +1800,7 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int if ((key > maxKey && ASCENDING_TRAVERSE(pQueryHandle->order)) || (key < maxKey && !ASCENDING_TRAVERSE(pQueryHandle->order))) { tsdbDebug("%p key:%"PRIu64" beyond qrange:%"PRId64" - %"PRId64", no more data in buffer", pQueryHandle, key, pQueryHandle->window.skey, pQueryHandle->window.ekey); - + break; } @@ -1809,21 +1815,21 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int moveToNextRowInMem(pCheckInfo); break; } - + } while(moveToNextRowInMem(pCheckInfo)); assert(numOfRows <= maxRowsToRead); - + // if the buffer is not full in case of descending order query, move the data in the front of the buffer if (!ASCENDING_TRAVERSE(pQueryHandle->order) && numOfRows < maxRowsToRead) { int32_t emptySize = maxRowsToRead - numOfRows; - + for(int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); } } - + int64_t elapsedTime = taosGetTimestampUs() - st; tsdbDebug("%p build data block from cache completed, elapsed time:%"PRId64" us, numOfRows:%d, numOfCols:%d", pQueryHandle, elapsedTime, numOfRows, numOfCols); @@ -1835,7 +1841,7 @@ void tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle, SDataBlockInfo* p STsdbQueryHandle* pHandle = (STsdbQueryHandle*)pQueryHandle; SQueryFilePos* cur = &pHandle->cur; STable* pTable = NULL; - + // there are data in file if (pHandle->cur.fid >= 0) { STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[cur->slot]; @@ -1857,13 +1863,13 @@ void tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle, SDataBlockInfo* p */ int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT* pQueryHandle, SDataStatis** pBlockStatis) { STsdbQueryHandle* pHandle = (STsdbQueryHandle*) pQueryHandle; - + SQueryFilePos* c = &pHandle->cur; if (c->mixBlock) { *pBlockStatis = NULL; return TSDB_CODE_SUCCESS; } - + STableBlockInfo* pBlockInfo = &pHandle->pDataBlockInfo[c->slot]; assert((c->slot >= 0 && c->slot < pHandle->numOfBlocks) || ((c->slot == pHandle->numOfBlocks) && (c->slot == 0))); @@ -1883,7 +1889,7 @@ int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT* pQueryHandle, SDataSta for(int32_t i = 0; i < numOfCols; ++i) { pHandle->statis[i].colId = colIds[i]; } - + tsdbGetDataStatis(&pHandle->rhelper, pHandle->statis, numOfCols); // always load the first primary timestamp column data @@ -1932,31 +1938,31 @@ SArray* tsdbRetrieveDataBlock(TsdbQueryHandleT* pQueryHandle, SArray* pIdList) { } else { SDataBlockInfo binfo = GET_FILE_DATA_BLOCK_INFO(pCheckInfo, pBlockInfo->compBlock); assert(pHandle->realNumOfRows <= binfo.rows); - + // data block has been loaded, todo extract method SDataBlockLoadInfo* pBlockLoadInfo = &pHandle->dataBlockLoadInfo; - + if (pBlockLoadInfo->slot == pHandle->cur.slot && pBlockLoadInfo->fileGroup->fileId == pHandle->cur.fid && pBlockLoadInfo->tid == pCheckInfo->pTableObj->tableId.tid) { return pHandle->pColumns; } else { // only load the file block SCompBlock* pBlock = pBlockInfo->compBlock; doLoadFileDataBlock(pHandle, pBlock, pCheckInfo); - + // todo refactor int32_t numOfRows = copyDataFromFileBlock(pHandle, pHandle->outputCapacity, 0, 0, pBlock->numOfRows - 1); - + // if the buffer is not full in case of descending order query, move the data in the front of the buffer if (!ASCENDING_TRAVERSE(pHandle->order) && numOfRows < pHandle->outputCapacity) { int32_t emptySize = pHandle->outputCapacity - numOfRows; int32_t reqNumOfCols = taosArrayGetSize(pHandle->pColumns); - + for(int32_t i = 0; i < reqNumOfCols; ++i) { SColumnInfoData* pColInfo = taosArrayGet(pHandle->pColumns, i); memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); } } - + return pHandle->pColumns; } } @@ -1967,11 +1973,11 @@ static int32_t getAllTableList(STable* pSuperTable, SArray* list) { SSkipListIterator* iter = tSkipListCreateIter(pSuperTable->pIndex); while (tSkipListIterNext(iter)) { SSkipListNode* pNode = tSkipListIterGet(iter); - + STable** pTable = (STable**) SL_GET_NODE_DATA((SSkipListNode*) pNode); taosArrayPush(list, pTable); } - + tSkipListDestroyIter(iter); return TSDB_CODE_SUCCESS; } @@ -1981,12 +1987,12 @@ static void destroyHelper(void* param) { return; } - + tQueryInfo* pInfo = (tQueryInfo*)param; if (pInfo->optr != TSDB_RELATION_IN) { tfree(pInfo->q); } - + // tVariantDestroy(&(pInfo->q)); free(param); } @@ -1998,7 +2004,7 @@ void filterPrepare(void* expr, void* param) { } pExpr->_node.info = calloc(1, sizeof(tQueryInfo)); - + STSchema* pTSSchema = (STSchema*) param; tQueryInfo* pInfo = pExpr->_node.info; tVariant* pCond = pExpr->_node.pRight->pVal; @@ -2008,7 +2014,7 @@ void filterPrepare(void* expr, void* param) { pInfo->optr = pExpr->_node.optr; pInfo->compare = getComparFunc(pSchema->type, pInfo->optr); pInfo->param = pTSSchema; - + if (pInfo->optr == TSDB_RELATION_IN) { pInfo->q = (char*) pCond->arr; } else { @@ -2028,18 +2034,18 @@ int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) { STableGroupSupporter* pTableGroupSupp = (STableGroupSupporter*) param; STable* pTable1 = *(STable**) p1; STable* pTable2 = *(STable**) p2; - + for (int32_t i = 0; i < pTableGroupSupp->numOfCols; ++i) { SColIndex* pColIndex = &pTableGroupSupp->pCols[i]; int32_t colIndex = pColIndex->colIndex; - + assert(colIndex >= TSDB_TBNAME_COLUMN_INDEX); - + char * f1 = NULL; char * f2 = NULL; int32_t type = 0; int32_t bytes = 0; - + if (colIndex == TSDB_TBNAME_COLUMN_INDEX) { f1 = (char*) TABLE_NAME(pTable1); f2 = (char*) TABLE_NAME(pTable2); @@ -2073,14 +2079,14 @@ int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) { return ret; } } - + return 0; } void createTableGroupImpl(SArray* pGroups, SArray* pTableList, size_t numOfTables, STableGroupSupporter* pSupp, __ext_compar_fn_t compareFn) { STable* pTable = taosArrayGetP(pTableList, 0); - + SArray* g = taosArrayInit(16, POINTER_BYTES); taosArrayPush(g, &pTable); tsdbRefTable(pTable); @@ -2088,10 +2094,10 @@ void createTableGroupImpl(SArray* pGroups, SArray* pTableList, size_t numOfTable for (int32_t i = 1; i < numOfTables; ++i) { STable** prev = taosArrayGet(pTableList, i - 1); STable** p = taosArrayGet(pTableList, i); - + int32_t ret = compareFn(prev, p, pSupp); assert(ret == 0 || ret == -1); - + tsdbRefTable(*p); assert((*p)->type == TSDB_CHILD_TABLE); @@ -2103,20 +2109,20 @@ void createTableGroupImpl(SArray* pGroups, SArray* pTableList, size_t numOfTable taosArrayPush(g, p); } } - + taosArrayPush(pGroups, &g); } SArray* createTableGroup(SArray* pTableList, STSchema* pTagSchema, SColIndex* pCols, int32_t numOfOrderCols) { assert(pTableList != NULL); SArray* pTableGroup = taosArrayInit(1, POINTER_BYTES); - + size_t size = taosArrayGetSize(pTableList); if (size == 0) { tsdbDebug("no qualified tables"); return pTableGroup; } - + if (numOfOrderCols == 0 || size == 1) { // no group by tags clause or only one table SArray* sa = taosArrayInit(size, POINTER_BYTES); for(int32_t i = 0; i < size; ++i) { @@ -2126,7 +2132,7 @@ SArray* createTableGroup(SArray* pTableList, STSchema* pTagSchema, SColIndex* pC tsdbRefTable(*pTable); taosArrayPush(sa, pTable); } - + taosArrayPush(pTableGroup, &sa); tsdbDebug("all %zu tables belong to one group", size); } else { @@ -2134,18 +2140,18 @@ SArray* createTableGroup(SArray* pTableList, STSchema* pTagSchema, SColIndex* pC pSupp->numOfCols = numOfOrderCols; pSupp->pTagSchema = pTagSchema; pSupp->pCols = pCols; - + taosqsort(pTableList->pData, size, POINTER_BYTES, pSupp, tableGroupComparFn); createTableGroupImpl(pTableGroup, pTableList, size, pSupp, tableGroupComparFn); tfree(pSupp); } - + return pTableGroup; } bool indexedNodeFilterFp(const void* pNode, void* param) { tQueryInfo* pInfo = (tQueryInfo*) param; - + STable* pTable = *(STable**)(SL_GET_NODE_DATA((SSkipListNode*)pNode)); char* val = NULL; @@ -2155,7 +2161,7 @@ bool indexedNodeFilterFp(const void* pNode, void* param) { } else { val = tdGetKVRowValOfCol(pTable->tagVal, pInfo->sch.colId); } - + int32_t ret = 0; if (val == NULL) { //the val is possible to be null, so check it out carefully ret = -1; // val is missing in table tags value pairs @@ -2192,7 +2198,7 @@ bool indexedNodeFilterFp(const void* pNode, void* param) { default: assert(false); } - + return true; } @@ -2222,7 +2228,7 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, const char* pT goto _error; } - + if (pTable->type != TSDB_SUPER_TABLE) { tsdbError("%p query normal tag not allowed, uid:%" PRIu64 ", tid:%d, name:%s", tsdb, uid, pTable->tableId.tid, pTable->name->data); @@ -2235,7 +2241,7 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, const char* pT //NOTE: not add ref count for super table SArray* res = taosArrayInit(8, POINTER_BYTES); STSchema* pTagSchema = tsdbGetTableTagSchema(pTable); - + // no tags and tbname condition, all child tables of this stable are involved if (tbnameCond == NULL && (pTagCond == NULL || len == 0)) { int32_t ret = getAllTableList(pTable, res); @@ -2246,7 +2252,7 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, const char* pT pGroupInfo->numOfTables = taosArrayGetSize(res); pGroupInfo->pGroupList = createTableGroup(res, pTagSchema, pColIndex, numOfCols); - + tsdbDebug("%p no table name/tag condition, all tables belong to one group, numOfTables:%zu", tsdb, pGroupInfo->numOfTables); taosArrayDestroy(res); @@ -2282,7 +2288,7 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, const char* pT } CATCH( code ) { CLEANUP_EXECUTE(); terrno = code; - goto _error; + goto _error; // TODO: more error handling } END_TRY @@ -2318,12 +2324,12 @@ int32_t tsdbGetOneTableGroup(TSDB_REPO_T* tsdb, uint64_t uid, STableGroupInfo* p pGroupInfo->numOfTables = 1; pGroupInfo->pGroupList = taosArrayInit(1, POINTER_BYTES); - + SArray* group = taosArrayInit(1, POINTER_BYTES); - + taosArrayPush(group, &pTable); taosArrayPush(pGroupInfo->pGroupList, &group); - + return TSDB_CODE_SUCCESS; _error: @@ -2375,7 +2381,7 @@ void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle) { if (pQueryHandle == NULL) { return; } - + size_t size = taosArrayGetSize(pQueryHandle->pTableCheckInfo); for (int32_t i = 0; i < size; ++i) { STableCheckInfo* pTableCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, i); From dbe47d986fdc7d52e97601801d540d64b5c4dbbf Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 12:03:36 +0800 Subject: [PATCH 04/47] [td-225] --- src/query/src/qResultbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index 2443381194..c1ce43b9dd 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -54,7 +54,7 @@ int32_t getResBufSize(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->tota static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { // pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); - pResultBuf->file = fopen(pResultBuf->path, "r+"); + pResultBuf->file = fopen(pResultBuf->path, "w"); if (pResultBuf->file == NULL) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); From c129e42232ac74dd8a009412943b0d73513377a9 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 12:22:10 +0800 Subject: [PATCH 05/47] [td-225] fix error in taoscache. update the resbuf file descriptor. --- src/query/inc/qResultbuf.h | 3 ++- src/query/src/qResultbuf.c | 23 +++++++++++------------ src/util/src/tcache.c | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index e8b3af7ccf..9d60870962 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -36,7 +36,8 @@ typedef struct SDiskbasedResultBuf { int32_t numOfRowsPerPage; int32_t numOfPages; int64_t totalBufSize; - FILE* file; + int32_t fd; +// FILE* file; int32_t allocateId; // allocated page id int32_t incStep; // minimum allocated pages void* pBuf; // mmap buffer pointer diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index c1ce43b9dd..9e597aea5c 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -35,7 +35,7 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu getTmpfilePath("qbuf", path); pResBuf->path = strdup(path); - pResBuf->file = NULL; + pResBuf->fd = FD_INITIALIZER; pResBuf->pBuf = NULL; pResBuf->emptyDummyIdList = taosArrayInit(1, sizeof(int32_t)); @@ -53,9 +53,9 @@ int32_t getResBufSize(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->tota #define FILE_SIZE_ON_DISK(_r) (NUM_OF_PAGES_ON_DISK(_r) * (_r)->pageSize) static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { -// pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); - pResultBuf->file = fopen(pResultBuf->path, "w"); - if (pResultBuf->file == NULL) { + pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); +// pResultBuf->file = fopen(pResultBuf->path, "w"); + if (!FD_VALID(pResultBuf->fd)) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); } @@ -63,14 +63,13 @@ static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { assert(pResultBuf->numOfPages == pResultBuf->inMemPages); pResultBuf->numOfPages += pResultBuf->incStep; - int32_t ret = ftruncate(fileno(pResultBuf->file), NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); + int32_t ret = ftruncate(pResultBuf->fd, NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); if (ret != TSDB_CODE_SUCCESS) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); } - pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, - fileno(pResultBuf->file), 0); + pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, pResultBuf->fd, 0); if (pResultBuf->pBuf == MAP_FAILED) { qError("QInfo:%p failed to map temp file: %s. %s", pResultBuf->handle, pResultBuf->path, strerror(errno)); @@ -86,7 +85,7 @@ static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNu int32_t ret = TSDB_CODE_SUCCESS; if (pResultBuf->pBuf == NULL) { - assert(pResultBuf->file == NULL); + assert(!FD_VALID(pResultBuf->fd)); if ((ret = createDiskResidesBuf(pResultBuf)) != TSDB_CODE_SUCCESS) { return ret; @@ -99,7 +98,7 @@ static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNu * disk-based output buffer is exhausted, try to extend the disk-based buffer, the available disk space may * be insufficient */ - ret = ftruncate(fileno(pResultBuf->file), NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); + ret = ftruncate(pResultBuf->fd, NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); if (ret != TSDB_CODE_SUCCESS) { // dError("QInfo:%p failed to create intermediate result output file:%s. %s", pQInfo, pSupporter->extBufFile, // strerror(errno)); @@ -107,7 +106,7 @@ static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNu } pResultBuf->totalBufSize = pResultBuf->numOfPages * pResultBuf->pageSize; - pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, fileno(pResultBuf->file), 0); + pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, pResultBuf->fd, 0); if (pResultBuf->pBuf == MAP_FAILED) { // dError("QInfo:%p failed to map temp file: %s. %s", pQInfo, pSupporter->extBufFile, strerror(errno)); @@ -189,11 +188,11 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { return; } - if (pResultBuf->file != NULL) { + if (FD_VALID(pResultBuf->fd)) { qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, file created:%s, file size:%d", handle, pResultBuf->totalBufSize, pResultBuf->path, FILE_SIZE_ON_DISK(pResultBuf)); - fclose(pResultBuf->file); + close(pResultBuf->fd); munmap(pResultBuf->pBuf, FILE_SIZE_ON_DISK(pResultBuf)); pResultBuf->pBuf = NULL; } else { diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 89199f035d..7c2a6b3219 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -381,7 +381,7 @@ void *taosCacheAcquireByData(SCacheObj *pCacheObj, void *data) { } void *taosCacheTransfer(SCacheObj *pCacheObj, void **data) { - if (pCacheObj == NULL || data == NULL) return NULL; + if (pCacheObj == NULL || data == NULL || *data == NULL) return NULL; size_t offset = offsetof(SCacheDataNode, data); SCacheDataNode *ptNode = (SCacheDataNode *)((char *)(*data) - offset); From df80c010a921eede036767944d3a097c23b0ea39 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 12:48:30 +0800 Subject: [PATCH 06/47] [td-225] set correct error code when errors occuring. --- src/client/src/tscAsync.c | 2 +- src/client/src/tscSubquery.c | 7 +++---- src/client/src/tscUtil.c | 14 +++++++++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index 9dd33e03cb..85cff4ba17 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -430,7 +430,7 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) { pRes->code = code; if (code != TSDB_CODE_SUCCESS) { - tscError("%p ge tableMeta failed, code:%s", pSql, tstrerror(code)); + tscError("%p get tableMeta failed, code:%s", pSql, tstrerror(code)); goto _error; } else { tscDebug("%p get tableMeta successfully", pSql); diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 5d26d09fae..95d65f4aff 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -1505,12 +1505,11 @@ static int32_t tscReissueSubquery(SRetrieveSupport *trsupport, SSqlObj *pSql, in SSqlObj *pNew = tscCreateSqlObjForSubquery(trsupport->pParentSql, trsupport, pSql); - // todo add to async res or not?? if (pNew == NULL) { - tscError("%p sub:%p failed to create new subquery due to out of memory, abort retry, vgId:%d, orderOfSub:%d", - trsupport->pParentSql, pSql, pVgroup->vgId, trsupport->subqueryIndex); + tscError("%p sub:%p failed to create new subquery due to error:%s, abort retry, vgId:%d, orderOfSub:%d", + trsupport->pParentSql, pSql, tstrerror(terrno), pVgroup->vgId, trsupport->subqueryIndex); - pParentSql->res.code = TSDB_CODE_TSC_OUT_OF_MEMORY; + pParentSql->res.code = terrno; trsupport->numOfRetry = MAX_NUM_OF_SUBQUERY_RETRY; return pParentSql->res.code; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 17adc0c03d..27f2535bdc 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1675,6 +1675,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void SSqlObj* pNew = (SSqlObj*)calloc(1, sizeof(SSqlObj)); if (pNew == NULL) { tscError("%p new subquery failed, tableIndex:%d", pSql, tableIndex); + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; return NULL; } @@ -1688,6 +1689,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void tscError("%p new subquery failed, tableIndex:%d, vgroupIndex:%d", pSql, tableIndex, pTableMetaInfo->vgroupIndex); free(pNew); + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; return NULL; } @@ -1706,6 +1708,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void if (tscAddSubqueryInfo(pnCmd) != TSDB_CODE_SUCCESS) { tscFreeSqlObj(pNew); + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; return NULL; } @@ -1743,6 +1746,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void if (tscAllocPayload(pnCmd, TSDB_DEFAULT_PAYLOAD_SIZE) != TSDB_CODE_SUCCESS) { tscError("%p new subquery failed, tableIndex:%d, vgroupIndex:%d", pSql, tableIndex, pTableMetaInfo->vgroupIndex); tscFreeSqlObj(pNew); + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; return NULL; } @@ -1827,8 +1831,16 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void } if (pFinalInfo->pTableMeta == NULL) { - tscError("%p new subquery failed for get tableMeta is NULL from cache", pSql); + tscError("%p new subquery failed since no tableMeta in cache, name:%s", pSql, name); tscFreeSqlObj(pNew); + + if (pPrevSql != NULL) { + assert(pPrevSql->res.code != TSDB_CODE_SUCCESS); + terrno = pPrevSql->res.code; + } else { + terrno = TSDB_CODE_TSC_APP_ERROR; + } + return NULL; } From f72183fea5d047adfc3e9e95bc667f79fc8b065a Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 21 Jul 2020 14:35:49 +0800 Subject: [PATCH 07/47] [td-225] enable block ts check. --- src/tsdb/src/tsdbRead.c | 42 +++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 1d15860912..7538c6f7e1 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -831,6 +831,12 @@ static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t cap TSKEY* tsArray = pCols->cols[0].pData; int32_t num = end - start + 1; + assert(num >= 0); + + if (num == 0) { + return numOfRows; + } + int32_t requiredNumOfCols = taosArrayGetSize(pQueryHandle->pColumns); //data in buffer has greater timestamp, copy data in file block @@ -973,7 +979,7 @@ static void copyOneRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, } static void moveDataToFront(STsdbQueryHandle* pQueryHandle, int32_t numOfRows, int32_t numOfCols) { - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + if (numOfRows == 0 || ASCENDING_TRAVERSE(pQueryHandle->order)) { return; } @@ -1022,6 +1028,26 @@ static void updateInfoAfterMerge(STsdbQueryHandle* pQueryHandle, STableCheckInfo cur->pos = endPos; } +static void doCheckGeneratedBlockRange(STsdbQueryHandle* pQueryHandle) { + SQueryFilePos* cur = &pQueryHandle->cur; + + if (cur->rows > 0) { + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + assert(cur->win.skey >= pQueryHandle->window.skey && cur->win.ekey <= pQueryHandle->window.ekey); + } else { + assert(cur->win.skey >= pQueryHandle->window.ekey && cur->win.ekey <= pQueryHandle->window.skey); + } + + SColumnInfoData* pColInfoData = taosArrayGet(pQueryHandle->pColumns, 0); + assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] && cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows-1]); + } else { + cur->win = pQueryHandle->window; + + int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; + cur->lastKey = pQueryHandle->window.ekey + step; + } +} + // only return the qualified data to client in terms of query time window, data rows in the same block but do not // be included in the query time window will be discarded static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* pCheckInfo, SCompBlock* pBlock) { @@ -1073,6 +1099,7 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* // the time window should always be right order: skey <= ekey cur->win = (STimeWindow) {.skey = tsArray[start], .ekey = tsArray[end]}; + cur->lastKey = tsArray[endPos]; pos += (end - start + 1) * step; cur->blockCompleted = @@ -1082,7 +1109,7 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* // if the buffer is not full in case of descending order query, move the data in the front of the buffer moveDataToFront(pQueryHandle, numOfRows, numOfCols); updateInfoAfterMerge(pQueryHandle, pCheckInfo, numOfRows, pos); - + doCheckGeneratedBlockRange(pQueryHandle); return; } else if (pCheckInfo->iter != NULL || pCheckInfo->iiter != NULL) { SSkipListNode* node = NULL; @@ -1175,15 +1202,7 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* moveDataToFront(pQueryHandle, numOfRows, numOfCols); updateInfoAfterMerge(pQueryHandle, pCheckInfo, numOfRows, pos); - - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - assert(cur->win.skey >= pQueryHandle->window.skey && cur->win.ekey <= pQueryHandle->window.ekey); - } else { - assert(cur->win.skey >= pQueryHandle->window.ekey && cur->win.ekey <= pQueryHandle->window.skey); - } - - SColumnInfoData* pColInfoData = taosArrayGet(pQueryHandle->pColumns, 0); - assert(cur->win.skey == ((TSKEY*)pColInfoData->pData)[0] && cur->win.ekey == ((TSKEY*)pColInfoData->pData)[cur->rows-1]); + doCheckGeneratedBlockRange(pQueryHandle); tsdbDebug("%p uid:%" PRIu64",tid:%d data block created, brange:%"PRIu64"-%"PRIu64" rows:%d, %p", pQueryHandle, pCheckInfo->tableId.uid, pCheckInfo->tableId.tid, cur->win.skey, cur->win.ekey, cur->rows, pQueryHandle->qinfo); @@ -2027,7 +2046,6 @@ typedef struct STableGroupSupporter { int32_t numOfCols; SColIndex* pCols; STSchema* pTagSchema; -// void* tsdbMeta; } STableGroupSupporter; int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) { From 7ff6bc2eb02ad0c9367e5db1673f631461e49a36 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 13:08:32 +0800 Subject: [PATCH 08/47] [td-225] add checks. --- src/tsdb/src/tsdbRead.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 3b6e90b740..6107c73921 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -721,7 +721,7 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock SQueryFilePos* cur = &pQueryHandle->cur; if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - // query ended in current block + // query ended in/started from current block if (pQueryHandle->window.ekey < pBlock->keyLast || pCheckInfo->lastKey > pBlock->keyFirst) { if (!doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo)) { return false; @@ -737,6 +737,7 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock cur->pos = 0; } + assert(pCheckInfo->lastKey <= pBlock->keyLast); doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock); } else { // the whole block is loaded in to buffer handleDataMergeIfNeeded(pQueryHandle, pBlock, pCheckInfo); @@ -754,6 +755,7 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock cur->pos = pBlock->numOfRows - 1; } + assert(pCheckInfo->lastKey >= pBlock->keyFirst); doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock); } else { handleDataMergeIfNeeded(pQueryHandle, pBlock, pCheckInfo); @@ -1059,7 +1061,9 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* initTableMemIterator(pQueryHandle, pCheckInfo); SDataCols* pCols = pQueryHandle->rhelper.pDataCols[0]; - assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == PRIMARYKEY_TIMESTAMP_COL_INDEX); + assert(pCols->cols[0].type == TSDB_DATA_TYPE_TIMESTAMP && pCols->cols[0].colId == PRIMARYKEY_TIMESTAMP_COL_INDEX && + cur->pos >= 0 && cur->pos < pBlock->numOfRows); + TSKEY* tsArray = pCols->cols[0].pData; // for search the endPos, so the order needs to reverse @@ -1069,8 +1073,8 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); STable* pTable = pCheckInfo->pTableObj; - int32_t endPos = cur->pos; + if (ASCENDING_TRAVERSE(pQueryHandle->order) && pQueryHandle->window.ekey > blockInfo.window.ekey) { endPos = blockInfo.rows - 1; cur->mixBlock = (cur->pos != 0); From 7e7f91b8fc20f3128d9d741b3ee72b8565eabecd Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 13:09:53 +0800 Subject: [PATCH 09/47] [td-225] add checks. --- src/tsdb/src/tsdbRead.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 6107c73921..9962019591 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -1490,6 +1490,7 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex return code; } + assert(pQueryHandle->pFileGroup != NULL); cur->slot = ASCENDING_TRAVERSE(pQueryHandle->order)? 0:pQueryHandle->numOfBlocks-1; cur->fid = pQueryHandle->pFileGroup->fileId; From 1f3571926e41a573146bbd373ca2354a987030d4 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 13:21:49 +0800 Subject: [PATCH 10/47] [td-225] refactor codes. --- src/tsdb/src/tsdbRead.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 9962019591..7577a8e8fc 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -1450,9 +1450,11 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex // current file are not overlapped with query time window, ignore remain files if ((ASCENDING_TRAVERSE(pQueryHandle->order) && win.skey > pQueryHandle->window.ekey) || - (!ASCENDING_TRAVERSE(pQueryHandle->order) && win.ekey < pQueryHandle->window.ekey)) { - tsdbDebug("%p remain files are not qualified for qrange:%"PRId64"-%"PRId64", ignore, %p", pQueryHandle, pQueryHandle->window.skey, pQueryHandle->window.ekey, pQueryHandle->qinfo) + (!ASCENDING_TRAVERSE(pQueryHandle->order) && win.ekey < pQueryHandle->window.ekey)) { + tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %p", pQueryHandle, + pQueryHandle->window.skey, pQueryHandle->window.ekey, pQueryHandle->qinfo); pQueryHandle->pFileGroup = NULL; + assert(pQueryHandle->numOfBlocks == 0); break; } @@ -1460,8 +1462,8 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex break; } - tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %p", pQueryHandle, numOfBlocks, - numOfTables, pQueryHandle->pFileGroup->fileId, pQueryHandle->qinfo); + tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %p", pQueryHandle, numOfBlocks, numOfTables, + pQueryHandle->pFileGroup->fileId, pQueryHandle->qinfo); assert(numOfBlocks >= 0); if (numOfBlocks == 0) { @@ -1469,7 +1471,7 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex } // todo return error code to query engine - if (createDataBlocksInfo(pQueryHandle, numOfBlocks, &pQueryHandle->numOfBlocks) != TSDB_CODE_SUCCESS) { + if ((code = createDataBlocksInfo(pQueryHandle, numOfBlocks, &pQueryHandle->numOfBlocks)) != TSDB_CODE_SUCCESS) { break; } @@ -1480,7 +1482,7 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex } // no data in file anymore - if (pQueryHandle->numOfBlocks <= 0) { + if (pQueryHandle->numOfBlocks <= 0 || code != TSDB_CODE_SUCCESS) { if (code == TSDB_CODE_SUCCESS) { assert(pQueryHandle->pFileGroup == NULL); } From e8b0eb7f224d96acc7ba7bdcd5e62c1af717d50f Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 13:29:31 +0800 Subject: [PATCH 11/47] [td-225] fix compiler errors. --- src/query/inc/qResultbuf.h | 9 ++------- src/query/src/qResultbuf.c | 8 ++++++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index 9d60870962..2e1126b517 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -97,13 +97,8 @@ SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId); * @param id * @return */ -static FORCE_INLINE tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { - if (id < pResultBuf->inMemPages) { - return (tFilePage*) ((char*) pResultBuf->iBuf + id * pResultBuf->pageSize); - } else { - return (tFilePage*) ((char*) pResultBuf->pBuf + (id - pResultBuf->inMemPages) * pResultBuf->pageSize); - } -} +tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); + /** * get the total buffer size in the format of disk file * @param pResultBuf diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index 9e597aea5c..a4696ea62c 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -144,6 +144,14 @@ static int32_t addNewGroupId(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { return num; } +tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { + if (id < pResultBuf->inMemPages) { + return (tFilePage*) ((char*) pResultBuf->iBuf + id * pResultBuf->pageSize); + } else { + return (tFilePage*) ((char*) pResultBuf->pBuf + (id - pResultBuf->inMemPages) * pResultBuf->pageSize); + } +} + static void registerPageId(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t pageId) { int32_t slot = getGroupIndex(pResultBuf, groupId); if (slot < 0) { From 9a9ea692ed538c07d306ee414ca87da87e4bf45a Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 14:02:23 +0800 Subject: [PATCH 12/47] [td-225] update resbuf --- src/query/inc/qResultbuf.h | 47 ++-- src/query/src/qResultbuf.c | 331 ++++++++++++++++++--------- src/query/tests/resultBufferTest.cpp | 28 ++- src/util/src/tlist.c | 1 + 4 files changed, 281 insertions(+), 126 deletions(-) diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index 9d60870962..b4c830370c 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -20,42 +20,56 @@ extern "C" { #endif +#include #include "hash.h" #include "os.h" #include "qExtbuffer.h" +#include "tlockfree.h" typedef struct SArray* SIDList; -typedef struct SPageInfo { - int32_t pageId; +typedef struct SPageDiskInfo { int32_t offset; - int32_t lengthOnDisk; + int32_t length; +} SPageDiskInfo; + +typedef struct SPageInfo { + int32_t pageId; + SPageDiskInfo info; + void* pData; + T_REF_DECLARE(); } SPageInfo; +typedef struct SFreeListItem { + int32_t offset; + int32_t len; +} SFreeListItem; + typedef struct SDiskbasedResultBuf { int32_t numOfRowsPerPage; int32_t numOfPages; int64_t totalBufSize; - int32_t fd; -// FILE* file; +// int32_t fd; + FILE* file; int32_t allocateId; // allocated page id - int32_t incStep; // minimum allocated pages +// int32_t incStep; // minimum allocated pages void* pBuf; // mmap buffer pointer char* path; // file path int32_t pageSize; // current used page size int32_t inMemPages; // numOfPages that are allocated in memory SHashObj* idsTable; // id hash table - SIDList list; // for each id, there is a page id list - - void* iBuf; // inmemory buf + SHashObj* all; + SList* pPageList; void* handle; // for debug purpose void* emptyDummyIdList; // dummy id list bool comp; - + SArray* pFree; // free area in file + int32_t nextPos; // next page flush position } SDiskbasedResultBuf; #define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) #define DEFAULT_INMEM_BUF_PAGES 10 +#define PAGE_INFO_INITIALIZER (SPageDiskInfo){-1, -1} /** * create disk-based result buffer @@ -65,7 +79,7 @@ typedef struct SDiskbasedResultBuf { * @return */ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t numOfPages, int32_t rowSize, int32_t pagesize, - int32_t inMemPages, const void* handle); + int32_t inMemPages, const void* handle); /** * @@ -97,13 +111,10 @@ SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId); * @param id * @return */ -static FORCE_INLINE tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { - if (id < pResultBuf->inMemPages) { - return (tFilePage*) ((char*) pResultBuf->iBuf + id * pResultBuf->pageSize); - } else { - return (tFilePage*) ((char*) pResultBuf->pBuf + (id - pResultBuf->inMemPages) * pResultBuf->pageSize); - } -} +tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); + +void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page); + /** * get the total buffer size in the format of disk file * @param pResultBuf diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index 9e597aea5c..dff629e6a8 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -1,4 +1,5 @@ #include "qResultbuf.h" +#include #include "hash.h" #include "qExtbuffer.h" #include "queryLog.h" @@ -14,29 +15,26 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu } pResBuf->pageSize = pagesize; - pResBuf->numOfPages = inMemPages; // all pages are in buffer in the first place + pResBuf->numOfPages = 0; // all pages are in buffer in the first place pResBuf->inMemPages = inMemPages; assert(inMemPages <= numOfPages); pResBuf->numOfRowsPerPage = (pagesize - sizeof(tFilePage)) / rowSize; pResBuf->totalBufSize = pResBuf->numOfPages * pagesize; - pResBuf->incStep = 4; pResBuf->allocateId = -1; - // todo opt perf by on demand create in memory buffer - pResBuf->iBuf = calloc(pResBuf->inMemPages, pResBuf->pageSize); + pResBuf->pPageList = tdListNew(POINTER_BYTES); // init id hash table - pResBuf->idsTable = taosHashInit(numOfPages, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); - pResBuf->list = taosArrayInit(numOfPages, POINTER_BYTES); + pResBuf->idsTable = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); + pResBuf->all = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); char path[PATH_MAX] = {0}; getTmpfilePath("qbuf", path); pResBuf->path = strdup(path); - pResBuf->fd = FD_INITIALIZER; - pResBuf->pBuf = NULL; + pResBuf->file = NULL; pResBuf->emptyDummyIdList = taosArrayInit(1, sizeof(int32_t)); qDebug("QInfo:%p create resBuf for output, page size:%d, initial pages:%d, %" PRId64 "bytes", handle, @@ -53,133 +51,258 @@ int32_t getResBufSize(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->tota #define FILE_SIZE_ON_DISK(_r) (NUM_OF_PAGES_ON_DISK(_r) * (_r)->pageSize) static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { - pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); -// pResultBuf->file = fopen(pResultBuf->path, "w"); - if (!FD_VALID(pResultBuf->fd)) { +// pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); + pResultBuf->file = fopen(pResultBuf->path, "w"); + if (pResultBuf->file == NULL) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); } - - assert(pResultBuf->numOfPages == pResultBuf->inMemPages); - pResultBuf->numOfPages += pResultBuf->incStep; - - int32_t ret = ftruncate(pResultBuf->fd, NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); - if (ret != TSDB_CODE_SUCCESS) { - qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); - return TAOS_SYSTEM_ERROR(errno); - } - - pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, pResultBuf->fd, 0); - - if (pResultBuf->pBuf == MAP_FAILED) { - qError("QInfo:%p failed to map temp file: %s. %s", pResultBuf->handle, pResultBuf->path, strerror(errno)); - return TAOS_SYSTEM_ERROR(errno); - } - - pResultBuf->totalBufSize = pResultBuf->numOfPages * pResultBuf->pageSize; return TSDB_CODE_SUCCESS; } -static int32_t extendDiskFileSize(SDiskbasedResultBuf* pResultBuf, int32_t incNumOfPages) { - assert(pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize); +static char* doCompressData(void* data, int32_t srcSize, int32_t *dst) { // do nothing + *dst = srcSize; + return data; +} + +static int32_t allocatePositionInFile(SDiskbasedResultBuf* pResultBuf, size_t size) { + if (pResultBuf->pFree == NULL) { + return pResultBuf->nextPos; + } else { //todo speed up the search procedure + size_t num = taosArrayGetSize(pResultBuf->pFree); + + int32_t offset = -1; + + for(int32_t i = 0; i < num; ++i) { + SFreeListItem* pi = taosArrayGet(pResultBuf->pFree, i); + if (pi->len >= size) { + offset = pi->offset; + pi->offset += size; + pi->len -= size; + + return offset; + } + } + + // no available recycle space, allocate new area in file + return pResultBuf->nextPos; + } +} + +static void doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { + assert(T_REF_VAL_GET(pg) == 0); + + int32_t size = -1; + char* t = doCompressData(pg->pData + POINTER_BYTES, pResultBuf->pageSize, &size); + + // this page is flushed to disk for the first time + if (pg->info.offset == -1) { + int32_t offset = allocatePositionInFile(pResultBuf, size); + pResultBuf->nextPos += size; + + fseek(pResultBuf->file, offset, SEEK_SET); + fwrite(t, size, 1, pResultBuf->file); + } else { + if (pg->info.length < size) { // length becomes greater, current space is not enough, allocate new place. + //1. add current space to free list + taosArrayPush(pResultBuf->pFree, &pg->info); + + //2. allocate new position, and update the info + int32_t offset = allocatePositionInFile(pResultBuf, size); + pResultBuf->nextPos += size; + + //3. write to disk. + fseek(pResultBuf->file, offset, SEEK_SET); + fwrite(t, size, 1, pResultBuf->file); + } + } +} + +static int32_t flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t ret = TSDB_CODE_SUCCESS; + assert(pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); if (pResultBuf->pBuf == NULL) { - assert(!FD_VALID(pResultBuf->fd)); - + assert(pResultBuf->file == NULL); if ((ret = createDiskResidesBuf(pResultBuf)) != TSDB_CODE_SUCCESS) { return ret; } - } else { - ret = munmap(pResultBuf->pBuf, FILE_SIZE_ON_DISK(pResultBuf)); - pResultBuf->numOfPages += incNumOfPages; - - /* - * disk-based output buffer is exhausted, try to extend the disk-based buffer, the available disk space may - * be insufficient - */ - ret = ftruncate(pResultBuf->fd, NUM_OF_PAGES_ON_DISK(pResultBuf) * pResultBuf->pageSize); - if (ret != TSDB_CODE_SUCCESS) { - // dError("QInfo:%p failed to create intermediate result output file:%s. %s", pQInfo, pSupporter->extBufFile, - // strerror(errno)); - return TSDB_CODE_QRY_NO_DISKSPACE; - } - - pResultBuf->totalBufSize = pResultBuf->numOfPages * pResultBuf->pageSize; - pResultBuf->pBuf = mmap(NULL, FILE_SIZE_ON_DISK(pResultBuf), PROT_READ | PROT_WRITE, MAP_SHARED, pResultBuf->fd, 0); - - if (pResultBuf->pBuf == MAP_FAILED) { - // dError("QInfo:%p failed to map temp file: %s. %s", pQInfo, pSupporter->extBufFile, strerror(errno)); - return TSDB_CODE_QRY_OUT_OF_MEMORY; - } } + doFlushPageToDisk(pResultBuf, pg); return TSDB_CODE_SUCCESS; } -#define NO_AVAILABLE_PAGES(_b) ((_b)->allocateId == (_b)->numOfPages - 1) +#define NO_AVAILABLE_PAGES(_b) ((_b)->numOfPages >= (_b)->inMemPages) -static FORCE_INLINE int32_t getGroupIndex(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { - assert(pResultBuf != NULL); +static SIDList addNewGroup(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { + assert(taosHashGet(pResultBuf->idsTable, (const char*) &groupId, sizeof(int32_t)) == NULL); - char* p = taosHashGet(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t)); + SArray* pa = taosArrayInit(1, sizeof(SPageInfo)); + int32_t ret = taosHashPut(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t), &pa, POINTER_BYTES); + assert(ret == 0); + + return pa; +} + +static SPageInfo* registerPage(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t pageId) { + SIDList list = NULL; + + char** p = taosHashGet(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t)); if (p == NULL) { // it is a new group id - return -1; + list = addNewGroup(pResultBuf, groupId); + } else { + list = (SIDList) (*p); } - int32_t slot = GET_INT32_VAL(p); - assert(slot >= 0 && slot < taosHashGetSize(pResultBuf->idsTable)); + pResultBuf->numOfPages += 1; - return slot; -} - -static int32_t addNewGroupId(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { - int32_t num = getNumOfResultBufGroupId(pResultBuf); // the num is the newest allocated group id slot - taosHashPut(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t), &num, sizeof(int32_t)); - - SArray* pa = taosArrayInit(1, sizeof(int32_t)); - taosArrayPush(pResultBuf->list, &pa); - - assert(taosArrayGetSize(pResultBuf->list) == taosHashGetSize(pResultBuf->idsTable)); - return num; -} - -static void registerPageId(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t pageId) { - int32_t slot = getGroupIndex(pResultBuf, groupId); - if (slot < 0) { - slot = addNewGroupId(pResultBuf, groupId); - } - - SIDList pList = taosArrayGetP(pResultBuf->list, slot); - taosArrayPush(pList, &pageId); + SPageInfo ppi = { .info = PAGE_INFO_INITIALIZER, .pageId = pageId, }; + return taosArrayPush(list, &ppi); } tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId) { if (NO_AVAILABLE_PAGES(pResultBuf)) { - if (extendDiskFileSize(pResultBuf, pResultBuf->incStep) != TSDB_CODE_SUCCESS) { - return NULL; + // get the last page in linked list + SListIter iter = {0}; + tdListInitIter(pResultBuf->pPageList, &iter, TD_LIST_BACKWARD); + + SListNode* pn = NULL; + while((pn = tdListNext(&iter)) != NULL) { + assert(pn != NULL); + if (T_REF_VAL_GET(*(SPageInfo**)pn->data) == 0) { + break; + } + } + + // all pages are referenced by user, try to allocate new space + if (pn == NULL) { + int32_t prev = pResultBuf->inMemPages; + pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; + + qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, + pResultBuf->inMemPages, pResultBuf->pageSize); + } else { + tdListPopNode(pResultBuf->pPageList, pn); + if (flushPageToDisk(pResultBuf, *(SPageInfo**)pn->data) != TSDB_CODE_SUCCESS) { + return NULL; + } } } // register new id in this group *pageId = (++pResultBuf->allocateId); - registerPageId(pResultBuf, groupId, *pageId); - // clear memory for the new page - tFilePage* page = getResBufPage(pResultBuf, *pageId); - memset(page, 0, pResultBuf->pageSize); - - return page; + // register page id info + SPageInfo* pi = registerPage(pResultBuf, groupId, *pageId); + + // add to LRU list + assert(listNEles(pResultBuf->pPageList) < pResultBuf->inMemPages); + tdListPrepend(pResultBuf->pPageList, &pi); + + // add to hash map + taosHashPut(pResultBuf->all, pageId, sizeof(int32_t), &pi, POINTER_BYTES); + + // allocate buf + pi->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES); + pResultBuf->totalBufSize += pResultBuf->pageSize; + + T_REF_INC(pi); // add ref count + ((void**)pi->pData)[0] = pi; + + return pi->pData + POINTER_BYTES; } +tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { + assert(pResultBuf != NULL && id >= 0); + + SPageInfo** pi = taosHashGet(pResultBuf->all, &id, sizeof(int32_t)); + assert(pi != NULL && *pi != NULL); + + if ((*pi)->pData != NULL) { // it is in memory + // no need to update the LRU list + if (pResultBuf->numOfPages == 1) { + return (*pi)->pData + POINTER_BYTES; + } + + SListNode* pnode = NULL; // todo speed up + + SListIter iter = {0}; + tdListInitIter(pResultBuf->pPageList, &iter, TD_LIST_FORWARD); + + while((pnode = tdListNext(&iter)) != NULL) { + SPageInfo** pInfo = (SPageInfo**) pnode->data; + + // remove it and add it into the front of linked-list + if ((*pInfo)->pageId == id) { + tdListPopNode(pResultBuf->pPageList, pnode); + tdListPrependNode(pResultBuf->pPageList, pnode); + T_REF_INC(*(SPageInfo**)pnode->data); + + return ((*(SPageInfo**)pnode->data)->pData + POINTER_BYTES); + } + } + } else { // not in memory + // choose the be flushed page + // get the last page in linked list + SListIter iter1 = {0}; + tdListInitIter(pResultBuf->pPageList, &iter1, TD_LIST_BACKWARD); + + SListNode* pn = NULL; + while((pn = tdListNext(&iter1)) != NULL) { + assert(pn != NULL); + if (T_REF_VAL_GET(*(SPageInfo**)pn->data) == 0) { + break; + } + } + + // all pages are referenced by user, try to allocate new space + if (pn == NULL) { + pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; + assert(0); + return NULL; + } else { + tdListPopNode(pResultBuf->pPageList, pn); + if (flushPageToDisk(pResultBuf, *(SPageInfo**)pn->data) != TSDB_CODE_SUCCESS) { + return NULL; + } + + char* buf = (*(SPageInfo**)pn->data)->pData; + (*(SPageInfo**)pn->data)->pData = NULL; + + // load file in disk + fseek(pResultBuf->file, (*pi)->info.offset, SEEK_SET); + fread(buf, (*pi)->info.length, 1, pResultBuf->file); + + (*pi)->pData = buf; + return (*pi)->pData; + } + } + + return NULL; +} + +void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page) { + assert(pResultBuf != NULL && page != NULL); + char* p = (char*) page - POINTER_BYTES; + + SPageInfo* ppi = ((SPageInfo**) p)[0]; + + assert(T_REF_VAL_GET(ppi) > 0); + T_REF_DEC(ppi); +} + + int32_t getNumOfRowsPerPage(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; } SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { - int32_t slot = getGroupIndex(pResultBuf, groupId); - if (slot < 0) { + assert(pResultBuf != NULL); + + char** p = taosHashGet(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t)); + if (p == NULL) { // it is a new group id return pResultBuf->emptyDummyIdList; } else { - return taosArrayGetP(pResultBuf->list, slot); + return (SArray*) (*p); } } @@ -188,12 +311,11 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { return; } - if (FD_VALID(pResultBuf->fd)) { + if (pResultBuf->file != NULL) { qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, file created:%s, file size:%d", handle, pResultBuf->totalBufSize, pResultBuf->path, FILE_SIZE_ON_DISK(pResultBuf)); - close(pResultBuf->fd); - munmap(pResultBuf->pBuf, FILE_SIZE_ON_DISK(pResultBuf)); + fclose(pResultBuf->file); pResultBuf->pBuf = NULL; } else { qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, no file created", handle, @@ -203,17 +325,16 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { unlink(pResultBuf->path); tfree(pResultBuf->path); - size_t size = taosArrayGetSize(pResultBuf->list); - for (int32_t i = 0; i < size; ++i) { - SArray* pa = taosArrayGetP(pResultBuf->list, i); - taosArrayDestroy(pa); - } +// size_t size = taosArrayGetSize(pResultBuf->list); +// for (int32_t i = 0; i < size; ++i) { +// SArray* pa = taosArrayGetP(pResultBuf->list, i); +// taosArrayDestroy(pa); +// } - taosArrayDestroy(pResultBuf->list); + tdListFree(pResultBuf->pPageList); taosArrayDestroy(pResultBuf->emptyDummyIdList); taosHashCleanup(pResultBuf->idsTable); - tfree(pResultBuf->iBuf); tfree(pResultBuf); } diff --git a/src/query/tests/resultBufferTest.cpp b/src/query/tests/resultBufferTest.cpp index 63ed89ab9f..93c1a65218 100644 --- a/src/query/tests/resultBufferTest.cpp +++ b/src/query/tests/resultBufferTest.cpp @@ -18,13 +18,35 @@ void simpleTest() { tFilePage* pBufPage = getNewDataBuf(pResultBuf, groupId, &pageId); ASSERT_TRUE(pBufPage != NULL); - ASSERT_EQ(getNumOfRowsPerPage(pResultBuf), (16384L - sizeof(int64_t))/64); - ASSERT_EQ(getResBufSize(pResultBuf), 1000*16384L); + ASSERT_EQ(getResBufSize(pResultBuf), 1024); SIDList list = getDataBufPagesIdList(pResultBuf, groupId); ASSERT_EQ(taosArrayGetSize(list), 1); ASSERT_EQ(getNumOfResultBufGroupId(pResultBuf), 1); - + + releaseResBufPage(pResultBuf, pBufPage); + + tFilePage* pBufPage1 = getNewDataBuf(pResultBuf, groupId, &pageId); + + tFilePage* t = getResBufPage(pResultBuf, pageId); + assert(t == pBufPage1); + + tFilePage* pBufPage2 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t1 = getResBufPage(pResultBuf, pageId); + assert(t1 == pBufPage2); + + tFilePage* pBufPage3 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t2 = getResBufPage(pResultBuf, pageId); + assert(t2 == pBufPage3); + + tFilePage* pBufPage4 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t3 = getResBufPage(pResultBuf, pageId); + assert(t3 == pBufPage4); + + tFilePage* pBufPage5 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t4 = getResBufPage(pResultBuf, pageId); + assert(t4 == pBufPage5); + destroyResultBuf(pResultBuf, NULL); } } // namespace diff --git a/src/util/src/tlist.c b/src/util/src/tlist.c index f402c2307e..93293b8b91 100644 --- a/src/util/src/tlist.c +++ b/src/util/src/tlist.c @@ -76,6 +76,7 @@ int tdListPrepend(SList *list, void *data) { SListNode *node = (SListNode *)malloc(sizeof(SListNode) + list->eleSize); if (node == NULL) return -1; + node->next = node->prev = NULL; memcpy((void *)(node->data), data, list->eleSize); tdListPrependNode(list, node); From 85def32807a982751c3aa760dbf9577699c01a4c Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 14:18:18 +0800 Subject: [PATCH 13/47] [td-225] add check. --- src/tsdb/src/tsdbRead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 7577a8e8fc..63ad8701ff 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -1492,7 +1492,7 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex return code; } - assert(pQueryHandle->pFileGroup != NULL); + assert(pQueryHandle->pFileGroup != NULL && pQueryHandle->numOfBlocks > 0); cur->slot = ASCENDING_TRAVERSE(pQueryHandle->order)? 0:pQueryHandle->numOfBlocks-1; cur->fid = pQueryHandle->pFileGroup->fileId; From e41aeb834903d2dc49fdf9400d7eb989925ef536 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 15:15:37 +0800 Subject: [PATCH 14/47] [td-225] update intermediate buf page size. --- src/query/inc/qExtbuffer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/query/inc/qExtbuffer.h b/src/query/inc/qExtbuffer.h index b57c48933f..bde5fc35ac 100644 --- a/src/query/inc/qExtbuffer.h +++ b/src/query/inc/qExtbuffer.h @@ -28,9 +28,9 @@ extern "C" { #include "tdataformat.h" #include "talgo.h" -#define DEFAULT_PAGE_SIZE (1024L*4) // 16k larger than the SHistoInfo #define MAX_TMPFILE_PATH_LENGTH PATH_MAX -#define INITIAL_ALLOCATION_BUFFER_SIZE 64 +#define INITIAL_ALLOCATION_BUFFER_SIZE 64L +#define DEFAULT_PAGE_SIZE (1024L*(INITIAL_ALLOCATION_BUFFER_SIZE)) // 16k larger than the SHistoInfo typedef enum EXT_BUFFER_FLUSH_MODEL { /* From 8e97949a143d27ab7d15c73833687aca4d0f3f05 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 17:04:05 +0800 Subject: [PATCH 15/47] [td-225] fix memory leaks. --- src/query/src/qResultbuf.c | 21 ++++++++++++++------- src/query/tests/CMakeLists.txt | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index dff629e6a8..e54217f7e5 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -184,7 +184,10 @@ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32 pResultBuf->inMemPages, pResultBuf->pageSize); } else { tdListPopNode(pResultBuf->pPageList, pn); - if (flushPageToDisk(pResultBuf, *(SPageInfo**)pn->data) != TSDB_CODE_SUCCESS) { + SPageInfo* d = *(SPageInfo**) pn->data; + tfree(pn); + + if (flushPageToDisk(pResultBuf, d) != TSDB_CODE_SUCCESS) { return NULL; } } @@ -275,6 +278,8 @@ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { fread(buf, (*pi)->info.length, 1, pResultBuf->file); (*pi)->pData = buf; + + tfree(pn); return (*pi)->pData; } } @@ -292,7 +297,6 @@ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page) { T_REF_DEC(ppi); } - int32_t getNumOfRowsPerPage(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; } SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { @@ -325,15 +329,18 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { unlink(pResultBuf->path); tfree(pResultBuf->path); -// size_t size = taosArrayGetSize(pResultBuf->list); -// for (int32_t i = 0; i < size; ++i) { -// SArray* pa = taosArrayGetP(pResultBuf->list, i); -// taosArrayDestroy(pa); -// } + SHashMutableIterator* iter = taosHashCreateIter(pResultBuf->idsTable); + while(taosHashIterNext(iter)) { + SArray** p = (SArray**) taosHashIterGet(iter); + taosArrayDestroy(*p); + } + + taosHashDestroyIter(iter); tdListFree(pResultBuf->pPageList); taosArrayDestroy(pResultBuf->emptyDummyIdList); taosHashCleanup(pResultBuf->idsTable); + taosHashCleanup(pResultBuf->all); tfree(pResultBuf); } diff --git a/src/query/tests/CMakeLists.txt b/src/query/tests/CMakeLists.txt index 0ae8600756..86715a4a0f 100644 --- a/src/query/tests/CMakeLists.txt +++ b/src/query/tests/CMakeLists.txt @@ -10,6 +10,6 @@ IF (HEADER_GTEST_INCLUDE_DIR AND LIB_GTEST_STATIC_DIR) INCLUDE_DIRECTORIES(${HEADER_GTEST_INCLUDE_DIR}) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) - ADD_EXECUTABLE(queryTest ${SOURCE_LIST}) + ADD_EXECUTABLE(queryTest ./unitTest.cpp ./resultBufferTest.cpp) TARGET_LINK_LIBRARIES(queryTest taos query gtest pthread) ENDIF() \ No newline at end of file From b337c07e8dc670fbbd7135bca005a39a04603950 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 17:08:56 +0800 Subject: [PATCH 16/47] [td-225] fix concurrent exec query. --- src/query/inc/qExtbuffer.h | 1 - src/query/src/qExecutor.c | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/query/inc/qExtbuffer.h b/src/query/inc/qExtbuffer.h index bde5fc35ac..a992f6153c 100644 --- a/src/query/inc/qExtbuffer.h +++ b/src/query/inc/qExtbuffer.h @@ -19,7 +19,6 @@ extern "C" { #endif - #include "os.h" #include "taosmsg.h" diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 30d6cc288f..458ce228bb 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -5963,8 +5963,6 @@ static int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQ pQuery->window.ekey, pQuery->order.order); setQueryStatus(pQuery, QUERY_COMPLETED); pQInfo->tableqinfoGroupInfo.numOfTables = 0; - - sem_post(&pQInfo->dataReady); return TSDB_CODE_SUCCESS; } @@ -5973,8 +5971,6 @@ static int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQ if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo); setQueryStatus(pQuery, QUERY_COMPLETED); - - sem_post(&pQInfo->dataReady); return TSDB_CODE_SUCCESS; } @@ -6319,6 +6315,8 @@ void qTableQuery(qinfo_t qinfo) { } if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { + setQueryStatus(pQInfo->runtimeEnv.pQuery, QUERY_COMPLETED); + qDebug("QInfo:%p no table exists for query, abort", pQInfo); sem_post(&pQInfo->dataReady); return; From 057e808930c97d9f16ec8f51ef88f40f2a3e5126 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 22 Jul 2020 18:17:38 +0800 Subject: [PATCH 17/47] [td-225] for expriments. --- src/vnode/src/vnodeRead.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 973df7c5a1..83986de682 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -122,7 +122,8 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { // current connect is broken if (code == TSDB_CODE_SUCCESS) { - handle = qRegisterQInfo(pVnode->qMgmt, (uint64_t) pQInfo); +// handle = qRegisterQInfo(pVnode->qMgmt, (uint64_t) pQInfo); + handle = &pQInfo; if (handle == NULL) { // failed to register qhandle vError("vgId:%d QInfo:%p register qhandle failed, return to app, code:%s", pVnode->vgId, (void *)pQInfo, tstrerror(pRsp->code)); @@ -133,11 +134,11 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { pRsp->qhandle = htobe64((uint64_t) pQInfo); } - pQInfo = NULL; +// pQInfo = NULL; if (handle != NULL && vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, *handle, pVnode->vgId) != TSDB_CODE_SUCCESS) { vError("vgId:%d, QInfo:%p, query discarded since link is broken, %p", pVnode->vgId, *handle, pReadMsg->rpcMsg.handle); pRsp->code = TSDB_CODE_RPC_NETWORK_UNAVAIL; - qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); +// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); return pRsp->code; } } else { @@ -148,12 +149,14 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { vDebug("vgId:%d, QInfo:%p, dnode query msg disposed, register qhandle and return to app", vgId, *handle); vnodePutItemIntoReadQueue(pVnode, *handle); - qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); +// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); } } else { assert(pCont != NULL); - handle = qAcquireQInfo(pVnode->qMgmt, (uint64_t) pCont); + void* p = (void*) pCont; + handle = &p; +// handle = qAcquireQInfo(pVnode->qMgmt, (uint64_t) pCont); if (handle == NULL) { vWarn("QInfo:%p invalid qhandle in continuing exec query, conn:%p", (void*) pCont, pReadMsg->rpcMsg.handle); code = TSDB_CODE_QRY_INVALID_QHANDLE; @@ -162,7 +165,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { code = TSDB_CODE_VND_ACTION_IN_PROGRESS; qTableQuery(*handle); // do execute query } - qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); +// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); } return code; @@ -181,7 +184,11 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { memset(pRet, 0, sizeof(SRspRet)); int32_t code = TSDB_CODE_SUCCESS; - void** handle = qAcquireQInfo(pVnode->qMgmt, pRetrieve->qhandle); + void** handle = NULL; + void* p1 = (void*) pRetrieve->qhandle; + handle = &p1; + +// void** handle = qAcquireQInfo(pVnode->qMgmt, pRetrieve->qhandle); if (handle == NULL || (*handle) != (void*) pRetrieve->qhandle) { code = TSDB_CODE_QRY_INVALID_QHANDLE; vDebug("vgId:%d, invalid qhandle in fetch result, QInfo:%p", pVnode->vgId, (void*) pRetrieve->qhandle); @@ -201,7 +208,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (pRetrieve->free == 1) { vDebug("vgId:%d, QInfo:%p, retrieve msg received to kill query and free qhandle", pVnode->vgId, *handle); qKillQuery(*handle); - qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); +// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); pRet->len = sizeof(SRetrieveTableRsp); @@ -234,7 +241,8 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { } } - qReleaseQInfo(pVnode->qMgmt, (void**) &handle, freeHandle); + UNUSED(freeHandle); +// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, freeHandle); return code; } From a6d92173d937d1cf5e276d5a014b5e9f02b36979 Mon Sep 17 00:00:00 2001 From: Liu Tao Date: Wed, 22 Jul 2020 18:53:49 +0800 Subject: [PATCH 18/47] performance tune --- src/client/src/tscUtil.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 27f2535bdc..1ef5d3feaf 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -351,14 +351,14 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) { int32_t cmd = pCmd->command; if (cmd < TSDB_SQL_INSERT || cmd == TSDB_SQL_RETRIEVE_LOCALMERGE || cmd == TSDB_SQL_RETRIEVE_EMPTY_RESULT || cmd == TSDB_SQL_TABLE_JOIN_RETRIEVE) { - tscRemoveFromSqlList(pSql); + //tscRemoveFromSqlList(pSql); } // pSql->sqlstr will be used by tscBuildQueryStreamDesc if (pObj->signature == pObj) { - pthread_mutex_lock(&pObj->mutex); + //pthread_mutex_lock(&pObj->mutex); tfree(pSql->sqlstr); - pthread_mutex_unlock(&pObj->mutex); + //pthread_mutex_unlock(&pObj->mutex); } tscFreeSqlResult(pSql); @@ -1885,7 +1885,7 @@ void tscDoQuery(SSqlObj* pSql) { } if (pCmd->command == TSDB_SQL_SELECT) { - tscAddIntoSqlList(pSql); + //tscAddIntoSqlList(pSql); } if (pCmd->dataSourceType == DATA_FROM_DATA_FILE) { From 10b9968d4a0a690b7ebac0c9b6f23b868f7d5bd3 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 23 Jul 2020 13:40:34 +0800 Subject: [PATCH 19/47] [td-225] fix bugs in resbuf --- src/query/inc/qResultbuf.h | 22 ++-- src/query/src/qResultbuf.c | 153 +++++++++++++++++---------- src/query/tests/resultBufferTest.cpp | 62 ++++++++++- src/util/src/tcompare.c | 2 +- 4 files changed, 170 insertions(+), 69 deletions(-) diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index b4c830370c..da5f46b5e9 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -49,20 +49,19 @@ typedef struct SDiskbasedResultBuf { int32_t numOfRowsPerPage; int32_t numOfPages; int64_t totalBufSize; -// int32_t fd; + int64_t diskFileSize; // disk file size FILE* file; int32_t allocateId; // allocated page id -// int32_t incStep; // minimum allocated pages - void* pBuf; // mmap buffer pointer char* path; // file path int32_t pageSize; // current used page size int32_t inMemPages; // numOfPages that are allocated in memory - SHashObj* idsTable; // id hash table + SHashObj* groupSet; // id hash table SHashObj* all; - SList* pPageList; + SList* lruList; void* handle; // for debug purpose void* emptyDummyIdList; // dummy id list - bool comp; + bool comp; // compressed before flushed to disk + void* assistBuf; // assistant buffer for compress data SArray* pFree; // free area in file int32_t nextPos; // next page flush position } SDiskbasedResultBuf; @@ -95,7 +94,7 @@ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32 * @param pResultBuf * @return */ -int32_t getNumOfRowsPerPage(SDiskbasedResultBuf* pResultBuf); +size_t getNumOfRowsPerPage(const SDiskbasedResultBuf* pResultBuf); /** * @@ -113,6 +112,11 @@ SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId); */ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); +/** + * release the referenced buf pages + * @param pResultBuf + * @param page + */ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page); /** @@ -120,14 +124,14 @@ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page); * @param pResultBuf * @return */ -int32_t getResBufSize(SDiskbasedResultBuf* pResultBuf); +size_t getResBufSize(const SDiskbasedResultBuf* pResultBuf); /** * get the number of groups in the result buffer * @param pResultBuf * @return */ -int32_t getNumOfResultBufGroupId(SDiskbasedResultBuf* pResultBuf); +size_t getNumOfResultBufGroupId(const SDiskbasedResultBuf* pResultBuf); /** * destroy result buffer diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index e54217f7e5..fa2bb814f2 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -1,5 +1,6 @@ #include "qResultbuf.h" #include +#include #include "hash.h" #include "qExtbuffer.h" #include "queryLog.h" @@ -24,11 +25,13 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu pResBuf->totalBufSize = pResBuf->numOfPages * pagesize; pResBuf->allocateId = -1; - pResBuf->pPageList = tdListNew(POINTER_BYTES); + pResBuf->lruList = tdListNew(POINTER_BYTES); // init id hash table - pResBuf->idsTable = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); + pResBuf->groupSet = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); pResBuf->all = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); + pResBuf->assistBuf = malloc(pResBuf->pageSize + 2); // EXTRA BYTES + pResBuf->comp = true; char path[PATH_MAX] = {0}; getTmpfilePath("qbuf", path); @@ -43,25 +46,28 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu return TSDB_CODE_SUCCESS; } -int32_t getNumOfResultBufGroupId(SDiskbasedResultBuf* pResultBuf) { return taosHashGetSize(pResultBuf->idsTable); } - -int32_t getResBufSize(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->totalBufSize; } - #define NUM_OF_PAGES_ON_DISK(_r) ((_r)->numOfPages - (_r)->inMemPages) #define FILE_SIZE_ON_DISK(_r) (NUM_OF_PAGES_ON_DISK(_r) * (_r)->pageSize) static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { -// pResultBuf->fd = open(pResultBuf->path, O_CREAT | O_RDWR, 0666); - pResultBuf->file = fopen(pResultBuf->path, "w"); + pResultBuf->file = fopen(pResultBuf->path, "wb+"); if (pResultBuf->file == NULL) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); return TAOS_SYSTEM_ERROR(errno); } + return TSDB_CODE_SUCCESS; } -static char* doCompressData(void* data, int32_t srcSize, int32_t *dst) { // do nothing - *dst = srcSize; +static char* doCompressData(void* data, int32_t srcSize, int32_t *dst, bool comp, void* assistBuf) { // do nothing + if (!comp) { + *dst = srcSize; + return data; + } + + *dst = tsCompressString(data, srcSize, 1, assistBuf, srcSize, ONE_STAGE_COMP, NULL, 0); + + memcpy(data, assistBuf, *dst); return data; } @@ -89,57 +95,64 @@ static int32_t allocatePositionInFile(SDiskbasedResultBuf* pResultBuf, size_t si } } -static void doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { - assert(T_REF_VAL_GET(pg) == 0); +static char* doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { + assert(T_REF_VAL_GET(pg) == 0 && pg->pData != NULL); int32_t size = -1; - char* t = doCompressData(pg->pData + POINTER_BYTES, pResultBuf->pageSize, &size); + char* t = doCompressData(pg->pData + POINTER_BYTES, pResultBuf->pageSize, &size, pResultBuf->comp, pResultBuf->assistBuf); + pg->info.length = size; // this page is flushed to disk for the first time if (pg->info.offset == -1) { - int32_t offset = allocatePositionInFile(pResultBuf, size); + pg->info.offset = allocatePositionInFile(pResultBuf, size); pResultBuf->nextPos += size; - fseek(pResultBuf->file, offset, SEEK_SET); - fwrite(t, size, 1, pResultBuf->file); + fseek(pResultBuf->file, pg->info.offset, SEEK_SET); + int32_t ret = fwrite(t, 1, size, pResultBuf->file); + + UNUSED(ret); } else { if (pg->info.length < size) { // length becomes greater, current space is not enough, allocate new place. //1. add current space to free list taosArrayPush(pResultBuf->pFree, &pg->info); //2. allocate new position, and update the info - int32_t offset = allocatePositionInFile(pResultBuf, size); + pg->info.offset = allocatePositionInFile(pResultBuf, size); pResultBuf->nextPos += size; //3. write to disk. - fseek(pResultBuf->file, offset, SEEK_SET); + fseek(pResultBuf->file, pg->info.offset, SEEK_SET); fwrite(t, size, 1, pResultBuf->file); } } + + char* ret = pg->pData; + pg->pData = NULL; + + return ret; } -static int32_t flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { +static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t ret = TSDB_CODE_SUCCESS; assert(pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); - if (pResultBuf->pBuf == NULL) { - assert(pResultBuf->file == NULL); + if (pResultBuf->file == NULL) { if ((ret = createDiskResidesBuf(pResultBuf)) != TSDB_CODE_SUCCESS) { - return ret; + terrno = ret; + return NULL; } } - doFlushPageToDisk(pResultBuf, pg); - return TSDB_CODE_SUCCESS; + return doFlushPageToDisk(pResultBuf, pg); } #define NO_AVAILABLE_PAGES(_b) ((_b)->numOfPages >= (_b)->inMemPages) static SIDList addNewGroup(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { - assert(taosHashGet(pResultBuf->idsTable, (const char*) &groupId, sizeof(int32_t)) == NULL); + assert(taosHashGet(pResultBuf->groupSet, (const char*) &groupId, sizeof(int32_t)) == NULL); SArray* pa = taosArrayInit(1, sizeof(SPageInfo)); - int32_t ret = taosHashPut(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t), &pa, POINTER_BYTES); + int32_t ret = taosHashPut(pResultBuf->groupSet, (const char*)&groupId, sizeof(int32_t), &pa, POINTER_BYTES); assert(ret == 0); return pa; @@ -148,7 +161,7 @@ static SIDList addNewGroup(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { static SPageInfo* registerPage(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t pageId) { SIDList list = NULL; - char** p = taosHashGet(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t)); + char** p = taosHashGet(pResultBuf->groupSet, (const char*)&groupId, sizeof(int32_t)); if (p == NULL) { // it is a new group id list = addNewGroup(pResultBuf, groupId); } else { @@ -162,10 +175,13 @@ static SPageInfo* registerPage(SDiskbasedResultBuf* pResultBuf, int32_t groupId, } tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId) { + char* allocPg = NULL; + if (NO_AVAILABLE_PAGES(pResultBuf)) { + // get the last page in linked list SListIter iter = {0}; - tdListInitIter(pResultBuf->pPageList, &iter, TD_LIST_BACKWARD); + tdListInitIter(pResultBuf->lruList, &iter, TD_LIST_BACKWARD); SListNode* pn = NULL; while((pn = tdListNext(&iter)) != NULL) { @@ -183,11 +199,12 @@ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32 qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, pResultBuf->inMemPages, pResultBuf->pageSize); } else { - tdListPopNode(pResultBuf->pPageList, pn); + tdListPopNode(pResultBuf->lruList, pn); SPageInfo* d = *(SPageInfo**) pn->data; tfree(pn); - if (flushPageToDisk(pResultBuf, d) != TSDB_CODE_SUCCESS) { + allocPg = flushPageToDisk(pResultBuf, d); + if (allocPg == NULL) { return NULL; } } @@ -200,14 +217,19 @@ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32 SPageInfo* pi = registerPage(pResultBuf, groupId, *pageId); // add to LRU list - assert(listNEles(pResultBuf->pPageList) < pResultBuf->inMemPages); - tdListPrepend(pResultBuf->pPageList, &pi); + assert(listNEles(pResultBuf->lruList) < pResultBuf->inMemPages); + tdListPrepend(pResultBuf->lruList, &pi); // add to hash map taosHashPut(pResultBuf->all, pageId, sizeof(int32_t), &pi, POINTER_BYTES); // allocate buf - pi->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES); + if (allocPg == NULL) { + pi->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES); + } else { + pi->pData = allocPg; + } + pResultBuf->totalBufSize += pResultBuf->pageSize; T_REF_INC(pi); // add ref count @@ -231,41 +253,47 @@ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { SListNode* pnode = NULL; // todo speed up SListIter iter = {0}; - tdListInitIter(pResultBuf->pPageList, &iter, TD_LIST_FORWARD); + tdListInitIter(pResultBuf->lruList, &iter, TD_LIST_FORWARD); while((pnode = tdListNext(&iter)) != NULL) { SPageInfo** pInfo = (SPageInfo**) pnode->data; // remove it and add it into the front of linked-list if ((*pInfo)->pageId == id) { - tdListPopNode(pResultBuf->pPageList, pnode); - tdListPrependNode(pResultBuf->pPageList, pnode); + tdListPopNode(pResultBuf->lruList, pnode); + tdListPrependNode(pResultBuf->lruList, pnode); T_REF_INC(*(SPageInfo**)pnode->data); return ((*(SPageInfo**)pnode->data)->pData + POINTER_BYTES); } } } else { // not in memory - // choose the be flushed page - // get the last page in linked list + assert((*pi)->pData == NULL && (*pi)->info.length >= 0 && (*pi)->info.offset >= 0); + + // choose the be flushed page: get the last page in linked list SListIter iter1 = {0}; - tdListInitIter(pResultBuf->pPageList, &iter1, TD_LIST_BACKWARD); + tdListInitIter(pResultBuf->lruList, &iter1, TD_LIST_BACKWARD); SListNode* pn = NULL; while((pn = tdListNext(&iter1)) != NULL) { assert(pn != NULL); - if (T_REF_VAL_GET(*(SPageInfo**)pn->data) == 0) { + if (T_REF_VAL_GET(*(SPageInfo**)(pn->data)) == 0) { break; } } // all pages are referenced by user, try to allocate new space if (pn == NULL) { + int32_t prev = pResultBuf->inMemPages; pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; - assert(0); - return NULL; + + qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, + pResultBuf->inMemPages, pResultBuf->pageSize); + + (*pi)->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES); } else { - tdListPopNode(pResultBuf->pPageList, pn); + tdListPopNode(pResultBuf->lruList, pn); + if (flushPageToDisk(pResultBuf, *(SPageInfo**)pn->data) != TSDB_CODE_SUCCESS) { return NULL; } @@ -273,15 +301,23 @@ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { char* buf = (*(SPageInfo**)pn->data)->pData; (*(SPageInfo**)pn->data)->pData = NULL; - // load file in disk - fseek(pResultBuf->file, (*pi)->info.offset, SEEK_SET); - fread(buf, (*pi)->info.length, 1, pResultBuf->file); - (*pi)->pData = buf; + ((void**)((*pi)->pData))[0] = (*pi); tfree(pn); - return (*pi)->pData; } + + // load file in disk + int32_t ret = fseek(pResultBuf->file, (*pi)->info.offset, SEEK_SET); + ret = fread((*pi)->pData + POINTER_BYTES, 1, (*pi)->info.length, pResultBuf->file); + if (ret != (*pi)->info.length) { + terrno = errno; + return NULL; + } + + // todo do decomp + + return (*pi)->pData + POINTER_BYTES; } return NULL; @@ -297,12 +333,16 @@ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page) { T_REF_DEC(ppi); } -int32_t getNumOfRowsPerPage(SDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; } +size_t getNumOfRowsPerPage(const SDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; } + +size_t getNumOfResultBufGroupId(const SDiskbasedResultBuf* pResultBuf) { return taosHashGetSize(pResultBuf->groupSet); } + +size_t getResBufSize(const SDiskbasedResultBuf* pResultBuf) { return pResultBuf->totalBufSize; } SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { assert(pResultBuf != NULL); - char** p = taosHashGet(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t)); + char** p = taosHashGet(pResultBuf->groupSet, (const char*)&groupId, sizeof(int32_t)); if (p == NULL) { // it is a new group id return pResultBuf->emptyDummyIdList; } else { @@ -320,7 +360,6 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { pResultBuf->totalBufSize, pResultBuf->path, FILE_SIZE_ON_DISK(pResultBuf)); fclose(pResultBuf->file); - pResultBuf->pBuf = NULL; } else { qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, no file created", handle, pResultBuf->totalBufSize); @@ -329,19 +368,25 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { unlink(pResultBuf->path); tfree(pResultBuf->path); - SHashMutableIterator* iter = taosHashCreateIter(pResultBuf->idsTable); + SHashMutableIterator* iter = taosHashCreateIter(pResultBuf->groupSet); while(taosHashIterNext(iter)) { SArray** p = (SArray**) taosHashIterGet(iter); + size_t n = taosArrayGetSize(*p); + for(int32_t i = 0; i < n; ++i) { + SPageInfo* pi = taosArrayGet(*p, i); + tfree(pi->pData); + } taosArrayDestroy(*p); } taosHashDestroyIter(iter); - tdListFree(pResultBuf->pPageList); + tdListFree(pResultBuf->lruList); taosArrayDestroy(pResultBuf->emptyDummyIdList); - taosHashCleanup(pResultBuf->idsTable); + taosHashCleanup(pResultBuf->groupSet); taosHashCleanup(pResultBuf->all); + tfree(pResultBuf->assistBuf); tfree(pResultBuf); } diff --git a/src/query/tests/resultBufferTest.cpp b/src/query/tests/resultBufferTest.cpp index 93c1a65218..53a05925c2 100644 --- a/src/query/tests/resultBufferTest.cpp +++ b/src/query/tests/resultBufferTest.cpp @@ -29,28 +29,80 @@ void simpleTest() { tFilePage* pBufPage1 = getNewDataBuf(pResultBuf, groupId, &pageId); tFilePage* t = getResBufPage(pResultBuf, pageId); - assert(t == pBufPage1); + ASSERT_TRUE(t == pBufPage1); tFilePage* pBufPage2 = getNewDataBuf(pResultBuf, groupId, &pageId); tFilePage* t1 = getResBufPage(pResultBuf, pageId); - assert(t1 == pBufPage2); + ASSERT_TRUE(t1 == pBufPage2); tFilePage* pBufPage3 = getNewDataBuf(pResultBuf, groupId, &pageId); tFilePage* t2 = getResBufPage(pResultBuf, pageId); - assert(t2 == pBufPage3); + ASSERT_TRUE(t2 == pBufPage3); tFilePage* pBufPage4 = getNewDataBuf(pResultBuf, groupId, &pageId); tFilePage* t3 = getResBufPage(pResultBuf, pageId); - assert(t3 == pBufPage4); + ASSERT_TRUE(t3 == pBufPage4); tFilePage* pBufPage5 = getNewDataBuf(pResultBuf, groupId, &pageId); tFilePage* t4 = getResBufPage(pResultBuf, pageId); - assert(t4 == pBufPage5); + ASSERT_TRUE(t4 == pBufPage5); + + destroyResultBuf(pResultBuf, NULL); +} + +void writeDownTest() { + SDiskbasedResultBuf* pResultBuf = NULL; + int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 1000, 64, 1024, 4, NULL); + + int32_t pageId = 0; + int32_t writePageId = 0; + int32_t groupId = 0; + int32_t nx = 12345; + + tFilePage* pBufPage = getNewDataBuf(pResultBuf, groupId, &pageId); + ASSERT_TRUE(pBufPage != NULL); + + *(int32_t*)(pBufPage->data) = nx; + writePageId = pageId; + releaseResBufPage(pResultBuf, pBufPage); + + tFilePage* pBufPage1 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t1 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t1 == pBufPage1); + ASSERT_TRUE(pageId == 1); + + tFilePage* pBufPage2 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t2 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t2 == pBufPage2); + ASSERT_TRUE(pageId == 2); + + tFilePage* pBufPage3 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t3 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t3 == pBufPage3); + ASSERT_TRUE(pageId == 3); + + tFilePage* pBufPage4 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t4 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t4 == pBufPage4); + ASSERT_TRUE(pageId == 4); + releaseResBufPage(pResultBuf, t4); + + // flush the written page to disk, and read it out again + tFilePage* pBufPagex = getResBufPage(pResultBuf, writePageId); + ASSERT_EQ(*(int32_t*)pBufPagex->data, nx); + + SArray* pa = getDataBufPagesIdList(pResultBuf, groupId); + ASSERT_EQ(taosArrayGetSize(pa), 5); + + destroyResultBuf(pResultBuf, NULL); } } // namespace + TEST(testCase, resultBufferTest) { + srand(time(NULL)); simpleTest(); + writeDownTest(); } diff --git a/src/util/src/tcompare.c b/src/util/src/tcompare.c index 889d38ff20..9564588254 100644 --- a/src/util/src/tcompare.c +++ b/src/util/src/tcompare.c @@ -1,6 +1,6 @@ #include "taosdef.h" #include "tcompare.h" -#include +#include "tarray.h" #include "tutil.h" int32_t compareInt32Val(const void *pLeft, const void *pRight) { From 74a5a231ad4a372c7da16d3ef643bb6892aa9710 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 23 Jul 2020 14:31:44 +0800 Subject: [PATCH 20/47] [td-225]add some logs. --- src/tsdb/src/tsdbRead.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 63ad8701ff..ccfcff3599 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -622,7 +622,7 @@ static int32_t getFileCompInfo(STsdbQueryHandle* pQueryHandle, int32_t* numOfBlo .uid = (_checkInfo)->tableId.uid}) -static bool doLoadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock, STableCheckInfo* pCheckInfo) { +static bool doLoadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock, STableCheckInfo* pCheckInfo, int32_t slotIndex) { STsdbRepo *pRepo = pQueryHandle->pTsdb; bool blockLoaded = false; int64_t st = taosGetTimestampUs(); @@ -657,8 +657,8 @@ static bool doLoadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlo int64_t elapsedTime = (taosGetTimestampUs() - st); pQueryHandle->cost.blockLoadTime += elapsedTime; - tsdbDebug("%p load file block into buffer, brange:%"PRId64"-%"PRId64" , rows:%d, elapsed time:%"PRId64 " us", - pQueryHandle, pBlock->keyFirst, pBlock->keyLast, pBlock->numOfRows, elapsedTime); + tsdbDebug("%p load file block into buffer, index:%d, brange:%"PRId64"-%"PRId64" , rows:%d, elapsed time:%"PRId64 " us, %p", + pQueryHandle, slotIndex, pBlock->keyFirst, pBlock->keyLast, pBlock->numOfRows, elapsedTime, pQueryHandle->qinfo); return blockLoaded; } @@ -681,8 +681,7 @@ static void handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SCompBlock* // do not load file block into buffer int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order) ? 1 : -1; - cur->rows = tsdbReadRowsFromCache(pCheckInfo, binfo.window.skey - step, - pQueryHandle->outputCapacity, &cur->win, pQueryHandle); + cur->rows = tsdbReadRowsFromCache(pCheckInfo, binfo.window.skey - step, pQueryHandle->outputCapacity, &cur->win, pQueryHandle); pQueryHandle->realNumOfRows = cur->rows; // update the last key value @@ -696,7 +695,7 @@ static void handleDataMergeIfNeeded(STsdbQueryHandle* pQueryHandle, SCompBlock* return; } - doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo); + doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo, cur->slot); doMergeTwoLevelData(pQueryHandle, pCheckInfo, pBlock); } else { /* @@ -723,7 +722,7 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock if (ASCENDING_TRAVERSE(pQueryHandle->order)) { // query ended in/started from current block if (pQueryHandle->window.ekey < pBlock->keyLast || pCheckInfo->lastKey > pBlock->keyFirst) { - if (!doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo)) { + if (!doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo, cur->slot)) { return false; } @@ -744,7 +743,7 @@ static bool loadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlock } } else { //desc order, query ended in current block if (pQueryHandle->window.ekey > pBlock->keyFirst || pCheckInfo->lastKey < pBlock->keyLast) { - if (!doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo)) { + if (!doLoadFileDataBlock(pQueryHandle, pBlock, pCheckInfo, cur->slot)) { return false; } @@ -1859,8 +1858,8 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int } int64_t elapsedTime = taosGetTimestampUs() - st; - tsdbDebug("%p build data block from cache completed, elapsed time:%"PRId64" us, numOfRows:%d, numOfCols:%d", pQueryHandle, - elapsedTime, numOfRows, numOfCols); + tsdbDebug("%p build data block from cache completed, elapsed time:%"PRId64" us, numOfRows:%d, numOfCols:%d, %p", pQueryHandle, + elapsedTime, numOfRows, numOfCols, pQueryHandle->qinfo); return numOfRows; } @@ -1975,7 +1974,7 @@ SArray* tsdbRetrieveDataBlock(TsdbQueryHandleT* pQueryHandle, SArray* pIdList) { return pHandle->pColumns; } else { // only load the file block SCompBlock* pBlock = pBlockInfo->compBlock; - doLoadFileDataBlock(pHandle, pBlock, pCheckInfo); + doLoadFileDataBlock(pHandle, pBlock, pCheckInfo, pHandle->cur.slot); // todo refactor int32_t numOfRows = copyDataFromFileBlock(pHandle, pHandle->outputCapacity, 0, 0, pBlock->numOfRows - 1); From b472a553830a89735b5383d277e074fe9119847c Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 23 Jul 2020 14:50:25 +0800 Subject: [PATCH 21/47] [td-225] destory qhandle. --- src/vnode/src/vnodeRead.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 83986de682..2586a2db99 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -236,6 +236,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { freeHandle = false; } else { qKillQuery(*handle); + qDestroyQueryInfo(*handle); freeHandle = true; } } From da88d370db238662dfeed1d3788efb1bd2153c60 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Thu, 23 Jul 2020 17:51:06 +0800 Subject: [PATCH 22/47] [td-225] update test scripts. --- src/query/inc/qExtbuffer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/query/inc/qExtbuffer.h b/src/query/inc/qExtbuffer.h index b57c48933f..aa30de4d0f 100644 --- a/src/query/inc/qExtbuffer.h +++ b/src/query/inc/qExtbuffer.h @@ -19,7 +19,6 @@ extern "C" { #endif - #include "os.h" #include "taosmsg.h" @@ -28,9 +27,9 @@ extern "C" { #include "tdataformat.h" #include "talgo.h" -#define DEFAULT_PAGE_SIZE (1024L*4) // 16k larger than the SHistoInfo #define MAX_TMPFILE_PATH_LENGTH PATH_MAX -#define INITIAL_ALLOCATION_BUFFER_SIZE 64 +#define INITIAL_ALLOCATION_BUFFER_SIZE 1L +#define DEFAULT_PAGE_SIZE (4096L*(INITIAL_ALLOCATION_BUFFER_SIZE)) // 16k larger than the SHistoInfo typedef enum EXT_BUFFER_FLUSH_MODEL { /* From 26bbbe221d0dcacda58b0d6d314278efecbcca49 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 24 Jul 2020 03:02:18 +0000 Subject: [PATCH 23/47] add query not ready msg --- src/dnode/src/dnodeVRead.c | 2 +- src/inc/taoserror.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index bbea1a5e0b..ebbad525dd 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -206,7 +206,7 @@ static void *dnodeProcessReadQueue(void *param) { taosMsg[pReadMsg->rpcMsg.msgType], type); int32_t code = vnodeProcessRead(pVnode, pReadMsg); - if (type == TAOS_QTYPE_RPC) { + if (type == TAOS_QTYPE_RPC && code != TSDB_CODE_QRY_NOT_READY) { dnodeSendRpcReadRsp(pVnode, pReadMsg, code); } else { dnodeDispatchNonRspMsg(pVnode, pReadMsg, code); diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 59b2c0220b..5a49f24804 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -210,6 +210,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_OUT_OF_MEMORY, 0, 0x0703, "query out TAOS_DEFINE_ERROR(TSDB_CODE_QRY_APP_ERROR, 0, 0x0704, "query app error") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_DUP_JOIN_KEY, 0, 0x0705, "query duplicated join key") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_EXCEED_TAGS_LIMIT, 0, 0x0706, "query tag conditon too many") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NOT_READY, 0, 0x0707, "query not ready") // grant TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_EXPIRED, 0, 0x0800, "grant expired") From 1a9fce812657ef47ac7323330b338bb1d086f013 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 24 Jul 2020 14:38:57 +0800 Subject: [PATCH 24/47] [td-225] avoid the retrieved thread being blocked. --- src/dnode/src/dnodeVRead.c | 6 ++- src/inc/query.h | 11 +++-- src/inc/taoserror.h | 1 + src/query/inc/qExecutor.h | 14 ++++-- src/query/src/qExecutor.c | 95 ++++++++++++++++++++++++++------------ src/vnode/src/vnodeRead.c | 50 ++++++++++++++------ 6 files changed, 127 insertions(+), 50 deletions(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index ebbad525dd..40b29cab79 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -209,7 +209,11 @@ static void *dnodeProcessReadQueue(void *param) { if (type == TAOS_QTYPE_RPC && code != TSDB_CODE_QRY_NOT_READY) { dnodeSendRpcReadRsp(pVnode, pReadMsg, code); } else { - dnodeDispatchNonRspMsg(pVnode, pReadMsg, code); + if (code == TSDB_CODE_QRY_HAS_RSP) { + dnodeSendRpcReadRsp(pVnode, pReadMsg, code); + } else { + dnodeDispatchNonRspMsg(pVnode, pReadMsg, code); + } } taosFreeQitem(pReadMsg); diff --git a/src/inc/query.h b/src/inc/query.h index d201b649f9..a9a21bc911 100644 --- a/src/inc/query.h +++ b/src/inc/query.h @@ -28,7 +28,7 @@ typedef void* qinfo_t; * @param qinfo * @return */ -int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryTableMsg, void* param, qinfo_t* qinfo); +int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryTableMsg, qinfo_t* qinfo); /** @@ -38,7 +38,10 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryTableMs * @param qinfo * @return */ -void qTableQuery(qinfo_t qinfo); +bool qTableQuery(qinfo_t qinfo); + +void* pGetRspMsg(qinfo_t qinfo); + /** * Retrieve the produced results information, if current query is not paused or completed, @@ -48,7 +51,7 @@ void qTableQuery(qinfo_t qinfo); * @param qinfo * @return */ -int32_t qRetrieveQueryResultInfo(qinfo_t qinfo); +int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContext); /** * @@ -60,7 +63,7 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo); * @param contLen payload length * @return */ -int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp** pRsp, int32_t* contLen); +int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp** pRsp, int32_t* contLen, bool* continueExec); /** * Decide if more results will be produced or not, NOTE: this function will increase the ref count of QInfo, diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 5a49f24804..697ce79715 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -211,6 +211,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_APP_ERROR, 0, 0x0704, "query app TAOS_DEFINE_ERROR(TSDB_CODE_QRY_DUP_JOIN_KEY, 0, 0x0705, "query duplicated join key") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_EXCEED_TAGS_LIMIT, 0, 0x0706, "query tag conditon too many") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NOT_READY, 0, 0x0707, "query not ready") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_HAS_RSP, 0, 0x0708, "query should response") // grant TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_EXPIRED, 0, 0x0800, "grant expired") diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index 92fe078c3f..b6f7b3600b 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -177,13 +177,18 @@ typedef struct SQueryRuntimeEnv { SDiskbasedResultBuf* pResultBuf; // query result buffer based on blocked-wised disk file } SQueryRuntimeEnv; +enum { + QUERY_RESULT_NOT_READY = 1, + QUERY_RESULT_READY = 2, +}; + typedef struct SQInfo { void* signature; int32_t pointsInterpo; int32_t code; // error code to returned to client - sem_t dataReady; +// sem_t dataReady; + void* tsdb; - void* param; int32_t vgId; STableGroupInfo tableGroupInfo; // table id list < only includes the STable list> STableGroupInfo tableqinfoGroupInfo; // this is a group array list, including SArray structure @@ -200,8 +205,11 @@ typedef struct SQInfo { */ int32_t tableIndex; int32_t numOfGroupResultPages; - void* pBuf; // allocated buffer for STableQueryInfo, sizeof(STableQueryInfo)*numOfTables; + void* pBuf; // allocated buffer for STableQueryInfo, sizeof(STableQueryInfo)*numOfTables; + pthread_mutex_t lock; // used to synchronize the rsp/query threads + int32_t dataReady; // denote if query result is ready or not + void* rspContext; // response context } SQInfo; #endif // TDENGINE_QUERYEXECUTOR_H diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 532bdeb43b..9e8a5839dd 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -5894,16 +5894,11 @@ static SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SArray* pTableIdList, } pQInfo->arrTableIdInfo = taosArrayInit(tableIndex, sizeof(STableIdInfo)); + pQInfo->dataReady = QUERY_RESULT_NOT_READY; + pthread_mutex_init(&pQInfo->lock, NULL); pQuery->pos = -1; pQuery->window = pQueryMsg->window; - - if (sem_init(&pQInfo->dataReady, 0, 0) != 0) { - int32_t code = TAOS_SYSTEM_ERROR(errno); - qError("QInfo:%p init dataReady sem failed, reason:%s", pQInfo, tstrerror(code)); - goto _cleanup; - } - colIdCheck(pQuery); qDebug("qmsg:%p QInfo:%p created", pQueryMsg, pQInfo); @@ -5943,7 +5938,7 @@ static bool isValidQInfo(void *param) { return (sig == (uint64_t)pQInfo); } -static int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, bool isSTable, void* param) { +static int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQInfo *pQInfo, bool isSTable) { int32_t code = TSDB_CODE_SUCCESS; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; @@ -5966,8 +5961,6 @@ static int32_t initQInfo(SQueryTableMsg *pQueryMsg, void *tsdb, int32_t vgId, SQ return TSDB_CODE_SUCCESS; } - pQInfo->param = param; - if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { qDebug("QInfo:%p no table qualified for tag filter, abort query", pQInfo); setQueryStatus(pQuery, QUERY_COMPLETED); @@ -6012,7 +6005,6 @@ static void freeQInfo(SQInfo *pQInfo) { tfree(pQuery->sdata[col]); } - sem_destroy(&(pQInfo->dataReady)); teardownQueryRuntimeEnv(&pQInfo->runtimeEnv); for (int32_t i = 0; i < pQuery->numOfFilterCols; ++i) { @@ -6164,7 +6156,7 @@ typedef struct SQueryMgmt { pthread_mutex_t lock; } SQueryMgmt; -int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, void* param, qinfo_t* pQInfo) { +int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qinfo_t* pQInfo) { assert(pQueryMsg != NULL && tsdb != NULL); int32_t code = TSDB_CODE_SUCCESS; @@ -6260,7 +6252,7 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, vo goto _over; } - code = initQInfo(pQueryMsg, tsdb, vgId, *pQInfo, isSTableQuery, param); + code = initQInfo(pQueryMsg, tsdb, vgId, *pQInfo, isSTableQuery); _over: free(tagCond); @@ -6300,26 +6292,32 @@ void qDestroyQueryInfo(qinfo_t qHandle) { freeQInfo(pQInfo); } -void qTableQuery(qinfo_t qinfo) { +static void setQueryResultReady(SQInfo* pQInfo) { + pthread_mutex_lock(&pQInfo->lock); + pQInfo->dataReady = QUERY_RESULT_READY; + pthread_mutex_unlock(&pQInfo->lock); +} + +bool qTableQuery(qinfo_t qinfo) { SQInfo *pQInfo = (SQInfo *)qinfo; if (pQInfo == NULL || pQInfo->signature != pQInfo) { qDebug("QInfo:%p has been freed, no need to execute", pQInfo); - return; + return false; } if (IS_QUERY_KILLED(pQInfo)) { qDebug("QInfo:%p it is already killed, abort", pQInfo); - sem_post(&pQInfo->dataReady); - return; + setQueryResultReady(pQInfo); + return false; } if (pQInfo->tableqinfoGroupInfo.numOfTables == 0) { setQueryStatus(pQInfo->runtimeEnv.pQuery, QUERY_COMPLETED); + setQueryResultReady(pQInfo); qDebug("QInfo:%p no table exists for query, abort", pQInfo); - sem_post(&pQInfo->dataReady); - return; + return false; } // error occurs, record the error code and return to client @@ -6327,8 +6325,9 @@ void qTableQuery(qinfo_t qinfo) { if (ret != TSDB_CODE_SUCCESS) { pQInfo->code = ret; qDebug("QInfo:%p query abort due to error/cancel occurs, code:%s", pQInfo, tstrerror(pQInfo->code)); - sem_post(&pQInfo->dataReady); - return; + + setQueryResultReady(pQInfo); + return false; } qDebug("QInfo:%p query task is launched", pQInfo); @@ -6353,10 +6352,23 @@ void qTableQuery(qinfo_t qinfo) { pQInfo, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows); } - sem_post(&pQInfo->dataReady); + taosMsleep(1000); + +// pQInfo->dataReady = QUERY_RESULT_READY; + bool buildRes = false; + pthread_mutex_lock(&pQInfo->lock); + pQInfo->dataReady = QUERY_RESULT_READY; + + if (pQInfo->rspContext != NULL) { + buildRes = true; + } + pthread_mutex_unlock(&pQInfo->lock); + + return buildRes; +// sem_post(&pQInfo->dataReady); } -int32_t qRetrieveQueryResultInfo(qinfo_t qinfo) { +int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContext) { SQInfo *pQInfo = (SQInfo *)qinfo; if (pQInfo == NULL || !isValidQInfo(pQInfo)) { @@ -6369,10 +6381,20 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo) { return pQInfo->code; } - sem_wait(&pQInfo->dataReady); - qDebug("QInfo:%p retrieve result info, rowsize:%d, rows:%"PRId64", code:%d", pQInfo, pQuery->rowSize, pQuery->rec.rows, - pQInfo->code); + *buildRes = false; + pthread_mutex_lock(&pQInfo->lock); + if (pQInfo->dataReady == QUERY_RESULT_READY) { + *buildRes = true; + qDebug("QInfo:%p retrieve result info, rowsize:%d, rows:%"PRId64", code:%d", pQInfo, pQuery->rowSize, pQuery->rec.rows, + pQInfo->code); + } else { + pQInfo->rspContext = pRspContext; + } + + pthread_mutex_unlock(&pQInfo->lock); + +// sem_wait(&pQInfo->dataReady); return pQInfo->code; } @@ -6385,6 +6407,7 @@ bool qHasMoreResultsToRetrieve(qinfo_t qinfo) { } SQuery *pQuery = pQInfo->runtimeEnv.pQuery; + bool ret = false; if (Q_STATUS_EQUAL(pQuery->status, QUERY_OVER)) { ret = false; @@ -6403,7 +6426,7 @@ bool qHasMoreResultsToRetrieve(qinfo_t qinfo) { return ret; } -int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *contLen) { +int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *contLen, bool* continueExec) { SQInfo *pQInfo = (SQInfo *)qinfo; if (pQInfo == NULL || !isValidQInfo(pQInfo)) { @@ -6413,8 +6436,10 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co SQueryRuntimeEnv* pRuntimeEnv = &pQInfo->runtimeEnv; SQuery *pQuery = pQInfo->runtimeEnv.pQuery; size_t size = getResultSize(pQInfo, &pQuery->rec.rows); + size += sizeof(int32_t); size += sizeof(STableIdInfo) * taosArrayGetSize(pQInfo->arrTableIdInfo); + *contLen = size + sizeof(SRetrieveTableRsp); // todo proper handle failed to allocate memory, @@ -6423,6 +6448,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co if (*pRsp == NULL) { return TSDB_CODE_QRY_OUT_OF_MEMORY; } + (*pRsp)->numOfRows = htonl(pQuery->rec.rows); int32_t code = pQInfo->code; @@ -6430,8 +6456,8 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co (*pRsp)->offset = htobe64(pQuery->limit.offset); (*pRsp)->useconds = htobe64(pRuntimeEnv->summary.elapsedTime); } else { - (*pRsp)->offset = 0; (*pRsp)->useconds = 0; + (*pRsp)->offset = 0; } (*pRsp)->precision = htons(pQuery->precision); @@ -6442,10 +6468,21 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co code = pQInfo->code; } + pQInfo->rspContext = NULL; + pQInfo->dataReady = QUERY_RESULT_NOT_READY; + if (IS_QUERY_KILLED(pQInfo) || Q_STATUS_EQUAL(pQuery->status, QUERY_OVER)) { (*pRsp)->completed = 1; // notify no more result to client } + if (qHasMoreResultsToRetrieve(pQInfo)) { + *continueExec = true; + } else { // failed to dump result, free qhandle immediately + *continueExec = false; + qKillQuery(pQInfo); + qDestroyQueryInfo(pQInfo); + } + return code; } @@ -6456,7 +6493,7 @@ int32_t qKillQuery(qinfo_t qinfo) { return TSDB_CODE_QRY_INVALID_QHANDLE; } - sem_post(&pQInfo->dataReady); +// sem_post(&pQInfo->dataReady); setQueryKilled(pQInfo); return TSDB_CODE_SUCCESS; } diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 2586a2db99..542c132e03 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -66,11 +66,12 @@ int32_t vnodeProcessRead(void *param, SReadMsg *pReadMsg) { return (*vnodeProcessReadMsgFp[msgType])(pVnode, pReadMsg); } -static void vnodePutItemIntoReadQueue(SVnodeObj *pVnode, void *qhandle) { +static void vnodePutItemIntoReadQueue(SVnodeObj *pVnode, void *qhandle, void* handle) { SReadMsg *pRead = (SReadMsg *)taosAllocateQitem(sizeof(SReadMsg)); pRead->rpcMsg.msgType = TSDB_MSG_TYPE_QUERY; pRead->pCont = qhandle; pRead->contLen = 0; + pRead->rpcMsg.handle = handle; atomic_add_fetch_32(&pVnode->refCount, 1); taosWriteQitem(pVnode->rqueue, TAOS_QTYPE_QUERY, pRead); @@ -110,7 +111,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (contLen != 0) { qinfo_t pQInfo = NULL; - code = qCreateQueryInfo(pVnode->tsdb, pVnode->vgId, pQueryTableMsg, pVnode, &pQInfo); + code = qCreateQueryInfo(pVnode->tsdb, pVnode->vgId, pQueryTableMsg, &pQInfo); SQueryTableRsp *pRsp = (SQueryTableRsp *) rpcMallocCont(sizeof(SQueryTableRsp)); pRsp->code = code; @@ -148,7 +149,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (handle != NULL) { vDebug("vgId:%d, QInfo:%p, dnode query msg disposed, register qhandle and return to app", vgId, *handle); - vnodePutItemIntoReadQueue(pVnode, *handle); + vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); // qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); } @@ -163,7 +164,23 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { } else { vDebug("vgId:%d, QInfo:%p, dnode continue exec query", pVnode->vgId, (void*) pCont); code = TSDB_CODE_VND_ACTION_IN_PROGRESS; - qTableQuery(*handle); // do execute query + bool buildRes = qTableQuery(*handle); // do execute query + + if (buildRes) { // build result rsp + pRet = &pReadMsg->rspRet; + + bool continueExec = false; + if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { + if (continueExec) { + vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); + pRet->qhandle = *handle; + + } + } else { // todo handle error + } + + code = TSDB_CODE_QRY_HAS_RSP; + } } // qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); } @@ -223,22 +240,29 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { } bool freeHandle = true; - code = qRetrieveQueryResultInfo(*handle); + bool buildRes = false; + + code = qRetrieveQueryResultInfo(*handle, &buildRes, pReadMsg); if (code != TSDB_CODE_SUCCESS) { //TODO handle malloc failure pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); - } else { // if failed to dump result, free qhandle immediately - if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len)) == TSDB_CODE_SUCCESS) { - if (qHasMoreResultsToRetrieve(*handle)) { - vnodePutItemIntoReadQueue(pVnode, *handle); + } else { + // result is not ready, return immediately + if (!buildRes) { + return TSDB_CODE_QRY_NOT_READY; + } + + bool continueExec = false; + if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { + if (continueExec) { + vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); pRet->qhandle = *handle; freeHandle = false; - } else { - qKillQuery(*handle); - qDestroyQueryInfo(*handle); - freeHandle = true; } + } else { + pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); + memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); } } From d9a04b397ffe8eada57a3cc87781b971896a4232 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 24 Jul 2020 15:05:44 +0800 Subject: [PATCH 25/47] [td-225] fix bugs in non-blocking processing. --- src/dnode/src/dnodeVRead.c | 2 +- src/query/src/qExecutor.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index 40b29cab79..f8a31d568e 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -210,7 +210,7 @@ static void *dnodeProcessReadQueue(void *param) { dnodeSendRpcReadRsp(pVnode, pReadMsg, code); } else { if (code == TSDB_CODE_QRY_HAS_RSP) { - dnodeSendRpcReadRsp(pVnode, pReadMsg, code); + dnodeSendRpcReadRsp(pVnode, pReadMsg, TSDB_CODE_SUCCESS); } else { dnodeDispatchNonRspMsg(pVnode, pReadMsg, code); } diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 9e8a5839dd..c4142f5d93 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6352,8 +6352,6 @@ bool qTableQuery(qinfo_t qinfo) { pQInfo, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows); } - taosMsleep(1000); - // pQInfo->dataReady = QUERY_RESULT_READY; bool buildRes = false; pthread_mutex_lock(&pQInfo->lock); From 699f28284132596e0288ebb2c5d6b0059995e48b Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 25 Jul 2020 00:22:46 +0800 Subject: [PATCH 26/47] [td-225] fix bugs in non-blocking processing. --- src/dnode/src/dnodeVRead.c | 2 +- src/query/src/qExecutor.c | 7 +++---- src/vnode/src/vnodeRead.c | 7 +++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index f8a31d568e..85ed194976 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -49,7 +49,7 @@ static taos_qset readQset; int32_t dnodeInitVnodeRead() { readQset = taosOpenQset(); - readPool.min = 2; + readPool.min = 4; readPool.max = tsNumOfCores * tsNumOfThreadsPerCore; if (readPool.max <= readPool.min * 2) readPool.max = 2 * readPool.min; readPool.readWorker = (SReadWorker *)calloc(sizeof(SReadWorker), readPool.max); diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index c4142f5d93..6de300400e 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6352,7 +6352,6 @@ bool qTableQuery(qinfo_t qinfo) { pQInfo, pQuery->rec.rows, pQuery->rec.total + pQuery->rec.rows); } -// pQInfo->dataReady = QUERY_RESULT_READY; bool buildRes = false; pthread_mutex_lock(&pQInfo->lock); pQInfo->dataReady = QUERY_RESULT_READY; @@ -6360,8 +6359,9 @@ bool qTableQuery(qinfo_t qinfo) { if (pQInfo->rspContext != NULL) { buildRes = true; } - pthread_mutex_unlock(&pQInfo->lock); + + pthread_mutex_unlock(&pQInfo->lock); return buildRes; // sem_post(&pQInfo->dataReady); } @@ -6387,12 +6387,11 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex qDebug("QInfo:%p retrieve result info, rowsize:%d, rows:%"PRId64", code:%d", pQInfo, pQuery->rowSize, pQuery->rec.rows, pQInfo->code); } else { + qDebug("QInfo:%p retrieve req set query return result after paused", pQInfo); pQInfo->rspContext = pRspContext; } pthread_mutex_unlock(&pQInfo->lock); - -// sem_wait(&pQInfo->dataReady); return pQInfo->code; } diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 542c132e03..5edfcf597c 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -163,18 +163,21 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { code = TSDB_CODE_QRY_INVALID_QHANDLE; } else { vDebug("vgId:%d, QInfo:%p, dnode continue exec query", pVnode->vgId, (void*) pCont); - code = TSDB_CODE_VND_ACTION_IN_PROGRESS; bool buildRes = qTableQuery(*handle); // do execute query if (buildRes) { // build result rsp + vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused", pVnode->vgId, *handle); + pRet = &pReadMsg->rspRet; bool continueExec = false; + code = TSDB_CODE_QRY_HAS_RSP; if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { + if (continueExec) { vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); pRet->qhandle = *handle; - + code = TSDB_CODE_SUCCESS; } } else { // todo handle error } From 4ce8f84e7e9f8a0ed7a1a255df6a24bd67b57118 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 25 Jul 2020 10:27:27 +0800 Subject: [PATCH 27/47] [td-225] fix bugs in non-blocking processing. --- src/query/src/qExecutor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 6de300400e..28d1c138f6 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6380,6 +6380,8 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex } *buildRes = false; + int32_t code = TSDB_CODE_SUCCESS; + pthread_mutex_lock(&pQInfo->lock); if (pQInfo->dataReady == QUERY_RESULT_READY) { *buildRes = true; @@ -6391,8 +6393,9 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex pQInfo->rspContext = pRspContext; } + code = pQInfo->code; pthread_mutex_unlock(&pQInfo->lock); - return pQInfo->code; + return code; } bool qHasMoreResultsToRetrieve(qinfo_t qinfo) { From 956eafa03165ab59c8f6b84fd416fd981f143320 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Sat, 25 Jul 2020 06:45:58 +0000 Subject: [PATCH 28/47] update cache expire time --- src/mnode/src/mnodeProfile.c | 4 ++-- src/plugins/http/src/httpContext.c | 2 +- src/util/src/tcache.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mnode/src/mnodeProfile.c b/src/mnode/src/mnodeProfile.c index 9121f31131..30a292f522 100644 --- a/src/mnode/src/mnodeProfile.c +++ b/src/mnode/src/mnodeProfile.c @@ -68,7 +68,7 @@ int32_t mnodeInitProfile() { mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_KILL_STREAM, mnodeProcessKillStreamMsg); mnodeAddWriteMsgHandle(TSDB_MSG_TYPE_CM_KILL_CONN, mnodeProcessKillConnectionMsg); - tsMnodeConnCache = taosCacheInit(TSDB_DATA_TYPE_INT, CONN_CHECK_TIME, false, mnodeFreeConn, "conn"); + tsMnodeConnCache = taosCacheInit(TSDB_DATA_TYPE_INT, CONN_CHECK_TIME, true, mnodeFreeConn, "conn"); return 0; } @@ -119,7 +119,7 @@ SConnObj *mnodeAccquireConn(int32_t connId, char *user, uint32_t ip, uint16_t po return NULL; } - if (pConn->ip != ip || pConn->port != port /* || strcmp(pConn->user, user) != 0 */) { + if (/* pConn->ip != ip || */ pConn->port != port /* || strcmp(pConn->user, user) != 0 */) { mError("connId:%d, incoming conn user:%s ip:%s:%u, not match exist conn user:%s ip:%s:%u", connId, user, taosIpStr(ip), port, pConn->user, taosIpStr(pConn->ip), pConn->port); taosCacheRelease(tsMnodeConnCache, (void **)&pConn, false); diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c index 225977abae..ca65f65608 100644 --- a/src/plugins/http/src/httpContext.c +++ b/src/plugins/http/src/httpContext.c @@ -58,7 +58,7 @@ static void httpDestroyContext(void *data) { } bool httpInitContexts() { - tsHttpServer.contextCache = taosCacheInit(TSDB_DATA_TYPE_BIGINT, 2, false, httpDestroyContext, "restc"); + tsHttpServer.contextCache = taosCacheInit(TSDB_DATA_TYPE_BIGINT, 2, true, httpDestroyContext, "restc"); if (tsHttpServer.contextCache == NULL) { httpError("failed to init context cache"); return false; diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 7c2a6b3219..3a3acdc05b 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -343,7 +343,7 @@ void* taosCacheUpdateExpireTimeByName(SCacheObj *pCacheObj, void *key, size_t ke SCacheDataNode **ptNode = (SCacheDataNode **)taosHashGet(pCacheObj->pHashTable, key, keyLen); if (ptNode != NULL) { T_REF_INC(*ptNode); - (*ptNode)->expireTime = taosGetTimestampMs() + (*ptNode)->lifespan; + (*ptNode)->expireTime = expireTime; // taosGetTimestampMs() + (*ptNode)->lifespan; } __cache_unlock(pCacheObj); From b04e3da3d8847229af3fa67f06d21674dd562f4b Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 27 Jul 2020 15:32:53 +0800 Subject: [PATCH 29/47] [td-225] fix bugs in res buf --- src/client/src/tscFunctionImpl.c | 5 + src/query/inc/qExecutor.h | 4 +- src/query/inc/qExtbuffer.h | 2 +- src/query/inc/qResultbuf.h | 26 +- src/query/inc/qUtil.h | 7 +- src/query/src/qExecutor.c | 64 ++--- src/query/src/qResultbuf.c | 302 ++++++++++++---------- src/query/src/qUtil.c | 13 +- src/query/tests/resultBufferTest.cpp | 53 ++++ src/util/inc/tlist.h | 2 + src/util/src/tlist.c | 16 ++ tests/script/general/parser/testSuite.sim | 2 + tests/script/general/parser/topbot.sim | 74 ++++++ 13 files changed, 395 insertions(+), 175 deletions(-) create mode 100644 tests/script/general/parser/topbot.sim diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c index 72ccd5adc6..17f6c97ea1 100644 --- a/src/client/src/tscFunctionImpl.c +++ b/src/client/src/tscFunctionImpl.c @@ -2131,6 +2131,11 @@ static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) { } bool topbot_datablock_filter(SQLFunctionCtx *pCtx, int32_t functionId, const char *minval, const char *maxval) { + SResultInfo *pResInfo = GET_RES_INFO(pCtx); + if (pResInfo == NULL) { + return true; + } + STopBotInfo *pTopBotInfo = getTopBotOutputInfo(pCtx); // required number of results are not reached, continue load data block diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index 92fe078c3f..a18f8e2731 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -42,8 +42,8 @@ typedef struct SSqlGroupbyExpr { } SSqlGroupbyExpr; typedef struct SPosInfo { - int16_t pageId; - int16_t rowId; + int32_t pageId; + int32_t rowId; } SPosInfo; typedef struct SWindowStatus { diff --git a/src/query/inc/qExtbuffer.h b/src/query/inc/qExtbuffer.h index b57c48933f..2cbef2b1be 100644 --- a/src/query/inc/qExtbuffer.h +++ b/src/query/inc/qExtbuffer.h @@ -28,7 +28,7 @@ extern "C" { #include "tdataformat.h" #include "talgo.h" -#define DEFAULT_PAGE_SIZE (1024L*4) // 16k larger than the SHistoInfo +#define DEFAULT_PAGE_SIZE (1024L*64) // 16k larger than the SHistoInfo #define MAX_TMPFILE_PATH_LENGTH PATH_MAX #define INITIAL_ALLOCATION_BUFFER_SIZE 64 diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index da5f46b5e9..ba446b4627 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -34,10 +34,11 @@ typedef struct SPageDiskInfo { } SPageDiskInfo; typedef struct SPageInfo { + SListNode* pn; // point to list node int32_t pageId; SPageDiskInfo info; void* pData; - T_REF_DECLARE(); + bool used; // set current page is in used } SPageInfo; typedef struct SFreeListItem { @@ -45,6 +46,15 @@ typedef struct SFreeListItem { int32_t len; } SFreeListItem; +typedef struct SResultBufStatis { + int32_t flushBytes; + int32_t loadBytes; + int32_t getPages; + int32_t releasePages; + int32_t flushPages; + int32_t fileSize; +} SResultBufStatis; + typedef struct SDiskbasedResultBuf { int32_t numOfRowsPerPage; int32_t numOfPages; @@ -64,6 +74,8 @@ typedef struct SDiskbasedResultBuf { void* assistBuf; // assistant buffer for compress data SArray* pFree; // free area in file int32_t nextPos; // next page flush position + + SResultBufStatis statis; } SDiskbasedResultBuf; #define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) @@ -119,6 +131,16 @@ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); */ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page); +void releaseResBufPageInfo(SDiskbasedResultBuf* pResultBuf, SPageInfo* pi); + +/** + * + * @param pResultBuf + * @param id + * @return + */ +//tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); + /** * get the total buffer size in the format of disk file * @param pResultBuf @@ -144,7 +166,7 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle); * @param pList * @return */ -int32_t getLastPageId(SIDList pList); +SPageInfo* getLastPageInfo(SIDList pList); #ifdef __cplusplus } diff --git a/src/query/inc/qUtil.h b/src/query/inc/qUtil.h index 7119cb75fe..ed7c7e8845 100644 --- a/src/query/inc/qUtil.h +++ b/src/query/inc/qUtil.h @@ -45,13 +45,14 @@ bool isWindowResClosed(SWindowResInfo *pWindowResInfo, int32_t slot); int32_t createQueryResultInfo(SQuery *pQuery, SWindowResult *pResultRow, bool isSTableQuery, size_t interBufSize); -static FORCE_INLINE char *getPosInResultPage(SQueryRuntimeEnv *pRuntimeEnv, int32_t columnIndex, SWindowResult *pResult) { +static FORCE_INLINE char *getPosInResultPage(SQueryRuntimeEnv *pRuntimeEnv, int32_t columnIndex, SWindowResult *pResult, + tFilePage* page) { assert(pResult != NULL && pRuntimeEnv != NULL); SQuery *pQuery = pRuntimeEnv->pQuery; - tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pos.pageId); - int32_t realRowId = pResult->pos.rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery); +// tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pos.pageId); + int32_t realRowId = pResult->pos.rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery); return ((char *)page->data) + pRuntimeEnv->offset[columnIndex] * pRuntimeEnv->numOfRowsPerPage + pQuery->pSelectExpr[columnIndex].bytes * realRowId; } diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 30d6cc288f..9d873dc95f 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -221,7 +221,7 @@ void updateNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOfRes) { } static int32_t getGroupResultId(int32_t groupIndex) { - int32_t base = 200000; + int32_t base = 20000000; return base + (groupIndex * 10000); } @@ -478,10 +478,14 @@ static int32_t addNewWindowResultBuf(SWindowResult *pWindowRes, SDiskbasedResult if (taosArrayGetSize(list) == 0) { pData = getNewDataBuf(pResultBuf, sid, &pageId); } else { - pageId = getLastPageId(list); - pData = getResBufPage(pResultBuf, pageId); + SPageInfo* pi = getLastPageInfo(list); + pData = getResBufPage(pResultBuf, pi->pageId); + pageId = pi->pageId; if (pData->num >= numOfRowsPerPage) { + // release current page first, and prepare the next one + releaseResBufPageInfo(pResultBuf, pi); + pData = getNewDataBuf(pResultBuf, sid, &pageId); if (pData != NULL) { assert(pData->num == 0); // number of elements must be 0 for new allocated buffer @@ -497,6 +501,8 @@ static int32_t addNewWindowResultBuf(SWindowResult *pWindowRes, SDiskbasedResult if (pWindowRes->pos.pageId == -1) { // not allocated yet, allocate new buffer pWindowRes->pos.pageId = pageId; pWindowRes->pos.rowId = pData->num++; + + assert(pWindowRes->pos.pageId >= 0); } return 0; @@ -2111,9 +2117,6 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv *pRuntimeEnv, void* pQueryHandle, } if (!needToLoadDataBlock(pRuntimeEnv, *pStatis, pRuntimeEnv->pCtx, pBlockInfo->rows)) { -#if defined(_DEBUG_VIEW) - qDebug("QInfo:%p block discarded by per-filter", GET_QINFO_ADDR(pRuntimeEnv)); -#endif // current block has been discard due to filter applied pRuntimeEnv->summary.discardBlocks += 1; qDebug("QInfo:%p data block discard, brange:%"PRId64 "-%"PRId64", rows:%d", GET_QINFO_ADDR(pRuntimeEnv), @@ -2446,6 +2449,8 @@ static void doMerge(SQueryRuntimeEnv *pRuntimeEnv, int64_t timestamp, SWindowRes SQuery * pQuery = pRuntimeEnv->pQuery; SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx; + tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pWindowRes->pos.pageId); + for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t functionId = pQuery->pSelectExpr[i].base.functionId; if (!mergeFlag) { @@ -2458,7 +2463,7 @@ static void doMerge(SQueryRuntimeEnv *pRuntimeEnv, int64_t timestamp, SWindowRes pCtx[i].hasNull = true; pCtx[i].nStartQueryTimestamp = timestamp; - pCtx[i].aInputElemBuf = getPosInResultPage(pRuntimeEnv, i, pWindowRes); + pCtx[i].aInputElemBuf = getPosInResultPage(pRuntimeEnv, i, pWindowRes, page); // in case of tag column, the tag information should be extracted from input buffer if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TAG) { @@ -2615,14 +2620,16 @@ int32_t tableResultComparFn(const void *pLeft, const void *pRight, void *param) SWindowResInfo *pWindowResInfo1 = &supporter->pTableQueryInfo[left]->windowResInfo; SWindowResult * pWindowRes1 = getWindowResult(pWindowResInfo1, leftPos); + tFilePage *page1 = getResBufPage(pRuntimeEnv->pResultBuf, pWindowRes1->pos.pageId); - char *b1 = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes1); + char *b1 = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes1, page1); TSKEY leftTimestamp = GET_INT64_VAL(b1); SWindowResInfo *pWindowResInfo2 = &supporter->pTableQueryInfo[right]->windowResInfo; SWindowResult * pWindowRes2 = getWindowResult(pWindowResInfo2, rightPos); + tFilePage *page2 = getResBufPage(pRuntimeEnv->pResultBuf, pWindowRes2->pos.pageId); - char *b2 = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes2); + char *b2 = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes2, page2); TSKEY rightTimestamp = GET_INT64_VAL(b2); if (leftTimestamp == rightTimestamp) { @@ -2685,35 +2692,26 @@ void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { int32_t id = getGroupResultId(pQInfo->groupIndex - 1); SIDList list = getDataBufPagesIdList(pResultBuf, pQInfo->offset + id); - int32_t total = 0; int32_t size = taosArrayGetSize(list); - for (int32_t i = 0; i < size; ++i) { - int32_t* pgId = taosArrayGet(list, i); - tFilePage *pData = getResBufPage(pResultBuf, *pgId); - total += pData->num; - } - - int32_t rows = total; int32_t offset = 0; for (int32_t j = 0; j < size; ++j) { - int32_t* pgId = taosArrayGet(list, j); - tFilePage *pData = getResBufPage(pResultBuf, *pgId); + SPageInfo* pi = *(SPageInfo**) taosArrayGet(list, j); + tFilePage *pData = getResBufPage(pResultBuf, pi->pageId); for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t bytes = pRuntimeEnv->pCtx[i].outputBytes; char * pDest = pQuery->sdata[i]->data; - - memcpy(pDest + offset * bytes, pData->data + pRuntimeEnv->offset[i] * pData->num, - bytes * pData->num); + memcpy(pDest + offset * bytes, pData->data + pRuntimeEnv->offset[i] * pData->num, bytes * pData->num); } +// rows += pData->num; offset += pData->num; } assert(pQuery->rec.rows == 0); - pQuery->rec.rows += rows; + pQuery->rec.rows += offset; pQInfo->offset += 1; } @@ -2777,7 +2775,6 @@ int32_t mergeIntoGroupResultImpl(SQInfo *pQInfo, SArray *pGroup) { assert(pQInfo->numOfGroupResultPages == 0); return 0; } else if (numOfTables == 1) { // no need to merge results since only one table in each group - } SCompSupporter cs = {pTableList, posList, pQInfo}; @@ -2802,8 +2799,9 @@ int32_t mergeIntoGroupResultImpl(SQInfo *pQInfo, SArray *pGroup) { SWindowResInfo *pWindowResInfo = &pTableList[pos]->windowResInfo; SWindowResult * pWindowRes = getWindowResult(pWindowResInfo, cs.position[pos]); + tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pWindowRes->pos.pageId); - char *b = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes); + char *b = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes, page); TSKEY ts = GET_INT64_VAL(b); assert(ts == pWindowRes->window.skey); @@ -3517,9 +3515,11 @@ void setWindowResOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *pResult SQuery *pQuery = pRuntimeEnv->pQuery; // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group + tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pos.pageId); + for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; - pCtx->aOutputBuf = getPosInResultPage(pRuntimeEnv, i, pResult); + pCtx->aOutputBuf = getPosInResultPage(pRuntimeEnv, i, pResult, page); int32_t functionId = pQuery->pSelectExpr[i].base.functionId; if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { @@ -3542,6 +3542,8 @@ void setWindowResOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult * SQuery *pQuery = pRuntimeEnv->pQuery; // Note: pResult->pos[i]->num == 0, there is only fixed number of results for each group + tFilePage* bufPage = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pos.pageId); + for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i]; @@ -3550,7 +3552,7 @@ void setWindowResOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult * continue; } - pCtx->aOutputBuf = getPosInResultPage(pRuntimeEnv, i, pResult); + pCtx->aOutputBuf = getPosInResultPage(pRuntimeEnv, i, pResult, bufPage); pCtx->currentStage = 0; int32_t functionId = pCtx->functionId; @@ -3713,11 +3715,13 @@ static int32_t doCopyToSData(SQInfo *pQInfo, SWindowResInfo *pResultInfo, int32_ pQInfo->groupIndex += 1; } + tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, result[i].pos.pageId); + for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { int32_t size = pRuntimeEnv->pCtx[j].outputBytes; char *out = pQuery->sdata[j]->data + numOfResult * size; - char *in = getPosInResultPage(pRuntimeEnv, j, &result[i]); + char *in = getPosInResultPage(pRuntimeEnv, j, &result[i], page); memcpy(out, in + oldOffset * size, size * numOfRowsToCopy); } @@ -4240,8 +4244,8 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); if (isSTableQuery && !onlyQueryTags(pRuntimeEnv->pQuery)) { - int32_t numOfPages = getInitialPageNum(pQInfo); - code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, numOfPages, rowsize, ps, numOfPages, pQInfo); +// int32_t numOfPages = getInitialPageNum(pQInfo); + code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, 2, rowsize, ps, 2, pQInfo); if (code != TSDB_CODE_SUCCESS) { return code; } diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index fa2bb814f2..fbb5f116e6 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -1,11 +1,13 @@ #include "qResultbuf.h" -#include -#include +#include "stddef.h" +#include "tscompression.h" #include "hash.h" #include "qExtbuffer.h" #include "queryLog.h" #include "taoserror.h" +#define GET_DATA_PAYLOAD(_p) ((_p)->pData + POINTER_BYTES) + int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t numOfPages, int32_t rowSize, int32_t pagesize, int32_t inMemPages, const void* handle) { @@ -15,23 +17,22 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu return TSDB_CODE_COM_OUT_OF_MEMORY; } - pResBuf->pageSize = pagesize; - pResBuf->numOfPages = 0; // all pages are in buffer in the first place - pResBuf->inMemPages = inMemPages; + pResBuf->pageSize = pagesize; + pResBuf->numOfPages = 0; // all pages are in buffer in the first place + pResBuf->inMemPages = inMemPages; + pResBuf->totalBufSize = pResBuf->numOfPages * pagesize; + pResBuf->allocateId = -1; + pResBuf->comp = true; + assert(inMemPages <= numOfPages); pResBuf->numOfRowsPerPage = (pagesize - sizeof(tFilePage)) / rowSize; - - pResBuf->totalBufSize = pResBuf->numOfPages * pagesize; - pResBuf->allocateId = -1; - pResBuf->lruList = tdListNew(POINTER_BYTES); // init id hash table pResBuf->groupSet = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); pResBuf->all = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); pResBuf->assistBuf = malloc(pResBuf->pageSize + 2); // EXTRA BYTES - pResBuf->comp = true; char path[PATH_MAX] = {0}; getTmpfilePath("qbuf", path); @@ -49,7 +50,7 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu #define NUM_OF_PAGES_ON_DISK(_r) ((_r)->numOfPages - (_r)->inMemPages) #define FILE_SIZE_ON_DISK(_r) (NUM_OF_PAGES_ON_DISK(_r) * (_r)->pageSize) -static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { +static int32_t createDiskFile(SDiskbasedResultBuf* pResultBuf) { pResultBuf->file = fopen(pResultBuf->path, "wb+"); if (pResultBuf->file == NULL) { qError("failed to create tmp file: %s on disk. %s", pResultBuf->path, strerror(errno)); @@ -59,15 +60,27 @@ static int32_t createDiskResidesBuf(SDiskbasedResultBuf* pResultBuf) { return TSDB_CODE_SUCCESS; } -static char* doCompressData(void* data, int32_t srcSize, int32_t *dst, bool comp, void* assistBuf) { // do nothing - if (!comp) { +static char* doCompressData(void* data, int32_t srcSize, int32_t *dst, SDiskbasedResultBuf* pResultBuf) { // do nothing + if (!pResultBuf->comp) { *dst = srcSize; return data; } - *dst = tsCompressString(data, srcSize, 1, assistBuf, srcSize, ONE_STAGE_COMP, NULL, 0); + *dst = tsCompressString(data, srcSize, 1, pResultBuf->assistBuf, srcSize, ONE_STAGE_COMP, NULL, 0); - memcpy(data, assistBuf, *dst); + memcpy(data, pResultBuf->assistBuf, *dst); + return data; +} + +static char* doDecompressData(void* data, int32_t srcSize, int32_t *dst, SDiskbasedResultBuf* pResultBuf) { // do nothing + if (!pResultBuf->comp) { + *dst = srcSize; + return data; + } + + *dst = tsDecompressString(data, srcSize, 1, pResultBuf->assistBuf, pResultBuf->pageSize, ONE_STAGE_COMP, NULL, 0); + + memcpy(data, pResultBuf->assistBuf, *dst); return data; } @@ -96,11 +109,10 @@ static int32_t allocatePositionInFile(SDiskbasedResultBuf* pResultBuf, size_t si } static char* doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { - assert(T_REF_VAL_GET(pg) == 0 && pg->pData != NULL); + assert(!pg->used && pg->pData != NULL); int32_t size = -1; - char* t = doCompressData(pg->pData + POINTER_BYTES, pResultBuf->pageSize, &size, pResultBuf->comp, pResultBuf->assistBuf); - pg->info.length = size; + char* t = doCompressData(GET_DATA_PAYLOAD(pg), pResultBuf->pageSize, &size, pResultBuf); // this page is flushed to disk for the first time if (pg->info.offset == -1) { @@ -108,26 +120,30 @@ static char* doFlushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { pResultBuf->nextPos += size; fseek(pResultBuf->file, pg->info.offset, SEEK_SET); - int32_t ret = fwrite(t, 1, size, pResultBuf->file); - - UNUSED(ret); + /*int32_t ret =*/ fwrite(t, 1, size, pResultBuf->file); } else { - if (pg->info.length < size) { // length becomes greater, current space is not enough, allocate new place. - //1. add current space to free list + // length becomes greater, current space is not enough, allocate new place, otherwise, do nothing + if (pg->info.length < size) { + // 1. add current space to free list taosArrayPush(pResultBuf->pFree, &pg->info); - //2. allocate new position, and update the info + // 2. allocate new position, and update the info pg->info.offset = allocatePositionInFile(pResultBuf, size); pResultBuf->nextPos += size; - - //3. write to disk. - fseek(pResultBuf->file, pg->info.offset, SEEK_SET); - fwrite(t, size, 1, pResultBuf->file); } + + //3. write to disk. + fseek(pResultBuf->file, pg->info.offset, SEEK_SET); + fwrite(t, size, 1, pResultBuf->file); } char* ret = pg->pData; + memset(ret, 0, pResultBuf->pageSize); + pg->pData = NULL; + pg->info.length = size; + + pResultBuf->statis.flushBytes += pg->info.length; return ret; } @@ -137,7 +153,7 @@ static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { assert(pResultBuf->numOfPages * pResultBuf->pageSize == pResultBuf->totalBufSize && pResultBuf->numOfPages >= pResultBuf->inMemPages); if (pResultBuf->file == NULL) { - if ((ret = createDiskResidesBuf(pResultBuf)) != TSDB_CODE_SUCCESS) { + if ((ret = createDiskFile(pResultBuf)) != TSDB_CODE_SUCCESS) { terrno = ret; return NULL; } @@ -146,12 +162,29 @@ static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { return doFlushPageToDisk(pResultBuf, pg); } +// load file block data in disk +static char* loadPageFromDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { + int32_t ret = fseek(pResultBuf->file, pg->info.offset, SEEK_SET); + ret = fread(GET_DATA_PAYLOAD(pg), 1, pg->info.length, pResultBuf->file); + if (ret != pg->info.length) { + terrno = errno; + return NULL; + } + + pResultBuf->statis.loadBytes += pg->info.length; + + int32_t fullSize = 0; + doDecompressData(GET_DATA_PAYLOAD(pg), pg->info.length, &fullSize, pResultBuf); + + return GET_DATA_PAYLOAD(pg); +} + #define NO_AVAILABLE_PAGES(_b) ((_b)->numOfPages >= (_b)->inMemPages) static SIDList addNewGroup(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { assert(taosHashGet(pResultBuf->groupSet, (const char*) &groupId, sizeof(int32_t)) == NULL); - SArray* pa = taosArrayInit(1, sizeof(SPageInfo)); + SArray* pa = taosArrayInit(1, POINTER_BYTES); int32_t ret = taosHashPut(pResultBuf->groupSet, (const char*)&groupId, sizeof(int32_t), &pa, POINTER_BYTES); assert(ret == 0); @@ -170,44 +203,79 @@ static SPageInfo* registerPage(SDiskbasedResultBuf* pResultBuf, int32_t groupId, pResultBuf->numOfPages += 1; - SPageInfo ppi = { .info = PAGE_INFO_INITIALIZER, .pageId = pageId, }; - return taosArrayPush(list, &ppi); + SPageInfo* ppi = malloc(sizeof(SPageInfo));//{ .info = PAGE_INFO_INITIALIZER, .pageId = pageId, .pn = NULL}; + ppi->info = PAGE_INFO_INITIALIZER; + ppi->pageId = pageId; + ppi->pData = NULL; + ppi->pn = NULL; + ppi->used = true; + + return *(SPageInfo**) taosArrayPush(list, &ppi); +} + +static SListNode* getEldestUnrefedPage(SDiskbasedResultBuf* pResultBuf) { + SListIter iter = {0}; + tdListInitIter(pResultBuf->lruList, &iter, TD_LIST_BACKWARD); + + SListNode* pn = NULL; + while((pn = tdListNext(&iter)) != NULL) { + assert(pn != NULL); + + SPageInfo* pageInfo = *(SPageInfo**) pn->data; + assert(pageInfo->pageId >= 0 && pageInfo->pn == pn); + + if (!pageInfo->used) { + break; + } + } + + return pn; +} + +static char* evicOneDataPage(SDiskbasedResultBuf* pResultBuf) { + char* bufPage = NULL; + SListNode* pn = getEldestUnrefedPage(pResultBuf); + + // all pages are referenced by user, try to allocate new space + if (pn == NULL) { + int32_t prev = pResultBuf->inMemPages; + pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; + + qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, + pResultBuf->inMemPages, pResultBuf->pageSize); + } else { + pResultBuf->statis.flushPages += 1; + tdListPopNode(pResultBuf->lruList, pn); + + SPageInfo* d = *(SPageInfo**) pn->data; + assert(d->pn == pn); + + d->pn = NULL; + tfree(pn); + + bufPage = flushPageToDisk(pResultBuf, d); + } + + return bufPage; +} + +static void lruListPushFront(SList *pList, SPageInfo* pi) { + tdListPrepend(pList, &pi); + SListNode* front = tdListGetHead(pList); + pi->pn = front; +} + +static void lruListMoveToFront(SList *pList, SPageInfo* pi) { + tdListPopNode(pList, pi->pn); + tdListPrependNode(pList, pi->pn); } tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId) { - char* allocPg = NULL; + pResultBuf->statis.getPages += 1; + char* availablePage = NULL; if (NO_AVAILABLE_PAGES(pResultBuf)) { - - // get the last page in linked list - SListIter iter = {0}; - tdListInitIter(pResultBuf->lruList, &iter, TD_LIST_BACKWARD); - - SListNode* pn = NULL; - while((pn = tdListNext(&iter)) != NULL) { - assert(pn != NULL); - if (T_REF_VAL_GET(*(SPageInfo**)pn->data) == 0) { - break; - } - } - - // all pages are referenced by user, try to allocate new space - if (pn == NULL) { - int32_t prev = pResultBuf->inMemPages; - pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; - - qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, - pResultBuf->inMemPages, pResultBuf->pageSize); - } else { - tdListPopNode(pResultBuf->lruList, pn); - SPageInfo* d = *(SPageInfo**) pn->data; - tfree(pn); - - allocPg = flushPageToDisk(pResultBuf, d); - if (allocPg == NULL) { - return NULL; - } - } + availablePage = evicOneDataPage(pResultBuf); } // register new id in this group @@ -216,111 +284,72 @@ tFilePage* getNewDataBuf(SDiskbasedResultBuf* pResultBuf, int32_t groupId, int32 // register page id info SPageInfo* pi = registerPage(pResultBuf, groupId, *pageId); + assert(pResultBuf->inMemPages > 0); + // add to LRU list assert(listNEles(pResultBuf->lruList) < pResultBuf->inMemPages); - tdListPrepend(pResultBuf->lruList, &pi); + lruListPushFront(pResultBuf->lruList, pi); // add to hash map taosHashPut(pResultBuf->all, pageId, sizeof(int32_t), &pi, POINTER_BYTES); // allocate buf - if (allocPg == NULL) { + if (availablePage == NULL) { pi->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES); } else { - pi->pData = allocPg; + pi->pData = availablePage; } pResultBuf->totalBufSize += pResultBuf->pageSize; - T_REF_INC(pi); // add ref count ((void**)pi->pData)[0] = pi; + pi->used = true; - return pi->pData + POINTER_BYTES; + return GET_DATA_PAYLOAD(pi); } tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id) { assert(pResultBuf != NULL && id >= 0); + pResultBuf->statis.getPages += 1; SPageInfo** pi = taosHashGet(pResultBuf->all, &id, sizeof(int32_t)); assert(pi != NULL && *pi != NULL); if ((*pi)->pData != NULL) { // it is in memory - // no need to update the LRU list + // no need to update the LRU list if only one page exists if (pResultBuf->numOfPages == 1) { - return (*pi)->pData + POINTER_BYTES; + (*pi)->used = true; + return GET_DATA_PAYLOAD(*pi); } - SListNode* pnode = NULL; // todo speed up + SPageInfo** pInfo = (SPageInfo**) ((*pi)->pn->data); + assert(*pInfo == *pi); - SListIter iter = {0}; - tdListInitIter(pResultBuf->lruList, &iter, TD_LIST_FORWARD); + lruListMoveToFront(pResultBuf->lruList, (*pi)); + (*pi)->used = true; - while((pnode = tdListNext(&iter)) != NULL) { - SPageInfo** pInfo = (SPageInfo**) pnode->data; + return GET_DATA_PAYLOAD(*pi); - // remove it and add it into the front of linked-list - if ((*pInfo)->pageId == id) { - tdListPopNode(pResultBuf->lruList, pnode); - tdListPrependNode(pResultBuf->lruList, pnode); - T_REF_INC(*(SPageInfo**)pnode->data); - - return ((*(SPageInfo**)pnode->data)->pData + POINTER_BYTES); - } - } } else { // not in memory - assert((*pi)->pData == NULL && (*pi)->info.length >= 0 && (*pi)->info.offset >= 0); + assert((*pi)->pData == NULL && (*pi)->pn == NULL && (*pi)->info.length >= 0 && (*pi)->info.offset >= 0); - // choose the be flushed page: get the last page in linked list - SListIter iter1 = {0}; - tdListInitIter(pResultBuf->lruList, &iter1, TD_LIST_BACKWARD); - - SListNode* pn = NULL; - while((pn = tdListNext(&iter1)) != NULL) { - assert(pn != NULL); - if (T_REF_VAL_GET(*(SPageInfo**)(pn->data)) == 0) { - break; - } + char* availablePage = NULL; + if (NO_AVAILABLE_PAGES(pResultBuf)) { + availablePage = evicOneDataPage(pResultBuf); } - // all pages are referenced by user, try to allocate new space - if (pn == NULL) { - int32_t prev = pResultBuf->inMemPages; - pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; - - qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, - pResultBuf->inMemPages, pResultBuf->pageSize); - + if (availablePage == NULL) { (*pi)->pData = calloc(1, pResultBuf->pageSize + POINTER_BYTES); } else { - tdListPopNode(pResultBuf->lruList, pn); - - if (flushPageToDisk(pResultBuf, *(SPageInfo**)pn->data) != TSDB_CODE_SUCCESS) { - return NULL; - } - - char* buf = (*(SPageInfo**)pn->data)->pData; - (*(SPageInfo**)pn->data)->pData = NULL; - - (*pi)->pData = buf; - - ((void**)((*pi)->pData))[0] = (*pi); - tfree(pn); + (*pi)->pData = availablePage; } - // load file in disk - int32_t ret = fseek(pResultBuf->file, (*pi)->info.offset, SEEK_SET); - ret = fread((*pi)->pData + POINTER_BYTES, 1, (*pi)->info.length, pResultBuf->file); - if (ret != (*pi)->info.length) { - terrno = errno; - return NULL; - } + ((void**)((*pi)->pData))[0] = (*pi); - // todo do decomp - - return (*pi)->pData + POINTER_BYTES; + lruListPushFront(pResultBuf->lruList, *pi); + loadPageFromDisk(pResultBuf, *pi); + return GET_DATA_PAYLOAD(*pi); } - - return NULL; } void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page) { @@ -328,9 +357,14 @@ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page) { char* p = (char*) page - POINTER_BYTES; SPageInfo* ppi = ((SPageInfo**) p)[0]; + releaseResBufPageInfo(pResultBuf, ppi); +} - assert(T_REF_VAL_GET(ppi) > 0); - T_REF_DEC(ppi); +void releaseResBufPageInfo(SDiskbasedResultBuf* pResultBuf, SPageInfo* pi) { + assert(pi->pData != NULL && pi->used); + + pi->used = false; + pResultBuf->statis.releasePages += 1; } size_t getNumOfRowsPerPage(const SDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; } @@ -373,9 +407,11 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { SArray** p = (SArray**) taosHashIterGet(iter); size_t n = taosArrayGetSize(*p); for(int32_t i = 0; i < n; ++i) { - SPageInfo* pi = taosArrayGet(*p, i); + SPageInfo* pi = taosArrayGetP(*p, i); tfree(pi->pData); + tfree(pi); } + taosArrayDestroy(*p); } @@ -390,8 +426,8 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { tfree(pResultBuf); } -int32_t getLastPageId(SIDList pList) { +SPageInfo* getLastPageInfo(SIDList pList) { size_t size = taosArrayGetSize(pList); - return *(int32_t*) taosArrayGet(pList, size - 1); + return (SPageInfo*) taosArrayGetP(pList, size - 1); } diff --git a/src/query/src/qUtil.c b/src/query/src/qUtil.c index be84471493..8ddc2d3857 100644 --- a/src/query/src/qUtil.c +++ b/src/query/src/qUtil.c @@ -233,11 +233,13 @@ void clearTimeWindowResBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *pWindow if (pWindowRes == NULL) { return; } - + + tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pWindowRes->pos.pageId); + for (int32_t i = 0; i < pRuntimeEnv->pQuery->numOfOutput; ++i) { SResultInfo *pResultInfo = &pWindowRes->resultInfo[i]; - char * s = getPosInResultPage(pRuntimeEnv, i, pWindowRes); + char * s = getPosInResultPage(pRuntimeEnv, i, pWindowRes, page); size_t size = pRuntimeEnv->pQuery->pSelectExpr[i].bytes; memset(s, 0, size); @@ -274,8 +276,11 @@ void copyTimeWindowResBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *dst, con memcpy(pDst->interResultBuf, pSrc->interResultBuf, pDst->bufLen); // copy the output buffer data from src to dst, the position info keep unchanged - char * dstBuf = getPosInResultPage(pRuntimeEnv, i, dst); - char * srcBuf = getPosInResultPage(pRuntimeEnv, i, (SWindowResult *)src); + tFilePage *dstpage = getResBufPage(pRuntimeEnv->pResultBuf, dst->pos.pageId); + char * dstBuf = getPosInResultPage(pRuntimeEnv, i, dst, dstpage); + + tFilePage *srcpage = getResBufPage(pRuntimeEnv->pResultBuf, src->pos.pageId); + char * srcBuf = getPosInResultPage(pRuntimeEnv, i, (SWindowResult *)src, srcpage); size_t s = pRuntimeEnv->pQuery->pSelectExpr[i].bytes; memcpy(dstBuf, srcBuf, s); diff --git a/src/query/tests/resultBufferTest.cpp b/src/query/tests/resultBufferTest.cpp index 53a05925c2..3171a7b322 100644 --- a/src/query/tests/resultBufferTest.cpp +++ b/src/query/tests/resultBufferTest.cpp @@ -94,7 +94,59 @@ void writeDownTest() { SArray* pa = getDataBufPagesIdList(pResultBuf, groupId); ASSERT_EQ(taosArrayGetSize(pa), 5); + destroyResultBuf(pResultBuf, NULL); +} +void recyclePageTest() { + SDiskbasedResultBuf* pResultBuf = NULL; + int32_t ret = createDiskbasedResultBuffer(&pResultBuf, 1000, 64, 1024, 4, NULL); + + int32_t pageId = 0; + int32_t writePageId = 0; + int32_t groupId = 0; + int32_t nx = 12345; + + tFilePage* pBufPage = getNewDataBuf(pResultBuf, groupId, &pageId); + ASSERT_TRUE(pBufPage != NULL); + releaseResBufPage(pResultBuf, pBufPage); + + tFilePage* pBufPage1 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t1 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t1 == pBufPage1); + ASSERT_TRUE(pageId == 1); + + tFilePage* pBufPage2 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t2 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t2 == pBufPage2); + ASSERT_TRUE(pageId == 2); + + tFilePage* pBufPage3 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t3 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t3 == pBufPage3); + ASSERT_TRUE(pageId == 3); + + tFilePage* pBufPage4 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t4 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t4 == pBufPage4); + ASSERT_TRUE(pageId == 4); + releaseResBufPage(pResultBuf, t4); + releaseResBufPage(pResultBuf, t4); + + tFilePage* pBufPage5 = getNewDataBuf(pResultBuf, groupId, &pageId); + tFilePage* t5 = getResBufPage(pResultBuf, pageId); + ASSERT_TRUE(t5 == pBufPage5); + ASSERT_TRUE(pageId == 5); + + // flush the written page to disk, and read it out again + tFilePage* pBufPagex = getResBufPage(pResultBuf, writePageId); + *(int32_t*)(pBufPagex->data) = nx; + writePageId = pageId; // update the data + releaseResBufPage(pResultBuf, pBufPagex); + + tFilePage* pBufPagex1 = getResBufPage(pResultBuf, 1); + + SArray* pa = getDataBufPagesIdList(pResultBuf, groupId); + ASSERT_EQ(taosArrayGetSize(pa), 6); destroyResultBuf(pResultBuf, NULL); } @@ -105,4 +157,5 @@ TEST(testCase, resultBufferTest) { srand(time(NULL)); simpleTest(); writeDownTest(); + recyclePageTest(); } diff --git a/src/util/inc/tlist.h b/src/util/inc/tlist.h index a4ed9311e2..e8380294da 100644 --- a/src/util/inc/tlist.h +++ b/src/util/inc/tlist.h @@ -55,6 +55,8 @@ int tdListPrepend(SList *list, void *data); int tdListAppend(SList *list, void *data); SListNode *tdListPopHead(SList *list); SListNode *tdListPopTail(SList *list); +SListNode *tdListGetHead(SList *list); +SListNode *tsListGetTail(SList *list); SListNode *tdListPopNode(SList *list, SListNode *node); void tdListMove(SList *src, SList *dst); void tdListDiscard(SList *list); diff --git a/src/util/src/tlist.c b/src/util/src/tlist.c index 93293b8b91..8c2ad83de1 100644 --- a/src/util/src/tlist.c +++ b/src/util/src/tlist.c @@ -122,6 +122,22 @@ SListNode *tdListPopTail(SList *list) { return node; } +SListNode *tdListGetHead(SList *list) { + if (list == NULL || list->numOfEles == 0) { + return NULL; + } + + return list->head; +} + +SListNode *tsListGetTail(SList *list) { + if (list == NULL || list->numOfEles == 0) { + return NULL; + } + + return list->tail; +} + SListNode *tdListPopNode(SList *list, SListNode *node) { if (list->head == node) { list->head = node->next; diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index c6981d2902..1e73893793 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -93,6 +93,8 @@ run general/parser/groupby.sim sleep 2000 run general/parser/tags_filter.sim sleep 2000 +run general/parser/topbot.sim +sleep 2000 run general/parser/union.sim sleep 2000 run general/parser/sliding.sim diff --git a/tests/script/general/parser/topbot.sim b/tests/script/general/parser/topbot.sim new file mode 100644 index 0000000000..a0c46dbc65 --- /dev/null +++ b/tests/script/general/parser/topbot.sim @@ -0,0 +1,74 @@ +system sh/stop_dnodes.sh + +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 0 +system sh/exec.sh -n dnode1 -s start +sleep 3000 +sql connect + +$dbPrefix = tb_db +$tbPrefix = tb_tb +$stbPrefix = tb_stb +$tbNum = 10 +$rowNum = 1000 +$totalNum = $tbNum * $rowNum +$loops = 200000 +$log = 10000 +$ts0 = 1537146000000 +$delta = 600000 +print ========== topbot.sim +$i = 0 +$db = $dbPrefix . $i +$stb = $stbPrefix . $i + +sql drop database $db -x step1 +step1: +sql create database $db cache 16 maxtables 200 +print ====== create tables +sql use $db +sql create table $stb (ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 smallint, c6 tinyint, c7 bool, c8 binary(10), c9 nchar(10)) tags(t1 int) + +$i = 0 +$ts = $ts0 +$halfNum = $tbNum / 2 +while $i < $halfNum + $tbId = $i + $halfNum + $tb = $tbPrefix . $i + $tb1 = $tbPrefix . $tbId + sql create table $tb using $stb tags( $i ) + sql create table $tb1 using $stb tags( $tbId ) + + $x = 0 + while $x < $rowNum + $xs = $x * $delta + $ts = $ts0 + $xs + $c = $x / 10 + $c = $c * 10 + $c = $x - $c + $binary = 'binary . $c + $binary = $binary . ' + $nchar = 'nchar . $c + $nchar = $nchar . ' + sql insert into $tb values ( $ts , $c , $c , $c , $c , $c , $c , true, $binary , $nchar ) + sql insert into $tb1 values ( $ts , $c , NULL , $c , NULL , $c , $c , true, $binary , $nchar ) + $x = $x + 1 + endw + + $i = $i + 1 +endw +print ====== tables created + +sql use $db +##### select from table +print ====== select top/bot from table and check num of rows returned +sql select top(c1, 100) from tb_stb0 +if $row != 100 then + return -1 +endi + +sql select last(c2) from tb_tb9 +if $row != 1 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file From d9622d9d8cb52de2343fb0f7137a6ab44d088ea1 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 27 Jul 2020 16:17:34 +0800 Subject: [PATCH 30/47] [td-225] fix bugs in rsp data using wrong connection handle --- src/inc/query.h | 9 +-------- src/query/src/qExecutor.c | 8 ++++++++ src/vnode/src/vnodeRead.c | 8 ++++++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/inc/query.h b/src/inc/query.h index a9a21bc911..ccff05bc1b 100644 --- a/src/inc/query.h +++ b/src/inc/query.h @@ -65,14 +65,7 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex */ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp** pRsp, int32_t* contLen, bool* continueExec); -/** - * Decide if more results will be produced or not, NOTE: this function will increase the ref count of QInfo, - * so it can be only called once for each retrieve - * - * @param qinfo - * @return - */ -bool qHasMoreResultsToRetrieve(qinfo_t qinfo); +void* qGetResultRetrieveMsg(qinfo_t qinfo); /** * kill current ongoing query and free query handle automatically diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 28d1c138f6..5b904936f2 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6640,6 +6640,13 @@ static void buildTagQueryResult(SQInfo* pQInfo) { setQueryStatus(pQuery, QUERY_COMPLETED); } +void* qGetResultRetrieveMsg(qinfo_t qinfo) { + SQInfo* pQInfo = (SQInfo*) qinfo; + assert(pQInfo != NULL); + + return pQInfo->rspContext; +} + void freeqinfoFn(void *qhandle) { void** handle = qhandle; if (handle == NULL || *handle == NULL) { @@ -6762,3 +6769,4 @@ void** qReleaseQInfo(void* pMgmt, void* pQInfo, bool needFree) { return 0; } + diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 5edfcf597c..3659ef1430 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -166,12 +166,16 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { bool buildRes = qTableQuery(*handle); // do execute query if (buildRes) { // build result rsp - vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused", pVnode->vgId, *handle); + + SReadMsg* pRetrieveMsg = qGetResultRetrieveMsg(*handle); + assert(pRetrieveMsg != NULL); + vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, pRetrieveMsg->rpcMsg.handle); + pReadMsg->rpcMsg.handle = pRetrieveMsg->rpcMsg.handle; // update the connection info according to the retrieve connection pRet = &pReadMsg->rspRet; + code = TSDB_CODE_QRY_HAS_RSP; bool continueExec = false; - code = TSDB_CODE_QRY_HAS_RSP; if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { if (continueExec) { From f32a87041316315664aa87a07a70bc44c1b23793 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 27 Jul 2020 16:40:34 +0800 Subject: [PATCH 31/47] [td-225] fix bugs in rsp data using wrong connection handle --- src/vnode/src/vnodeRead.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 3659ef1430..bb7b7c5a80 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -168,7 +168,8 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (buildRes) { // build result rsp SReadMsg* pRetrieveMsg = qGetResultRetrieveMsg(*handle); - assert(pRetrieveMsg != NULL); + assert(pRetrieveMsg != NULL && pRetrieveMsg->rpcMsg.handle != NULL); + vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, pRetrieveMsg->rpcMsg.handle); pReadMsg->rpcMsg.handle = pRetrieveMsg->rpcMsg.handle; // update the connection info according to the retrieve connection @@ -203,7 +204,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { pRetrieve->qhandle = htobe64(pRetrieve->qhandle); pRetrieve->free = htons(pRetrieve->free); - vDebug("vgId:%d, QInfo:%p, retrieve msg is disposed", pVnode->vgId, (void*) pRetrieve->qhandle); + vDebug("vgId:%d, QInfo:%p, retrieve msg is disposed, free:%d, conn:%p", pVnode->vgId, (void*) pRetrieve->qhandle, pRetrieve->free, pReadMsg->rpcMsg.handle); memset(pRet, 0, sizeof(SRspRet)); From d32eb69fdb4f600304555a70fd720519cb2d2656 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 27 Jul 2020 16:45:18 +0800 Subject: [PATCH 32/47] [td-225] fix bugs in rsp data using wrong connection handle --- src/vnode/src/vnodeRead.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index bb7b7c5a80..49c10dca3f 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -167,11 +167,11 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (buildRes) { // build result rsp - SReadMsg* pRetrieveMsg = qGetResultRetrieveMsg(*handle); - assert(pRetrieveMsg != NULL && pRetrieveMsg->rpcMsg.handle != NULL); + void* retrieveHandle = qGetResultRetrieveMsg(*handle); + assert(retrieveHandle != NULL); - vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, pRetrieveMsg->rpcMsg.handle); - pReadMsg->rpcMsg.handle = pRetrieveMsg->rpcMsg.handle; // update the connection info according to the retrieve connection + vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, retrieveHandle); + pReadMsg->rpcMsg.handle = retrieveHandle; // update the connection info according to the retrieve connection pRet = &pReadMsg->rspRet; code = TSDB_CODE_QRY_HAS_RSP; @@ -250,7 +250,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { bool freeHandle = true; bool buildRes = false; - code = qRetrieveQueryResultInfo(*handle, &buildRes, pReadMsg); + code = qRetrieveQueryResultInfo(*handle, &buildRes, pReadMsg->rpcMsg.handle); if (code != TSDB_CODE_SUCCESS) { //TODO handle malloc failure pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); From ed4fb4ac0822356d601e4c764b4c8ab317333187 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 27 Jul 2020 17:02:21 +0800 Subject: [PATCH 33/47] [td-225] --- src/client/src/tscUtil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 1ef5d3feaf..e7fa2a84a9 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -351,7 +351,7 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) { int32_t cmd = pCmd->command; if (cmd < TSDB_SQL_INSERT || cmd == TSDB_SQL_RETRIEVE_LOCALMERGE || cmd == TSDB_SQL_RETRIEVE_EMPTY_RESULT || cmd == TSDB_SQL_TABLE_JOIN_RETRIEVE) { - //tscRemoveFromSqlList(pSql); + tscRemoveFromSqlList(pSql); } // pSql->sqlstr will be used by tscBuildQueryStreamDesc @@ -1885,7 +1885,7 @@ void tscDoQuery(SSqlObj* pSql) { } if (pCmd->command == TSDB_SQL_SELECT) { - //tscAddIntoSqlList(pSql); + tscAddIntoSqlList(pSql); } if (pCmd->dataSourceType == DATA_FROM_DATA_FILE) { From bb6cbf5fef1b1f2d032c21824ea0e284e2cf4036 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 27 Jul 2020 19:01:36 +0800 Subject: [PATCH 34/47] [td-225] --- src/client/src/tscLocalMerge.c | 8 +++++++- src/query/inc/qExtbuffer.h | 6 +++--- src/query/inc/qResultbuf.h | 27 +++++++++++++------------- src/query/src/qExecutor.c | 9 ++++----- src/query/src/qExtbuffer.c | 4 ++-- src/query/src/qPercentile.c | 2 +- src/query/src/qResultbuf.c | 29 ++++++++++++++-------------- src/query/tests/resultBufferTest.cpp | 6 +++--- src/util/src/tcache.c | 2 +- 9 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 80fc82d90b..bf76b8cbe8 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -691,9 +691,15 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr pModel = createColumnModel(pSchema, size, capacity); + int32_t pg = DEFAULT_PAGE_SIZE; + int32_t overhead = sizeof(tFilePage); + while((pg - overhead) < pModel->rowSize * 2) { + pg *= 2; + } + size_t numOfSubs = pTableMetaInfo->vgroupList->numOfVgroups; for (int32_t i = 0; i < numOfSubs; ++i) { - (*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pModel); + (*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pg, pModel); (*pMemBuffer)[i]->flushModel = MULTIPLE_APPEND_MODEL; } diff --git a/src/query/inc/qExtbuffer.h b/src/query/inc/qExtbuffer.h index 2cbef2b1be..9823e7d6ce 100644 --- a/src/query/inc/qExtbuffer.h +++ b/src/query/inc/qExtbuffer.h @@ -28,9 +28,9 @@ extern "C" { #include "tdataformat.h" #include "talgo.h" -#define DEFAULT_PAGE_SIZE (1024L*64) // 16k larger than the SHistoInfo -#define MAX_TMPFILE_PATH_LENGTH PATH_MAX +#define MAX_TMPFILE_PATH_LENGTH PATH_MAX #define INITIAL_ALLOCATION_BUFFER_SIZE 64 +#define DEFAULT_PAGE_SIZE (4096L) // 16k larger than the SHistoInfo typedef enum EXT_BUFFER_FLUSH_MODEL { /* @@ -126,7 +126,7 @@ typedef struct tExtMemBuffer { * @param pModel * @return */ -tExtMemBuffer *createExtMemBuffer(int32_t inMemSize, int32_t elemSize, SColumnModel *pModel); +tExtMemBuffer *createExtMemBuffer(int32_t inMemSize, int32_t elemSize, int32_t pagesize, SColumnModel *pModel); /** * diff --git a/src/query/inc/qResultbuf.h b/src/query/inc/qResultbuf.h index ba446b4627..ac907cfee6 100644 --- a/src/query/inc/qResultbuf.h +++ b/src/query/inc/qResultbuf.h @@ -52,7 +52,6 @@ typedef struct SResultBufStatis { int32_t getPages; int32_t releasePages; int32_t flushPages; - int32_t fileSize; } SResultBufStatis; typedef struct SDiskbasedResultBuf { @@ -68,29 +67,31 @@ typedef struct SDiskbasedResultBuf { SHashObj* groupSet; // id hash table SHashObj* all; SList* lruList; - void* handle; // for debug purpose void* emptyDummyIdList; // dummy id list - bool comp; // compressed before flushed to disk - void* assistBuf; // assistant buffer for compress data + void* assistBuf; // assistant buffer for compress/decompress data SArray* pFree; // free area in file + bool comp; // compressed before flushed to disk int32_t nextPos; // next page flush position + const void* handle; // for debug purpose SResultBufStatis statis; } SDiskbasedResultBuf; -#define DEFAULT_INTERN_BUF_PAGE_SIZE (1024L) +#define DEFAULT_INTERN_BUF_PAGE_SIZE (4096L) #define DEFAULT_INMEM_BUF_PAGES 10 #define PAGE_INFO_INITIALIZER (SPageDiskInfo){-1, -1} /** * create disk-based result buffer * @param pResultBuf - * @param size * @param rowSize + * @param pagesize + * @param inMemPages + * @param handle * @return */ -int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t numOfPages, int32_t rowSize, int32_t pagesize, - int32_t inMemPages, const void* handle); +int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t rowSize, int32_t pagesize, + int32_t inMemBufSize, const void* handle); /** * @@ -131,15 +132,13 @@ tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); */ void releaseResBufPage(SDiskbasedResultBuf* pResultBuf, void* page); -void releaseResBufPageInfo(SDiskbasedResultBuf* pResultBuf, SPageInfo* pi); - /** * * @param pResultBuf - * @param id - * @return + * @param pi */ -//tFilePage* getResBufPage(SDiskbasedResultBuf* pResultBuf, int32_t id); +void releaseResBufPageInfo(SDiskbasedResultBuf* pResultBuf, SPageInfo* pi); + /** * get the total buffer size in the format of disk file @@ -159,7 +158,7 @@ size_t getNumOfResultBufGroupId(const SDiskbasedResultBuf* pResultBuf); * destroy result buffer * @param pResultBuf */ -void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle); +void destroyResultBuf(SDiskbasedResultBuf* pResultBuf); /** * diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 9d873dc95f..ee24365d87 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1621,7 +1621,7 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { pRuntimeEnv->pFillInfo = taosDestoryFillInfo(pRuntimeEnv->pFillInfo); - destroyResultBuf(pRuntimeEnv->pResultBuf, pQInfo); + destroyResultBuf(pRuntimeEnv->pResultBuf); tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle); tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); @@ -4242,10 +4242,10 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo int32_t ps = DEFAULT_PAGE_SIZE; int32_t rowsize = 0; getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); + int32_t TWOMB = 1024*1024*2; if (isSTableQuery && !onlyQueryTags(pRuntimeEnv->pQuery)) { -// int32_t numOfPages = getInitialPageNum(pQInfo); - code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, 2, rowsize, ps, 2, pQInfo); + code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TWOMB, pQInfo); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -4273,8 +4273,7 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo } else if (pRuntimeEnv->groupbyNormalCol || QUERY_IS_INTERVAL_QUERY(pQuery)) { int32_t numOfResultRows = getInitialPageNum(pQInfo); getIntermediateBufInfo(pRuntimeEnv, &ps, &rowsize); - - code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, numOfResultRows, rowsize, ps, numOfResultRows, pQInfo); + code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rowsize, ps, TWOMB, pQInfo); if (code != TSDB_CODE_SUCCESS) { return code; } diff --git a/src/query/src/qExtbuffer.c b/src/query/src/qExtbuffer.c index 69c5f0e24f..fb57f71199 100644 --- a/src/query/src/qExtbuffer.c +++ b/src/query/src/qExtbuffer.c @@ -28,10 +28,10 @@ /* * SColumnModel is deeply copy */ -tExtMemBuffer* createExtMemBuffer(int32_t inMemSize, int32_t elemSize, SColumnModel *pModel) { +tExtMemBuffer* createExtMemBuffer(int32_t inMemSize, int32_t elemSize, int32_t pagesize, SColumnModel *pModel) { tExtMemBuffer* pMemBuffer = (tExtMemBuffer *)calloc(1, sizeof(tExtMemBuffer)); - pMemBuffer->pageSize = DEFAULT_PAGE_SIZE; + pMemBuffer->pageSize = pagesize; pMemBuffer->inMemCapacity = ALIGN8(inMemSize) / pMemBuffer->pageSize; pMemBuffer->nElemSize = elemSize; diff --git a/src/query/src/qPercentile.c b/src/query/src/qPercentile.c index c4490a01e7..85e45e46b3 100644 --- a/src/query/src/qPercentile.c +++ b/src/query/src/qPercentile.c @@ -535,7 +535,7 @@ void tMemBucketPut(tMemBucket *pBucket, void *data, int32_t numOfRows) { if (pSeg->pBuffer[slotIdx] == NULL) { pSeg->pBuffer[slotIdx] = createExtMemBuffer(pBucket->numOfTotalPages * pBucket->pageSize, pBucket->nElemSize, - pBucket->pOrderDesc->pColumnModel); + pBucket->pageSize, pBucket->pOrderDesc->pColumnModel); pSeg->pBuffer[slotIdx]->flushModel = SINGLE_APPEND_MODEL; pBucket->pOrderDesc->pColumnModel->capacity = pSeg->pBuffer[slotIdx]->numOfElemsPerPage; } diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index fbb5f116e6..33ae93f434 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -8,31 +8,33 @@ #define GET_DATA_PAYLOAD(_p) ((_p)->pData + POINTER_BYTES) -int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t numOfPages, int32_t rowSize, - int32_t pagesize, int32_t inMemPages, const void* handle) { - +int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t rowSize, int32_t pagesize, + int32_t inMemBufSize, const void* handle) { *pResultBuf = calloc(1, sizeof(SDiskbasedResultBuf)); + SDiskbasedResultBuf* pResBuf = *pResultBuf; if (pResBuf == NULL) { return TSDB_CODE_COM_OUT_OF_MEMORY; } pResBuf->pageSize = pagesize; - pResBuf->numOfPages = 0; // all pages are in buffer in the first place - pResBuf->inMemPages = inMemPages; + pResBuf->numOfPages = 0; // all pages are in buffer in the first place + pResBuf->inMemPages = inMemBufSize/pagesize; // maximum allowed pages, it is a soft limit. pResBuf->totalBufSize = pResBuf->numOfPages * pagesize; pResBuf->allocateId = -1; pResBuf->comp = true; + pResBuf->handle = handle; - assert(inMemPages <= numOfPages); + // at least more than 2 pages must be in memory + assert(inMemBufSize >= pagesize * 2); pResBuf->numOfRowsPerPage = (pagesize - sizeof(tFilePage)) / rowSize; pResBuf->lruList = tdListNew(POINTER_BYTES); // init id hash table - pResBuf->groupSet = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); - pResBuf->all = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); + pResBuf->groupSet = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); pResBuf->assistBuf = malloc(pResBuf->pageSize + 2); // EXTRA BYTES + pResBuf->all = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false); char path[PATH_MAX] = {0}; getTmpfilePath("qbuf", path); @@ -47,9 +49,6 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t nu return TSDB_CODE_SUCCESS; } -#define NUM_OF_PAGES_ON_DISK(_r) ((_r)->numOfPages - (_r)->inMemPages) -#define FILE_SIZE_ON_DISK(_r) (NUM_OF_PAGES_ON_DISK(_r) * (_r)->pageSize) - static int32_t createDiskFile(SDiskbasedResultBuf* pResultBuf) { pResultBuf->file = fopen(pResultBuf->path, "wb+"); if (pResultBuf->file == NULL) { @@ -384,18 +383,18 @@ SIDList getDataBufPagesIdList(SDiskbasedResultBuf* pResultBuf, int32_t groupId) } } -void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) { +void destroyResultBuf(SDiskbasedResultBuf* pResultBuf) { if (pResultBuf == NULL) { return; } if (pResultBuf->file != NULL) { - qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, file created:%s, file size:%d", handle, - pResultBuf->totalBufSize, pResultBuf->path, FILE_SIZE_ON_DISK(pResultBuf)); + qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, file created:%s, file size:%"PRId64, pResultBuf->handle, + pResultBuf->totalBufSize, pResultBuf->path, pResultBuf->diskFileSize); fclose(pResultBuf->file); } else { - qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, no file created", handle, + qDebug("QInfo:%p disk-based output buffer closed, total:%" PRId64 " bytes, no file created", pResultBuf->handle, pResultBuf->totalBufSize); } diff --git a/src/query/tests/resultBufferTest.cpp b/src/query/tests/resultBufferTest.cpp index 3171a7b322..3b74bf1b64 100644 --- a/src/query/tests/resultBufferTest.cpp +++ b/src/query/tests/resultBufferTest.cpp @@ -47,7 +47,7 @@ void simpleTest() { tFilePage* t4 = getResBufPage(pResultBuf, pageId); ASSERT_TRUE(t4 == pBufPage5); - destroyResultBuf(pResultBuf, NULL); + destroyResultBuf(pResultBuf); } void writeDownTest() { @@ -94,7 +94,7 @@ void writeDownTest() { SArray* pa = getDataBufPagesIdList(pResultBuf, groupId); ASSERT_EQ(taosArrayGetSize(pa), 5); - destroyResultBuf(pResultBuf, NULL); + destroyResultBuf(pResultBuf); } void recyclePageTest() { @@ -148,7 +148,7 @@ void recyclePageTest() { SArray* pa = getDataBufPagesIdList(pResultBuf, groupId); ASSERT_EQ(taosArrayGetSize(pa), 6); - destroyResultBuf(pResultBuf, NULL); + destroyResultBuf(pResultBuf); } } // namespace diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 7c2a6b3219..4058bf1672 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -381,7 +381,7 @@ void *taosCacheAcquireByData(SCacheObj *pCacheObj, void *data) { } void *taosCacheTransfer(SCacheObj *pCacheObj, void **data) { - if (pCacheObj == NULL || data == NULL || *data == NULL) return NULL; + if (pCacheObj == NULL || data == NULL || (*data) == NULL) return NULL; size_t offset = offsetof(SCacheDataNode, data); SCacheDataNode *ptNode = (SCacheDataNode *)((char *)(*data) - offset); From 1e46bb51d2f831d80591ead4a858d679382accd3 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 28 Jul 2020 09:28:50 +0800 Subject: [PATCH 35/47] fix some doc errors on website --- documentation/webdocs/markdowndocs/TAOS SQL-ch.md | 4 ++-- documentation/webdocs/markdowndocs/TAOS SQL.md | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/documentation/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation/webdocs/markdowndocs/TAOS SQL-ch.md index 343ce80422..e494a1be45 100644 --- a/documentation/webdocs/markdowndocs/TAOS SQL-ch.md +++ b/documentation/webdocs/markdowndocs/TAOS SQL-ch.md @@ -556,7 +556,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 功能说明:统计表中某列的值百分比分位数。 返回结果数据类型: 双精度浮点数Double。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 - 说明:*k*值取值范围0≤*k*≤100,为0的时候等同于MIN,为100的时候等同于MAX。 + 说明:*k*值取值范围0≤*P*≤100,为0的时候等同于MIN,为100的时候等同于MAX。 - **APERCENTILE** ```mysql @@ -565,7 +565,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 功能说明:统计表中某列的值百分比分位数,与PERCENTILE函数相似,但是返回近似结果。 返回结果数据类型: 双精度浮点数Double。 应用字段:不能应用在timestamp、binary、nchar、bool类型字段。 - 说明:*k*值取值范围0≤*k*≤100,为0的时候等同于MIN,为100的时候等同于MAX。推荐使用```APERCENTILE```函数,该函数性能远胜于```PERCENTILE```函数 + 说明:*k*值取值范围0≤*P*≤100,为0的时候等同于MIN,为100的时候等同于MAX。推荐使用```APERCENTILE```函数,该函数性能远胜于```PERCENTILE```函数 - **LAST_ROW** ```mysql diff --git a/documentation/webdocs/markdowndocs/TAOS SQL.md b/documentation/webdocs/markdowndocs/TAOS SQL.md index c0d35e9afc..f94047fb6a 100644 --- a/documentation/webdocs/markdowndocs/TAOS SQL.md +++ b/documentation/webdocs/markdowndocs/TAOS SQL.md @@ -289,10 +289,10 @@ TDengine supports aggregations over numerical values, they are listed below: Applied to: table/STable. -- **WAVG** +- **TWA** ```mysql - SELECT WAVG(field_name) FROM tb_name WHERE clause + SELECT TWA(field_name) FROM tb_name WHERE clause ``` Function: return the time-weighted average value of a specific column Return Data Type: `double` @@ -324,7 +324,7 @@ TDengine supports aggregations over numerical values, they are listed below: - **LEASTSQUARES** ```mysql - SELECT LEASTSQUARES(field_name) FROM tb_name [WHERE clause] + SELECT LEASTSQUARES(field_name, start_val, step_val) FROM tb_name [WHERE clause] ``` Function: performs a linear fit to the primary timestamp and the specified column. Return Data Type: return a string of the coefficient and the interception of the fitted line. @@ -417,6 +417,15 @@ TDengine supports aggregations over numerical values, they are listed below: Applied to: table/STable. Note: The range of `P` is `[0, 100]`. When `P=0` , `PERCENTILE` returns the equal value as `MIN`; when `P=100`, `PERCENTILE` returns the equal value as `MAX`. +- **APERCENTILE** + ```mysql + SELECT APERCENTILE(field_name, P) FROM { tb_name | stb_name } [WHERE clause] + ``` + Function: the value of the specified column below which `P` percent of the data points fall, it returns approximate value of percentile. + Return Data Type: double. + Applicable Data Types: all types except `timestamp`, `binary`, `nchar`, `bool`. + Applied to: table/STable. + Note: The range of `P` is `[0, 100]`. When `P=0` , `APERCENTILE` returns the equal value as `MIN`; when `P=100`, `APERCENTILE` returns the equal value as `MAX`. `APERCENTILE` has a much better performance than `PERCENTILE`. - **LAST_ROW** ```mysql From eb8c0bd72ddcf0c296f2bdfd64a4b1546105a737 Mon Sep 17 00:00:00 2001 From: Jeff Tao Date: Tue, 28 Jul 2020 02:33:40 +0000 Subject: [PATCH 36/47] publish sync module --- src/sync/CMakeLists.txt | 23 + src/sync/inc/syncInt.h | 176 +++++ src/sync/inc/syncMain.h | 33 + src/sync/inc/taosTcpPool.h | 47 ++ src/sync/src/syncMain.c | 1207 ++++++++++++++++++++++++++++++++++ src/sync/src/syncRestore.c | 326 +++++++++ src/sync/src/syncRetrieve.c | 479 ++++++++++++++ src/sync/src/taosTcpPool.c | 325 +++++++++ src/sync/src/tarbitrator.c | 191 ++++++ src/sync/test/CMakeLists.txt | 20 + src/sync/test/syncClient.c | 194 ++++++ src/sync/test/syncServer.c | 487 ++++++++++++++ 12 files changed, 3508 insertions(+) create mode 100644 src/sync/CMakeLists.txt create mode 100644 src/sync/inc/syncInt.h create mode 100644 src/sync/inc/syncMain.h create mode 100644 src/sync/inc/taosTcpPool.h create mode 100644 src/sync/src/syncMain.c create mode 100644 src/sync/src/syncRestore.c create mode 100644 src/sync/src/syncRetrieve.c create mode 100644 src/sync/src/taosTcpPool.c create mode 100644 src/sync/src/tarbitrator.c create mode 100644 src/sync/test/CMakeLists.txt create mode 100644 src/sync/test/syncClient.c create mode 100644 src/sync/test/syncServer.c diff --git a/src/sync/CMakeLists.txt b/src/sync/CMakeLists.txt new file mode 100644 index 0000000000..0a5d18022b --- /dev/null +++ b/src/sync/CMakeLists.txt @@ -0,0 +1,23 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) + INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) + INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) + INCLUDE_DIRECTORIES(inc) + AUX_SOURCE_DIRECTORY(src SRC) + LIST(REMOVE_ITEM SRC ./src/tarbitrator.c) + + ADD_LIBRARY(sync ${SRC}) + TARGET_LINK_LIBRARIES(sync tutil pthread common) + + LIST(APPEND BIN_SRC ./src/tarbitrator.c) + LIST(APPEND BIN_SRC ./src/taosTcpPool.c) + ADD_EXECUTABLE(tarbitrator ${BIN_SRC}) + TARGET_LINK_LIBRARIES(tarbitrator tutil sync common) + + ADD_SUBDIRECTORY(test) +ENDIF () diff --git a/src/sync/inc/syncInt.h b/src/sync/inc/syncInt.h new file mode 100644 index 0000000000..d6d86064d6 --- /dev/null +++ b/src/sync/inc/syncInt.h @@ -0,0 +1,176 @@ +/* + * 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 TDENGINE_SYNCINT_H +#define TDENGINE_SYNCINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define sFatal(...) { if (sDebugFlag & DEBUG_FATAL) { taosPrintLog("SYN FATAL ", sDebugFlag, __VA_ARGS__); }} +#define sError(...) { if (sDebugFlag & DEBUG_ERROR) { taosPrintLog("SYN ERROR ", sDebugFlag, __VA_ARGS__); }} +#define sWarn(...) { if (sDebugFlag & DEBUG_WARN) { taosPrintLog("SYN WARN ", sDebugFlag, __VA_ARGS__); }} +#define sInfo(...) { if (sDebugFlag & DEBUG_INFO) { taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); }} +#define sDebug(...) { if (sDebugFlag & DEBUG_DEBUG) { taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); }} +#define sTrace(...) { if (sDebugFlag & DEBUG_TRACE) { taosPrintLog("SYN ", sDebugFlag, __VA_ARGS__); }} + +#define TAOS_SMSG_SYNC_DATA 1 +#define TAOS_SMSG_FORWARD 2 +#define TAOS_SMSG_FORWARD_RSP 3 +#define TAOS_SMSG_SYNC_REQ 4 +#define TAOS_SMSG_SYNC_RSP 5 +#define TAOS_SMSG_SYNC_MUST 6 +#define TAOS_SMSG_STATUS 7 + +#define nodeRole pNode->peerInfo[pNode->selfIndex]->role +#define nodeVersion pNode->peerInfo[pNode->selfIndex]->version +#define nodeSStatus pNode->peerInfo[pNode->selfIndex]->sstatus + +#pragma pack(push, 1) + +typedef struct { + char type; // msg type + char pversion; // protocol version + char reserved[6]; // not used + int32_t vgId; // vg ID + int32_t len; // content length, does not include head + // char cont[]; // message content starts from here +} SSyncHead; + +typedef struct { + SSyncHead syncHead; + uint16_t port; + char fqdn[TSDB_FQDN_LEN]; + int32_t sourceId; // only for arbitrator +} SFirstPkt; + +typedef struct { + int8_t role; + uint64_t version; +} SPeerStatus; + +typedef struct { + int8_t role; + int8_t ack; + uint64_t version; + SPeerStatus peersStatus[]; +} SPeersStatus; + +typedef struct { + char name[TSDB_FILENAME_LEN]; + uint32_t magic; + uint32_t index; + uint64_t fversion; + int32_t size; +} SFileInfo; + +typedef struct { + int8_t sync; +} SFileAck; + +typedef struct { + uint64_t version; + int32_t code; +} SFwdRsp; + +#pragma pack(pop) + +typedef struct { + char *buffer; + int bufferSize; + char *offset; + int forwards; + int code; +} SRecvBuffer; + +typedef struct { + uint64_t version; + void *mhandle; + int8_t acks; + int8_t nacks; + int8_t confirmed; + int32_t code; + uint64_t time; +} SFwdInfo; + +typedef struct { + int first; + int last; + int fwds; // number of forwards + SFwdInfo fwdInfo[]; +} SSyncFwds; + +typedef struct SsyncPeer { + int32_t nodeId; + uint32_t ip; + uint16_t port; + char fqdn[TSDB_FQDN_LEN]; // peer ip string + char id[TSDB_EP_LEN+16]; // peer vgId + end point + int8_t role; + int8_t sstatus; // sync status + uint64_t version; + uint64_t sversion; // track the peer version in retrieve process + int syncFd; + int peerFd; // forward FD + void *timer; + void *pConn; + int notifyFd; + int watchNum; + int *watchFd; + int8_t refCount; // reference count + struct SSyncNode *pSyncNode; +} SSyncPeer; + +typedef struct SSyncNode { + char path[TSDB_FILENAME_LEN]; + int8_t replica; + int8_t quorum; + uint32_t vgId; + void *ahandle; + int8_t selfIndex; + SSyncPeer *peerInfo[TAOS_SYNC_MAX_REPLICA+1]; // extra one for arbitrator + SSyncPeer *pMaster; + int8_t refCount; + SRecvBuffer *pRecv; + SSyncFwds *pSyncFwds; // saved forward info if quorum >1 + void *pFwdTimer; + FGetFileInfo getFileInfo; + FGetWalInfo getWalInfo; + FWriteToCache writeToCache; + FConfirmForward confirmForward; + FNotifyRole notifyRole; + FNotifyFileSynced notifyFileSynced; + pthread_mutex_t mutex; +} SSyncNode; + +// sync module global +extern int tsSyncNum; +extern char tsNodeFqdn[TSDB_FQDN_LEN]; + +void *syncRetrieveData(void *param); +void *syncRestoreData(void *param); +int syncSaveIntoBuffer(SSyncPeer *pPeer, SWalHead *pHead); +void syncRestartConnection(SSyncPeer *pPeer); +void syncBroadcastStatus(SSyncNode *pNode); +void syncAddPeerRef(SSyncPeer *pPeer); +int syncDecPeerRef(SSyncPeer *pPeer); + + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_VNODEPEER_H diff --git a/src/sync/inc/syncMain.h b/src/sync/inc/syncMain.h new file mode 100644 index 0000000000..d4ddb12733 --- /dev/null +++ b/src/sync/inc/syncMain.h @@ -0,0 +1,33 @@ +/* + * 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 TDENGINE_PLUGINS_SYNC_H +#define TDENGINE_PLUGINS_SYNC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int32_t syncTest1(); +int32_t syncTest2(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/sync/inc/taosTcpPool.h b/src/sync/inc/taosTcpPool.h new file mode 100644 index 0000000000..1e410acc26 --- /dev/null +++ b/src/sync/inc/taosTcpPool.h @@ -0,0 +1,47 @@ +/* + * 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 TDENGINE_TCP_POOL_H +#define TDENGINE_TCP_POOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* ttpool_h; +typedef void* tthread_h; + +typedef struct { + int numOfThreads; + uint32_t serverIp; + short port; + int bufferSize; + void (*processBrokenLink)(void *ahandle); + int (*processIncomingMsg)(void *ahandle, void *buffer); + void (*processIncomingConn)(int fd, uint32_t ip); +} SPoolInfo; + +ttpool_h taosOpenTcpThreadPool(SPoolInfo *pInfo); +void taosCloseTcpThreadPool(ttpool_h); +void *taosAllocateTcpConn(void *, void *ahandle, int connFd); +void taosFreeTcpConn(void *); + + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_TCP_POOL_H + diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c new file mode 100644 index 0000000000..93c4a9402f --- /dev/null +++ b/src/sync/src/syncMain.c @@ -0,0 +1,1207 @@ +/* + * 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 . + */ + +//#include +//#include +#include "os.h" +#include "hash.h" +#include "tlog.h" +#include "tutil.h" +#include "ttimer.h" +#include "ttime.h" +#include "tsocket.h" +#include "tglobal.h" +#include "taoserror.h" +#include "taosTcpPool.h" +#include "tqueue.h" +#include "twal.h" +#include "tsync.h" +#include "syncInt.h" + +// global configurable +int tsMaxSyncNum = 4; +int tsSyncTcpThreads = 2; +int tsMaxWatchFiles = 100; +int tsMaxFwdInfo = 200; +int tsSyncTimer = 1; +//int sDebugFlag = 135; +//char tsArbitrator[TSDB_FQDN_LEN] = {0}; + +// module global, not configurable +int tsSyncNum; // number of sync in process in whole system +char tsNodeFqdn[TSDB_FQDN_LEN]; + +static int tsNodeNum; // number of nodes in system +static ttpool_h tsTcpPool; +static void *syncTmrCtrl = NULL; +static void *vgIdHash; +static pthread_once_t syncModuleInit = PTHREAD_ONCE_INIT; + +// local functions +static void syncProcessSyncRequest(char *pMsg, SSyncPeer *pPeer); +static void syncRecoverFromMaster(SSyncPeer *pPeer); +static void syncCheckPeerConnection(void *param, void *tmrId); +static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack); +static void syncProcessBrokenLink(void *param); +static int syncProcessPeerMsg(void *param, void *buffer); +static void syncProcessIncommingConnection(int connFd, uint32_t sourceIp); +static void syncRemovePeer(SSyncPeer *pPeer); +static void syncAddArbitrator(SSyncNode *pNode); +static void syncAddNodeRef(SSyncNode *pNode); +static void syncDecNodeRef(SSyncNode *pNode); +static void syncRemoveConfirmedFwdInfo(SSyncNode *pNode); +static void syncMonitorFwdInfos(void *param, void *tmrId); +static void syncProcessFwdAck(SSyncNode *pNode, SFwdInfo *pFwdInfo, int32_t code); +static void syncSaveFwdInfo(SSyncNode *pNode, uint64_t version, void *mhandle); +static void syncRestartPeer(SSyncPeer *pPeer); +static SSyncPeer *syncAddPeer(SSyncNode *pNode, const SNodeInfo *pInfo); + +char* syncRole[] = { + "offline", + "unsynced", + "slave", + "master" +}; + +static void syncModuleInitFunc() { + SPoolInfo info; + + info.numOfThreads = tsSyncTcpThreads; + info.serverIp = 0; + info.port = tsSyncPort; + info.bufferSize = 640000; + info.processBrokenLink = syncProcessBrokenLink; + info.processIncomingMsg = syncProcessPeerMsg; + info.processIncomingConn = syncProcessIncommingConnection; + + tsTcpPool = taosOpenTcpThreadPool(&info); + if (tsTcpPool == NULL) return; + + syncTmrCtrl = taosTmrInit(1000, 50, 10000, "SYNC"); + if (syncTmrCtrl == NULL) { + taosCloseTcpThreadPool(tsTcpPool); + tsTcpPool = NULL; + return; + } + + vgIdHash = taosHashInit(TSDB_MIN_VNODES, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true); + if (vgIdHash == NULL) { + taosTmrCleanUp(syncTmrCtrl); + taosCloseTcpThreadPool(tsTcpPool); + tsTcpPool = NULL; + syncTmrCtrl = NULL; + return; + } + + tstrncpy(tsNodeFqdn, tsLocalFqdn, sizeof(tsNodeFqdn)); +} + +void *syncStart(const SSyncInfo *pInfo) +{ + const SSyncCfg *pCfg = &pInfo->syncCfg; + + SSyncNode *pNode = (SSyncNode *) calloc(sizeof(SSyncNode), 1); + if (pNode == NULL) { + sError("no memory to allocate syncNode"); + terrno = TAOS_SYSTEM_ERROR(errno); + return NULL; + } + + pthread_once(&syncModuleInit, syncModuleInitFunc); + if (tsTcpPool == NULL) { + free(pNode); + syncModuleInit = PTHREAD_ONCE_INIT; + sError("failed to init sync module(%s)", tstrerror(errno)); + return NULL; + } + + atomic_add_fetch_32(&tsNodeNum, 1); + tstrncpy(pNode->path, pInfo->path, sizeof(pNode->path)); + pthread_mutex_init(&pNode->mutex, NULL); + + pNode->ahandle = pInfo->ahandle; + pNode->getFileInfo = pInfo->getFileInfo; + pNode->getWalInfo = pInfo->getWalInfo; + pNode->writeToCache = pInfo->writeToCache; + pNode->notifyRole = pInfo->notifyRole; + pNode->confirmForward = pInfo->confirmForward; + pNode->notifyFileSynced = pInfo->notifyFileSynced; + + pNode->selfIndex = -1; + pNode->vgId = pInfo->vgId; + pNode->replica = pCfg->replica; + pNode->quorum = pCfg->quorum; + for (int i = 0; i < pCfg->replica; ++i) { + const SNodeInfo *pNodeInfo = pCfg->nodeInfo + i; + pNode->peerInfo[i] = syncAddPeer(pNode, pNodeInfo); + if ((strcmp(pNodeInfo->nodeFqdn, tsNodeFqdn) == 0) && (pNodeInfo->nodePort == tsSyncPort)) + pNode->selfIndex = i; + } + + if (pNode->selfIndex < 0) { + sInfo("vgId:%d, this node is not configured", pNode->vgId); + terrno = TSDB_CODE_SYN_INVALID_CONFIG; + syncStop(pNode); + return NULL; + } + + nodeVersion = pInfo->version; // set the initial version + nodeRole = (pNode->replica > 1) ? TAOS_SYNC_ROLE_UNSYNCED : TAOS_SYNC_ROLE_MASTER; + sInfo("vgId:%d, %d replicas are configured, quorum:%d role:%s", pNode->vgId, pNode->replica, pNode->quorum, syncRole[nodeRole]); + + pNode->pSyncFwds = calloc(sizeof(SSyncFwds) + tsMaxFwdInfo*sizeof(SFwdInfo), 1); + if (pNode->pSyncFwds == NULL) { + sError("vgId:%d, no memory to allocate syncFwds", pNode->vgId); + terrno = TAOS_SYSTEM_ERROR(errno); + syncStop(pNode); + return NULL; + } + + pNode->pFwdTimer = taosTmrStart(syncMonitorFwdInfos, 300, pNode, syncTmrCtrl); + if (pNode->pFwdTimer == NULL) { + sError("vgId:%d, failed to allocate timer", pNode->vgId); + syncStop(pNode); + return NULL; + } + + syncAddArbitrator(pNode); + syncAddNodeRef(pNode); + taosHashPut(vgIdHash, (const char *)&pNode->vgId, sizeof(int32_t), (char *)(&pNode), sizeof(SSyncNode *)); + + if (pNode->notifyRole) + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + + return pNode; +} + +void syncStop(void *param) +{ + SSyncNode *pNode = param; + SSyncPeer *pPeer; + + if (pNode == NULL) return; + sInfo("vgId:%d, cleanup sync", pNode->vgId); + + pthread_mutex_lock(&(pNode->mutex)); + + for (int i = 0; i < pNode->replica; ++i) { + pPeer = pNode->peerInfo[i]; + if (pPeer) syncRemovePeer(pPeer); + } + + pPeer = pNode->peerInfo[TAOS_SYNC_MAX_REPLICA]; + if (pPeer) syncRemovePeer(pPeer); + + if (vgIdHash) taosHashRemove(vgIdHash, (const char *)&pNode->vgId, sizeof(int32_t)); + if (pNode->pFwdTimer) taosTmrStop(pNode->pFwdTimer); + + pthread_mutex_unlock(&(pNode->mutex)); + + syncDecNodeRef(pNode); +} + +int32_t syncReconfig(void *param, const SSyncCfg *pNewCfg) +{ + SSyncNode *pNode = param; + int i, j; + + if (pNode == NULL) return TSDB_CODE_SYN_INVALID_CONFIG; + sInfo("vgId:%d, reconfig, role:%s replica:%d old:%d", pNode->vgId, syncRole[nodeRole], + pNewCfg->replica, pNode->replica); + + pthread_mutex_lock(&(pNode->mutex)); + + for (i = 0; i < pNode->replica; ++i) { + for (j = 0; j < pNewCfg->replica; ++j) { + if ((strcmp(pNode->peerInfo[i]->fqdn, pNewCfg->nodeInfo[j].nodeFqdn) == 0) && + (pNode->peerInfo[i]->port == pNewCfg->nodeInfo[j].nodePort)) + break; + } + + if (j >= pNewCfg->replica) { + syncRemovePeer(pNode->peerInfo[i]); + pNode->peerInfo[i] = NULL; + } + } + + SSyncPeer *newPeers[TAOS_SYNC_MAX_REPLICA]; + for (i = 0; i < pNewCfg->replica; ++i) { + const SNodeInfo *pNewNode = &pNewCfg->nodeInfo[i]; + + for (j = 0; j < pNode->replica; ++j) { + if (pNode->peerInfo[j] && (strcmp(pNode->peerInfo[j]->fqdn, pNewNode->nodeFqdn) == 0) && + (pNode->peerInfo[j]->port == pNewNode->nodePort)) + break; + } + + if (j >= pNode->replica) { + newPeers[i] = syncAddPeer(pNode, pNewNode); + } else { + newPeers[i] = pNode->peerInfo[j]; + } + + if ((strcmp(pNewNode->nodeFqdn, tsNodeFqdn) == 0) && (pNewNode->nodePort == tsSyncPort)) + pNode->selfIndex = i; + } + + pNode->replica = pNewCfg->replica; + pNode->quorum = pNewCfg->quorum; + memcpy(pNode->peerInfo, newPeers, sizeof(SSyncPeer *) * pNewCfg->replica); + + for (i = pNewCfg->replica; i < TAOS_SYNC_MAX_REPLICA; ++i) + pNode->peerInfo[i] = NULL; + + syncAddArbitrator(pNode); + + if (pNewCfg->replica <= 1) { + sInfo("vgId:%d, no peers are configured, work as master!", pNode->vgId); + nodeRole = TAOS_SYNC_ROLE_MASTER; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + } + + pthread_mutex_unlock(&(pNode->mutex)); + + sInfo("vgId:%d, %d replicas are configured, quorum:%d role:%s", pNode->vgId, pNode->replica, pNode->quorum, syncRole[nodeRole]); + syncBroadcastStatus(pNode); + + return 0; +} + +int32_t syncForwardToPeer(void *param, void *data, void *mhandle, int qtype) +{ + SSyncNode *pNode = param; + SSyncPeer *pPeer; + SSyncHead *pSyncHead; + SWalHead *pWalHead = data; + int fwdLen; + int code = 0; + + if (pNode == NULL) return 0; + + // always update version + nodeVersion = pWalHead->version; + if (pNode->replica == 1 || nodeRole != TAOS_SYNC_ROLE_MASTER ) return 0; + + // only pkt from RPC or CQ can be forwarded + if (qtype != TAOS_QTYPE_RPC && qtype != TAOS_QTYPE_CQ) return 0; + + // a hacker way to improve the performance + pSyncHead = (SSyncHead *) ( ((char *)pWalHead) - sizeof(SSyncHead)); + pSyncHead->type = TAOS_SMSG_FORWARD; + pSyncHead->pversion = 0; + pSyncHead->len = sizeof(SWalHead) + pWalHead->len; + fwdLen = pSyncHead->len + sizeof(SSyncHead); //include the WAL and SYNC head + + pthread_mutex_lock(&(pNode->mutex)); + + if (pNode->quorum > 1) { + syncSaveFwdInfo(pNode, pWalHead->version, mhandle); + code = 1; + } + + for (int i = 0; i < pNode->replica; ++i) { + pPeer = pNode->peerInfo[i]; + if (pPeer == NULL || pPeer->peerFd <0) continue; + if (pPeer->role != TAOS_SYNC_ROLE_SLAVE && pPeer->sstatus != TAOS_SYNC_STATUS_CACHE) continue; + + int retLen = write(pPeer->peerFd, pSyncHead, fwdLen); + if (retLen == fwdLen) { + sDebug("%s, forward is sent, ver:%" PRIu64 " contLen:%d", pPeer->id, pWalHead->version, pWalHead->len); + } else { + sError("%s, failed to forward, ver:%" PRIu64 " retLen:%d", pPeer->id, pWalHead->version, retLen); + syncRestartConnection(pPeer); + } + } + + pthread_mutex_unlock(&(pNode->mutex)); + + return code; +} + +void syncConfirmForward(void *param, uint64_t version, int32_t code) +{ + SSyncNode *pNode = param; + if (pNode == NULL) return; + if (pNode->quorum <= 1) return; + + SSyncPeer *pPeer = pNode->pMaster; + if (pPeer == NULL) return; + + char msg[sizeof(SSyncHead) + sizeof(SFwdRsp)] = {0}; + + SSyncHead *pHead = (SSyncHead *) msg; + pHead->type = TAOS_SMSG_FORWARD_RSP; + pHead->len = sizeof(SFwdRsp); + + SFwdRsp *pFwdRsp = (SFwdRsp *)(msg + sizeof(SSyncHead)); + pFwdRsp->version = version; + pFwdRsp->code = code; + + int msgLen = sizeof(SSyncHead) + sizeof(SFwdRsp); + int retLen = write(pPeer->peerFd, msg, msgLen); + + if (retLen == msgLen) { + sDebug("%s, forward-rsp is sent, ver:%" PRIu64, pPeer->id, version); + } else { + sDebug("%s, failed to send forward ack, restart", pPeer->id); + syncRestartConnection(pPeer); + } +} + +void syncRecover(void *param) { + SSyncNode *pNode = param; + SSyncPeer *pPeer; + + // to do: add a few lines to check if recover is OK + // if take this node to unsync state, the whole system may not work + + nodeRole = TAOS_SYNC_ROLE_UNSYNCED; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + nodeVersion = 0; + + pthread_mutex_lock(&(pNode->mutex)); + + for (int i = 0; i < pNode->replica; ++i) { + pPeer = (SSyncPeer *) pNode->peerInfo[i]; + if (pPeer->peerFd >= 0) { + syncRestartConnection(pPeer); + } + } + + pthread_mutex_unlock(&(pNode->mutex)); +} + +int syncGetNodesRole(void *param, SNodesRole *pNodesRole) +{ + SSyncNode *pNode = param; + + pNodesRole->selfIndex = pNode->selfIndex; + for (int i=0; ireplica; ++i) { + pNodesRole->nodeId[i] = pNode->peerInfo[i]->nodeId; + pNodesRole->role[i] = pNode->peerInfo[i]->role; + } + + return 0; +} + +static void syncAddArbitrator(SSyncNode *pNode) +{ + SSyncPeer *pPeer = pNode->peerInfo[TAOS_SYNC_MAX_REPLICA]; + + // if not configured, return right away + if (tsArbitrator[0] == 0) { + if (pPeer) syncRemovePeer(pPeer); + pNode->peerInfo[TAOS_SYNC_MAX_REPLICA] = NULL; + return; + } + + SNodeInfo nodeInfo; + nodeInfo.nodeId = 0; + taosGetFqdnPortFromEp(tsArbitrator, nodeInfo.nodeFqdn, &nodeInfo.nodePort); + nodeInfo.nodePort += TSDB_PORT_SYNC; + + if (pPeer) { + if ((strcmp(nodeInfo.nodeFqdn, pPeer->fqdn) == 0) && (nodeInfo.nodePort == pPeer->port)) { + return; + } else { + syncRemovePeer(pPeer); + pNode->peerInfo[TAOS_SYNC_MAX_REPLICA] = NULL; + } + } + + pNode->peerInfo[TAOS_SYNC_MAX_REPLICA] = syncAddPeer(pNode, &nodeInfo); +} + +static void syncAddNodeRef(SSyncNode *pNode) +{ + atomic_add_fetch_8(&pNode->refCount, 1); +} + +static void syncDecNodeRef(SSyncNode *pNode) +{ + if (atomic_sub_fetch_8(&pNode->refCount, 1) == 0) { + pthread_mutex_destroy(&pNode->mutex); + tfree(pNode->pRecv); + tfree(pNode->pSyncFwds); + tfree(pNode); + + if (atomic_sub_fetch_32(&tsNodeNum, 1) == 0) { + if (tsTcpPool) taosCloseTcpThreadPool(tsTcpPool); + if (syncTmrCtrl) taosTmrCleanUp(syncTmrCtrl); + if (vgIdHash) taosHashCleanup(vgIdHash); + syncTmrCtrl = NULL; + tsTcpPool = NULL; + vgIdHash = NULL; + syncModuleInit = PTHREAD_ONCE_INIT; + sDebug("sync module is cleaned up"); + } + } +} + +void syncAddPeerRef(SSyncPeer *pPeer) +{ + atomic_add_fetch_8(&pPeer->refCount, 1); +} + +int syncDecPeerRef(SSyncPeer *pPeer) +{ + if (atomic_sub_fetch_8(&pPeer->refCount, 1) == 0) { + syncDecNodeRef(pPeer->pSyncNode); + + sDebug("%s, resource is freed", pPeer->id); + tfree(pPeer->watchFd); + tfree(pPeer); + return 0; + } + + return 1; +} + +static void syncClosePeerConn(SSyncPeer *pPeer) +{ + taosTmrStopA(&pPeer->timer); + tclose(pPeer->syncFd); + if (pPeer->peerFd >=0) { + pPeer->peerFd = -1; + taosFreeTcpConn(pPeer->pConn); + } +} + +static void syncRemovePeer(SSyncPeer *pPeer) +{ + sInfo("%s, it is removed", pPeer->id); + + pPeer->ip = 0; + syncClosePeerConn(pPeer); + syncDecPeerRef(pPeer); +} + +static SSyncPeer *syncAddPeer(SSyncNode *pNode, const SNodeInfo *pInfo) +{ + uint32_t ip = taosGetIpFromFqdn(pInfo->nodeFqdn); + if (ip == -1) return NULL; + + SSyncPeer *pPeer = (SSyncPeer *) calloc(1, sizeof(SSyncPeer)); + if (pPeer == NULL) return NULL; + + pPeer->nodeId = pInfo->nodeId; + tstrncpy(pPeer->fqdn, pInfo->nodeFqdn, sizeof(pPeer->fqdn)); + pPeer->ip = ip; + pPeer->port = pInfo->nodePort; + snprintf(pPeer->id, sizeof(pPeer->id), "vgId:%d peer:%s:%d", pNode->vgId, pPeer->fqdn, pPeer->port); + + pPeer->peerFd = -1; + pPeer->syncFd = -1; + pPeer->role = TAOS_SYNC_ROLE_OFFLINE; + pPeer->pSyncNode = pNode; + pPeer->refCount = 1; + + sInfo("%s, it is configured", pPeer->id); + int ret = strcmp(pPeer->fqdn, tsNodeFqdn); + if (pPeer->nodeId == 0 || (ret > 0) || (ret == 0 && pPeer->port > tsSyncPort)) { + sDebug("%s, start to check peer connection", pPeer->id); + taosTmrReset(syncCheckPeerConnection, 100, pPeer, syncTmrCtrl, &pPeer->timer); + } + + syncAddNodeRef(pNode); + return pPeer; +} + +void syncBroadcastStatus(SSyncNode *pNode) +{ + SSyncPeer *pPeer; + + for (int i = 0; i < pNode->replica; ++i) { + if ( i == pNode->selfIndex ) continue; + pPeer = pNode->peerInfo[i]; + syncSendPeersStatusMsgToPeer(pPeer, 1); + } +} + +static void syncChooseMaster(SSyncNode *pNode) { + SSyncPeer *pPeer; + int onlineNum = 0; + int index = -1; + int replica = pNode->replica; + + sDebug("vgId:%d, choose master", pNode->vgId); + + for (int i = 0; i < pNode->replica; ++i) { + if (pNode->peerInfo[i]->role != TAOS_SYNC_ROLE_OFFLINE) + onlineNum++; + } + + if (onlineNum == pNode->replica) { + // if all peers are online, peer with highest version shall be master + index = 0; + for (int i = 1; i < pNode->replica; ++i) { + if (pNode->peerInfo[i]->version > pNode->peerInfo[index]->version) + index = i; + } + } + + // add arbitrator connection + SSyncPeer *pArb = pNode->peerInfo[TAOS_SYNC_MAX_REPLICA]; + if (pArb && pArb->role != TAOS_SYNC_ROLE_OFFLINE) { + onlineNum++; + replica = pNode->replica + 1; + } + + if (index < 0 && onlineNum > replica/2.0) { + // over half of nodes are online + for (int i = 0; i < pNode->replica; ++i) { + //slave with highest version shall be master + pPeer = pNode->peerInfo[i]; + if (pPeer->role == TAOS_SYNC_ROLE_SLAVE || pPeer->role == TAOS_SYNC_ROLE_MASTER) { + if (index < 0 || pPeer->version > pNode->peerInfo[index]->version) + index = i; + } + } + } + + if (index >= 0) { + if (index == pNode->selfIndex) { + sInfo("vgId:%d, start to work as master", pNode->vgId); + nodeRole = TAOS_SYNC_ROLE_MASTER; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + } else { + pPeer = pNode->peerInfo[index]; + sInfo("%s, it shall work as master", pPeer->id); + } + } else { + sDebug("vgId:%d, failed to choose master", pNode->vgId); + } +} + +static SSyncPeer *syncCheckMaster(SSyncNode *pNode ) { + int onlineNum = 0; + int index = -1; + int replica = pNode->replica; + + for (int i = 0; i < pNode->replica; ++i) { + if (pNode->peerInfo[i]->role != TAOS_SYNC_ROLE_OFFLINE) + onlineNum++; + } + + // add arbitrator connection + SSyncPeer *pArb = pNode->peerInfo[TAOS_SYNC_MAX_REPLICA]; + if (pArb && pArb->role != TAOS_SYNC_ROLE_OFFLINE) { + onlineNum++; + replica = pNode->replica + 1; + } + + if (onlineNum <= replica*0.5) { + if (nodeRole != TAOS_SYNC_ROLE_UNSYNCED) { + nodeRole = TAOS_SYNC_ROLE_UNSYNCED; + pNode->peerInfo[pNode->selfIndex]->role = nodeRole; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + sInfo("vgId:%d, change to unsynced state, online:%d replica:%d", pNode->vgId, onlineNum, replica); + } + } else { + for (int i=0; ireplica; ++i) { + SSyncPeer *pTemp = pNode->peerInfo[i]; + if ( pTemp->role != TAOS_SYNC_ROLE_MASTER ) continue; + if ( index < 0 ) { + index = i; + } else { // multiple masters, it shall not happen + if ( i == pNode->selfIndex ) { + sError("%s, peer is master, work as slave instead", pTemp->id); + nodeRole = TAOS_SYNC_ROLE_SLAVE; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + } + } + } + } + + SSyncPeer *pMaster = (index>=0) ? pNode->peerInfo[index]:NULL; + return pMaster; +} + +static int syncValidateMaster(SSyncPeer *pPeer) { + SSyncNode *pNode = pPeer->pSyncNode; + int code = 0; + + if (nodeRole == TAOS_SYNC_ROLE_MASTER && nodeVersion < pPeer->version) { + sDebug("%s, slave has higher version, restart all connections!!!", pPeer->id); + nodeRole = TAOS_SYNC_ROLE_UNSYNCED; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + code = -1; + + for (int i = 0; i < pNode->replica; ++i) { + if ( i == pNode->selfIndex ) continue; + syncRestartPeer(pNode->peerInfo[i]); + } + } + + return code; +} + +static void syncCheckRole(SSyncPeer *pPeer, SPeerStatus peersStatus[], int8_t newRole) +{ + SSyncNode *pNode = pPeer->pSyncNode; + int8_t peerOldRole = pPeer->role; + int8_t selfOldRole = nodeRole; + int8_t i, syncRequired = 0; + + pNode->peerInfo[pNode->selfIndex]->version = nodeVersion; + pPeer->role = newRole; + + sDebug("%s, own role:%s, new peer role:%s", pPeer->id, + syncRole[nodeRole], syncRole[pPeer->role]); + + SSyncPeer *pMaster = syncCheckMaster(pNode); + + if ( pMaster ) { + // master is there + pNode->pMaster = pMaster; + sDebug("%s, it is the master, ver:%" PRIu64, pMaster->id, pMaster->version); + + if (syncValidateMaster(pPeer) < 0) return; + + if (nodeRole == TAOS_SYNC_ROLE_UNSYNCED) { + if ( nodeVersion < pMaster->version) { + syncRequired = 1; + } else { + sInfo("%s is master, work as slave, ver:%" PRIu64, pMaster->id, pMaster->version); + nodeRole = TAOS_SYNC_ROLE_SLAVE; + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + } + } else if ( nodeRole == TAOS_SYNC_ROLE_SLAVE && pMaster == pPeer) { + // nodeVersion = pMaster->version; + } + } else { + // master not there, if all peer's state and version are consistent, choose the master + int consistent = 0; + if (peersStatus) { + for (i = 0; i < pNode->replica; ++i) { + SSyncPeer *pTemp = pNode->peerInfo[i]; + if (pTemp->role != peersStatus[i].role) break; + if ((pTemp->role != TAOS_SYNC_ROLE_OFFLINE) && (pTemp->version != peersStatus[i].version)) break; + } + + if (i >= pNode->replica) consistent = 1; + } else { + if (pNode->replica == 2) consistent = 1; + } + + if (consistent) + syncChooseMaster(pNode); + } + + if (syncRequired) { + syncRecoverFromMaster(pMaster); + } + + if (peerOldRole != newRole || nodeRole != selfOldRole) + syncBroadcastStatus(pNode); +} + +static void syncRestartPeer(SSyncPeer *pPeer) { + sDebug("%s, restart connection", pPeer->id); + + syncClosePeerConn(pPeer); + + pPeer->sstatus = TAOS_SYNC_STATUS_INIT; + + int ret = strcmp(pPeer->fqdn, tsNodeFqdn); + if (ret > 0 || (ret == 0 && pPeer->port > tsSyncPort) ) + taosTmrReset(syncCheckPeerConnection, tsSyncTimer*1000, pPeer, syncTmrCtrl, &pPeer->timer); +} + +void syncRestartConnection(SSyncPeer *pPeer) +{ + if (pPeer->ip == 0) return; + + syncRestartPeer(pPeer); + syncCheckRole(pPeer, NULL, TAOS_SYNC_ROLE_OFFLINE); +} + +static void syncProcessSyncRequest(char *msg, SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + sDebug("%s, sync-req is received", pPeer->id); + + if (pPeer->ip == 0) return; + + if (nodeRole != TAOS_SYNC_ROLE_MASTER) { + sError("%s, I am not master anymore", pPeer->id); + tclose(pPeer->syncFd); + return; + } + + if (pPeer->sstatus != TAOS_SYNC_STATUS_INIT) { + sDebug("%s, sync is already started", pPeer->id); + return; // already started + } + + // start a new thread to retrieve the data + syncAddPeerRef(pPeer); + pthread_attr_t thattr; + pthread_t thread; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED); + int ret = pthread_create(&thread, &thattr, syncRetrieveData, pPeer); + pthread_attr_destroy(&thattr); + + if (ret != 0) { + sError("%s, failed to create sync thread(%s)", pPeer->id, strerror(errno)); + syncDecPeerRef(pPeer); + } else { + pPeer->sstatus = TAOS_SYNC_STATUS_START; + sDebug("%s, thread is created to retrieve data", pPeer->id); + } +} + +static void syncNotStarted(void *param, void *tmrId) +{ + SSyncPeer *pPeer = param; + SSyncNode *pNode = pPeer->pSyncNode; + + pthread_mutex_lock(&(pNode->mutex)); + pPeer->timer = NULL; + sInfo("%s, sync connection is still not up, restart", pPeer->id); + syncRestartConnection(pPeer); + pthread_mutex_unlock(&(pNode->mutex)); +} + +static void syncTryRecoverFromMaster(void *param, void *tmrId) { + SSyncPeer *pPeer = param; + SSyncNode *pNode = pPeer->pSyncNode; + + pthread_mutex_lock(&(pNode->mutex)); + syncRecoverFromMaster(pPeer); + pthread_mutex_unlock(&(pNode->mutex)); +} + +static void syncRecoverFromMaster(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + + if ( nodeSStatus != TAOS_SYNC_STATUS_INIT) { + sDebug("%s, sync is already started, status:%d", pPeer->id, nodeSStatus); + return; + } + + taosTmrStopA(&pPeer->timer); + if (tsSyncNum >= tsMaxSyncNum) { + sInfo("%s, %d syncs are in process, try later", pPeer->id, tsSyncNum); + taosTmrReset(syncTryRecoverFromMaster, 500, pPeer, syncTmrCtrl, &pPeer->timer); + return; + } + + sDebug("%s, try to sync", pPeer->id) + + SFirstPkt firstPkt; + memset(&firstPkt, 0, sizeof(firstPkt)); + firstPkt.syncHead.type = TAOS_SMSG_SYNC_REQ; + firstPkt.syncHead.vgId = pNode->vgId; + firstPkt.syncHead.len = sizeof(firstPkt) - sizeof(SSyncHead); + tstrncpy(firstPkt.fqdn, tsNodeFqdn, sizeof(firstPkt.fqdn)); + firstPkt.port = tsSyncPort; + taosTmrReset(syncNotStarted, tsSyncTimer*1000, pPeer, syncTmrCtrl, &pPeer->timer); + + if (write(pPeer->peerFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt) ) { + sError("%s, failed to send sync-req to peer", pPeer->id); + } else { + nodeSStatus = TAOS_SYNC_STATUS_START; + sInfo("%s, sync-req is sent", pPeer->id); + } + + return; +} + +static void syncProcessFwdResponse(char *cont, SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SFwdRsp *pFwdRsp = (SFwdRsp *) cont; + SSyncFwds *pSyncFwds = pNode->pSyncFwds; + SFwdInfo *pFwdInfo; + + sDebug("%s, forward-rsp is received, ver:%" PRIu64, pPeer->id, pFwdRsp->version); + SFwdInfo *pFirst = pSyncFwds->fwdInfo + pSyncFwds->first; + + if (pFirst->version <= pFwdRsp->version && pSyncFwds->fwds > 0) { + // find the forwardInfo from first + for (int i=0; ifwds; ++i) { + pFwdInfo = pSyncFwds->fwdInfo + (i+pSyncFwds->first)%tsMaxFwdInfo; + if (pFwdRsp->version == pFwdInfo->version) break; + } + + syncProcessFwdAck(pNode, pFwdInfo, pFwdRsp->code); + syncRemoveConfirmedFwdInfo(pNode); + } +} + + +static void syncProcessForwardFromPeer(char *cont, SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SWalHead *pHead = (SWalHead *)cont; + + sDebug("%s, forward is received, ver:%" PRIu64, pPeer->id, pHead->version); + + if (nodeRole == TAOS_SYNC_ROLE_SLAVE) { + //nodeVersion = pHead->version; + (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_FWD); + } else { + if (nodeSStatus != TAOS_SYNC_STATUS_INIT) { + syncSaveIntoBuffer(pPeer, pHead); + } else { + sError("%s, forward discarded, ver:%" PRIu64, pPeer->id, pHead->version); + } + } + + return; +} + +static void syncProcessPeersStatusMsg(char *cont, SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SPeersStatus *pPeersStatus = (SPeersStatus *)cont; + + sDebug("%s, status msg received, self:%s ver:%" PRIu64 " peer:%s ver:%" PRIu64 ", ack:%d", pPeer->id, + syncRole[nodeRole], nodeVersion, syncRole[pPeersStatus->role], pPeersStatus->version, pPeersStatus->ack); + + pPeer->version = pPeersStatus->version; + syncCheckRole(pPeer, pPeersStatus->peersStatus, pPeersStatus->role); + + if (pPeersStatus->ack) + syncSendPeersStatusMsgToPeer(pPeer, 0); +} + +static int syncReadPeerMsg(SSyncPeer *pPeer, SSyncHead *pHead, char *cont) { + if (pPeer->peerFd <0) return -1; + + int hlen = taosReadMsg(pPeer->peerFd, pHead, sizeof(SSyncHead)); + if (hlen != sizeof(SSyncHead)) { + sDebug("%s, failed to read msg, hlen:%d", pPeer->id, hlen); + return -1; + } + + // head.len = htonl(head.len); + if (pHead->len <0) { + sError("%s, invalid pkt length, len:%d", pPeer->id, pHead->len); + return -1; + } + + int bytes = taosReadMsg(pPeer->peerFd, cont, pHead->len); + if (bytes != pHead->len) { + sError("%s, failed to read, bytes:%d len:%d", pPeer->id, bytes, pHead->len); + return -1; + } + + return 0; +} + +static int syncProcessPeerMsg(void *param, void *buffer) +{ + SSyncPeer *pPeer = param; + SSyncHead head; + char *cont = (char *)buffer; + + SSyncNode *pNode = pPeer->pSyncNode; + pthread_mutex_lock(&(pNode->mutex)); + + int code = syncReadPeerMsg(pPeer, &head, cont); + + if (code == 0) { + if (head.type == TAOS_SMSG_FORWARD) { + syncProcessForwardFromPeer(cont, pPeer); + } else if (head.type == TAOS_SMSG_FORWARD_RSP) { + syncProcessFwdResponse(cont, pPeer); + } else if (head.type == TAOS_SMSG_SYNC_REQ) { + syncProcessSyncRequest(cont, pPeer); + } else if (head.type == TAOS_SMSG_STATUS) { + syncProcessPeersStatusMsg(cont, pPeer); + } + } + + pthread_mutex_unlock(&(pNode->mutex)); + + return code; +} + +#define statusMsgLen sizeof(SSyncHead)+sizeof(SPeersStatus)+sizeof(SPeerStatus)*TAOS_SYNC_MAX_REPLICA + +static void syncSendPeersStatusMsgToPeer(SSyncPeer *pPeer, char ack) +{ + SSyncNode *pNode = pPeer->pSyncNode; + char msg[statusMsgLen] = {0}; + + if (pPeer->peerFd <0 || pPeer->ip ==0) return; + + SSyncHead *pHead = (SSyncHead *) msg; + SPeersStatus *pPeersStatus = (SPeersStatus *) (msg + sizeof(SSyncHead)); + + pHead->type = TAOS_SMSG_STATUS; + pHead->len = statusMsgLen - sizeof(SSyncHead); + + pPeersStatus->version = nodeVersion; + pPeersStatus->role = nodeRole; + pPeersStatus->ack = ack; + + for (int i = 0; i < pNode->replica; ++i) { + pPeersStatus->peersStatus[i].role = pNode->peerInfo[i]->role; + pPeersStatus->peersStatus[i].version = pNode->peerInfo[i]->version; + } + + int retLen = write(pPeer->peerFd, msg, statusMsgLen); + if (retLen == statusMsgLen) { + sDebug("%s, status msg is sent", pPeer->id); + } else { + sDebug("%s, failed to send status msg, restart", pPeer->id); + syncRestartConnection(pPeer); + } + + return; +} + +static void syncSetupPeerConnection(SSyncPeer *pPeer) { + SSyncNode *pNode = pPeer->pSyncNode; + + taosTmrStopA(&pPeer->timer); + if (pPeer->peerFd >= 0) { + sDebug("%s, send role version to peer", pPeer->id); + syncSendPeersStatusMsgToPeer(pPeer, 1); + return; + } + + int connFd = taosOpenTcpClientSocket(pPeer->ip, pPeer->port, 0); + if (connFd < 0) { + sDebug("%s, failed to open tcp socket(%s)", pPeer->id, strerror(errno)); + taosTmrReset(syncCheckPeerConnection, tsSyncTimer *1000, pPeer, syncTmrCtrl, &pPeer->timer); + return; + } + + SFirstPkt firstPkt; + memset(&firstPkt, 0, sizeof(firstPkt)); + firstPkt.syncHead.vgId = pPeer->nodeId ? pNode->vgId:0; + firstPkt.syncHead.type = TAOS_SMSG_STATUS; + tstrncpy(firstPkt.fqdn, tsNodeFqdn, sizeof(firstPkt.fqdn)); + firstPkt.port = tsSyncPort; + firstPkt.sourceId = pNode->vgId; // tell arbitrator its vgId + + if ( write(connFd, &firstPkt, sizeof(firstPkt)) == sizeof(firstPkt)) { + sDebug("%s, connection to peer server is setup", pPeer->id); + pPeer->peerFd = connFd; + pPeer->role = TAOS_SYNC_ROLE_UNSYNCED; + pPeer->pConn = taosAllocateTcpConn(tsTcpPool, pPeer, connFd); + syncAddPeerRef(pPeer); + } else { + sDebug("try later"); + close(connFd); + taosTmrReset(syncCheckPeerConnection, tsSyncTimer *1000, pPeer, syncTmrCtrl, &pPeer->timer); + } +} + +static void syncCheckPeerConnection(void *param, void *tmrId) +{ + SSyncPeer *pPeer = param; + SSyncNode *pNode = pPeer->pSyncNode; + + pthread_mutex_lock(&(pNode->mutex)); + + sDebug("%s, check peer connection", pPeer->id); + syncSetupPeerConnection(pPeer); + + pthread_mutex_unlock(&(pNode->mutex)); +} + +static void syncCreateRestoreDataThread(SSyncPeer *pPeer) +{ + taosTmrStopA(&pPeer->timer); + + pthread_attr_t thattr; + pthread_t thread; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED); + + syncAddPeerRef(pPeer); + int ret = pthread_create(&(thread), &thattr, (void *)syncRestoreData, pPeer); + pthread_attr_destroy(&thattr); + + if (ret < 0) { + sError("%s, failed to create sync thread", pPeer->id); + tclose(pPeer->syncFd); + syncDecPeerRef(pPeer); + } else { + sInfo("%s, sync connection is up", pPeer->id); + } +} + +static void syncProcessIncommingConnection(int connFd, uint32_t sourceIp) +{ + char ipstr[24]; + int i; + + tinet_ntoa(ipstr, sourceIp); + sDebug("peer TCP connection from ip:%s", ipstr); + + SFirstPkt firstPkt; + if (taosReadMsg(connFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt)) { + sError("failed to read peer first pkt from ip:%s(%s)", ipstr, strerror(errno)); + taosCloseSocket(connFd); + return; + } + + int32_t vgId = firstPkt.syncHead.vgId; + SSyncNode **ppNode = (SSyncNode **)taosHashGet(vgIdHash, (const char *)&vgId, sizeof(int32_t)); + if (ppNode == NULL || *ppNode == NULL) { + sError("vgId:%d, vgId could not be found", vgId); + taosCloseSocket(connFd); + return; + } + + SSyncNode *pNode = *ppNode; + pthread_mutex_lock(&(pNode->mutex)); + + SSyncPeer *pPeer; + for (i = 0; i < pNode->replica; ++i) { + pPeer = pNode->peerInfo[i]; + if (pPeer && (strcmp(pPeer->fqdn, firstPkt.fqdn) == 0) && (pPeer->port == firstPkt.port)) + break; + } + + pPeer = (i < pNode->replica) ? pNode->peerInfo[i] : NULL; + if (pPeer == NULL) { + sError("vgId:%d, peer:%s not configured", pNode->vgId, firstPkt.fqdn); + taosCloseSocket(connFd); + // syncSendVpeerCfgMsg(sync); + } else { + // first packet tells what kind of link + if (firstPkt.syncHead.type == TAOS_SMSG_SYNC_DATA) { + pPeer->syncFd = connFd; + syncCreateRestoreDataThread(pPeer); + } else { + sDebug("%s, TCP connection is already up, close one", pPeer->id); + syncClosePeerConn(pPeer); + pPeer->peerFd = connFd; + pPeer->pConn = taosAllocateTcpConn(tsTcpPool, pPeer, connFd); + syncAddPeerRef(pPeer); + sDebug("%s, ready to exchange data", pPeer->id); + syncSendPeersStatusMsgToPeer(pPeer, 1); + } + } + + pthread_mutex_unlock(&(pNode->mutex)); + + return; +} + +static void syncProcessBrokenLink(void *param) { + if (param == NULL) return; // the connection for arbitrator + SSyncPeer *pPeer = param; + SSyncNode *pNode = pPeer->pSyncNode; + + syncAddNodeRef(pNode); + pthread_mutex_lock(&(pNode->mutex)); + + sDebug("%s, TCP link is broken(%s)", pPeer->id, strerror(errno)); + pPeer->peerFd = -1; + + if (syncDecPeerRef(pPeer) != 0) { + syncRestartConnection(pPeer); + } + + pthread_mutex_unlock(&(pNode->mutex)); + syncDecNodeRef(pNode); +} + +static void syncSaveFwdInfo(SSyncNode *pNode, uint64_t version, void *mhandle) +{ + SSyncFwds *pSyncFwds = pNode->pSyncFwds; + uint64_t time = taosGetTimestampMs(); + + if (pSyncFwds->fwds >= tsMaxFwdInfo) { + pSyncFwds->first = (pSyncFwds->first + 1) % tsMaxFwdInfo; + pSyncFwds->fwds--; + } + + if (pSyncFwds->fwds > 0) + pSyncFwds->last = (pSyncFwds->last+1) % tsMaxFwdInfo; + SFwdInfo *pFwdInfo = pSyncFwds->fwdInfo + pSyncFwds->last; + pFwdInfo->version = version; + pFwdInfo->mhandle = mhandle; + pFwdInfo->acks = 0; + pFwdInfo->confirmed = 0; + pFwdInfo->time = time; + + pSyncFwds->fwds++; + sDebug("vgId:%d, fwd info is saved, ver:%" PRIu64 " fwds:%d ", pNode->vgId, version, pSyncFwds->fwds); +} + +static void syncRemoveConfirmedFwdInfo(SSyncNode *pNode) +{ + SSyncFwds *pSyncFwds = pNode->pSyncFwds; + + int fwds = pSyncFwds->fwds; + for (int i=0; ifwdInfo + pSyncFwds->first; + if (pFwdInfo->confirmed == 0) break; + + pSyncFwds->first = (pSyncFwds->first+1) % tsMaxFwdInfo; + pSyncFwds->fwds--; + if (pSyncFwds->fwds == 0) pSyncFwds->first = pSyncFwds->last; + //sDebug("vgId:%d, fwd info is removed, ver:%d, fwds:%d", + // pNode->vgId, pFwdInfo->version, pSyncFwds->fwds); + memset(pFwdInfo, 0, sizeof(SFwdInfo)); + } +} + +static void syncProcessFwdAck(SSyncNode *pNode, SFwdInfo *pFwdInfo, int32_t code) +{ + int confirm = 0; + if (pFwdInfo->code == 0) pFwdInfo->code = code; + + if (code == 0) { + pFwdInfo->acks++; + if (pFwdInfo->acks >= pNode->quorum-1) + confirm = 1; + } else { + pFwdInfo->nacks++; + if (pFwdInfo->nacks > pNode->replica-pNode->quorum) + confirm = 1; + } + + if (confirm && pFwdInfo->confirmed == 0) { + sDebug("vgId:%d, forward is confirmed, ver:%" PRIu64 " code:%x", pNode->vgId, pFwdInfo->version, pFwdInfo->code); + (*pNode->confirmForward)(pNode->ahandle, pFwdInfo->mhandle, pFwdInfo->code); + pFwdInfo->confirmed = 1; + } +} + +static void syncMonitorFwdInfos(void *param, void *tmrId) +{ + SSyncNode *pNode = param; + SSyncFwds *pSyncFwds = pNode->pSyncFwds; + uint64_t time = taosGetTimestampMs(); + + if (pSyncFwds->fwds > 0) { + pthread_mutex_lock(&(pNode->mutex)); + for (int i=0; ifwds; ++i) { + SFwdInfo *pFwdInfo = pSyncFwds->fwdInfo + (pSyncFwds->first+i) % tsMaxFwdInfo; + if (time - pFwdInfo->time < 2000) break; + syncProcessFwdAck(pNode, pFwdInfo, TSDB_CODE_RPC_NETWORK_UNAVAIL); + } + + syncRemoveConfirmedFwdInfo(pNode); + pthread_mutex_unlock(&(pNode->mutex)); + } + + pNode->pFwdTimer = taosTmrStart(syncMonitorFwdInfos, 300, pNode, syncTmrCtrl); +} + + + diff --git a/src/sync/src/syncRestore.c b/src/sync/src/syncRestore.c new file mode 100644 index 0000000000..34afbc4db6 --- /dev/null +++ b/src/sync/src/syncRestore.c @@ -0,0 +1,326 @@ +/* + * 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 . + */ + +#include "os.h" +#include "tlog.h" +#include "tutil.h" +#include "ttimer.h" +#include "tsocket.h" +#include "tqueue.h" +#include "twal.h" +#include "tsync.h" +#include "syncInt.h" + +static void syncRemoveExtraFile(SSyncPeer *pPeer, uint32_t sindex, uint32_t eindex) { + char name[TSDB_FILENAME_LEN*2] = {0}; + char fname[TSDB_FILENAME_LEN*3] = {0}; + uint32_t magic; + uint64_t fversion; + int32_t size; + uint32_t index = sindex; + SSyncNode *pNode = pPeer->pSyncNode; + + if (sindex < 0 || eindex < sindex) return; + + while (1) { + name[0] = 0; + magic = (*pNode->getFileInfo)(pNode->ahandle, name, &index, eindex, &size, &fversion); + if (magic == 0) break; + + snprintf(fname, sizeof(fname), "%s/%s", pNode->path, name); + remove(fname); + sDebug("%s, %s is removed", pPeer->id, fname); + + index++; + if (index > eindex) break; + } +} + +static int syncRestoreFile(SSyncPeer *pPeer, uint64_t *fversion) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SFileInfo minfo; memset(&minfo, 0, sizeof(minfo)); /* = {0}; */ // master file info + SFileInfo sinfo; memset(&sinfo, 0, sizeof(sinfo)); /* = {0}; */ // slave file info + SFileAck fileAck; + int code = -1; + char name[TSDB_FILENAME_LEN * 2] = {0}; + uint32_t pindex = 0; // index in last restore + + *fversion = 0; + sinfo.index = 0; + while (1) { + // read file info + int ret = taosReadMsg(pPeer->syncFd, &(minfo), sizeof(minfo)); + if (ret < 0 ) break; + + // if no more file from master, break; + if (minfo.name[0] == 0 || minfo.magic == 0) { + sDebug("%s, no more files to restore", pPeer->id); + + // remove extra files after the current index + syncRemoveExtraFile(pPeer, sinfo.index+1, TAOS_SYNC_MAX_INDEX); + code = 0; + break; + } + + // remove extra files on slave between the current and last index + syncRemoveExtraFile(pPeer, pindex+1, minfo.index-1); + pindex = minfo.index; + + // check the file info + sinfo = minfo; + sDebug("%s, get file info:%s", pPeer->id, minfo.name); + sinfo.magic = (*pNode->getFileInfo)(pNode->ahandle, sinfo.name, &sinfo.index, TAOS_SYNC_MAX_INDEX, &sinfo.size, &sinfo.fversion); + + // if file not there or magic is not the same, file shall be synced + memset(&fileAck, 0, sizeof(fileAck)); + fileAck.sync = (sinfo.magic != minfo.magic || sinfo.name[0] == 0) ? 1:0; + + // send file ack + ret = taosWriteMsg(pPeer->syncFd, &(fileAck), sizeof(fileAck)); + if (ret <0) break; + + // if sync is not required, continue + if (fileAck.sync == 0) { + sDebug("%s, %s is the same", pPeer->id, minfo.name); + continue; + } + + // if sync is required, open file, receive from master, and write to file + // get the full path to file + snprintf(name, sizeof(name), "%s/%s", pNode->path, minfo.name); + + int dfd = open(name, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO); + if ( dfd < 0 ) { + sError("%s, failed to open file:%s", pPeer->id, name); + break; + } + + ret = taosCopyFds(pPeer->syncFd, dfd, minfo.size); + fsync(dfd); + close(dfd); + if (ret<0) break; + + sDebug("%s, %s is received, size:%d", pPeer->id, minfo.name, minfo.size); + + } + + if (code == 0 && (minfo.fversion != sinfo.fversion)) { + // data file is changed, code shall be set to 1 + *fversion = minfo.fversion; + code = 1; + } + + if (code < 0) { + sError("%s, failed to restore %s(%s)", pPeer->id, name, strerror(errno)); + } + + return code; +} + +static int syncRestoreWal(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + int ret, code = -1; + + void *buffer = calloc(1024000, 1); // size for one record + if (buffer == NULL) return -1; + + SWalHead *pHead = (SWalHead *)buffer; + + while (1) { + ret = taosReadMsg(pPeer->syncFd, pHead, sizeof(SWalHead)); + if (ret <0) break; + + if (pHead->len == 0) {code = 0; break;} // wal sync over + + ret = taosReadMsg(pPeer->syncFd, pHead->cont, pHead->len); + if (ret <0) break; + + sDebug("%s, restore a record, ver:%" PRIu64, pPeer->id, pHead->version); + (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_WAL); + } + + if (code<0) { + sError("%s, failed to restore wal(%s)", pPeer->id, strerror(errno)); + } + + free(buffer); + return code; +} + +static char *syncProcessOneBufferedFwd(SSyncPeer *pPeer, char *offset) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SWalHead *pHead = (SWalHead *) offset; + + (*pNode->writeToCache)(pNode->ahandle, pHead, TAOS_QTYPE_FWD); + offset += pHead->len + sizeof(SWalHead); + + return offset; +} + +static int syncProcessBufferedFwd(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SRecvBuffer *pRecv = pNode->pRecv; + int forwards = 0; + + sDebug("%s, number of buffered forwards:%d", pPeer->id, pRecv->forwards); + + char *offset = pRecv->buffer; + while (forwards < pRecv->forwards) { + offset = syncProcessOneBufferedFwd(pPeer, offset); + forwards++; + } + + pthread_mutex_lock(&pNode->mutex); + + while (forwards < pRecv->forwards && pRecv->code == 0) { + offset = syncProcessOneBufferedFwd(pPeer, offset); + forwards++; + } + + nodeRole = TAOS_SYNC_ROLE_SLAVE; + sDebug("%s, finish processing buffered fwds:%d", pPeer->id, forwards); + + pthread_mutex_unlock(&pNode->mutex); + + return pRecv->code; +} + +int syncSaveIntoBuffer(SSyncPeer *pPeer, SWalHead *pHead) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SRecvBuffer *pRecv = pNode->pRecv; + + if (pRecv == NULL) return -1; + int len = pHead->len + sizeof(SWalHead); + + if (pRecv->bufferSize - (pRecv->offset - pRecv->buffer) >= len) { + memcpy(pRecv->offset, pHead, len); + pRecv->offset += len; + pRecv->forwards++; + sDebug("%s, fwd is saved into queue, ver:%" PRIu64 " fwds:%d", pPeer->id, pHead->version, pRecv->forwards); + } else { + sError("%s, buffer size:%d is too small", pPeer->id, pRecv->bufferSize); + pRecv->code = -1; // set error code + } + + return pRecv->code; +} + +static void syncCloseRecvBuffer(SSyncNode *pNode) +{ + if (pNode->pRecv) { + tfree(pNode->pRecv->buffer); + } + + tfree(pNode->pRecv); +} + +static int syncOpenRecvBuffer(SSyncNode *pNode) +{ + syncCloseRecvBuffer(pNode); + + SRecvBuffer *pRecv = calloc(sizeof(SRecvBuffer), 1); + if (pRecv == NULL) return -1; + + pRecv->bufferSize = 5000000; + pRecv->buffer = malloc(pRecv->bufferSize); + if (pRecv->buffer == NULL) { + free(pRecv); + return -1; + } + + pRecv->offset = pRecv->buffer; + pRecv->forwards = 0; + + pNode->pRecv = pRecv; + + return 0; +} + +static int syncRestoreDataStepByStep(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + nodeSStatus = TAOS_SYNC_STATUS_FILE; + uint64_t fversion = 0; + + sDebug("%s, start to restore file", pPeer->id); + int code = syncRestoreFile(pPeer, &fversion); + if (code < 0) { + sError("%s, failed to restore file", pPeer->id); + return -1; + } + + // if code > 0, data file is changed, notify app, and pass the version + if (code > 0 && pNode->notifyFileSynced) { + if ( (*pNode->notifyFileSynced)(pNode->ahandle, fversion) < 0 ) { + sError("%s, app not in ready state", pPeer->id); + return -1; + } + } + + nodeVersion = fversion; + + sDebug("%s, start to restore wal", pPeer->id); + if (syncRestoreWal(pPeer) < 0) { + sError("%s, failed to restore wal", pPeer->id); + return -1; + } + + nodeSStatus = TAOS_SYNC_STATUS_CACHE; + sDebug("%s, start to insert buffered points", pPeer->id); + if (syncProcessBufferedFwd(pPeer) < 0) { + sError("%s, failed to insert buffered points", pPeer->id); + return -1; + } + + return 0; +} + +void *syncRestoreData(void *param) +{ + SSyncPeer *pPeer = (SSyncPeer *)param; + SSyncNode *pNode = pPeer->pSyncNode; + + taosBlockSIGPIPE(); + __sync_fetch_and_add(&tsSyncNum, 1); + + if (syncOpenRecvBuffer(pNode) < 0) { + sError("%s, failed to allocate recv buffer", pPeer->id); + } else { + if ( syncRestoreDataStepByStep(pPeer) == 0) { + sInfo("%s, it is synced successfully", pPeer->id); + nodeRole = TAOS_SYNC_ROLE_SLAVE; + syncBroadcastStatus(pNode); + (*pNode->notifyRole)(pNode->ahandle, nodeRole); + } else { + sError("%s, failed to restore data, restart connection", pPeer->id); + nodeRole = TAOS_SYNC_ROLE_UNSYNCED; + syncRestartConnection(pPeer); + } + } + + nodeSStatus = TAOS_SYNC_STATUS_INIT; + tclose(pPeer->syncFd) + syncCloseRecvBuffer(pNode); + __sync_fetch_and_sub(&tsSyncNum, 1); + syncDecPeerRef(pPeer); + + return NULL; +} + diff --git a/src/sync/src/syncRetrieve.c b/src/sync/src/syncRetrieve.c new file mode 100644 index 0000000000..c7f136ed9d --- /dev/null +++ b/src/sync/src/syncRetrieve.c @@ -0,0 +1,479 @@ +/* + * 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 . + */ + +#include +#include +#include +#include +#include "os.h" +#include "tlog.h" +#include "tutil.h" +#include "tglobal.h" +#include "ttimer.h" +#include "tsocket.h" +#include "twal.h" +#include "tsync.h" +#include "syncInt.h" + +static int syncAddIntoWatchList(SSyncPeer *pPeer, char *name) +{ + sDebug("%s, start to monitor:%s", pPeer->id, name); + + if (pPeer->notifyFd <=0) { + pPeer->watchNum = 0; + pPeer->notifyFd = inotify_init1(IN_NONBLOCK); + if (pPeer->notifyFd < 0) { + sError("%s, failed to init inotify(%s)", pPeer->id, strerror(errno)); + return -1; + } + + if (pPeer->watchFd == NULL) pPeer->watchFd = malloc(sizeof(int)*tsMaxWatchFiles); + if (pPeer->watchFd == NULL) { + sError("%s, failed to allocate watchFd", pPeer->id); + return -1; + } + + memset(pPeer->watchFd, -1, sizeof(int)*tsMaxWatchFiles); + } + + int *wd = pPeer->watchFd + pPeer->watchNum; + + if (*wd >= 0) { + if (inotify_rm_watch(pPeer->notifyFd, *wd) < 0) { + sError("%s, failed to remove wd:%d(%s)", pPeer->id, *wd, strerror(errno)); + return -1; + } + } + + *wd = inotify_add_watch(pPeer->notifyFd, name, IN_MODIFY); + if (*wd == -1) { + sError("%s, failed to add %s(%s)", pPeer->id, name, strerror(errno)); + return -1; + } + + pPeer->watchNum++; + pPeer->watchNum = (pPeer->watchNum +1) % tsMaxWatchFiles; + + return 0; +} + +static int syncAreFilesModified(SSyncPeer *pPeer) +{ + if (pPeer->notifyFd <=0) return 0; + + char buf[2048]; + int len = read(pPeer->notifyFd, buf, sizeof(buf)); + if (len <0 && errno != EAGAIN) { + sError("%s, failed to read notify FD(%s)", pPeer->id, strerror(errno)); + return -1; + } + + int code = 0; + if (len >0) { + sDebug("%s, processed file is changed", pPeer->id); + code = 1; + } + + return code; +} + +static int syncRetrieveFile(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + SFileInfo fileInfo; + SFileAck fileAck; + int code = -1; + char name[TSDB_FILENAME_LEN * 2] = {0}; + + memset(&fileInfo, 0, sizeof(fileInfo)); + memset(&fileAck, 0, sizeof(fileAck)); + + while (1) { + // retrieve file info + fileInfo.name[0] = 0; + fileInfo.magic = (*pNode->getFileInfo)(pNode->ahandle, fileInfo.name, &fileInfo.index, TAOS_SYNC_MAX_INDEX, &fileInfo.size, &fileInfo.fversion); + //fileInfo.size = htonl(size); + + // send the file info + int32_t ret = taosWriteMsg(pPeer->syncFd, &(fileInfo), sizeof(fileInfo)); + if (ret < 0 ) break; + + // if no file anymore, break + if (fileInfo.magic == 0 || fileInfo.name[0] == 0) { + sDebug("%s, no more files to sync", pPeer->id); + code = 0; break; + } + + // wait for the ack from peer + ret = taosReadMsg(pPeer->syncFd, &(fileAck), sizeof(fileAck)); + if (ret <0) break; + + // set the peer sync version + pPeer->sversion = fileInfo.fversion; + + // get the full path to file + snprintf(name, sizeof(name), "%s/%s", pNode->path, fileInfo.name); + + // add the file into watch list + if ( syncAddIntoWatchList(pPeer, name) <0) break; + + // if sync is not required, continue + if (fileAck.sync == 0) { + fileInfo.index++; + sDebug("%s, %s is the same", pPeer->id, fileInfo.name); + continue; + } + + // send the file to peer + int sfd = open(name, O_RDONLY); + if ( sfd < 0 ) break; + + ret = tsendfile(pPeer->syncFd, sfd, NULL, fileInfo.size); + close(sfd); + if (ret <0) break; + + sDebug("%s, %s is sent, size:%d", pPeer->id, name, fileInfo.size); + fileInfo.index++; + + // check if processed files are modified + if (syncAreFilesModified(pPeer) != 0) break; + } + + if (code < 0) { + sError("%s, failed to retrieve file(%s)", pPeer->id, strerror(errno)); + } + + return code; +} + +/* if only a partial record is read out, set the IN_MODIFY flag in event, + so upper layer will reload the file to get a complete record */ +static int syncReadOneWalRecord(int sfd, SWalHead *pHead, uint32_t *pEvent) +{ + int ret; + + ret = read(sfd, pHead, sizeof(SWalHead)); + if (ret < 0) return -1; + if (ret == 0) return 0; + + if (ret != sizeof(SWalHead)) { + // file is not at end yet, it shall be reloaded + *pEvent = *pEvent | IN_MODIFY; + return 0; + } + + ret = read(sfd, pHead->cont, pHead->len); + if (ret <0) return -1; + + if (ret != pHead->len) { + // file is not at end yet, it shall be reloaded + *pEvent = *pEvent | IN_MODIFY; + return 0; + } + + return sizeof(SWalHead) + pHead->len; +} + +static int syncMonitorLastWal(SSyncPeer *pPeer, char *name) +{ + pPeer->watchNum = 0; + tclose(pPeer->notifyFd); + pPeer->notifyFd = inotify_init1(IN_NONBLOCK); + if (pPeer->notifyFd < 0) { + sError("%s, failed to init inotify(%s)", pPeer->id, strerror(errno)); + return -1; + } + + if (pPeer->watchFd == NULL) pPeer->watchFd = malloc(sizeof(int)*tsMaxWatchFiles); + if (pPeer->watchFd == NULL) { + sError("%s, failed to allocate watchFd", pPeer->id); + return -1; + } + + memset(pPeer->watchFd, -1, sizeof(int)*tsMaxWatchFiles); + int *wd = pPeer->watchFd; + + *wd = inotify_add_watch(pPeer->notifyFd, name, IN_MODIFY | IN_CLOSE_WRITE); + if (*wd == -1) { + sError("%s, failed to watch last wal(%s)", pPeer->id, strerror(errno)); + return -1; + } + + return 0; +} + +static uint32_t syncCheckLastWalChanges(SSyncPeer *pPeer, uint32_t *pEvent) +{ + char buf[2048]; + int len = read(pPeer->notifyFd, buf, sizeof(buf)); + if (len <0 && errno != EAGAIN) { + sError("%s, failed to read notify FD(%s)", pPeer->id, strerror(errno)); + return -1; + } + + if (len == 0) return 0; + + struct inotify_event *event; + for (char *ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len) { + event = (struct inotify_event *) ptr; + if (event->mask & IN_MODIFY) *pEvent = *pEvent | IN_MODIFY; + if (event->mask & IN_CLOSE_WRITE) *pEvent = *pEvent | IN_CLOSE_WRITE; + } + + if (pEvent != 0) + sDebug("%s, last wal event:0x%x", pPeer->id, *pEvent); + + return 0; +} + +static int syncRetrieveLastWal(SSyncPeer *pPeer, char *name, uint64_t fversion, int64_t offset, uint32_t *pEvent) +{ + SWalHead *pHead = (SWalHead *) malloc(640000); + int code = -1; + int32_t bytes = 0; + int sfd; + + sfd = open(name, O_RDONLY); + if (sfd < 0) return -1; + lseek(sfd, offset, SEEK_SET); + sDebug("%s, retrieve last wal, offset:%" PRId64 " fversion:%" PRIu64, pPeer->id, offset, fversion); + + while (1) { + int wsize = syncReadOneWalRecord(sfd, pHead, pEvent); + if (wsize <0) break; + if (wsize == 0) { code = 0; break; } + + sDebug("%s, last wal is forwarded, ver:%" PRIu64, pPeer->id, pHead->version); + int ret = taosWriteMsg(pPeer->syncFd, pHead, wsize); + if ( ret != wsize ) break; + pPeer->sversion = pHead->version; + + bytes += wsize; + + if (pHead->version >= fversion && fversion > 0) { + code = 0; + bytes = 0; + break; + } + } + + free(pHead); + tclose(sfd); + + if (code == 0) return bytes; + return -1; +} + +static int syncProcessLastWal(SSyncPeer *pPeer, char *wname, uint32_t index) +{ + SSyncNode *pNode = pPeer->pSyncNode; + int code = -1; + char fname[TSDB_FILENAME_LEN * 2]; // full path to wal file + + if (syncAreFilesModified(pPeer) != 0) return -1; + + while (1) { + int32_t once = 0; // last WAL has once ever been processed + int64_t offset = 0; + uint64_t fversion = 0; + uint32_t event = 0; + + // get full path to wal file + snprintf(fname, sizeof(fname), "%s/%s", pNode->path, wname); + sDebug("%s, start to retrieve last wal:%s", pPeer->id, fname); + + // monitor last wal + if (syncMonitorLastWal(pPeer, fname) <0) break; + + while (1) { + int32_t bytes = syncRetrieveLastWal(pPeer, fname, fversion, offset, &event); + if (bytes < 0) break; + + // check file changes + if (syncCheckLastWalChanges(pPeer, &event) <0) break; + + // if file is not updated or updated once, set the fversion and sstatus + if (((event & IN_MODIFY) == 0) || once) { + if (fversion == 0) { + pPeer->sstatus = TAOS_SYNC_STATUS_CACHE; // start to forward pkt + fversion = nodeVersion; // must read data to fversion + } + } + + // if all data up to fversion is read out, it is over + if (pPeer->sversion >= fversion && fversion > 0) { + code = 0; + sDebug("%s, data up to fversion:%ld has been read out, bytes:%d", pPeer->id, fversion, bytes); + break; + } + + // if all data are read out, and no update + if ((bytes == 0) && ((event & IN_MODIFY) == 0)) { + // wal file is closed, break + if (event & IN_CLOSE_WRITE) { + code = 0; + sDebug("%s, current wal is closed", pPeer->id); + break; + } + + // wal not closed, it means some data not flushed to disk, wait for a while + usleep(10000); + } + + // if bytes>0, file is updated, or fversion is not reached but file still open, read again + once = 1; + offset += bytes; + sDebug("%s, retrieve last wal, bytes:%d", pPeer->id, bytes); + event = event & (~IN_MODIFY); // clear IN_MODIFY flag + } + + if (code < 0) break; + if (pPeer->sversion >= fversion && fversion > 0) break; + + index++; wname[0] = 0; + code = (*pNode->getWalInfo)(pNode->ahandle, wname, &index); + if ( code < 0) break; + if ( wname[0] == 0 ) {code = 0; break;} + + // current last wal is closed, there is a new one + sDebug("%s, last wal is closed, try new one", pPeer->id); + } + + tclose(pPeer->notifyFd); + + return code; +} + +static int syncRetrieveWal(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + char fname[TSDB_FILENAME_LEN * 3]; + char wname[TSDB_FILENAME_LEN * 2]; + int32_t size; + struct stat fstat; + int code = -1; + uint32_t index = 0; + + while (1) { + // retrieve wal info + wname[0] = 0; + code = (*pNode->getWalInfo)(pNode->ahandle, wname, &index); + if (code < 0) break; // error + if (wname[0] == 0) { // no wal file + sDebug("%s, no wal file", pPeer->id); + break; + } + + if (code == 0) { // last wal + code = syncProcessLastWal(pPeer, wname, index); + break; + } + + // get the full path to wal file + snprintf(fname, sizeof(fname), "%s/%s", pNode->path, wname); + + // send wal file, + // inotify is not required, old wal file won't be modified, even remove is ok + if ( stat(fname, &fstat) < 0 ) break; + size = fstat.st_size; + + sDebug("%s, retrieve wal:%s size:%d", pPeer->id, fname, size); + int sfd = open(fname, O_RDONLY); + if (sfd < 0) break; + + code = tsendfile(pPeer->syncFd, sfd, NULL, size); + close(sfd); + if (code <0) break; + + index++; + + if (syncAreFilesModified(pPeer) != 0) break; + } + + if (code == 0) { + sDebug("%s, wal retrieve is finished", pPeer->id); + pPeer->sstatus = TAOS_SYNC_STATUS_CACHE; + SWalHead walHead; + memset(&walHead, 0, sizeof(walHead)); + code = taosWriteMsg(pPeer->syncFd, &walHead, sizeof(walHead)); + } else { + sError("%s, failed to send wal(%s)", pPeer->id, strerror(errno)); + } + + return code; +} + +static int syncRetrieveDataStepByStep(SSyncPeer *pPeer) +{ + SSyncNode *pNode = pPeer->pSyncNode; + + SFirstPkt firstPkt; + memset(&firstPkt, 0, sizeof(firstPkt)); + firstPkt.syncHead.type = TAOS_SMSG_SYNC_DATA; + firstPkt.syncHead.vgId = pNode->vgId; + tstrncpy(firstPkt.fqdn, tsNodeFqdn, sizeof(firstPkt.fqdn)); + firstPkt.port = tsSyncPort; + + if (write(pPeer->syncFd, (char *) &firstPkt, sizeof(firstPkt)) < 0) { + sError("%s, failed to send syncCmd", pPeer->id); + return -1; + } + + pPeer->sversion = 0; + pPeer->sstatus = TAOS_SYNC_STATUS_FILE; + sDebug("%s, start to retrieve file", pPeer->id); + if (syncRetrieveFile(pPeer) < 0) { + sError("%s, failed to retrieve file", pPeer->id); + return -1; + } + + // if no files are synced, there must be wal to sync, sversion must be larger than one + if (pPeer->sversion == 0) + pPeer->sversion = 1; + + sDebug("%s, start to retrieve wal", pPeer->id); + if (syncRetrieveWal(pPeer) < 0) { + sError("%s, failed to retrieve wal", pPeer->id); + return -1; + } + + return 0; +} + +void *syncRetrieveData(void *param) +{ + SSyncPeer *pPeer = (SSyncPeer *)param; + taosBlockSIGPIPE(); + + pPeer->syncFd = taosOpenTcpClientSocket(pPeer->ip, pPeer->port, 0); + if (pPeer->syncFd < 0) { + sError("%s, failed to open socket to sync", pPeer->id); + } else { + sInfo("%s, sync tcp is setup", pPeer->id); + + if (syncRetrieveDataStepByStep(pPeer) == 0) { + sDebug("%s, sync retrieve process is successful", pPeer->id); + } else { + sError("%s, failed to retrieve data, restart connection", pPeer->id); + syncRestartConnection(pPeer); + } + } + + tclose(pPeer->notifyFd); + tclose(pPeer->syncFd); + syncDecPeerRef(pPeer); + + return NULL; +} diff --git a/src/sync/src/taosTcpPool.c b/src/sync/src/taosTcpPool.c new file mode 100644 index 0000000000..fa94caeed7 --- /dev/null +++ b/src/sync/src/taosTcpPool.c @@ -0,0 +1,325 @@ +/* + * 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 . + */ + +#include "os.h" +#include "tulog.h" +#include "tutil.h" +#include "tsocket.h" +#include "taoserror.h" +#include "taosTcpPool.h" + +typedef struct SThreadObj { + pthread_t thread; + bool stop; + int pollFd; + int numOfFds; + struct SPoolObj *pPool; +} SThreadObj; + +typedef struct SPoolObj { + SPoolInfo info; + SThreadObj **pThread; + pthread_t thread; + int nextId; + int acceptFd; // FD for accept new connection +} SPoolObj; + +typedef struct { + SThreadObj *pThread; + void *ahandle; + int fd; + int closedByApp; +} SConnObj; + +static void *taosAcceptPeerTcpConnection(void *argv); +static void *taosProcessTcpData(void *param); +static SThreadObj *taosGetTcpThread(SPoolObj *pPool); +static void taosStopPoolThread(SThreadObj* pThread); + +void *taosOpenTcpThreadPool(SPoolInfo *pInfo) +{ + pthread_attr_t thattr; + + SPoolObj *pPool = calloc(sizeof(SPoolObj), 1); + if (pPool == NULL) { + uError("TCP server, no enough memory"); + return NULL; + } + + pPool->info = *pInfo; + + pPool->pThread = (SThreadObj **) calloc(sizeof(SThreadObj *), pInfo->numOfThreads); + if (pPool->pThread == NULL) { + uError("TCP server, no enough memory"); + free(pPool); + return NULL; + } + + pPool->acceptFd = taosOpenTcpServerSocket(pInfo->serverIp, pInfo->port); + if (pPool->acceptFd < 0) { + free(pPool->pThread); free(pPool); + uError("failed to create TCP server socket, port:%d (%s)", pInfo->port, strerror(errno)); + return NULL; + } + + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + if (pthread_create(&(pPool->thread), &thattr, (void *) taosAcceptPeerTcpConnection, pPool) != 0) { + uError("TCP server, failed to create accept thread, reason:%s", strerror(errno)); + close(pPool->acceptFd); + free(pPool->pThread); free(pPool); + return NULL; + } + + pthread_attr_destroy(&thattr); + + uDebug("%p TCP pool is created", pPool); + return pPool; +} + +void taosCloseTcpThreadPool(void *param) +{ + SPoolObj *pPool = (SPoolObj *)param; + SThreadObj *pThread; + + shutdown(pPool->acceptFd, SHUT_RD); + pthread_join(pPool->thread, NULL); + + for (int i = 0; i < pPool->info.numOfThreads; ++i) { + pThread = pPool->pThread[i]; + if (pThread) taosStopPoolThread(pThread); + } + + tfree(pPool->pThread); + free(pPool); + uDebug("%p TCP pool is closed", pPool); +} + +void *taosAllocateTcpConn(void *param, void *pPeer, int connFd) +{ + struct epoll_event event; + SPoolObj *pPool = (SPoolObj *)param; + + SConnObj *pConn = (SConnObj *) calloc(sizeof(SConnObj), 1); + if (pConn == NULL) { + terrno = TAOS_SYSTEM_ERROR(errno); + return NULL; + } + + SThreadObj *pThread = taosGetTcpThread(pPool); + if (pThread == NULL) { + free(pConn); + return NULL; + } + + pConn->fd = connFd; + pConn->pThread = pThread; + pConn->ahandle = pPeer; + pConn->closedByApp = 0; + + event.events = EPOLLIN | EPOLLRDHUP; + event.data.ptr = pConn; + + if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, connFd, &event) < 0) { + uError("failed to add fd:%d(%s)", connFd, strerror(errno)); + terrno = TAOS_SYSTEM_ERROR(errno); + free(pConn); + pConn = NULL; + } else { + pThread->numOfFds++; + uDebug("%p fd:%d is added to epoll thread, num:%d", pThread, connFd, pThread->numOfFds); + } + + return pConn; +} + +void taosFreeTcpConn(void *param) +{ + SConnObj *pConn = (SConnObj *)param; + SThreadObj *pThread = pConn->pThread; + + uDebug("%p TCP connection will be closed, fd:%d", pThread, pConn->fd); + pConn->closedByApp = 1; + shutdown(pConn->fd, SHUT_WR); +} + +static void taosProcessBrokenLink(SConnObj *pConn) { + SThreadObj *pThread = pConn->pThread; + SPoolObj *pPool = pThread->pPool; + SPoolInfo *pInfo = &pPool->info; + + if (pConn->closedByApp == 0) shutdown(pConn->fd, SHUT_WR); + (*pInfo->processBrokenLink)(pConn->ahandle); + + pThread->numOfFds--; + epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pConn->fd, NULL); + uDebug("%p fd:%d is removed from epoll thread, num:%d", pThread, pConn->fd, pThread->numOfFds); + tclose(pConn->fd); + free(pConn); +} + +#define maxEvents 10 + +static void *taosProcessTcpData(void *param) { + SThreadObj *pThread = (SThreadObj *) param; + SPoolObj *pPool = pThread->pPool; + SPoolInfo *pInfo = &pPool->info; + SConnObj *pConn = NULL; + struct epoll_event events[maxEvents]; + + void *buffer = malloc(pInfo->bufferSize); + taosBlockSIGPIPE(); + + while (1) { + if (pThread->stop) break; + int fdNum = epoll_wait(pThread->pollFd, events, maxEvents, -1); + if (pThread->stop) { + uDebug("%p TCP epoll thread is exiting...", pThread); + break; + } + + if (fdNum < 0) { + uError("epoll_wait failed (%s)", strerror(errno)); + continue; + } + + for (int i = 0; i < fdNum; ++i) { + pConn = events[i].data.ptr; + assert(pConn); + + if (events[i].events & EPOLLERR) { + taosProcessBrokenLink(pConn); + continue; + } + + if (events[i].events & EPOLLHUP) { + taosProcessBrokenLink(pConn); + continue; + } + + if (events[i].events & EPOLLRDHUP) { + taosProcessBrokenLink(pConn); + continue; + } + + if (pConn->closedByApp == 0) { + if ((*pInfo->processIncomingMsg)(pConn->ahandle, buffer) < 0) { + taosFreeTcpConn(pConn); + continue; + } + } + } + } + + close(pThread->pollFd); + free(pThread); + free(buffer); + uDebug("%p TCP epoll thread exits", pThread); + return NULL; +} + +static void *taosAcceptPeerTcpConnection(void *argv) { + SPoolObj *pPool = (SPoolObj *)argv; + SPoolInfo *pInfo = &pPool->info; + + taosBlockSIGPIPE(); + + while (1) { + struct sockaddr_in clientAddr; + socklen_t addrlen = sizeof(clientAddr); + int connFd = accept(pPool->acceptFd, (struct sockaddr *) &clientAddr, &addrlen); + if (connFd < 0) { + if (errno == EINVAL) { + uDebug("%p TCP server accept is exiting...", pPool); + break; + } else { + uError("TCP accept failure, reason:%s", strerror(errno)); + continue; + } + } + + //uDebug("TCP connection from: 0x%x:%d", clientAddr.sin_addr.s_addr, clientAddr.sin_port); + taosKeepTcpAlive(connFd); + (*pInfo->processIncomingConn)(connFd, clientAddr.sin_addr.s_addr); + } + + tclose(pPool->acceptFd); + return NULL; +} + +static SThreadObj *taosGetTcpThread(SPoolObj *pPool) { + SThreadObj *pThread = pPool->pThread[pPool->nextId]; + + if (pThread) return pThread; + + pThread = (SThreadObj *) calloc(1, sizeof(SThreadObj)); + if (pThread == NULL) return NULL; + + pThread->pPool = pPool; + pThread->pollFd = epoll_create(10); // size does not matter + if (pThread->pollFd < 0) { + free(pThread); + return NULL; + } + + pthread_attr_t thattr; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + int ret = pthread_create(&(pThread->thread), &thattr, (void *) taosProcessTcpData, pThread); + pthread_attr_destroy(&thattr); + + if (ret != 0) { + close(pThread->pollFd); + free(pThread); + return NULL; + } + + uDebug("%p TCP epoll thread is created", pThread); + pPool->pThread[pPool->nextId] = pThread; + pPool->nextId++; + pPool->nextId = pPool->nextId % pPool->info.numOfThreads; + + return pThread; +} + +static void taosStopPoolThread(SThreadObj* pThread) { + pThread->stop = true; + + if (pThread->thread == pthread_self()) { + pthread_detach(pthread_self()); + return; + } + + // save thread ID into a local variable, since pThread is freed when the thread exits + pthread_t thread = pThread->thread; + + // signal the thread to stop, try graceful method first, + // and use pthread_cancel when failed + struct epoll_event event = { .events = EPOLLIN }; + eventfd_t fd = eventfd(1, 0); + if (fd == -1) { + // failed to create eventfd, call pthread_cancel instead, which may result in data corruption + uError("failed to create eventfd(%s)", strerror(errno)); + pthread_cancel(pThread->thread); + } else if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) { + // failed to call epoll_ctl, call pthread_cancel instead, which may result in data corruption + uError("failed to call epoll_ctl(%s)", strerror(errno)); + pthread_cancel(pThread->thread); + } + + pthread_join(thread, NULL); + tclose(fd); +} + diff --git a/src/sync/src/tarbitrator.c b/src/sync/src/tarbitrator.c new file mode 100644 index 0000000000..c308c2a454 --- /dev/null +++ b/src/sync/src/tarbitrator.c @@ -0,0 +1,191 @@ +/* + * 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 "hash.h" +#include "tlog.h" +#include "tutil.h" +#include "ttimer.h" +#include "ttime.h" +#include "tsocket.h" +#include "tglobal.h" +#include "taoserror.h" +#include "taosTcpPool.h" +#include "twal.h" +#include "tsync.h" +#include "syncInt.h" + +static void arbSignalHandler(int32_t signum, siginfo_t *sigInfo, void *context); +static void arbProcessIncommingConnection(int connFd, uint32_t sourceIp); +static void arbProcessBrokenLink(void *param); +static int arbProcessPeerMsg(void *param, void *buffer); +static sem_t tsArbSem; +static ttpool_h tsArbTcpPool; + +typedef struct { + char id[TSDB_EP_LEN+24]; + int nodeFd; + void *pConn; +} SNodeConn; + +int main(int argc, char *argv[]) { + char arbLogPath[TSDB_FILENAME_LEN + 16] = {0}; + + for (int i=1; i TSDB_FILENAME_LEN) continue; + tstrncpy(arbLogPath, argv[i], sizeof(arbLogPath)); + } else { + printf("\nusage: %s [options] \n", argv[0]); + printf(" [-p port]: server port number, default is:%d\n", tsServerPort); + printf(" [-d debugFlag]: debug flag, default:%d\n", debugFlag); + printf(" [-g logFilePath]: log file pathe, default:%s\n", arbLogPath); + printf(" [-h help]: print out this help\n\n"); + exit(0); + } + } + + if (sem_init(&tsArbSem, 0, 0) != 0) { + printf("failed to create exit semphore\n"); + exit(EXIT_FAILURE); + } + + /* Set termination handler. */ + struct sigaction act = {{0}}; + act.sa_flags = SA_SIGINFO; + act.sa_sigaction = arbSignalHandler; + sigaction(SIGTERM, &act, NULL); + sigaction(SIGHUP, &act, NULL); + sigaction(SIGINT, &act, NULL); + + tsAsyncLog = 0; + strcat(arbLogPath, "/arbitrator.log"); + taosInitLog(arbLogPath, 1000000, 10); + + taosGetFqdn(tsNodeFqdn); + tsSyncPort = tsServerPort + TSDB_PORT_SYNC; + + SPoolInfo info; + info.numOfThreads = 1; + info.serverIp = 0; + info.port = tsSyncPort; + info.bufferSize = 640000; + info.processBrokenLink = arbProcessBrokenLink; + info.processIncomingMsg = arbProcessPeerMsg; + info.processIncomingConn = arbProcessIncommingConnection; + tsArbTcpPool = taosOpenTcpThreadPool(&info); + + if (tsArbTcpPool == NULL) { + sDebug("failed to open TCP thread pool, exit..."); + return -1; + } + + sInfo("TAOS arbitrator: %s:%d is running", tsNodeFqdn, tsServerPort); + + for (int res = sem_wait(&tsArbSem); res != 0; res = sem_wait(&tsArbSem)) { + if (res != EINTR) break; + } + + taosCloseTcpThreadPool(tsArbTcpPool); + sInfo("TAOS arbitrator is shut down\n"); + closelog(); + + return 0; +} + +static void arbProcessIncommingConnection(int connFd, uint32_t sourceIp) +{ + char ipstr[24]; + tinet_ntoa(ipstr, sourceIp); + sDebug("peer TCP connection from ip:%s", ipstr); + + SFirstPkt firstPkt; + if (taosReadMsg(connFd, &firstPkt, sizeof(firstPkt)) != sizeof(firstPkt)) { + sError("failed to read peer first pkt from ip:%s(%s)", ipstr, strerror(errno)); + taosCloseSocket(connFd); + return; + } + + SNodeConn *pNode = (SNodeConn *) calloc(sizeof(SNodeConn), 1); + if (pNode == NULL) { + sError("failed to allocate memory(%s)", strerror(errno)); + taosCloseSocket(connFd); + return; + } + + snprintf(pNode->id, sizeof(pNode->id), "vgId:%d peer:%s:%d", firstPkt.sourceId, firstPkt.fqdn, firstPkt.port); + if (firstPkt.syncHead.vgId) { + sDebug("%s, vgId in head is not zero, close the connection", pNode->id); + tfree(pNode); + taosCloseSocket(connFd); + return; + } + + sDebug("%s, arbitrator request is accepted", pNode->id); + pNode->nodeFd = connFd; + pNode->pConn = taosAllocateTcpConn(tsArbTcpPool, pNode, connFd); + + return; +} + +static void arbProcessBrokenLink(void *param) { + SNodeConn *pNode = param; + + sDebug("%s, TCP link is broken(%s), close connection", pNode->id, strerror(errno)); + tfree(pNode); +} + +static int arbProcessPeerMsg(void *param, void *buffer) +{ + SNodeConn *pNode = param; + SSyncHead head; + int bytes = 0; + char *cont = (char *)buffer; + + int hlen = taosReadMsg(pNode->nodeFd, &head, sizeof(head)); + if (hlen != sizeof(head)) { + sDebug("%s, failed to read msg, hlen:%d", pNode->id, hlen); + return -1; + } + + bytes = taosReadMsg(pNode->nodeFd, cont, head.len); + if (bytes != head.len) { + sDebug("%s, failed to read, bytes:%d len:%d", pNode->id, bytes, head.len); + return -1; + } + + sDebug("%s, msg is received, len:%d", pNode->id, head.len); + return 0; +} + +static void arbSignalHandler(int32_t signum, siginfo_t *sigInfo, void *context) { + + struct sigaction act = {{0}}; + act.sa_handler = SIG_IGN; + sigaction(SIGTERM, &act, NULL); + sigaction(SIGHUP, &act, NULL); + sigaction(SIGINT, &act, NULL); + + sInfo("shut down signal is %d, sender PID:%d", signum, sigInfo->si_pid); + + // inform main thread to exit + sem_post(&tsArbSem); +} + diff --git a/src/sync/test/CMakeLists.txt b/src/sync/test/CMakeLists.txt new file mode 100644 index 0000000000..fd8bdd1668 --- /dev/null +++ b/src/sync/test/CMakeLists.txt @@ -0,0 +1,20 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) + INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) + INCLUDE_DIRECTORIES(../inc) + + LIST(APPEND CLIENT_SRC ./syncClient.c) + ADD_EXECUTABLE(syncClient ${CLIENT_SRC}) + TARGET_LINK_LIBRARIES(syncClient sync trpc common) + + LIST(APPEND SERVER_SRC ./syncServer.c) + ADD_EXECUTABLE(syncServer ${SERVER_SRC}) + TARGET_LINK_LIBRARIES(syncServer sync trpc common) +ENDIF () + + diff --git a/src/sync/test/syncClient.c b/src/sync/test/syncClient.c new file mode 100644 index 0000000000..cd873b758b --- /dev/null +++ b/src/sync/test/syncClient.c @@ -0,0 +1,194 @@ +/* + * 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 . + */ + +#include "os.h" +#include "tglobal.h" +#include "tulog.h" +#include "trpc.h" +#include "taoserror.h" + +typedef struct { + int index; + SRpcEpSet epSet; + int num; + int numOfReqs; + int msgSize; + sem_t rspSem; + sem_t *pOverSem; + pthread_t thread; + void *pRpc; +} SInfo; + +void processResponse(SRpcMsg *pMsg, SRpcEpSet *pEpSet) { + SInfo *pInfo = (SInfo *)pMsg->ahandle; + uDebug("thread:%d, response is received, type:%d contLen:%d code:0x%x", pInfo->index, pMsg->msgType, pMsg->contLen, pMsg->code); + + if (pEpSet) pInfo->epSet = *pEpSet; + rpcFreeCont(pMsg->pCont); + + sem_post(&pInfo->rspSem); +} + +int tcount = 0; + +void *sendRequest(void *param) { + SInfo *pInfo = (SInfo *)param; + SRpcMsg rpcMsg = {0}; + + uDebug("thread:%d, start to send request", pInfo->index); + + while ( pInfo->numOfReqs == 0 || pInfo->num < pInfo->numOfReqs) { + pInfo->num++; + rpcMsg.pCont = rpcMallocCont(pInfo->msgSize); + rpcMsg.contLen = pInfo->msgSize; + rpcMsg.ahandle = pInfo; + rpcMsg.msgType = 1; + uDebug("thread:%d, send request, contLen:%d num:%d", pInfo->index, pInfo->msgSize, pInfo->num); + rpcSendRequest(pInfo->pRpc, &pInfo->epSet, &rpcMsg); + if ( pInfo->num % 20000 == 0 ) + uInfo("thread:%d, %d requests have been sent", pInfo->index, pInfo->num); + sem_wait(&pInfo->rspSem); + } + + uDebug("thread:%d, it is over", pInfo->index); + tcount++; + + return NULL; +} + +int main(int argc, char *argv[]) { + SRpcInit rpcInit; + SRpcEpSet epSet; + char secret[TSDB_KEY_LEN] = "mypassword"; + int msgSize = 128; + int numOfReqs = 0; + int appThreads = 1; + char serverIp[40] = "127.0.0.1"; + struct timeval systemTime; + int64_t startTime, endTime; + pthread_attr_t thattr; + + // server info + epSet.numOfEps = 1; + epSet.inUse = 0; + epSet.port[0] = 7000; + epSet.port[1] = 7000; + strcpy(epSet.fqdn[0], serverIp); + strcpy(epSet.fqdn[1], "192.168.0.1"); + + // client info + memset(&rpcInit, 0, sizeof(rpcInit)); + rpcInit.localPort = 0; + rpcInit.label = "APP"; + rpcInit.numOfThreads = 1; + rpcInit.cfp = processResponse; + rpcInit.sessions = 100; + rpcInit.idleTime = tsShellActivityTimer*1000; + rpcInit.user = "michael"; + rpcInit.secret = secret; + rpcInit.ckey = "key"; + rpcInit.spi = 1; + rpcInit.connType = TAOS_CONN_CLIENT; + + for (int i=1; iindex = i; + pInfo->epSet = epSet; + pInfo->numOfReqs = numOfReqs; + pInfo->msgSize = msgSize; + sem_init(&pInfo->rspSem, 0, 0); + pInfo->pRpc = pRpc; + pthread_create(&pInfo->thread, &thattr, sendRequest, pInfo); + pInfo++; + } + + do { + usleep(1); + } while ( tcount < appThreads); + + gettimeofday(&systemTime, NULL); + endTime = systemTime.tv_sec*1000000 + systemTime.tv_usec; + float usedTime = (endTime - startTime)/1000.0; // mseconds + + uInfo("it takes %.3f mseconds to send %d requests to server", usedTime, numOfReqs*appThreads); + uInfo("Performance: %.3f requests per second, msgSize:%d bytes", 1000.0*numOfReqs*appThreads/usedTime, msgSize); + + taosCloseLog(); + + return 0; +} + + diff --git a/src/sync/test/syncServer.c b/src/sync/test/syncServer.c new file mode 100644 index 0000000000..44019ad96e --- /dev/null +++ b/src/sync/test/syncServer.c @@ -0,0 +1,487 @@ +/* + * 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 +#include "os.h" +#include "tulog.h" +#include "tglobal.h" +#include "tsocket.h" +#include "trpc.h" +#include "tqueue.h" +#include "twal.h" +#include "tsync.h" + +int msgSize = 128; +int commit = 0; +int dataFd = -1; +void *qhandle = NULL; +int walNum = 0; +uint64_t tversion = 0; +void *syncHandle; +int role; +int nodeId; +char path[256]; +int numOfWrites ; +SSyncInfo syncInfo; +SSyncCfg *pCfg; + +int writeIntoWal(SWalHead *pHead) +{ + if (dataFd < 0) { + char walName[280]; + snprintf(walName, sizeof(walName), "%s/wal/wal.%d", path, walNum); + remove(walName); + dataFd = open(walName, O_CREAT | O_WRONLY, S_IRWXU | S_IRWXG | S_IRWXO); + if (dataFd < 0) { + uInfo("failed to open wal file:%s(%s)", walName, strerror(errno)); + return -1; + } else { + walNum++; + uInfo("file:%s is opened to write, walNum:%d", walName, walNum); + } + } + + if (write(dataFd, pHead, sizeof(SWalHead) + pHead->len) < 0) { + uError("ver:%" PRIu64 ", failed to write wal file(%s)", pHead->version, strerror(errno)); + } else { + uDebug("ver:%" PRIu64 ", written to wal", pHead->version); + } + + numOfWrites++; + if (numOfWrites >= 10000) { + uInfo("%d request have been written into disk", numOfWrites); + close(dataFd); + dataFd = -1; + numOfWrites = 0; + } + + return 0; +} + +void confirmForward(void *ahandle, void *mhandle, int32_t code) +{ + SRpcMsg *pMsg = (SRpcMsg *)mhandle; + SWalHead *pHead = (SWalHead *)(((char *)pMsg->pCont) - sizeof(SWalHead)); + + uDebug("ver:%" PRIu64 ", confirm is received", pHead->version); + + rpcFreeCont(pMsg->pCont); + + SRpcMsg rpcMsg; + rpcMsg.pCont = rpcMallocCont(msgSize); + rpcMsg.contLen = msgSize; + rpcMsg.handle = pMsg->handle; + rpcMsg.code = code; + rpcSendResponse(&rpcMsg); + + taosFreeQitem(mhandle); +} + +int processRpcMsg(void *item) { + SRpcMsg *pMsg = (SRpcMsg *)item; + SWalHead *pHead = (SWalHead *)(((char *)pMsg->pCont) - sizeof(SWalHead)); + int code = -1; + + if (role != TAOS_SYNC_ROLE_MASTER) { + uError("not master, write failed, role:%s", syncRole[role]); + } else { + + pHead->version = ++tversion; + pHead->msgType = pMsg->msgType; + pHead->len = pMsg->contLen; + + uDebug("ver:%" PRIu64 ", pkt from client processed", pHead->version); + writeIntoWal(pHead); + syncForwardToPeer(syncHandle, pHead, item, TAOS_QTYPE_RPC); + + code = 0; + } + + if (pCfg->quorum <= 1) { + taosFreeQitem(item); + rpcFreeCont(pMsg->pCont); + + SRpcMsg rpcMsg; + rpcMsg.pCont = rpcMallocCont(msgSize); + rpcMsg.contLen = msgSize; + rpcMsg.handle = pMsg->handle; + rpcMsg.code = code; + rpcSendResponse(&rpcMsg); + } + + return code; +} + +int processFwdMsg(void *item) { + + SWalHead *pHead = (SWalHead *)item; + + if (pHead->version <= tversion) { + uError("ver:%" PRIu64 ", forward is even lower than local:%" PRIu64, pHead->version, tversion); + return -1; + } + + uDebug("ver:%" PRIu64 ", forward from peer is received", pHead->version); + writeIntoWal(pHead); + tversion = pHead->version; + + if (pCfg->quorum > 1) syncConfirmForward(syncHandle, pHead->version, 0); + + // write into cache + +/* + if (pHead->handle) { + syncSendFwdAck(syncHandle, pHead->handle, 0); + } +*/ + + taosFreeQitem(item); + + return 0; +} + +int processWalMsg(void *item) { + + SWalHead *pHead = (SWalHead *)item; + + if (pHead->version <= tversion) { + uError("ver:%" PRIu64 ", wal is even lower than local:%" PRIu64, pHead->version, tversion); + return -1; + }; + + uDebug("ver:%" PRIu64 ", wal from peer is received", pHead->version); + writeIntoWal(pHead); + tversion = pHead->version; + + // write into cache + +/* + if (pHead->handle) { + syncSendFwdAck(syncHandle, pHead->handle, 0); + } +*/ + + taosFreeQitem(item); + + return 0; +} + +void *processWriteQueue(void *param) { + int type; + void *item; + + while (1) { + int ret = taosReadQitem(qhandle, &type, &item); + if (ret <= 0) { + usleep(1000); + continue; + } + + if (type == TAOS_QTYPE_RPC) { + processRpcMsg(item); + } else if (type == TAOS_QTYPE_WAL) { + processWalMsg(item); + } else if (type == TAOS_QTYPE_FWD) { + processFwdMsg(item); + } + + } + + return NULL; +} + +int retrieveAuthInfo(char *meterId, char *spi, char *encrypt, char *secret, char *ckey) { + // app shall retrieve the auth info based on meterID from DB or a data file + // demo code here only for simple demo + int ret = 0; + + if (strcmp(meterId, "michael") == 0) { + *spi = 1; + *encrypt = 0; + strcpy(secret, "mypassword"); + strcpy(ckey, "key"); + } else if (strcmp(meterId, "jeff") == 0) { + *spi = 0; + *encrypt = 0; + } else { + ret = -1; // user not there + } + + return ret; +} + +void processRequestMsg(SRpcMsg *pMsg, SRpcEpSet *pEpSet) { + + SRpcMsg *pTemp; + + pTemp = taosAllocateQitem(sizeof(SRpcMsg)); + memcpy(pTemp, pMsg, sizeof(SRpcMsg)); + + uDebug("request is received, type:%d, len:%d", pMsg->msgType, pMsg->contLen); + taosWriteQitem(qhandle, TAOS_QTYPE_RPC, pTemp); +} + +uint32_t getFileInfo(void *ahandle, char *name, uint32_t *index, uint32_t eindex, int32_t *size, uint64_t *fversion) +{ + uint32_t magic; + struct stat fstat; + char aname[280]; + + if (*index == 2) { + uInfo("wait for a while ....."); + sleep(3); + } + + if (name[0] == 0) { + // find the file + snprintf(aname, sizeof(aname), "%s/data/data.%d", path, *index); + sprintf(name, "data/data.%d", *index); + } else { + snprintf(aname, sizeof(aname), "%s/%s", path, name); + } + + uInfo("get file info:%s", aname); + if ( stat(aname, &fstat) < 0 ) return 0; + + *size = fstat.st_size; + magic = fstat.st_size; + + return magic; +} + +int getWalInfo(void *ahandle, char *name, uint32_t *index) { + + struct stat fstat; + char aname[280]; + + name[0] = 0; + if (*index + 1> walNum) return 0; + + snprintf(aname, sizeof(aname), "%s/wal/wal.%d", path, *index); + sprintf(name, "wal/wal.%d", *index); + uInfo("get wal info:%s", aname); + + if ( stat(aname, &fstat) < 0 ) return -1; + + if (*index >= walNum-1) return 0; // no more + + return 1; + +} + +int writeToCache(void *ahandle, void *data, int type) { + SWalHead *pHead = data; + + uDebug("pkt from peer is received, ver:%" PRIu64 " len:%d type:%d", pHead->version, pHead->len, type); + + int msgSize = pHead->len + sizeof(SWalHead); + void *pMsg = taosAllocateQitem(msgSize); + memcpy(pMsg, pHead, msgSize); + taosWriteQitem(qhandle, type, pMsg); + + return 0; +} + +void confirmFwd(void *ahandle, int64_t version) { + + return; +} + +void notifyRole(void *ahandle, int8_t r) { + role = r; + printf("current role:%s\n", syncRole[role]); +} + + +void initSync() { + + pCfg->replica = 1; + pCfg->quorum = 1; + syncInfo.vgId = 1; + syncInfo.ahandle = &syncInfo; + syncInfo.getFileInfo = getFileInfo; + syncInfo.getWalInfo = getWalInfo; + syncInfo.writeToCache = writeToCache; + syncInfo.confirmForward = confirmForward; + syncInfo.notifyRole = notifyRole; + + pCfg->nodeInfo[0].nodeId = 1; + pCfg->nodeInfo[0].nodePort = 7010; + taosGetFqdn(pCfg->nodeInfo[0].nodeFqdn); + + pCfg->nodeInfo[1].nodeId = 2; + pCfg->nodeInfo[1].nodePort = 7110; + taosGetFqdn(pCfg->nodeInfo[1].nodeFqdn); + + pCfg->nodeInfo[2].nodeId = 3; + pCfg->nodeInfo[2].nodePort = 7210; + taosGetFqdn(pCfg->nodeInfo[2].nodeFqdn); + + pCfg->nodeInfo[3].nodeId = 4; + pCfg->nodeInfo[3].nodePort = 7310; + taosGetFqdn(pCfg->nodeInfo[3].nodeFqdn); + + pCfg->nodeInfo[4].nodeId = 5; + pCfg->nodeInfo[4].nodePort = 7410; + taosGetFqdn(pCfg->nodeInfo[4].nodeFqdn); +} + +void doSync() +{ + for (int i=0; i<5; ++i) { + if (tsSyncPort == pCfg->nodeInfo[i].nodePort) + nodeId = pCfg->nodeInfo[i].nodeId; + } + + snprintf(path, sizeof(path), "/root/test/d%d", nodeId); + strcpy(syncInfo.path, path); + + if ( syncHandle == NULL) { + syncHandle = syncStart(&syncInfo); + } else { + if (syncReconfig(syncHandle, pCfg) < 0) syncHandle = NULL; + } + + uInfo("nodeId:%d path:%s syncPort:%d", nodeId, path, tsSyncPort); +} + +int main(int argc, char *argv[]) { + SRpcInit rpcInit; + char dataName[20] = "server.data"; + pCfg = &syncInfo.syncCfg; + + initSync(); + + memset(&rpcInit, 0, sizeof(rpcInit)); + rpcInit.localPort = 7000; + rpcInit.label = "SER"; + rpcInit.numOfThreads = 1; + rpcInit.cfp = processRequestMsg; + rpcInit.sessions = 1000; + rpcInit.idleTime = tsShellActivityTimer*1500; + rpcInit.afp = retrieveAuthInfo; + + for (int i=1; ireplica = atoi(argv[++i]); + } else if (strcmp(argv[i], "-q")==0 && i < argc-1) { + pCfg->quorum = atoi(argv[++i]); + } else if (strcmp(argv[i], "-d")==0 && i < argc-1) { + rpcDebugFlag = atoi(argv[++i]); + } else { + printf("\nusage: %s [options] \n", argv[0]); + printf(" [-p port]: server port number, default is:%d\n", rpcInit.localPort); + printf(" [-t threads]: number of rpc threads, default is:%d\n", rpcInit.numOfThreads); + printf(" [-s sessions]: number of sessions, default is:%d\n", rpcInit.sessions); + printf(" [-m msgSize]: message body size, default is:%d\n", msgSize); + printf(" [-o compSize]: compression message size, default is:%d\n", tsCompressMsgSize); + printf(" [-w write]: write received data to file(0, 1, 2), default is:%d\n", commit); + printf(" [-v version]: initial node version, default is:%ld\n", syncInfo.version); + printf(" [-r replica]: replicacation number, default is:%d\n", pCfg->replica); + printf(" [-q quorum]: quorum, default is:%d\n", pCfg->quorum); + printf(" [-d debugFlag]: debug flag, default:%d\n", rpcDebugFlag); + printf(" [-h help]: print out this help\n\n"); + exit(0); + } + } + + uDebugFlag = rpcDebugFlag; + dDebugFlag = rpcDebugFlag; + //tmrDebugFlag = rpcDebugFlag; + tsAsyncLog = 0; + taosInitLog("server.log", 1000000, 10); + + rpcInit.connType = TAOS_CONN_SERVER; + void *pRpc = rpcOpen(&rpcInit); + if (pRpc == NULL) { + uError("failed to start RPC server"); + return -1; + } + + tsSyncPort = rpcInit.localPort + 10; + qhandle = taosOpenQueue(); + + doSync(); + + pthread_attr_t thattr; + pthread_t thread; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + if (pthread_create(&thread, &thattr, processWriteQueue, NULL) != 0) { + uError("failed to create thread, reason:%s", strerror(errno)); + return -1; + } + + printf("server is running, localPort:%d\n", rpcInit.localPort); + SNodesRole nroles; + + while (1) { + char c = getchar(); + + switch(c) { + case '1': + pCfg->replica = 1; doSync(); + break; + case '2': + pCfg->replica = 2; doSync(); + break; + case '3': + pCfg->replica = 3; doSync(); + break; + case '4': + pCfg->replica = 4; doSync(); + break; + case '5': + pCfg->replica = 5; doSync(); + break; + case 's': + syncGetNodesRole(syncHandle, &nroles); + for (int i=0; ireplica; ++i) + printf("=== nodeId:%d role:%s\n", nroles.nodeId[i], syncRole[nroles.role[i]]); + break; + default: + break; + } + + if (c=='q') break; + + } + + syncStop(syncHandle); + + if (dataFd >= 0) { + close(dataFd); + remove(dataName); + } + + return 0; +} + + From fe05941584cc6c5973a3cb0c55c5f85bd148802c Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 10:51:21 +0800 Subject: [PATCH 37/47] [td-255] --- src/query/src/qExecutor.c | 5 +--- src/util/src/tcache.c | 3 +- src/vnode/src/vnodeRead.c | 58 ++++++++++++++++++--------------------- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index cc4fab343d..bca07e7150 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6372,16 +6372,14 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContex return pQInfo->code; } - *buildRes = false; int32_t code = TSDB_CODE_SUCCESS; - pthread_mutex_lock(&pQInfo->lock); if (pQInfo->dataReady == QUERY_RESULT_READY) { *buildRes = true; - qDebug("QInfo:%p retrieve result info, rowsize:%d, rows:%"PRId64", code:%d", pQInfo, pQuery->rowSize, pQuery->rec.rows, pQInfo->code); } else { + *buildRes = false; qDebug("QInfo:%p retrieve req set query return result after paused", pQInfo); pQInfo->rspContext = pRspContext; } @@ -6473,7 +6471,6 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co } else { // failed to dump result, free qhandle immediately *continueExec = false; qKillQuery(pQInfo); - qDestroyQueryInfo(pQInfo); } return code; diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 0d295a0cfa..a086a87b4b 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -419,7 +419,7 @@ void taosCacheRelease(SCacheObj *pCacheObj, void **data, bool _remove) { // note: extend lifespan before dec ref count bool inTrashCan = pNode->inTrashCan; - if (pCacheObj->extendLifespan && (!inTrashCan)) { + if (pCacheObj->extendLifespan && (!inTrashCan) && (!_remove)) { atomic_store_64(&pNode->expireTime, pNode->lifespan + taosGetTimestampMs()); uDebug("cache:%s data:%p extend life time to %"PRId64 " before release", pCacheObj->name, pNode->data, pNode->expireTime); } @@ -643,6 +643,7 @@ static void doCacheRefresh(SCacheObj* pCacheObj, int64_t time, __cache_free_fn_t __cache_wr_lock(pCacheObj); while (taosHashIterNext(pIter)) { SCacheDataNode *pNode = *(SCacheDataNode **)taosHashIterGet(pIter); + if (pNode->expireTime < time && T_REF_VAL_GET(pNode) <= 0) { taosCacheReleaseNode(pCacheObj, pNode); continue; diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 49c10dca3f..2a4ca0e663 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -66,12 +66,12 @@ int32_t vnodeProcessRead(void *param, SReadMsg *pReadMsg) { return (*vnodeProcessReadMsgFp[msgType])(pVnode, pReadMsg); } -static void vnodePutItemIntoReadQueue(SVnodeObj *pVnode, void *qhandle, void* handle) { +static void vnodePutItemIntoReadQueue(SVnodeObj *pVnode, void *qhandle) { SReadMsg *pRead = (SReadMsg *)taosAllocateQitem(sizeof(SReadMsg)); pRead->rpcMsg.msgType = TSDB_MSG_TYPE_QUERY; pRead->pCont = qhandle; pRead->contLen = 0; - pRead->rpcMsg.handle = handle; + pRead->rpcMsg.handle = NULL; atomic_add_fetch_32(&pVnode->refCount, 1); taosWriteQitem(pVnode->rqueue, TAOS_QTYPE_QUERY, pRead); @@ -99,6 +99,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { vWarn("QInfo:%p invalid qhandle, no matched query handle, conn:%p", (void*) killQueryMsg->qhandle, pReadMsg->rpcMsg.handle); } else { assert(*qhandle == (void*) killQueryMsg->qhandle); + qKillQuery(*qhandle); qReleaseQInfo(pVnode->qMgmt, (void**) &qhandle, true); } @@ -123,8 +124,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { // current connect is broken if (code == TSDB_CODE_SUCCESS) { -// handle = qRegisterQInfo(pVnode->qMgmt, (uint64_t) pQInfo); - handle = &pQInfo; + handle = qRegisterQInfo(pVnode->qMgmt, (uint64_t) pQInfo); if (handle == NULL) { // failed to register qhandle vError("vgId:%d QInfo:%p register qhandle failed, return to app, code:%s", pVnode->vgId, (void *)pQInfo, tstrerror(pRsp->code)); @@ -135,11 +135,10 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { pRsp->qhandle = htobe64((uint64_t) pQInfo); } -// pQInfo = NULL; if (handle != NULL && vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, *handle, pVnode->vgId) != TSDB_CODE_SUCCESS) { vError("vgId:%d, QInfo:%p, query discarded since link is broken, %p", pVnode->vgId, *handle, pReadMsg->rpcMsg.handle); pRsp->code = TSDB_CODE_RPC_NETWORK_UNAVAIL; -// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); return pRsp->code; } } else { @@ -149,15 +148,14 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (handle != NULL) { vDebug("vgId:%d, QInfo:%p, dnode query msg disposed, register qhandle and return to app", vgId, *handle); - vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); -// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); + vnodePutItemIntoReadQueue(pVnode, *handle); + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); } } else { assert(pCont != NULL); - void* p = (void*) pCont; - handle = &p; -// handle = qAcquireQInfo(pVnode->qMgmt, (uint64_t) pCont); + + handle = qAcquireQInfo(pVnode->qMgmt, (uint64_t) pCont); if (handle == NULL) { vWarn("QInfo:%p invalid qhandle in continuing exec query, conn:%p", (void*) pCont, pReadMsg->rpcMsg.handle); code = TSDB_CODE_QRY_INVALID_QHANDLE; @@ -166,23 +164,25 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { bool buildRes = qTableQuery(*handle); // do execute query if (buildRes) { // build result rsp + // update the connection info according to the retrieve connection + pReadMsg->rpcMsg.handle = qGetResultRetrieveMsg(*handle); + assert(pReadMsg->rpcMsg.handle != NULL); - void* retrieveHandle = qGetResultRetrieveMsg(*handle); - assert(retrieveHandle != NULL); - - vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, retrieveHandle); - pReadMsg->rpcMsg.handle = retrieveHandle; // update the connection info according to the retrieve connection + vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, pReadMsg->rpcMsg.handle); pRet = &pReadMsg->rspRet; - code = TSDB_CODE_QRY_HAS_RSP; +// code = TSDB_CODE_QRY_HAS_RSP; bool continueExec = false; if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { if (continueExec) { - vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); + vTrace("QInfo:%p add to queue for further exec", *handle); + vnodePutItemIntoReadQueue(pVnode, *handle); pRet->qhandle = *handle; - code = TSDB_CODE_SUCCESS; +// code = TSDB_CODE_SUCCESS; + } else { + vDebug("QInfo:%p query completed", *handle); } } else { // todo handle error } @@ -190,7 +190,8 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { code = TSDB_CODE_QRY_HAS_RSP; } } -// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); + + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); } return code; @@ -209,11 +210,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { memset(pRet, 0, sizeof(SRspRet)); int32_t code = TSDB_CODE_SUCCESS; - void** handle = NULL; - void* p1 = (void*) pRetrieve->qhandle; - handle = &p1; - -// void** handle = qAcquireQInfo(pVnode->qMgmt, pRetrieve->qhandle); + void** handle = qAcquireQInfo(pVnode->qMgmt, pRetrieve->qhandle); if (handle == NULL || (*handle) != (void*) pRetrieve->qhandle) { code = TSDB_CODE_QRY_INVALID_QHANDLE; vDebug("vgId:%d, invalid qhandle in fetch result, QInfo:%p", pVnode->vgId, (void*) pRetrieve->qhandle); @@ -233,7 +230,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (pRetrieve->free == 1) { vDebug("vgId:%d, QInfo:%p, retrieve msg received to kill query and free qhandle", pVnode->vgId, *handle); qKillQuery(*handle); -// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); pRet->len = sizeof(SRetrieveTableRsp); @@ -255,16 +252,16 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { //TODO handle malloc failure pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); - } else { - // result is not ready, return immediately + } else { // result is not ready, return immediately if (!buildRes) { + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); return TSDB_CODE_QRY_NOT_READY; } bool continueExec = false; if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { if (continueExec) { - vnodePutItemIntoReadQueue(pVnode, *handle, pReadMsg->rpcMsg.handle); + vnodePutItemIntoReadQueue(pVnode, *handle); pRet->qhandle = *handle; freeHandle = false; } @@ -274,8 +271,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { } } - UNUSED(freeHandle); -// qReleaseQInfo(pVnode->qMgmt, (void**) &handle, freeHandle); + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, freeHandle); return code; } From 276fb370994dc12f03e5cc073be85e94ecff921c Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Tue, 28 Jul 2020 02:59:54 +0000 Subject: [PATCH 38/47] [TD-992] refactor codes --- CMakeLists.txt | 1 - cmake/define.inc | 4 - cmake/env.inc | 1 - cmake/platform.inc | 19 +- src/balance/CMakeLists.txt | 16 + src/balance/src/balance.c | 1006 ++++++++++++++++++++++++++ src/client/CMakeLists.txt | 2 +- src/client/src/tscParseInsert.c | 2 +- src/client/src/tscSystem.c | 10 +- src/common/CMakeLists.txt | 17 +- src/common/inc/tglobal.h | 6 +- src/common/src/tglobal.c | 2 +- src/cq/CMakeLists.txt | 2 +- src/cq/test/CMakeLists.txt | 21 +- src/dnode/CMakeLists.txt | 8 +- src/dnode/src/dnodeSystem.c | 3 +- src/inc/taosdef.h | 2 +- src/kit/shell/CMakeLists.txt | 2 +- src/kit/taosdemo/CMakeLists.txt | 2 +- src/kit/taosdump/CMakeLists.txt | 2 +- src/kit/taosdump/taosdump.c | 8 +- src/kit/taosmigrate/CMakeLists.txt | 2 +- src/mnode/CMakeLists.txt | 2 +- src/mnode/src/mnodeDb.c | 7 - src/mnode/src/mnodeDnode.c | 8 - src/os/CMakeLists.txt | 16 +- src/os/inc/os.h | 53 ++ src/os/inc/osAlpine.h | 91 +++ src/os/inc/osDarwin64.h | 277 +++++++ src/os/inc/osLinux32.h | 85 +++ src/os/inc/osLinux64.h | 85 +++ src/os/inc/osSpec.h | 240 ++++++ src/os/inc/osWindows32.h | 54 ++ src/os/inc/osWindows64.h | 423 +++++++++++ src/os/src/alpine/CMakeLists.txt | 12 + src/os/src/alpine/alpineEnv.c | 30 + src/os/src/darwin64/CMakeLists.txt | 13 + src/os/src/darwin64/darwinEnv.c | 30 + src/os/src/darwin64/darwinPlatform.c | 370 ++++++++++ src/os/src/detail/CMakeLists.txt | 14 + src/os/src/detail/osCoredump.c | 98 +++ src/os/src/detail/osFail.c | 141 ++++ src/os/src/detail/osFile.c | 88 +++ src/os/src/detail/osPThread.c | 24 + src/os/src/detail/osSocket.c | 56 ++ src/os/src/detail/osSysinfo.c | 573 +++++++++++++++ src/os/src/detail/osTimer.c | 133 ++++ src/os/src/detail/osUtil.c | 26 + src/os/src/linux64/CMakeLists.txt | 12 + src/os/src/linux64/linuxEnv.c | 30 + src/os/src/windows64/CMakeLists.txt | 11 + src/os/src/windows64/twindows.c | 410 +++++++++++ src/os/src/windows64/twinenv.c | 30 + src/os/src/windows64/twingetline.c | 145 ++++ src/os/src/windows64/twinmsghdr.c | 57 ++ src/os/src/windows64/twinsocket.c | 117 +++ src/os/src/windows64/twinstrptime.c | 398 ++++++++++ src/os/src/windows64/twintcpclient.c | 39 + src/os/src/windows64/twintcpserver.c | 34 + src/os/src/windows64/twintime.c | 34 + src/os/src/windows64/twintimer.c | 54 ++ src/plugins/CMakeLists.txt | 2 + src/plugins/http/CMakeLists.txt | 2 +- src/plugins/http/src/httpJson.c | 2 +- src/plugins/monitor/CMakeLists.txt | 2 +- src/plugins/mqtt/CMakeLists.txt | 2 +- src/query/CMakeLists.txt | 4 +- src/query/src/qTsbuf.c | 2 +- src/rpc/CMakeLists.txt | 11 +- src/rpc/src/rpcUdp.c | 2 +- src/rpc/test/CMakeLists.txt | 12 +- src/tsdb/CMakeLists.txt | 2 +- src/tsdb/src/tsdbFile.c | 17 +- src/tsdb/src/tsdbMain.c | 4 +- src/tsdb/src/tsdbRWHelper.c | 20 +- src/util/CMakeLists.txt | 42 +- src/util/inc/talgo.h | 2 + src/util/inc/tutil.h | 5 +- src/util/src/tbuffer.c | 1 + src/util/src/tcache.c | 4 +- src/util/src/tkvstore.c | 29 +- src/util/src/tlog.c | 20 +- src/util/src/tnote.c | 2 +- src/util/src/tsocket.c | 2 +- src/vnode/CMakeLists.txt | 2 +- src/vnode/src/vnodeMain.c | 13 - src/wal/CMakeLists.txt | 4 +- src/wal/src/walMain.c | 16 +- src/wal/test/CMakeLists.txt | 2 +- 89 files changed, 5458 insertions(+), 228 deletions(-) create mode 100644 src/balance/CMakeLists.txt create mode 100644 src/balance/src/balance.c create mode 100644 src/os/inc/os.h create mode 100644 src/os/inc/osAlpine.h create mode 100644 src/os/inc/osDarwin64.h create mode 100644 src/os/inc/osLinux32.h create mode 100644 src/os/inc/osLinux64.h create mode 100644 src/os/inc/osSpec.h create mode 100644 src/os/inc/osWindows32.h create mode 100644 src/os/inc/osWindows64.h create mode 100644 src/os/src/alpine/CMakeLists.txt create mode 100644 src/os/src/alpine/alpineEnv.c create mode 100644 src/os/src/darwin64/CMakeLists.txt create mode 100644 src/os/src/darwin64/darwinEnv.c create mode 100644 src/os/src/darwin64/darwinPlatform.c create mode 100644 src/os/src/detail/CMakeLists.txt create mode 100644 src/os/src/detail/osCoredump.c create mode 100644 src/os/src/detail/osFail.c create mode 100644 src/os/src/detail/osFile.c create mode 100644 src/os/src/detail/osPThread.c create mode 100644 src/os/src/detail/osSocket.c create mode 100644 src/os/src/detail/osSysinfo.c create mode 100644 src/os/src/detail/osTimer.c create mode 100644 src/os/src/detail/osUtil.c create mode 100644 src/os/src/linux64/CMakeLists.txt create mode 100644 src/os/src/linux64/linuxEnv.c create mode 100644 src/os/src/windows64/CMakeLists.txt create mode 100644 src/os/src/windows64/twindows.c create mode 100644 src/os/src/windows64/twinenv.c create mode 100644 src/os/src/windows64/twingetline.c create mode 100644 src/os/src/windows64/twinmsghdr.c create mode 100644 src/os/src/windows64/twinsocket.c create mode 100644 src/os/src/windows64/twinstrptime.c create mode 100644 src/os/src/windows64/twintcpclient.c create mode 100644 src/os/src/windows64/twintcpserver.c create mode 100644 src/os/src/windows64/twintime.c create mode 100644 src/os/src/windows64/twintimer.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e53cca2ea8..500b2ff1eb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -SET(TD_SYNC FALSE) SET(TD_ACCOUNT FALSE) SET(TD_ADMIN FALSE) SET(TD_GRANT FALSE) diff --git a/cmake/define.inc b/cmake/define.inc index 93bf602610..d68f2230f1 100755 --- a/cmake/define.inc +++ b/cmake/define.inc @@ -1,10 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_SYNC) - ADD_DEFINITIONS(-D_SYNC) -ENDIF () - IF (TD_ACCOUNT) ADD_DEFINITIONS(-D_ACCT) ENDIF () diff --git a/cmake/env.inc b/cmake/env.inc index fbfa40e5ae..67b934119d 100755 --- a/cmake/env.inc +++ b/cmake/env.inc @@ -9,7 +9,6 @@ SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build/lib) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build/bin) SET(TD_TESTS_OUTPUT_DIR ${PROJECT_BINARY_DIR}/test) -MESSAGE(STATUS "Operating system dependency directory: " ${TD_OS_DIR}) MESSAGE(STATUS "Project source directory: " ${PROJECT_SOURCE_DIR}) MESSAGE(STATUS "Project binary files output path: " ${PROJECT_BINARY_DIR}) MESSAGE(STATUS "Project executable files output path: " ${EXECUTABLE_OUTPUT_PATH}) diff --git a/cmake/platform.inc b/cmake/platform.inc index 2e0e2d6af0..7a371df70b 100755 --- a/cmake/platform.inc +++ b/cmake/platform.inc @@ -33,20 +33,23 @@ IF (${CPUTYPE} MATCHES "aarch32") SET(TD_PAGMODE_LITE TRUE) ADD_DEFINITIONS(-D_TD_ARM_) ADD_DEFINITIONS(-D_TD_ARM_32_) + MESSAGE(STATUS "input cpuType: aarch32") ELSEIF (${CPUTYPE} MATCHES "aarch64") SET(TD_ARM TRUE) SET(TD_ARM_64 TRUE) ADD_DEFINITIONS(-D_TD_ARM_) ADD_DEFINITIONS(-D_TD_ARM_64_) + MESSAGE(STATUS "input cpuType: aarch64") ELSEIF (${CPUTYPE} MATCHES "mips64") SET(TD_MIPS TRUE) SET(TD_MIPS_64 TRUE) ADD_DEFINITIONS(-D_TD_MIPS_) ADD_DEFINITIONS(-D_TD_MIPS_64_) + MESSAGE(STATUS "input cpuType: mips64") ELSEIF (${CPUTYPE} MATCHES "x64") - MESSAGE(STATUS "input cpuType: " ${CPUTYPE}) + MESSAGE(STATUS "input cpuType: x64") ELSEIF (${CPUTYPE} MATCHES "x86") - MESSAGE(STATUS "input cpuType: " ${CPUTYPE}) + MESSAGE(STATUS "input cpuType: x86") ELSE () MESSAGE(STATUS "input cpuType: " ${CPUTYPE}) ENDIF () @@ -61,13 +64,13 @@ MESSAGE(STATUS "The current os is " ${TD_OS_INFO}) IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) SET(TD_LINUX_64 TRUE) - SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/linux) ADD_DEFINITIONS(-D_M_X64) + ADD_DEFINITIONS(-D_TD_LINUX_64) MESSAGE(STATUS "The current platform is Linux 64-bit") ELSEIF (${CMAKE_SIZEOF_VOID_P} MATCHES 4) + SET(TD_LINUX_32 TRUE) + ADD_DEFINITIONS(-D_TD_LINUX_32) IF (TD_ARM) - SET(TD_LINUX_32 TRUE) - SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/linux) #ADD_DEFINITIONS(-D_M_IX86) MESSAGE(STATUS "The current platform is Linux 32-bit") ELSE () @@ -81,7 +84,7 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) SET(TD_DARWIN_64 TRUE) - SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/darwin) + ADD_DEFINITIONS(-D_TD_DARWIN_64) MESSAGE(STATUS "The current platform is Darwin 64-bit") ELSE () MESSAGE(FATAL_ERROR "The current platform is Darwin 32-bit, not supported yet") @@ -90,10 +93,12 @@ ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Windows") IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) SET(TD_WINDOWS_64 TRUE) - SET(TD_OS_DIR ${TD_COMMUNITY_DIR}/src/os/windows) ADD_DEFINITIONS(-D_M_X64) + ADD_DEFINITIONS(-D_TD_WINDOWS_64) MESSAGE(STATUS "The current platform is Windows 64-bit") ELSE () + SET(TD_WINDOWS_32 TRUE) + ADD_DEFINITIONS(-D_TD_WINDOWS_32) MESSAGE(FATAL_ERROR "The current platform is Windows 32-bit, not supported yet") EXIT () ENDIF () diff --git a/src/balance/CMakeLists.txt b/src/balance/CMakeLists.txt new file mode 100644 index 0000000000..45b7c4ed57 --- /dev/null +++ b/src/balance/CMakeLists.txt @@ -0,0 +1,16 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/sdb/inc) + INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) + INCLUDE_DIRECTORIES(inc) + AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(balance ${SRC}) +ENDIF () diff --git a/src/balance/src/balance.c b/src/balance/src/balance.c new file mode 100644 index 0000000000..3ef616bff0 --- /dev/null +++ b/src/balance/src/balance.c @@ -0,0 +1,1006 @@ +/* + * 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 "tutil.h" +#include "tbalance.h" +#include "tsync.h" +#include "ttime.h" +#include "ttimer.h" +#include "tglobal.h" +#include "tdataformat.h" +#include "dnode.h" +#include "mnode.h" +#include "mnodeDef.h" +#include "mnodeInt.h" +#include "mnodeDnode.h" +#include "mnodeDb.h" +#include "mnodeMnode.h" +#include "mnodeSdb.h" +#include "mnodeShow.h" +#include "mnodeUser.h" +#include "mnodeVgroup.h" + +/* + * once sdb work as mater, then tsAccessSquence reset to zero + * increase tsAccessSquence every balance interval + */ +extern void * tsMnodeTmr; +static void * tsBalanceTimer = NULL; +static int32_t tsBalanceDnodeListSize = 0; +static SDnodeObj ** tsBalanceDnodeList = NULL; +static int32_t tsBalanceDnodeListMallocSize = 16; +static pthread_mutex_t tsBalanceMutex; + +static void balanceStartTimer(int64_t mseconds); +static void balanceInitDnodeList(); +static void balanceCleanupDnodeList(); +static void balanceAccquireDnodeList(); +static void balanceReleaseDnodeList(); +static void balanceMonitorDnodeModule(); +static float balanceTryCalcDnodeScore(SDnodeObj *pDnode, int32_t extraVnode); +static int32_t balanceGetScoresMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn); +static int32_t balanceRetrieveScores(SShowObj *pShow, char *data, int32_t rows, void *pConn); + +static void balanceLock() { + pthread_mutex_lock(&tsBalanceMutex); +} + +static void balanceUnLock() { + pthread_mutex_unlock(&tsBalanceMutex); +} + +static bool balanceCheckFree(SDnodeObj *pDnode) { + if (pDnode->status == TAOS_DN_STATUS_DROPPING || pDnode->status == TAOS_DN_STATUS_OFFLINE) { + mError("dnode:%d, status:%s not available", pDnode->dnodeId, mnodeGetDnodeStatusStr(pDnode->status)); + return false; + } + + if (pDnode->openVnodes >= TSDB_MAX_VNODES) { + mError("dnode:%d, openVnodes:%d maxVnodes:%d not available", pDnode->dnodeId, pDnode->openVnodes, TSDB_MAX_VNODES); + return false; + } + + if (pDnode->diskAvailable <= tsMinimalDataDirGB) { + mError("dnode:%d, disk space:%fGB, not available", pDnode->dnodeId, pDnode->diskAvailable); + return false; + } + + if (pDnode->alternativeRole == TAOS_DN_ALTERNATIVE_ROLE_MNODE) { + mDebug("dnode:%d, alternative role is master, can't alloc vnodes in this dnode", pDnode->dnodeId); + return false; + } + + return true; +} + +static void balanceDiscardVnode(SVgObj *pVgroup, SVnodeGid *pVnodeGid) { + mDebug("vgId:%d, dnode:%d is dropping", pVgroup->vgId, pVnodeGid->dnodeId); + + SDnodeObj *pDnode = mnodeGetDnode(pVnodeGid->dnodeId); + if (pDnode != NULL) { + atomic_sub_fetch_32(&pDnode->openVnodes, 1); + mnodeDecDnodeRef(pDnode); + } + + SVnodeGid vnodeGid[TSDB_MAX_REPLICA]; memset(vnodeGid, 0, sizeof(vnodeGid)); /* = {0}; */ + int32_t numOfVnodes = 0; + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + SVnodeGid *pTmpVodeGid = pVgroup->vnodeGid + i; + if (pTmpVodeGid == pVnodeGid) { + continue; + } + vnodeGid[numOfVnodes] = *pTmpVodeGid; + ++numOfVnodes; + } + memcpy(pVgroup->vnodeGid, vnodeGid, TSDB_MAX_REPLICA * sizeof(SVnodeGid)); + pVgroup->numOfVnodes = numOfVnodes; + + mnodeUpdateVgroup(pVgroup); +} + +static void balanceSwapVnodeGid(SVnodeGid *pVnodeGid1, SVnodeGid *pVnodeGid2) { + // SVnodeGid tmp = *pVnodeGid1; + // *pVnodeGid1 = *pVnodeGid2; + // *pVnodeGid2 = tmp; +} + +int32_t balanceAllocVnodes(SVgObj *pVgroup) { + int32_t dnode = 0; + int32_t vnodes = 0; + + balanceLock(); + + balanceAccquireDnodeList(); + + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + for (; dnode < tsBalanceDnodeListSize; ++dnode) { + SDnodeObj *pDnode = tsBalanceDnodeList[dnode]; + if (balanceCheckFree(pDnode)) { + SVnodeGid *pVnodeGid = pVgroup->vnodeGid + i; + pVnodeGid->dnodeId = pDnode->dnodeId; + pVnodeGid->pDnode = pDnode; + dnode++; + vnodes++; + break; + } + } + } + + if (vnodes != pVgroup->numOfVnodes) { + mDebug("vgId:%d, db:%s need vnodes:%d, but alloc:%d, free them", pVgroup->vgId, pVgroup->dbName, + pVgroup->numOfVnodes, vnodes); + balanceReleaseDnodeList(); + balanceUnLock(); + return -1; + } + + /* + * make the choice more random. + * replica 1: no choice + * replica 2: there are 2 combinations + * replica 3 or larger: there are 6 combinations + */ + if (pVgroup->numOfVnodes == 1) { + } else if (pVgroup->numOfVnodes == 2) { + if (rand() % 2 == 0) { + balanceSwapVnodeGid(pVgroup->vnodeGid, pVgroup->vnodeGid + 1); + } + } else { + int32_t randVal = rand() % 6; + if (randVal == 1) { // 1, 0, 2 + balanceSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 1); + } else if (randVal == 2) { // 1, 2, 0 + balanceSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 1); + balanceSwapVnodeGid(pVgroup->vnodeGid + 1, pVgroup->vnodeGid + 2); + } else if (randVal == 3) { // 2, 1, 0 + balanceSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 2); + } else if (randVal == 4) { // 2, 0, 1 + balanceSwapVnodeGid(pVgroup->vnodeGid + 0, pVgroup->vnodeGid + 2); + balanceSwapVnodeGid(pVgroup->vnodeGid + 1, pVgroup->vnodeGid + 2); + } + if (randVal == 5) { // 0, 2, 1 + balanceSwapVnodeGid(pVgroup->vnodeGid + 1, pVgroup->vnodeGid + 2); + } else { + } // 0, 1, 2 + } + + balanceReleaseDnodeList(); + balanceUnLock(); + return 0; +} + +static bool balanceCheckVgroupReady(SVgObj *pVgroup, SVnodeGid *pRmVnode) { + if (pVgroup->lbTime + 5 * tsStatusInterval > tsAccessSquence) { + return false; + } + + bool isReady = false; + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + SVnodeGid *pVnode = pVgroup->vnodeGid + i; + if (pVnode == pRmVnode) continue; + + mTrace("vgId:%d, change vgroup status, dnode:%d status:%d", pVgroup->vgId, pVnode->pDnode->dnodeId, + pVnode->pDnode->status); + if (pVnode->pDnode->status == TAOS_DN_STATUS_DROPPING) continue; + if (pVnode->pDnode->status == TAOS_DN_STATUS_OFFLINE) continue; + + if (pVnode->role == TAOS_SYNC_ROLE_SLAVE || pVnode->role == TAOS_SYNC_ROLE_MASTER) { + isReady = true; + } + } + + return isReady; +} + +/** + * desc: remove one vnode from vgroup + * all vnodes in vgroup should in ready state, except the balancing one + **/ +static void balanceRemoveVnode(SVgObj *pVgroup) { + if (pVgroup->numOfVnodes <= 1) return; + + SVnodeGid *pRmVnode = NULL; + SVnodeGid *pSelVnode = NULL; + int32_t maxScore = 0; + + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + SVnodeGid *pVnode = &(pVgroup->vnodeGid[i]); + SDnodeObj *pDnode = mnodeGetDnode(pVnode->dnodeId); + + if (pDnode == NULL) { + mError("vgId:%d, dnode:%d not exist, remove it", pVgroup->vgId, pVnode->dnodeId); + pRmVnode = pVnode; + break; + } + + if (pDnode->status == TAOS_DN_STATUS_DROPPING) { + mDebug("vgId:%d, dnode:%d in dropping state", pVgroup->vgId, pVnode->dnodeId); + pRmVnode = pVnode; + } else if (pVnode->dnodeId == pVgroup->lbDnodeId) { + mDebug("vgId:%d, dnode:%d in updating state", pVgroup->vgId, pVnode->dnodeId); + pRmVnode = pVnode; + } else { + if (pSelVnode == NULL) { + pSelVnode = pVnode; + maxScore = pDnode->score; + } else { + if (maxScore < pDnode->score) { + pSelVnode = pVnode; + maxScore = pDnode->score; + } + } + } + + mnodeDecDnodeRef(pDnode); + } + + if (pRmVnode != NULL) { + pSelVnode = pRmVnode; + } + + if (!balanceCheckVgroupReady(pVgroup, pSelVnode)) { + mDebug("vgId:%d, is not ready", pVgroup->vgId); + } else { + mDebug("vgId:%d, is ready, discard dnode:%d", pVgroup->vgId, pSelVnode->dnodeId); + balanceDiscardVnode(pVgroup, pSelVnode); + } +} + +static bool balanceCheckDnodeInVgroup(SDnodeObj *pDnode, SVgObj *pVgroup) { + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + SVnodeGid *pGid = &pVgroup->vnodeGid[i]; + if (pGid->dnodeId == 0) break; + if (pGid->dnodeId == pDnode->dnodeId) { + return true; + } + } + + return false; +} + +/** + * desc: add vnode to vgroup, find a new one if dest dnode is null + **/ +static int32_t balanceAddVnode(SVgObj *pVgroup, SDnodeObj *pSrcDnode, SDnodeObj *pDestDnode) { + if (pDestDnode == NULL) { + for (int32_t i = 0; i < tsBalanceDnodeListSize; ++i) { + SDnodeObj *pDnode = tsBalanceDnodeList[i]; + if (pDnode == pSrcDnode) continue; + if (balanceCheckDnodeInVgroup(pDnode, pVgroup)) continue; + if (!balanceCheckFree(pDnode)) continue; + + pDestDnode = pDnode; + mDebug("vgId:%d, add vnode to dnode:%d", pVgroup->vgId, pDnode->dnodeId); + break; + } + } + + if (pDestDnode == NULL) { + return TSDB_CODE_MND_DNODE_NOT_EXIST; + } + + SVnodeGid *pVnodeGid = pVgroup->vnodeGid + pVgroup->numOfVnodes; + pVnodeGid->dnodeId = pDestDnode->dnodeId; + pVnodeGid->pDnode = pDestDnode; + pVgroup->numOfVnodes++; + + if (pSrcDnode != NULL) { + pVgroup->lbDnodeId = pSrcDnode->dnodeId; + } + + atomic_add_fetch_32(&pDestDnode->openVnodes, 1); + + mnodeUpdateVgroup(pVgroup); + + return TSDB_CODE_SUCCESS; +} + +static bool balanceMonitorBalance() { + if (tsBalanceDnodeListSize < 2) return false; + + for (int32_t src = tsBalanceDnodeListSize - 1; src >= 0; --src) { + SDnodeObj *pDnode = tsBalanceDnodeList[src]; + mDebug("%d-dnode:%d, state:%s, score:%.1f, numOfCores:%d, openVnodes:%d", tsBalanceDnodeListSize - src - 1, + pDnode->dnodeId, mnodeGetDnodeStatusStr(pDnode->status), pDnode->score, pDnode->numOfCores, + pDnode->openVnodes); + } + + float scoresDiff = tsBalanceDnodeList[tsBalanceDnodeListSize - 1]->score - tsBalanceDnodeList[0]->score; + if (scoresDiff < 0.01) { + mDebug("all dnodes:%d is already balanced, scoresDiff:%f", tsBalanceDnodeListSize, scoresDiff); + return false; + } + + for (int32_t src = tsBalanceDnodeListSize - 1; src > 0; --src) { + SDnodeObj *pSrcDnode = tsBalanceDnodeList[src]; + float srcScore = balanceTryCalcDnodeScore(pSrcDnode, -1); + if (tsEnableBalance == 0 && pSrcDnode->status != TAOS_DN_STATUS_DROPPING) { + continue; + } + + void *pIter = NULL; + while (1) { + SVgObj *pVgroup; + pIter = mnodeGetNextVgroup(pIter, &pVgroup); + if (pVgroup == NULL) break; + + if (balanceCheckDnodeInVgroup(pSrcDnode, pVgroup)) { + for (int32_t dest = 0; dest < src; dest++) { + SDnodeObj *pDestDnode = tsBalanceDnodeList[dest]; + if (balanceCheckDnodeInVgroup(pDestDnode, pVgroup)) continue; + + float destScore = balanceTryCalcDnodeScore(pDestDnode, 1); + if (srcScore + 0.0001 < destScore) continue; + if (!balanceCheckFree(pDestDnode)) continue; + + mDebug("vgId:%d, balance from dnode:%d to dnode:%d, srcScore:%.1f:%.1f, destScore:%.1f:%.1f", + pVgroup->vgId, pSrcDnode->dnodeId, pDestDnode->dnodeId, pSrcDnode->score, + srcScore, pDestDnode->score, destScore); + balanceAddVnode(pVgroup, pSrcDnode, pDestDnode); + mnodeDecVgroupRef(pVgroup); + sdbFreeIter(pIter); + return true; + } + } + + mnodeDecVgroupRef(pVgroup); + } + + sdbFreeIter(pIter); + } + + return false; +} + +// if mgmt changed to master +// 1. reset balanceAccessSquence to zero +// 2. reset state of dnodes to offline +// 3. reset lastAccess of dnodes to zero +void balanceReset() { + void * pIter = NULL; + SDnodeObj *pDnode = NULL; + while (1) { + pIter = mnodeGetNextDnode(pIter, &pDnode); + if (pDnode == NULL) break; + + // while master change, should reset dnode to offline + mInfo("dnode:%d set access:%d to 0", pDnode->dnodeId, pDnode->lastAccess); + pDnode->lastAccess = 0; + if (pDnode->status != TAOS_DN_STATUS_DROPPING) { + pDnode->status = TAOS_DN_STATUS_OFFLINE; + } + + mnodeDecDnodeRef(pDnode); + } + + sdbFreeIter(pIter); + + tsAccessSquence = 0; +} + +static int32_t balanceMonitorVgroups() { + void * pIter = NULL; + SVgObj *pVgroup = NULL; + bool hasUpdatingVgroup = false; + + while (1) { + pIter = mnodeGetNextVgroup(pIter, &pVgroup); + if (pVgroup == NULL) break; + + int32_t dbReplica = pVgroup->pDb->cfg.replications; + int32_t vgReplica = pVgroup->numOfVnodes; + + if (vgReplica > dbReplica) { + mInfo("vgId:%d, replica:%d numOfVnodes:%d, try remove one vnode", pVgroup->vgId, dbReplica, vgReplica); + hasUpdatingVgroup = true; + balanceRemoveVnode(pVgroup); + } else if (vgReplica < dbReplica) { + mInfo("vgId:%d, replica:%d numOfVnodes:%d, try add one vnode", pVgroup->vgId, dbReplica, vgReplica); + hasUpdatingVgroup = true; + balanceAddVnode(pVgroup, NULL, NULL); + } + + mnodeDecVgroupRef(pVgroup); + } + + sdbFreeIter(pIter); + + return hasUpdatingVgroup; +} + +static bool balanceMonitorDnodeDropping(SDnodeObj *pDnode) { + mDebug("dnode:%d, in dropping state", pDnode->dnodeId); + + void * pIter = NULL; + bool hasThisDnode = false; + while (1) { + SVgObj *pVgroup = NULL; + pIter = mnodeGetNextVgroup(pIter, &pVgroup); + if (pVgroup == NULL) break; + + hasThisDnode = balanceCheckDnodeInVgroup(pDnode, pVgroup); + mnodeDecVgroupRef(pVgroup); + + if (hasThisDnode) break; + } + + sdbFreeIter(pIter); + + if (!hasThisDnode) { + mInfo("dnode:%d, dropped for all vnodes are moving to other dnodes", pDnode->dnodeId); + mnodeDropDnode(pDnode, NULL); + return true; + } + + return false; +} + +static bool balanceMontiorDropping() { + void *pIter = NULL; + SDnodeObj *pDnode = NULL; + + while (1) { + mnodeDecDnodeRef(pDnode); + pIter = mnodeGetNextDnode(pIter, &pDnode); + if (pDnode == NULL) break; + + if (pDnode->status == TAOS_DN_STATUS_OFFLINE) { + if (pDnode->lastAccess + tsOfflineThreshold > tsAccessSquence) continue; + if (strcmp(pDnode->dnodeEp, dnodeGetMnodeMasterEp()) == 0) continue; + if (mnodeGetDnodesNum() <= 1) continue; + + mLInfo("dnode:%d, set to removing state for it offline:%d seconds", pDnode->dnodeId, + tsAccessSquence - pDnode->lastAccess); + + pDnode->status = TAOS_DN_STATUS_DROPPING; + mnodeUpdateDnode(pDnode); + mnodeDecDnodeRef(pDnode); + sdbFreeIter(pIter); + return true; + } + + if (pDnode->status == TAOS_DN_STATUS_DROPPING) { + bool ret = balanceMonitorDnodeDropping(pDnode); + mnodeDecDnodeRef(pDnode); + sdbFreeIter(pIter); + return ret; + } + } + + sdbFreeIter(pIter); + + return false; +} + +static bool balanceStart() { + if (!sdbIsMaster()) return false; + + balanceLock(); + + balanceAccquireDnodeList(); + + balanceMonitorDnodeModule(); + + bool updateSoon = balanceMontiorDropping(); + + if (!updateSoon) { + updateSoon = balanceMonitorVgroups(); + } + + if (!updateSoon) { + updateSoon = balanceMonitorBalance(); + } + + balanceReleaseDnodeList(); + + balanceUnLock(); + + return updateSoon; +} + +static void balanceSetVgroupOffline(SDnodeObj* pDnode) { + void *pIter = NULL; + while (1) { + SVgObj *pVgroup; + pIter = mnodeGetNextVgroup(pIter, &pVgroup); + if (pVgroup == NULL) break; + + for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) { + if (pVgroup->vnodeGid[i].pDnode == pDnode) { + pVgroup->vnodeGid[i].role = TAOS_SYNC_ROLE_OFFLINE; + } + } + mnodeDecVgroupRef(pVgroup); + } + + sdbFreeIter(pIter); +} + +static void balanceCheckDnodeAccess() { + void * pIter = NULL; + SDnodeObj *pDnode = NULL; + + while (1) { + pIter = mnodeGetNextDnode(pIter, &pDnode); + if (pDnode == NULL) break; + if (tsAccessSquence - pDnode->lastAccess > 3) { + if (pDnode->status != TAOS_DN_STATUS_DROPPING && pDnode->status != TAOS_DN_STATUS_OFFLINE) { + pDnode->status = TAOS_DN_STATUS_OFFLINE; + mInfo("dnode:%d, set to offline state", pDnode->dnodeId); + balanceSetVgroupOffline(pDnode); + } + } + mnodeDecDnodeRef(pDnode); + } + + sdbFreeIter(pIter); +} + +static void balanceProcessBalanceTimer(void *handle, void *tmrId) { + if (!sdbIsMaster()) return; + + tsBalanceTimer = NULL; + tsAccessSquence ++; + + balanceCheckDnodeAccess(); + bool updateSoon = false; + + if (handle == NULL) { + if (tsAccessSquence % tsBalanceInterval == 0) { + mDebug("balance function is scheduled by timer"); + updateSoon = balanceStart(); + } + } else { + int64_t mseconds = (int64_t)handle; + mDebug("balance function is scheduled by event for %" PRId64 " mseconds arrived", mseconds); + updateSoon = balanceStart(); + } + + if (updateSoon) { + balanceStartTimer(1000); + } else { + taosTmrReset(balanceProcessBalanceTimer, tsStatusInterval * 1000, NULL, tsMnodeTmr, &tsBalanceTimer); + } +} + +static void balanceStartTimer(int64_t mseconds) { + taosTmrReset(balanceProcessBalanceTimer, mseconds, (void *)mseconds, tsMnodeTmr, &tsBalanceTimer); +} + +void balanceSyncNotify() { + if (sdbIsMaster()) { + balanceLock(); + balanceAccquireDnodeList(); + balanceMonitorDnodeModule(); + balanceReleaseDnodeList(); + balanceUnLock(); + } +} + +void balanceAsyncNotify() { + balanceStartTimer(500); +} + +int32_t balanceInit() { + mnodeAddShowMetaHandle(TSDB_MGMT_TABLE_SCORES, balanceGetScoresMeta); + mnodeAddShowRetrieveHandle(TSDB_MGMT_TABLE_SCORES, balanceRetrieveScores); + + pthread_mutex_init(&tsBalanceMutex, NULL); + balanceInitDnodeList(); + balanceStartTimer(2000); + mDebug("balance start fp:%p initialized", balanceProcessBalanceTimer); + + balanceReset(); + + return 0; +} + +void balanceCleanUp() { + if (tsBalanceTimer != NULL) { + taosTmrStopA(&tsBalanceTimer); + pthread_mutex_destroy(&tsBalanceMutex); + tsBalanceTimer = NULL; + mDebug("stop balance timer"); + } + balanceCleanupDnodeList(); +} + +int32_t balanceDropDnode(SDnodeObj *pDnode) { + int32_t totalFreeVnodes = 0; + void * pIter = NULL; + SDnodeObj *pTempDnode = NULL; + + while (1) { + pIter = mnodeGetNextDnode(pIter, &pTempDnode); + if (pTempDnode == NULL) break; + + if (pTempDnode != pDnode && balanceCheckFree(pTempDnode)) { + totalFreeVnodes += (TSDB_MAX_VNODES - pTempDnode->openVnodes); + } + + mnodeDecDnodeRef(pTempDnode); + } + + sdbFreeIter(pIter); + + if (pDnode->openVnodes > totalFreeVnodes) { + mError("dnode:%d, openVnodes:%d totalFreeVnodes:%d no enough dnodes", pDnode->dnodeId, pDnode->openVnodes, totalFreeVnodes); + return TSDB_CODE_MND_NO_ENOUGH_DNODES; + } + + pDnode->status = TAOS_DN_STATUS_DROPPING; + mnodeUpdateDnode(pDnode); + + balanceStartTimer(1100); + + return TSDB_CODE_SUCCESS; +} + +static int32_t balanceCalcCpuScore(SDnodeObj *pDnode) { + if (pDnode->cpuAvgUsage < 80) + return 0; + else if (pDnode->cpuAvgUsage < 90) + return 10; + else + return 50; +} + +static int32_t balanceCalcMemoryScore(SDnodeObj *pDnode) { + if (pDnode->memoryAvgUsage < 80) + return 0; + else if (pDnode->memoryAvgUsage < 90) + return 10; + else + return 50; +} + +static int32_t balanceCalcDiskScore(SDnodeObj *pDnode) { + if (pDnode->diskAvgUsage < 80) + return 0; + else if (pDnode->diskAvgUsage < 90) + return 10; + else + return 50; +} + +static int32_t balanceCalcBandwidthScore(SDnodeObj *pDnode) { + if (pDnode->bandwidthUsage < 30) + return 0; + else if (pDnode->bandwidthUsage < 80) + return 10; + else + return 50; +} + +static float balanceCalcModuleScore(SDnodeObj *pDnode) { + if (pDnode->numOfCores <= 0) return 0; + if (pDnode->isMgmt) { + return (float)tsMnodeEqualVnodeNum / pDnode->numOfCores; + } + return 0; +} + +static float balanceCalcVnodeScore(SDnodeObj *pDnode, int32_t extra) { + if (pDnode->status == TAOS_DN_STATUS_DROPPING || pDnode->status == TAOS_DN_STATUS_OFFLINE) return 100000000; + if (pDnode->numOfCores <= 0) return 0; + return (float)(pDnode->openVnodes + extra) / pDnode->numOfCores; +} + +/** + * calc singe score, such as cpu/memory/disk/bandwitdh/vnode + * 1. get the score config + * 2. if the value is out of range, use border data + * 3. otherwise use interpolation method + **/ +void balanceCalcDnodeScore(SDnodeObj *pDnode) { + pDnode->score = balanceCalcCpuScore(pDnode) + balanceCalcMemoryScore(pDnode) + balanceCalcDiskScore(pDnode) + + balanceCalcBandwidthScore(pDnode) + balanceCalcModuleScore(pDnode) + + balanceCalcVnodeScore(pDnode, 0) + pDnode->customScore; +} + +float balanceTryCalcDnodeScore(SDnodeObj *pDnode, int32_t extra) { + int32_t systemScore = balanceCalcCpuScore(pDnode) + balanceCalcMemoryScore(pDnode) + balanceCalcDiskScore(pDnode) + + balanceCalcBandwidthScore(pDnode); + float moduleScore = balanceCalcModuleScore(pDnode); + float vnodeScore = balanceCalcVnodeScore(pDnode, extra); + + float score = systemScore + moduleScore + vnodeScore + pDnode->customScore; + return score; +} + +static void balanceInitDnodeList() { + tsBalanceDnodeList = calloc(tsBalanceDnodeListMallocSize, sizeof(SDnodeObj *)); +} + +static void balanceCleanupDnodeList() { + if (tsBalanceDnodeList != NULL) { + free(tsBalanceDnodeList); + tsBalanceDnodeList = NULL; + } +} + +static void balanceCheckDnodeListSize(int32_t dnodesNum) { + if (tsBalanceDnodeListMallocSize <= dnodesNum) { + tsBalanceDnodeListMallocSize = dnodesNum * 2; + tsBalanceDnodeList = realloc(tsBalanceDnodeList, tsBalanceDnodeListMallocSize * sizeof(SDnodeObj *)); + } +} + +void balanceAccquireDnodeList() { + int32_t dnodesNum = mnodeGetDnodesNum(); + balanceCheckDnodeListSize(dnodesNum); + + void * pIter = NULL; + SDnodeObj *pDnode = NULL; + int32_t dnodeIndex = 0; + + while (1) { + if (dnodeIndex >= dnodesNum) break; + pIter = mnodeGetNextDnode(pIter, &pDnode); + if (pDnode == NULL) break; + if (pDnode->status == TAOS_DN_STATUS_OFFLINE) { + mnodeDecDnodeRef(pDnode); + continue; + } + + balanceCalcDnodeScore(pDnode); + + int32_t orderIndex = dnodeIndex; + for (; orderIndex > 0; --orderIndex) { + if (pDnode->score > tsBalanceDnodeList[orderIndex - 1]->score) { + break; + } + tsBalanceDnodeList[orderIndex] = tsBalanceDnodeList[orderIndex - 1]; + } + tsBalanceDnodeList[orderIndex] = pDnode; + dnodeIndex++; + } + + sdbFreeIter(pIter); + + tsBalanceDnodeListSize = dnodeIndex; +} + +void balanceReleaseDnodeList() { + for (int32_t i = 0; i < tsBalanceDnodeListSize; ++i) { + SDnodeObj *pDnode = tsBalanceDnodeList[i]; + if (pDnode != NULL) { + mnodeDecDnodeRef(pDnode); + } + } +} + +static int32_t balanceGetScoresMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { + SUserObj *pUser = mnodeGetUserFromConn(pConn); + if (pUser == NULL) return 0; + + if (strcmp(pUser->pAcct->user, "root") != 0) { + mnodeDecUserRef(pUser); + return TSDB_CODE_MND_NO_RIGHTS; + } + + int32_t cols = 0; + SSchema *pSchema = pMeta->schema; + + pShow->bytes[cols] = 2; + pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT; + strcpy(pSchema[cols].name, "id"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_FLOAT; + strcpy(pSchema[cols].name, "system scores"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_FLOAT; + strcpy(pSchema[cols].name, "custom scores"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_FLOAT; + strcpy(pSchema[cols].name, "module scores"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_FLOAT; + strcpy(pSchema[cols].name, "vnode scores"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_FLOAT; + strcpy(pSchema[cols].name, "total scores"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "open vnodes"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "cpu cores"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 18 + VARSTR_HEADER_SIZE; + pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + strcpy(pSchema[cols].name, "balance state"); + 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 = mnodeGetDnodesNum(); + pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; + pShow->pIter = NULL; + + mnodeDecUserRef(pUser); + + return 0; +} + +static int32_t balanceRetrieveScores(SShowObj *pShow, char *data, int32_t rows, void *pConn) { + int32_t numOfRows = 0; + SDnodeObj *pDnode = NULL; + char * pWrite; + int32_t cols = 0; + + while (numOfRows < rows) { + pShow->pIter = mnodeGetNextDnode(pShow->pIter, &pDnode); + if (pDnode == NULL) break; + + int32_t systemScore = balanceCalcCpuScore(pDnode) + balanceCalcMemoryScore(pDnode) + balanceCalcDiskScore(pDnode) + + balanceCalcBandwidthScore(pDnode); + float moduleScore = balanceCalcModuleScore(pDnode); + float vnodeScore = balanceCalcVnodeScore(pDnode, 0); + + cols = 0; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int16_t *)pWrite = pDnode->dnodeId; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(float *)pWrite = systemScore; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(float *)pWrite = pDnode->customScore; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(float *)pWrite = (int32_t)moduleScore; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(float *)pWrite = (int32_t)vnodeScore; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(float *)pWrite = (int32_t)(vnodeScore + moduleScore + pDnode->customScore + systemScore); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int32_t *)pWrite = pDnode->openVnodes; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int32_t *)pWrite = pDnode->numOfCores; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + STR_TO_VARSTR(pWrite, mnodeGetDnodeStatusStr(pDnode->status)); + cols++; + + numOfRows++; + mnodeDecDnodeRef(pDnode); + } + + pShow->numOfReads += numOfRows; + return numOfRows; +} + +static void balanceMonitorDnodeModule() { + int32_t numOfMnodes = mnodeGetMnodesNum(); + if (numOfMnodes >= tsNumOfMnodes) return; + + for (int32_t i = 0; i < tsBalanceDnodeListSize; ++i) { + SDnodeObj *pDnode = tsBalanceDnodeList[i]; + if (pDnode == NULL) break; + + if (pDnode->isMgmt || pDnode->status == TAOS_DN_STATUS_DROPPING || pDnode->status == TAOS_DN_STATUS_OFFLINE) { + continue; + } + + if (pDnode->alternativeRole == TAOS_DN_ALTERNATIVE_ROLE_VNODE) { + continue; + } + + mLInfo("dnode:%d, numOfMnodes:%d expect:%d, add mnode in this dnode", pDnode->dnodeId, numOfMnodes, tsNumOfMnodes); + mnodeAddMnode(pDnode->dnodeId); + + numOfMnodes = mnodeGetMnodesNum(); + if (numOfMnodes >= tsNumOfMnodes) return; + } +} + +int32_t balanceAlterDnode(struct SDnodeObj *pSrcDnode, int32_t vnodeId, int32_t dnodeId) { + if (!sdbIsMaster()) { + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, for self not master", pSrcDnode->dnodeId, vnodeId, dnodeId); + return TSDB_CODE_MND_DNODE_NOT_EXIST; + } + + if (tsEnableBalance != 0) { + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, for balance enabled", pSrcDnode->dnodeId, vnodeId, dnodeId); + return TSDB_CODE_MND_BALANCE_ENABLED; + } + + SVgObj *pVgroup = mnodeGetVgroup(vnodeId); + if (pVgroup == NULL) { + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, for vgroup not exist", pSrcDnode->dnodeId, vnodeId, dnodeId); + return TSDB_CODE_MND_VGROUP_NOT_EXIST; + } + + SDnodeObj *pDestDnode = mnodeGetDnode(dnodeId); + if (pDestDnode == NULL) { + mnodeDecVgroupRef(pVgroup); + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, for dnode not exist", pSrcDnode->dnodeId, vnodeId, dnodeId); + return TSDB_CODE_MND_DNODE_NOT_EXIST; + } + + balanceLock(); + balanceAccquireDnodeList(); + + int32_t code = TSDB_CODE_SUCCESS; + if (!balanceCheckDnodeInVgroup(pSrcDnode, pVgroup)) { + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, vgroup not in dnode:%d", pSrcDnode->dnodeId, vnodeId, + dnodeId, pSrcDnode->dnodeId); + code = TSDB_CODE_MND_VGROUP_NOT_IN_DNODE; + } else if (balanceCheckDnodeInVgroup(pDestDnode, pVgroup)) { + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, vgroup already in dnode:%d", pSrcDnode->dnodeId, vnodeId, + dnodeId, dnodeId); + code = TSDB_CODE_MND_VGROUP_ALREADY_IN_DNODE; + } else if (!balanceCheckFree(pDestDnode)) { + mError("dnode:%d, failed to alter vgId:%d to dnode:%d, for dnode:%d not free", pSrcDnode->dnodeId, vnodeId, dnodeId, + dnodeId); + code = TSDB_CODE_MND_DNODE_NOT_FREE; + } else { + code = balanceAddVnode(pVgroup, pSrcDnode, pDestDnode); + mInfo("dnode:%d, alter vgId:%d to dnode:%d, result:%s", pSrcDnode->dnodeId, vnodeId, dnodeId, tstrerror(code)); + } + + balanceReleaseDnodeList(); + balanceUnLock(); + + mnodeDecVgroupRef(pVgroup); + mnodeDecDnodeRef(pDestDnode); + + return code; +} \ No newline at end of file diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 00fa1a1479..eaebd2f19d 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -4,11 +4,11 @@ PROJECT(TDengine) INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(jni) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) AUX_SOURCE_DIRECTORY(src SRC) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index 95098bbab1..232ea52ded 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -104,7 +104,7 @@ int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int1 } else if (strncmp(pToken->z, "0", 1) == 0 && pToken->n == 1) { // do nothing } else if (pToken->type == TK_INTEGER) { - useconds = str2int64(pToken->z); + useconds = tsosStr2int64(pToken->z); } else { // strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm); if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index 5662b4a885..bf1b674260 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -220,7 +220,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { if (strlen(tsLocale) == 0) { // locale does not set yet char* defaultLocale = setlocale(LC_CTYPE, ""); - tstrncpy(tsLocale, defaultLocale, sizeof(tsLocale)); + tstrncpy(tsLocale, defaultLocale, TSDB_LOCALE_LEN); } // set the user specified locale @@ -234,7 +234,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { tscInfo("failed to set locale:%s, current locale:%s", pStr, tsLocale); } - tstrncpy(tsLocale, locale, sizeof(tsLocale)); + tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN); char *charset = strrchr(tsLocale, sep); if (charset != NULL) { @@ -249,7 +249,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { tscInfo("charset changed from %s to %s", tsCharset, charset); } - tstrncpy(tsCharset, charset, sizeof(tsCharset)); + tstrncpy(tsCharset, charset, TSDB_LOCALE_LEN); cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; } else { @@ -286,7 +286,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { tscInfo("charset changed from %s to %s", tsCharset, pStr); } - tstrncpy(tsCharset, pStr, sizeof(tsCharset)); + tstrncpy(tsCharset, pStr, TSDB_LOCALE_LEN); cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; } else { tscInfo("charset:%s not valid", pStr); @@ -304,7 +304,7 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) { assert(cfg != NULL); if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_OPTION) { - tstrncpy(tsTimezone, pStr, sizeof(tsTimezone)); + tstrncpy(tsTimezone, pStr, TSDB_TIMEZONE_LEN); tsSetTimeZone(); cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; tscDebug("timezone set:%s, input:%s by taos_options", tsTimezone, pStr); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 57a32f3d69..e856481a9a 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,12 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(common ${SRC}) - TARGET_LINK_LIBRARIES(common tutil) -ENDIF () +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(inc) + +AUX_SOURCE_DIRECTORY(src SRC) +ADD_LIBRARY(common ${SRC}) +TARGET_LINK_LIBRARIES(common tutil) diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h index b9afef65d9..495d2ae006 100644 --- a/src/common/inc/tglobal.h +++ b/src/common/inc/tglobal.h @@ -43,9 +43,9 @@ extern uint32_t tsMaxTmrCtrl; extern float tsNumOfThreadsPerCore; extern float tsRatioOfQueryThreads; extern int8_t tsDaylight; -extern char tsTimezone[64]; -extern char tsLocale[64]; -extern char tsCharset[64]; // default encode string +extern char tsTimezone[]; +extern char tsLocale[]; +extern char tsCharset[]; // default encode string extern int32_t tsEnableCoreFile; extern int32_t tsCompressMsgSize; diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index 08349374b1..5ab2d0a36d 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -50,7 +50,7 @@ int32_t tsShellActivityTimer = 3; // second float tsNumOfThreadsPerCore = 1.0; float tsRatioOfQueryThreads = 0.5; int8_t tsDaylight = 0; -char tsTimezone[64] = {0}; +char tsTimezone[TSDB_TIMEZONE_LEN] = {0}; char tsLocale[TSDB_LOCALE_LEN] = {0}; char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string int32_t tsEnableCoreFile = 0; diff --git a/src/cq/CMakeLists.txt b/src/cq/CMakeLists.txt index e8796306f3..4ccdb765c3 100644 --- a/src/cq/CMakeLists.txt +++ b/src/cq/CMakeLists.txt @@ -1,8 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(inc) diff --git a/src/cq/test/CMakeLists.txt b/src/cq/test/CMakeLists.txt index 99c729dff4..82781f531a 100644 --- a/src/cq/test/CMakeLists.txt +++ b/src/cq/test/CMakeLists.txt @@ -1,17 +1,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(../inc) - - LIST(APPEND CQTEST_SRC ./cqtest.c) - ADD_EXECUTABLE(cqtest ${CQTEST_SRC}) - TARGET_LINK_LIBRARIES(cqtest tcq) - -ENDIF () - +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/cq/inc) +LIST(APPEND CQTEST_SRC ./cqtest.c) +ADD_EXECUTABLE(cqtest ${CQTEST_SRC}) +TARGET_LINK_LIBRARIES(cqtest tcq) diff --git a/src/dnode/CMakeLists.txt b/src/dnode/CMakeLists.txt index de6e15e6b9..f7c2961352 100644 --- a/src/dnode/CMakeLists.txt +++ b/src/dnode/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) @@ -16,7 +16,7 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) AUX_SOURCE_DIRECTORY(src SRC) ADD_EXECUTABLE(taosd ${SRC}) - TARGET_LINK_LIBRARIES(taosd mnode taos_static monitor http mqtt tsdb twal vnode cJson lz4) + TARGET_LINK_LIBRARIES(taosd mnode taos_static monitor http mqtt tsdb twal vnode cJson lz4 balance sync) IF (TD_ACCOUNT) TARGET_LINK_LIBRARIES(taosd account) @@ -26,10 +26,6 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) TARGET_LINK_LIBRARIES(taosd grant) ENDIF () - IF (TD_SYNC) - TARGET_LINK_LIBRARIES(taosd balance sync) - ENDIF () - SET(PREPARE_ENV_CMD "prepare_env_cmd") SET(PREPARE_ENV_TARGET "prepare_env_target") ADD_CUSTOM_COMMAND(OUTPUT ${PREPARE_ENV_CMD} diff --git a/src/dnode/src/dnodeSystem.c b/src/dnode/src/dnodeSystem.c index 901e0061e9..2519684878 100644 --- a/src/dnode/src/dnodeSystem.c +++ b/src/dnode/src/dnodeSystem.c @@ -20,7 +20,6 @@ #include "tglobal.h" #include "dnodeInt.h" #include "dnodeMain.h" -#include "tfile.h" static void signal_handler(int32_t signum, siginfo_t *sigInfo, void *context); static sem_t exitSem; @@ -40,7 +39,7 @@ int32_t main(int32_t argc, char *argv[]) { exit(EXIT_FAILURE); } } else if (strcmp(argv[i], "-V") == 0) { -#ifdef _SYNC +#ifdef _ACCT char *versionStr = "enterprise"; #else char *versionStr = "community"; diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 1bb185e448..ee95548c2d 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -250,7 +250,7 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size); #define TSDB_STATE_LEN 20 #define TSDB_COUNTRY_LEN 20 #define TSDB_LOCALE_LEN 64 -#define TSDB_TIMEZONE_LEN 64 +#define TSDB_TIMEZONE_LEN 96 #define TSDB_LABEL_LEN 8 #define TSDB_FQDN_LEN 128 diff --git a/src/kit/shell/CMakeLists.txt b/src/kit/shell/CMakeLists.txt index 9854a44c3b..01c5f5ea3a 100644 --- a/src/kit/shell/CMakeLists.txt +++ b/src/kit/shell/CMakeLists.txt @@ -2,11 +2,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) diff --git a/src/kit/taosdemo/CMakeLists.txt b/src/kit/taosdemo/CMakeLists.txt index 627092a85b..a1593ce5a1 100644 --- a/src/kit/taosdemo/CMakeLists.txt +++ b/src/kit/taosdemo/CMakeLists.txt @@ -2,9 +2,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) diff --git a/src/kit/taosdump/CMakeLists.txt b/src/kit/taosdump/CMakeLists.txt index c63168237c..2a14dbfb4a 100644 --- a/src/kit/taosdump/CMakeLists.txt +++ b/src/kit/taosdump/CMakeLists.txt @@ -2,11 +2,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) diff --git a/src/kit/taosdump/taosdump.c b/src/kit/taosdump/taosdump.c index a1b1998298..7ae209bbdf 100644 --- a/src/kit/taosdump/taosdump.c +++ b/src/kit/taosdump/taosdump.c @@ -545,7 +545,7 @@ int32_t taosSaveAllNormalTableToTempFile(TAOS *taosCon, char*meter, char* metric strcpy(tableRecord.name, meter); strcpy(tableRecord.metric, metric); - twrite(*fd, &tableRecord, sizeof(STableRecord)); + taosTWrite(*fd, &tableRecord, sizeof(STableRecord)); return 0; } @@ -600,7 +600,7 @@ int32_t taosSaveTableOfMetricToTempFile(TAOS *taosCon, char* metric, struct argu strncpy(tableRecord.name, (char *)row[0], fields[0].bytes); strcpy(tableRecord.metric, metric); - twrite(fd, &tableRecord, sizeof(STableRecord)); + taosTWrite(fd, &tableRecord, sizeof(STableRecord)); numOfTable++; @@ -1196,7 +1196,7 @@ int32_t taosDumpCreateSuperTableClause(TAOS* taosCon, char* dbName, FILE *fp) while ((row = taos_fetch_row(tmpResult)) != NULL) { memset(&tableRecord, 0, sizeof(STableRecord)); strncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - twrite(fd, &tableRecord, sizeof(STableRecord)); + taosTWrite(fd, &tableRecord, sizeof(STableRecord)); } taos_free_result(tmpResult); @@ -1282,7 +1282,7 @@ int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *tao strncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); strncpy(tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX], fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes); - twrite(fd, &tableRecord, sizeof(STableRecord)); + taosTWrite(fd, &tableRecord, sizeof(STableRecord)); numOfTable++; diff --git a/src/kit/taosmigrate/CMakeLists.txt b/src/kit/taosmigrate/CMakeLists.txt index 85b2f33f01..86b428c61b 100644 --- a/src/kit/taosmigrate/CMakeLists.txt +++ b/src/kit/taosmigrate/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/vnode/inc) diff --git a/src/mnode/CMakeLists.txt b/src/mnode/CMakeLists.txt index 2e975f089c..f5b9fbf747 100644 --- a/src/mnode/CMakeLists.txt +++ b/src/mnode/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c index a159e98ed5..199cc63da6 100644 --- a/src/mnode/src/mnodeDb.c +++ b/src/mnode/src/mnodeDb.c @@ -301,13 +301,6 @@ static int32_t mnodeCheckDbCfg(SDbCfg *pCfg) { return TSDB_CODE_MND_INVALID_DB_OPTION; } -#ifndef _SYNC - if (pCfg->replications != 1) { - mError("invalid db option replications:%d can only be 1 in this version", pCfg->replications); - return TSDB_CODE_MND_INVALID_DB_OPTION; - } -#endif - return TSDB_CODE_SUCCESS; } diff --git a/src/mnode/src/mnodeDnode.c b/src/mnode/src/mnodeDnode.c index 4f9421efde..aa05eade24 100644 --- a/src/mnode/src/mnodeDnode.c +++ b/src/mnode/src/mnodeDnode.c @@ -79,9 +79,6 @@ static int32_t mnodeDnodeActionInsert(SSdbOper *pOper) { static int32_t mnodeDnodeActionDelete(SSdbOper *pOper) { SDnodeObj *pDnode = pOper->pObj; -#ifndef _SYNC - mnodeDropAllDnodeVgroups(pDnode); -#endif mnodeDropMnodeLocal(pDnode->dnodeId); balanceAsyncNotify(); @@ -552,12 +549,7 @@ static int32_t mnodeDropDnodeByEp(char *ep, SMnodeMsg *pMsg) { mInfo("dnode:%d, start to drop it", pDnode->dnodeId); -#ifndef _SYNC - int32_t code = mnodeDropDnode(pDnode, pMsg); -#else int32_t code = balanceDropDnode(pDnode); -#endif - mnodeDecDnodeRef(pDnode); return code; } diff --git a/src/os/CMakeLists.txt b/src/os/CMakeLists.txt index f88209ad9b..a8664669d0 100644 --- a/src/os/CMakeLists.txt +++ b/src/os/CMakeLists.txt @@ -1,6 +1,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -ADD_SUBDIRECTORY(linux) -ADD_SUBDIRECTORY(windows) -ADD_SUBDIRECTORY(darwin) +IF (TD_LINUX_64) + ADD_SUBDIRECTORY(src/linux64) +ELSEIF (TD_LINUX_32) + ADD_SUBDIRECTORY(src/linux32) +ELSEIF (TD_DARWIN_64) + ADD_SUBDIRECTORY(src/darwin64) +ELSEIF (TD_WINDOWS_64) + ADD_SUBDIRECTORY(src/windows64) +ELSEIF (TD_WINDOWS_32) + ADD_SUBDIRECTORY(src/windows32) +ENDIF () + +ADD_SUBDIRECTORY(src/detail) diff --git a/src/os/inc/os.h b/src/os/inc/os.h new file mode 100644 index 0000000000..896f3afc7a --- /dev/null +++ b/src/os/inc/os.h @@ -0,0 +1,53 @@ +/* + * 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 TDENGINE_OS_H +#define TDENGINE_OS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _TD_DARWIN_64 +#include "osDarwin64.h" +#endif + +#ifdef _TD_LINUX_64 +#include "osLinux64.h" +#endif + +#ifdef _TD_LINUX_32 +#include "osLinux32.h" +#endif + +#ifdef _TD_ALPINE +#include "osAlpine.h" +#endif + +#ifdef _TD_WINDOWS_64 +#include "osWindows64.h" +#endif + +#ifdef _TD_WINDOWS_32 +#include "osWindows32.h" +#endif + +#include "osSpec.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os/inc/osAlpine.h b/src/os/inc/osAlpine.h new file mode 100644 index 0000000000..b8212373ce --- /dev/null +++ b/src/os/inc/osAlpine.h @@ -0,0 +1,91 @@ +/* + * 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 TDENGINE_OS_LINUX64_H +#define TDENGINE_OS_LINUX64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef int(*__compar_fn_t)(const void *, const void *); +void error (int, int, const char *); +#ifndef PTHREAD_MUTEX_RECURSIVE_NP + #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os/inc/osDarwin64.h b/src/os/inc/osDarwin64.h new file mode 100644 index 0000000000..2bb0777ab8 --- /dev/null +++ b/src/os/inc/osDarwin64.h @@ -0,0 +1,277 @@ +/* + * 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 TDENGINE_PLATFORM_LINUX_H +#define TDENGINE_PLATFORM_LINUX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define htobe64 htonll + +#define taosCloseSocket(x) \ + { \ + if (FD_VALID(x)) { \ + close(x); \ + x = FD_INITIALIZER; \ + } \ + } + +#define taosWriteSocket(fd, buf, len) write(fd, buf, len) +#define taosReadSocket(fd, buf, len) read(fd, buf, len) + +#define atomic_load_8(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) +#define atomic_load_16(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) +#define atomic_load_32(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) +#define atomic_load_64(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) +#define atomic_load_ptr(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) + +#define atomic_store_8(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_store_16(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_store_32(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_store_64(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_store_ptr(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_exchange_8(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_exchange_16(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_exchange_32(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_exchange_64(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_exchange_ptr(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_val_compare_exchange_8 __sync_val_compare_and_swap +#define atomic_val_compare_exchange_16 __sync_val_compare_and_swap +#define atomic_val_compare_exchange_32 __sync_val_compare_and_swap +#define atomic_val_compare_exchange_64 __sync_val_compare_and_swap +#define atomic_val_compare_exchange_ptr __sync_val_compare_and_swap + +#define atomic_add_fetch_8(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_add_fetch_16(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_add_fetch_32(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_add_fetch_64(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_add_fetch_ptr(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_fetch_add_8(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_add_16(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_add_32(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_add_64(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_add_ptr(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_sub_fetch_8(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_sub_fetch_16(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_sub_fetch_32(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_sub_fetch_64(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_sub_fetch_ptr(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_fetch_sub_8(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_16(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_32(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_64(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_sub_ptr(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_and_fetch_8(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_and_fetch_16(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_and_fetch_32(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_and_fetch_64(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_and_fetch_ptr(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_fetch_and_8(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_and_16(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_and_32(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_and_64(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_and_ptr(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_or_fetch_8(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_or_fetch_16(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_or_fetch_32(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_or_fetch_64(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_or_fetch_ptr(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_fetch_or_8(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_or_16(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_or_32(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_or_64(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_or_ptr(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_xor_fetch_8(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_xor_fetch_16(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_xor_fetch_32(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_xor_fetch_64(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_xor_fetch_ptr(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) + +#define atomic_fetch_xor_8(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_16(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_32(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_64(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) +#define atomic_fetch_xor_ptr(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) + +#define SWAP(a, b, c) \ + do { \ + typeof(a) __tmp = (a); \ + (a) = (b); \ + (b) = __tmp; \ + } while (0) + +#define MAX(a, b) \ + ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + (__a > __b) ? __a : __b; \ + }) + +#define MIN(a, b) \ + ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + (__a < __b) ? __a : __b; \ + }) + +#define MILLISECOND_PER_SECOND ((int64_t)1000L) + +#define tsem_t dispatch_semaphore_t + +int tsem_init(dispatch_semaphore_t *sem, int pshared, unsigned int value); +int tsem_wait(dispatch_semaphore_t *sem); +int tsem_post(dispatch_semaphore_t *sem); +int tsem_destroy(dispatch_semaphore_t *sem); + +void osInit(); + +ssize_t tread(int fd, void *buf, size_t count); + +ssize_t twrite(int fd, void *buf, size_t n); + +char *taosCharsetReplace(char *charsetstr); + +bool taosCheckPthreadValid(pthread_t thread); + +void taosResetPthread(pthread_t *thread); + +int64_t taosGetPthreadId(); + +int taosSetNonblocking(int sock, int on); + +int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); + +void taosPrintOsInfo(); + +char *taosCharsetReplace(char *charsetstr); + +void taosPrintOsInfo(); + +void taosGetSystemInfo(); + +void taosKillSystem(); + +bool taosSkipSocketCheck(); + +bool taosGetDisk(); + +int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count); + +void taosSetCoreDump(); + +int tSystem(const char * cmd); + +typedef int(*__compar_fn_t)(const void *, const void *); + +// for send function in tsocket.c +#define MSG_NOSIGNAL 0 +#define SO_NO_CHECK 0x1234 +#define SOL_TCP 0x1234 +#define TCP_KEEPIDLE 0x1234 + +#ifndef PTHREAD_MUTEX_RECURSIVE_NP + #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE +#endif + +#ifndef _TD_ARM_32_ +#define BUILDIN_CLZL(val) __builtin_clzl(val) +#define BUILDIN_CTZL(val) __builtin_ctzl(val) +#else +#define BUILDIN_CLZL(val) __builtin_clzll(val) +#define BUILDIN_CTZL(val) __builtin_ctzll(val) +#endif +#define BUILDIN_CLZ(val) __builtin_clz(val) +#define BUILDIN_CTZ(val) __builtin_ctz(val) + +#undef threadlocal +#ifdef _ISOC11_SOURCE + #define threadlocal _Thread_local +#elif defined(__APPLE__) + #define threadlocal +#elif defined(__GNUC__) && !defined(threadlocal) + #define threadlocal __thread +#else + #define threadlocal +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os/inc/osLinux32.h b/src/os/inc/osLinux32.h new file mode 100644 index 0000000000..1778b0e315 --- /dev/null +++ b/src/os/inc/osLinux32.h @@ -0,0 +1,85 @@ +/* + * 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 TDENGINE_OS_LINUX64_H +#define TDENGINE_OS_LINUX64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os/inc/osLinux64.h b/src/os/inc/osLinux64.h new file mode 100644 index 0000000000..0a99f4b745 --- /dev/null +++ b/src/os/inc/osLinux64.h @@ -0,0 +1,85 @@ +/* + * 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 TDENGINE_OS_LINUX64_H +#define TDENGINE_OS_LINUX64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os/inc/osSpec.h b/src/os/inc/osSpec.h new file mode 100644 index 0000000000..b7b7bd9ff4 --- /dev/null +++ b/src/os/inc/osSpec.h @@ -0,0 +1,240 @@ +/* + * 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 TDENGINE_OS_SPEC_H +#define TDENGINE_OS_SPEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TAOS_OS_FUNC_MATH + #define SWAP(a, b, c) \ + do { \ + typeof(a) __tmp = (a); \ + (a) = (b); \ + (b) = __tmp; \ + } while (0) + + #define MAX(a, b) \ + ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + (__a > __b) ? __a : __b; \ + }) + + #define MIN(a, b) \ + ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + (__a < __b) ? __a : __b; \ + }) +#endif + +#ifndef TAOS_OS_DEF_TIME + #define MILLISECOND_PER_SECOND ((int64_t)1000L) +#endif + +#ifndef TAOS_OS_FUNC_SEMPHONE + #define tsem_t sem_t + #define tsem_init sem_init + #define tsem_wait sem_wait + #define tsem_post sem_post + #define tsem_destroy sem_destroy +#endif + +#ifndef TAOS_OS_FUNC_ATOMIC + #define atomic_load_8(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) + #define atomic_load_16(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) + #define atomic_load_32(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) + #define atomic_load_64(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) + #define atomic_load_ptr(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) + + #define atomic_store_8(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_store_16(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_store_32(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_store_64(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_store_ptr(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_exchange_8(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_exchange_16(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_exchange_32(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_exchange_64(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_exchange_ptr(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_val_compare_exchange_8 __sync_val_compare_and_swap + #define atomic_val_compare_exchange_16 __sync_val_compare_and_swap + #define atomic_val_compare_exchange_32 __sync_val_compare_and_swap + #define atomic_val_compare_exchange_64 __sync_val_compare_and_swap + #define atomic_val_compare_exchange_ptr __sync_val_compare_and_swap + + #define atomic_add_fetch_8(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_add_fetch_16(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_add_fetch_32(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_add_fetch_64(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_add_fetch_ptr(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_fetch_add_8(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_add_16(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_add_32(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_add_64(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_add_ptr(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_sub_fetch_8(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_sub_fetch_16(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_sub_fetch_32(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_sub_fetch_64(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_sub_fetch_ptr(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_fetch_sub_8(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_sub_16(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_sub_32(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_sub_64(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_sub_ptr(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_and_fetch_8(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_and_fetch_16(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_and_fetch_32(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_and_fetch_64(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_and_fetch_ptr(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_fetch_and_8(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_and_16(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_and_32(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_and_64(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_and_ptr(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_or_fetch_8(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_or_fetch_16(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_or_fetch_32(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_or_fetch_64(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_or_fetch_ptr(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_fetch_or_8(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_or_16(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_or_32(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_or_64(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_or_ptr(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_xor_fetch_8(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_xor_fetch_16(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_xor_fetch_32(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_xor_fetch_64(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_xor_fetch_ptr(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) + + #define atomic_fetch_xor_8(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_xor_16(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_xor_32(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_xor_64(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) + #define atomic_fetch_xor_ptr(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) +#endif + +ssize_t taosTReadImp(int fd, void *buf, size_t count); +ssize_t taosTWriteImp(int fd, void *buf, size_t count); +ssize_t taosTSendFileImp(int dfd, int sfd, off_t *offset, size_t size); +#ifndef TAOS_OS_FUNC_FILE + #define taosTRead(fd, buf, count) taosTReadImp(fd, buf, count) + #define taosTWrite(fd, buf, count) taosTWriteImp(fd, buf, count) + #define taosLSeek(fd, offset, whence) lseek(fd, offset, whence) + #define taosTSendFile(dfd, sfd, offset, size) taosTSendFileImp(dfd, sfd, offset, size) +#endif + +#ifdef TAOS_RANDOM_FILE_FAIL + void taosSetRandomFileFailFactor(int factor); + void taosSetRandomFileFailOutput(const char *path); + ssize_t taosReadFileRandomFail(int fd, void *buf, size_t count, const char *file, uint32_t line); + ssize_t taosWriteFileRandomFail(int fd, void *buf, size_t count, const char *file, uint32_t line); + off_t taosLSeekRandomFail(int fd, off_t offset, int whence, const char *file, uint32_t line); + #define taosTRead(fd, buf, count) taosReadFileRandomFail(fd, buf, count, __FILE__, __LINE__) + #define taosTWrite(fd, buf, count) taosWriteFileRandomFail(fd, buf, count, __FILE__, __LINE__) + #define taosLSeek(fd, offset, whence) taosLSeekRandomFail(fd, offset, whence, __FILE__, __LINE__) +#endif + +#ifndef TAOS_OS_FUNC_NETWORK + #define taosSend(sockfd, buf, len, flags) send(sockfd, buf, len, flags) + #define taosSendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto(sockfd, buf, len, flags, dest_addr, addrlen) + #define taosReadSocket(fd, buf, len) read(fd, buf, len) + #define taosWriteSocket(fd, buf, len) write(fd, buf, len) + #define taosCloseSocket(x) \ + { \ + if (FD_VALID(x)) { \ + close(x); \ + x = FD_INITIALIZER; \ + } \ + } +#endif + +#ifdef TAOS_RANDOM_NETWORK_FAIL + ssize_t taosSendRandomFail(int sockfd, const void *buf, size_t len, int flags); + ssize_t taosSendToRandomFail(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); + ssize_t taosReadSocketRandomFail(int fd, void *buf, size_t count); + ssize_t taosWriteSocketRandomFail(int fd, const void *buf, size_t count); + #define taosSend(sockfd, buf, len, flags) taosSendRandomFail(sockfd, buf, len, flags) + #define taosSendto(sockfd, buf, len, flags, dest_addr, addrlen) taosSendToRandomFail(sockfd, buf, len, flags, dest_addr, addrlen) + #define taosReadSocket(fd, buf, len) taosReadSocketRandomFail(fd, buf, len) + #define taosWriteSocket(fd, buf, len) taosWriteSocketRandomFail(fd, buf, len) +#endif + +#ifndef TAOS_OS_FUNC_LZ4 + #define BUILDIN_CLZL(val) __builtin_clzl(val) + #define BUILDIN_CTZL(val) __builtin_ctzl(val) + #define BUILDIN_CLZ(val) __builtin_clz(val) + #define BUILDIN_CTZ(val) __builtin_ctz(val) +#endif + +#undef threadlocal +#ifdef _ISOC11_SOURCE + #define threadlocal _Thread_local +#elif defined(__APPLE__) + #define threadlocal +#elif defined(__GNUC__) && !defined(threadlocal) + #define threadlocal __thread +#else + #define threadlocal +#endif + +void osInit(); + +// TAOS_OS_FUNC_PTHREAD +bool taosCheckPthreadValid(pthread_t thread); +int64_t taosGetPthreadId(); + +// TAOS_OS_FUNC_SOCKET +int taosSetNonblocking(int sock, int on); +int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); +void taosBlockSIGPIPE(); + +// TAOS_OS_FUNC_SYSINFO +void taosGetSystemInfo(); +void taosPrintOsInfo(); +void taosKillSystem(); +int tSystem(const char * cmd) ; + +// TAOS_OS_FUNC_CORE +void taosSetCoreDump(); + +// TAOS_OS_FUNC_UTIL +int64_t tsosStr2int64(char *str); + +// TAOS_OS_FUNC_TIMER +void taosMsleep(int mseconds); +int taosInitTimer(void (*callback)(int), int ms); +void taosUninitTimer(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/os/inc/osWindows32.h b/src/os/inc/osWindows32.h new file mode 100644 index 0000000000..4744d4beb5 --- /dev/null +++ b/src/os/inc/osWindows32.h @@ -0,0 +1,54 @@ +/* +* 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 TDENGINE_PLATFORM_WINDOWS32_H +#define TDENGINE_PLATFORM_WINDOWS32_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "winsock2.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/os/inc/osWindows64.h b/src/os/inc/osWindows64.h new file mode 100644 index 0000000000..8fd41fb2fd --- /dev/null +++ b/src/os/inc/osWindows64.h @@ -0,0 +1,423 @@ +/* +* 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 TDENGINE_PLATFORM_WINDOWS_H +#define TDENGINE_PLATFORM_WINDOWS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "winsock2.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// for function open in stat.h +#define S_IRWXU _S_IREAD +#define S_IRWXG _S_IWRITE +#define S_IRWXO _S_IWRITE + +// for access function in io.h +#define F_OK 00 //Existence only +#define W_OK 02 //Write - only +#define R_OK 04 //Read - only +#define X_OK 06 //Read and write + +// for send function in tsocket.c +#define MSG_NOSIGNAL 0 +#define SO_NO_CHECK 0x1234 +#define SOL_TCP 0x1234 +#define TCP_KEEPCNT 0x1234 +#define TCP_KEEPIDLE 0x1234 +#define TCP_KEEPINTVL 0x1234 + +#define LOCK_EX 1 +#define LOCK_NB 2 +#define LOCK_UN 3 + +#define bzero(ptr, size) memset((ptr), 0, (size)) +#define mkdir(pathname, mode) _mkdir(pathname) +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define wcsncasecmp _wcsnicmp +#define strtok_r strtok_s +#ifdef _TD_GO_DLL_ + int64_t tsosStr2int64(char *str); + uint64_t htonll(uint64_t val); +#else + #define tsosStr2int64 _atoi64 +#endif + +#define snprintf _snprintf +#define in_addr_t unsigned long +#define socklen_t int +#define htobe64 htonll +#define twrite write + +#ifndef PATH_MAX + #define PATH_MAX 256 +#endif + +#define taosCloseSocket(fd) closesocket(fd) +#define taosWriteSocket(fd, buf, len) send(fd, buf, len, 0) +#define taosReadSocket(fd, buf, len) recv(fd, buf, len, 0) + +#if defined(_M_ARM) || defined(_M_ARM64) + +/* the '__iso_volatile' functions does not use a memory fence, so these + * definitions are incorrect, comment out as we don't support Windows on + * ARM at present. + +#define atomic_load_8(ptr) __iso_volatile_load8((const volatile __int8*)(ptr)) +#define atomic_load_16(ptr) __iso_volatile_load16((const volatile __int16*)(ptr)) +#define atomic_load_32(ptr) __iso_volatile_load32((const volatile __int32*)(ptr)) +#define atomic_load_64(ptr) __iso_volatile_load64((const volatile __int64*)(ptr)) + +#define atomic_store_8(ptr, val) __iso_volatile_store8((volatile __int8*)(ptr), (__int8)(val)) +#define atomic_store_16(ptr, val) __iso_volatile_store16((volatile __int16*)(ptr), (__int16)(val)) +#define atomic_store_32(ptr, val) __iso_volatile_store32((volatile __int32*)(ptr), (__int32)(val)) +#define atomic_store_64(ptr, val) __iso_volatile_store64((volatile __int64*)(ptr), (__int64)(val)) + +#ifdef _M_ARM64 +#define atomic_load_ptr atomic_load_64 +#define atomic_store_ptr atomic_store_64 +#else +#define atomic_load_ptr atomic_load_32 +#define atomic_store_ptr atomic_store_32 +#endif +*/ +#else + +#define atomic_load_8(ptr) (*(char volatile*)(ptr)) +#define atomic_load_16(ptr) (*(short volatile*)(ptr)) +#define atomic_load_32(ptr) (*(long volatile*)(ptr)) +#define atomic_load_64(ptr) (*(__int64 volatile*)(ptr)) +#define atomic_load_ptr(ptr) (*(void* volatile*)(ptr)) + +#define atomic_store_8(ptr, val) ((*(char volatile*)(ptr)) = (char)(val)) +#define atomic_store_16(ptr, val) ((*(short volatile*)(ptr)) = (short)(val)) +#define atomic_store_32(ptr, val) ((*(long volatile*)(ptr)) = (long)(val)) +#define atomic_store_64(ptr, val) ((*(__int64 volatile*)(ptr)) = (__int64)(val)) +#define atomic_store_ptr(ptr, val) ((*(void* volatile*)(ptr)) = (void*)(val)) + +#endif + +#define atomic_exchange_8(ptr, val) _InterlockedExchange8((char volatile*)(ptr), (char)(val)) +#define atomic_exchange_16(ptr, val) _InterlockedExchange16((short volatile*)(ptr), (short)(val)) +#define atomic_exchange_32(ptr, val) _InterlockedExchange((long volatile*)(ptr), (long)(val)) +#define atomic_exchange_64(ptr, val) _InterlockedExchange64((__int64 volatile*)(ptr), (__int64)(val)) +#define atomic_exchange_ptr(ptr, val) _InterlockedExchangePointer((void* volatile*)(ptr), (void*)(val)) + +#ifdef _TD_GO_DLL_ + #define atomic_val_compare_exchange_8 __sync_val_compare_and_swap +#else + #define atomic_val_compare_exchange_8(ptr, oldval, newval) _InterlockedCompareExchange8((char volatile*)(ptr), (char)(newval), (char)(oldval)) +#endif + +#define atomic_val_compare_exchange_16(ptr, oldval, newval) _InterlockedCompareExchange16((short volatile*)(ptr), (short)(newval), (short)(oldval)) +#define atomic_val_compare_exchange_32(ptr, oldval, newval) _InterlockedCompareExchange((long volatile*)(ptr), (long)(newval), (long)(oldval)) +#define atomic_val_compare_exchange_64(ptr, oldval, newval) _InterlockedCompareExchange64((__int64 volatile*)(ptr), (__int64)(newval), (__int64)(oldval)) +#define atomic_val_compare_exchange_ptr(ptr, oldval, newval) _InterlockedCompareExchangePointer((void* volatile*)(ptr), (void*)(newval), (void*)(oldval)) + +char interlocked_add_fetch_8(char volatile *ptr, char val); +short interlocked_add_fetch_16(short volatile *ptr, short val); +long interlocked_add_fetch_32(long volatile *ptr, long val); +__int64 interlocked_add_fetch_64(__int64 volatile *ptr, __int64 val); + +#define atomic_add_fetch_8(ptr, val) interlocked_add_fetch_8((char volatile*)(ptr), (char)(val)) +#define atomic_add_fetch_16(ptr, val) interlocked_add_fetch_16((short volatile*)(ptr), (short)(val)) +#define atomic_add_fetch_32(ptr, val) interlocked_add_fetch_32((long volatile*)(ptr), (long)(val)) +#define atomic_add_fetch_64(ptr, val) interlocked_add_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) +#ifdef _WIN64 + #define atomic_add_fetch_ptr atomic_add_fetch_64 +#else + #define atomic_add_fetch_ptr atomic_add_fetch_32 +#endif +#ifdef _TD_GO_DLL_ + #define atomic_fetch_add_8 __sync_fetch_and_ad + #define atomic_fetch_add_16 __sync_fetch_and_add +#else + #define atomic_fetch_add_8(ptr, val) _InterlockedExchangeAdd8((char volatile*)(ptr), (char)(val)) + #define atomic_fetch_add_16(ptr, val) _InterlockedExchangeAdd16((short volatile*)(ptr), (short)(val)) +#endif + +#define atomic_fetch_add_32(ptr, val) _InterlockedExchangeAdd((long volatile*)(ptr), (long)(val)) +#define atomic_fetch_add_64(ptr, val) _InterlockedExchangeAdd64((__int64 volatile*)(ptr), (__int64)(val)) +#ifdef _WIN64 + #define atomic_fetch_add_ptr atomic_fetch_add_64 +#else + #define atomic_fetch_add_ptr atomic_fetch_add_32 +#endif + +#define atomic_sub_fetch_8(ptr, val) interlocked_add_fetch_8((char volatile*)(ptr), -(char)(val)) +#define atomic_sub_fetch_16(ptr, val) interlocked_add_fetch_16((short volatile*)(ptr), -(short)(val)) +#define atomic_sub_fetch_32(ptr, val) interlocked_add_fetch_32((long volatile*)(ptr), -(long)(val)) +#define atomic_sub_fetch_64(ptr, val) interlocked_add_fetch_64((__int64 volatile*)(ptr), -(__int64)(val)) +#ifdef _WIN64 + #define atomic_sub_fetch_ptr atomic_sub_fetch_64 +#else + #define atomic_sub_fetch_ptr atomic_sub_fetch_32 +#endif + +#define atomic_fetch_sub_8(ptr, val) _InterlockedExchangeAdd8((char volatile*)(ptr), -(char)(val)) +#define atomic_fetch_sub_16(ptr, val) _InterlockedExchangeAdd16((short volatile*)(ptr), -(short)(val)) +#define atomic_fetch_sub_32(ptr, val) _InterlockedExchangeAdd((long volatile*)(ptr), -(long)(val)) +#define atomic_fetch_sub_64(ptr, val) _InterlockedExchangeAdd64((__int64 volatile*)(ptr), -(__int64)(val)) +#ifdef _WIN64 + #define atomic_fetch_sub_ptr atomic_fetch_sub_64 +#else + #define atomic_fetch_sub_ptr atomic_fetch_sub_32 +#endif +#ifndef _TD_GO_DLL_ + char interlocked_and_fetch_8(char volatile* ptr, char val); + short interlocked_and_fetch_16(short volatile* ptr, short val); +#endif +long interlocked_and_fetch_32(long volatile* ptr, long val); +__int64 interlocked_and_fetch_64(__int64 volatile* ptr, __int64 val); + +#ifndef _TD_GO_DLL_ + #define atomic_and_fetch_8(ptr, val) interlocked_and_fetch_8((char volatile*)(ptr), (char)(val)) + #define atomic_and_fetch_16(ptr, val) interlocked_and_fetch_16((short volatile*)(ptr), (short)(val)) +#endif +#define atomic_and_fetch_32(ptr, val) interlocked_and_fetch_32((long volatile*)(ptr), (long)(val)) +#define atomic_and_fetch_64(ptr, val) interlocked_and_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) +#ifdef _WIN64 + #define atomic_and_fetch_ptr atomic_and_fetch_64 +#else + #define atomic_and_fetch_ptr atomic_and_fetch_32 +#endif +#ifndef _TD_GO_DLL_ + #define atomic_fetch_and_8(ptr, val) _InterlockedAnd8((char volatile*)(ptr), (char)(val)) + #define atomic_fetch_and_16(ptr, val) _InterlockedAnd16((short volatile*)(ptr), (short)(val)) +#endif +#define atomic_fetch_and_32(ptr, val) _InterlockedAnd((long volatile*)(ptr), (long)(val)) + +#ifdef _M_IX86 + __int64 interlocked_fetch_and_64(__int64 volatile* ptr, __int64 val); + #define atomic_fetch_and_64(ptr, val) interlocked_fetch_and_64((__int64 volatile*)(ptr), (__int64)(val)) +#else + #define atomic_fetch_and_64(ptr, val) _InterlockedAnd64((__int64 volatile*)(ptr), (__int64)(val)) +#endif + +#ifdef _WIN64 + #define atomic_fetch_and_ptr atomic_fetch_and_64 +#else + #define atomic_fetch_and_ptr atomic_fetch_and_32 +#endif +#ifndef _TD_GO_DLL_ + char interlocked_or_fetch_8(char volatile* ptr, char val); + short interlocked_or_fetch_16(short volatile* ptr, short val); +#endif +long interlocked_or_fetch_32(long volatile* ptr, long val); +__int64 interlocked_or_fetch_64(__int64 volatile* ptr, __int64 val); + +#ifndef _TD_GO_DLL_ + #define atomic_or_fetch_8(ptr, val) interlocked_or_fetch_8((char volatile*)(ptr), (char)(val)) + #define atomic_or_fetch_16(ptr, val) interlocked_or_fetch_16((short volatile*)(ptr), (short)(val)) +#endif +#define atomic_or_fetch_32(ptr, val) interlocked_or_fetch_32((long volatile*)(ptr), (long)(val)) +#define atomic_or_fetch_64(ptr, val) interlocked_or_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) +#ifdef _WIN64 + #define atomic_or_fetch_ptr atomic_or_fetch_64 +#else + #define atomic_or_fetch_ptr atomic_or_fetch_32 +#endif +#ifndef _TD_GO_DLL_ + #define atomic_fetch_or_8(ptr, val) _InterlockedOr8((char volatile*)(ptr), (char)(val)) + #define atomic_fetch_or_16(ptr, val) _InterlockedOr16((short volatile*)(ptr), (short)(val)) +#endif +#define atomic_fetch_or_32(ptr, val) _InterlockedOr((long volatile*)(ptr), (long)(val)) + +#ifdef _M_IX86 + __int64 interlocked_fetch_or_64(__int64 volatile* ptr, __int64 val); + #define atomic_fetch_or_64(ptr, val) interlocked_fetch_or_64((__int64 volatile*)(ptr), (__int64)(val)) +#else + #define atomic_fetch_or_64(ptr, val) _InterlockedOr64((__int64 volatile*)(ptr), (__int64)(val)) +#endif + +#ifdef _WIN64 + #define atomic_fetch_or_ptr atomic_fetch_or_64 +#else + #define atomic_fetch_or_ptr atomic_fetch_or_32 +#endif + +#ifndef _TD_GO_DLL_ + char interlocked_xor_fetch_8(char volatile* ptr, char val); + short interlocked_xor_fetch_16(short volatile* ptr, short val); +#endif +long interlocked_xor_fetch_32(long volatile* ptr, long val); +__int64 interlocked_xor_fetch_64(__int64 volatile* ptr, __int64 val); + +#ifndef _TD_GO_DLL_ + #define atomic_xor_fetch_8(ptr, val) interlocked_xor_fetch_8((char volatile*)(ptr), (char)(val)) + #define atomic_xor_fetch_16(ptr, val) interlocked_xor_fetch_16((short volatile*)(ptr), (short)(val)) +#endif +#define atomic_xor_fetch_32(ptr, val) interlocked_xor_fetch_32((long volatile*)(ptr), (long)(val)) +#define atomic_xor_fetch_64(ptr, val) interlocked_xor_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) +#ifdef _WIN64 + #define atomic_xor_fetch_ptr atomic_xor_fetch_64 +#else + #define atomic_xor_fetch_ptr atomic_xor_fetch_32 +#endif + +#ifndef _TD_GO_DLL_ + #define atomic_fetch_xor_8(ptr, val) _InterlockedXor8((char volatile*)(ptr), (char)(val)) + #define atomic_fetch_xor_16(ptr, val) _InterlockedXor16((short volatile*)(ptr), (short)(val)) +#endif +#define atomic_fetch_xor_32(ptr, val) _InterlockedXor((long volatile*)(ptr), (long)(val)) + +#ifdef _M_IX86 + __int64 interlocked_fetch_xor_64(__int64 volatile* ptr, __int64 val); + #define atomic_fetch_xor_64(ptr, val) interlocked_fetch_xor_64((__int64 volatile*)(ptr), (__int64)(val)) +#else + #define atomic_fetch_xor_64(ptr, val) _InterlockedXor64((__int64 volatile*)(ptr), (__int64)(val)) +#endif + +#ifdef _WIN64 + #define atomic_fetch_xor_ptr atomic_fetch_xor_64 +#else + #define atomic_fetch_xor_ptr atomic_fetch_xor_32 +#endif + +#define SWAP(a, b, c) \ + do { \ + c __tmp = (c)(a); \ + (a) = (c)(b); \ + (b) = __tmp; \ + } while (0) + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#ifdef _TD_GO_DLL_ + #define MILLISECOND_PER_SECOND (1000LL) +#else + #define MILLISECOND_PER_SECOND (1000i64) +#endif + +#define tsem_t sem_t +#define tsem_init sem_init +#define tsem_wait sem_wait +#define tsem_post sem_post +#define tsem_destroy sem_destroy + +void osInit(); + +int getline(char **lineptr, size_t *n, FILE *stream); + +int taosWinSetTimer(int ms, void(*callback)(int)); + +int gettimeofday(struct timeval *tv, struct timezone *tz); + +struct tm *localtime_r(const time_t *timep, struct tm *result); + +char *strptime(const char *buf, const char *fmt, struct tm *tm); + +bool taosCheckPthreadValid(pthread_t thread); + +void taosResetPthread(pthread_t *thread); + +int64_t taosGetPthreadId(); + +int taosSetNonblocking(int sock, int on); + +int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); + +char *taosCharsetReplace(char *charsetstr); + +void taosPrintOsInfo(); + +void taosGetSystemInfo(); + +void taosKillSystem(); + +int32_t BUILDIN_CLZL(uint64_t val); +int32_t BUILDIN_CLZ(uint32_t val); +int32_t BUILDIN_CTZL(uint64_t val); +int32_t BUILDIN_CTZ(uint32_t val); + +//for signal, not dispose +#define SIGALRM 1234 +typedef int sigset_t; + +struct sigaction { + void (*sa_handler)(int); +}; + +typedef struct { + int we_wordc; + char **we_wordv; + int we_offs; + char wordPos[20]; +} wordexp_t; + +int wordexp(const char *words, wordexp_t *pwordexp, int flags); + +void wordfree(wordexp_t *pwordexp); + +int flock(int fd, int option); + +int fsync(int filedes); + +char *getpass(const char *prefix); + +char *strsep(char **stringp, const char *delim); + +typedef int(*__compar_fn_t)(const void *, const void *); + +int sigaction(int, struct sigaction *, void *); + +void sleep(int mseconds); + +bool taosSkipSocketCheck(); + +int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count); + +#define ssize_t int + +#define strdup _strdup + +char *strndup(const char *s, size_t n); + +void taosSetCoreDump(); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/os/src/alpine/CMakeLists.txt b/src/os/src/alpine/CMakeLists.txt new file mode 100644 index 0000000000..79cbf917e2 --- /dev/null +++ b/src/os/src/alpine/CMakeLists.txt @@ -0,0 +1,12 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +AUX_SOURCE_DIRECTORY(. SRC) + +ADD_LIBRARY(os ${SRC}) +TARGET_LINK_LIBRARIES(os m rt) + diff --git a/src/os/src/alpine/alpineEnv.c b/src/os/src/alpine/alpineEnv.c new file mode 100644 index 0000000000..0a9d81311a --- /dev/null +++ b/src/os/src/alpine/alpineEnv.c @@ -0,0 +1,30 @@ +/* + * 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 "tglobal.h" +#include "tulog.h" + +void osInit() { + strcpy(configDir, "/etc/taos"); + strcpy(tsVnodeDir, ""); + strcpy(tsDnodeDir, ""); + strcpy(tsMnodeDir, ""); + strcpy(tsDataDir, "/var/lib/taos"); + strcpy(tsLogDir, "/var/log/taos"); + strcpy(tsScriptDir, "/etc/taos"); + strcpy(tsOsName, "Linux"); +} \ No newline at end of file diff --git a/src/os/src/darwin64/CMakeLists.txt b/src/os/src/darwin64/CMakeLists.txt new file mode 100644 index 0000000000..71029d9291 --- /dev/null +++ b/src/os/src/darwin64/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_DARWIN_64) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) + INCLUDE_DIRECTORIES(inc) + AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(os ${SRC}) +ENDIF () + diff --git a/src/os/src/darwin64/darwinEnv.c b/src/os/src/darwin64/darwinEnv.c new file mode 100644 index 0000000000..27d5a7c99b --- /dev/null +++ b/src/os/src/darwin64/darwinEnv.c @@ -0,0 +1,30 @@ +/* + * 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 "tglobal.h" +#include "tulog.h" + +void osInit() { + strcpy(configDir, "/etc/taos"); + strcpy(tsVnodeDir, ""); + strcpy(tsDnodeDir, ""); + strcpy(tsMnodeDir, ""); + strcpy(tsDataDir, "/var/lib/taos"); + strcpy(tsLogDir, "~/TDengineLog"); + strcpy(tsScriptDir, "/etc/taos"); + strcpy(tsOsName, "Darwin"); +} diff --git a/src/os/src/darwin64/darwinPlatform.c b/src/os/src/darwin64/darwinPlatform.c new file mode 100644 index 0000000000..045e4a7099 --- /dev/null +++ b/src/os/src/darwin64/darwinPlatform.c @@ -0,0 +1,370 @@ +/* + * 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 "os.h" +#include "taosdef.h" +#include "tglobal.h" +#include "tconfig.h" +#include "ttimer.h" +#include "tulog.h" +#include "tutil.h" + +int64_t tsosStr2int64(char *str) { + char *endptr = NULL; + return strtoll(str, &endptr, 10); +} + +/* + to make taosMsleep work, + signal SIGALRM shall be blocked in the calling thread, + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGALRM); + pthread_sigmask(SIG_BLOCK, &set, NULL); +*/ +void taosMsleep(int mseconds) { + struct timeval timeout; + int seconds, useconds; + + seconds = mseconds / 1000; + useconds = (mseconds % 1000) * 1000; + timeout.tv_sec = seconds; + timeout.tv_usec = useconds; + + /* sigset_t set; */ + /* sigemptyset(&set); */ + /* sigaddset(&set, SIGALRM); */ + /* pthread_sigmask(SIG_BLOCK, &set, NULL); */ + + select(0, NULL, NULL, NULL, &timeout); + + /* pthread_sigmask(SIG_UNBLOCK, &set, NULL); */ +} + +bool taosCheckPthreadValid(pthread_t thread) { return thread != 0; } + +void taosResetPthread(pthread_t *thread) { *thread = 0; } + +int64_t taosGetPthreadId() { return (int64_t)pthread_self(); } + +/* +* Function to get the private ip address of current machine. If get IP +* successfully, return 0, else, return -1. The return values is ip. +* +* Use: +* if (taosGetPrivateIp(ip) != 0) { +* perror("Fail to get private IP address\n"); +* exit(EXIT_FAILURE); +* } +*/ +int taosGetPrivateIp(char *const ip) { + bool hasLoCard = false; + + struct ifaddrs *ifaddr, *ifa; + int family, s; + char host[NI_MAXHOST]; + + if (getifaddrs(&ifaddr) == -1) { + return -1; + } + + /* Walk through linked list, maintaining head pointer so we can free list later */ + int flag = 0; + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) continue; + + family = ifa->ifa_addr->sa_family; + if (strcmp("lo", ifa->ifa_name) == 0) { + hasLoCard = true; + continue; + } + + if (family == AF_INET) { + /* printf("%-8s", ifa->ifa_name); */ + s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), + host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (s != 0) { + freeifaddrs(ifaddr); + return -1; + } + + strcpy(ip, host); + flag = 1; + break; + } + } + + freeifaddrs(ifaddr); + if (flag) { + return 0; + } else { + if (hasLoCard) { + uInfo("no net card was found, use lo:127.0.0.1 as default"); + strcpy(ip, "127.0.0.1"); + return 0; + } + return -1; + } +} + +int taosSetNonblocking(int sock, int on) { + int flags = 0; + if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { + uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); + return 1; + } + + if (on) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + + if ((flags = fcntl(sock, F_SETFL, flags)) < 0) { + uError("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno)); + return 1; + } + + return 0; +} + +int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { + if (level == SOL_SOCKET && optname == SO_SNDBUF) { + return 0; + } + + if (level == SOL_SOCKET && optname == SO_RCVBUF) { + return 0; + } + + return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); +} + +int taosInitTimer(void (*callback)(int), int ms) { + signal(SIGALRM, callback); + + struct itimerval tv; + tv.it_interval.tv_sec = 0; /* my timer resolution */ + tv.it_interval.tv_usec = 1000 * ms; // resolution is in msecond + tv.it_value = tv.it_interval; + + setitimer(ITIMER_REAL, &tv, NULL); + + return 0; +} + +void taosUninitTimer() { + struct itimerval tv = { 0 }; + setitimer(ITIMER_REAL, &tv, NULL); +} + +void taosGetSystemTimezone() { + // get and set default timezone + SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone"); + if (cfg_timezone && cfg_timezone->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + char *tz = getenv("TZ"); + if (tz == NULL || strlen(tz) == 0) { + strcpy(tsTimezone, "not configured"); + } + else { + strcpy(tsTimezone, tz); + } + cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("timezone not configured, use default"); + } +} + +void taosGetSystemLocale() { + // get and set default locale + SGlobalCfg *cfg_locale = taosGetConfigOption("locale"); + if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + char *locale = setlocale(LC_CTYPE, "chs"); + if (locale != NULL) { + tstrncpy(tsLocale, locale, sizeof(tsLocale)); + cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("locale not configured, set to default:%s", tsLocale); + } + } + + SGlobalCfg *cfg_charset = taosGetConfigOption("charset"); + if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + strcpy(tsCharset, "cp936"); + cfg_charset->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("charset not configured, set to default:%s", tsCharset); + } +} + + +void taosPrintOsInfo() {} + +void taosKillSystem() { + uError("function taosKillSystem, exit!"); + exit(0); +} + +bool taosGetDisk() { + return true; +} + +void taosGetSystemInfo() { + taosGetSystemTimezone(); + taosGetSystemLocale(); +} + +void *taosInitTcpClient(char *ip, uint16_t port, char *flabel, int num, void *fp, void *shandle) { + uError("function taosInitTcpClient is not implemented in darwin system, exit!"); + exit(0); +} + +void taosCloseTcpClientConnection(void *chandle) { + uError("function taosCloseTcpClientConnection is not implemented in darwin system, exit!"); + exit(0); +} + +void *taosOpenTcpClientConnection(void *shandle, void *thandle, char *ip, uint16_t port) { + uError("function taosOpenTcpClientConnection is not implemented in darwin system, exit!"); + exit(0); +} + +int taosSendTcpClientData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { + uError("function taosSendTcpClientData is not implemented in darwin system, exit!"); + exit(0); +} + +void taosCleanUpTcpClient(void *chandle) { + uError("function taosCleanUpTcpClient is not implemented in darwin system, exit!"); + exit(0); +} + +void taosCloseTcpServerConnection(void *chandle) { + uError("function taosCloseTcpServerConnection is not implemented in darwin system, exit!"); + exit(0); +} + +void taosCleanUpTcpServer(void *handle) { + uError("function taosCleanUpTcpServer is not implemented in darwin system, exit!"); + exit(0); +} + +void *taosInitTcpServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) { + uError("function taosInitTcpServer is not implemented in darwin system, exit!"); + exit(0); +} + +int taosSendTcpServerData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { + uError("function taosSendTcpServerData is not implemented in darwin system, exit!"); + exit(0); +} + +void taosFreeMsgHdr(void *hdr) { + uError("function taosFreeMsgHdr is not implemented in darwin system, exit!"); + exit(0); +} + +int taosMsgHdrSize(void *hdr) { + uError("function taosMsgHdrSize is not implemented in darwin system, exit!"); + exit(0); +} + +void taosSendMsgHdr(void *hdr, int fd) { + uError("function taosSendMsgHdr is not implemented in darwin system, exit!"); + exit(0); +} + +void taosInitMsgHdr(void **hdr, void *dest, int maxPkts) { + uError("function taosInitMsgHdr is not implemented in darwin system, exit!"); + exit(0); +} + +void taosSetMsgHdrData(void *hdr, char *data, int dataLen) { + uError("function taosSetMsgHdrData is not implemented in darwin system, exit!"); + exit(0); +} + +bool taosSkipSocketCheck() { + return true; +} + +int tsem_init(dispatch_semaphore_t *sem, int pshared, unsigned int value) { + *sem = dispatch_semaphore_create(value); + if (*sem == NULL) { + return -1; + } else { + return 0; + } +} + +int tsem_wait(dispatch_semaphore_t *sem) { + dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER); + return 0; +} + +int tsem_post(dispatch_semaphore_t *sem) { + dispatch_semaphore_signal(*sem); + return 0; +} + +int tsem_destroy(dispatch_semaphore_t *sem) { + return 0; +} + +int32_t __sync_val_load_32(int32_t *ptr) { + return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); +} + +void __sync_val_restore_32(int32_t *ptr, int32_t newval) { + __atomic_store_n(ptr, newval, __ATOMIC_RELEASE); +} + +#define _SEND_FILE_STEP_ 1000 + +int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count) { + fseek(in_file, (int32_t)(*offset), 0); + int writeLen = 0; + uint8_t buffer[_SEND_FILE_STEP_] = { 0 }; + + for (int len = 0; len < (count - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) { + size_t rlen = fread(buffer, 1, _SEND_FILE_STEP_, in_file); + if (rlen <= 0) { + return writeLen; + } + else if (rlen < _SEND_FILE_STEP_) { + fwrite(buffer, 1, rlen, out_file); + return (int)(writeLen + rlen); + } + else { + fwrite(buffer, 1, _SEND_FILE_STEP_, in_file); + writeLen += _SEND_FILE_STEP_; + } + } + + int remain = count - writeLen; + if (remain > 0) { + size_t rlen = fread(buffer, 1, remain, in_file); + if (rlen <= 0) { + return writeLen; + } + else { + fwrite(buffer, 1, remain, out_file); + writeLen += remain; + } + } + + return writeLen; +} + +void taosSetCoreDump() {} diff --git a/src/os/src/detail/CMakeLists.txt b/src/os/src/detail/CMakeLists.txt new file mode 100644 index 0000000000..5902a9356b --- /dev/null +++ b/src/os/src/detail/CMakeLists.txt @@ -0,0 +1,14 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +INCLUDE_DIRECTORIES(.) +AUX_SOURCE_DIRECTORY(. SRC) +SET_SOURCE_FILES_PROPERTIES(osSysinfo.c PROPERTIES COMPILE_FLAGS -w) +SET_SOURCE_FILES_PROPERTIES(osCoredump.c PROPERTIES COMPILE_FLAGS -w) + +ADD_LIBRARY(osdetail ${SRC}) +TARGET_LINK_LIBRARIES(osdetail os) diff --git a/src/os/src/detail/osCoredump.c b/src/os/src/detail/osCoredump.c new file mode 100644 index 0000000000..fe97000c7d --- /dev/null +++ b/src/os/src/detail/osCoredump.c @@ -0,0 +1,98 @@ +/* + * 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 "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tutil.h" +#include "tsystem.h" + +#ifndef TAOS_OS_FUNC_CORE + +int _sysctl(struct __sysctl_args *args ); + +void taosSetCoreDump() { + if (0 == tsEnableCoreFile) { + return; + } + + // 1. set ulimit -c unlimited + struct rlimit rlim; + struct rlimit rlim_new; + if (getrlimit(RLIMIT_CORE, &rlim) == 0) { + uInfo("the old unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max); + rlim_new.rlim_cur = RLIM_INFINITY; + rlim_new.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) { + uInfo("set unlimited fail, error: %s", strerror(errno)); + rlim_new.rlim_cur = rlim.rlim_max; + rlim_new.rlim_max = rlim.rlim_max; + (void)setrlimit(RLIMIT_CORE, &rlim_new); + } + } + + if (getrlimit(RLIMIT_CORE, &rlim) == 0) { + uInfo("the new unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max); + } + +#ifndef _TD_ARM_ + // 2. set the path for saving core file + struct __sysctl_args args; + int old_usespid = 0; + size_t old_len = 0; + int new_usespid = 1; + size_t new_len = sizeof(new_usespid); + + int name[] = {CTL_KERN, KERN_CORE_USES_PID}; + + memset(&args, 0, sizeof(struct __sysctl_args)); + args.name = name; + args.nlen = sizeof(name)/sizeof(name[0]); + args.oldval = &old_usespid; + args.oldlenp = &old_len; + args.newval = &new_usespid; + args.newlen = new_len; + + old_len = sizeof(old_usespid); + + if (syscall(SYS__sysctl, &args) == -1) { + uInfo("_sysctl(kern_core_uses_pid) set fail: %s", strerror(errno)); + } + + uInfo("The old core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid); + + + old_usespid = 0; + old_len = 0; + memset(&args, 0, sizeof(struct __sysctl_args)); + args.name = name; + args.nlen = sizeof(name)/sizeof(name[0]); + args.oldval = &old_usespid; + args.oldlenp = &old_len; + + old_len = sizeof(old_usespid); + + if (syscall(SYS__sysctl, &args) == -1) { + uInfo("_sysctl(kern_core_uses_pid) get fail: %s", strerror(errno)); + } + + uInfo("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid); +#endif + +} + +#endif \ No newline at end of file diff --git a/src/os/src/detail/osFail.c b/src/os/src/detail/osFail.c new file mode 100644 index 0000000000..e0eb200851 --- /dev/null +++ b/src/os/src/detail/osFail.c @@ -0,0 +1,141 @@ +/* + * 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" + +#define RANDOM_NETWORK_FAIL_FACTOR 20 + +#ifdef TAOS_RANDOM_NETWORK_FAIL + +ssize_t taosSendRandomFail(int sockfd, const void *buf, size_t len, int flags) { + if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { + errno = ECONNRESET; + return -1; + } + + return send(sockfd, buf, len, flags); +} + +ssize_t taosSendToRandomFail(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, + socklen_t addrlen) { + if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { + errno = ECONNRESET; + return -1; + } + + return sendto(sockfd, buf, len, flags, dest_addr, addrlen); +} + +ssize_t taosReadSocketRandomFail(int fd, void *buf, size_t count) { + if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { + errno = ECONNRESET; + return -1; + } + + return read(fd, buf, count); +} + +ssize_t taosWriteSocketRandomFail(int fd, const void *buf, size_t count) { + if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { + errno = EINTR; + return -1; + } + + return write(fd, buf, count); +} + +#endif //TAOS_RANDOM_NETWORK_FAIL + +#ifdef TAOS_RANDOM_FILE_FAIL + +static int random_file_fail_factor = 20; +static FILE *fpRandomFileFailOutput = NULL; + +void taosSetRandomFileFailFactor(int factor) { + random_file_fail_factor = factor; +} + +static void close_random_file_fail_output() { + if (fpRandomFileFailOutput != NULL) { + if (fpRandomFileFailOutput != stdout) { + fclose(fpRandomFileFailOutput); + } + fpRandomFileFailOutput = NULL; + } +} + +static void random_file_fail_output_sig(int sig) { + fprintf(fpRandomFileFailOutput, "signal %d received.\n", sig); + + struct sigaction act = {0}; + act.sa_handler = SIG_DFL; + sigaction(sig, &act, NULL); + + close_random_file_fail_output(); + exit(EXIT_FAILURE); +} + +void taosSetRandomFileFailOutput(const char *path) { + if (path == NULL) { + fpRandomFileFailOutput = stdout; + } else if ((fpRandomFileFailOutput = fopen(path, "w")) != NULL) { + atexit(close_random_file_fail_output); + } else { + printf("failed to open random file fail log file '%s', errno=%d\n", path, errno); + return; + } + + struct sigaction act = {0}; + act.sa_handler = random_file_fail_output_sig; + sigaction(SIGFPE, &act, NULL); + sigaction(SIGSEGV, &act, NULL); + sigaction(SIGILL, &act, NULL); +} + +ssize_t taosReadFileRandomFail(int fd, void *buf, size_t count, const char *file, uint32_t line) { + if (random_file_fail_factor > 0) { + if (rand() % random_file_fail_factor == 0) { + errno = EIO; + return -1; + } + } + + return taosTReadImp(fd, buf, count); +} + +ssize_t taosWriteFileRandomFail(int fd, void *buf, size_t count, const char *file, uint32_t line) { + if (random_file_fail_factor > 0) { + if (rand() % random_file_fail_factor == 0) { + errno = EIO; + return -1; + } + } + + return taosTWriteImp(fd, buf, count); +} + +off_t taosLSeekRandomFail(int fd, off_t offset, int whence, const char *file, uint32_t line) { + if (random_file_fail_factor > 0) { + if (rand() % random_file_fail_factor == 0) { + errno = EIO; + return -1; + } + } + + return lseek(fd, offset, whence); +} + +#endif //TAOS_RANDOM_FILE_FAIL diff --git a/src/os/src/detail/osFile.c b/src/os/src/detail/osFile.c new file mode 100644 index 0000000000..897b6c3f03 --- /dev/null +++ b/src/os/src/detail/osFile.c @@ -0,0 +1,88 @@ +/* + * 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" + +ssize_t taosTReadImp(int fd, void *buf, size_t count) { + size_t leftbytes = count; + ssize_t readbytes; + char * tbuf = (char *)buf; + + while (leftbytes > 0) { + readbytes = read(fd, (void *)tbuf, leftbytes); + if (readbytes < 0) { + if (errno == EINTR) { + continue; + } else { + return -1; + } + } else if (readbytes == 0) { + return (ssize_t)(count - leftbytes); + } + + leftbytes -= readbytes; + tbuf += readbytes; + } + + return (ssize_t)count; +} + +ssize_t taosTSendFileImp(int dfd, int sfd, off_t *offset, size_t size) { + size_t leftbytes = size; + ssize_t sentbytes; + + while (leftbytes > 0) { + /* + * TODO : Think to check if file is larger than 1GB + */ + //if (leftbytes > 1000000000) leftbytes = 1000000000; + sentbytes = sendfile(dfd, sfd, offset, leftbytes); + if (sentbytes == -1) { + if (errno == EINTR) { + continue; + } + else { + return -1; + } + } else if (sentbytes == 0) { + return (ssize_t)(size - leftbytes); + } + + leftbytes -= sentbytes; + } + + return size; +} + +ssize_t taosTWriteImp(int fd, void *buf, size_t n) { + size_t nleft = n; + ssize_t nwritten = 0; + char *tbuf = (char *)buf; + + while (nleft > 0) { + nwritten = write(fd, (void *)tbuf, nleft); + if (nwritten < 0) { + if (errno == EINTR) { + continue; + } + return -1; + } + nleft -= nwritten; + tbuf += nwritten; + } + + return n; +} diff --git a/src/os/src/detail/osPThread.c b/src/os/src/detail/osPThread.c new file mode 100644 index 0000000000..18207dc12e --- /dev/null +++ b/src/os/src/detail/osPThread.c @@ -0,0 +1,24 @@ +/* + * 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" + +#ifndef TAOS_OS_FUNC_PTHREAD + +bool taosCheckPthreadValid(pthread_t thread) { return thread != 0; } +int64_t taosGetPthreadId() { return (int64_t)pthread_self(); } + +#endif \ No newline at end of file diff --git a/src/os/src/detail/osSocket.c b/src/os/src/detail/osSocket.c new file mode 100644 index 0000000000..ea0b92de5f --- /dev/null +++ b/src/os/src/detail/osSocket.c @@ -0,0 +1,56 @@ +/* + * 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 "tulog.h" + +#ifndef TAOS_OS_FUNC_SOCKET + +int taosSetNonblocking(int sock, int on) { + int flags = 0; + if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { + uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); + return 1; + } + + if (on) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + + if ((flags = fcntl(sock, F_SETFL, flags)) < 0) { + uError("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno)); + return 1; + } + + return 0; +} + +int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { + return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); +} + +void taosBlockSIGPIPE() { + sigset_t signal_mask; + sigemptyset(&signal_mask); + sigaddset(&signal_mask, SIGPIPE); + int rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); + if (rc != 0) { + uError("failed to block SIGPIPE"); + } +} + +#endif \ No newline at end of file diff --git a/src/os/src/detail/osSysinfo.c b/src/os/src/detail/osSysinfo.c new file mode 100644 index 0000000000..ac9b441555 --- /dev/null +++ b/src/os/src/detail/osSysinfo.c @@ -0,0 +1,573 @@ +/* + * 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 "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tutil.h" +#include "tsystem.h" + +#ifndef TAOS_OS_FUNC_SYSINFO + +#define PROCESS_ITEM 12 + +typedef struct { + uint64_t user; + uint64_t nice; + uint64_t system; + uint64_t idle; +} SysCpuInfo; + +typedef struct { + uint64_t utime; // user time + uint64_t stime; // kernel time + uint64_t cutime; // all user time + uint64_t cstime; // all dead time +} ProcCpuInfo; + +static pid_t tsProcId; +static char tsSysNetFile[] = "/proc/net/dev"; +static char tsSysCpuFile[] = "/proc/stat"; +static char tsProcCpuFile[25] = {0}; +static char tsProcMemFile[25] = {0}; +static char tsProcIOFile[25] = {0}; +static float tsPageSizeKB = 0; + +bool taosGetSysMemory(float *memoryUsedMB) { + float memoryAvailMB = (float)sysconf(_SC_AVPHYS_PAGES) * tsPageSizeKB / 1024; + *memoryUsedMB = (float)tsTotalMemoryMB - memoryAvailMB; + return true; +} + +bool taosGetProcMemory(float *memoryUsedMB) { + FILE *fp = fopen(tsProcMemFile, "r"); + if (fp == NULL) { + uError("open file:%s failed", tsProcMemFile); + return false; + } + + size_t len; + char * line = NULL; + while (!feof(fp)) { + tfree(line); + len = 0; + getline(&line, &len, fp); + if (line == NULL) { + break; + } + if (strstr(line, "VmRSS:") != NULL) { + break; + } + } + + if (line == NULL) { + uError("read file:%s failed", tsProcMemFile); + fclose(fp); + return false; + } + + int64_t memKB = 0; + char tmp[10]; + sscanf(line, "%s %" PRId64, tmp, &memKB); + *memoryUsedMB = (float)((double)memKB / 1024); + + tfree(line); + fclose(fp); + return true; +} + +static bool taosGetSysCpuInfo(SysCpuInfo *cpuInfo) { + FILE *fp = fopen(tsSysCpuFile, "r"); + if (fp == NULL) { + uError("open file:%s failed", tsSysCpuFile); + return false; + } + + size_t len; + char * line = NULL; + getline(&line, &len, fp); + if (line == NULL) { + uError("read file:%s failed", tsSysCpuFile); + fclose(fp); + return false; + } + + char cpu[10] = {0}; + sscanf(line, "%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, cpu, &cpuInfo->user, &cpuInfo->nice, &cpuInfo->system, &cpuInfo->idle); + + tfree(line); + fclose(fp); + return true; +} + +static bool taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) { + FILE *fp = fopen(tsProcCpuFile, "r"); + if (fp == NULL) { + uError("open file:%s failed", tsProcCpuFile); + return false; + } + + size_t len = 0; + char * line = NULL; + getline(&line, &len, fp); + if (line == NULL) { + uError("read file:%s failed", tsProcCpuFile); + fclose(fp); + return false; + } + + for (int i = 0, blank = 0; line[i] != 0; ++i) { + if (line[i] == ' ') blank++; + if (blank == PROCESS_ITEM) { + sscanf(line + i + 1, "%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &cpuInfo->utime, &cpuInfo->stime, &cpuInfo->cutime, &cpuInfo->cstime); + break; + } + } + + tfree(line); + fclose(fp); + return true; +} + +static void taosGetSystemTimezone() { + SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone"); + if (cfg_timezone == NULL) return; + if (cfg_timezone->cfgStatus >= TAOS_CFG_CSTATUS_DEFAULT) { + return; + } + + /* + * NOTE: do not remove it. + * Enforce set the correct daylight saving time(DST) flag according + * to current time + */ + time_t tx1 = time(NULL); + struct tm tm1; + localtime_r(&tx1, &tm1); + + /* load time zone string from /etc/timezone */ + FILE *f = fopen("/etc/timezone", "r"); + char buf[68] = {0}; + if (f != NULL) { + int len = fread(buf, 64, 1, f); + if(len < 64 && ferror(f)) { + fclose(f); + uError("read /etc/timezone error, reason:%s", strerror(errno)); + return; + } + + fclose(f); + + char *lineEnd = strstr(buf, "\n"); + if (lineEnd != NULL) { + *lineEnd = 0; + } + + // for CentOS system, /etc/timezone does not exist. Ignore the TZ environment variables + if (strlen(buf) > 0) { + setenv("TZ", buf, 1); + } + } + // get and set default timezone + tzset(); + + /* + * get CURRENT time zone. + * system current time zone is affected by daylight saving time(DST) + * + * e.g., the local time zone of London in DST is GMT+01:00, + * otherwise is GMT+00:00 + */ + int32_t tz = (-timezone * MILLISECOND_PER_SECOND) / MILLISECOND_PER_HOUR; + tz += daylight; + + /* + * format example: + * + * Asia/Shanghai (CST, +0800) + * Europe/London (BST, +0100) + */ + snprintf(tsTimezone, TSDB_TIMEZONE_LEN, "%s (%s, %s%02d00)", buf, tzname[daylight], tz >= 0 ? "+" : "-", abs(tz)); + + // cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("timezone not configured, set to system default:%s", tsTimezone); +} + +/* + * POSIX format locale string: + * (Language Strings)_(Country/Region Strings).(code_page) + * + * example: en_US.UTF-8, zh_CN.GB18030, zh_CN.UTF-8, + * + * if user does not specify the locale in taos.cfg the program use default LC_CTYPE as system locale. + * + * In case of some CentOS systems, their default locale is "en_US.utf8", which is not valid code_page + * for libiconv that is employed to convert string in this system. This program will automatically use + * UTF-8 instead as the charset. + * + * In case of windows client, the locale string is not valid POSIX format, user needs to set the + * correct code_page for libiconv. Usually, the code_page of windows system with simple chinese is + * CP936, CP437 for English charset. + * + */ +static void taosGetSystemLocale() { // get and set default locale + char sep = '.'; + char *locale = NULL; + + SGlobalCfg *cfg_locale = taosGetConfigOption("locale"); + if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + locale = setlocale(LC_CTYPE, ""); + if (locale == NULL) { + uError("can't get locale from system, set it to en_US.UTF-8"); + strcpy(tsLocale, "en_US.UTF-8"); + } else { + tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN); + uError("locale not configured, set to system default:%s", tsLocale); + } + } + + /* if user does not specify the charset, extract it from locale */ + SGlobalCfg *cfg_charset = taosGetConfigOption("charset"); + if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + char *str = strrchr(tsLocale, sep); + if (str != NULL) { + str++; + + char *revisedCharset = taosCharsetReplace(str); + tstrncpy(tsCharset, revisedCharset, TSDB_LOCALE_LEN); + + free(revisedCharset); + uWarn("charset not configured, set to system default:%s", tsCharset); + } else { + strcpy(tsCharset, "UTF-8"); + uWarn("can't get locale and charset from system, set it to UTF-8"); + } + } +} + +bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) { + static uint64_t lastSysUsed = 0; + static uint64_t lastSysTotal = 0; + static uint64_t lastProcTotal = 0; + + SysCpuInfo sysCpu; + ProcCpuInfo procCpu; + if (!taosGetSysCpuInfo(&sysCpu)) { + return false; + } + if (!taosGetProcCpuInfo(&procCpu)) { + return false; + } + + uint64_t curSysUsed = sysCpu.user + sysCpu.nice + sysCpu.system; + uint64_t curSysTotal = curSysUsed + sysCpu.idle; + uint64_t curProcTotal = procCpu.utime + procCpu.stime + procCpu.cutime + procCpu.cstime; + + if (lastSysUsed == 0 || lastSysTotal == 0 || lastProcTotal == 0) { + lastSysUsed = curSysUsed > 1 ? curSysUsed : 1; + lastSysTotal = curSysTotal > 1 ? curSysTotal : 1; + lastProcTotal = curProcTotal > 1 ? curProcTotal : 1; + return false; + } + + if (curSysTotal == lastSysTotal) { + return false; + } + + *sysCpuUsage = (float)((double)(curSysUsed - lastSysUsed) / (double)(curSysTotal - lastSysTotal) * 100); + *procCpuUsage = (float)((double)(curProcTotal - lastProcTotal) / (double)(curSysTotal - lastSysTotal) * 100); + + lastSysUsed = curSysUsed; + lastSysTotal = curSysTotal; + lastProcTotal = curProcTotal; + + return true; +} + +bool taosGetDisk() { + struct statvfs info; + const double unit = 1024 * 1024 * 1024; + + if (tscEmbedded) { + if (statvfs(tsDataDir, &info)) { + //tsTotalDataDirGB = 0; + //tsAvailDataDirGB = 0; + uError("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); + return false; + } else { + tsTotalDataDirGB = (float)((double)info.f_blocks * (double)info.f_frsize / unit); + tsAvailDataDirGB = (float)((double)info.f_bavail * (double)info.f_frsize / unit); + } + } + + if (statvfs(tsLogDir, &info)) { + //tsTotalLogDirGB = 0; + //tsAvailLogDirGB = 0; + uError("failed to get disk size, logDir:%s errno:%s", tsLogDir, strerror(errno)); + return false; + } else { + tsTotalLogDirGB = (float)((double)info.f_blocks * (double)info.f_frsize / unit); + tsAvailLogDirGB = (float)((double)info.f_bavail * (double)info.f_frsize / unit); + } + + if (statvfs("/tmp", &info)) { + //tsTotalTmpDirGB = 0; + //tsAvailTmpDirectorySpace = 0; + uError("failed to get disk size, tmpDir:/tmp errno:%s", strerror(errno)); + return false; + } else { + tsTotalTmpDirGB = (float)((double)info.f_blocks * (double)info.f_frsize / unit); + tsAvailTmpDirectorySpace = (float)((double)info.f_bavail * (double)info.f_frsize / unit); + } + + return true; +} + +static bool taosGetCardInfo(int64_t *bytes) { + *bytes = 0; + FILE *fp = fopen(tsSysNetFile, "r"); + if (fp == NULL) { + uError("open file:%s failed", tsSysNetFile); + return false; + } + + + size_t len = 2048; + char * line = calloc(1, len); + + while (!feof(fp)) { + memset(line, 0, len); + + int64_t rbytes = 0; + int64_t rpackts = 0; + int64_t tbytes = 0; + int64_t tpackets = 0; + int64_t nouse1 = 0; + int64_t nouse2 = 0; + int64_t nouse3 = 0; + int64_t nouse4 = 0; + int64_t nouse5 = 0; + int64_t nouse6 = 0; + char nouse0[200] = {0}; + + getline(&line, &len, fp); + line[len - 1] = 0; + + if (strstr(line, "lo:") != NULL) { + continue; + } + + sscanf(line, + "%s %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 + " %" PRId64, + nouse0, &rbytes, &rpackts, &nouse1, &nouse2, &nouse3, &nouse4, &nouse5, &nouse6, &tbytes, &tpackets); + *bytes += (rbytes + tbytes); + } + + tfree(line); + fclose(fp); + + return true; +} + +bool taosGetBandSpeed(float *bandSpeedKb) { + static int64_t lastBytes = 0; + static time_t lastTime = 0; + int64_t curBytes = 0; + time_t curTime = time(NULL); + + if (!taosGetCardInfo(&curBytes)) { + return false; + } + + if (lastTime == 0 || lastBytes == 0) { + lastTime = curTime; + lastBytes = curBytes; + *bandSpeedKb = 0; + return true; + } + + if (lastTime >= curTime || lastBytes > curBytes) { + lastTime = curTime; + lastBytes = curBytes; + *bandSpeedKb = 0; + return true; + } + + double totalBytes = (double)(curBytes - lastBytes) / 1024 * 8; // Kb + *bandSpeedKb = (float)(totalBytes / (double)(curTime - lastTime)); + + // uInfo("bandwidth lastBytes:%ld, lastTime:%ld, curBytes:%ld, curTime:%ld, + // speed:%f", lastBytes, lastTime, curBytes, curTime, *bandSpeed); + + lastTime = curTime; + lastBytes = curBytes; + + return true; +} + +static bool taosReadProcIO(int64_t *readbyte, int64_t *writebyte) { + FILE *fp = fopen(tsProcIOFile, "r"); + if (fp == NULL) { + uError("open file:%s failed", tsProcIOFile); + return false; + } + + size_t len; + char * line = NULL; + char tmp[10]; + int readIndex = 0; + + while (!feof(fp)) { + tfree(line); + len = 0; + getline(&line, &len, fp); + if (line == NULL) { + break; + } + if (strstr(line, "rchar:") != NULL) { + sscanf(line, "%s %" PRId64, tmp, readbyte); + readIndex++; + } else if (strstr(line, "wchar:") != NULL) { + sscanf(line, "%s %" PRId64, tmp, writebyte); + readIndex++; + } else { + } + + if (readIndex >= 2) break; + } + + tfree(line); + fclose(fp); + + if (readIndex < 2) { + uError("read file:%s failed", tsProcIOFile); + return false; + } + + return true; +} + +bool taosGetProcIO(float *readKB, float *writeKB) { + static int64_t lastReadbyte = -1; + static int64_t lastWritebyte = -1; + + int64_t curReadbyte = 0; + int64_t curWritebyte = 0; + + if (!taosReadProcIO(&curReadbyte, &curWritebyte)) { + return false; + } + + if (lastReadbyte == -1 || lastWritebyte == -1) { + lastReadbyte = curReadbyte; + lastWritebyte = curWritebyte; + return false; + } + + *readKB = (float)((double)(curReadbyte - lastReadbyte) / 1024); + *writeKB = (float)((double)(curWritebyte - lastWritebyte) / 1024); + if (*readKB < 0) *readKB = 0; + if (*writeKB < 0) *writeKB = 0; + + lastReadbyte = curReadbyte; + lastWritebyte = curWritebyte; + + return true; +} + +void taosGetSystemInfo() { + tsNumOfCores = (int32_t)sysconf(_SC_NPROCESSORS_ONLN); + tsPageSize = sysconf(_SC_PAGESIZE); + tsOpenMax = sysconf(_SC_OPEN_MAX); + tsStreamMax = sysconf(_SC_STREAM_MAX); + + tsProcId = (pid_t)syscall(SYS_gettid); + tsPageSizeKB = (float)(sysconf(_SC_PAGESIZE)) / 1024; + tsTotalMemoryMB = (int32_t)((float)sysconf(_SC_PHYS_PAGES) * tsPageSizeKB / 1024); + + snprintf(tsProcMemFile, 25, "/proc/%d/status", tsProcId); + snprintf(tsProcCpuFile, 25, "/proc/%d/stat", tsProcId); + snprintf(tsProcIOFile, 25, "/proc/%d/io", tsProcId); + + float tmp1, tmp2; + taosGetSysMemory(&tmp1); + taosGetProcMemory(&tmp2); + taosGetDisk(); + taosGetBandSpeed(&tmp1); + taosGetCpuUsage(&tmp1, &tmp2); + taosGetProcIO(&tmp1, &tmp2); + + taosGetSystemTimezone(); + taosGetSystemLocale(); +} + +void taosPrintOsInfo() { + uInfo(" os pageSize: %" PRId64 "(KB)", tsPageSize); + uInfo(" os openMax: %" PRId64, tsOpenMax); + uInfo(" os streamMax: %" PRId64, tsStreamMax); + uInfo(" os numOfCores: %d", tsNumOfCores); + uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB); + uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB); + + struct utsname buf; + if (uname(&buf)) { + uInfo(" can't fetch os info"); + return; + } + uInfo(" os sysname: %s", buf.sysname); + uInfo(" os nodename: %s", buf.nodename); + uInfo(" os release: %s", buf.release); + uInfo(" os version: %s", buf.version); + uInfo(" os machine: %s", buf.machine); + uInfo("=================================="); +} + +void taosKillSystem() { + // SIGINT + uInfo("taosd will shut down soon"); + kill(tsProcId, 2); +} + +int tSystem(const char *cmd) { + FILE *fp; + int res; + char buf[1024]; + if (cmd == NULL) { + uError("tSystem cmd is NULL!\n"); + return -1; + } + + if ((fp = popen(cmd, "r")) == NULL) { + uError("popen cmd:%s error: %s/n", cmd, strerror(errno)); + return -1; + } else { + while (fgets(buf, sizeof(buf), fp)) { + uDebug("popen result:%s", buf); + } + + if ((res = pclose(fp)) == -1) { + uError("close popen file pointer fp error!\n"); + } else { + uDebug("popen res is :%d\n", res); + } + + return res; + } +} + +#endif \ No newline at end of file diff --git a/src/os/src/detail/osTimer.c b/src/os/src/detail/osTimer.c new file mode 100644 index 0000000000..843c29fcb0 --- /dev/null +++ b/src/os/src/detail/osTimer.c @@ -0,0 +1,133 @@ +/* + * 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 . + */ + +#include "os.h" +#include "taosdef.h" +#include "tglobal.h" +#include "ttimer.h" +#include "tulog.h" +#include "tutil.h" +#include + +#ifndef TAOS_OS_FUNC_TIMER + +/* + to make taosMsleep work, + signal SIGALRM shall be blocked in the calling thread, + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGALRM); + pthread_sigmask(SIG_BLOCK, &set, NULL); +*/ +void taosMsleep(int mseconds) { + struct timeval timeout; + int seconds, useconds; + + seconds = mseconds / 1000; + useconds = (mseconds % 1000) * 1000; + timeout.tv_sec = seconds; + timeout.tv_usec = useconds; + + /* sigset_t set; */ + /* sigemptyset(&set); */ + /* sigaddset(&set, SIGALRM); */ + /* pthread_sigmask(SIG_BLOCK, &set, NULL); */ + + select(0, NULL, NULL, NULL, &timeout); + + /* pthread_sigmask(SIG_UNBLOCK, &set, NULL); */ +} + + +static void taosDeleteTimer(void *tharg) { + timer_t *pTimer = tharg; + timer_delete(*pTimer); +} + +static pthread_t timerThread; +static timer_t timerId; +static volatile bool stopTimer = false; +static void *taosProcessAlarmSignal(void *tharg) { + // Block the signal + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGALRM); + sigprocmask(SIG_BLOCK, &sigset, NULL); + void (*callback)(int) = tharg; + + struct sigevent sevent = {{0}}; + + #ifdef _ALPINE + sevent.sigev_notify = SIGEV_THREAD; + sevent.sigev_value.sival_int = syscall(__NR_gettid); + #else + sevent.sigev_notify = SIGEV_THREAD_ID; + sevent._sigev_un._tid = syscall(__NR_gettid); + #endif + + sevent.sigev_signo = SIGALRM; + + if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) { + uError("Failed to create timer"); + } + + pthread_cleanup_push(taosDeleteTimer, &timerId); + + struct itimerspec ts; + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK; + + if (timer_settime(timerId, 0, &ts, NULL)) { + uError("Failed to init timer"); + return NULL; + } + + int signo; + while (!stopTimer) { + if (sigwait(&sigset, &signo)) { + uError("Failed to wait signal: number %d", signo); + continue; + } + /* printf("Signal handling: number %d ......\n", signo); */ + + callback(0); + } + + pthread_cleanup_pop(1); + + return NULL; +} + +int taosInitTimer(void (*callback)(int), int ms) { + pthread_attr_t tattr; + pthread_attr_init(&tattr); + int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback); + pthread_attr_destroy(&tattr); + if (code != 0) { + uError("failed to create timer thread"); + return -1; + } + return 0; +} + +void taosUninitTimer() { + stopTimer = true; + pthread_join(timerThread, NULL); +} + +#endif \ No newline at end of file diff --git a/src/os/src/detail/osUtil.c b/src/os/src/detail/osUtil.c new file mode 100644 index 0000000000..10576c9a0a --- /dev/null +++ b/src/os/src/detail/osUtil.c @@ -0,0 +1,26 @@ +/* + * 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" + +#ifndef TAOS_OS_FUNC_UTIL + +int64_t tsosStr2int64(char *str) { + char *endptr = NULL; + return strtoll(str, &endptr, 10); +} + +#endif \ No newline at end of file diff --git a/src/os/src/linux64/CMakeLists.txt b/src/os/src/linux64/CMakeLists.txt new file mode 100644 index 0000000000..79cbf917e2 --- /dev/null +++ b/src/os/src/linux64/CMakeLists.txt @@ -0,0 +1,12 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +AUX_SOURCE_DIRECTORY(. SRC) + +ADD_LIBRARY(os ${SRC}) +TARGET_LINK_LIBRARIES(os m rt) + diff --git a/src/os/src/linux64/linuxEnv.c b/src/os/src/linux64/linuxEnv.c new file mode 100644 index 0000000000..0a9d81311a --- /dev/null +++ b/src/os/src/linux64/linuxEnv.c @@ -0,0 +1,30 @@ +/* + * 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 "tglobal.h" +#include "tulog.h" + +void osInit() { + strcpy(configDir, "/etc/taos"); + strcpy(tsVnodeDir, ""); + strcpy(tsDnodeDir, ""); + strcpy(tsMnodeDir, ""); + strcpy(tsDataDir, "/var/lib/taos"); + strcpy(tsLogDir, "/var/log/taos"); + strcpy(tsScriptDir, "/etc/taos"); + strcpy(tsOsName, "Linux"); +} \ No newline at end of file diff --git a/src/os/src/windows64/CMakeLists.txt b/src/os/src/windows64/CMakeLists.txt new file mode 100644 index 0000000000..dc60b736ea --- /dev/null +++ b/src/os/src/windows64/CMakeLists.txt @@ -0,0 +1,11 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_WINDOWS_64) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(inc) + AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(os ${SRC}) + TARGET_LINK_LIBRARIES(os winmm IPHLPAPI ws2_32) +ENDIF () diff --git a/src/os/src/windows64/twindows.c b/src/os/src/windows64/twindows.c new file mode 100644 index 0000000000..4284dcb14e --- /dev/null +++ b/src/os/src/windows64/twindows.c @@ -0,0 +1,410 @@ +/* + * 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 "taosdef.h" +#include "tglobal.h" +#include "ttimer.h" +#include "tulog.h" +#include "tutil.h" + +bool taosCheckPthreadValid(pthread_t thread) { + return thread.p != NULL; +} + +void taosResetPthread(pthread_t *thread) { + thread->p = 0; +} + +int64_t taosGetPthreadId() { +#ifdef PTW32_VERSION + return pthread_getw32threadid_np(pthread_self()); +#else + return (int64_t)pthread_self(); +#endif +} + +int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { + if (level == SOL_SOCKET && optname == TCP_KEEPCNT) { + return 0; + } + + if (level == SOL_TCP && optname == TCP_KEEPIDLE) { + return 0; + } + + if (level == SOL_TCP && optname == TCP_KEEPINTVL) { + return 0; + } + + return setsockopt(socketfd, level, optname, optval, optlen); +} + +// add +char interlocked_add_fetch_8(char volatile* ptr, char val) { + #ifdef _TD_GO_DLL_ + return __sync_fetch_and_add(ptr, val) + val; + #else + return _InterlockedExchangeAdd8(ptr, val) + val; + #endif +} + +short interlocked_add_fetch_16(short volatile* ptr, short val) { + #ifdef _TD_GO_DLL_ + return __sync_fetch_and_add(ptr, val) + val; + #else + return _InterlockedExchangeAdd16(ptr, val) + val; + #endif +} + +long interlocked_add_fetch_32(long volatile* ptr, long val) { + return _InterlockedExchangeAdd(ptr, val) + val; +} + +__int64 interlocked_add_fetch_64(__int64 volatile* ptr, __int64 val) { + return _InterlockedExchangeAdd64(ptr, val) + val; +} + +// and +#ifndef _TD_GO_DLL_ +char interlocked_and_fetch_8(char volatile* ptr, char val) { + return _InterlockedAnd8(ptr, val) & val; +} + +short interlocked_and_fetch_16(short volatile* ptr, short val) { + return _InterlockedAnd16(ptr, val) & val; +} +#endif + +long interlocked_and_fetch_32(long volatile* ptr, long val) { + return _InterlockedAnd(ptr, val) & val; +} + +#ifndef _M_IX86 + +__int64 interlocked_and_fetch_64(__int64 volatile* ptr, __int64 val) { + return _InterlockedAnd64(ptr, val) & val; +} + +#else + +__int64 interlocked_and_fetch_64(__int64 volatile* ptr, __int64 val) { + __int64 old, res; + do { + old = *ptr; + res = old & val; + } while(_InterlockedCompareExchange64(ptr, res, old) != old); + return res; +} + +__int64 interlocked_fetch_and_64(__int64 volatile* ptr, __int64 val) { + __int64 old; + do { + old = *ptr; + } while(_InterlockedCompareExchange64(ptr, old & val, old) != old); + return old; +} + +#endif + +// or +#ifndef _TD_GO_DLL_ +char interlocked_or_fetch_8(char volatile* ptr, char val) { + return _InterlockedOr8(ptr, val) | val; +} + +short interlocked_or_fetch_16(short volatile* ptr, short val) { + return _InterlockedOr16(ptr, val) | val; +} +#endif +long interlocked_or_fetch_32(long volatile* ptr, long val) { + return _InterlockedOr(ptr, val) | val; +} + +#ifndef _M_IX86 + +__int64 interlocked_or_fetch_64(__int64 volatile* ptr, __int64 val) { + return _InterlockedOr64(ptr, val) & val; +} + +#else + +__int64 interlocked_or_fetch_64(__int64 volatile* ptr, __int64 val) { + __int64 old, res; + do { + old = *ptr; + res = old | val; + } while(_InterlockedCompareExchange64(ptr, res, old) != old); + return res; +} + +__int64 interlocked_fetch_or_64(__int64 volatile* ptr, __int64 val) { + __int64 old; + do { + old = *ptr; + } while(_InterlockedCompareExchange64(ptr, old | val, old) != old); + return old; +} + +#endif + +// xor +#ifndef _TD_GO_DLL_ +char interlocked_xor_fetch_8(char volatile* ptr, char val) { + return _InterlockedXor8(ptr, val) ^ val; +} + +short interlocked_xor_fetch_16(short volatile* ptr, short val) { + return _InterlockedXor16(ptr, val) ^ val; +} +#endif +long interlocked_xor_fetch_32(long volatile* ptr, long val) { + return _InterlockedXor(ptr, val) ^ val; +} + +#ifndef _M_IX86 + +__int64 interlocked_xor_fetch_64(__int64 volatile* ptr, __int64 val) { + return _InterlockedXor64(ptr, val) ^ val; +} + +#else + +__int64 interlocked_xor_fetch_64(__int64 volatile* ptr, __int64 val) { + __int64 old, res; + do { + old = *ptr; + res = old ^ val; + } while(_InterlockedCompareExchange64(ptr, res, old) != old); + return res; +} + +__int64 interlocked_fetch_xor_64(__int64 volatile* ptr, __int64 val) { + __int64 old; + do { + old = *ptr; + } while(_InterlockedCompareExchange64(ptr, old ^ val, old) != old); + return old; +} + +#endif + +void taosPrintOsInfo() {} + +void taosGetSystemTimezone() { + // get and set default timezone + SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone"); + if (cfg_timezone && cfg_timezone->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + char *tz = getenv("TZ"); + if (tz == NULL || strlen(tz) == 0) { + strcpy(tsTimezone, "not configured"); + } + else { + strcpy(tsTimezone, tz); + } + cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("timezone not configured, use default"); + } +} + +void taosGetSystemLocale() { + // get and set default locale + SGlobalCfg *cfg_locale = taosGetConfigOption("locale"); + if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + char *locale = setlocale(LC_CTYPE, "chs"); + if (locale != NULL) { + tstrncpy(tsLocale, locale, sizeof(tsLocale)); + cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("locale not configured, set to default:%s", tsLocale); + } + } + + SGlobalCfg *cfg_charset = taosGetConfigOption("charset"); + if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { + strcpy(tsCharset, "cp936"); + cfg_charset->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; + uInfo("charset not configured, set to default:%s", tsCharset); + } +} + +void taosGetSystemInfo() { + taosGetSystemTimezone(); + taosGetSystemLocale(); +} + +void taosKillSystem() { + exit(0); +} + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no moretokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char *strsep(char **stringp, const char *delim) { + char *s; + const char *spanp; + int c, sc; + char *tok; + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +char *getpass(const char *prefix) { + static char passwd[TSDB_KEY_LEN] = {0}; + + printf("%s", prefix); + scanf("%s", passwd); + + char n = getchar(); + return passwd; +} + +int flock(int fd, int option) { + return 0; +} + +int fsync(int filedes) { + return 0; +} + +int sigaction(int sig, struct sigaction *d, void *p) { + return 0; +} + +int wordexp(const char *words, wordexp_t *pwordexp, int flags) { + pwordexp->we_offs = 0; + pwordexp->we_wordc = 1; + pwordexp->we_wordv = (char **)(pwordexp->wordPos); + pwordexp->we_wordv[0] = (char *)words; + return 0; +} + +void wordfree(wordexp_t *pwordexp) {} + +void taosGetDisk() {} + +bool taosSkipSocketCheck() { + return false; +} + +#define _SEND_FILE_STEP_ 1000 + +int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count) { + fseek(in_file, (int32_t)(*offset), 0); + int writeLen = 0; + uint8_t buffer[_SEND_FILE_STEP_] = { 0 }; + + for (int len = 0; len < (count - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) { + size_t rlen = fread(buffer, 1, _SEND_FILE_STEP_, in_file); + if (rlen <= 0) { + return writeLen; + } + else if (rlen < _SEND_FILE_STEP_) { + fwrite(buffer, 1, rlen, out_file); + return (int)(writeLen + rlen); + } + else { + fwrite(buffer, 1, _SEND_FILE_STEP_, in_file); + writeLen += _SEND_FILE_STEP_; + } + } + + int remain = count - writeLen; + if (remain > 0) { + size_t rlen = fread(buffer, 1, remain, in_file); + if (rlen <= 0) { + return writeLen; + } + else { + fwrite(buffer, 1, remain, out_file); + writeLen += remain; + } + } + + return writeLen; +} + +int32_t BUILDIN_CLZL(uint64_t val) { + unsigned long r = 0; + _BitScanReverse64(&r, val); + return (int)(r >> 3); +} + +int32_t BUILDIN_CLZ(uint32_t val) { + unsigned long r = 0; + _BitScanReverse(&r, val); + return (int)(r >> 3); +} + +int32_t BUILDIN_CTZL(uint64_t val) { + unsigned long r = 0; + _BitScanForward64(&r, val); + return (int)(r >> 3); +} + +int32_t BUILDIN_CTZ(uint32_t val) { + unsigned long r = 0; + _BitScanForward(&r, val); + return (int)(r >> 3); +} + +char *strndup(const char *s, size_t n) { + int len = strlen(s); + if (len >= n) { + len = n; + } + + char *r = calloc(len + 1, 1); + memcpy(r, s, len); + r[len] = 0; + return r; +} + +void taosSetCoreDump() {} + +#ifdef _TD_GO_DLL_ +int64_t tsosStr2int64(char *str) { + char *endptr = NULL; + return strtoll(str, &endptr, 10); +} + +uint64_t htonll(uint64_t val) +{ + return (((uint64_t) htonl(val)) << 32) + htonl(val >> 32); +} +#endif \ No newline at end of file diff --git a/src/os/src/windows64/twinenv.c b/src/os/src/windows64/twinenv.c new file mode 100644 index 0000000000..840a8d9f7a --- /dev/null +++ b/src/os/src/windows64/twinenv.c @@ -0,0 +1,30 @@ +/* + * 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 "tglobal.h" +#include "tulog.h" + +void osInit() { + strcpy(configDir, "C:/TDengine/cfg"); + strcpy(tsVnodeDir, "C:/TDengine/data"); + strcpy(tsDnodeDir, ""); + strcpy(tsMnodeDir, ""); + strcpy(tsDataDir, "C:/TDengine/data"); + strcpy(tsLogDir, "C:/TDengine/log"); + strcpy(tsScriptDir, "C:/TDengine/script"); + strcpy(tsOsName, "Windows"); +} \ No newline at end of file diff --git a/src/os/src/windows64/twingetline.c b/src/os/src/windows64/twingetline.c new file mode 100644 index 0000000000..1dd56fd547 --- /dev/null +++ b/src/os/src/windows64/twingetline.c @@ -0,0 +1,145 @@ +/* getline.c -- Replacement for GNU C library function getline + +Copyright (C) 1993 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +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. See the GNU +General Public License for more details. */ + +/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#if STDC_HEADERS +#include +#else +char *malloc(), *realloc(); +#endif + +/* Always add at least this many bytes when extending the buffer. */ +#define MIN_CHUNK 64 + +/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR ++ OFFSET (and null-terminate it). *LINEPTR is a pointer returned from +malloc (or NULL), pointing to *N characters of space. It is realloc'd +as necessary. Return the number of characters read (not including the +null terminator), or -1 on error or EOF. On a -1 return, the caller +should check feof(), if not then errno has been set to indicate +the error. */ + +int +getstr(lineptr, n, stream, terminator, offset) +char **lineptr; +size_t *n; +FILE *stream; +char terminator; +int offset; +{ + int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ + char *read_pos; /* Where we're reading into *LINEPTR. */ + int ret; + + if (!lineptr || !n || !stream) + { + errno = EINVAL; + return -1; + } + + if (!*lineptr) + { + *n = MIN_CHUNK; + *lineptr = malloc(*n); + if (!*lineptr) + { + errno = ENOMEM; + return -1; + } + } + + nchars_avail = (int)(*n - offset); + read_pos = *lineptr + offset; + + for (;;) + { + int save_errno; + register int c = getc(stream); + + save_errno = errno; + + /* We always want at least one char left in the buffer, since we + always (unless we get an error while reading the first char) + NUL-terminate the line buffer. */ + + assert((*lineptr + *n) == (read_pos + nchars_avail)); + if (nchars_avail < 2) + { + if (*n > MIN_CHUNK) + *n *= 2; + else + *n += MIN_CHUNK; + + nchars_avail = (int)(*n + *lineptr - read_pos); + *lineptr = realloc(*lineptr, *n); + if (!*lineptr) + { + errno = ENOMEM; + return -1; + } + read_pos = *n - nchars_avail + *lineptr; + assert((*lineptr + *n) == (read_pos + nchars_avail)); + } + + if (ferror(stream)) + { + /* Might like to return partial line, but there is no + place for us to store errno. And we don't want to just + lose errno. */ + errno = save_errno; + return -1; + } + + if (c == EOF) + { + /* Return partial line, if any. */ + if (read_pos == *lineptr) + return -1; + else + break; + } + + *read_pos++ = c; + nchars_avail--; + + if (c == terminator) + /* Return the line. */ + break; + } + + /* Done - NUL terminate and return the number of chars read. */ + *read_pos = '\0'; + + ret = (int)(read_pos - (*lineptr + offset)); + return ret; +} + +int +getline(lineptr, n, stream) +char **lineptr; +size_t *n; +FILE *stream; +{ + return getstr(lineptr, n, stream, '\n', 0); +} \ No newline at end of file diff --git a/src/os/src/windows64/twinmsghdr.c b/src/os/src/windows64/twinmsghdr.c new file mode 100644 index 0000000000..9f35d3ec62 --- /dev/null +++ b/src/os/src/windows64/twinmsghdr.c @@ -0,0 +1,57 @@ +/* + * 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 . + */ + +#include + +void taosFreeMsgHdr(void *hdr) { + WSAMSG *msgHdr = (WSAMSG *)hdr; + free(msgHdr->lpBuffers); +} + +int taosMsgHdrSize(void *hdr) { + WSAMSG *msgHdr = (WSAMSG *)hdr; + return msgHdr->dwBufferCount; +} + +void taosSendMsgHdr(void *hdr, int fd) { + WSAMSG *msgHdr = (WSAMSG *)hdr; + DWORD len; + + WSASendMsg(fd, msgHdr, 0, &len, 0, 0); + msgHdr->dwBufferCount = 0; +} + +void taosInitMsgHdr(void **hdr, void *dest, int maxPkts) { + WSAMSG *msgHdr = (WSAMSG *)malloc(sizeof(WSAMSG)); + memset(msgHdr, 0, sizeof(WSAMSG)); + *hdr = msgHdr; + + // see ws2def.h + // the size of LPSOCKADDR and sockaddr_in * is same, so it's safe + msgHdr->name = (LPSOCKADDR)dest; + msgHdr->namelen = sizeof(struct sockaddr_in); + int size = sizeof(WSABUF) * maxPkts; + msgHdr->lpBuffers = (LPWSABUF)malloc(size); + memset(msgHdr->lpBuffers, 0, size); + msgHdr->dwBufferCount = 0; +} + +void taosSetMsgHdrData(void *hdr, char *data, int dataLen) { + WSAMSG *msgHdr = (WSAMSG *)hdr; + msgHdr->lpBuffers[msgHdr->dwBufferCount].buf = data; + msgHdr->lpBuffers[msgHdr->dwBufferCount].len = dataLen; + msgHdr->dwBufferCount++; +} + diff --git a/src/os/src/windows64/twinsocket.c b/src/os/src/windows64/twinsocket.c new file mode 100644 index 0000000000..0690a4ceb1 --- /dev/null +++ b/src/os/src/windows64/twinsocket.c @@ -0,0 +1,117 @@ +/* + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +void taosWinSocketInit() { + static char flag = 0; + if (flag == 0) { + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD(1, 1); + if (WSAStartup(wVersionRequested, &wsaData) == 0) { + flag = 1; + } + } +} + +int taosSetNonblocking(SOCKET sock, int on) { + u_long mode; + if (on) { + mode = 1; + ioctlsocket(sock, FIONBIO, &mode); + } + else { + mode = 0; + ioctlsocket(sock, FIONBIO, &mode); + } + return 0; +} + +int taosGetPrivateIp(char *const ip) { + PIP_ADAPTER_ADDRESSES pAddresses = 0; + IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = 0; + ULONG outBufLen = 0; + DWORD dwRetVal = 0; + char buff[100]; + DWORD bufflen = 100; + int i; + int flag = -1; + + taosWinSocketInit(); + GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen); + pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen); + if ((dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen)) == NO_ERROR) { + while (pAddresses) { + if (wcsstr(pAddresses->FriendlyName, L"Loopback") != 0) { + pAddresses = pAddresses->Next; + continue; + } + if (pAddresses->OperStatus == IfOperStatusUp) { + //printf("%s, Status: active\n", pAddresses->FriendlyName); + } + else { + //printf("%s, Status: deactive\n", pAddresses->FriendlyName); + pAddresses = pAddresses->Next; + continue; + } + + PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress; + for (i = 0; pUnicast != NULL; i++) { + if (pUnicast->Address.lpSockaddr->sa_family == AF_INET) { + struct sockaddr_in *sa_in = (struct sockaddr_in *)pUnicast->Address.lpSockaddr; + strcpy(ip, inet_ntop(AF_INET, &(sa_in->sin_addr), buff, bufflen)); + flag = 0; + //printf("%s\n", ip); + } + else if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6) { + struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)pUnicast->Address.lpSockaddr; + strcpy(ip, inet_ntop(AF_INET6, &(sa_in6->sin6_addr), buff, bufflen)); + flag = 0; + //printf("%s\n", ip); + } + else { + } + pUnicast = pUnicast->Next; + } + pAddresses = pAddresses->Next; + } + } + else { + LPVOID lpMsgBuf; + printf("Call to GetAdaptersAddresses failed.\n"); + if (FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwRetVal, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) & lpMsgBuf, + 0, + NULL)) { + printf("\tError: %s", lpMsgBuf); + } + LocalFree(lpMsgBuf); + } + free(pAddresses); + return flag; +} diff --git a/src/os/src/windows64/twinstrptime.c b/src/os/src/windows64/twinstrptime.c new file mode 100644 index 0000000000..2401818274 --- /dev/null +++ b/src/os/src/windows64/twinstrptime.c @@ -0,0 +1,398 @@ +/* $Id$ */ +/* $NetBSD: strptime.c,v 1.18 1999/04/29 02:58:30 tv Exp $ */ + +/*- +* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. +* All rights reserved. +* +* This code was contributed to The NetBSD Foundation by Klaus Klein. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. All advertising materials mentioning features or use of this software +* must display the following acknowledgement: +* This product includes software developed by the NetBSD +* Foundation, Inc. and its contributors. +* 4. Neither the name of The NetBSD Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ +// +//#include "lukemftp.h" +#include +#include +#include +#include +//#define TM_YEAR_BASE 1970 //origin +#define TM_YEAR_BASE 1900 //slguan +/* +* We do not implement alternate representations. However, we always +* check whether a given modifier is allowed for a certain conversion. +*/ +#define ALT_E 0x01 +#define ALT_O 0x02 +#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } + + +static int conv_num(const char **, int *, int, int); + +static const char *day[7] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" +}; +static const char *abday[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; +static const char *mon[12] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" +}; +static const char *abmon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +static const char *am_pm[2] = { + "AM", "PM" +}; + + +char * +strptime(const char *buf, const char *fmt, struct tm *tm) +{ + char c; + const char *bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (isspace(c)) { + while (isspace(*bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + + again: switch (c = *fmt++) { + case '%': /* "%%" is converted to "%". */ + literal : + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, "%x %X", tm))) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%m/%d/%y", tm))) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%H:%M", tm))) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%I:%M:%S %p", tm))) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, "%m/%d/%y", tm))) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) { + /* Full name. */ + len = strlen(day[i]); + if (strncmp(day[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abday[i]); + if (strncmp(abday[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) { + /* Full name. */ + len = strlen(mon[i]); + if (strncmp(mon[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abmon[i]); + if (strncmp(abmon[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } + else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; + + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; + + case 'p': /* The locale's equivalent of AM/PM. */ + LEGAL_ALT(0); + /* AM? */ + if (strcmp(am_pm[0], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + bp += strlen(am_pm[0]); + break; + } + /* PM? */ + else if (strcmp(am_pm[1], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + tm->tm_hour += 12; + bp += strlen(am_pm[1]); + break; + } + + /* Nothing matched. */ + return (0); + + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (isspace(*bp)) + bp++; + break; + + + default: /* Unknown/unsupported conversion. */ + return (0); + } + + + } + + /* LINTED functional specification */ + return ((char *)bp); +} + + +static int +conv_num(const char **buf, int *dest, int llim, int ulim) +{ + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} \ No newline at end of file diff --git a/src/os/src/windows64/twintcpclient.c b/src/os/src/windows64/twintcpclient.c new file mode 100644 index 0000000000..4736042aba --- /dev/null +++ b/src/os/src/windows64/twintcpclient.c @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +#include "tulog.h" + +void *taosInitTcpClient(char *ip, uint16_t port, char *label, int num, void *fp, void *shandle) { + tError("InitTcpClient not support in windows"); + return 0; +} + +void taosCloseTcpClientConnection(void *chandle) { + tError("CloseTcpClientConnection not support in windows"); +} + +void *taosOpenTcpClientConnection(void *shandle, void *thandle, char *ip, uint16_t port) { + tError("OpenTcpClientConnection not support in windows"); + return 0; +} + +int taosSendTcpClientData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { + tError("SendTcpClientData not support in windows"); + return 0; +} + +void taosCleanUpTcpClient(void *chandle) { + tError("SendTcpClientData not support in windows"); +} diff --git a/src/os/src/windows64/twintcpserver.c b/src/os/src/windows64/twintcpserver.c new file mode 100644 index 0000000000..10c0348bef --- /dev/null +++ b/src/os/src/windows64/twintcpserver.c @@ -0,0 +1,34 @@ +/* + * 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 . + */ + +#include "tulog.h" + +void taosCloseTcpServerConnection(void *chandle) { + tError("CloseTcpServerConnection not support in windows"); +} + +void taosCleanUpTcpServer(void *handle) { + tError("CleanUpTcpServer not support in windows"); +} + +void *taosInitTcpServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) { + tError("InitTcpServer not support in windows"); + return 0; +} + +int taosSendTcpServerData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { + tError("SendTcpServerData not support in windows"); + return 0; +} diff --git a/src/os/src/windows64/twintime.c b/src/os/src/windows64/twintime.c new file mode 100644 index 0000000000..1484b13843 --- /dev/null +++ b/src/os/src/windows64/twintime.c @@ -0,0 +1,34 @@ +/* + * 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 . + */ + +#include +#include + +int gettimeofday(struct timeval *tv, struct timezone *tz) { + time_t t; + t = time(NULL); + SYSTEMTIME st; + GetLocalTime(&st); + + tv->tv_sec = (long)t; + tv->tv_usec = st.wMilliseconds * 1000; + + return 0; +} + +struct tm *localtime_r(const time_t *timep, struct tm *result) { + localtime_s(result, timep); + return result; +} \ No newline at end of file diff --git a/src/os/src/windows64/twintimer.c b/src/os/src/windows64/twintimer.c new file mode 100644 index 0000000000..2bb8478f09 --- /dev/null +++ b/src/os/src/windows64/twintimer.c @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +#include +#include +#include +#include + +#pragma warning( disable : 4244 ) + +typedef void (*win_timer_f)(int signo); + +void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwl, DWORD_PTR dw2) +{ + win_timer_f callback = *((win_timer_f *)&dwUser); + if (callback != NULL) { + callback(0); + } +} + +static MMRESULT timerId; +int taosInitTimer(win_timer_f callback, int ms) { + DWORD_PTR param = *((int64_t *) & callback); + + timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC); + if (timerId == 0) { + return -1; + } + return 0; +} + +void taosUninitTimer() { + timeKillEvent(timerId); +} + +void taosMsleep(int mseconds) { + Sleep(mseconds); +} + +void sleep(int mseconds) { + taosMsleep(mseconds); +} \ No newline at end of file diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 2bc6bf54bf..c71820211b 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -4,3 +4,5 @@ PROJECT(TDengine) ADD_SUBDIRECTORY(monitor) ADD_SUBDIRECTORY(http) ADD_SUBDIRECTORY(mqtt) +ADD_SUBDIRECTORY(balance) +ADD_SUBDIRECTORY(sync) diff --git a/src/plugins/http/CMakeLists.txt b/src/plugins/http/CMakeLists.txt index 27bcae943c..3280a37c94 100644 --- a/src/plugins/http/CMakeLists.txt +++ b/src/plugins/http/CMakeLists.txt @@ -3,6 +3,7 @@ PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) @@ -10,7 +11,6 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(http ${SRC}) diff --git a/src/plugins/http/src/httpJson.c b/src/plugins/http/src/httpJson.c index 82666826bc..4748f03b66 100644 --- a/src/plugins/http/src/httpJson.c +++ b/src/plugins/http/src/httpJson.c @@ -45,7 +45,7 @@ int httpWriteBufByFd(struct HttpContext* pContext, const char* buf, int sz) { do { if (pContext->fd > 2){ - len = (int)send(pContext->fd, buf + writeLen, (size_t)(sz - writeLen), MSG_NOSIGNAL); + len = (int)taosSend(pContext->fd, buf + writeLen, (size_t)(sz - writeLen), MSG_NOSIGNAL); } else { return sz; diff --git a/src/plugins/monitor/CMakeLists.txt b/src/plugins/monitor/CMakeLists.txt index 0ea5507501..9a20286797 100644 --- a/src/plugins/monitor/CMakeLists.txt +++ b/src/plugins/monitor/CMakeLists.txt @@ -3,11 +3,11 @@ PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(./src SRC) ADD_LIBRARY(monitor ${SRC}) diff --git a/src/plugins/mqtt/CMakeLists.txt b/src/plugins/mqtt/CMakeLists.txt index cc88bd95a4..5fc8f9039f 100644 --- a/src/plugins/mqtt/CMakeLists.txt +++ b/src/plugins/mqtt/CMakeLists.txt @@ -3,6 +3,7 @@ PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) @@ -10,7 +11,6 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MQTT-C/include) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MQTT-C/examples/templates) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(mqtt ${SRC}) diff --git a/src/query/CMakeLists.txt b/src/query/CMakeLists.txt index 620fd217de..625b85d908 100644 --- a/src/query/CMakeLists.txt +++ b/src/query/CMakeLists.txt @@ -1,9 +1,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) diff --git a/src/query/src/qTsbuf.c b/src/query/src/qTsbuf.c index 20b29107f5..90cf394035 100644 --- a/src/query/src/qTsbuf.c +++ b/src/query/src/qTsbuf.c @@ -740,7 +740,7 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf, int32_t vnodeId) { int32_t size = pSrcBuf->fileSize - offset; #ifdef LINUX - ssize_t rc = tsendfile(fileno(pDestBuf->f), fileno(pSrcBuf->f), &offset, size); + ssize_t rc = taosTSendFile(fileno(pDestBuf->f), fileno(pSrcBuf->f), &offset, size); #else ssize_t rc = fsendfile(pDestBuf->f, pSrcBuf->f, &offset, size); #endif diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 96c63b45ca..902c8b66e4 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -1,8 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) @@ -12,10 +12,11 @@ INCLUDE_DIRECTORIES(inc) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) AUX_SOURCE_DIRECTORY(./src SRC) ELSEIF (TD_DARWIN_64) - LIST(APPEND SRC ./src/thaship.c) - LIST(APPEND SRC ./src/trpc.c) - LIST(APPEND SRC ./src/tstring.c) - LIST(APPEND SRC ./src/tudp.c) + #LIST(APPEND SRC ./src/thaship.c) + #LIST(APPEND SRC ./src/trpc.c) + #LIST(APPEND SRC ./src/tstring.c) + #LIST(APPEND SRC ./src/tudp.c) + AUX_SOURCE_DIRECTORY(src SRC) ELSEIF (TD_WINDOWS_64) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) LIST(APPEND SRC ./src/thaship.c) diff --git a/src/rpc/src/rpcUdp.c b/src/rpc/src/rpcUdp.c index decd7a8307..bdaae4c597 100644 --- a/src/rpc/src/rpcUdp.c +++ b/src/rpc/src/rpcUdp.c @@ -242,7 +242,7 @@ int taosSendUdpData(uint32_t ip, uint16_t port, void *data, int dataLen, void *c destAdd.sin_addr.s_addr = ip; destAdd.sin_port = htons(port); - int ret = (int)sendto(pConn->fd, data, (size_t)dataLen, 0, (struct sockaddr *)&destAdd, sizeof(destAdd)); + int ret = (int)taosSendto(pConn->fd, data, (size_t)dataLen, 0, (struct sockaddr *)&destAdd, sizeof(destAdd)); return ret; } diff --git a/src/rpc/test/CMakeLists.txt b/src/rpc/test/CMakeLists.txt index 6787de56f6..ac7ea8e4c1 100644 --- a/src/rpc/test/CMakeLists.txt +++ b/src/rpc/test/CMakeLists.txt @@ -1,13 +1,13 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(../inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/rpc/inc) +IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) LIST(APPEND CLIENT_SRC ./rclient.c) ADD_EXECUTABLE(rclient ${CLIENT_SRC}) TARGET_LINK_LIBRARIES(rclient trpc) diff --git a/src/tsdb/CMakeLists.txt b/src/tsdb/CMakeLists.txt index b2154969d6..450afe337b 100644 --- a/src/tsdb/CMakeLists.txt +++ b/src/tsdb/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) # INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/vnode/common/inc) diff --git a/src/tsdb/src/tsdbFile.c b/src/tsdb/src/tsdbFile.c index f698878698..6e7b39830e 100644 --- a/src/tsdb/src/tsdbFile.c +++ b/src/tsdb/src/tsdbFile.c @@ -12,23 +12,14 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#define _DEFAULT_SOURCE +#include "os.h" #include "talgo.h" #include "tchecksum.h" #include "tsdbMain.h" #include "tutil.h" #include "ttime.h" -#include "tfile.h" #ifdef TSDB_IDX const char *tsdbFileSuffix[] = {".idx", ".head", ".data", ".last", "", ".i", ".h", ".l"}; @@ -317,7 +308,7 @@ int tsdbUpdateFileHeader(SFile *pFile, uint32_t version) { terrno = TAOS_SYSTEM_ERROR(errno); return -1; } - if (twrite(pFile->fd, (void *)buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { + if (taosTWrite(pFile->fd, (void *)buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { tsdbError("failed to write %d bytes to file %s since %s", TSDB_FILE_HEAD_SIZE, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; @@ -383,7 +374,7 @@ static int tsdbInitFile(SFile *pFile, STsdbRepo *pRepo, int fid, int type) { pFile->fd = -1; if (tsdbOpenFile(pFile, O_RDONLY) < 0) goto _err; - if (tread(pFile->fd, buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { + if (taosTRead(pFile->fd, buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pRepo), TSDB_FILE_HEAD_SIZE, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 89a19c15af..3a453249a9 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -545,7 +545,7 @@ static int32_t tsdbSaveConfig(char *rootDir, STsdbCfg *pCfg) { taosCalcChecksumAppend(0, (uint8_t *)buf, TSDB_FILE_HEAD_SIZE); - if (twrite(fd, (void *)buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { + if (taosTWrite(fd, (void *)buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { tsdbError("vgId:%d failed to write %d bytes to file %s since %s", pCfg->tsdbId, TSDB_FILE_HEAD_SIZE, fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -586,7 +586,7 @@ static int tsdbLoadConfig(char *rootDir, STsdbCfg *pCfg) { goto _err; } - if (tread(fd, (void *)buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { + if (taosTRead(fd, (void *)buf, TSDB_FILE_HEAD_SIZE) < TSDB_FILE_HEAD_SIZE) { tsdbError("failed to read %d bytes from file %s since %s", TSDB_FILE_HEAD_SIZE, fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); goto _err; diff --git a/src/tsdb/src/tsdbRWHelper.c b/src/tsdb/src/tsdbRWHelper.c index 28f2974573..9456996071 100644 --- a/src/tsdb/src/tsdbRWHelper.c +++ b/src/tsdb/src/tsdbRWHelper.c @@ -13,13 +13,13 @@ * along with this program. If not, see . */ +#define _DEFAULT_SOURCE #include "os.h" #include "talgo.h" #include "tchecksum.h" #include "tcoding.h" #include "tscompression.h" #include "tsdbMain.h" -#include "tfile.h" #define TSDB_GET_COMPCOL_LEN(nCols) (sizeof(SCompData) + sizeof(SCompCol) * (nCols) + sizeof(TSCKSUM)) #define TSDB_KEY_COL_OFFSET 0 @@ -379,7 +379,7 @@ int tsdbMoveLastBlockIfNeccessary(SRWHelper *pHelper) { return -1; } - if (tsendfile(helperNewLastF(pHelper)->fd, helperLastF(pHelper)->fd, NULL, pCompBlock->len) < pCompBlock->len) { + if (taosTSendFile(helperNewLastF(pHelper)->fd, helperLastF(pHelper)->fd, NULL, pCompBlock->len) < pCompBlock->len) { tsdbError("vgId:%d failed to sendfile from file %s to file %s since %s", REPO_ID(pHelper->pRepo), helperLastF(pHelper)->fname, helperNewLastF(pHelper)->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -424,7 +424,7 @@ int tsdbWriteCompInfo(SRWHelper *pHelper) { pIdx->tid = pHelper->tableInfo.tid; ASSERT(pIdx->offset >= TSDB_FILE_HEAD_SIZE); - if (twrite(pFile->fd, (void *)(pHelper->pCompInfo), pIdx->len) < pIdx->len) { + if (taosTWrite(pFile->fd, (void *)(pHelper->pCompInfo), pIdx->len) < pIdx->len) { tsdbError("vgId:%d failed to write %d bytes to file %s since %s", REPO_ID(pHelper->pRepo), pIdx->len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -481,7 +481,7 @@ int tsdbWriteCompIdx(SRWHelper *pHelper) { pFile->info.offset = offset; - if (twrite(pFile->fd, (void *)pHelper->pWIdx, pFile->info.len) < pFile->info.len) { + if (taosTWrite(pFile->fd, (void *)pHelper->pWIdx, pFile->info.len) < pFile->info.len) { tsdbError("vgId:%d failed to write %d bytes to file %s since %s", REPO_ID(pHelper->pRepo), pFile->info.len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -514,7 +514,7 @@ int tsdbLoadCompIdx(SRWHelper *pHelper, void *target) { return -1; } - if (tread(fd, (void *)(pHelper->pBuffer), pFile->info.len) < pFile->info.len) { + if (taosTRead(fd, (void *)(pHelper->pBuffer), pFile->info.len) < pFile->info.len) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pHelper->pRepo), pFile->info.len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -585,7 +585,7 @@ int tsdbLoadCompInfo(SRWHelper *pHelper, void *target) { } pHelper->pCompInfo = trealloc((void *)pHelper->pCompInfo, pIdx->len); - if (tread(fd, (void *)(pHelper->pCompInfo), pIdx->len) < pIdx->len) { + if (taosTRead(fd, (void *)(pHelper->pCompInfo), pIdx->len) < pIdx->len) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pHelper->pRepo), pIdx->len, helperHeadF(pHelper)->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -626,7 +626,7 @@ int tsdbLoadCompData(SRWHelper *pHelper, SCompBlock *pCompBlock, void *target) { return -1; } - if (tread(pFile->fd, (void *)pHelper->pCompData, tsize) < tsize) { + if (taosTRead(pFile->fd, (void *)pHelper->pCompData, tsize) < tsize) { tsdbError("vgId:%d failed to read %zu bytes from file %s since %s", REPO_ID(pHelper->pRepo), tsize, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -841,7 +841,7 @@ static int tsdbWriteBlockToFile(SRWHelper *pHelper, SFile *pFile, SDataCols *pDa sizeof(TSCKSUM)); // Write the whole block to file - if (twrite(pFile->fd, (void *)pCompData, lsize) < lsize) { + if (taosTWrite(pFile->fd, (void *)pCompData, lsize) < lsize) { tsdbError("vgId:%d failed to write %d bytes to file %s since %s", REPO_ID(helperRepo(pHelper)), lsize, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -1222,7 +1222,7 @@ static int tsdbLoadColData(SRWHelper *pHelper, SFile *pFile, SCompBlock *pCompBl return -1; } - if (tread(pFile->fd, pHelper->pBuffer, pCompCol->len) < pCompCol->len) { + if (taosTRead(pFile->fd, pHelper->pBuffer, pCompCol->len) < pCompCol->len) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pHelper->pRepo), pCompCol->len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -1337,7 +1337,7 @@ static int tsdbLoadBlockDataImpl(SRWHelper *pHelper, SCompBlock *pCompBlock, SDa terrno = TAOS_SYSTEM_ERROR(errno); goto _err; } - if (tread(fd, (void *)pCompData, pCompBlock->len) < pCompBlock->len) { + if (taosTRead(fd, (void *)pCompData, pCompBlock->len) < pCompBlock->len) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pHelper->pRepo), pCompBlock->len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index d4350fc8b2..1969b40443 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,8 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) @@ -11,7 +11,7 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(tutil ${SRC}) - TARGET_LINK_LIBRARIES(tutil pthread os m rt lz4) + TARGET_LINK_LIBRARIES(tutil pthread osdetail m rt lz4) FIND_PATH(ICONV_INCLUDE_EXIST iconv.h /usr/include/ /usr/local/include/) IF (ICONV_INCLUDE_EXIST) ADD_DEFINITIONS(-DUSE_LIBICONV) @@ -68,44 +68,12 @@ ELSEIF (TD_WINDOWS_64) LIST(APPEND SRC ./src/tutil.c) LIST(APPEND SRC ./src/version.c) ADD_LIBRARY(tutil ${SRC}) - TARGET_LINK_LIBRARIES(tutil iconv regex pthread os winmm IPHLPAPI ws2_32 lz4) + TARGET_LINK_LIBRARIES(tutil iconv regex pthread osdetail winmm IPHLPAPI ws2_32 lz4) ELSEIF(TD_DARWIN_64) ADD_DEFINITIONS(-DUSE_LIBICONV) - LIST(APPEND SRC ./src/hash.c) - LIST(APPEND SRC ./src/ihash.c) - LIST(APPEND SRC ./src/lz4.c) - LIST(APPEND SRC ./src/shash.c) - LIST(APPEND SRC ./src/tbase64.c) - LIST(APPEND SRC ./src/tcache.c) - LIST(APPEND SRC ./src/tcompression.c) - LIST(APPEND SRC ./src/textbuffer.c) - LIST(APPEND SRC ./src/tglobalcfg.c) - LIST(APPEND SRC ./src/thash.c) - LIST(APPEND SRC ./src/thashutil.c) - LIST(APPEND SRC ./src/thistogram.c) - LIST(APPEND SRC ./src/tidpool.c) - LIST(APPEND SRC ./src/tinterpolation.c) - LIST(APPEND SRC ./src/tlog.c) - LIST(APPEND SRC ./src/tlosertree.c) - LIST(APPEND SRC ./src/tmd5.c) - LIST(APPEND SRC ./src/tmem.c) - LIST(APPEND SRC ./src/tmempool.c) - LIST(APPEND SRC ./src/tmodule.c) - LIST(APPEND SRC ./src/tnote.c) - LIST(APPEND SRC ./src/tpercentile.c) - LIST(APPEND SRC ./src/tsched.c) - LIST(APPEND SRC ./src/tskiplist.c) - LIST(APPEND SRC ./src/tsocket.c) - LIST(APPEND SRC ./src/tstrbuild.c) - LIST(APPEND SRC ./src/ttime.c) - LIST(APPEND SRC ./src/ttimer.c) - LIST(APPEND SRC ./src/ttokenizer.c) - LIST(APPEND SRC ./src/ttypes.c) - LIST(APPEND SRC ./src/tutil.c) - LIST(APPEND SRC ./src/version.c) - LIST(APPEND SRC ./src/hash.c) + AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(tutil ${SRC}) - TARGET_LINK_LIBRARIES(tutil iconv pthread os lz4) + TARGET_LINK_LIBRARIES(tutil iconv pthread osdetail lz4) ENDIF() # TARGET_LINK_LIBRARIES(tutil mstorage) diff --git a/src/util/inc/talgo.h b/src/util/inc/talgo.h index e71e340a21..5de8a302b1 100644 --- a/src/util/inc/talgo.h +++ b/src/util/inc/talgo.h @@ -20,6 +20,8 @@ extern "C" { #endif +#include "os.h" + #define TD_EQ 0x1 #define TD_GT 0x2 #define TD_LT 0x4 diff --git a/src/util/inc/tutil.h b/src/util/inc/tutil.h index 34f35c3807..4c003eeb2c 100644 --- a/src/util/inc/tutil.h +++ b/src/util/inc/tutil.h @@ -143,8 +143,6 @@ char *strbetween(char *string, char *begin, char *end); char *paGetToken(char *src, char **token, int32_t *tokenLen); -void taosMsleep(int32_t mseconds); - int32_t taosByteArrayToHexStr(char bytes[], int32_t len, char hexstr[]); int32_t taosHexStrToByteArray(char hexstr[], char bytes[]); @@ -225,6 +223,9 @@ ssize_t taos_getline(char **lineptr, size_t *n, FILE *stream, const char *file, #endif // TAOS_MEM_CHECK + +char *taosCharsetReplace(char *charsetstr); + #ifdef __cplusplus } #endif diff --git a/src/util/src/tbuffer.c b/src/util/src/tbuffer.c index 4b37cbd2d5..4af435798c 100644 --- a/src/util/src/tbuffer.c +++ b/src/util/src/tbuffer.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "os.h" #include #include #include diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 92d4b2caac..3d2df5f214 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -259,7 +259,7 @@ SCacheObj *taosCacheInit(int32_t keyType, int64_t refreshTimeInSeconds, bool ext return NULL; } - pthread_attr_t thattr = {{0}}; + pthread_attr_t thattr; pthread_attr_init(&thattr); pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); @@ -288,7 +288,7 @@ void *taosCachePut(SCacheObj *pCacheObj, const void *key, size_t keyLen, const v uDebug("cache:%s, key:%p, %p added into cache, added:%" PRIu64 ", expire:%" PRIu64 ", totalNum:%d totalSize:%" PRId64 "bytes size:%" PRId64 "bytes", pCacheObj->name, key, pNode->data, pNode->addedTime, pNode->expireTime, - (int32_t)taosHashGetSize(pCacheObj->pHashTable), pCacheObj->totalSize, dataSize); + (int32_t)taosHashGetSize(pCacheObj->pHashTable), pCacheObj->totalSize, (int64_t)dataSize); } else { uError("cache:%s, key:%p, failed to added into cache, out of memory", pCacheObj->name, key); } diff --git a/src/util/src/tkvstore.c b/src/util/src/tkvstore.c index 0704285da5..d7bf9d7857 100644 --- a/src/util/src/tkvstore.c +++ b/src/util/src/tkvstore.c @@ -12,22 +12,15 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include -#include "hash.h" +#define _DEFAULT_SOURCE #include "os.h" +#include "hash.h" #include "taoserror.h" #include "tchecksum.h" #include "tcoding.h" #include "tkvstore.h" #include "tulog.h" -#include "tfile.h" #define TD_KVSTORE_HEADER_SIZE 512 #define TD_KVSTORE_MAJOR_VERSION 1 @@ -182,7 +175,7 @@ int tdKVStoreStartCommit(SKVStore *pStore) { goto _err; } - if (tsendfile(pStore->sfd, pStore->fd, NULL, TD_KVSTORE_HEADER_SIZE) < TD_KVSTORE_HEADER_SIZE) { + if (taosTSendFile(pStore->sfd, pStore->fd, NULL, TD_KVSTORE_HEADER_SIZE) < TD_KVSTORE_HEADER_SIZE) { uError("failed to send file %d bytes since %s", TD_KVSTORE_HEADER_SIZE, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); goto _err; @@ -242,13 +235,13 @@ int tdUpdateKVStoreRecord(SKVStore *pStore, uint64_t uid, void *cont, int contLe ASSERT(tlen == POINTER_DISTANCE(pBuf, buf)); ASSERT(tlen == sizeof(SKVRecord)); - if (twrite(pStore->fd, buf, tlen) < tlen) { + if (taosTWrite(pStore->fd, buf, tlen) < tlen) { uError("failed to write %d bytes to file %s since %s", tlen, pStore->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; } - if (twrite(pStore->fd, cont, contLen) < contLen) { + if (taosTWrite(pStore->fd, cont, contLen) < contLen) { uError("failed to write %d bytes to file %s since %s", contLen, pStore->fname, strerror(errno)); return -1; } @@ -286,8 +279,8 @@ int tdDropKVStoreRecord(SKVStore *pStore, uint64_t uid) { void *pBuf = buf; tdEncodeKVRecord(&pBuf, &rInfo); - if (twrite(pStore->fd, buf, POINTER_DISTANCE(pBuf, buf)) < POINTER_DISTANCE(pBuf, buf)) { - uError("failed to write %" PRId64 " bytes to file %s since %s", POINTER_DISTANCE(pBuf, buf), pStore->fname, strerror(errno)); + if (taosTWrite(pStore->fd, buf, POINTER_DISTANCE(pBuf, buf)) < POINTER_DISTANCE(pBuf, buf)) { + uError("failed to write %" PRId64 " bytes to file %s since %s", (int64_t)(POINTER_DISTANCE(pBuf, buf)), pStore->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; } @@ -335,7 +328,7 @@ static int tdLoadKVStoreHeader(int fd, char *fname, SStoreInfo *pInfo) { return -1; } - if (tread(fd, buf, TD_KVSTORE_HEADER_SIZE) < TD_KVSTORE_HEADER_SIZE) { + if (taosTRead(fd, buf, TD_KVSTORE_HEADER_SIZE) < TD_KVSTORE_HEADER_SIZE) { uError("failed to read %d bytes from file %s since %s", TD_KVSTORE_HEADER_SIZE, fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; @@ -366,7 +359,7 @@ static int tdUpdateKVStoreHeader(int fd, char *fname, SStoreInfo *pInfo) { ASSERT(POINTER_DISTANCE(pBuf, buf) + sizeof(TSCKSUM) <= TD_KVSTORE_HEADER_SIZE); taosCalcChecksumAppend(0, (uint8_t *)buf, TD_KVSTORE_HEADER_SIZE); - if (twrite(fd, buf, TD_KVSTORE_HEADER_SIZE) < TD_KVSTORE_HEADER_SIZE) { + if (taosTWrite(fd, buf, TD_KVSTORE_HEADER_SIZE) < TD_KVSTORE_HEADER_SIZE) { uError("failed to write %d bytes to file %s since %s", TD_KVSTORE_HEADER_SIZE, fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; @@ -499,7 +492,7 @@ static int tdRestoreKVStore(SKVStore *pStore) { ASSERT(pStore->info.size == TD_KVSTORE_HEADER_SIZE); while (true) { - ssize_t tsize = tread(pStore->fd, tbuf, sizeof(SKVRecord)); + ssize_t tsize = taosTRead(pStore->fd, tbuf, sizeof(SKVRecord)); if (tsize == 0) break; if (tsize < sizeof(SKVRecord)) { uError("failed to read %zu bytes from file %s at offset %" PRId64 "since %s", sizeof(SKVRecord), pStore->fname, @@ -562,7 +555,7 @@ static int tdRestoreKVStore(SKVStore *pStore) { goto _err; } - if (tread(pStore->fd, buf, pRecord->size) < pRecord->size) { + if (taosTRead(pStore->fd, buf, pRecord->size) < pRecord->size) { uError("failed to read %" PRId64 " bytes from file %s since %s, offset %" PRId64, pRecord->size, pStore->fname, strerror(errno), pRecord->offset); terrno = TAOS_SYSTEM_ERROR(errno); diff --git a/src/util/src/tlog.c b/src/util/src/tlog.c index c2c56f29db..2489ae56be 100644 --- a/src/util/src/tlog.c +++ b/src/util/src/tlog.c @@ -301,11 +301,11 @@ static int32_t taosOpenLogFile(char *fn, int32_t maxLines, int32_t maxFileNum) { lseek(tsLogObj.logHandle->fd, 0, SEEK_END); sprintf(name, "==================================================\n"); - twrite(tsLogObj.logHandle->fd, name, (uint32_t)strlen(name)); + taosTWrite(tsLogObj.logHandle->fd, name, (uint32_t)strlen(name)); sprintf(name, " new log file \n"); - twrite(tsLogObj.logHandle->fd, name, (uint32_t)strlen(name)); + taosTWrite(tsLogObj.logHandle->fd, name, (uint32_t)strlen(name)); sprintf(name, "==================================================\n"); - twrite(tsLogObj.logHandle->fd, name, (uint32_t)strlen(name)); + taosTWrite(tsLogObj.logHandle->fd, name, (uint32_t)strlen(name)); return 0; } @@ -355,7 +355,7 @@ void taosPrintLog(const char *flags, int32_t dflag, const char *format, ...) { if (tsAsyncLog) { taosPushLogBuffer(tsLogObj.logHandle, buffer, len); } else { - twrite(tsLogObj.logHandle->fd, buffer, len); + taosTWrite(tsLogObj.logHandle->fd, buffer, len); } if (tsLogObj.maxLines > 0) { @@ -365,7 +365,7 @@ void taosPrintLog(const char *flags, int32_t dflag, const char *format, ...) { } } - if (dflag & DEBUG_SCREEN) twrite(1, buffer, (uint32_t)len); + if (dflag & DEBUG_SCREEN) taosTWrite(1, buffer, (uint32_t)len); } void taosDumpData(unsigned char *msg, int32_t len) { @@ -384,7 +384,7 @@ void taosDumpData(unsigned char *msg, int32_t len) { pos += 3; if (c >= 16) { temp[pos++] = '\n'; - twrite(tsLogObj.logHandle->fd, temp, (uint32_t)pos); + taosTWrite(tsLogObj.logHandle->fd, temp, (uint32_t)pos); c = 0; pos = 0; } @@ -392,7 +392,7 @@ void taosDumpData(unsigned char *msg, int32_t len) { temp[pos++] = '\n'; - twrite(tsLogObj.logHandle->fd, temp, (uint32_t)pos); + taosTWrite(tsLogObj.logHandle->fd, temp, (uint32_t)pos); return; } @@ -432,7 +432,7 @@ void taosPrintLongString(const char *flags, int32_t dflag, const char *format, . if (tsAsyncLog) { taosPushLogBuffer(tsLogObj.logHandle, buffer, len); } else { - twrite(tsLogObj.logHandle->fd, buffer, len); + taosTWrite(tsLogObj.logHandle->fd, buffer, len); } if (tsLogObj.maxLines > 0) { @@ -442,7 +442,7 @@ void taosPrintLongString(const char *flags, int32_t dflag, const char *format, . } } - if (dflag & DEBUG_SCREEN) twrite(1, buffer, (uint32_t)len); + if (dflag & DEBUG_SCREEN) taosTWrite(1, buffer, (uint32_t)len); } #if 0 @@ -571,7 +571,7 @@ static void *taosAsyncOutputLog(void *param) { while (1) { log_size = taosPollLogBuffer(tLogBuff, tempBuffer, TSDB_DEFAULT_LOG_BUF_UNIT); if (log_size) { - twrite(tLogBuff->fd, tempBuffer, log_size); + taosTWrite(tLogBuff->fd, tempBuffer, log_size); LOG_BUF_START(tLogBuff) = (LOG_BUF_START(tLogBuff) + log_size) % LOG_BUF_SIZE(tLogBuff); } else { break; diff --git a/src/util/src/tnote.c b/src/util/src/tnote.c index 12a7fc2b9b..fdf11eb5c4 100644 --- a/src/util/src/tnote.c +++ b/src/util/src/tnote.c @@ -264,7 +264,7 @@ void taosNotePrint(taosNoteInfo * pNote, const char * const format, ...) buffer[len] = 0; if (pNote->taosNoteFd >= 0) { - twrite(pNote->taosNoteFd, buffer, (unsigned int)len); + taosTWrite(pNote->taosNoteFd, buffer, (unsigned int)len); if (pNote->taosNoteMaxLines > 0) { pNote->taosNoteLines++; diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index 5de61a3d57..6c536a4303 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -164,7 +164,7 @@ int taosNonblockwrite(int fd, char *ptr, int nbytes) { return -1; } - nwritten = (int)send(fd, ptr, (size_t)nleft, MSG_NOSIGNAL); + nwritten = (int)taosSend(fd, ptr, (size_t)nleft, MSG_NOSIGNAL); if (nwritten <= 0) { if (errno == EAGAIN || errno == EINTR) continue; diff --git a/src/vnode/CMakeLists.txt b/src/vnode/CMakeLists.txt index a1c56b32b5..9b6b03209e 100644 --- a/src/vnode/CMakeLists.txt +++ b/src/vnode/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index dd5ec18439..77d4503d9d 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -46,15 +46,6 @@ static int vnodeGetWalInfo(void *ahandle, char *name, uint32_t *index); static void vnodeNotifyRole(void *ahandle, int8_t role); static int vnodeNotifyFileSynced(void *ahandle, uint64_t fversion); -#ifndef _SYNC -tsync_h syncStart(const SSyncInfo *info) { return NULL; } -int32_t syncForwardToPeer(tsync_h shandle, void *pHead, void *mhandle, int qtype) { return 0; } -void syncStop(tsync_h shandle) {} -int32_t syncReconfig(tsync_h shandle, const SSyncCfg * cfg) { return 0; } -int syncGetNodesRole(tsync_h shandle, SNodesRole * cfg) { return 0; } -void syncConfirmForward(tsync_h shandle, uint64_t version, int32_t code) {} -#endif - int32_t vnodeInitResources() { vnodeInitWriteFp(); vnodeInitReadFp(); @@ -289,14 +280,10 @@ int32_t vnodeOpen(int32_t vnode, char *rootDir) { syncInfo.notifyFileSynced = vnodeNotifyFileSynced; pVnode->sync = syncStart(&syncInfo); -#ifndef _SYNC - pVnode->role = TAOS_SYNC_ROLE_MASTER; -#else if (pVnode->sync == NULL) { vnodeCleanUp(pVnode); return terrno; } -#endif pVnode->qMgmt = qOpenQueryMgmt(pVnode->vgId); pVnode->events = NULL; diff --git a/src/wal/CMakeLists.txt b/src/wal/CMakeLists.txt index 684616ba0e..a9c20f643a 100644 --- a/src/wal/CMakeLists.txt +++ b/src/wal/CMakeLists.txt @@ -1,9 +1,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC) diff --git a/src/wal/src/walMain.c b/src/wal/src/walMain.c index a0e2ccb51d..43869da477 100644 --- a/src/wal/src/walMain.c +++ b/src/wal/src/walMain.c @@ -13,14 +13,7 @@ * along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include - +#define _DEFAULT_SOURCE #include "os.h" #include "tlog.h" #include "tchecksum.h" @@ -29,7 +22,6 @@ #include "taoserror.h" #include "twal.h" #include "tqueue.h" -#include "tfile.h" #define walPrefix "wal" @@ -214,7 +206,7 @@ int walWrite(void *handle, SWalHead *pHead) { taosCalcChecksumAppend(0, (uint8_t *)pHead, sizeof(SWalHead)); int contLen = pHead->len + sizeof(SWalHead); - if(twrite(pWal->fd, pHead, contLen) != contLen) { + if(taosTWrite(pWal->fd, pHead, contLen) != contLen) { wError("wal:%s, failed to write(%s)", pWal->name, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); } else { @@ -373,7 +365,7 @@ static int walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp) { wDebug("wal:%s, start to restore", name); while (1) { - int ret = tread(fd, pHead, sizeof(SWalHead)); + int ret = taosTRead(fd, pHead, sizeof(SWalHead)); if ( ret == 0) break; if (ret != sizeof(SWalHead)) { @@ -388,7 +380,7 @@ static int walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp) { break; } - ret = tread(fd, pHead->cont, pHead->len); + ret = taosTRead(fd, pHead->cont, pHead->len); if ( ret != pHead->len) { wWarn("wal:%s, failed to read body, skip, len:%d ret:%d", name, pHead->len, ret); terrno = TAOS_SYSTEM_ERROR(errno); diff --git a/src/wal/test/CMakeLists.txt b/src/wal/test/CMakeLists.txt index f007bc3882..be0b8a948d 100644 --- a/src/wal/test/CMakeLists.txt +++ b/src/wal/test/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(../inc) From 64d818516b4f2f517e8ce0319246a741d7747240 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Tue, 28 Jul 2020 03:21:15 +0000 Subject: [PATCH 39/47] [TD-992] refactor os module --- src/CMakeLists.txt | 2 + src/mnode/src/mnodeBalance.c | 70 --- src/os/darwin/CMakeLists.txt | 9 - src/os/darwin/inc/os.h | 262 ----------- src/os/darwin/src/darwinEnv.c | 30 -- src/os/darwin/src/darwinPlatform.c | 385 ----------------- src/os/linux/CMakeLists.txt | 16 - src/os/linux/inc/os.h | 294 ------------- src/os/linux/inc/tsysctl.h | 30 -- src/os/linux/src/linuxEnv.c | 30 -- src/os/linux/src/linuxPlatform.c | 318 -------------- src/os/linux/src/linuxSysPara.c | 667 ----------------------------- src/os/windows/CMakeLists.txt | 11 - src/os/windows/inc/os.h | 423 ------------------ src/os/windows/src/twindows.c | 410 ------------------ src/os/windows/src/twinenv.c | 30 -- src/os/windows/src/twingetline.c | 145 ------- src/os/windows/src/twinmsghdr.c | 57 --- src/os/windows/src/twinsocket.c | 117 ----- src/os/windows/src/twinstrptime.c | 398 ----------------- src/os/windows/src/twintcpclient.c | 39 -- src/os/windows/src/twintcpserver.c | 34 -- src/os/windows/src/twintime.c | 34 -- src/os/windows/src/twintimer.c | 54 --- src/plugins/CMakeLists.txt | 2 - src/sync/CMakeLists.txt | 2 +- src/sync/src/syncRetrieve.c | 4 +- src/sync/test/CMakeLists.txt | 2 +- src/util/inc/tfile.h | 33 -- src/util/src/tfile.c | 117 ----- tests/test/c/CMakeLists.txt | 2 +- tests/tsim/CMakeLists.txt | 2 +- 32 files changed, 8 insertions(+), 4021 deletions(-) delete mode 100644 src/mnode/src/mnodeBalance.c delete mode 100644 src/os/darwin/CMakeLists.txt delete mode 100644 src/os/darwin/inc/os.h delete mode 100644 src/os/darwin/src/darwinEnv.c delete mode 100644 src/os/darwin/src/darwinPlatform.c delete mode 100644 src/os/linux/CMakeLists.txt delete mode 100644 src/os/linux/inc/os.h delete mode 100644 src/os/linux/inc/tsysctl.h delete mode 100644 src/os/linux/src/linuxEnv.c delete mode 100644 src/os/linux/src/linuxPlatform.c delete mode 100644 src/os/linux/src/linuxSysPara.c delete mode 100644 src/os/windows/CMakeLists.txt delete mode 100644 src/os/windows/inc/os.h delete mode 100644 src/os/windows/src/twindows.c delete mode 100644 src/os/windows/src/twinenv.c delete mode 100644 src/os/windows/src/twingetline.c delete mode 100644 src/os/windows/src/twinmsghdr.c delete mode 100644 src/os/windows/src/twinsocket.c delete mode 100644 src/os/windows/src/twinstrptime.c delete mode 100644 src/os/windows/src/twintcpclient.c delete mode 100644 src/os/windows/src/twintcpserver.c delete mode 100644 src/os/windows/src/twintime.c delete mode 100644 src/os/windows/src/twintimer.c delete mode 100644 src/util/inc/tfile.h delete mode 100644 src/util/src/tfile.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 57d7234379..ede66d95bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,8 @@ ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(query) ADD_SUBDIRECTORY(kit) ADD_SUBDIRECTORY(plugins) +ADD_SUBDIRECTORY(sync) +ADD_SUBDIRECTORY(balance) ADD_SUBDIRECTORY(mnode) ADD_SUBDIRECTORY(vnode) ADD_SUBDIRECTORY(tsdb) diff --git a/src/mnode/src/mnodeBalance.c b/src/mnode/src/mnodeBalance.c deleted file mode 100644 index 95a97bd055..0000000000 --- a/src/mnode/src/mnodeBalance.c +++ /dev/null @@ -1,70 +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 "tglobal.h" -#include "mnodeDef.h" -#include "mnodeInt.h" -#include "mnodeDnode.h" -#include "mnodeSdb.h" - -#ifndef _SYNC - -int32_t balanceInit() { return TSDB_CODE_SUCCESS; } -void balanceCleanUp() {} -void balanceAsyncNotify() {} -void balanceSyncNotify() {} -void balanceReset() {} -int32_t balanceAlterDnode(struct SDnodeObj *pDnode, int32_t vnodeId, int32_t dnodeId) { return TSDB_CODE_SYN_NOT_ENABLED; } - -int32_t balanceAllocVnodes(SVgObj *pVgroup) { - void * pIter = NULL; - SDnodeObj *pDnode = NULL; - SDnodeObj *pSelDnode = NULL; - float vnodeUsage = 1000.0; - - while (1) { - pIter = mnodeGetNextDnode(pIter, &pDnode); - if (pDnode == NULL) break; - - if (pDnode->numOfCores > 0 && pDnode->openVnodes < TSDB_MAX_VNODES) { - float openVnodes = pDnode->openVnodes; - if (pDnode->isMgmt) openVnodes += tsMnodeEqualVnodeNum; - - float usage = openVnodes / pDnode->numOfCores; - if (usage <= vnodeUsage) { - pSelDnode = pDnode; - vnodeUsage = usage; - } - } - mnodeDecDnodeRef(pDnode); - } - - sdbFreeIter(pIter); - - if (pSelDnode == NULL) { - mError("failed to alloc vnode to vgroup"); - return TSDB_CODE_MND_NO_ENOUGH_DNODES; - } - - pVgroup->vnodeGid[0].dnodeId = pSelDnode->dnodeId; - pVgroup->vnodeGid[0].pDnode = pSelDnode; - - mDebug("dnode:%d, alloc one vnode to vgroup, openVnodes:%d", pSelDnode->dnodeId, pSelDnode->openVnodes); - return TSDB_CODE_SUCCESS; -} - -#endif diff --git a/src/os/darwin/CMakeLists.txt b/src/os/darwin/CMakeLists.txt deleted file mode 100644 index 116d0ec8c0..0000000000 --- a/src/os/darwin/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -IF (TD_DARWIN_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(os ${SRC}) -ENDIF () diff --git a/src/os/darwin/inc/os.h b/src/os/darwin/inc/os.h deleted file mode 100644 index 1c719933a4..0000000000 --- a/src/os/darwin/inc/os.h +++ /dev/null @@ -1,262 +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 TDENGINE_PLATFORM_LINUX_H -#define TDENGINE_PLATFORM_LINUX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define htobe64 htonll - -#define taosCloseSocket(x) \ - { \ - if (FD_VALID(x)) { \ - close(x); \ - x = FD_INITIALIZER; \ - } \ - } - -#define taosWriteSocket(fd, buf, len) write(fd, buf, len) -#define taosReadSocket(fd, buf, len) read(fd, buf, len) - -#define atomic_load_8(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_16(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_32(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_64(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_ptr(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) - -#define atomic_store_8(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_16(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_32(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_64(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_ptr(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_exchange_8(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_16(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_32(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_64(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_ptr(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_val_compare_exchange_8 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_16 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_32 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_64 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_ptr __sync_val_compare_and_swap - -#define atomic_add_fetch_8(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_16(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_32(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_64(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_ptr(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_add_8(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_16(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_32(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_64(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_ptr(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_sub_fetch_8(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_16(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_32(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_64(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_ptr(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_sub_8(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_16(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_32(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_64(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_ptr(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_and_fetch_8(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_16(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_32(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_64(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_ptr(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_and_8(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_16(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_32(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_64(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_ptr(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_or_fetch_8(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_16(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_32(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_64(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_ptr(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_or_8(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_16(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_32(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_64(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_ptr(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_xor_fetch_8(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_16(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_32(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_64(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_ptr(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_xor_8(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_16(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_32(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_64(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_ptr(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) - -#define SWAP(a, b, c) \ - do { \ - typeof(a) __tmp = (a); \ - (a) = (b); \ - (b) = __tmp; \ - } while (0) - -#define MAX(a, b) \ - ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - (__a > __b) ? __a : __b; \ - }) - -#define MIN(a, b) \ - ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - (__a < __b) ? __a : __b; \ - }) - -#define MILLISECOND_PER_SECOND ((int64_t)1000L) - -#define tsem_t dispatch_semaphore_t - -int tsem_init(dispatch_semaphore_t *sem, int pshared, unsigned int value); -int tsem_wait(dispatch_semaphore_t *sem); -int tsem_post(dispatch_semaphore_t *sem); -int tsem_destroy(dispatch_semaphore_t *sem); - -void osInit(); - -ssize_t twrite(int fd, void *buf, size_t n); - -char *taosCharsetReplace(char *charsetstr); - -bool taosCheckPthreadValid(pthread_t thread); - -void taosResetPthread(pthread_t *thread); - -int64_t taosGetPthreadId(); - -int taosSetNonblocking(int sock, int on); - -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); - -void taosPrintOsInfo(); - -char *taosCharsetReplace(char *charsetstr); - -void taosPrintOsInfo(); - -void taosGetSystemInfo(); - -void taosKillSystem(); - -bool taosSkipSocketCheck(); - -bool taosGetDisk(); - -int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count); - -void taosSetCoreDump(); - -typedef int(*__compar_fn_t)(const void *, const void *); - -// for send function in tsocket.c -#define MSG_NOSIGNAL 0 -#define SO_NO_CHECK 0x1234 -#define SOL_TCP 0x1234 -#define TCP_KEEPIDLE 0x1234 - -#ifndef PTHREAD_MUTEX_RECURSIVE_NP - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE -#endif - -#ifndef _TD_ARM_32_ -#define BUILDIN_CLZL(val) __builtin_clzl(val) -#define BUILDIN_CTZL(val) __builtin_ctzl(val) -#else -#define BUILDIN_CLZL(val) __builtin_clzll(val) -#define BUILDIN_CTZL(val) __builtin_ctzll(val) -#endif -#define BUILDIN_CLZ(val) __builtin_clz(val) -#define BUILDIN_CTZ(val) __builtin_ctz(val) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/os/darwin/src/darwinEnv.c b/src/os/darwin/src/darwinEnv.c deleted file mode 100644 index 27d5a7c99b..0000000000 --- a/src/os/darwin/src/darwinEnv.c +++ /dev/null @@ -1,30 +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 "tglobal.h" -#include "tulog.h" - -void osInit() { - strcpy(configDir, "/etc/taos"); - strcpy(tsVnodeDir, ""); - strcpy(tsDnodeDir, ""); - strcpy(tsMnodeDir, ""); - strcpy(tsDataDir, "/var/lib/taos"); - strcpy(tsLogDir, "~/TDengineLog"); - strcpy(tsScriptDir, "/etc/taos"); - strcpy(tsOsName, "Darwin"); -} diff --git a/src/os/darwin/src/darwinPlatform.c b/src/os/darwin/src/darwinPlatform.c deleted file mode 100644 index 44540cf69e..0000000000 --- a/src/os/darwin/src/darwinPlatform.c +++ /dev/null @@ -1,385 +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 "tglobal.h" -#include "taosdef.h" -#include "tutil.h" -#include "tulog.h" - -int64_t str2int64(char *str) { - char *endptr = NULL; - return strtoll(str, &endptr, 10); -} - -/* - to make taosMsleep work, - signal SIGALRM shall be blocked in the calling thread, - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_BLOCK, &set, NULL); -*/ -void taosMsleep(int mseconds) { - struct timeval timeout; - int seconds, useconds; - - seconds = mseconds / 1000; - useconds = (mseconds % 1000) * 1000; - timeout.tv_sec = seconds; - timeout.tv_usec = useconds; - - /* sigset_t set; */ - /* sigemptyset(&set); */ - /* sigaddset(&set, SIGALRM); */ - /* pthread_sigmask(SIG_BLOCK, &set, NULL); */ - - select(0, NULL, NULL, NULL, &timeout); - - /* pthread_sigmask(SIG_UNBLOCK, &set, NULL); */ -} - -bool taosCheckPthreadValid(pthread_t thread) { return thread != 0; } - -void taosResetPthread(pthread_t *thread) { *thread = 0; } - -int64_t taosGetPthreadId() { return (int64_t)pthread_self(); } - -/* -* Function to get the private ip address of current machine. If get IP -* successfully, return 0, else, return -1. The return values is ip. -* -* Use: -* if (taosGetPrivateIp(ip) != 0) { -* perror("Fail to get private IP address\n"); -* exit(EXIT_FAILURE); -* } -*/ -int taosGetPrivateIp(char *const ip) { - bool hasLoCard = false; - - struct ifaddrs *ifaddr, *ifa; - int family, s; - char host[NI_MAXHOST]; - - if (getifaddrs(&ifaddr) == -1) { - return -1; - } - - /* Walk through linked list, maintaining head pointer so we can free list later */ - int flag = 0; - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == NULL) continue; - - family = ifa->ifa_addr->sa_family; - if (strcmp("lo", ifa->ifa_name) == 0) { - hasLoCard = true; - continue; - } - - if (family == AF_INET) { - /* printf("%-8s", ifa->ifa_name); */ - s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), - host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (s != 0) { - freeifaddrs(ifaddr); - return -1; - } - - strcpy(ip, host); - flag = 1; - break; - } - } - - freeifaddrs(ifaddr); - if (flag) { - return 0; - } else { - if (hasLoCard) { - uInfo("no net card was found, use lo:127.0.0.1 as default"); - strcpy(ip, "127.0.0.1"); - return 0; - } - return -1; - } -} - -int taosSetNonblocking(int sock, int on) { - int flags = 0; - if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { - uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); - return 1; - } - - if (on) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - - if ((flags = fcntl(sock, F_SETFL, flags)) < 0) { - uError("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno)); - return 1; - } - - return 0; -} - -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { - if (level == SOL_SOCKET && optname == SO_SNDBUF) { - return 0; - } - - if (level == SOL_SOCKET && optname == SO_RCVBUF) { - return 0; - } - - return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); -} - -int taosInitTimer(void (*callback)(int), int ms) { - signal(SIGALRM, callback); - - struct itimerval tv; - tv.it_interval.tv_sec = 0; /* my timer resolution */ - tv.it_interval.tv_usec = 1000 * ms; // resolution is in msecond - tv.it_value = tv.it_interval; - - return setitimer(ITIMER_REAL, &tv, NULL); -} - -void taosUninitTimer() { - struct itimerval tv = { 0 }; - return setitimer(ITIMER_REAL, &tv, NULL); -} - -void taosGetSystemTimezone() { - // get and set default timezone - SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone"); - if (cfg_timezone && cfg_timezone->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - char *tz = getenv("TZ"); - if (tz == NULL || strlen(tz) == 0) { - strcpy(tsTimezone, "not configured"); - } - else { - strcpy(tsTimezone, tz); - } - cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("timezone not configured, use default"); - } -} - -void taosGetSystemLocale() { - // get and set default locale - SGlobalCfg *cfg_locale = taosGetConfigOption("locale"); - if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - char *locale = setlocale(LC_CTYPE, "chs"); - if (locale != NULL) { - tstrncpy(tsLocale, locale, sizeof(tsLocale)); - cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("locale not configured, set to default:%s", tsLocale); - } - } - - SGlobalCfg *cfg_charset = taosGetConfigOption("charset"); - if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - strcpy(tsCharset, "cp936"); - cfg_charset->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("charset not configured, set to default:%s", tsCharset); - } -} - - -void taosPrintOsInfo() {} - -void taosKillSystem() { - tError("function taosKillSystem, exit!"); - exit(0); -} - -bool taosGetDisk() { - return true; -} - -void taosGetSystemInfo() { - taosGetSystemTimezone(); - taosGetSystemLocale(); -} - -void *taosInitTcpClient(char *ip, uint16_t port, char *flabel, int num, void *fp, void *shandle) { - tError("function taosInitTcpClient is not implemented in darwin system, exit!"); - exit(0); -} - -void taosCloseTcpClientConnection(void *chandle) { - tError("function taosCloseTcpClientConnection is not implemented in darwin system, exit!"); - exit(0); -} - -void *taosOpenTcpClientConnection(void *shandle, void *thandle, char *ip, uint16_t port) { - tError("function taosOpenTcpClientConnection is not implemented in darwin system, exit!"); - exit(0); -} - -int taosSendTcpClientData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { - tError("function taosSendTcpClientData is not implemented in darwin system, exit!"); - exit(0); -} - -void taosCleanUpTcpClient(void *chandle) { - tError("function taosCleanUpTcpClient is not implemented in darwin system, exit!"); - exit(0); -} - -void taosCloseTcpServerConnection(void *chandle) { - tError("function taosCloseTcpServerConnection is not implemented in darwin system, exit!"); - exit(0); -} - -void taosCleanUpTcpServer(void *handle) { - tError("function taosCleanUpTcpServer is not implemented in darwin system, exit!"); - exit(0); -} - -void *taosInitTcpServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) { - tError("function taosInitTcpServer is not implemented in darwin system, exit!"); - exit(0); -} - -int taosSendTcpServerData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { - tError("function taosSendTcpServerData is not implemented in darwin system, exit!"); - exit(0); -} - -void taosFreeMsgHdr(void *hdr) { - tError("function taosFreeMsgHdr is not implemented in darwin system, exit!"); - exit(0); -} - -int taosMsgHdrSize(void *hdr) { - tError("function taosMsgHdrSize is not implemented in darwin system, exit!"); - exit(0); -} - -void taosSendMsgHdr(void *hdr, int fd) { - tError("function taosSendMsgHdr is not implemented in darwin system, exit!"); - exit(0); -} - -void taosInitMsgHdr(void **hdr, void *dest, int maxPkts) { - tError("function taosInitMsgHdr is not implemented in darwin system, exit!"); - exit(0); -} - -void taosSetMsgHdrData(void *hdr, char *data, int dataLen) { - tError("function taosSetMsgHdrData is not implemented in darwin system, exit!"); - exit(0); -} - -ssize_t twrite(int fd, void *buf, size_t n) { - size_t nleft = n; - ssize_t nwritten = 0; - char *tbuf = (char *)buf; - - while (nleft > 0) { - nwritten = write(fd, (void *)tbuf, nleft); - if (nwritten < 0) { - if (errno == EINTR) { - continue; - } - return -1; - } - nleft -= nwritten; - tbuf += nwritten; - } - - return n; -} - -bool taosSkipSocketCheck() { - return true; -} - -int tsem_init(dispatch_semaphore_t *sem, int pshared, unsigned int value) { - *sem = dispatch_semaphore_create(value); - if (*sem == NULL) { - return -1; - } else { - return 0; - } -} - -int tsem_wait(dispatch_semaphore_t *sem) { - dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER); - return 0; -} - -int tsem_post(dispatch_semaphore_t *sem) { - dispatch_semaphore_signal(*sem); - return 0; -} - -int tsem_destroy(dispatch_semaphore_t *sem) { - return 0; -} - -int32_t __sync_val_load_32(int32_t *ptr) { - return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); -} - -void __sync_val_restore_32(int32_t *ptr, int32_t newval) { - __atomic_store_n(ptr, newval, __ATOMIC_RELEASE); -} - -#define _SEND_FILE_STEP_ 1000 - -int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count) { - fseek(in_file, (int32_t)(*offset), 0); - int writeLen = 0; - uint8_t buffer[_SEND_FILE_STEP_] = { 0 }; - - for (int len = 0; len < (count - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) { - size_t rlen = fread(buffer, 1, _SEND_FILE_STEP_, in_file); - if (rlen <= 0) { - return writeLen; - } - else if (rlen < _SEND_FILE_STEP_) { - fwrite(buffer, 1, rlen, out_file); - return (int)(writeLen + rlen); - } - else { - fwrite(buffer, 1, _SEND_FILE_STEP_, in_file); - writeLen += _SEND_FILE_STEP_; - } - } - - int remain = count - writeLen; - if (remain > 0) { - size_t rlen = fread(buffer, 1, remain, in_file); - if (rlen <= 0) { - return writeLen; - } - else { - fwrite(buffer, 1, remain, out_file); - writeLen += remain; - } - } - - return writeLen; -} - -void taosSetCoreDump() {} diff --git a/src/os/linux/CMakeLists.txt b/src/os/linux/CMakeLists.txt deleted file mode 100644 index 7be4a13f25..0000000000 --- a/src/os/linux/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) - - ADD_LIBRARY(os ${SRC}) - TARGET_LINK_LIBRARIES(os m rt) -ENDIF () - -SET_SOURCE_FILES_PROPERTIES(src/linuxSysPara.c PROPERTIES COMPILE_FLAGS -w) diff --git a/src/os/linux/inc/os.h b/src/os/linux/inc/os.h deleted file mode 100644 index 00b9f33f1b..0000000000 --- a/src/os/linux/inc/os.h +++ /dev/null @@ -1,294 +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 TDENGINE_PLATFORM_LINUX_H -#define TDENGINE_PLATFORM_LINUX_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define taosCloseSocket(x) \ - { \ - if (FD_VALID(x)) { \ - close(x); \ - x = FD_INITIALIZER; \ - } \ - } - -#ifdef TAOS_RANDOM_NETWORK_FAIL - -ssize_t taos_send_random_fail(int sockfd, const void *buf, size_t len, int flags); - -ssize_t taos_sendto_random_fail(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen); -ssize_t taos_read_random_fail(int fd, void *buf, size_t count); -ssize_t taos_write_random_fail(int fd, const void *buf, size_t count); - -#define send(sockfd, buf, len, flags) taos_send_random_fail(sockfd, buf, len, flags) -#define sendto(sockfd, buf, len, flags, dest_addr, addrlen) \ - taos_sendto_random_fail(sockfd, buf, len, flags, dest_addr, addrlen) -#define taosWriteSocket(fd, buf, len) taos_write_random_fail(fd, buf, len) -#define taosReadSocket(fd, buf, len) taos_read_random_fail(fd, buf, len) - -#else - -#define taosWriteSocket(fd, buf, len) write(fd, buf, len) -#define taosReadSocket(fd, buf, len) read(fd, buf, len) - -#endif /* TAOS_RANDOM_NETWORK_FAIL */ - -#define atomic_load_8(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_16(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_32(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_64(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) -#define atomic_load_ptr(ptr) __atomic_load_n((ptr), __ATOMIC_SEQ_CST) - -#define atomic_store_8(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_16(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_32(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_64(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_store_ptr(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_exchange_8(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_16(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_32(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_64(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_exchange_ptr(ptr, val) __atomic_exchange_n((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_val_compare_exchange_8 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_16 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_32 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_64 __sync_val_compare_and_swap -#define atomic_val_compare_exchange_ptr __sync_val_compare_and_swap - -#define atomic_add_fetch_8(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_16(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_32(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_64(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_add_fetch_ptr(ptr, val) __atomic_add_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_add_8(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_16(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_32(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_64(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_add_ptr(ptr, val) __atomic_fetch_add((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_sub_fetch_8(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_16(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_32(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_64(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_sub_fetch_ptr(ptr, val) __atomic_sub_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_sub_8(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_16(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_32(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_64(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_sub_ptr(ptr, val) __atomic_fetch_sub((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_and_fetch_8(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_16(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_32(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_64(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_and_fetch_ptr(ptr, val) __atomic_and_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_and_8(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_16(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_32(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_64(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_and_ptr(ptr, val) __atomic_fetch_and((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_or_fetch_8(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_16(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_32(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_64(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_or_fetch_ptr(ptr, val) __atomic_or_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_or_8(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_16(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_32(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_64(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_or_ptr(ptr, val) __atomic_fetch_or((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_xor_fetch_8(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_16(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_32(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_64(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_xor_fetch_ptr(ptr, val) __atomic_xor_fetch((ptr), (val), __ATOMIC_SEQ_CST) - -#define atomic_fetch_xor_8(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_16(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_32(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_64(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) -#define atomic_fetch_xor_ptr(ptr, val) __atomic_fetch_xor((ptr), (val), __ATOMIC_SEQ_CST) - -#define SWAP(a, b, c) \ - do { \ - typeof(a) __tmp = (a); \ - (a) = (b); \ - (b) = __tmp; \ - } while (0) - -#define MAX(a, b) \ - ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - (__a > __b) ? __a : __b; \ - }) - -#define MIN(a, b) \ - ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - (__a < __b) ? __a : __b; \ - }) - -#define MILLISECOND_PER_SECOND ((int64_t)1000L) - -#define tsem_t sem_t -#define tsem_init sem_init -#define tsem_wait sem_wait -#define tsem_post sem_post -#define tsem_destroy sem_destroy - -void osInit(); - -ssize_t tsendfile(int dfd, int sfd, off_t *offset, size_t size); - -ssize_t twrite(int fd, void *buf, size_t n); - -ssize_t tread(int fd, void *buf, size_t count); - -bool taosCheckPthreadValid(pthread_t thread); - -void taosResetPthread(pthread_t *thread); - -int64_t taosGetPthreadId(); - -int taosSetNonblocking(int sock, int on); - -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); - -void taosPrintOsInfo(); - -char *taosCharsetReplace(char *charsetstr); - -void taosGetSystemInfo(); - -void taosKillSystem(); - -bool taosSkipSocketCheck(); - -int64_t str2int64(char *str); - -void taosSetCoreDump(); - -void taosBlockSIGPIPE(); - -int tSystem(const char * cmd) ; - - -#ifdef _ALPINE - typedef int(*__compar_fn_t)(const void *, const void *); - void error (int, int, const char *); - #ifndef PTHREAD_MUTEX_RECURSIVE_NP - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE - #endif -#endif - -#ifndef _TD_ARM_32_ -#define BUILDIN_CLZL(val) __builtin_clzl(val) -#define BUILDIN_CTZL(val) __builtin_ctzl(val) -#else -#define BUILDIN_CLZL(val) __builtin_clzll(val) -#define BUILDIN_CTZL(val) __builtin_ctzll(val) -#endif -#define BUILDIN_CLZ(val) __builtin_clz(val) -#define BUILDIN_CTZ(val) __builtin_ctz(val) - -#undef threadlocal -#ifdef _ISOC11_SOURCE - #define threadlocal _Thread_local -#elif defined(__APPLE__) - #define threadlocal -#elif defined(__GNUC__) && !defined(threadlocal) - #define threadlocal __thread -#else - #define threadlocal -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/os/linux/inc/tsysctl.h b/src/os/linux/inc/tsysctl.h deleted file mode 100644 index 559d5653ee..0000000000 --- a/src/os/linux/inc/tsysctl.h +++ /dev/null @@ -1,30 +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 TDENGINE_TSYSCTL_H -#define TDENGINE_TSYSCTL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ALPINE - #include - #include -#else - #include -#endif - -#endif diff --git a/src/os/linux/src/linuxEnv.c b/src/os/linux/src/linuxEnv.c deleted file mode 100644 index 0a9d81311a..0000000000 --- a/src/os/linux/src/linuxEnv.c +++ /dev/null @@ -1,30 +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 "tglobal.h" -#include "tulog.h" - -void osInit() { - strcpy(configDir, "/etc/taos"); - strcpy(tsVnodeDir, ""); - strcpy(tsDnodeDir, ""); - strcpy(tsMnodeDir, ""); - strcpy(tsDataDir, "/var/lib/taos"); - strcpy(tsLogDir, "/var/log/taos"); - strcpy(tsScriptDir, "/etc/taos"); - strcpy(tsOsName, "Linux"); -} \ No newline at end of file diff --git a/src/os/linux/src/linuxPlatform.c b/src/os/linux/src/linuxPlatform.c deleted file mode 100644 index 216d8942bc..0000000000 --- a/src/os/linux/src/linuxPlatform.c +++ /dev/null @@ -1,318 +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 "taosdef.h" -#include "tglobal.h" -#include "ttimer.h" -#include "tulog.h" -#include "tutil.h" - -int64_t str2int64(char *str) { - char *endptr = NULL; - return strtoll(str, &endptr, 10); -} - -/* - to make taosMsleep work, - signal SIGALRM shall be blocked in the calling thread, - - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGALRM); - pthread_sigmask(SIG_BLOCK, &set, NULL); -*/ -void taosMsleep(int mseconds) { - struct timeval timeout; - int seconds, useconds; - - seconds = mseconds / 1000; - useconds = (mseconds % 1000) * 1000; - timeout.tv_sec = seconds; - timeout.tv_usec = useconds; - - /* sigset_t set; */ - /* sigemptyset(&set); */ - /* sigaddset(&set, SIGALRM); */ - /* pthread_sigmask(SIG_BLOCK, &set, NULL); */ - - select(0, NULL, NULL, NULL, &timeout); - - /* pthread_sigmask(SIG_UNBLOCK, &set, NULL); */ -} - -bool taosCheckPthreadValid(pthread_t thread) { return thread != 0; } - -int64_t taosGetPthreadId() { return (int64_t)pthread_self(); } - -int taosSetNonblocking(int sock, int on) { - int flags = 0; - if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { - uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); - return 1; - } - - if (on) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - - if ((flags = fcntl(sock, F_SETFL, flags)) < 0) { - uError("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno)); - return 1; - } - - return 0; -} - -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { - return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); -} -static void taosDeleteTimer(void *tharg) { - timer_t *pTimer = tharg; - timer_delete(*pTimer); -} - -static pthread_t timerThread; -static timer_t timerId; -static volatile bool stopTimer = false; - -void *taosProcessAlarmSignal(void *tharg) { - // Block the signal - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGALRM); - sigprocmask(SIG_BLOCK, &sigset, NULL); - void (*callback)(int) = tharg; - - struct sigevent sevent = {{0}}; - - #ifdef _ALPINE - sevent.sigev_notify = SIGEV_THREAD; - sevent.sigev_value.sival_int = syscall(__NR_gettid); - #else - sevent.sigev_notify = SIGEV_THREAD_ID; - sevent._sigev_un._tid = syscall(__NR_gettid); - #endif - - sevent.sigev_signo = SIGALRM; - - if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) { - uError("Failed to create timer"); - } - - pthread_cleanup_push(taosDeleteTimer, &timerId); - - struct itimerspec ts; - ts.it_value.tv_sec = 0; - ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK; - ts.it_interval.tv_sec = 0; - ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK; - - if (timer_settime(timerId, 0, &ts, NULL)) { - uError("Failed to init timer"); - return NULL; - } - - int signo; - while (!stopTimer) { - if (sigwait(&sigset, &signo)) { - uError("Failed to wait signal: number %d", signo); - continue; - } - /* printf("Signal handling: number %d ......\n", signo); */ - - callback(0); - } - - pthread_cleanup_pop(1); - - return NULL; -} - - -int taosInitTimer(void (*callback)(int), int ms) { - pthread_attr_t tattr; - pthread_attr_init(&tattr); - int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback); - pthread_attr_destroy(&tattr); - if (code != 0) { - uError("failed to create timer thread"); - return -1; - } - return 0; -} - -void taosUninitTimer() { - stopTimer = true; - pthread_join(timerThread, NULL); -} - -ssize_t tread(int fd, void *buf, size_t count) { - size_t leftbytes = count; - ssize_t readbytes; - char * tbuf = (char *)buf; - - while (leftbytes > 0) { - readbytes = read(fd, (void *)tbuf, leftbytes); - if (readbytes < 0) { - if (errno == EINTR) { - continue; - } else { - return -1; - } - } else if (readbytes == 0) { - return (ssize_t)(count - leftbytes); - } - - leftbytes -= readbytes; - tbuf += readbytes; - } - - return (ssize_t)count; -} - -ssize_t tsendfile(int dfd, int sfd, off_t *offset, size_t size) { - size_t leftbytes = size; - ssize_t sentbytes; - - while (leftbytes > 0) { - /* - * TODO : Think to check if file is larger than 1GB - */ - //if (leftbytes > 1000000000) leftbytes = 1000000000; - sentbytes = sendfile(dfd, sfd, offset, leftbytes); - if (sentbytes == -1) { - if (errno == EINTR) { - continue; - } - else { - return -1; - } - } else if (sentbytes == 0) { - return (ssize_t)(size - leftbytes); - } - - leftbytes -= sentbytes; - } - - return size; -} - -ssize_t twrite(int fd, void *buf, size_t n) { - size_t nleft = n; - ssize_t nwritten = 0; - char *tbuf = (char *)buf; - - while (nleft > 0) { - nwritten = write(fd, (void *)tbuf, nleft); - if (nwritten < 0) { - if (errno == EINTR) { - continue; - } - return -1; - } - nleft -= nwritten; - tbuf += nwritten; - } - - return n; -} - -void taosBlockSIGPIPE() { - sigset_t signal_mask; - sigemptyset(&signal_mask); - sigaddset(&signal_mask, SIGPIPE); - int rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); - if (rc != 0) { - uError("failed to block SIGPIPE"); - } -} - -int tSystem(const char * cmd) -{ - FILE * fp; - int res; - char buf[1024]; - if (cmd == NULL) { - uError("tSystem cmd is NULL!\n"); - return -1; - } - - if ((fp = popen(cmd, "r") ) == NULL) { - uError("popen cmd:%s error: %s/n", cmd, strerror(errno)); - return -1; - } else { - while(fgets(buf, sizeof(buf), fp)) { - uDebug("popen result:%s", buf); - } - - if ((res = pclose(fp)) == -1) { - uError("close popen file pointer fp error!\n"); - } else { - uDebug("popen res is :%d\n", res); - } - - return res; - } -} - -#ifdef TAOS_RANDOM_NETWORK_FAIL - -#define RANDOM_NETWORK_FAIL_FACTOR 20 - -ssize_t taos_send_random_fail(int sockfd, const void *buf, size_t len, int flags) -{ - if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { - errno = ECONNRESET; - return -1; - } - - return send(sockfd, buf, len, flags); -} - -ssize_t taos_sendto_random_fail(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen) -{ - if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { - errno = ECONNRESET; - return -1; - } - - return sendto(sockfd, buf, len, flags, dest_addr, addrlen); -} - -ssize_t taos_read_random_fail(int fd, void *buf, size_t count) -{ - if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { - errno = ECONNRESET; - return -1; - } - - return read(fd, buf, count); -} - -ssize_t taos_write_random_fail(int fd, const void *buf, size_t count) -{ - if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) { - errno = EINTR; - return -1; - } - - return write(fd, buf, count); -} - -#endif /* TAOS_RANDOM_NETWORK_FAIL */ diff --git a/src/os/linux/src/linuxSysPara.c b/src/os/linux/src/linuxSysPara.c deleted file mode 100644 index 1331503619..0000000000 --- a/src/os/linux/src/linuxSysPara.c +++ /dev/null @@ -1,667 +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 "tsysctl.h" -#include "tconfig.h" -#include "tglobal.h" -#include "tulog.h" -#include "tutil.h" -#include "tsystem.h" - -#define PROCESS_ITEM 12 - -typedef struct { - uint64_t user; - uint64_t nice; - uint64_t system; - uint64_t idle; -} SysCpuInfo; - -typedef struct { - uint64_t utime; // user time - uint64_t stime; // kernel time - uint64_t cutime; // all user time - uint64_t cstime; // all dead time -} ProcCpuInfo; - -static pid_t tsProcId; -static char tsSysNetFile[] = "/proc/net/dev"; -static char tsSysCpuFile[] = "/proc/stat"; -static char tsProcCpuFile[25] = {0}; -static char tsProcMemFile[25] = {0}; -static char tsProcIOFile[25] = {0}; -static float tsPageSizeKB = 0; - -bool taosGetSysMemory(float *memoryUsedMB) { - float memoryAvailMB = (float)sysconf(_SC_AVPHYS_PAGES) * tsPageSizeKB / 1024; - *memoryUsedMB = (float)tsTotalMemoryMB - memoryAvailMB; - return true; -} - -bool taosGetProcMemory(float *memoryUsedMB) { - FILE *fp = fopen(tsProcMemFile, "r"); - if (fp == NULL) { - uError("open file:%s failed", tsProcMemFile); - return false; - } - - size_t len; - char * line = NULL; - while (!feof(fp)) { - tfree(line); - len = 0; - getline(&line, &len, fp); - if (line == NULL) { - break; - } - if (strstr(line, "VmRSS:") != NULL) { - break; - } - } - - if (line == NULL) { - uError("read file:%s failed", tsProcMemFile); - fclose(fp); - return false; - } - - int64_t memKB = 0; - char tmp[10]; - sscanf(line, "%s %" PRId64, tmp, &memKB); - *memoryUsedMB = (float)((double)memKB / 1024); - - tfree(line); - fclose(fp); - return true; -} - -static bool taosGetSysCpuInfo(SysCpuInfo *cpuInfo) { - FILE *fp = fopen(tsSysCpuFile, "r"); - if (fp == NULL) { - uError("open file:%s failed", tsSysCpuFile); - return false; - } - - size_t len; - char * line = NULL; - getline(&line, &len, fp); - if (line == NULL) { - uError("read file:%s failed", tsSysCpuFile); - fclose(fp); - return false; - } - - char cpu[10] = {0}; - sscanf(line, "%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, cpu, &cpuInfo->user, &cpuInfo->nice, &cpuInfo->system, &cpuInfo->idle); - - tfree(line); - fclose(fp); - return true; -} - -static bool taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) { - FILE *fp = fopen(tsProcCpuFile, "r"); - if (fp == NULL) { - uError("open file:%s failed", tsProcCpuFile); - return false; - } - - size_t len = 0; - char * line = NULL; - getline(&line, &len, fp); - if (line == NULL) { - uError("read file:%s failed", tsProcCpuFile); - fclose(fp); - return false; - } - - for (int i = 0, blank = 0; line[i] != 0; ++i) { - if (line[i] == ' ') blank++; - if (blank == PROCESS_ITEM) { - sscanf(line + i + 1, "%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &cpuInfo->utime, &cpuInfo->stime, &cpuInfo->cutime, &cpuInfo->cstime); - break; - } - } - - tfree(line); - fclose(fp); - return true; -} - -static void taosGetSystemTimezone() { - SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone"); - if (cfg_timezone == NULL) return; - if (cfg_timezone->cfgStatus >= TAOS_CFG_CSTATUS_DEFAULT) { - return; - } - - /* - * NOTE: do not remove it. - * Enforce set the correct daylight saving time(DST) flag according - * to current time - */ - time_t tx1 = time(NULL); - struct tm tm1; - localtime_r(&tx1, &tm1); - - /* load time zone string from /etc/timezone */ - FILE *f = fopen("/etc/timezone", "r"); - char buf[68] = {0}; - if (f != NULL) { - int len = fread(buf, 64, 1, f); - if(len < 64 && ferror(f)) { - fclose(f); - uError("read /etc/timezone error, reason:%s", strerror(errno)); - return; - } - - fclose(f); - - char *lineEnd = strstr(buf, "\n"); - if (lineEnd != NULL) { - *lineEnd = 0; - } - - // for CentOS system, /etc/timezone does not exist. Ignore the TZ environment variables - if (strlen(buf) > 0) { - setenv("TZ", buf, 1); - } - } - // get and set default timezone - tzset(); - - /* - * get CURRENT time zone. - * system current time zone is affected by daylight saving time(DST) - * - * e.g., the local time zone of London in DST is GMT+01:00, - * otherwise is GMT+00:00 - */ - int32_t tz = (-timezone * MILLISECOND_PER_SECOND) / MILLISECOND_PER_HOUR; - tz += daylight; - - /* - * format example: - * - * Asia/Shanghai (CST, +0800) - * Europe/London (BST, +0100) - */ - sprintf(tsTimezone, "%s (%s, %s%02d00)", buf, tzname[daylight], tz >= 0 ? "+" : "-", abs(tz)); - - // cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("timezone not configured, set to system default:%s", tsTimezone); -} - -/* - * POSIX format locale string: - * (Language Strings)_(Country/Region Strings).(code_page) - * - * example: en_US.UTF-8, zh_CN.GB18030, zh_CN.UTF-8, - * - * if user does not specify the locale in taos.cfg the program use default LC_CTYPE as system locale. - * - * In case of some CentOS systems, their default locale is "en_US.utf8", which is not valid code_page - * for libiconv that is employed to convert string in this system. This program will automatically use - * UTF-8 instead as the charset. - * - * In case of windows client, the locale string is not valid POSIX format, user needs to set the - * correct code_page for libiconv. Usually, the code_page of windows system with simple chinese is - * CP936, CP437 for English charset. - * - */ -static void taosGetSystemLocale() { // get and set default locale - char sep = '.'; - char *locale = NULL; - - SGlobalCfg *cfg_locale = taosGetConfigOption("locale"); - if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - locale = setlocale(LC_CTYPE, ""); - if (locale == NULL) { - uError("can't get locale from system, set it to en_US.UTF-8"); - strcpy(tsLocale, "en_US.UTF-8"); - } else { - tstrncpy(tsLocale, locale, sizeof(tsLocale)); - uError("locale not configured, set to system default:%s", tsLocale); - } - } - - /* if user does not specify the charset, extract it from locale */ - SGlobalCfg *cfg_charset = taosGetConfigOption("charset"); - if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - char *str = strrchr(tsLocale, sep); - if (str != NULL) { - str++; - - char *revisedCharset = taosCharsetReplace(str); - tstrncpy(tsCharset, revisedCharset, sizeof(tsCharset)); - - free(revisedCharset); - uWarn("charset not configured, set to system default:%s", tsCharset); - } else { - strcpy(tsCharset, "UTF-8"); - uWarn("can't get locale and charset from system, set it to UTF-8"); - } - } -} - -bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) { - static uint64_t lastSysUsed = 0; - static uint64_t lastSysTotal = 0; - static uint64_t lastProcTotal = 0; - - SysCpuInfo sysCpu; - ProcCpuInfo procCpu; - if (!taosGetSysCpuInfo(&sysCpu)) { - return false; - } - if (!taosGetProcCpuInfo(&procCpu)) { - return false; - } - - uint64_t curSysUsed = sysCpu.user + sysCpu.nice + sysCpu.system; - uint64_t curSysTotal = curSysUsed + sysCpu.idle; - uint64_t curProcTotal = procCpu.utime + procCpu.stime + procCpu.cutime + procCpu.cstime; - - if (lastSysUsed == 0 || lastSysTotal == 0 || lastProcTotal == 0) { - lastSysUsed = curSysUsed > 1 ? curSysUsed : 1; - lastSysTotal = curSysTotal > 1 ? curSysTotal : 1; - lastProcTotal = curProcTotal > 1 ? curProcTotal : 1; - return false; - } - - if (curSysTotal == lastSysTotal) { - return false; - } - - *sysCpuUsage = (float)((double)(curSysUsed - lastSysUsed) / (double)(curSysTotal - lastSysTotal) * 100); - *procCpuUsage = (float)((double)(curProcTotal - lastProcTotal) / (double)(curSysTotal - lastSysTotal) * 100); - - lastSysUsed = curSysUsed; - lastSysTotal = curSysTotal; - lastProcTotal = curProcTotal; - - return true; -} - -bool taosGetDisk() { - struct statvfs info; - const double unit = 1024 * 1024 * 1024; - - if (tscEmbedded) { - if (statvfs(tsDataDir, &info)) { - //tsTotalDataDirGB = 0; - //tsAvailDataDirGB = 0; - uError("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno)); - return false; - } else { - tsTotalDataDirGB = (float)((double)info.f_blocks * (double)info.f_frsize / unit); - tsAvailDataDirGB = (float)((double)info.f_bavail * (double)info.f_frsize / unit); - } - } - - if (statvfs(tsLogDir, &info)) { - //tsTotalLogDirGB = 0; - //tsAvailLogDirGB = 0; - uError("failed to get disk size, logDir:%s errno:%s", tsLogDir, strerror(errno)); - return false; - } else { - tsTotalLogDirGB = (float)((double)info.f_blocks * (double)info.f_frsize / unit); - tsAvailLogDirGB = (float)((double)info.f_bavail * (double)info.f_frsize / unit); - } - - if (statvfs("/tmp", &info)) { - //tsTotalTmpDirGB = 0; - //tsAvailTmpDirectorySpace = 0; - uError("failed to get disk size, tmpDir:/tmp errno:%s", strerror(errno)); - return false; - } else { - tsTotalTmpDirGB = (float)((double)info.f_blocks * (double)info.f_frsize / unit); - tsAvailTmpDirectorySpace = (float)((double)info.f_bavail * (double)info.f_frsize / unit); - } - - return true; -} - -static bool taosGetCardInfo(int64_t *bytes) { - *bytes = 0; - FILE *fp = fopen(tsSysNetFile, "r"); - if (fp == NULL) { - uError("open file:%s failed", tsSysNetFile); - return false; - } - - - size_t len = 2048; - char * line = calloc(1, len); - - while (!feof(fp)) { - memset(line, 0, len); - - int64_t rbytes = 0; - int64_t rpackts = 0; - int64_t tbytes = 0; - int64_t tpackets = 0; - int64_t nouse1 = 0; - int64_t nouse2 = 0; - int64_t nouse3 = 0; - int64_t nouse4 = 0; - int64_t nouse5 = 0; - int64_t nouse6 = 0; - char nouse0[200] = {0}; - - getline(&line, &len, fp); - line[len - 1] = 0; - - if (strstr(line, "lo:") != NULL) { - continue; - } - - sscanf(line, - "%s %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 " %" PRId64 - " %" PRId64, - nouse0, &rbytes, &rpackts, &nouse1, &nouse2, &nouse3, &nouse4, &nouse5, &nouse6, &tbytes, &tpackets); - *bytes += (rbytes + tbytes); - } - - tfree(line); - fclose(fp); - - return true; -} - -bool taosGetBandSpeed(float *bandSpeedKb) { - static int64_t lastBytes = 0; - static time_t lastTime = 0; - int64_t curBytes = 0; - time_t curTime = time(NULL); - - if (!taosGetCardInfo(&curBytes)) { - return false; - } - - if (lastTime == 0 || lastBytes == 0) { - lastTime = curTime; - lastBytes = curBytes; - *bandSpeedKb = 0; - return true; - } - - if (lastTime >= curTime || lastBytes > curBytes) { - lastTime = curTime; - lastBytes = curBytes; - *bandSpeedKb = 0; - return true; - } - - double totalBytes = (double)(curBytes - lastBytes) / 1024 * 8; // Kb - *bandSpeedKb = (float)(totalBytes / (double)(curTime - lastTime)); - - // uInfo("bandwidth lastBytes:%ld, lastTime:%ld, curBytes:%ld, curTime:%ld, - // speed:%f", lastBytes, lastTime, curBytes, curTime, *bandSpeed); - - lastTime = curTime; - lastBytes = curBytes; - - return true; -} - -static bool taosReadProcIO(int64_t *readbyte, int64_t *writebyte) { - FILE *fp = fopen(tsProcIOFile, "r"); - if (fp == NULL) { - uError("open file:%s failed", tsProcIOFile); - return false; - } - - size_t len; - char * line = NULL; - char tmp[10]; - int readIndex = 0; - - while (!feof(fp)) { - tfree(line); - len = 0; - getline(&line, &len, fp); - if (line == NULL) { - break; - } - if (strstr(line, "rchar:") != NULL) { - sscanf(line, "%s %" PRId64, tmp, readbyte); - readIndex++; - } else if (strstr(line, "wchar:") != NULL) { - sscanf(line, "%s %" PRId64, tmp, writebyte); - readIndex++; - } else { - } - - if (readIndex >= 2) break; - } - - tfree(line); - fclose(fp); - - if (readIndex < 2) { - uError("read file:%s failed", tsProcIOFile); - return false; - } - - return true; -} - -bool taosGetProcIO(float *readKB, float *writeKB) { - static int64_t lastReadbyte = -1; - static int64_t lastWritebyte = -1; - - int64_t curReadbyte = 0; - int64_t curWritebyte = 0; - - if (!taosReadProcIO(&curReadbyte, &curWritebyte)) { - return false; - } - - if (lastReadbyte == -1 || lastWritebyte == -1) { - lastReadbyte = curReadbyte; - lastWritebyte = curWritebyte; - return false; - } - - *readKB = (float)((double)(curReadbyte - lastReadbyte) / 1024); - *writeKB = (float)((double)(curWritebyte - lastWritebyte) / 1024); - if (*readKB < 0) *readKB = 0; - if (*writeKB < 0) *writeKB = 0; - - lastReadbyte = curReadbyte; - lastWritebyte = curWritebyte; - - return true; -} - -void taosGetSystemInfo() { - tsNumOfCores = (int32_t)sysconf(_SC_NPROCESSORS_ONLN); - tsPageSize = sysconf(_SC_PAGESIZE); - tsOpenMax = sysconf(_SC_OPEN_MAX); - tsStreamMax = sysconf(_SC_STREAM_MAX); - - tsProcId = (pid_t)syscall(SYS_gettid); - tsPageSizeKB = (float)(sysconf(_SC_PAGESIZE)) / 1024; - tsTotalMemoryMB = (int32_t)((float)sysconf(_SC_PHYS_PAGES) * tsPageSizeKB / 1024); - - snprintf(tsProcMemFile, 25, "/proc/%d/status", tsProcId); - snprintf(tsProcCpuFile, 25, "/proc/%d/stat", tsProcId); - snprintf(tsProcIOFile, 25, "/proc/%d/io", tsProcId); - - float tmp1, tmp2; - taosGetSysMemory(&tmp1); - taosGetProcMemory(&tmp2); - taosGetDisk(); - taosGetBandSpeed(&tmp1); - taosGetCpuUsage(&tmp1, &tmp2); - taosGetProcIO(&tmp1, &tmp2); - - taosGetSystemTimezone(); - taosGetSystemLocale(); -} - -void taosPrintOsInfo() { - uInfo(" os pageSize: %" PRId64 "(KB)", tsPageSize); - uInfo(" os openMax: %" PRId64, tsOpenMax); - uInfo(" os streamMax: %" PRId64, tsStreamMax); - uInfo(" os numOfCores: %d", tsNumOfCores); - uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB); - uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB); - - struct utsname buf; - if (uname(&buf)) { - uInfo(" can't fetch os info"); - return; - } - uInfo(" os sysname: %s", buf.sysname); - uInfo(" os nodename: %s", buf.nodename); - uInfo(" os release: %s", buf.release); - uInfo(" os version: %s", buf.version); - uInfo(" os machine: %s", buf.machine); - uInfo("=================================="); -} - -void taosKillSystem() { - // SIGINT - uInfo("taosd will shut down soon"); - kill(tsProcId, 2); -} - -int _sysctl(struct __sysctl_args *args ); -void taosSetCoreDump() { - if (0 == tsEnableCoreFile) { - return; - } - - // 1. set ulimit -c unlimited - struct rlimit rlim; - struct rlimit rlim_new; - if (getrlimit(RLIMIT_CORE, &rlim) == 0) { - uInfo("the old unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max); - rlim_new.rlim_cur = RLIM_INFINITY; - rlim_new.rlim_max = RLIM_INFINITY; - if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) { - uInfo("set unlimited fail, error: %s", strerror(errno)); - rlim_new.rlim_cur = rlim.rlim_max; - rlim_new.rlim_max = rlim.rlim_max; - (void)setrlimit(RLIMIT_CORE, &rlim_new); - } - } - - if (getrlimit(RLIMIT_CORE, &rlim) == 0) { - uInfo("the new unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max); - } - -#ifndef _TD_ARM_ - // 2. set the path for saving core file - struct __sysctl_args args; - int old_usespid = 0; - size_t old_len = 0; - int new_usespid = 1; - size_t new_len = sizeof(new_usespid); - - int name[] = {CTL_KERN, KERN_CORE_USES_PID}; - - memset(&args, 0, sizeof(struct __sysctl_args)); - args.name = name; - args.nlen = sizeof(name)/sizeof(name[0]); - args.oldval = &old_usespid; - args.oldlenp = &old_len; - args.newval = &new_usespid; - args.newlen = new_len; - - old_len = sizeof(old_usespid); - - if (syscall(SYS__sysctl, &args) == -1) { - uInfo("_sysctl(kern_core_uses_pid) set fail: %s", strerror(errno)); - } - - uInfo("The old core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid); - - - old_usespid = 0; - old_len = 0; - memset(&args, 0, sizeof(struct __sysctl_args)); - args.name = name; - args.nlen = sizeof(name)/sizeof(name[0]); - args.oldval = &old_usespid; - args.oldlenp = &old_len; - - old_len = sizeof(old_usespid); - - if (syscall(SYS__sysctl, &args) == -1) { - uInfo("_sysctl(kern_core_uses_pid) get fail: %s", strerror(errno)); - } - - uInfo("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid); -#endif - -#if 0 - // 3. create the path for saving core file - int status; - char coredump_dir[32] = "/var/log/taosdump"; - if (opendir(coredump_dir) == NULL) { - status = mkdir(coredump_dir, S_IRWXU | S_IRWXG | S_IRWXO); - if (status) { - uInfo("mkdir fail, error: %s\n", strerror(errno)); - } - } - - // 4. set kernel.core_pattern - struct __sysctl_args args; - char old_corefile[128]; - size_t old_len; - char new_corefile[128] = "/var/log/taosdump/core-%e-%p"; - size_t new_len = sizeof(new_corefile); - - int name[] = {CTL_KERN, KERN_CORE_PATTERN}; - - memset(&args, 0, sizeof(struct __sysctl_args)); - args.name = name; - args.nlen = sizeof(name)/sizeof(name[0]); - args.oldval = old_corefile; - args.oldlenp = &old_len; - args.newval = new_corefile; - args.newlen = new_len; - - old_len = sizeof(old_corefile); - - if (syscall(SYS__sysctl, &args) == -1) { - uInfo("_sysctl(kern_core_pattern) set fail: %s", strerror(errno)); - } - - uInfo("The old kern_core_pattern: %*s\n", old_len, old_corefile); - - - memset(&args, 0, sizeof(struct __sysctl_args)); - args.name = name; - args.nlen = sizeof(name)/sizeof(name[0]); - args.oldval = old_corefile; - args.oldlenp = &old_len; - - old_len = sizeof(old_corefile); - - if (syscall(SYS__sysctl, &args) == -1) { - uInfo("_sysctl(kern_core_pattern) get fail: %s", strerror(errno)); - } - - uInfo("The new kern_core_pattern: %*s\n", old_len, old_corefile); -#endif - -} - diff --git a/src/os/windows/CMakeLists.txt b/src/os/windows/CMakeLists.txt deleted file mode 100644 index dc60b736ea..0000000000 --- a/src/os/windows/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -IF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(os ${SRC}) - TARGET_LINK_LIBRARIES(os winmm IPHLPAPI ws2_32) -ENDIF () diff --git a/src/os/windows/inc/os.h b/src/os/windows/inc/os.h deleted file mode 100644 index a1901aa6e7..0000000000 --- a/src/os/windows/inc/os.h +++ /dev/null @@ -1,423 +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 TDENGINE_PLATFORM_WINDOWS_H -#define TDENGINE_PLATFORM_WINDOWS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "winsock2.h" -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// for function open in stat.h -#define S_IRWXU _S_IREAD -#define S_IRWXG _S_IWRITE -#define S_IRWXO _S_IWRITE - -// for access function in io.h -#define F_OK 00 //Existence only -#define W_OK 02 //Write - only -#define R_OK 04 //Read - only -#define X_OK 06 //Read and write - -// for send function in tsocket.c -#define MSG_NOSIGNAL 0 -#define SO_NO_CHECK 0x1234 -#define SOL_TCP 0x1234 -#define TCP_KEEPCNT 0x1234 -#define TCP_KEEPIDLE 0x1234 -#define TCP_KEEPINTVL 0x1234 - -#define LOCK_EX 1 -#define LOCK_NB 2 -#define LOCK_UN 3 - -#define bzero(ptr, size) memset((ptr), 0, (size)) -#define mkdir(pathname, mode) _mkdir(pathname) -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#define wcsncasecmp _wcsnicmp -#define strtok_r strtok_s -#ifdef _TD_GO_DLL_ - int64_t str2int64(char *str); - uint64_t htonll(uint64_t val); -#else - #define str2int64 _atoi64 -#endif - -#define snprintf _snprintf -#define in_addr_t unsigned long -#define socklen_t int -#define htobe64 htonll -#define twrite write - -#ifndef PATH_MAX - #define PATH_MAX 256 -#endif - -#define taosCloseSocket(fd) closesocket(fd) -#define taosWriteSocket(fd, buf, len) send(fd, buf, len, 0) -#define taosReadSocket(fd, buf, len) recv(fd, buf, len, 0) - -#if defined(_M_ARM) || defined(_M_ARM64) - -/* the '__iso_volatile' functions does not use a memory fence, so these - * definitions are incorrect, comment out as we don't support Windows on - * ARM at present. - -#define atomic_load_8(ptr) __iso_volatile_load8((const volatile __int8*)(ptr)) -#define atomic_load_16(ptr) __iso_volatile_load16((const volatile __int16*)(ptr)) -#define atomic_load_32(ptr) __iso_volatile_load32((const volatile __int32*)(ptr)) -#define atomic_load_64(ptr) __iso_volatile_load64((const volatile __int64*)(ptr)) - -#define atomic_store_8(ptr, val) __iso_volatile_store8((volatile __int8*)(ptr), (__int8)(val)) -#define atomic_store_16(ptr, val) __iso_volatile_store16((volatile __int16*)(ptr), (__int16)(val)) -#define atomic_store_32(ptr, val) __iso_volatile_store32((volatile __int32*)(ptr), (__int32)(val)) -#define atomic_store_64(ptr, val) __iso_volatile_store64((volatile __int64*)(ptr), (__int64)(val)) - -#ifdef _M_ARM64 -#define atomic_load_ptr atomic_load_64 -#define atomic_store_ptr atomic_store_64 -#else -#define atomic_load_ptr atomic_load_32 -#define atomic_store_ptr atomic_store_32 -#endif -*/ -#else - -#define atomic_load_8(ptr) (*(char volatile*)(ptr)) -#define atomic_load_16(ptr) (*(short volatile*)(ptr)) -#define atomic_load_32(ptr) (*(long volatile*)(ptr)) -#define atomic_load_64(ptr) (*(__int64 volatile*)(ptr)) -#define atomic_load_ptr(ptr) (*(void* volatile*)(ptr)) - -#define atomic_store_8(ptr, val) ((*(char volatile*)(ptr)) = (char)(val)) -#define atomic_store_16(ptr, val) ((*(short volatile*)(ptr)) = (short)(val)) -#define atomic_store_32(ptr, val) ((*(long volatile*)(ptr)) = (long)(val)) -#define atomic_store_64(ptr, val) ((*(__int64 volatile*)(ptr)) = (__int64)(val)) -#define atomic_store_ptr(ptr, val) ((*(void* volatile*)(ptr)) = (void*)(val)) - -#endif - -#define atomic_exchange_8(ptr, val) _InterlockedExchange8((char volatile*)(ptr), (char)(val)) -#define atomic_exchange_16(ptr, val) _InterlockedExchange16((short volatile*)(ptr), (short)(val)) -#define atomic_exchange_32(ptr, val) _InterlockedExchange((long volatile*)(ptr), (long)(val)) -#define atomic_exchange_64(ptr, val) _InterlockedExchange64((__int64 volatile*)(ptr), (__int64)(val)) -#define atomic_exchange_ptr(ptr, val) _InterlockedExchangePointer((void* volatile*)(ptr), (void*)(val)) - -#ifdef _TD_GO_DLL_ - #define atomic_val_compare_exchange_8 __sync_val_compare_and_swap -#else - #define atomic_val_compare_exchange_8(ptr, oldval, newval) _InterlockedCompareExchange8((char volatile*)(ptr), (char)(newval), (char)(oldval)) -#endif - -#define atomic_val_compare_exchange_16(ptr, oldval, newval) _InterlockedCompareExchange16((short volatile*)(ptr), (short)(newval), (short)(oldval)) -#define atomic_val_compare_exchange_32(ptr, oldval, newval) _InterlockedCompareExchange((long volatile*)(ptr), (long)(newval), (long)(oldval)) -#define atomic_val_compare_exchange_64(ptr, oldval, newval) _InterlockedCompareExchange64((__int64 volatile*)(ptr), (__int64)(newval), (__int64)(oldval)) -#define atomic_val_compare_exchange_ptr(ptr, oldval, newval) _InterlockedCompareExchangePointer((void* volatile*)(ptr), (void*)(newval), (void*)(oldval)) - -char interlocked_add_fetch_8(char volatile *ptr, char val); -short interlocked_add_fetch_16(short volatile *ptr, short val); -long interlocked_add_fetch_32(long volatile *ptr, long val); -__int64 interlocked_add_fetch_64(__int64 volatile *ptr, __int64 val); - -#define atomic_add_fetch_8(ptr, val) interlocked_add_fetch_8((char volatile*)(ptr), (char)(val)) -#define atomic_add_fetch_16(ptr, val) interlocked_add_fetch_16((short volatile*)(ptr), (short)(val)) -#define atomic_add_fetch_32(ptr, val) interlocked_add_fetch_32((long volatile*)(ptr), (long)(val)) -#define atomic_add_fetch_64(ptr, val) interlocked_add_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) -#ifdef _WIN64 - #define atomic_add_fetch_ptr atomic_add_fetch_64 -#else - #define atomic_add_fetch_ptr atomic_add_fetch_32 -#endif -#ifdef _TD_GO_DLL_ - #define atomic_fetch_add_8 __sync_fetch_and_ad - #define atomic_fetch_add_16 __sync_fetch_and_add -#else - #define atomic_fetch_add_8(ptr, val) _InterlockedExchangeAdd8((char volatile*)(ptr), (char)(val)) - #define atomic_fetch_add_16(ptr, val) _InterlockedExchangeAdd16((short volatile*)(ptr), (short)(val)) -#endif - -#define atomic_fetch_add_32(ptr, val) _InterlockedExchangeAdd((long volatile*)(ptr), (long)(val)) -#define atomic_fetch_add_64(ptr, val) _InterlockedExchangeAdd64((__int64 volatile*)(ptr), (__int64)(val)) -#ifdef _WIN64 - #define atomic_fetch_add_ptr atomic_fetch_add_64 -#else - #define atomic_fetch_add_ptr atomic_fetch_add_32 -#endif - -#define atomic_sub_fetch_8(ptr, val) interlocked_add_fetch_8((char volatile*)(ptr), -(char)(val)) -#define atomic_sub_fetch_16(ptr, val) interlocked_add_fetch_16((short volatile*)(ptr), -(short)(val)) -#define atomic_sub_fetch_32(ptr, val) interlocked_add_fetch_32((long volatile*)(ptr), -(long)(val)) -#define atomic_sub_fetch_64(ptr, val) interlocked_add_fetch_64((__int64 volatile*)(ptr), -(__int64)(val)) -#ifdef _WIN64 - #define atomic_sub_fetch_ptr atomic_sub_fetch_64 -#else - #define atomic_sub_fetch_ptr atomic_sub_fetch_32 -#endif - -#define atomic_fetch_sub_8(ptr, val) _InterlockedExchangeAdd8((char volatile*)(ptr), -(char)(val)) -#define atomic_fetch_sub_16(ptr, val) _InterlockedExchangeAdd16((short volatile*)(ptr), -(short)(val)) -#define atomic_fetch_sub_32(ptr, val) _InterlockedExchangeAdd((long volatile*)(ptr), -(long)(val)) -#define atomic_fetch_sub_64(ptr, val) _InterlockedExchangeAdd64((__int64 volatile*)(ptr), -(__int64)(val)) -#ifdef _WIN64 - #define atomic_fetch_sub_ptr atomic_fetch_sub_64 -#else - #define atomic_fetch_sub_ptr atomic_fetch_sub_32 -#endif -#ifndef _TD_GO_DLL_ - char interlocked_and_fetch_8(char volatile* ptr, char val); - short interlocked_and_fetch_16(short volatile* ptr, short val); -#endif -long interlocked_and_fetch_32(long volatile* ptr, long val); -__int64 interlocked_and_fetch_64(__int64 volatile* ptr, __int64 val); - -#ifndef _TD_GO_DLL_ - #define atomic_and_fetch_8(ptr, val) interlocked_and_fetch_8((char volatile*)(ptr), (char)(val)) - #define atomic_and_fetch_16(ptr, val) interlocked_and_fetch_16((short volatile*)(ptr), (short)(val)) -#endif -#define atomic_and_fetch_32(ptr, val) interlocked_and_fetch_32((long volatile*)(ptr), (long)(val)) -#define atomic_and_fetch_64(ptr, val) interlocked_and_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) -#ifdef _WIN64 - #define atomic_and_fetch_ptr atomic_and_fetch_64 -#else - #define atomic_and_fetch_ptr atomic_and_fetch_32 -#endif -#ifndef _TD_GO_DLL_ - #define atomic_fetch_and_8(ptr, val) _InterlockedAnd8((char volatile*)(ptr), (char)(val)) - #define atomic_fetch_and_16(ptr, val) _InterlockedAnd16((short volatile*)(ptr), (short)(val)) -#endif -#define atomic_fetch_and_32(ptr, val) _InterlockedAnd((long volatile*)(ptr), (long)(val)) - -#ifdef _M_IX86 - __int64 interlocked_fetch_and_64(__int64 volatile* ptr, __int64 val); - #define atomic_fetch_and_64(ptr, val) interlocked_fetch_and_64((__int64 volatile*)(ptr), (__int64)(val)) -#else - #define atomic_fetch_and_64(ptr, val) _InterlockedAnd64((__int64 volatile*)(ptr), (__int64)(val)) -#endif - -#ifdef _WIN64 - #define atomic_fetch_and_ptr atomic_fetch_and_64 -#else - #define atomic_fetch_and_ptr atomic_fetch_and_32 -#endif -#ifndef _TD_GO_DLL_ - char interlocked_or_fetch_8(char volatile* ptr, char val); - short interlocked_or_fetch_16(short volatile* ptr, short val); -#endif -long interlocked_or_fetch_32(long volatile* ptr, long val); -__int64 interlocked_or_fetch_64(__int64 volatile* ptr, __int64 val); - -#ifndef _TD_GO_DLL_ - #define atomic_or_fetch_8(ptr, val) interlocked_or_fetch_8((char volatile*)(ptr), (char)(val)) - #define atomic_or_fetch_16(ptr, val) interlocked_or_fetch_16((short volatile*)(ptr), (short)(val)) -#endif -#define atomic_or_fetch_32(ptr, val) interlocked_or_fetch_32((long volatile*)(ptr), (long)(val)) -#define atomic_or_fetch_64(ptr, val) interlocked_or_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) -#ifdef _WIN64 - #define atomic_or_fetch_ptr atomic_or_fetch_64 -#else - #define atomic_or_fetch_ptr atomic_or_fetch_32 -#endif -#ifndef _TD_GO_DLL_ - #define atomic_fetch_or_8(ptr, val) _InterlockedOr8((char volatile*)(ptr), (char)(val)) - #define atomic_fetch_or_16(ptr, val) _InterlockedOr16((short volatile*)(ptr), (short)(val)) -#endif -#define atomic_fetch_or_32(ptr, val) _InterlockedOr((long volatile*)(ptr), (long)(val)) - -#ifdef _M_IX86 - __int64 interlocked_fetch_or_64(__int64 volatile* ptr, __int64 val); - #define atomic_fetch_or_64(ptr, val) interlocked_fetch_or_64((__int64 volatile*)(ptr), (__int64)(val)) -#else - #define atomic_fetch_or_64(ptr, val) _InterlockedOr64((__int64 volatile*)(ptr), (__int64)(val)) -#endif - -#ifdef _WIN64 - #define atomic_fetch_or_ptr atomic_fetch_or_64 -#else - #define atomic_fetch_or_ptr atomic_fetch_or_32 -#endif - -#ifndef _TD_GO_DLL_ - char interlocked_xor_fetch_8(char volatile* ptr, char val); - short interlocked_xor_fetch_16(short volatile* ptr, short val); -#endif -long interlocked_xor_fetch_32(long volatile* ptr, long val); -__int64 interlocked_xor_fetch_64(__int64 volatile* ptr, __int64 val); - -#ifndef _TD_GO_DLL_ - #define atomic_xor_fetch_8(ptr, val) interlocked_xor_fetch_8((char volatile*)(ptr), (char)(val)) - #define atomic_xor_fetch_16(ptr, val) interlocked_xor_fetch_16((short volatile*)(ptr), (short)(val)) -#endif -#define atomic_xor_fetch_32(ptr, val) interlocked_xor_fetch_32((long volatile*)(ptr), (long)(val)) -#define atomic_xor_fetch_64(ptr, val) interlocked_xor_fetch_64((__int64 volatile*)(ptr), (__int64)(val)) -#ifdef _WIN64 - #define atomic_xor_fetch_ptr atomic_xor_fetch_64 -#else - #define atomic_xor_fetch_ptr atomic_xor_fetch_32 -#endif - -#ifndef _TD_GO_DLL_ - #define atomic_fetch_xor_8(ptr, val) _InterlockedXor8((char volatile*)(ptr), (char)(val)) - #define atomic_fetch_xor_16(ptr, val) _InterlockedXor16((short volatile*)(ptr), (short)(val)) -#endif -#define atomic_fetch_xor_32(ptr, val) _InterlockedXor((long volatile*)(ptr), (long)(val)) - -#ifdef _M_IX86 - __int64 interlocked_fetch_xor_64(__int64 volatile* ptr, __int64 val); - #define atomic_fetch_xor_64(ptr, val) interlocked_fetch_xor_64((__int64 volatile*)(ptr), (__int64)(val)) -#else - #define atomic_fetch_xor_64(ptr, val) _InterlockedXor64((__int64 volatile*)(ptr), (__int64)(val)) -#endif - -#ifdef _WIN64 - #define atomic_fetch_xor_ptr atomic_fetch_xor_64 -#else - #define atomic_fetch_xor_ptr atomic_fetch_xor_32 -#endif - -#define SWAP(a, b, c) \ - do { \ - c __tmp = (c)(a); \ - (a) = (c)(b); \ - (b) = __tmp; \ - } while (0) - -#define MAX(a,b) (((a)>(b))?(a):(b)) -#define MIN(a,b) (((a)<(b))?(a):(b)) - -#ifdef _TD_GO_DLL_ - #define MILLISECOND_PER_SECOND (1000LL) -#else - #define MILLISECOND_PER_SECOND (1000i64) -#endif - -#define tsem_t sem_t -#define tsem_init sem_init -#define tsem_wait sem_wait -#define tsem_post sem_post -#define tsem_destroy sem_destroy - -void osInit(); - -int getline(char **lineptr, size_t *n, FILE *stream); - -int taosWinSetTimer(int ms, void(*callback)(int)); - -int gettimeofday(struct timeval *tv, struct timezone *tz); - -struct tm *localtime_r(const time_t *timep, struct tm *result); - -char *strptime(const char *buf, const char *fmt, struct tm *tm); - -bool taosCheckPthreadValid(pthread_t thread); - -void taosResetPthread(pthread_t *thread); - -int64_t taosGetPthreadId(); - -int taosSetNonblocking(int sock, int on); - -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); - -char *taosCharsetReplace(char *charsetstr); - -void taosPrintOsInfo(); - -void taosGetSystemInfo(); - -void taosKillSystem(); - -int32_t BUILDIN_CLZL(uint64_t val); -int32_t BUILDIN_CLZ(uint32_t val); -int32_t BUILDIN_CTZL(uint64_t val); -int32_t BUILDIN_CTZ(uint32_t val); - -//for signal, not dispose -#define SIGALRM 1234 -typedef int sigset_t; - -struct sigaction { - void (*sa_handler)(int); -}; - -typedef struct { - int we_wordc; - char **we_wordv; - int we_offs; - char wordPos[20]; -} wordexp_t; - -int wordexp(const char *words, wordexp_t *pwordexp, int flags); - -void wordfree(wordexp_t *pwordexp); - -int flock(int fd, int option); - -int fsync(int filedes); - -char *getpass(const char *prefix); - -char *strsep(char **stringp, const char *delim); - -typedef int(*__compar_fn_t)(const void *, const void *); - -int sigaction(int, struct sigaction *, void *); - -void sleep(int mseconds); - -bool taosSkipSocketCheck(); - -int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count); - -#define ssize_t int - -#define strdup _strdup - -char *strndup(const char *s, size_t n); - -void taosSetCoreDump(); - -#ifdef __cplusplus -} -#endif -#endif \ No newline at end of file diff --git a/src/os/windows/src/twindows.c b/src/os/windows/src/twindows.c deleted file mode 100644 index 295824846e..0000000000 --- a/src/os/windows/src/twindows.c +++ /dev/null @@ -1,410 +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 "taosdef.h" -#include "tglobal.h" -#include "ttimer.h" -#include "tulog.h" -#include "tutil.h" - -bool taosCheckPthreadValid(pthread_t thread) { - return thread.p != NULL; -} - -void taosResetPthread(pthread_t *thread) { - thread->p = 0; -} - -int64_t taosGetPthreadId() { -#ifdef PTW32_VERSION - return pthread_getw32threadid_np(pthread_self()); -#else - return (int64_t)pthread_self(); -#endif -} - -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { - if (level == SOL_SOCKET && optname == TCP_KEEPCNT) { - return 0; - } - - if (level == SOL_TCP && optname == TCP_KEEPIDLE) { - return 0; - } - - if (level == SOL_TCP && optname == TCP_KEEPINTVL) { - return 0; - } - - return setsockopt(socketfd, level, optname, optval, optlen); -} - -// add -char interlocked_add_fetch_8(char volatile* ptr, char val) { - #ifdef _TD_GO_DLL_ - return __sync_fetch_and_add(ptr, val) + val; - #else - return _InterlockedExchangeAdd8(ptr, val) + val; - #endif -} - -short interlocked_add_fetch_16(short volatile* ptr, short val) { - #ifdef _TD_GO_DLL_ - return __sync_fetch_and_add(ptr, val) + val; - #else - return _InterlockedExchangeAdd16(ptr, val) + val; - #endif -} - -long interlocked_add_fetch_32(long volatile* ptr, long val) { - return _InterlockedExchangeAdd(ptr, val) + val; -} - -__int64 interlocked_add_fetch_64(__int64 volatile* ptr, __int64 val) { - return _InterlockedExchangeAdd64(ptr, val) + val; -} - -// and -#ifndef _TD_GO_DLL_ -char interlocked_and_fetch_8(char volatile* ptr, char val) { - return _InterlockedAnd8(ptr, val) & val; -} - -short interlocked_and_fetch_16(short volatile* ptr, short val) { - return _InterlockedAnd16(ptr, val) & val; -} -#endif - -long interlocked_and_fetch_32(long volatile* ptr, long val) { - return _InterlockedAnd(ptr, val) & val; -} - -#ifndef _M_IX86 - -__int64 interlocked_and_fetch_64(__int64 volatile* ptr, __int64 val) { - return _InterlockedAnd64(ptr, val) & val; -} - -#else - -__int64 interlocked_and_fetch_64(__int64 volatile* ptr, __int64 val) { - __int64 old, res; - do { - old = *ptr; - res = old & val; - } while(_InterlockedCompareExchange64(ptr, res, old) != old); - return res; -} - -__int64 interlocked_fetch_and_64(__int64 volatile* ptr, __int64 val) { - __int64 old; - do { - old = *ptr; - } while(_InterlockedCompareExchange64(ptr, old & val, old) != old); - return old; -} - -#endif - -// or -#ifndef _TD_GO_DLL_ -char interlocked_or_fetch_8(char volatile* ptr, char val) { - return _InterlockedOr8(ptr, val) | val; -} - -short interlocked_or_fetch_16(short volatile* ptr, short val) { - return _InterlockedOr16(ptr, val) | val; -} -#endif -long interlocked_or_fetch_32(long volatile* ptr, long val) { - return _InterlockedOr(ptr, val) | val; -} - -#ifndef _M_IX86 - -__int64 interlocked_or_fetch_64(__int64 volatile* ptr, __int64 val) { - return _InterlockedOr64(ptr, val) & val; -} - -#else - -__int64 interlocked_or_fetch_64(__int64 volatile* ptr, __int64 val) { - __int64 old, res; - do { - old = *ptr; - res = old | val; - } while(_InterlockedCompareExchange64(ptr, res, old) != old); - return res; -} - -__int64 interlocked_fetch_or_64(__int64 volatile* ptr, __int64 val) { - __int64 old; - do { - old = *ptr; - } while(_InterlockedCompareExchange64(ptr, old | val, old) != old); - return old; -} - -#endif - -// xor -#ifndef _TD_GO_DLL_ -char interlocked_xor_fetch_8(char volatile* ptr, char val) { - return _InterlockedXor8(ptr, val) ^ val; -} - -short interlocked_xor_fetch_16(short volatile* ptr, short val) { - return _InterlockedXor16(ptr, val) ^ val; -} -#endif -long interlocked_xor_fetch_32(long volatile* ptr, long val) { - return _InterlockedXor(ptr, val) ^ val; -} - -#ifndef _M_IX86 - -__int64 interlocked_xor_fetch_64(__int64 volatile* ptr, __int64 val) { - return _InterlockedXor64(ptr, val) ^ val; -} - -#else - -__int64 interlocked_xor_fetch_64(__int64 volatile* ptr, __int64 val) { - __int64 old, res; - do { - old = *ptr; - res = old ^ val; - } while(_InterlockedCompareExchange64(ptr, res, old) != old); - return res; -} - -__int64 interlocked_fetch_xor_64(__int64 volatile* ptr, __int64 val) { - __int64 old; - do { - old = *ptr; - } while(_InterlockedCompareExchange64(ptr, old ^ val, old) != old); - return old; -} - -#endif - -void taosPrintOsInfo() {} - -void taosGetSystemTimezone() { - // get and set default timezone - SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone"); - if (cfg_timezone && cfg_timezone->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - char *tz = getenv("TZ"); - if (tz == NULL || strlen(tz) == 0) { - strcpy(tsTimezone, "not configured"); - } - else { - strcpy(tsTimezone, tz); - } - cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("timezone not configured, use default"); - } -} - -void taosGetSystemLocale() { - // get and set default locale - SGlobalCfg *cfg_locale = taosGetConfigOption("locale"); - if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - char *locale = setlocale(LC_CTYPE, "chs"); - if (locale != NULL) { - tstrncpy(tsLocale, locale, sizeof(tsLocale)); - cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("locale not configured, set to default:%s", tsLocale); - } - } - - SGlobalCfg *cfg_charset = taosGetConfigOption("charset"); - if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) { - strcpy(tsCharset, "cp936"); - cfg_charset->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT; - uInfo("charset not configured, set to default:%s", tsCharset); - } -} - -void taosGetSystemInfo() { - taosGetSystemTimezone(); - taosGetSystemLocale(); -} - -void taosKillSystem() { - exit(0); -} - -/* - * Get next token from string *stringp, where tokens are possibly-empty - * strings separated by characters from delim. - * - * Writes NULs into the string at *stringp to end tokens. - * delim need not remain constant from call to call. - * On return, *stringp points past the last NUL written (if there might - * be further tokens), or is NULL (if there are definitely no moretokens). - * - * If *stringp is NULL, strsep returns NULL. - */ -char *strsep(char **stringp, const char *delim) { - char *s; - const char *spanp; - int c, sc; - char *tok; - if ((s = *stringp) == NULL) - return (NULL); - for (tok = s;;) { - c = *s++; - spanp = delim; - do { - if ((sc = *spanp++) == c) { - if (c == 0) - s = NULL; - else - s[-1] = 0; - *stringp = s; - return (tok); - } - } while (sc != 0); - } - /* NOTREACHED */ -} - -char *getpass(const char *prefix) { - static char passwd[TSDB_KEY_LEN] = {0}; - - printf("%s", prefix); - scanf("%s", passwd); - - char n = getchar(); - return passwd; -} - -int flock(int fd, int option) { - return 0; -} - -int fsync(int filedes) { - return 0; -} - -int sigaction(int sig, struct sigaction *d, void *p) { - return 0; -} - -int wordexp(const char *words, wordexp_t *pwordexp, int flags) { - pwordexp->we_offs = 0; - pwordexp->we_wordc = 1; - pwordexp->we_wordv = (char **)(pwordexp->wordPos); - pwordexp->we_wordv[0] = (char *)words; - return 0; -} - -void wordfree(wordexp_t *pwordexp) {} - -void taosGetDisk() {} - -bool taosSkipSocketCheck() { - return false; -} - -#define _SEND_FILE_STEP_ 1000 - -int fsendfile(FILE* out_file, FILE* in_file, int64_t* offset, int32_t count) { - fseek(in_file, (int32_t)(*offset), 0); - int writeLen = 0; - uint8_t buffer[_SEND_FILE_STEP_] = { 0 }; - - for (int len = 0; len < (count - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) { - size_t rlen = fread(buffer, 1, _SEND_FILE_STEP_, in_file); - if (rlen <= 0) { - return writeLen; - } - else if (rlen < _SEND_FILE_STEP_) { - fwrite(buffer, 1, rlen, out_file); - return (int)(writeLen + rlen); - } - else { - fwrite(buffer, 1, _SEND_FILE_STEP_, in_file); - writeLen += _SEND_FILE_STEP_; - } - } - - int remain = count - writeLen; - if (remain > 0) { - size_t rlen = fread(buffer, 1, remain, in_file); - if (rlen <= 0) { - return writeLen; - } - else { - fwrite(buffer, 1, remain, out_file); - writeLen += remain; - } - } - - return writeLen; -} - -int32_t BUILDIN_CLZL(uint64_t val) { - unsigned long r = 0; - _BitScanReverse64(&r, val); - return (int)(r >> 3); -} - -int32_t BUILDIN_CLZ(uint32_t val) { - unsigned long r = 0; - _BitScanReverse(&r, val); - return (int)(r >> 3); -} - -int32_t BUILDIN_CTZL(uint64_t val) { - unsigned long r = 0; - _BitScanForward64(&r, val); - return (int)(r >> 3); -} - -int32_t BUILDIN_CTZ(uint32_t val) { - unsigned long r = 0; - _BitScanForward(&r, val); - return (int)(r >> 3); -} - -char *strndup(const char *s, size_t n) { - int len = strlen(s); - if (len >= n) { - len = n; - } - - char *r = calloc(len + 1, 1); - memcpy(r, s, len); - r[len] = 0; - return r; -} - -void taosSetCoreDump() {} - -#ifdef _TD_GO_DLL_ -int64_t str2int64(char *str) { - char *endptr = NULL; - return strtoll(str, &endptr, 10); -} - -uint64_t htonll(uint64_t val) -{ - return (((uint64_t) htonl(val)) << 32) + htonl(val >> 32); -} -#endif \ No newline at end of file diff --git a/src/os/windows/src/twinenv.c b/src/os/windows/src/twinenv.c deleted file mode 100644 index 840a8d9f7a..0000000000 --- a/src/os/windows/src/twinenv.c +++ /dev/null @@ -1,30 +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 "tglobal.h" -#include "tulog.h" - -void osInit() { - strcpy(configDir, "C:/TDengine/cfg"); - strcpy(tsVnodeDir, "C:/TDengine/data"); - strcpy(tsDnodeDir, ""); - strcpy(tsMnodeDir, ""); - strcpy(tsDataDir, "C:/TDengine/data"); - strcpy(tsLogDir, "C:/TDengine/log"); - strcpy(tsScriptDir, "C:/TDengine/script"); - strcpy(tsOsName, "Windows"); -} \ No newline at end of file diff --git a/src/os/windows/src/twingetline.c b/src/os/windows/src/twingetline.c deleted file mode 100644 index 1dd56fd547..0000000000 --- a/src/os/windows/src/twingetline.c +++ /dev/null @@ -1,145 +0,0 @@ -/* getline.c -- Replacement for GNU C library function getline - -Copyright (C) 1993 Free Software Foundation, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -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. See the GNU -General Public License for more details. */ - -/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#if STDC_HEADERS -#include -#else -char *malloc(), *realloc(); -#endif - -/* Always add at least this many bytes when extending the buffer. */ -#define MIN_CHUNK 64 - -/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR -+ OFFSET (and null-terminate it). *LINEPTR is a pointer returned from -malloc (or NULL), pointing to *N characters of space. It is realloc'd -as necessary. Return the number of characters read (not including the -null terminator), or -1 on error or EOF. On a -1 return, the caller -should check feof(), if not then errno has been set to indicate -the error. */ - -int -getstr(lineptr, n, stream, terminator, offset) -char **lineptr; -size_t *n; -FILE *stream; -char terminator; -int offset; -{ - int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ - char *read_pos; /* Where we're reading into *LINEPTR. */ - int ret; - - if (!lineptr || !n || !stream) - { - errno = EINVAL; - return -1; - } - - if (!*lineptr) - { - *n = MIN_CHUNK; - *lineptr = malloc(*n); - if (!*lineptr) - { - errno = ENOMEM; - return -1; - } - } - - nchars_avail = (int)(*n - offset); - read_pos = *lineptr + offset; - - for (;;) - { - int save_errno; - register int c = getc(stream); - - save_errno = errno; - - /* We always want at least one char left in the buffer, since we - always (unless we get an error while reading the first char) - NUL-terminate the line buffer. */ - - assert((*lineptr + *n) == (read_pos + nchars_avail)); - if (nchars_avail < 2) - { - if (*n > MIN_CHUNK) - *n *= 2; - else - *n += MIN_CHUNK; - - nchars_avail = (int)(*n + *lineptr - read_pos); - *lineptr = realloc(*lineptr, *n); - if (!*lineptr) - { - errno = ENOMEM; - return -1; - } - read_pos = *n - nchars_avail + *lineptr; - assert((*lineptr + *n) == (read_pos + nchars_avail)); - } - - if (ferror(stream)) - { - /* Might like to return partial line, but there is no - place for us to store errno. And we don't want to just - lose errno. */ - errno = save_errno; - return -1; - } - - if (c == EOF) - { - /* Return partial line, if any. */ - if (read_pos == *lineptr) - return -1; - else - break; - } - - *read_pos++ = c; - nchars_avail--; - - if (c == terminator) - /* Return the line. */ - break; - } - - /* Done - NUL terminate and return the number of chars read. */ - *read_pos = '\0'; - - ret = (int)(read_pos - (*lineptr + offset)); - return ret; -} - -int -getline(lineptr, n, stream) -char **lineptr; -size_t *n; -FILE *stream; -{ - return getstr(lineptr, n, stream, '\n', 0); -} \ No newline at end of file diff --git a/src/os/windows/src/twinmsghdr.c b/src/os/windows/src/twinmsghdr.c deleted file mode 100644 index 9f35d3ec62..0000000000 --- a/src/os/windows/src/twinmsghdr.c +++ /dev/null @@ -1,57 +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 . - */ - -#include - -void taosFreeMsgHdr(void *hdr) { - WSAMSG *msgHdr = (WSAMSG *)hdr; - free(msgHdr->lpBuffers); -} - -int taosMsgHdrSize(void *hdr) { - WSAMSG *msgHdr = (WSAMSG *)hdr; - return msgHdr->dwBufferCount; -} - -void taosSendMsgHdr(void *hdr, int fd) { - WSAMSG *msgHdr = (WSAMSG *)hdr; - DWORD len; - - WSASendMsg(fd, msgHdr, 0, &len, 0, 0); - msgHdr->dwBufferCount = 0; -} - -void taosInitMsgHdr(void **hdr, void *dest, int maxPkts) { - WSAMSG *msgHdr = (WSAMSG *)malloc(sizeof(WSAMSG)); - memset(msgHdr, 0, sizeof(WSAMSG)); - *hdr = msgHdr; - - // see ws2def.h - // the size of LPSOCKADDR and sockaddr_in * is same, so it's safe - msgHdr->name = (LPSOCKADDR)dest; - msgHdr->namelen = sizeof(struct sockaddr_in); - int size = sizeof(WSABUF) * maxPkts; - msgHdr->lpBuffers = (LPWSABUF)malloc(size); - memset(msgHdr->lpBuffers, 0, size); - msgHdr->dwBufferCount = 0; -} - -void taosSetMsgHdrData(void *hdr, char *data, int dataLen) { - WSAMSG *msgHdr = (WSAMSG *)hdr; - msgHdr->lpBuffers[msgHdr->dwBufferCount].buf = data; - msgHdr->lpBuffers[msgHdr->dwBufferCount].len = dataLen; - msgHdr->dwBufferCount++; -} - diff --git a/src/os/windows/src/twinsocket.c b/src/os/windows/src/twinsocket.c deleted file mode 100644 index 0690a4ceb1..0000000000 --- a/src/os/windows/src/twinsocket.c +++ /dev/null @@ -1,117 +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 . - */ - -#include -#include -#include -#include -#include -#include -#include - -void taosWinSocketInit() { - static char flag = 0; - if (flag == 0) { - WORD wVersionRequested; - WSADATA wsaData; - wVersionRequested = MAKEWORD(1, 1); - if (WSAStartup(wVersionRequested, &wsaData) == 0) { - flag = 1; - } - } -} - -int taosSetNonblocking(SOCKET sock, int on) { - u_long mode; - if (on) { - mode = 1; - ioctlsocket(sock, FIONBIO, &mode); - } - else { - mode = 0; - ioctlsocket(sock, FIONBIO, &mode); - } - return 0; -} - -int taosGetPrivateIp(char *const ip) { - PIP_ADAPTER_ADDRESSES pAddresses = 0; - IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = 0; - ULONG outBufLen = 0; - DWORD dwRetVal = 0; - char buff[100]; - DWORD bufflen = 100; - int i; - int flag = -1; - - taosWinSocketInit(); - GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen); - pAddresses = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen); - if ((dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST, NULL, pAddresses, &outBufLen)) == NO_ERROR) { - while (pAddresses) { - if (wcsstr(pAddresses->FriendlyName, L"Loopback") != 0) { - pAddresses = pAddresses->Next; - continue; - } - if (pAddresses->OperStatus == IfOperStatusUp) { - //printf("%s, Status: active\n", pAddresses->FriendlyName); - } - else { - //printf("%s, Status: deactive\n", pAddresses->FriendlyName); - pAddresses = pAddresses->Next; - continue; - } - - PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress; - for (i = 0; pUnicast != NULL; i++) { - if (pUnicast->Address.lpSockaddr->sa_family == AF_INET) { - struct sockaddr_in *sa_in = (struct sockaddr_in *)pUnicast->Address.lpSockaddr; - strcpy(ip, inet_ntop(AF_INET, &(sa_in->sin_addr), buff, bufflen)); - flag = 0; - //printf("%s\n", ip); - } - else if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6) { - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)pUnicast->Address.lpSockaddr; - strcpy(ip, inet_ntop(AF_INET6, &(sa_in6->sin6_addr), buff, bufflen)); - flag = 0; - //printf("%s\n", ip); - } - else { - } - pUnicast = pUnicast->Next; - } - pAddresses = pAddresses->Next; - } - } - else { - LPVOID lpMsgBuf; - printf("Call to GetAdaptersAddresses failed.\n"); - if (FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dwRetVal, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) & lpMsgBuf, - 0, - NULL)) { - printf("\tError: %s", lpMsgBuf); - } - LocalFree(lpMsgBuf); - } - free(pAddresses); - return flag; -} diff --git a/src/os/windows/src/twinstrptime.c b/src/os/windows/src/twinstrptime.c deleted file mode 100644 index 2401818274..0000000000 --- a/src/os/windows/src/twinstrptime.c +++ /dev/null @@ -1,398 +0,0 @@ -/* $Id$ */ -/* $NetBSD: strptime.c,v 1.18 1999/04/29 02:58:30 tv Exp $ */ - -/*- -* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. -* All rights reserved. -* -* This code was contributed to The NetBSD Foundation by Klaus Klein. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. All advertising materials mentioning features or use of this software -* must display the following acknowledgement: -* This product includes software developed by the NetBSD -* Foundation, Inc. and its contributors. -* 4. Neither the name of The NetBSD Foundation nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*/ -// -//#include "lukemftp.h" -#include -#include -#include -#include -//#define TM_YEAR_BASE 1970 //origin -#define TM_YEAR_BASE 1900 //slguan -/* -* We do not implement alternate representations. However, we always -* check whether a given modifier is allowed for a certain conversion. -*/ -#define ALT_E 0x01 -#define ALT_O 0x02 -#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } - - -static int conv_num(const char **, int *, int, int); - -static const char *day[7] = { - "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", - "Friday", "Saturday" -}; -static const char *abday[7] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; -static const char *mon[12] = { - "January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December" -}; -static const char *abmon[12] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; -static const char *am_pm[2] = { - "AM", "PM" -}; - - -char * -strptime(const char *buf, const char *fmt, struct tm *tm) -{ - char c; - const char *bp; - size_t len = 0; - int alt_format, i, split_year = 0; - - bp = buf; - - while ((c = *fmt) != '\0') { - /* Clear `alternate' modifier prior to new conversion. */ - alt_format = 0; - - /* Eat up white-space. */ - if (isspace(c)) { - while (isspace(*bp)) - bp++; - - fmt++; - continue; - } - - if ((c = *fmt++) != '%') - goto literal; - - - again: switch (c = *fmt++) { - case '%': /* "%%" is converted to "%". */ - literal : - if (c != *bp++) - return (0); - break; - - /* - * "Alternative" modifiers. Just set the appropriate flag - * and start over again. - */ - case 'E': /* "%E?" alternative conversion modifier. */ - LEGAL_ALT(0); - alt_format |= ALT_E; - goto again; - - case 'O': /* "%O?" alternative conversion modifier. */ - LEGAL_ALT(0); - alt_format |= ALT_O; - goto again; - - /* - * "Complex" conversion rules, implemented through recursion. - */ - case 'c': /* Date and time, using the locale's format. */ - LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%x %X", tm))) - return (0); - break; - - case 'D': /* The date as "%m/%d/%y". */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%m/%d/%y", tm))) - return (0); - break; - - case 'R': /* The time as "%H:%M". */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%H:%M", tm))) - return (0); - break; - - case 'r': /* The time in 12-hour clock representation. */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%I:%M:%S %p", tm))) - return (0); - break; - - case 'T': /* The time as "%H:%M:%S". */ - LEGAL_ALT(0); - if (!(bp = strptime(bp, "%H:%M:%S", tm))) - return (0); - break; - - case 'X': /* The time, using the locale's format. */ - LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%H:%M:%S", tm))) - return (0); - break; - - case 'x': /* The date, using the locale's format. */ - LEGAL_ALT(ALT_E); - if (!(bp = strptime(bp, "%m/%d/%y", tm))) - return (0); - break; - - /* - * "Elementary" conversion rules. - */ - case 'A': /* The day of week, using the locale's form. */ - case 'a': - LEGAL_ALT(0); - for (i = 0; i < 7; i++) { - /* Full name. */ - len = strlen(day[i]); - if (strncmp(day[i], bp, len) == 0) - break; - - /* Abbreviated name. */ - len = strlen(abday[i]); - if (strncmp(abday[i], bp, len) == 0) - break; - } - - /* Nothing matched. */ - if (i == 7) - return (0); - - tm->tm_wday = i; - bp += len; - break; - - case 'B': /* The month, using the locale's form. */ - case 'b': - case 'h': - LEGAL_ALT(0); - for (i = 0; i < 12; i++) { - /* Full name. */ - len = strlen(mon[i]); - if (strncmp(mon[i], bp, len) == 0) - break; - - /* Abbreviated name. */ - len = strlen(abmon[i]); - if (strncmp(abmon[i], bp, len) == 0) - break; - } - - /* Nothing matched. */ - if (i == 12) - return (0); - - tm->tm_mon = i; - bp += len; - break; - - case 'C': /* The century number. */ - LEGAL_ALT(ALT_E); - if (!(conv_num(&bp, &i, 0, 99))) - return (0); - - if (split_year) { - tm->tm_year = (tm->tm_year % 100) + (i * 100); - } - else { - tm->tm_year = i * 100; - split_year = 1; - } - break; - - case 'd': /* The day of month. */ - case 'e': - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) - return (0); - break; - - case 'k': /* The hour (24-hour clock representation). */ - LEGAL_ALT(0); - /* FALLTHROUGH */ - case 'H': - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) - return (0); - break; - - case 'l': /* The hour (12-hour clock representation). */ - LEGAL_ALT(0); - /* FALLTHROUGH */ - case 'I': - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) - return (0); - if (tm->tm_hour == 12) - tm->tm_hour = 0; - break; - - case 'j': /* The day of year. */ - LEGAL_ALT(0); - if (!(conv_num(&bp, &i, 1, 366))) - return (0); - tm->tm_yday = i - 1; - break; - - case 'M': /* The minute. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_min, 0, 59))) - return (0); - break; - - case 'm': /* The month. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &i, 1, 12))) - return (0); - tm->tm_mon = i - 1; - break; - - case 'p': /* The locale's equivalent of AM/PM. */ - LEGAL_ALT(0); - /* AM? */ - if (strcmp(am_pm[0], bp) == 0) { - if (tm->tm_hour > 11) - return (0); - - bp += strlen(am_pm[0]); - break; - } - /* PM? */ - else if (strcmp(am_pm[1], bp) == 0) { - if (tm->tm_hour > 11) - return (0); - - tm->tm_hour += 12; - bp += strlen(am_pm[1]); - break; - } - - /* Nothing matched. */ - return (0); - - case 'S': /* The seconds. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) - return (0); - break; - - case 'U': /* The week of year, beginning on sunday. */ - case 'W': /* The week of year, beginning on monday. */ - LEGAL_ALT(ALT_O); - /* - * XXX This is bogus, as we can not assume any valid - * information present in the tm structure at this - * point to calculate a real value, so just check the - * range for now. - */ - if (!(conv_num(&bp, &i, 0, 53))) - return (0); - break; - - case 'w': /* The day of week, beginning on sunday. */ - LEGAL_ALT(ALT_O); - if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) - return (0); - break; - - case 'Y': /* The year. */ - LEGAL_ALT(ALT_E); - if (!(conv_num(&bp, &i, 0, 9999))) - return (0); - - tm->tm_year = i - TM_YEAR_BASE; - break; - - case 'y': /* The year within 100 years of the epoch. */ - LEGAL_ALT(ALT_E | ALT_O); - if (!(conv_num(&bp, &i, 0, 99))) - return (0); - - if (split_year) { - tm->tm_year = ((tm->tm_year / 100) * 100) + i; - break; - } - split_year = 1; - if (i <= 68) - tm->tm_year = i + 2000 - TM_YEAR_BASE; - else - tm->tm_year = i + 1900 - TM_YEAR_BASE; - break; - - /* - * Miscellaneous conversions. - */ - case 'n': /* Any kind of white-space. */ - case 't': - LEGAL_ALT(0); - while (isspace(*bp)) - bp++; - break; - - - default: /* Unknown/unsupported conversion. */ - return (0); - } - - - } - - /* LINTED functional specification */ - return ((char *)bp); -} - - -static int -conv_num(const char **buf, int *dest, int llim, int ulim) -{ - int result = 0; - - /* The limit also determines the number of valid digits. */ - int rulim = ulim; - - if (**buf < '0' || **buf > '9') - return (0); - - do { - result *= 10; - result += *(*buf)++ - '0'; - rulim /= 10; - } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); - - if (result < llim || result > ulim) - return (0); - - *dest = result; - return (1); -} \ No newline at end of file diff --git a/src/os/windows/src/twintcpclient.c b/src/os/windows/src/twintcpclient.c deleted file mode 100644 index 4736042aba..0000000000 --- a/src/os/windows/src/twintcpclient.c +++ /dev/null @@ -1,39 +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 . - */ - -#include "tulog.h" - -void *taosInitTcpClient(char *ip, uint16_t port, char *label, int num, void *fp, void *shandle) { - tError("InitTcpClient not support in windows"); - return 0; -} - -void taosCloseTcpClientConnection(void *chandle) { - tError("CloseTcpClientConnection not support in windows"); -} - -void *taosOpenTcpClientConnection(void *shandle, void *thandle, char *ip, uint16_t port) { - tError("OpenTcpClientConnection not support in windows"); - return 0; -} - -int taosSendTcpClientData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { - tError("SendTcpClientData not support in windows"); - return 0; -} - -void taosCleanUpTcpClient(void *chandle) { - tError("SendTcpClientData not support in windows"); -} diff --git a/src/os/windows/src/twintcpserver.c b/src/os/windows/src/twintcpserver.c deleted file mode 100644 index 10c0348bef..0000000000 --- a/src/os/windows/src/twintcpserver.c +++ /dev/null @@ -1,34 +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 . - */ - -#include "tulog.h" - -void taosCloseTcpServerConnection(void *chandle) { - tError("CloseTcpServerConnection not support in windows"); -} - -void taosCleanUpTcpServer(void *handle) { - tError("CleanUpTcpServer not support in windows"); -} - -void *taosInitTcpServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle) { - tError("InitTcpServer not support in windows"); - return 0; -} - -int taosSendTcpServerData(unsigned int ip, uint16_t port, char *data, int len, void *chandle) { - tError("SendTcpServerData not support in windows"); - return 0; -} diff --git a/src/os/windows/src/twintime.c b/src/os/windows/src/twintime.c deleted file mode 100644 index 1484b13843..0000000000 --- a/src/os/windows/src/twintime.c +++ /dev/null @@ -1,34 +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 . - */ - -#include -#include - -int gettimeofday(struct timeval *tv, struct timezone *tz) { - time_t t; - t = time(NULL); - SYSTEMTIME st; - GetLocalTime(&st); - - tv->tv_sec = (long)t; - tv->tv_usec = st.wMilliseconds * 1000; - - return 0; -} - -struct tm *localtime_r(const time_t *timep, struct tm *result) { - localtime_s(result, timep); - return result; -} \ No newline at end of file diff --git a/src/os/windows/src/twintimer.c b/src/os/windows/src/twintimer.c deleted file mode 100644 index 2bb8478f09..0000000000 --- a/src/os/windows/src/twintimer.c +++ /dev/null @@ -1,54 +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 . - */ - -#include -#include -#include -#include - -#pragma warning( disable : 4244 ) - -typedef void (*win_timer_f)(int signo); - -void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwl, DWORD_PTR dw2) -{ - win_timer_f callback = *((win_timer_f *)&dwUser); - if (callback != NULL) { - callback(0); - } -} - -static MMRESULT timerId; -int taosInitTimer(win_timer_f callback, int ms) { - DWORD_PTR param = *((int64_t *) & callback); - - timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC); - if (timerId == 0) { - return -1; - } - return 0; -} - -void taosUninitTimer() { - timeKillEvent(timerId); -} - -void taosMsleep(int mseconds) { - Sleep(mseconds); -} - -void sleep(int mseconds) { - taosMsleep(mseconds); -} \ No newline at end of file diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index c71820211b..2bc6bf54bf 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -4,5 +4,3 @@ PROJECT(TDengine) ADD_SUBDIRECTORY(monitor) ADD_SUBDIRECTORY(http) ADD_SUBDIRECTORY(mqtt) -ADD_SUBDIRECTORY(balance) -ADD_SUBDIRECTORY(sync) diff --git a/src/sync/CMakeLists.txt b/src/sync/CMakeLists.txt index 0a5d18022b..ca6a74f695 100644 --- a/src/sync/CMakeLists.txt +++ b/src/sync/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) diff --git a/src/sync/src/syncRetrieve.c b/src/sync/src/syncRetrieve.c index c7f136ed9d..74970017fa 100644 --- a/src/sync/src/syncRetrieve.c +++ b/src/sync/src/syncRetrieve.c @@ -140,7 +140,7 @@ static int syncRetrieveFile(SSyncPeer *pPeer) int sfd = open(name, O_RDONLY); if ( sfd < 0 ) break; - ret = tsendfile(pPeer->syncFd, sfd, NULL, fileInfo.size); + ret = taosTSendFile(pPeer->syncFd, sfd, NULL, fileInfo.size); close(sfd); if (ret <0) break; @@ -393,7 +393,7 @@ static int syncRetrieveWal(SSyncPeer *pPeer) int sfd = open(fname, O_RDONLY); if (sfd < 0) break; - code = tsendfile(pPeer->syncFd, sfd, NULL, size); + code = taosTSendFile(pPeer->syncFd, sfd, NULL, size); close(sfd); if (code <0) break; diff --git a/src/sync/test/CMakeLists.txt b/src/sync/test/CMakeLists.txt index fd8bdd1668..89d739080f 100644 --- a/src/sync/test/CMakeLists.txt +++ b/src/sync/test/CMakeLists.txt @@ -2,8 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(../inc) diff --git a/src/util/inc/tfile.h b/src/util/inc/tfile.h deleted file mode 100644 index de52a40967..0000000000 --- a/src/util/inc/tfile.h +++ /dev/null @@ -1,33 +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 TDENGINE_TFILE_H -#define TDENGINE_TFILE_H - -#ifdef TAOS_RANDOM_FILE_FAIL - -void taosSetRandomFileFailFactor(int factor); -void taosSetRandomFileFailOutput(const char *path); -ssize_t taos_tread(int fd, void *buf, size_t count, const char *file, uint32_t line); -ssize_t taos_twrite(int fd, void *buf, size_t count, const char *file, uint32_t line); -off_t taos_lseek(int fd, off_t offset, int whence, const char *file, uint32_t line); - -#define tread(fd, buf, count) taos_tread(fd, buf, count, __FILE__, __LINE__) -#define twrite(fd, buf, count) taos_twrite(fd, buf, count, __FILE__, __LINE__) -#define lseek(fd, offset, whence) taos_lseek(fd, offset, whence, __FILE__, __LINE__) - -#endif // TAOS_RANDOM_FILE_FAIL - -#endif // TDENGINE_TFILE_H diff --git a/src/util/src/tfile.c b/src/util/src/tfile.c deleted file mode 100644 index d1a9c24615..0000000000 --- a/src/util/src/tfile.c +++ /dev/null @@ -1,117 +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 . - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "os.h" - -#ifdef TAOS_RANDOM_FILE_FAIL - -static int random_file_fail_factor = 20; -static FILE *fpRandomFileFailOutput = NULL; - -void taosSetRandomFileFailFactor(int factor) -{ - random_file_fail_factor = factor; -} - -static void close_random_file_fail_output() -{ - if (fpRandomFileFailOutput != NULL) { - if (fpRandomFileFailOutput != stdout) { - fclose(fpRandomFileFailOutput); - } - fpRandomFileFailOutput = NULL; - } -} - -static void random_file_fail_output_sig(int sig) -{ - fprintf(fpRandomFileFailOutput, "signal %d received.\n", sig); - - struct sigaction act = {0}; - act.sa_handler = SIG_DFL; - sigaction(sig, &act, NULL); - - close_random_file_fail_output(); - exit(EXIT_FAILURE); -} - -void taosSetRandomFileFailOutput(const char *path) -{ - if (path == NULL) { - fpRandomFileFailOutput = stdout; - } else if ((fpRandomFileFailOutput = fopen(path, "w")) != NULL) { - atexit(close_random_file_fail_output); - } else { - printf("failed to open random file fail log file '%s', errno=%d\n", path, errno); - return; - } - - struct sigaction act = {0}; - act.sa_handler = random_file_fail_output_sig; - sigaction(SIGFPE, &act, NULL); - sigaction(SIGSEGV, &act, NULL); - sigaction(SIGILL, &act, NULL); -} -#endif - -ssize_t taos_tread(int fd, void *buf, size_t count, const char *file, uint32_t line) -{ -#ifdef TAOS_RANDOM_FILE_FAIL - if (random_file_fail_factor > 0) { - if (rand() % random_file_fail_factor == 0) { - errno = EIO; - return -1; - } - } -#endif - return tread(fd, buf, count); -} - -ssize_t taos_twrite(int fd, void *buf, size_t count, const char *file, uint32_t line) -{ -#ifdef TAOS_RANDOM_FILE_FAIL - if (random_file_fail_factor > 0) { - if (rand() % random_file_fail_factor == 0) { - errno = EIO; - return -1; - } - } -#endif - return twrite(fd, buf, count); -} - -off_t taos_lseek(int fd, off_t offset, int whence, const char *file, uint32_t line) -{ -#ifdef TAOS_RANDOM_FILE_FAIL - if (random_file_fail_factor > 0) { - if (rand() % random_file_fail_factor == 0) { - errno = EIO; - return -1; - } - } -#endif - return lseek(fd, offset, whence); -} diff --git a/tests/test/c/CMakeLists.txt b/tests/test/c/CMakeLists.txt index 8686a23f65..4736c1ebed 100644 --- a/tests/test/c/CMakeLists.txt +++ b/tests/test/c/CMakeLists.txt @@ -2,9 +2,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) #add_executable(insertPerTable insertPerTable.c) diff --git a/tests/tsim/CMakeLists.txt b/tests/tsim/CMakeLists.txt index 14ef791a4e..0a11a8f14e 100644 --- a/tests/tsim/CMakeLists.txt +++ b/tests/tsim/CMakeLists.txt @@ -1,11 +1,11 @@ PROJECT(TDengine) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) INCLUDE_DIRECTORIES(inc) IF (TD_WINDOWS_64) From 11a649240627c59ab8e8e978db55ea74205921c1 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 11:42:52 +0800 Subject: [PATCH 40/47] [td-255] --- src/dnode/src/dnodeVRead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index 85ed194976..506cc0895b 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -49,7 +49,7 @@ static taos_qset readQset; int32_t dnodeInitVnodeRead() { readQset = taosOpenQset(); - readPool.min = 4; + readPool.min = 32; readPool.max = tsNumOfCores * tsNumOfThreadsPerCore; if (readPool.max <= readPool.min * 2) readPool.max = 2 * readPool.min; readPool.readWorker = (SReadWorker *)calloc(sizeof(SReadWorker), readPool.max); From 534a0a32cddfb7204dcd8843da5f35783617f790 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 11:49:50 +0800 Subject: [PATCH 41/47] [td-255] change the min worker threads --- src/dnode/src/dnodeVRead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index 506cc0895b..8064f4d496 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -49,7 +49,7 @@ static taos_qset readQset; int32_t dnodeInitVnodeRead() { readQset = taosOpenQset(); - readPool.min = 32; + readPool.min = tsNumOfCores / 2; readPool.max = tsNumOfCores * tsNumOfThreadsPerCore; if (readPool.max <= readPool.min * 2) readPool.max = 2 * readPool.min; readPool.readWorker = (SReadWorker *)calloc(sizeof(SReadWorker), readPool.max); From 9d2d061c15b5a0fcb2259a876565c30ad5fa85ab Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 11:53:02 +0800 Subject: [PATCH 42/47] [td-255] change the min worker threads --- src/dnode/src/dnodeVRead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index 8064f4d496..75e5ff7b6b 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -49,7 +49,7 @@ static taos_qset readQset; int32_t dnodeInitVnodeRead() { readQset = taosOpenQset(); - readPool.min = tsNumOfCores / 2; + readPool.min = (tsNumOfCores * 2) / 3; readPool.max = tsNumOfCores * tsNumOfThreadsPerCore; if (readPool.max <= readPool.min * 2) readPool.max = 2 * readPool.min; readPool.readWorker = (SReadWorker *)calloc(sizeof(SReadWorker), readPool.max); From 228ea8ae9c7021c5bb110af3ac1d7fa04871d7f6 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 11:54:59 +0800 Subject: [PATCH 43/47] [td-255] change the min worker threads --- src/dnode/src/dnodeVRead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnode/src/dnodeVRead.c b/src/dnode/src/dnodeVRead.c index 75e5ff7b6b..cb53bb5e60 100644 --- a/src/dnode/src/dnodeVRead.c +++ b/src/dnode/src/dnodeVRead.c @@ -49,7 +49,7 @@ static taos_qset readQset; int32_t dnodeInitVnodeRead() { readQset = taosOpenQset(); - readPool.min = (tsNumOfCores * 2) / 3; + readPool.min = tsNumOfCores; readPool.max = tsNumOfCores * tsNumOfThreadsPerCore; if (readPool.max <= readPool.min * 2) readPool.max = 2 * readPool.min; readPool.readWorker = (SReadWorker *)calloc(sizeof(SReadWorker), readPool.max); From 1e99fd0f075e7534f4c90772a16eb1740a296c18 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Tue, 28 Jul 2020 11:58:43 +0800 Subject: [PATCH 44/47] fix examples/go/src/taosapp/taosapp.go to make it work with 2.0 [TD-1008] --- tests/examples/go/src/taosapp/taosapp.go | 79 ++++++++++++------------ 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/tests/examples/go/src/taosapp/taosapp.go b/tests/examples/go/src/taosapp/taosapp.go index 5c7b92f6fb..30126ea571 100644 --- a/tests/examples/go/src/taosapp/taosapp.go +++ b/tests/examples/go/src/taosapp/taosapp.go @@ -13,13 +13,13 @@ * along with this program. If not, see . */ package main - + import ( "database/sql" "time" "log" "fmt" - _ "taosSql" + _ "github.com/taosdata/driver-go/taosSql" ) func main() { @@ -29,7 +29,7 @@ func main() { fmt.Printf("\n======== start demo test ========\n") // open connect to taos server - db, err := sql.Open(taosDriverName, "root:taosdata@/tcp(127.0.0.1:0)/demodb") + db, err := sql.Open(taosDriverName, "root:taosdata@/tcp(127.0.0.1:0)/") if err != nil { log.Fatalf("Open database error: %s\n", err) } @@ -58,11 +58,11 @@ func main() { func drop_database(db *sql.DB, demodb string) { st := time.Now().Nanosecond() - res, err := db.Exec("drop database " + demodb) - checkErr(err) + res, err := db.Exec("drop database if exists " + demodb) + checkErr(err, "drop database if exists " + demodb) affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "drop db, res.RowsAffected") et := time.Now().Nanosecond() @@ -73,10 +73,10 @@ func create_database(db *sql.DB, demodb string) { st := time.Now().Nanosecond() // create database res, err := db.Exec("create database " + demodb) - checkErr(err) + checkErr(err, "create db, db.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "create db, res.RowsAffected") et := time.Now().Nanosecond() @@ -89,10 +89,10 @@ func use_database(db *sql.DB, demodb string) { st := time.Now().Nanosecond() // use database res, err := db.Exec("use " + demodb) // notes: must no quote to db name - checkErr(err) + checkErr(err, "use db db.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "use db, res.RowsAffected") et := time.Now().Nanosecond() @@ -103,10 +103,10 @@ func create_table(db *sql.DB, demot string) { st := time.Now().Nanosecond() // create table res, err := db.Exec("create table " + demot + " (ts timestamp, id int, name binary(8), len tinyint, flag bool, notes binary(8), fv float, dv double)") - checkErr(err) + checkErr(err, "create table db.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "create table res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("create table result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -120,10 +120,10 @@ func insert_data(db *sql.DB, demot string) { " (now+1s, 101, 'shanghai', 11, true, 'two', 789.123, 789.123)" + " (now+2s, 102, 'shenzhen', 12, false, 'three', 456.789, 456.789)") - checkErr(err) + checkErr(err, "insert data, db.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "insert data res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -133,7 +133,7 @@ func select_data(db *sql.DB, demot string) { st := time.Now().Nanosecond() rows, err := db.Query("select * from ? " , demot) // go text mode - checkErr(err) + checkErr(err, "select db.Query") fmt.Printf("%10s%s%8s %5s %9s%s %s %8s%s %7s%s %8s%s %4s%s %5s%s\n", " ","ts", " ", "id"," ", "name"," ","len", " ","flag"," ", "notes", " ", "fv", " ", " ", "dv") var affectd int @@ -148,7 +148,7 @@ func select_data(db *sql.DB, demot string) { var dv float64 err = rows.Scan(&ts, &id, &name, &len, &flag, ¬es, &fv, &dv) - checkErr(err) + checkErr(err, "select rows.Scan") fmt.Printf("%s\t", ts) fmt.Printf("%d\t",id) @@ -170,15 +170,11 @@ func select_data(db *sql.DB, demot string) { func drop_database_stmt(db *sql.DB,demodb string) { st := time.Now().Nanosecond() // drop test db - stmt, err := db.Prepare("drop database ?") - checkErr(err) - defer stmt.Close() - - res, err := stmt.Exec(demodb) - checkErr(err) + res, err := db.Exec("drop database if exists " + demodb) + checkErr(err, "drop database " + demodb) affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "drop db, res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("drop database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -189,15 +185,15 @@ func create_database_stmt(db *sql.DB,demodb string) { // create database //var stmt interface{} stmt, err := db.Prepare("create database ?") - checkErr(err) + checkErr(err, "create db, db.Prepare") //var res driver.Result res, err := stmt.Exec(demodb) - checkErr(err) + checkErr(err, "create db, stmt.Exec") //fmt.Printf("Query OK, %d row(s) affected()", res.RowsAffected()) affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "create db, res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("create database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -208,13 +204,13 @@ func use_database_stmt (db *sql.DB,demodb string) { // create database //var stmt interface{} stmt, err := db.Prepare("use " + demodb) - checkErr(err) + checkErr(err, "use db, db.Prepare") res, err := stmt.Exec() - checkErr(err) + checkErr(err, "use db, stmt.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "use db, res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("use database result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -224,14 +220,14 @@ func create_table_stmt (db *sql.DB,demot string) { st := time.Now().Nanosecond() // create table // (ts timestamp, id int, name binary(8), len tinyint, flag bool, notes binary(8), fv float, dv double) - stmt, err := db.Prepare("create table ? (? timestamp, ? int, ? binary(8), ? tinyint, ? bool, ? binary(8), ? float, ? double)") - checkErr(err) + stmt, err := db.Prepare("create table ? (? timestamp, ? int, ? binary(10), ? tinyint, ? bool, ? binary(8), ? float, ? double)") + checkErr(err, "create table db.Prepare") res, err := stmt.Exec(demot, "ts", "id", "name", "len", "flag", "notes", "fv", "dv") - checkErr(err) + checkErr(err, "create table stmt.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "create table res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("create table result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -241,15 +237,15 @@ func insert_data_stmt(db *sql.DB,demot string) { st := time.Now().Nanosecond() // insert data into table stmt, err := db.Prepare("insert into ? values(?, ?, ?, ?, ?, ?, ?, ?) (?, ?, ?, ?, ?, ?, ?, ?) (?, ?, ?, ?, ?, ?, ?, ?)") - checkErr(err) + checkErr(err, "insert db.Prepare") res, err := stmt.Exec(demot, "now" , 1000, "'haidian'" , 6, true, "'AI world'", 6987.654, 321.987, "now+1s", 1001, "'changyang'" , 7, false, "'DeepMode'", 12356.456, 128634.456, "now+2s", 1002, "'chuangping'" , 8, true, "'database'", 3879.456, 65433478.456,) - checkErr(err) + checkErr(err, "insert data, stmt.Exec") affectd, err := res.RowsAffected() - checkErr(err) + checkErr(err, "res.RowsAffected") et := time.Now().Nanosecond() fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) @@ -259,12 +255,12 @@ func select_data_stmt(db *sql.DB, demot string) { st := time.Now().Nanosecond() stmt, err := db.Prepare("select ?, ?, ?, ?, ?, ?, ?, ? from ?" ) // go binary mode - checkErr(err) + checkErr(err, "db.Prepare") rows, err := stmt.Query("ts", "id","name","len", "flag","notes", "fv", "dv", demot) - checkErr(err) + checkErr(err, "stmt.Query") - fmt.Printf("%10s%s%8s %5s %9s%s %s %8s%s %7s%s %8s%s %11s%s %14s%s\n", " ","ts", " ", "id"," ", "name"," ","len", " ","flag"," ", "notes", " ", "fv", " ", " ", "dv") + fmt.Printf("%10s%s%8s %5s %8s%s %s %10s%s %7s%s %8s%s %11s%s %14s%s\n", " ","ts", " ", "id"," ", "name"," ","len", " ","flag"," ", "notes", " ", "fv", " ", " ", "dv") var affectd int for rows.Next() { var ts string @@ -279,7 +275,7 @@ func select_data_stmt(db *sql.DB, demot string) { err = rows.Scan(&ts, &id, &name, &len, &flag, ¬es, &fv, &dv) //fmt.Println("start scan fields from row.rs, &fv:", &fv) //err = rows.Scan(&fv) - checkErr(err) + checkErr(err, "rows.Scan") fmt.Printf("%s\t", ts) fmt.Printf("%d\t",id) @@ -298,8 +294,9 @@ func select_data_stmt(db *sql.DB, demot string) { fmt.Printf("insert data result:\n %d row(s) affectd (%6.6fs)\n\n", affectd, (float32(et-st))/1E9) } -func checkErr(err error) { +func checkErr(err error, prompt string) { if err != nil { + fmt.Printf("%s\n", prompt) panic(err) } } From 5d6079e3ded2f3ed06dec2f4ee9af799d8c34ca6 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 13:50:08 +0800 Subject: [PATCH 45/47] [td-255] refactor codes. --- src/query/src/qExecutor.c | 1 - src/vnode/src/vnodeRead.c | 97 +++++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index bca07e7150..5aa453f30e 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6356,7 +6356,6 @@ bool qTableQuery(qinfo_t qinfo) { pthread_mutex_unlock(&pQInfo->lock); return buildRes; -// sem_post(&pQInfo->dataReady); } int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContext) { diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 2a4ca0e663..066770e1bb 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -77,6 +77,39 @@ static void vnodePutItemIntoReadQueue(SVnodeObj *pVnode, void *qhandle) { taosWriteQitem(pVnode->rqueue, TAOS_QTYPE_QUERY, pRead); } +static int32_t vnodeDumpQueryResult(SRspRet *pRet, void* pVnode, void* handle, bool* freeHandle) { + bool continueExec = false; + + int32_t code = TSDB_CODE_SUCCESS; + if ((code = qDumpRetrieveResult(handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { + if (continueExec) { + vDebug("QInfo:%p add to query task queue for exec", handle); + vnodePutItemIntoReadQueue(pVnode, handle); + pRet->qhandle = handle; + *freeHandle = false; + } else { + vDebug("QInfo:%p exec completed", handle); + *freeHandle = true; + } + } else { + pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); + memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); + *freeHandle = true; + } + + return code; +} + +static void vnodeBuildNoResultQueryRsp(SRspRet* pRet) { + pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); + pRet->len = sizeof(SRetrieveTableRsp); + + memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); + SRetrieveTableRsp* pRsp = pRet->rsp; + + pRsp->completed = true; +} + static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { void *pCont = pReadMsg->pCont; int32_t contLen = pReadMsg->contLen; @@ -161,37 +194,27 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { code = TSDB_CODE_QRY_INVALID_QHANDLE; } else { vDebug("vgId:%d, QInfo:%p, dnode continue exec query", pVnode->vgId, (void*) pCont); + + bool freehandle = false; bool buildRes = qTableQuery(*handle); // do execute query - if (buildRes) { // build result rsp + // build query rsp + if (buildRes) { // update the connection info according to the retrieve connection pReadMsg->rpcMsg.handle = qGetResultRetrieveMsg(*handle); assert(pReadMsg->rpcMsg.handle != NULL); vDebug("vgId:%d, QInfo:%p, start to build result rsp after query paused, %p", pVnode->vgId, *handle, pReadMsg->rpcMsg.handle); + code = vnodeDumpQueryResult(&pReadMsg->rspRet, pVnode, *handle, &freehandle); - pRet = &pReadMsg->rspRet; -// code = TSDB_CODE_QRY_HAS_RSP; - - bool continueExec = false; - if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { - - if (continueExec) { - vTrace("QInfo:%p add to queue for further exec", *handle); - vnodePutItemIntoReadQueue(pVnode, *handle); - pRet->qhandle = *handle; -// code = TSDB_CODE_SUCCESS; - } else { - vDebug("QInfo:%p query completed", *handle); - } - } else { // todo handle error + // todo test the error code case + if (code == TSDB_CODE_SUCCESS) { + code = TSDB_CODE_QRY_HAS_RSP; } - - code = TSDB_CODE_QRY_HAS_RSP; } - } - qReleaseQInfo(pVnode->qMgmt, (void**) &handle, false); + qReleaseQInfo(pVnode->qMgmt, (void**) &handle, freehandle); + } } return code; @@ -214,16 +237,8 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (handle == NULL || (*handle) != (void*) pRetrieve->qhandle) { code = TSDB_CODE_QRY_INVALID_QHANDLE; vDebug("vgId:%d, invalid qhandle in fetch result, QInfo:%p", pVnode->vgId, (void*) pRetrieve->qhandle); - - pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); - pRet->len = sizeof(SRetrieveTableRsp); - - memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); - SRetrieveTableRsp* pRsp = pRet->rsp; - pRsp->numOfRows = 0; - pRsp->useconds = 0; - pRsp->completed = true; - + + vnodeBuildNoResultQueryRsp(pRet); return code; } @@ -232,15 +247,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { qKillQuery(*handle); qReleaseQInfo(pVnode->qMgmt, (void**) &handle, true); - pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); - pRet->len = sizeof(SRetrieveTableRsp); - - memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); - SRetrieveTableRsp* pRsp = pRet->rsp; - pRsp->numOfRows = 0; - pRsp->completed = true; - pRsp->useconds = 0; - + vnodeBuildNoResultQueryRsp(pRet); return code; } @@ -258,17 +265,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { return TSDB_CODE_QRY_NOT_READY; } - bool continueExec = false; - if ((code = qDumpRetrieveResult(*handle, (SRetrieveTableRsp **)&pRet->rsp, &pRet->len, &continueExec)) == TSDB_CODE_SUCCESS) { - if (continueExec) { - vnodePutItemIntoReadQueue(pVnode, *handle); - pRet->qhandle = *handle; - freeHandle = false; - } - } else { - pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); - memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); - } + code = vnodeDumpQueryResult(pRet, pVnode, *handle, &freeHandle); } qReleaseQInfo(pVnode->qMgmt, (void**) &handle, freeHandle); From 5b248a9808c618c1ab46453e0208ace4418428ed Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 14:24:12 +0800 Subject: [PATCH 46/47] [td-255] refactor codes. --- src/util/src/tcache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index a086a87b4b..ca0fdc36be 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -457,8 +457,9 @@ void taosCacheRelease(SCacheObj *pCacheObj, void **data, bool _remove) { } else { // NOTE: once refcount is decrease, pNode may be freed by other thread immediately. int32_t ref = T_REF_DEC(pNode); - uDebug("cache:%s, key:%p, %p is released, refcnt:%d, in trashcan:%d", pCacheObj->name, pNode->key, pNode->data, ref, - inTrashCan); + + uDebug("cache:%s, key:%p, %p released, refcnt:%d, data in trancan:%d", pCacheObj->name, pNode->key, pNode->data, + ref, inTrashCan); } } From 71b8850cce28900db8d34de415fa035e1f76bc97 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 28 Jul 2020 14:36:05 +0800 Subject: [PATCH 47/47] [td-255] refactor codes. --- src/query/src/qExecutor.c | 2 +- src/util/inc/tcache.h | 2 -- src/util/src/tcache.c | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 5aa453f30e..5313e5378a 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -6647,7 +6647,7 @@ void freeqinfoFn(void *qhandle) { } void* qOpenQueryMgmt(int32_t vgId) { - const int32_t REFRESH_HANDLE_INTERVAL = 2; // every 2 seconds, refresh handle pool + const int32_t REFRESH_HANDLE_INTERVAL = 30; // every 30 seconds, refresh handle pool char cacheName[128] = {0}; sprintf(cacheName, "qhandle_%d", vgId); diff --git a/src/util/inc/tcache.h b/src/util/inc/tcache.h index 5a3545fd8f..1e2aeae394 100644 --- a/src/util/inc/tcache.h +++ b/src/util/inc/tcache.h @@ -68,8 +68,6 @@ typedef struct { int64_t refreshTime; STrashElem * pTrash; char* name; -// void * tmrCtrl; -// void * pTimer; SCacheStatis statistics; SHashObj * pHashTable; __cache_free_fn_t freeFp; diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index ca0fdc36be..0a9a69737b 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -573,6 +573,7 @@ void taosRemoveFromTrashCan(SCacheObj *pCacheObj, STrashElem *pElem) { free(pElem); } +// TODO add another lock when scanning trashcan void taosTrashCanEmpty(SCacheObj *pCacheObj, bool force) { __cache_wr_lock(pCacheObj);