Merge branch 'develop' into feature/2.0tsdb
This commit is contained in:
commit
2e3ae87f47
259
.travis.yml
259
.travis.yml
|
@ -45,7 +45,9 @@ matrix:
|
|||
cd ${TRAVIS_BUILD_DIR}/debug
|
||||
make install > /dev/null || travis_terminate $?
|
||||
|
||||
pip install numpy
|
||||
pip install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python2/
|
||||
pip3 install numpy
|
||||
pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/
|
||||
|
||||
cd ${TRAVIS_BUILD_DIR}/tests
|
||||
|
@ -164,7 +166,9 @@ matrix:
|
|||
cd ${TRAVIS_BUILD_DIR}/debug
|
||||
make install > /dev/null || travis_terminate $?
|
||||
|
||||
pip install numpy
|
||||
pip install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python2/
|
||||
pip3 install numpy
|
||||
pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/
|
||||
|
||||
cd ${TRAVIS_BUILD_DIR}/tests
|
||||
|
@ -256,6 +260,261 @@ matrix:
|
|||
- cmake .. > /dev/null
|
||||
- make > /dev/null
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
language: c
|
||||
compiler: clang
|
||||
env: DESC="linux/clang build"
|
||||
git:
|
||||
- depth: 1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- cmake
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- mkdir debug
|
||||
- cd debug
|
||||
|
||||
script:
|
||||
- if [ "${TRAVIS_CPU_ARCH}" == "arm64" ]; then
|
||||
cmake .. -DCPUTYPE=aarch64 > /dev/null;
|
||||
else
|
||||
cmake .. > /dev/null;
|
||||
fi
|
||||
- make > /dev/null
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: trusty
|
||||
language: c
|
||||
git:
|
||||
- depth: 1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- cmake
|
||||
env:
|
||||
- DESC="trusty/gcc-4.8 build"
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- mkdir debug
|
||||
- cd debug
|
||||
|
||||
script:
|
||||
- if [ "${TRAVIS_CPU_ARCH}" == "arm64" ]; then
|
||||
cmake .. -DCPUTYPE=aarch64 > /dev/null;
|
||||
else
|
||||
cmake .. > /dev/null;
|
||||
fi
|
||||
- make > /dev/null
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
language: c
|
||||
compiler: gcc
|
||||
env: ENV_COVER=true
|
||||
|
||||
git:
|
||||
- depth: 1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- cmake
|
||||
- net-tools
|
||||
- python-pip
|
||||
- python-setuptools
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
- lcov
|
||||
- psmisc
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- mkdir debug
|
||||
- cd debug
|
||||
|
||||
script:
|
||||
- if [ "${TRAVIS_CPU_ARCH}" == "arm64" ];
|
||||
then cmake -DCOVER=true .. -DCPUTYPE=aarch64 > /dev/null;
|
||||
else cmake -DCOVER=true .. > /dev/null;
|
||||
fi
|
||||
- make > /dev/null
|
||||
|
||||
after_success:
|
||||
- |-
|
||||
case $TRAVIS_OS_NAME in
|
||||
linux)
|
||||
cd ${TRAVIS_BUILD_DIR}/debug
|
||||
make install > /dev/null || travis_terminate $?
|
||||
pip install numpy
|
||||
pip install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python2/
|
||||
pip3 install numpy
|
||||
pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/
|
||||
cd ${TRAVIS_BUILD_DIR}/tests
|
||||
./test-all.sh smoke COVER
|
||||
TEST_RESULT=$?
|
||||
pkill taosd
|
||||
sleep 1
|
||||
cd ${TRAVIS_BUILD_DIR}
|
||||
lcov -d . --capture --rc lcov_branch_coverage=1 -o coverage.info
|
||||
lcov --remove coverage.info '*/tests/*' '*/test/*' '*/deps/*' '*/plugins/*' -o coverage.info
|
||||
lcov -l --rc lcov_branch_coverage=1 coverage.info || travis_terminate $?
|
||||
gem install coveralls-lcov
|
||||
# Color setting
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[1;32m'
|
||||
GREEN_DARK='\033[0;32m'
|
||||
GREEN_UNDERLINE='\033[4;32m'
|
||||
NC='\033[0m'
|
||||
coveralls-lcov coverage.info
|
||||
if [ "$?" -eq "0" ]; then
|
||||
echo -e "${GREEN} ## Uploaded to Coveralls.io! ## ${NC}"
|
||||
else
|
||||
echo -e "${RED} ## Coveralls.io not collect coverage report! ## ${NC} "
|
||||
fi
|
||||
bash <(curl -s https://codecov.io/bash) -y .codecov.yml -f coverage.info
|
||||
if [ "$?" -eq "0" ]; then
|
||||
echo -e "${GREEN} ## Uploaded to Codecov! ## ${NC} "
|
||||
else
|
||||
echo -e "${RED} ## Codecov did not collect coverage report! ## ${NC} "
|
||||
fi
|
||||
if [ "$TEST_RESULT" -ne "0" ]; then
|
||||
travis_terminate $?
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
language: c
|
||||
|
||||
git:
|
||||
- depth: 1
|
||||
|
||||
compiler: gcc
|
||||
env: DESC="linux/gcc build and test"
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- build-essential
|
||||
- cmake
|
||||
- net-tools
|
||||
- python-pip
|
||||
- python-setuptools
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
- valgrind
|
||||
- psmisc
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- mkdir debug
|
||||
- cd debug
|
||||
|
||||
script:
|
||||
- if [ "${TRAVIS_CPU_ARCH}" == "arm64" ];
|
||||
then cmake .. -DCPUTYPE=aarch64 > /dev/null;
|
||||
else cmake .. > /dev/null;
|
||||
fi
|
||||
- make > /dev/null
|
||||
|
||||
after_success:
|
||||
- travis_wait 20
|
||||
- |-
|
||||
case $TRAVIS_OS_NAME in
|
||||
linux)
|
||||
cd ${TRAVIS_BUILD_DIR}/debug
|
||||
make install > /dev/null || travis_terminate $?
|
||||
pip install numpy
|
||||
pip install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python2/
|
||||
pip3 install numpy
|
||||
pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/
|
||||
cd ${TRAVIS_BUILD_DIR}/tests
|
||||
./test-all.sh smoke || travis_terminate $?
|
||||
cd ${TRAVIS_BUILD_DIR}/tests/pytest
|
||||
./valgrind-test.sh 2>&1 > mem-error-out.log
|
||||
sleep 1
|
||||
# Color setting
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[1;32m'
|
||||
GREEN_DARK='\033[0;32m'
|
||||
GREEN_UNDERLINE='\033[4;32m'
|
||||
NC='\033[0m'
|
||||
grep 'start to execute\|ERROR SUMMARY' mem-error-out.log|grep -v 'grep'|uniq|tee uniq-mem-error-out.log
|
||||
for memError in `grep 'ERROR SUMMARY' uniq-mem-error-out.log | awk '{print $4}'`
|
||||
do
|
||||
if [ -n "$memError" ]; then
|
||||
if [ "$memError" -gt 12 ]; then
|
||||
echo -e "${RED} ## Memory errors number valgrind reports is $memError.\
|
||||
More than our threshold! ## ${NC}"
|
||||
travis_terminate $memError
|
||||
fi
|
||||
fi
|
||||
done
|
||||
grep 'start to execute\|definitely lost:' mem-error-out.log|grep -v 'grep'|uniq|tee uniq-definitely-lost-out.log
|
||||
for defiMemError in `grep 'definitely lost:' uniq-definitely-lost-out.log | awk '{print $7}'`
|
||||
do
|
||||
if [ -n "$defiMemError" ]; then
|
||||
if [ "$defiMemError" -gt 13 ]; then
|
||||
echo -e "${RED} ## Memory errors number valgrind reports \
|
||||
Definitely lost is $defiMemError. More than our threshold! ## ${NC}"
|
||||
travis_terminate $defiMemError
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
language: c
|
||||
compiler: gcc
|
||||
env: COVERITY_SCAN=true
|
||||
git:
|
||||
- depth: 1
|
||||
|
||||
script:
|
||||
- echo "this job is for coverity scan"
|
||||
|
||||
addons:
|
||||
coverity_scan:
|
||||
# GitHub project metadata
|
||||
# ** specific to your project **
|
||||
project:
|
||||
name: TDengine
|
||||
version: 2.x
|
||||
description: TDengine
|
||||
|
||||
# Where email notification of build analysis results will be sent
|
||||
notification_email: sdsang@taosdata.com, slguan@taosdata.com
|
||||
|
||||
# Commands to prepare for build_command
|
||||
# ** likely specific to your build **
|
||||
build_command_prepend: cmake . > /dev/null
|
||||
|
||||
# The command that will be added as an argument to "cov-build" to compile your project for analysis,
|
||||
# ** likely specific to your build **
|
||||
build_command: make
|
||||
|
||||
# Pattern to match selecting branches that will run analysis. We recommend leaving this set to 'coverity_scan'.
|
||||
# Take care in resource usage, and consider the build frequency allowances per
|
||||
# https://scan.coverity.com/faq#frequency
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
# - os: osx
|
||||
# language: c
|
||||
# compiler: clang
|
||||
|
|
|
@ -28,7 +28,7 @@ extern "C" {
|
|||
#include "exception.h"
|
||||
#include "qextbuffer.h"
|
||||
#include "taosdef.h"
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "tscLocalMerge.h"
|
||||
#include "tsclient.h"
|
||||
|
||||
#define UTIL_TABLE_IS_SUPER_TABLE(metaInfo) \
|
||||
|
@ -122,15 +122,13 @@ bool tscNonOrderedProjectionQueryOnSTable(SQueryInfo *pQueryInfo, int32_t tableI
|
|||
bool tscOrderedProjectionQueryOnSTable(SQueryInfo* pQueryInfo, int32_t tableIndex);
|
||||
bool tscIsProjectionQueryOnSTable(SQueryInfo* pQueryInfo, int32_t tableIndex);
|
||||
|
||||
bool tscProjectionQueryOnTable(SQueryInfo* pQueryInfo);
|
||||
bool tscIsProjectionQuery(SQueryInfo* pQueryInfo);
|
||||
|
||||
bool tscIsTwoStageSTableQuery(SQueryInfo* pQueryInfo, int32_t tableIndex);
|
||||
bool tscQueryOnSTable(SSqlCmd* pCmd);
|
||||
bool tscQueryTags(SQueryInfo* pQueryInfo);
|
||||
bool tscIsSelectivityWithTagQuery(SSqlCmd* pCmd);
|
||||
|
||||
void tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, SColumnIndex* pIndex,
|
||||
SSchema* pColSchema, int16_t isTag);
|
||||
SSchema* pColSchema, int16_t colType);
|
||||
|
||||
int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SSQLToken* pzTableName, SSqlObj* pSql);
|
||||
void tscClearInterpInfo(SQueryInfo* pQueryInfo);
|
||||
|
@ -139,7 +137,7 @@ bool tscIsInsertData(char* sqlstr);
|
|||
|
||||
/* use for keep current db info temporarily, for handle table with db prefix */
|
||||
// todo remove it
|
||||
void tscGetDBInfoFromMeterId(char* tableId, char* db);
|
||||
void tscGetDBInfoFromTableFullName(char* tableId, char* db);
|
||||
|
||||
int tscAllocPayload(SSqlCmd* pCmd, int size);
|
||||
|
||||
|
@ -253,7 +251,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t sub
|
|||
|
||||
void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex);
|
||||
|
||||
int16_t tscGetJoinTagColIndexByUid(STagCond* pTagCond, uint64_t uid);
|
||||
int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid);
|
||||
|
||||
void tscPrintSelectClause(SSqlObj* pSql, int32_t subClauseIndex);
|
||||
|
||||
|
|
|
@ -64,12 +64,20 @@ SSchema* tscGetTableSchema(const STableMeta* pTableMeta);
|
|||
SSchema *tscGetTableTagSchema(const STableMeta *pMeta);
|
||||
|
||||
/**
|
||||
*
|
||||
* get the column schema according to the column index
|
||||
* @param pMeta
|
||||
* @param startCol
|
||||
* @param colIndex
|
||||
* @return
|
||||
*/
|
||||
SSchema *tscGetTableColumnSchema(const STableMeta *pMeta, int32_t startCol);
|
||||
SSchema *tscGetTableColumnSchema(const STableMeta *pMeta, int32_t colIndex);
|
||||
|
||||
/**
|
||||
* get the column schema according to the column id
|
||||
* @param pTableMeta
|
||||
* @param colId
|
||||
* @return
|
||||
*/
|
||||
SSchema* tscGetTableColumnSchemaById(STableMeta* pTableMeta, int16_t colId);
|
||||
|
||||
/**
|
||||
* check if the schema is valid or not, including following aspects:
|
||||
|
|
|
@ -123,7 +123,7 @@ typedef struct SCond {
|
|||
typedef struct SJoinNode {
|
||||
char tableId[TSDB_TABLE_ID_LEN];
|
||||
uint64_t uid;
|
||||
int16_t tagCol;
|
||||
int16_t tagColId;
|
||||
} SJoinNode;
|
||||
|
||||
typedef struct SJoinInfo {
|
||||
|
@ -161,14 +161,13 @@ typedef struct STableDataBlocks {
|
|||
int64_t vgId; // virtual group id
|
||||
int64_t prevTS; // previous timestamp, recorded to decide if the records array is ts ascending
|
||||
int32_t numOfTables; // number of tables in current submit block
|
||||
|
||||
int32_t rowSize; // row size for current table
|
||||
uint32_t nAllocSize;
|
||||
uint32_t headerSize; // header for metadata (submit metadata)
|
||||
uint32_t headerSize; // header for table info (uid, tid, submit metadata)
|
||||
uint32_t size;
|
||||
|
||||
/*
|
||||
* the metermeta for current table, the metermeta will be used during submit stage, keep a ref
|
||||
* the table meta of table, the table meta will be used during submit, keep a ref
|
||||
* to avoid it to be removed from cache
|
||||
*/
|
||||
STableMeta *pTableMeta;
|
||||
|
@ -194,12 +193,10 @@ typedef struct SQueryInfo {
|
|||
int16_t command; // the command may be different for each subclause, so keep it seperately.
|
||||
uint32_t type; // query/insert/import type
|
||||
char slidingTimeUnit;
|
||||
|
||||
STimeWindow window;
|
||||
int64_t intervalTime; // aggregation time interval
|
||||
int64_t slidingTime; // sliding window in mseconds
|
||||
SSqlGroupbyExpr groupbyExpr; // group by tags info
|
||||
|
||||
SArray * colList; // SArray<SColumn*>
|
||||
SFieldInfo fieldsInfo;
|
||||
SArray * exprList; // SArray<SSqlExpr*>
|
||||
|
@ -214,9 +211,7 @@ typedef struct SQueryInfo {
|
|||
int64_t * fillVal; // default value for fill
|
||||
char * msg; // pointer to the pCmd->payload to keep error message temporarily
|
||||
int64_t clauseLimit; // limit for current sub clause
|
||||
|
||||
// offset value in the original sql expression, NOT sent to virtual node, only applied at client side
|
||||
int64_t prjOffset;
|
||||
int64_t prjOffset; // offset value in the original sql expression, only applied at client side
|
||||
} SQueryInfo;
|
||||
|
||||
typedef struct {
|
||||
|
@ -286,7 +281,7 @@ typedef struct STscObj {
|
|||
char user[TSDB_USER_LEN];
|
||||
char pass[TSDB_KEY_LEN];
|
||||
char acctId[TSDB_ACCT_LEN];
|
||||
char db[TSDB_DB_NAME_LEN];
|
||||
char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN];
|
||||
char sversion[TSDB_VERSION_LEN];
|
||||
char writeAuth : 1;
|
||||
char superAuth : 1;
|
||||
|
@ -431,7 +426,7 @@ extern int (*tscBuildMsg[TSDB_SQL_MAX])(SSqlObj *pSql, SSqlInfo *pInfo);
|
|||
typedef void (*__async_cb_func_t)(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
int32_t tscCompareTidTags(const void* p1, const void* p2);
|
||||
void tscBuildVgroupTableInfo(STableMetaInfo* pTableMetaInfo, SArray* tables);
|
||||
void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArray* tables);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -151,8 +151,8 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_dumpMemoryLeakImp
|
|||
JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *env, jobject jobj, jstring jconfigDir) {
|
||||
if (jconfigDir != NULL) {
|
||||
const char *confDir = (*env)->GetStringUTFChars(env, jconfigDir, NULL);
|
||||
if (confDir && strlen(configDir) != 0) {
|
||||
strcpy(configDir, confDir);
|
||||
if (confDir && strlen(confDir) != 0) {
|
||||
tstrncpy(configDir, confDir, TSDB_FILENAME_LEN);
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, jconfigDir, confDir);
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsIm
|
|||
}
|
||||
|
||||
jint ret = taos_affected_rows((SSqlObj *)res);
|
||||
jniTrace("jobj:%p, conn:%p, sql:%p, affect rows:%d", jobj, tscon, (void *)con, res, ret);
|
||||
jniTrace("jobj:%p, conn:%p, sql:%p, affect rows:%d", jobj, tscon, (SSqlObj*)res, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -411,10 +411,10 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaData
|
|||
// jobject arrayListObj = (*env)->NewObject(env, g_arrayListClass, g_arrayListConstructFp, "");
|
||||
|
||||
if (num_fields == 0) {
|
||||
jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields);
|
||||
jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void*)res, num_fields);
|
||||
return JNI_NUM_OF_FIELDS_0;
|
||||
} else {
|
||||
jniTrace("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields);
|
||||
jniTrace("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void*)res, num_fields);
|
||||
for (int i = 0; i < num_fields; ++i) {
|
||||
jobject metadataObj = (*env)->NewObject(env, g_metadataClass, g_metadataConstructFp);
|
||||
(*env)->SetIntField(env, metadataObj, g_metadataColtypeField, fields[i].type);
|
||||
|
@ -465,7 +465,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
|
|||
int num_fields = taos_num_fields(result);
|
||||
|
||||
if (num_fields == 0) {
|
||||
jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, res, num_fields);
|
||||
jniError("jobj:%p, conn:%p, resultset:%p, fields size is %d", jobj, tscon, (void*)res, num_fields);
|
||||
return JNI_NUM_OF_FIELDS_0;
|
||||
}
|
||||
|
||||
|
@ -473,7 +473,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
|
|||
if (row == NULL) {
|
||||
int tserrno = taos_errno(result);
|
||||
if (tserrno == 0) {
|
||||
jniTrace("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, res, num_fields);
|
||||
jniTrace("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, num_fields);
|
||||
return JNI_FETCH_END;
|
||||
} else {
|
||||
jniTrace("jobj:%p, conn:%p, interruptted query", jobj, tscon);
|
||||
|
@ -571,9 +571,9 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp(JNI
|
|||
sub = (jlong)tsub;
|
||||
|
||||
if (sub == 0) {
|
||||
jniTrace("jobj:%p, failed to subscribe: topic:%s", jobj, jtopic);
|
||||
jniTrace("jobj:%p, failed to subscribe: topic:%s", jobj, topic);
|
||||
} else {
|
||||
jniTrace("jobj:%p, successfully subscribe: topic: %s", jobj, jtopic);
|
||||
jniTrace("jobj:%p, successfully subscribe: topic: %s", jobj, topic);
|
||||
}
|
||||
|
||||
if (topic != NULL) (*env)->ReleaseStringUTFChars(env, jtopic, topic);
|
||||
|
@ -583,7 +583,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp(JNI
|
|||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_consumeImp(JNIEnv *env, jobject jobj, jlong sub) {
|
||||
jniTrace("jobj:%p, in TSDBJNIConnector_consumeImp, sub:%ld", jobj, sub);
|
||||
jniTrace("jobj:%p, in TSDBJNIConnector_consumeImp, sub:%" PRId64, jobj, sub);
|
||||
jniGetGlobalMethod(env);
|
||||
|
||||
TAOS_SUB *tsub = (TAOS_SUB *)sub;
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
#include "tnote.h"
|
||||
#include "trpc.h"
|
||||
#include "tscLog.h"
|
||||
#include "tscProfile.h"
|
||||
#include "tscSubquery.h"
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "tscLocalMerge.h"
|
||||
#include "tscUtil.h"
|
||||
#include "tsched.h"
|
||||
#include "tschemautil.h"
|
||||
|
@ -46,7 +45,8 @@ int doAsyncParseSql(SSqlObj* pSql) {
|
|||
int32_t code = tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("failed to malloc payload");
|
||||
tscQueueAsyncError(pSql->fp, pSql->param, TSDB_CODE_TSC_OUT_OF_MEMORY);
|
||||
tscQueueAsyncRes(pSql);
|
||||
// tscQueueAsyncRes(pSql->fp, pSql->param, TSDB_CODE_TSC_OUT_OF_MEMORY);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,8 @@ void taos_fetch_rows_a(TAOS_RES *taosa, void (*fp)(void *, TAOS_RES *, int), voi
|
|||
|
||||
if (pRes->qhandle == 0) {
|
||||
tscError("qhandle is NULL");
|
||||
tscQueueAsyncError(fp, param, TSDB_CODE_TSC_INVALID_QHANDLE);
|
||||
pRes->code = TSDB_CODE_TSC_INVALID_QHANDLE;
|
||||
tscQueueAsyncRes(pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -285,7 +286,7 @@ void taos_fetch_row_a(TAOS_RES *taosa, void (*fp)(void *, TAOS_RES *, TAOS_ROW),
|
|||
|
||||
tscProcessSql(pSql);
|
||||
} else {
|
||||
SSchedMsg schedMsg;
|
||||
SSchedMsg schedMsg = { 0 };
|
||||
schedMsg.fp = tscProcessFetchRow;
|
||||
schedMsg.ahandle = pSql;
|
||||
schedMsg.thandle = pRes->tsrow;
|
||||
|
@ -368,7 +369,9 @@ void tscProcessAsyncRes(SSchedMsg *pMsg) {
|
|||
pSql->fp = pSql->fetchFp;
|
||||
}
|
||||
|
||||
if (pSql->fp) {
|
||||
(*pSql->fp)(pSql->param, taosres, code);
|
||||
}
|
||||
|
||||
if (shouldFree) {
|
||||
tscTrace("%p sqlObj is automatically freed in async res", pSql);
|
||||
|
@ -385,7 +388,7 @@ void tscQueueAsyncError(void(*fp), void *param, int32_t code) {
|
|||
int32_t* c = malloc(sizeof(int32_t));
|
||||
*c = code;
|
||||
|
||||
SSchedMsg schedMsg;
|
||||
SSchedMsg schedMsg = { 0 };
|
||||
schedMsg.fp = tscProcessAsyncError;
|
||||
schedMsg.ahandle = fp;
|
||||
schedMsg.thandle = param;
|
||||
|
@ -401,7 +404,7 @@ void tscQueueAsyncRes(SSqlObj *pSql) {
|
|||
tscError("%p add into queued async res, code:%s", pSql, tstrerror(pSql->res.code));
|
||||
}
|
||||
|
||||
SSchedMsg schedMsg;
|
||||
SSchedMsg schedMsg = { 0 };
|
||||
schedMsg.fp = tscProcessAsyncRes;
|
||||
schedMsg.ahandle = pSql;
|
||||
schedMsg.thandle = (void *)1;
|
||||
|
@ -418,7 +421,7 @@ void tscProcessAsyncFree(SSchedMsg *pMsg) {
|
|||
void tscQueueAsyncFreeResult(SSqlObj *pSql) {
|
||||
tscTrace("%p sqlObj put in queue to async free", pSql);
|
||||
|
||||
SSchedMsg schedMsg;
|
||||
SSchedMsg schedMsg = { 0 };
|
||||
schedMsg.fp = tscProcessAsyncFree;
|
||||
schedMsg.ahandle = pSql;
|
||||
schedMsg.thandle = (void *)1;
|
||||
|
|
|
@ -153,7 +153,7 @@ typedef struct SRateInfo {
|
|||
|
||||
int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type,
|
||||
int16_t *bytes, int32_t *interBytes, int16_t extLength, bool isSuperTable) {
|
||||
if (!isValidDataType(dataType, dataBytes)) {
|
||||
if (!isValidDataType(dataType)) {
|
||||
tscError("Illegal data type %d or data type length %d", dataType, dataBytes);
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ static int32_t first_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end,
|
|||
}
|
||||
|
||||
static int32_t last_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) {
|
||||
if (pCtx->order == TSDB_ORDER_ASC) {
|
||||
if (pCtx->order != pCtx->param[0].i64Key) {
|
||||
return BLK_DATA_NO_NEEDED;
|
||||
}
|
||||
|
||||
|
@ -727,7 +727,7 @@ static int32_t first_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY
|
|||
}
|
||||
|
||||
static int32_t last_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) {
|
||||
if (pCtx->order == TSDB_ORDER_ASC) {
|
||||
if (pCtx->order != pCtx->param[0].i64Key) {
|
||||
return BLK_DATA_NO_NEEDED;
|
||||
}
|
||||
|
||||
|
@ -1652,7 +1652,7 @@ static void first_dist_func_second_merge(SQLFunctionCtx *pCtx) {
|
|||
* least one data in this block that is not null.(TODO opt for this case)
|
||||
*/
|
||||
static void last_function(SQLFunctionCtx *pCtx) {
|
||||
if (pCtx->order == TSDB_ORDER_ASC) {
|
||||
if (pCtx->order != pCtx->param[0].i64Key) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1681,7 +1681,6 @@ static void last_function(SQLFunctionCtx *pCtx) {
|
|||
}
|
||||
|
||||
static void last_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
||||
assert(pCtx->order != TSDB_ORDER_ASC);
|
||||
void *pData = GET_INPUT_CHAR_INDEX(pCtx, index);
|
||||
if (pCtx->hasNull && isNull(pData, pCtx->inputType)) {
|
||||
return;
|
||||
|
@ -1725,7 +1724,7 @@ static void last_dist_function(SQLFunctionCtx *pCtx) {
|
|||
* 1. for scan data in asc order, no need to check data
|
||||
* 2. for data blocks that are not loaded, no need to check data
|
||||
*/
|
||||
if (pCtx->order == TSDB_ORDER_ASC) {
|
||||
if (pCtx->order != pCtx->param[0].i64Key) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1763,7 +1762,7 @@ static void last_dist_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
|||
* 1. for scan data in asc order, no need to check data
|
||||
* 2. for data blocks that are not loaded, no need to check data
|
||||
*/
|
||||
if (pCtx->order == TSDB_ORDER_ASC) {
|
||||
if (pCtx->order != pCtx->param[0].i64Key) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1854,7 +1853,6 @@ static void last_row_function(SQLFunctionCtx *pCtx) {
|
|||
static void last_row_finalizer(SQLFunctionCtx *pCtx) {
|
||||
// do nothing at the first stage
|
||||
SResultInfo *pResInfo = GET_RES_INFO(pCtx);
|
||||
if (pCtx->currentStage == SECONDARY_STAGE_MERGE) {
|
||||
if (pResInfo->hasResult != DATA_SET_FLAG) {
|
||||
if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pCtx->aOutputBuf, pCtx->outputType);
|
||||
|
@ -1864,17 +1862,6 @@ static void last_row_finalizer(SQLFunctionCtx *pCtx) {
|
|||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (pResInfo->hasResult != DATA_SET_FLAG) {
|
||||
if (pCtx->outputType == TSDB_DATA_TYPE_BINARY || pCtx->outputType == TSDB_DATA_TYPE_NCHAR) {
|
||||
setVardataNull(pCtx->aOutputBuf, pCtx->outputType);
|
||||
} else {
|
||||
setNull(pCtx->aOutputBuf, pCtx->outputType, pCtx->outputBytes);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GET_RES_INFO(pCtx)->numOfRes = 1;
|
||||
doFinalizer(pCtx);
|
||||
|
@ -2990,12 +2977,12 @@ static void tag_project_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
|||
*/
|
||||
static void tag_function(SQLFunctionCtx *pCtx) {
|
||||
SET_VAL(pCtx, 1, 1);
|
||||
tVariantDump(&pCtx->tag, pCtx->aOutputBuf, pCtx->tag.nType, true);
|
||||
tVariantDump(&pCtx->tag, pCtx->aOutputBuf, pCtx->outputType, true);
|
||||
}
|
||||
|
||||
static void tag_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
||||
SET_VAL(pCtx, 1, 1);
|
||||
tVariantDump(&pCtx->tag, pCtx->aOutputBuf, pCtx->tag.nType, true);
|
||||
tVariantDump(&pCtx->tag, pCtx->aOutputBuf, pCtx->outputType, true);
|
||||
}
|
||||
|
||||
static void copy_function(SQLFunctionCtx *pCtx) {
|
||||
|
@ -3904,7 +3891,7 @@ static bool ts_comp_function_setup(SQLFunctionCtx *pCtx) {
|
|||
SResultInfo *pResInfo = GET_RES_INFO(pCtx);
|
||||
STSCompInfo *pInfo = pResInfo->interResultBuf;
|
||||
|
||||
pInfo->pTSBuf = tsBufCreate(false);
|
||||
pInfo->pTSBuf = tsBufCreate(false, pCtx->order);
|
||||
pInfo->pTSBuf->tsOrder = pCtx->order;
|
||||
return true;
|
||||
}
|
||||
|
@ -3926,7 +3913,6 @@ static void ts_comp_function(SQLFunctionCtx *pCtx) {
|
|||
}
|
||||
|
||||
SET_VAL(pCtx, pCtx->size, 1);
|
||||
|
||||
pResInfo->hasResult = DATA_SET_FLAG;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "taosdef.h"
|
||||
#include "tscLog.h"
|
||||
#include "qextbuffer.h"
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tname.h"
|
||||
|
||||
|
@ -132,14 +131,14 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
|
|||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0);
|
||||
char* dst = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 0) * totalNumOfRows + pField->bytes * i;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(dst, pSchema[i].name, TSDB_COL_NAME_LEN - 1);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(dst, pSchema[i].name, pField->bytes);
|
||||
|
||||
char *type = tDataTypeDesc[pSchema[i].type].aName;
|
||||
|
||||
pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 1);
|
||||
dst = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 1) * totalNumOfRows + pField->bytes * i;
|
||||
|
||||
STR_TO_VARSTR(dst, type);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(dst, type, pField->bytes);
|
||||
|
||||
int32_t bytes = pSchema[i].bytes;
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_BINARY || pSchema[i].type == TSDB_DATA_TYPE_NCHAR) {
|
||||
|
@ -157,7 +156,7 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
|
|||
if (i >= tscGetNumOfColumns(pMeta) && tscGetNumOfTags(pMeta) != 0) {
|
||||
char* output = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 3) * totalNumOfRows + pField->bytes * i;
|
||||
const char *src = "TAG";
|
||||
STR_WITH_SIZE_TO_VARSTR(output, src, strlen(src));
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(output, src, pField->bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +170,7 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
|
|||
// field name
|
||||
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0);
|
||||
char* output = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 0) * totalNumOfRows + pField->bytes * i;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(output, pSchema[i].name, TSDB_COL_NAME_LEN - 1);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(output, pSchema[i].name, pField->bytes);
|
||||
|
||||
// type name
|
||||
pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 1);
|
||||
|
@ -183,9 +182,13 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
|
|||
// type length
|
||||
int32_t bytes = pSchema[i].bytes;
|
||||
pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 2);
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_BINARY || pSchema[i].type == TSDB_DATA_TYPE_NCHAR) {
|
||||
bytes -= VARSTR_HEADER_SIZE;
|
||||
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR) {
|
||||
bytes = bytes / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
*(int32_t *)(pRes->data + tscFieldInfoGetOffset(pQueryInfo, 2) * totalNumOfRows + pField->bytes * i) = bytes;
|
||||
|
||||
|
@ -193,7 +196,7 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) {
|
|||
pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 3);
|
||||
char *target = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 3) * totalNumOfRows + pField->bytes * i;
|
||||
const char *src = "TAG";
|
||||
STR_WITH_SIZE_TO_VARSTR(target, src, strlen(src));
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(target, src, pField->bytes);
|
||||
|
||||
pTagValue += pSchema[i].bytes;
|
||||
}
|
||||
|
@ -220,15 +223,15 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
|
|||
|
||||
rowLen += ((TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE);
|
||||
|
||||
f.bytes = typeColLength;
|
||||
f.bytes = typeColLength + VARSTR_HEADER_SIZE;
|
||||
f.type = TSDB_DATA_TYPE_BINARY;
|
||||
tstrncpy(f.name, "Type", sizeof(f.name));
|
||||
|
||||
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, typeColLength,
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, typeColLength + VARSTR_HEADER_SIZE,
|
||||
typeColLength, false);
|
||||
|
||||
rowLen += typeColLength;
|
||||
rowLen += typeColLength + VARSTR_HEADER_SIZE;
|
||||
|
||||
f.bytes = sizeof(int32_t);
|
||||
f.type = TSDB_DATA_TYPE_INT;
|
||||
|
@ -240,15 +243,15 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
|
|||
|
||||
rowLen += sizeof(int32_t);
|
||||
|
||||
f.bytes = noteColLength;
|
||||
f.bytes = noteColLength + VARSTR_HEADER_SIZE;
|
||||
f.type = TSDB_DATA_TYPE_BINARY;
|
||||
tstrncpy(f.name, "Note", sizeof(f.name));
|
||||
|
||||
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, noteColLength,
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, noteColLength + VARSTR_HEADER_SIZE,
|
||||
noteColLength, false);
|
||||
|
||||
rowLen += noteColLength;
|
||||
rowLen += noteColLength + VARSTR_HEADER_SIZE;
|
||||
return rowLen;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "os.h"
|
||||
#include "tlosertree.h"
|
||||
#include "tscUtil.h"
|
||||
|
@ -21,6 +20,7 @@
|
|||
#include "tsclient.h"
|
||||
#include "tutil.h"
|
||||
#include "tscLog.h"
|
||||
#include "tscLocalMerge.h"
|
||||
|
||||
typedef struct SCompareParam {
|
||||
SLocalDataSource **pLocalData;
|
||||
|
@ -230,6 +230,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
|
|||
if (ds == NULL) {
|
||||
tscError("%p failed to create merge structure", pSql);
|
||||
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
tfree(pReducer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -266,6 +267,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
|
|||
|
||||
// no data actually, no need to merge result.
|
||||
if (idx == 0) {
|
||||
tfree(pReducer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -282,6 +284,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
|
|||
|
||||
pRes->code = tLoserTreeCreate(&pReducer->pLoserTree, pReducer->numOfBuffer, param, treeComparator);
|
||||
if (pReducer->pLoserTree == NULL || pRes->code != 0) {
|
||||
tfree(pReducer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -325,7 +328,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
|
|||
tfree(pReducer->pResultBuf);
|
||||
tfree(pReducer->pFinalRes);
|
||||
tfree(pReducer->prevRowOfInput);
|
||||
|
||||
tfree(pReducer);
|
||||
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
return;
|
||||
}
|
||||
|
@ -353,7 +356,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
|
|||
pRes->numOfGroups = 0;
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);;
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
TSKEY stime = MIN(pQueryInfo->window.skey, pQueryInfo->window.ekey);
|
||||
int64_t revisedSTime =
|
||||
|
@ -685,6 +688,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
|
|||
|
||||
if (createOrderDescriptor(pOrderDesc, pCmd, pModel) != TSDB_CODE_SUCCESS) {
|
||||
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
tfree(pSchema);
|
||||
return pRes->code;
|
||||
}
|
||||
|
||||
|
@ -1092,14 +1096,6 @@ static int64_t getNumOfResultLocal(SQueryInfo *pQueryInfo, SQLFunctionCtx *pCtx)
|
|||
|
||||
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
for (int32_t j = 0; j < size; ++j) {
|
||||
// SSqlExpr* pExpr = pQueryInfo->fieldsInfo.pSqlExpr[j];
|
||||
// if (pExpr == NULL) {
|
||||
// assert(pQueryInfo->fieldsInfo.pExpr[j] != NULL);
|
||||
//
|
||||
// maxOutput = 1;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
/*
|
||||
* ts, tag, tagprj function can not decide the output number of current query
|
||||
* the number of output result is decided by main output
|
||||
|
@ -1109,8 +1105,9 @@ static int64_t getNumOfResultLocal(SQueryInfo *pQueryInfo, SQLFunctionCtx *pCtx)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (maxOutput < GET_RES_INFO(&pCtx[j])->numOfRes) {
|
||||
maxOutput = GET_RES_INFO(&pCtx[j])->numOfRes;
|
||||
SResultInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
|
||||
if (maxOutput < pResInfo->numOfRes) {
|
||||
maxOutput = pResInfo->numOfRes;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1260,7 +1257,6 @@ bool doGenerateFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool no
|
|||
|
||||
#ifdef _DEBUG_VIEW
|
||||
printf("final result before interpo:\n");
|
||||
assert(0);
|
||||
// tColModelDisplay(pLocalReducer->resColModel, pLocalReducer->pBufForInterpo, pResBuf->num, pResBuf->num);
|
||||
#endif
|
||||
|
|
@ -97,7 +97,7 @@ int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int1
|
|||
useconds = str2int64(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) != TSDB_CODE_SUCCESS) {
|
||||
if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) {
|
||||
return tscInvalidSQLErrMsg(error, "invalid timestamp format", pToken->z);
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ int32_t tsParseOneColumnData(SSchema *pSchema, SSQLToken *pToken, char *payload,
|
|||
numType = tscToInteger(pToken, &iv, &endptr);
|
||||
if (TK_ILLEGAL == numType) {
|
||||
return tscInvalidSQLErrMsg(msg, "invalid bigint data", pToken->z);
|
||||
} else if (errno == ERANGE || iv > INT64_MAX || iv <= INT64_MIN) {
|
||||
} else if (errno == ERANGE || iv == INT64_MIN) {
|
||||
return tscInvalidSQLErrMsg(msg, "bigint data overflow", pToken->z);
|
||||
}
|
||||
|
||||
|
@ -594,7 +594,6 @@ int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int3
|
|||
size_t remain = pDataBlock->nAllocSize - pDataBlock->size;
|
||||
const int factor = 5;
|
||||
uint32_t nAllocSizeOld = pDataBlock->nAllocSize;
|
||||
assert(pDataBlock->headerSize >= 0);
|
||||
|
||||
// expand the allocated size
|
||||
if (remain < rowSize * factor) {
|
||||
|
@ -1328,12 +1327,14 @@ int tsParseSql(SSqlObj *pSql, bool initialParse) {
|
|||
int32_t ret = TSDB_CODE_SUCCESS;
|
||||
|
||||
if (initialParse) {
|
||||
assert(!pSql->cmd.parseFinished);
|
||||
|
||||
char* p = pSql->sqlstr;
|
||||
pSql->sqlstr = NULL;
|
||||
|
||||
tscPartiallyFreeSqlObj(pSql);
|
||||
pSql->sqlstr = p;
|
||||
} else {
|
||||
} else if (!pSql->cmd.parseFinished) {
|
||||
tscTrace("continue parse sql: %s", pSql->cmd.curSql);
|
||||
}
|
||||
|
||||
|
|
|
@ -98,8 +98,6 @@ static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo, int32_t killTy
|
|||
static bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField);
|
||||
static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo);
|
||||
|
||||
static void updateTagColumnIndex(SQueryInfo* pQueryInfo, int32_t tableIndex);
|
||||
|
||||
static int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t index, SQuerySQL* pQuerySql, SSqlObj* pSql);
|
||||
static int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDBInfo* pCreateDbSql);
|
||||
static int32_t getColumnIndexByName(const SSQLToken* pToken, SQueryInfo* pQueryInfo, SColumnIndex* pIndex);
|
||||
|
@ -138,7 +136,7 @@ static int setColumnFilterInfoForTimestamp(SQueryInfo* pQueryInfo, tVariant* pVa
|
|||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
if (seg != NULL) {
|
||||
if (taosParseTime(pVar->pz, &time, pVar->nLen, tinfo.precision) != TSDB_CODE_SUCCESS) {
|
||||
if (taosParseTime(pVar->pz, &time, pVar->nLen, tinfo.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg);
|
||||
}
|
||||
} else {
|
||||
|
@ -640,17 +638,11 @@ int32_t parseIntervalClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
|
|||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
SSchema s = {.bytes = TSDB_KEYSIZE, .type = TSDB_DATA_TYPE_TIMESTAMP, .colId = PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
tstrncpy(s.name, aAggs[TSDB_FUNC_TS].aName, sizeof(s.name));
|
||||
|
||||
SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS, &index, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
|
||||
TSDB_KEYSIZE, false);
|
||||
|
||||
SColumnList ids = getColumnList(1, 0, PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
|
||||
int32_t ret =
|
||||
insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS].aName, pExpr);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, 0, TSDB_FUNC_TS, &index, &s, TSDB_COL_NORMAL);
|
||||
|
||||
if (parseSlidingClause(pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
|
@ -1042,7 +1034,7 @@ int32_t setObjFullName(char* fullName, const char* account, SSQLToken* pDB, SSQL
|
|||
|
||||
/* db name is not specified, the tableName dose not include db name */
|
||||
if (pDB != NULL) {
|
||||
if (pDB->n >= TSDB_DB_NAME_LEN) {
|
||||
if (pDB->n >= TSDB_ACCT_LEN + TSDB_DB_NAME_LEN) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -1241,11 +1233,11 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
|
|||
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
|
||||
}
|
||||
|
||||
if (isSTable) {
|
||||
/*
|
||||
* transfer sql functions that need secondary merge into another format
|
||||
* in dealing with metric queries such as: count/first/last
|
||||
*/
|
||||
if (isSTable) {
|
||||
tscTansformSQLFuncForSTableQuery(pQueryInfo);
|
||||
|
||||
if (hasUnsupportFunctionsForSTableQuery(pQueryInfo)) {
|
||||
|
@ -1324,8 +1316,9 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn
|
|||
|
||||
void tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId,
|
||||
SColumnIndex* pIndex, SSchema* pColSchema, int16_t flag) {
|
||||
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionId, pIndex, pColSchema->type,
|
||||
SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, outputColIndex, functionId, pIndex, pColSchema->type,
|
||||
pColSchema->bytes, pColSchema->bytes, flag);
|
||||
tstrncpy(pExpr->aliasName, pColSchema->name, sizeof(pExpr->aliasName));
|
||||
|
||||
SColumnList ids = getColumnList(1, pIndex->tableIndex, pIndex->columnIndex);
|
||||
if (TSDB_COL_IS_TAG(flag)) {
|
||||
|
@ -1403,7 +1396,7 @@ int32_t addProjectionExprAndResultField(SQueryInfo* pQueryInfo, tSQLExprItem* pI
|
|||
|
||||
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
SSchema colSchema = tGetTableNameColumnSchema();
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, startPos, TSDB_FUNC_TAGPRJ, &index, &colSchema, true);
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, startPos, TSDB_FUNC_TAGPRJ, &index, &colSchema, TSDB_COL_TAG);
|
||||
} else {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
@ -1445,7 +1438,7 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema,
|
|||
}
|
||||
|
||||
if (aliasName != NULL) {
|
||||
strcpy(columnName, aliasName);
|
||||
tstrncpy(columnName, aliasName, sizeof(columnName));
|
||||
} else {
|
||||
getRevisedName(columnName, functionID, sizeof(columnName) - 1, pSchema[pColIndex->columnIndex].name);
|
||||
}
|
||||
|
@ -1453,6 +1446,13 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema,
|
|||
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, bytes, false);
|
||||
tstrncpy(pExpr->aliasName, columnName, sizeof(pExpr->aliasName));
|
||||
|
||||
// set reverse order scan data blocks for last query
|
||||
if (functionID == TSDB_FUNC_LAST) {
|
||||
pExpr->numOfParams = 1;
|
||||
pExpr->param[0].i64Key = TSDB_ORDER_DESC;
|
||||
pExpr->param[0].nType = TSDB_DATA_TYPE_INT;
|
||||
}
|
||||
|
||||
// for all queries, the timestamp column needs to be loaded
|
||||
SColumnIndex index = {.tableIndex = pColIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
tscColumnListInsert(pQueryInfo->colList, &index);
|
||||
|
@ -1724,6 +1724,22 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExpr
|
|||
if (setExprInfoForFunctions(pQueryInfo, pSchema, functionID, pItem->aliasName, colIndex + i, &index) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
if (optr == TK_LAST) { // todo refactor
|
||||
SSqlGroupbyExpr* pGroupBy = &pQueryInfo->groupbyExpr;
|
||||
if (pGroupBy->numOfGroupCols > 0) {
|
||||
for(int32_t k = 0; k < pGroupBy->numOfGroupCols; ++k) {
|
||||
SColIndex* pIndex = taosArrayGet(pGroupBy->columnInfo, k);
|
||||
if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { // group by normal columns
|
||||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, colIndex + i);
|
||||
pExpr->numOfParams = 1;
|
||||
pExpr->param->i64Key = TSDB_ORDER_ASC;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1823,7 +1839,7 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExpr
|
|||
} else {
|
||||
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT, true);
|
||||
|
||||
int64_t nTop = *((int32_t*)val);
|
||||
int64_t nTop = GET_INT32_VAL(val);
|
||||
if (nTop <= 0 || nTop > 100) { // todo use macro
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg5);
|
||||
}
|
||||
|
@ -1833,12 +1849,14 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExpr
|
|||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
// todo REFACTOR
|
||||
// set the first column ts for top/bottom query
|
||||
SColumnIndex index1 = {0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
|
||||
TSDB_KEYSIZE, false);
|
||||
tstrncpy(pExpr->aliasName, aAggs[TSDB_FUNC_TS].aName, sizeof(pExpr->aliasName));
|
||||
|
||||
const int32_t TS_COLUMN_INDEX = 0;
|
||||
const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
SColumnList ids = getColumnList(1, 0, TS_COLUMN_INDEX);
|
||||
insertResultField(pQueryInfo, TS_COLUMN_INDEX, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP,
|
||||
aAggs[TSDB_FUNC_TS].aName, pExpr);
|
||||
|
@ -1990,6 +2008,7 @@ static int16_t doGetColumnIndex(SQueryInfo* pQueryInfo, int32_t index, SSQLToken
|
|||
|
||||
if (strncasecmp(pSchema[i].name, pToken->z, pToken->n) == 0) {
|
||||
columnIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2197,7 +2216,6 @@ int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
// db prefix in tagCond, show table conds in payload
|
||||
SSQLToken* pDbPrefixToken = &pShowInfo->prefix;
|
||||
if (pDbPrefixToken->type != 0) {
|
||||
assert(pDbPrefixToken->n >= 0);
|
||||
|
||||
if (pDbPrefixToken->n >= TSDB_DB_NAME_LEN) { // db name is too long
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
|
@ -2446,62 +2464,10 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void updateTagColumnIndex(SQueryInfo* pQueryInfo, int32_t tableIndex) {
|
||||
// STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex);
|
||||
//
|
||||
// // update tags column index for expression
|
||||
// size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
// for (int32_t i = 0; i < size; ++i) {
|
||||
// SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
//
|
||||
// if (!TSDB_COL_IS_TAG(pExpr->colInfo.flag)) { // not tags, continue
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// // not belongs to this table
|
||||
// if (pExpr->uid != pTableMetaInfo->pTableMeta->uid) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// for (int32_t j = 0; j < pTableMetaInfo->numOfTags; ++j) {
|
||||
// if (pExpr->colInfo.colIndex == pTableMetaInfo->tagColumnIndex[j]) {
|
||||
// pExpr->colInfo.colIndex = j;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// update join condition tag column index
|
||||
// SJoinInfo* pJoinInfo = &pQueryInfo->tagCond.joinInfo;
|
||||
// if (!pJoinInfo->hasJoin) { // not join query
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// assert(pJoinInfo->left.uid != pJoinInfo->right.uid);
|
||||
//
|
||||
// // the join condition expression node belongs to this table(super table)
|
||||
// assert(0);
|
||||
// if (pTableMetaInfo->pTableMeta->uid == pJoinInfo->left.uid) {
|
||||
// for (int32_t i = 0; i < pTableMetaInfo->numOfTags; ++i) {
|
||||
// if (pJoinInfo->left.tagCol == pTableMetaInfo->tagColumnIndex[i]) {
|
||||
// pJoinInfo->left.tagCol = i;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (pTableMetaInfo->pTableMeta->uid == pJoinInfo->right.uid) {
|
||||
// for (int32_t i = 0; i < pTableMetaInfo->numOfTags; ++i) {
|
||||
// if (pJoinInfo->right.tagCol == pTableMetaInfo->tagColumnIndex[i]) {
|
||||
// pJoinInfo->right.tagCol = i;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd* pCmd) {
|
||||
const char* msg1 = "too many columns in group by clause";
|
||||
const char* msg2 = "invalid column name in group by clause";
|
||||
const char* msg3 = "group by columns must belong to one table";
|
||||
// const char* msg3 = "group by columns must belong to one table";
|
||||
const char* msg7 = "not support group by expression";
|
||||
const char* msg8 = "not allowed column type for group by";
|
||||
const char* msg9 = "tags not allowed for table query";
|
||||
|
@ -2537,10 +2503,6 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
|
|||
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
|
||||
}
|
||||
|
||||
if (tableIndex != index.tableIndex && tableIndex >= 0) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg3);
|
||||
}
|
||||
|
||||
tableIndex = index.tableIndex;
|
||||
|
||||
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
|
@ -2586,9 +2548,7 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
|
|||
|
||||
tscColumnListInsert(pQueryInfo->colList, &index);
|
||||
|
||||
SColIndex colIndex = {
|
||||
.colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId,
|
||||
};
|
||||
SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId };
|
||||
taosArrayPush(pGroupExpr->columnInfo, &colIndex);
|
||||
pQueryInfo->groupbyExpr.orderType = TSDB_ORDER_ASC;
|
||||
|
||||
|
@ -2599,7 +2559,6 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd*
|
|||
}
|
||||
|
||||
pQueryInfo->groupbyExpr.tableIndex = tableIndex;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2887,6 +2846,7 @@ static int32_t extractColumnFilterInfo(SQueryInfo* pQueryInfo, SColumnIndex* pIn
|
|||
|
||||
const char* msg1 = "non binary column not support like operator";
|
||||
const char* msg2 = "binary column not support this operator";
|
||||
const char* msg3 = "bool column not support this operator";
|
||||
|
||||
SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex);
|
||||
SColumnFilterInfo* pColFilter = NULL;
|
||||
|
@ -2920,6 +2880,12 @@ static int32_t extractColumnFilterInfo(SQueryInfo* pQueryInfo, SColumnIndex* pIn
|
|||
if (pExpr->nSQLOptr == TK_LIKE) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
|
||||
}
|
||||
|
||||
if (pSchema->type == TSDB_DATA_TYPE_BOOL) {
|
||||
if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pColumn->colIndex = *pIndex;
|
||||
|
@ -3022,14 +2988,17 @@ static int32_t getColumnQueryCondInfo(SQueryInfo* pQueryInfo, tSQLExpr* pExpr, i
|
|||
}
|
||||
|
||||
static int32_t getJoinCondInfo(SQueryInfo* pQueryInfo, tSQLExpr* pExpr) {
|
||||
const char* msg = "invalid join query condition";
|
||||
const char* msg1 = "invalid join query condition";
|
||||
const char* msg2 = "join on binary/nchar not supported";
|
||||
const char* msg3 = "type of join columns must be identical";
|
||||
const char* msg4 = "invalid column name in join condition";
|
||||
|
||||
if (pExpr == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!isExprDirectParentOfLeaftNode(pExpr)) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg);
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
|
||||
}
|
||||
|
||||
STagCond* pTagCond = &pQueryInfo->tagCond;
|
||||
|
@ -3038,28 +3007,36 @@ static int32_t getJoinCondInfo(SQueryInfo* pQueryInfo, tSQLExpr* pExpr) {
|
|||
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
if (getColumnIndexByName(&pExpr->pLeft->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg4);
|
||||
}
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
int16_t tagColIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
SSchema* pTagSchema1 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
|
||||
|
||||
pLeft->uid = pTableMetaInfo->pTableMeta->uid;
|
||||
pLeft->tagCol = tagColIndex;
|
||||
pLeft->tagColId = pTagSchema1->colId;
|
||||
strcpy(pLeft->tableId, pTableMetaInfo->name);
|
||||
|
||||
index = (SColumnIndex)COLUMN_INDEX_INITIALIZER;
|
||||
if (getColumnIndexByName(&pExpr->pRight->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg4);
|
||||
}
|
||||
|
||||
pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
tagColIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||
SSchema* pTagSchema2 = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex);
|
||||
|
||||
pRight->uid = pTableMetaInfo->pTableMeta->uid;
|
||||
pRight->tagCol = tagColIndex;
|
||||
pRight->tagColId = pTagSchema2->colId;
|
||||
strcpy(pRight->tableId, pTableMetaInfo->name);
|
||||
|
||||
if (pTagSchema1->type != pTagSchema2->type) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg3);
|
||||
}
|
||||
|
||||
if (pTagSchema1->type == TSDB_DATA_TYPE_BINARY || pTagSchema1->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
|
||||
}
|
||||
|
||||
pTagCond->joinInfo.hasJoin = true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -3787,6 +3764,10 @@ static int32_t getTagQueryCondExpr(SQueryInfo* pQueryInfo, SCondExpr* pCondExpr,
|
|||
|
||||
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
|
||||
tSQLExpr* p1 = extractExprForSTable(pExpr, pQueryInfo, i);
|
||||
if (p1 == NULL) { // no query condition on this table
|
||||
continue;
|
||||
}
|
||||
|
||||
tExprNode* p = NULL;
|
||||
|
||||
SArray* colList = taosArrayInit(10, sizeof(SColIndex));
|
||||
|
@ -3921,7 +3902,7 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t
|
|||
|
||||
char* seg = strnchr(pRight->val.pz, '-', pRight->val.nLen, false);
|
||||
if (seg != NULL) {
|
||||
if (taosParseTime(pRight->val.pz, &val, pRight->val.nLen, TSDB_TIME_PRECISION_MICRO) == TSDB_CODE_SUCCESS) {
|
||||
if (taosParseTime(pRight->val.pz, &val, pRight->val.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) {
|
||||
parsed = true;
|
||||
} else {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
|
@ -4479,7 +4460,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
if (pTagsSchema->type != TSDB_DATA_TYPE_BINARY && pTagsSchema->type != TSDB_DATA_TYPE_NCHAR) {
|
||||
len = tDataTypeDesc[pTagsSchema->type].nSize;
|
||||
} else {
|
||||
len = varDataLen(pUpdateMsg->data);
|
||||
len = varDataTLen(pUpdateMsg->data);
|
||||
}
|
||||
|
||||
pUpdateMsg->tagValLen = htonl(len); // length may be changed after dump data
|
||||
|
@ -4736,7 +4717,7 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL*
|
|||
pQueryInfo->clauseLimit = pQueryInfo->limit.limit;
|
||||
pQueryInfo->slimit = pQuerySql->slimit;
|
||||
|
||||
tscTrace("%p limit:%d, offset:%" PRId64 " slimit:%d, soffset:%" PRId64, pSql, pQueryInfo->limit.limit,
|
||||
tscTrace("%p limit:%" PRId64 ", offset:%" PRId64 " slimit:%" PRId64 ", soffset:%" PRId64, pSql, pQueryInfo->limit.limit,
|
||||
pQueryInfo->limit.offset, pQueryInfo->slimit.limit, pQueryInfo->slimit.offset);
|
||||
|
||||
if (pQueryInfo->slimit.offset < 0 || pQueryInfo->limit.offset < 0) {
|
||||
|
@ -4920,25 +4901,25 @@ int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDBInfo* pCreateDbSql) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void tscAddTimestampColumn(SQueryInfo* pQueryInfo, int16_t functionId, int16_t tableIndex) {
|
||||
// the first column not timestamp column, add it
|
||||
SSqlExpr* pExpr = NULL;
|
||||
if (tscSqlExprNumOfExprs(pQueryInfo) > 0) {
|
||||
pExpr = tscSqlExprGet(pQueryInfo, 0);
|
||||
}
|
||||
|
||||
if (pExpr == NULL || pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX || pExpr->functionId != functionId) {
|
||||
SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
|
||||
pExpr = tscSqlExprInsert(pQueryInfo, 0, functionId, &index, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE, false);
|
||||
pExpr->colInfo.flag = TSDB_COL_NORMAL;
|
||||
|
||||
// NOTE: tag column does not add to source column list
|
||||
SColumnList ids = getColumnList(1, tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
|
||||
insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, "ts", pExpr);
|
||||
}
|
||||
}
|
||||
//void tscAddTimestampColumn(SQueryInfo* pQueryInfo, int16_t functionId, int16_t tableIndex) {
|
||||
// // the first column not timestamp column, add it
|
||||
// SSqlExpr* pExpr = NULL;
|
||||
// if (tscSqlExprNumOfExprs(pQueryInfo) > 0) {
|
||||
// pExpr = tscSqlExprGet(pQueryInfo, 0);
|
||||
// }
|
||||
//
|
||||
// if (pExpr == NULL || pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX || pExpr->functionId != functionId) {
|
||||
// SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
//
|
||||
// pExpr = tscSqlExprInsert(pQueryInfo, 0, functionId, &index, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE, false);
|
||||
// pExpr->colInfo.flag = TSDB_COL_NORMAL;
|
||||
//
|
||||
// // NOTE: tag column does not add to source column list
|
||||
// SColumnList ids = getColumnList(1, tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
//
|
||||
// insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, "ts", pExpr);
|
||||
// }
|
||||
//}
|
||||
|
||||
void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClauseIndex, int32_t tableIndex) {
|
||||
SQueryInfo* pParentQueryInfo = tscGetQueryInfoDetail(&pParentObj->cmd, subClauseIndex);
|
||||
|
@ -4951,7 +4932,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau
|
|||
|
||||
if (pExpr->functionId != TSDB_FUNC_TAG) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex);
|
||||
int16_t columnInfo = tscGetJoinTagColIndexByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
int16_t columnInfo = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
SColumnIndex index = {.tableIndex = 0, .columnIndex = columnInfo};
|
||||
SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
|
||||
|
||||
|
@ -4987,27 +4968,17 @@ static void doLimitOutputNormalColOfGroupby(SSqlExpr* pExpr) {
|
|||
|
||||
void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) {
|
||||
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, tagIndex);
|
||||
int32_t index = pColIndex->colIndex;
|
||||
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, index);
|
||||
SColumnIndex colIndex = {.tableIndex = 0, .columnIndex = index};
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, pColIndex->colIndex);
|
||||
SColumnIndex colIndex = {.tableIndex = 0, .columnIndex = pColIndex->colIndex};
|
||||
|
||||
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_PRJ, &colIndex, pSchema->type, pSchema->bytes,
|
||||
pSchema->bytes, false);
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL);
|
||||
|
||||
pExpr->colInfo.flag = TSDB_COL_NORMAL;
|
||||
doLimitOutputNormalColOfGroupby(pExpr);
|
||||
|
||||
// NOTE: tag column does not add to source column list
|
||||
SColumnList list = {0};
|
||||
list.num = 1;
|
||||
list.ids[0] = colIndex;
|
||||
|
||||
insertResultField(pQueryInfo, size, &list, pSchema->bytes, pSchema->type, pSchema->name, pExpr);
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, size - 1);
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, size);
|
||||
doLimitOutputNormalColOfGroupby(pInfo->pSqlExpr);
|
||||
pInfo->visible = false;
|
||||
}
|
||||
|
||||
|
@ -5219,6 +5190,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SQueryInfo* pQueryInfo) {
|
|||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
SSchema s = tGetTableNameColumnSchema();
|
||||
SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
|
||||
int16_t bytes = 0;
|
||||
int16_t type = 0;
|
||||
|
@ -5226,10 +5198,8 @@ static int32_t doAddGroupbyColumnsOnDemand(SQueryInfo* pQueryInfo) {
|
|||
|
||||
for (int32_t i = 0; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
|
||||
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, i);
|
||||
|
||||
int16_t colIndex = pColIndex->colIndex;
|
||||
if (colIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
SSchema s = tGetTableNameColumnSchema();
|
||||
type = s.type;
|
||||
bytes = s.bytes;
|
||||
name = s.name;
|
||||
|
@ -5926,10 +5896,6 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
|
||||
setColumnOffsetValueInResultset(pQueryInfo);
|
||||
|
||||
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
|
||||
updateTagColumnIndex(pQueryInfo, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* fill options are set at the end position, when all columns are set properly
|
||||
* the columns may be increased due to group by operation
|
||||
|
@ -6052,6 +6018,19 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray*
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) {
|
||||
if (pRight->nodeType == TSQL_NODE_VALUE) {
|
||||
if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
if ((pRight->pVal->nType == TSDB_DATA_TYPE_BINARY || pRight->pVal->nType == TSDB_DATA_TYPE_NCHAR)
|
||||
&& (*pExpr)->_node.optr != TSDB_RELATION_LIKE) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
|
|
@ -64,14 +64,6 @@ SSchema* tscGetTableTagSchema(const STableMeta* pTableMeta) {
|
|||
|
||||
STableComInfo tscGetTableInfo(const STableMeta* pTableMeta) {
|
||||
assert(pTableMeta != NULL);
|
||||
|
||||
#if 0
|
||||
if (pTableMeta->tableType == TSDB_CHILD_TABLE) {
|
||||
assert (pTableMeta->pSTable != NULL);
|
||||
return pTableMeta->pSTable->tableInfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pTableMeta->tableInfo;
|
||||
}
|
||||
|
||||
|
@ -119,11 +111,24 @@ bool isValidSchema(struct SSchema* pSchema, int32_t numOfCols) {
|
|||
return (rowLen <= TSDB_MAX_BYTES_PER_ROW);
|
||||
}
|
||||
|
||||
SSchema* tscGetTableColumnSchema(const STableMeta* pTableMeta, int32_t startCol) {
|
||||
SSchema* tscGetTableColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
|
||||
assert(pTableMeta != NULL);
|
||||
|
||||
SSchema* pSchema = (SSchema*) pTableMeta->schema;
|
||||
return &pSchema[startCol];
|
||||
return &pSchema[colIndex];
|
||||
}
|
||||
|
||||
// TODO for large number of columns, employ the binary search method
|
||||
SSchema* tscGetTableColumnSchemaById(STableMeta* pTableMeta, int16_t colId) {
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMeta);
|
||||
|
||||
for(int32_t i = 0; i < tinfo.numOfColumns + tinfo.numOfTags; ++i) {
|
||||
if (pTableMeta->schema[i].colId == colId) {
|
||||
return &pTableMeta->schema[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct SSchema tscGetTbnameColumnSchema() {
|
||||
|
|
|
@ -14,20 +14,18 @@
|
|||
*/
|
||||
|
||||
#include "os.h"
|
||||
#include "qsqltype.h"
|
||||
#include "tcache.h"
|
||||
#include "trpc.h"
|
||||
#include "tscLocalMerge.h"
|
||||
#include "tscLog.h"
|
||||
#include "tscProfile.h"
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "tscSubquery.h"
|
||||
#include "tscUtil.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tsclient.h"
|
||||
#include "tsocket.h"
|
||||
#include "ttime.h"
|
||||
#include "ttimer.h"
|
||||
#include "tutil.h"
|
||||
#include "tscLog.h"
|
||||
#include "qsqltype.h"
|
||||
|
||||
#define TSC_MGMT_VNODE 999
|
||||
|
||||
|
@ -430,7 +428,7 @@ void tscKillSTableQuery(SSqlObj *pSql) {
|
|||
/*
|
||||
* 1. if the subqueries are not launched or partially launched, we need to waiting the launched
|
||||
* query return to successfully free allocated resources.
|
||||
* 2. if no any subqueries are launched yet, which means the metric query only in parse sql stage,
|
||||
* 2. if no any subqueries are launched yet, which means the super table query only in parse sql stage,
|
||||
* set the res.code, and return.
|
||||
*/
|
||||
const int64_t MAX_WAITING_TIME = 10000; // 10 Sec.
|
||||
|
@ -644,7 +642,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pQueryMsg->numOfGroupCols = htons(pQueryInfo->groupbyExpr.numOfGroupCols);
|
||||
pQueryMsg->numOfTags = htonl(numOfTags);
|
||||
pQueryMsg->tagNameRelType = htons(pQueryInfo->tagCond.relType);
|
||||
pQueryMsg->queryType = htons(pQueryInfo->type);
|
||||
pQueryMsg->queryType = htonl(pQueryInfo->type);
|
||||
|
||||
size_t numOfOutput = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
pQueryMsg->numOfOutput = htons(numOfOutput);
|
||||
|
@ -723,6 +721,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pMsg += sizeof(SSqlFuncMsg);
|
||||
|
||||
for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
|
||||
// todo add log
|
||||
pSqlFuncExpr->arg[j].argType = htons((uint16_t)pExpr->param[j].nType);
|
||||
pSqlFuncExpr->arg[j].argBytes = htons(pExpr->param[j].nLen);
|
||||
|
||||
|
@ -800,6 +799,27 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
// serialize tag column query condition
|
||||
if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0) {
|
||||
STagCond* pTagCond = &pQueryInfo->tagCond;
|
||||
|
||||
SCond *pCond = tsGetSTableQueryCond(pTagCond, pTableMeta->uid);
|
||||
if (pCond != NULL && pCond->cond != NULL) {
|
||||
pQueryMsg->tagCondLen = htons(pCond->len);
|
||||
memcpy(pMsg, pCond->cond, pCond->len);
|
||||
|
||||
pMsg += pCond->len;
|
||||
}
|
||||
}
|
||||
|
||||
if (pQueryInfo->tagCond.tbnameCond.cond == NULL) {
|
||||
*pMsg = 0;
|
||||
pMsg++;
|
||||
} else {
|
||||
strcpy(pMsg, pQueryInfo->tagCond.tbnameCond.cond);
|
||||
pMsg += strlen(pQueryInfo->tagCond.tbnameCond.cond) + 1;
|
||||
}
|
||||
|
||||
// compressed ts block
|
||||
pQueryMsg->tsOffset = htonl(pMsg - pStart);
|
||||
int32_t tsLen = 0;
|
||||
|
@ -824,27 +844,6 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pQueryMsg->tsOrder = htonl(pQueryInfo->tsBuf->tsOrder);
|
||||
}
|
||||
|
||||
// serialize tag column query condition
|
||||
if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0) {
|
||||
STagCond* pTagCond = &pQueryInfo->tagCond;
|
||||
|
||||
SCond *pCond = tsGetSTableQueryCond(pTagCond, pTableMeta->uid);
|
||||
if (pCond != NULL && pCond->cond != NULL) {
|
||||
pQueryMsg->tagCondLen = htons(pCond->len);
|
||||
memcpy(pMsg, pCond->cond, pCond->len);
|
||||
|
||||
pMsg += pCond->len;
|
||||
}
|
||||
}
|
||||
|
||||
if (pQueryInfo->tagCond.tbnameCond.cond == NULL) {
|
||||
*pMsg = 0;
|
||||
pMsg++;
|
||||
} else {
|
||||
strcpy(pMsg, pQueryInfo->tagCond.tbnameCond.cond);
|
||||
pMsg += strlen(pQueryInfo->tagCond.tbnameCond.cond) + 1;
|
||||
}
|
||||
|
||||
int32_t msgLen = pMsg - pStart;
|
||||
|
||||
tscTrace("%p msg built success,len:%d bytes", pSql, msgLen);
|
||||
|
@ -1175,7 +1174,7 @@ int tscBuildCreateTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
strcpy(pCreateTableMsg->tableId, pTableMetaInfo->name);
|
||||
|
||||
// use dbinfo from table id without modifying current db info
|
||||
tscGetDBInfoFromMeterId(pTableMetaInfo->name, pCreateTableMsg->db);
|
||||
tscGetDBInfoFromTableFullName(pTableMetaInfo->name, pCreateTableMsg->db);
|
||||
|
||||
SCreateTableSQL *pCreateTable = pInfo->pCreateTableInfo;
|
||||
|
||||
|
@ -1252,7 +1251,7 @@ int tscBuildAlterTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
}
|
||||
|
||||
SCMAlterTableMsg *pAlterTableMsg = (SCMAlterTableMsg *)pCmd->payload;
|
||||
tscGetDBInfoFromMeterId(pTableMetaInfo->name, pAlterTableMsg->db);
|
||||
tscGetDBInfoFromTableFullName(pTableMetaInfo->name, pAlterTableMsg->db);
|
||||
|
||||
strcpy(pAlterTableMsg->tableId, pTableMetaInfo->name);
|
||||
pAlterTableMsg->type = htons(pAlterInfo->type);
|
||||
|
@ -1473,7 +1472,7 @@ int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pMsg += len;
|
||||
}
|
||||
|
||||
pCmd->payloadLen = pMsg - (char*)pInfoMsg;;
|
||||
pCmd->payloadLen = pMsg - (char*)pInfoMsg;
|
||||
pCmd->msgType = TSDB_MSG_TYPE_CM_TABLE_META;
|
||||
|
||||
tfree(tmpData);
|
||||
|
@ -1577,7 +1576,7 @@ int tscBuildSTableVgroupMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pMsg = pStart;
|
||||
|
||||
SMgmtHead *pMgmt = (SMgmtHead *)pMsg;
|
||||
tscGetDBInfoFromMeterId(pTableMetaInfo->name, pMgmt->db);
|
||||
tscGetDBInfoFromTableFullName(pTableMetaInfo->name, pMgmt->db);
|
||||
|
||||
pMsg += sizeof(SMgmtHead);
|
||||
|
||||
|
@ -1932,113 +1931,6 @@ int tscProcessMultiMeterMetaRsp(SSqlObj *pSql) {
|
|||
}
|
||||
|
||||
int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
|
||||
#if 0
|
||||
void ** metricMetaList = NULL;
|
||||
int32_t * sizes = NULL;
|
||||
|
||||
int32_t num = htons(*(int16_t *)rsp);
|
||||
rsp += sizeof(int16_t);
|
||||
|
||||
metricMetaList = calloc(1, POINTER_BYTES * num);
|
||||
sizes = calloc(1, sizeof(int32_t) * num);
|
||||
|
||||
// return with error code
|
||||
if (metricMetaList == NULL || sizes == NULL) {
|
||||
tfree(metricMetaList);
|
||||
tfree(sizes);
|
||||
pSql->res.code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
||||
return pSql->res.code;
|
||||
}
|
||||
|
||||
for (int32_t k = 0; k < num; ++k) {
|
||||
pMeta = (SSuperTableMeta *)rsp;
|
||||
|
||||
size_t size = (size_t)pSql->res.rspLen - 1;
|
||||
rsp = rsp + sizeof(SSuperTableMeta);
|
||||
|
||||
pMeta->numOfTables = htonl(pMeta->numOfTables);
|
||||
pMeta->numOfVnodes = htonl(pMeta->numOfVnodes);
|
||||
pMeta->tagLen = htons(pMeta->tagLen);
|
||||
|
||||
size += pMeta->numOfVnodes * sizeof(SVnodeSidList *) + pMeta->numOfTables * sizeof(STableIdInfo *);
|
||||
|
||||
char *pBuf = calloc(1, size);
|
||||
if (pBuf == NULL) {
|
||||
pSql->res.code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto _error_clean;
|
||||
}
|
||||
|
||||
SSuperTableMeta *pNewMetricMeta = (SSuperTableMeta *)pBuf;
|
||||
metricMetaList[k] = pNewMetricMeta;
|
||||
|
||||
pNewMetricMeta->numOfTables = pMeta->numOfTables;
|
||||
pNewMetricMeta->numOfVnodes = pMeta->numOfVnodes;
|
||||
pNewMetricMeta->tagLen = pMeta->tagLen;
|
||||
|
||||
pBuf = pBuf + sizeof(SSuperTableMeta) + pNewMetricMeta->numOfVnodes * sizeof(SVnodeSidList *);
|
||||
|
||||
for (int32_t i = 0; i < pMeta->numOfVnodes; ++i) {
|
||||
SVnodeSidList *pSidLists = (SVnodeSidList *)rsp;
|
||||
memcpy(pBuf, pSidLists, sizeof(SVnodeSidList));
|
||||
|
||||
pNewMetricMeta->list[i] = pBuf - (char *)pNewMetricMeta; // offset value
|
||||
SVnodeSidList *pLists = (SVnodeSidList *)pBuf;
|
||||
|
||||
tscTrace("%p metricmeta:vid:%d,numOfTables:%d", pSql, i, pLists->numOfSids);
|
||||
|
||||
pBuf += sizeof(SVnodeSidList) + sizeof(STableIdInfo *) * pSidLists->numOfSids;
|
||||
rsp += sizeof(SVnodeSidList);
|
||||
|
||||
size_t elemSize = sizeof(STableIdInfo) + pNewMetricMeta->tagLen;
|
||||
for (int32_t j = 0; j < pSidLists->numOfSids; ++j) {
|
||||
pLists->pSidExtInfoList[j] = pBuf - (char *)pLists;
|
||||
memcpy(pBuf, rsp, elemSize);
|
||||
|
||||
((STableIdInfo *)pBuf)->uid = htobe64(((STableIdInfo *)pBuf)->uid);
|
||||
((STableIdInfo *)pBuf)->sid = htonl(((STableIdInfo *)pBuf)->sid);
|
||||
|
||||
rsp += elemSize;
|
||||
pBuf += elemSize;
|
||||
}
|
||||
}
|
||||
|
||||
sizes[k] = pBuf - (char *)pNewMetricMeta;
|
||||
}
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
char name[TSDB_MAX_TAGS_LEN + 1] = {0};
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i);
|
||||
tscGetMetricMetaCacheKey(pQueryInfo, name, pTableMetaInfo->pTableMeta->uid);
|
||||
|
||||
#ifdef _DEBUG_VIEW
|
||||
printf("generate the metric key:%s, index:%d\n", name, i);
|
||||
#endif
|
||||
|
||||
// release the used metricmeta
|
||||
taosCacheRelease(tscCacheHandle, (void **)&(pTableMetaInfo->pMetricMeta), false);
|
||||
pTableMetaInfo->pMetricMeta = (SSuperTableMeta *)taosCachePut(tscCacheHandle, name, (char *)metricMetaList[i],
|
||||
sizes[i], tsMetricMetaKeepTimer);
|
||||
tfree(metricMetaList[i]);
|
||||
|
||||
// failed to put into cache
|
||||
if (pTableMetaInfo->pMetricMeta == NULL) {
|
||||
pSql->res.code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto _error_clean;
|
||||
}
|
||||
}
|
||||
|
||||
_error_clean:
|
||||
// free allocated resource
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
tfree(metricMetaList[i]);
|
||||
}
|
||||
|
||||
free(sizes);
|
||||
free(metricMetaList);
|
||||
#endif
|
||||
SSqlRes* pRes = &pSql->res;
|
||||
|
||||
// NOTE: the order of several table must be preserved.
|
||||
|
@ -2201,7 +2093,7 @@ int tscProcessDropTableRsp(SSqlObj *pSql) {
|
|||
* The cached information is expired, however, we may have lost the ref of original meter. So, clear whole cache
|
||||
* instead.
|
||||
*/
|
||||
tscTrace("%p force release metermeta after drop table:%s", pSql, pTableMetaInfo->name);
|
||||
tscTrace("%p force release table meta after drop table:%s", pSql, pTableMetaInfo->name);
|
||||
taosCacheRelease(tscCacheHandle, (void **)&pTableMeta, true);
|
||||
|
||||
if (pTableMetaInfo->pTableMeta) {
|
||||
|
|
|
@ -20,14 +20,9 @@
|
|||
#include "tnote.h"
|
||||
#include "trpc.h"
|
||||
#include "tscLog.h"
|
||||
#include "tscProfile.h"
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "tscSubquery.h"
|
||||
#include "tscUtil.h"
|
||||
#include "tsclient.h"
|
||||
#include "tscompression.h"
|
||||
#include "tsocket.h"
|
||||
#include "ttimer.h"
|
||||
#include "ttokendef.h"
|
||||
#include "tutil.h"
|
||||
|
||||
|
|
|
@ -499,7 +499,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
|
|||
if (pSql->sqlstr == NULL) {
|
||||
tscError("%p failed to malloc sql string buffer", pSql);
|
||||
tscFreeSqlObj(pSql);
|
||||
return NULL;;
|
||||
return NULL;
|
||||
}
|
||||
strtolower(pSql->sqlstr, sqlstr);
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) {
|
|||
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
taosArraySort( tables, tscCompareTidTags );
|
||||
tscBuildVgroupTableInfo( pTableMetaInfo, tables );
|
||||
tscBuildVgroupTableInfo(pSql, pTableMetaInfo, tables);
|
||||
}
|
||||
taosArrayDestroy(tables);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ typedef struct SInsertSupporter {
|
|||
} SInsertSupporter;
|
||||
|
||||
static void freeJoinSubqueryObj(SSqlObj* pSql);
|
||||
static bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql);
|
||||
static bool tscHasRemainDataInSubqueryResultSet(SSqlObj *pSql);
|
||||
|
||||
static bool tsCompare(int32_t order, int64_t left, int64_t right) {
|
||||
if (order == TSDB_ORDER_ASC) {
|
||||
|
@ -38,16 +38,15 @@ static bool tsCompare(int32_t order, int64_t left, int64_t right) {
|
|||
}
|
||||
}
|
||||
|
||||
static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1,
|
||||
SJoinSupporter* pSupporter2, TSKEY* st, TSKEY* et) {
|
||||
STSBuf* output1 = tsBufCreate(true);
|
||||
STSBuf* output2 = tsBufCreate(true);
|
||||
|
||||
*st = INT64_MAX;
|
||||
*et = INT64_MIN;
|
||||
|
||||
static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJoinSupporter* pSupporter2, STimeWindow * win) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
|
||||
|
||||
STSBuf* output1 = tsBufCreate(true, pQueryInfo->order.order);
|
||||
STSBuf* output2 = tsBufCreate(true, pQueryInfo->order.order);
|
||||
|
||||
win->skey = INT64_MAX;
|
||||
win->ekey = INT64_MIN;
|
||||
|
||||
SLimitVal* pLimit = &pQueryInfo->limit;
|
||||
int32_t order = pQueryInfo->order.order;
|
||||
|
||||
|
@ -106,12 +105,12 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1,
|
|||
* final results which is acquired after the secondry merge of in the client.
|
||||
*/
|
||||
if (pLimit->offset == 0 || pQueryInfo->intervalTime > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
|
||||
if (*st > elem1.ts) {
|
||||
*st = elem1.ts;
|
||||
if (win->skey > elem1.ts) {
|
||||
win->skey = elem1.ts;
|
||||
}
|
||||
|
||||
if (*et < elem1.ts) {
|
||||
*et = elem1.ts;
|
||||
if (win->ekey < elem1.ts) {
|
||||
win->ekey = elem1.ts;
|
||||
}
|
||||
|
||||
tsBufAppend(output1, elem1.vnode, elem1.tag, (const char*)&elem1.ts, sizeof(elem1.ts));
|
||||
|
@ -151,8 +150,8 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1,
|
|||
tsBufDestory(pSupporter2->pTSBuf);
|
||||
|
||||
tscTrace("%p input1:%" PRId64 ", input2:%" PRId64 ", final:%" PRId64 " for secondary query after ts blocks "
|
||||
"intersecting, skey:%" PRId64 ", ekey:%" PRId64, pSql,
|
||||
numOfInput1, numOfInput2, output1->numOfTotal, *st, *et);
|
||||
"intersecting, skey:%" PRId64 ", ekey:%" PRId64, pSql, numOfInput1, numOfInput2, output1->numOfTotal,
|
||||
win->skey, win->ekey);
|
||||
|
||||
return output1->numOfTotal;
|
||||
}
|
||||
|
@ -252,7 +251,7 @@ int32_t tscLaunchSecondPhaseSubqueries(SSqlObj* pSql) {
|
|||
assert(numOfSub > 0);
|
||||
|
||||
// scan all subquery, if one sub query has only ts, ignore it
|
||||
tscTrace("%p start to launch secondary subqueries, total:%d, only:%d needs to query, others are not retrieve in "
|
||||
tscTrace("%p start to launch secondary subquery, total:%d, only:%d needs to query, others are not retrieve in "
|
||||
"select clause", pSql, pSql->numOfSubs, numOfSub);
|
||||
|
||||
//the subqueries that do not actually launch the secondary query to virtual node is set as completed.
|
||||
|
@ -329,21 +328,37 @@ int32_t tscLaunchSecondPhaseSubqueries(SSqlObj* pSql) {
|
|||
pSupporter->limit = pQueryInfo->limit;
|
||||
pNewQueryInfo->limit = pSupporter->limit;
|
||||
|
||||
// fetch the join tag column
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pNewQueryInfo, 0);
|
||||
assert(pQueryInfo->tagCond.joinInfo.hasJoin);
|
||||
SColumnIndex index = {.tableIndex = 0, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
SSchema* s = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, 0);
|
||||
|
||||
int16_t tagColIndex = tscGetJoinTagColIndexByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
pExpr->param[0].i64Key = tagColIndex;
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, 0);
|
||||
int16_t funcId = pExpr->functionId;
|
||||
|
||||
if ((pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) ||
|
||||
(funcId != TSDB_FUNC_TS && funcId != TSDB_FUNC_TS_DUMMY && funcId != TSDB_FUNC_PRJ)) {
|
||||
|
||||
int16_t functionId = tscIsProjectionQuery(pQueryInfo)? TSDB_FUNC_PRJ : TSDB_FUNC_TS;
|
||||
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, 0, functionId, &index, s, TSDB_COL_NORMAL);
|
||||
tscPrintSelectClause(pNew, 0);
|
||||
tscFieldInfoUpdateOffset(pNewQueryInfo);
|
||||
|
||||
pExpr = tscSqlExprGet(pQueryInfo, 0);
|
||||
}
|
||||
|
||||
// set the join condition tag column info, to do extract method
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
assert(pQueryInfo->tagCond.joinInfo.hasJoin);
|
||||
int16_t colId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
|
||||
pExpr->param[0].i64Key = colId;
|
||||
pExpr->numOfParams = 1;
|
||||
}
|
||||
|
||||
size_t numOfCols = taosArrayGetSize(pNewQueryInfo->colList);
|
||||
tscTrace("%p subquery:%p tableIndex:%d, vgroupIndex:%d, type:%d, exprInfo:%d, colList:%d, fieldsInfo:%d, name:%s",
|
||||
pSql, pNew, 0, pTableMetaInfo->vgroupIndex, pNewQueryInfo->type,
|
||||
taosArrayGetSize(pNewQueryInfo->exprList), numOfCols,
|
||||
pNewQueryInfo->fieldsInfo.numOfOutput, pNewQueryInfo->pTableMetaInfo[0]->name);
|
||||
pSql, pNew, 0, pTableMetaInfo->vgroupIndex, pNewQueryInfo->type, taosArrayGetSize(pNewQueryInfo->exprList),
|
||||
numOfCols, pNewQueryInfo->fieldsInfo.numOfOutput, pTableMetaInfo->name);
|
||||
}
|
||||
|
||||
//prepare the subqueries object failed, abort
|
||||
|
@ -357,12 +372,10 @@ int32_t tscLaunchSecondPhaseSubqueries(SSqlObj* pSql) {
|
|||
}
|
||||
|
||||
for(int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
SSqlObj* pSub = pSql->pSubs[i];
|
||||
if (pSub == NULL) {
|
||||
if (pSql->pSubs[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tscProcessSql(pSub);
|
||||
tscDoQuery(pSql->pSubs[i]);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -403,11 +416,9 @@ static void quitAllSubquery(SSqlObj* pSqlObj, SJoinSupporter* pSupporter) {
|
|||
}
|
||||
|
||||
// update the query time range according to the join results on timestamp
|
||||
static void updateQueryTimeRange(SQueryInfo* pQueryInfo, int64_t st, int64_t et) {
|
||||
assert(pQueryInfo->window.skey <= st && pQueryInfo->window.ekey >= et);
|
||||
|
||||
pQueryInfo->window.skey = st;
|
||||
pQueryInfo->window.ekey = et;
|
||||
static void updateQueryTimeRange(SQueryInfo* pQueryInfo, STimeWindow* win) {
|
||||
assert(pQueryInfo->window.skey <= win->skey && pQueryInfo->window.ekey >= win->ekey);
|
||||
pQueryInfo->window = *win;
|
||||
}
|
||||
|
||||
static void tSIntersectionAndLaunchSecQuery(SJoinSupporter* pSupporter, SSqlObj* pSql) {
|
||||
|
@ -451,21 +462,21 @@ static void tSIntersectionAndLaunchSecQuery(SJoinSupporter* pSupporter, SSqlObj*
|
|||
SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
|
||||
SJoinSupporter* p2 = pParentSql->pSubs[1]->param;
|
||||
|
||||
TSKEY st, et;
|
||||
int64_t num = doTSBlockIntersect(pParentSql, p1, p2, &st, &et);
|
||||
STimeWindow win = TSWINDOW_INITIALIZER;
|
||||
int64_t num = doTSBlockIntersect(pParentSql, p1, p2, &win);
|
||||
if (num <= 0) { // no result during ts intersect
|
||||
tscTrace("%p free all sub SqlObj and quit", pParentSql);
|
||||
freeJoinSubqueryObj(pParentSql);
|
||||
} else {
|
||||
updateQueryTimeRange(pParentQueryInfo, st, et);
|
||||
updateQueryTimeRange(pParentQueryInfo, &win);
|
||||
tscLaunchSecondPhaseSubqueries(pParentSql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tscCompareTidTags(const void* p1, const void* p2) {
|
||||
const STidTags* t1 = (const STidTags*) p1;
|
||||
const STidTags* t2 = (const STidTags*) p2;
|
||||
const STidTags* t1 = (const STidTags*) varDataVal(p1);
|
||||
const STidTags* t2 = (const STidTags*) varDataVal(p2);
|
||||
|
||||
if (t1->vgId != t2->vgId) {
|
||||
return (t1->vgId > t2->vgId) ? 1 : -1;
|
||||
|
@ -476,7 +487,7 @@ int32_t tscCompareTidTags(const void* p1, const void* p2) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tscBuildVgroupTableInfo(STableMetaInfo* pTableMetaInfo, SArray* tables) {
|
||||
void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArray* tables) {
|
||||
SArray* result = taosArrayInit(4, sizeof(SVgroupTableInfo));
|
||||
SArray* vgTables = NULL;
|
||||
STidTags* prev = NULL;
|
||||
|
@ -502,12 +513,14 @@ void tscBuildVgroupTableInfo(STableMetaInfo* pTableMetaInfo, SArray* tables) {
|
|||
taosArrayPush(result, &info);
|
||||
}
|
||||
|
||||
tscTrace("%p tid:%d, uid:%"PRIu64",vgId:%d added for vnode query", pSql, tt->tid, tt->uid, tt->vgId)
|
||||
STableIdInfo item = {.uid = tt->uid, .tid = tt->tid, .key = INT64_MIN};
|
||||
taosArrayPush(vgTables, &item);
|
||||
prev = tt;
|
||||
}
|
||||
|
||||
pTableMetaInfo->pVgroupTables = result;
|
||||
pTableMetaInfo->vgroupIndex = 0;
|
||||
}
|
||||
|
||||
static void issueTSCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj* pParent) {
|
||||
|
@ -533,9 +546,8 @@ static void issueTSCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj*
|
|||
|
||||
// set the tags value for ts_comp function
|
||||
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, 0);
|
||||
int16_t tagColIndex = tscGetJoinTagColIndexByUid(&pSupporter->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
|
||||
pExpr->param->i64Key = tagColIndex;
|
||||
int16_t tagColId = tscGetJoinTagColIdByUid(&pSupporter->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
pExpr->param->i64Key = tagColId;
|
||||
pExpr->numOfParams = 1;
|
||||
|
||||
// add the filter tag column
|
||||
|
@ -555,47 +567,36 @@ static void issueTSCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj*
|
|||
size_t numOfCols = taosArrayGetSize(pQueryInfo->colList);
|
||||
|
||||
tscTrace(
|
||||
"%p subquery:%p tableIndex:%d, vgroupIndex:%d, type:%d, transfer to ts_comp query to retrieve timestamps, "
|
||||
"exprInfo:%d, colList:%d, fieldsInfo:%d, name:%s",
|
||||
pParent, pSql, 0, pTableMetaInfo->vgroupIndex, pQueryInfo->type, tscSqlExprNumOfExprs(pQueryInfo),
|
||||
numOfCols, pQueryInfo->fieldsInfo.numOfOutput, pTableMetaInfo->name);
|
||||
"%p subquery:%p tableIndex:%d, vgroupIndex:%d, numOfVgroups:%d, type:%d, ts_comp query to retrieve timestamps, "
|
||||
"numOfExpr:%d, colList:%d, numOfOutputFields:%d, name:%s",
|
||||
pParent, pSql, 0, pTableMetaInfo->vgroupIndex, pTableMetaInfo->vgroupList->numOfVgroups, pQueryInfo->type,
|
||||
tscSqlExprNumOfExprs(pQueryInfo), numOfCols, pQueryInfo->fieldsInfo.numOfOutput, pTableMetaInfo->name);
|
||||
|
||||
tscProcessSql(pSql);
|
||||
}
|
||||
|
||||
static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
||||
SJoinSupporter* pSupporter = (SJoinSupporter*)param;
|
||||
static bool checkForIdenticalTagVal(SQueryInfo* pQueryInfo, SJoinSupporter* p1, void* pSql) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
SSqlObj* pParentSql = pSupporter->pObj;
|
||||
SSqlObj* pSql = (SSqlObj*)tres;
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);// todo: tags mismatch, tags not completed
|
||||
SColumn *pCol = taosArrayGetP(pTableMetaInfo->tagColList, 0);
|
||||
SSchema *pColSchema = &pSchema[pCol->colIndex.columnIndex];
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
for(int32_t i = 1; i < p1->num; ++i) {
|
||||
STidTags* prev = (STidTags*) varDataVal(p1->pIdTagList + (i - 1) * p1->tagSize);
|
||||
STidTags* p = (STidTags*) varDataVal(p1->pIdTagList + i * p1->tagSize);
|
||||
|
||||
// response of tag retrieve
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) {
|
||||
if (numOfRows == 0 || pSql->res.completed) {
|
||||
|
||||
if (numOfRows > 0) {
|
||||
size_t length = pSupporter->totalLen + pSql->res.rspLen;
|
||||
char* tmp = realloc(pSupporter->pIdTagList, length);
|
||||
assert(tmp != NULL);
|
||||
pSupporter->pIdTagList = tmp;
|
||||
|
||||
memcpy(pSupporter->pIdTagList, pSql->res.data, pSql->res.rspLen);
|
||||
pSupporter->totalLen += pSql->res.rspLen;
|
||||
pSupporter->num += pSql->res.numOfRows;
|
||||
if (doCompare(prev->tag, p->tag, pColSchema->type, pColSchema->bytes) == 0) {
|
||||
tscError("%p join tags have same value for different table, free all sub SqlObj and quit", pSql);
|
||||
p1->pState->code = TSDB_CODE_QRY_DUP_JOIN_KEY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t numOfTotal = pSupporter->pState->numOfTotal;
|
||||
int32_t finished = atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1);
|
||||
|
||||
if (finished < numOfTotal) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// all subqueries are returned, start to compare the tags
|
||||
assert(finished == numOfTotal);
|
||||
static void getIntersectionOfTagVal(SQueryInfo* pQueryInfo, SSqlObj* pParentSql, SArray** s1, SArray** s2) {
|
||||
tscTrace("%p all subqueries retrieve tags complete, do tags match", pParentSql);
|
||||
|
||||
SJoinSupporter* p1 = pParentSql->pSubs[0]->param;
|
||||
|
@ -605,24 +606,32 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
qsort(p2->pIdTagList, p2->num, p2->tagSize, tscCompareTidTags);
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
int16_t tagColId = tscGetJoinTagColIdByUid(&pQueryInfo->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
|
||||
SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);// todo: tags mismatch, tags not completed
|
||||
SSchema* pColSchema = tscGetTableColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
|
||||
|
||||
SColumn *pCol = taosArrayGetP(pTableMetaInfo->tagColList, 0);
|
||||
SSchema *pColSchema = &pSchema[pCol->colIndex.columnIndex];
|
||||
*s1 = taosArrayInit(p1->num, p1->tagSize);
|
||||
*s2 = taosArrayInit(p2->num, p2->tagSize);
|
||||
|
||||
SArray* s1 = taosArrayInit(p1->num, p1->tagSize);
|
||||
SArray* s2 = taosArrayInit(p2->num, p2->tagSize);
|
||||
if (!(checkForIdenticalTagVal(pQueryInfo, p1, pParentSql) && checkForIdenticalTagVal(pQueryInfo, p2, pParentSql))) {
|
||||
freeJoinSubqueryObj(pParentSql);
|
||||
pParentSql->res.code = TSDB_CODE_QRY_DUP_JOIN_KEY;
|
||||
tscQueueAsyncRes(pParentSql);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t i = 0, j = 0;
|
||||
while(i < p1->num && j < p2->num) {
|
||||
STidTags* pp1 = (STidTags*) p1->pIdTagList + i * p1->tagSize;
|
||||
STidTags* pp2 = (STidTags*) p2->pIdTagList + j * p2->tagSize;
|
||||
STidTags* pp1 = (STidTags*) varDataVal(p1->pIdTagList + i * p1->tagSize);
|
||||
STidTags* pp2 = (STidTags*) varDataVal(p2->pIdTagList + j * p2->tagSize);
|
||||
|
||||
int32_t ret = doCompare(pp1->tag, pp2->tag, pColSchema->type, pColSchema->bytes);
|
||||
if (ret == 0) {
|
||||
taosArrayPush(s1, pp1);
|
||||
taosArrayPush(s2, pp2);
|
||||
tscTrace("%p tag matched, vgId:%d, val:%d, tid:%d, uid:%"PRIu64", tid:%d, uid:%"PRIu64, pParentSql, pp1->vgId,
|
||||
*(int*) pp1->tag, pp1->tid, pp1->uid, pp2->tid, pp2->uid);
|
||||
|
||||
taosArrayPush(*s1, pp1);
|
||||
taosArrayPush(*s2, pp2);
|
||||
j++;
|
||||
i++;
|
||||
} else if (ret > 0) {
|
||||
|
@ -631,6 +640,69 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
||||
SJoinSupporter* pSupporter = (SJoinSupporter*)param;
|
||||
|
||||
SSqlObj* pParentSql = pSupporter->pObj;
|
||||
|
||||
SSqlObj* pSql = (SSqlObj*)tres;
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
SSqlRes* pRes = &pSql->res;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
// response of tag retrieve
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) {
|
||||
// todo handle error
|
||||
|
||||
if (numOfRows == 0 || pRes->completed) {
|
||||
if (numOfRows > 0) {
|
||||
size_t validLen = pSupporter->tagSize * pRes->numOfRows;
|
||||
|
||||
size_t length = pSupporter->totalLen + validLen;
|
||||
char* tmp = realloc(pSupporter->pIdTagList, length);
|
||||
assert(tmp != NULL);
|
||||
pSupporter->pIdTagList = tmp;
|
||||
|
||||
memcpy(pSupporter->pIdTagList + pSupporter->totalLen,pRes->data, validLen);
|
||||
pSupporter->totalLen += validLen;
|
||||
pSupporter->num += pRes->numOfRows;
|
||||
}
|
||||
|
||||
// <tid + tag> tuples have been retrieved to client, try <tid + tag> tuples from the next vnode
|
||||
if (hasMoreVnodesToTry(pSql)) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
int32_t totalVgroups = pTableMetaInfo->vgroupList->numOfVgroups;
|
||||
pTableMetaInfo->vgroupIndex += 1;
|
||||
assert(pTableMetaInfo->vgroupIndex < totalVgroups);
|
||||
|
||||
tscTrace("%p tid_tag from vgroup index:%d completed, try next vgroup:%d. total vgroups:%d. current numOfRes:%d",
|
||||
pSql, pTableMetaInfo->vgroupIndex - 1, pTableMetaInfo->vgroupIndex, totalVgroups,
|
||||
pSupporter->num);
|
||||
|
||||
pCmd->command = TSDB_SQL_SELECT;
|
||||
tscResetForNextRetrieve(&pSql->res);
|
||||
|
||||
// set the callback function
|
||||
pSql->fp = tscJoinQueryCallback;
|
||||
tscProcessSql(pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t numOfTotal = pSupporter->pState->numOfTotal;
|
||||
int32_t finished = atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1);
|
||||
if (finished < numOfTotal) {
|
||||
return;
|
||||
}
|
||||
|
||||
// all subquery are returned, start to compare the tags
|
||||
assert(finished == numOfTotal);
|
||||
|
||||
SArray *s1 = NULL, *s2 = NULL;
|
||||
getIntersectionOfTagVal(pQueryInfo, pParentSql, &s1, &s2);
|
||||
|
||||
if (taosArrayGetSize(s1) == 0 || taosArrayGetSize(s2) == 0) { // no results,return.
|
||||
tscTrace("%p free all sub SqlObj and quit", pParentSql);
|
||||
|
@ -642,11 +714,11 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
|
||||
SQueryInfo* pQueryInfo1 = tscGetQueryInfoDetail(pSubCmd1, 0);
|
||||
STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo1, 0);
|
||||
tscBuildVgroupTableInfo(pTableMetaInfo1, s1);
|
||||
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo1, s1);
|
||||
|
||||
SQueryInfo* pQueryInfo2 = tscGetQueryInfoDetail(pSubCmd2, 0);
|
||||
STableMetaInfo* pTableMetaInfo2 = tscGetMetaInfo(pQueryInfo2, 0);
|
||||
tscBuildVgroupTableInfo(pTableMetaInfo2, s2);
|
||||
tscBuildVgroupTableInfo(pParentSql, pTableMetaInfo2, s2);
|
||||
|
||||
pSupporter->pState->numOfCompleted = 0;
|
||||
pSupporter->pState->code = 0;
|
||||
|
@ -659,15 +731,26 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
}
|
||||
|
||||
} else {
|
||||
size_t length = pSupporter->totalLen + pSql->res.rspLen;
|
||||
if (numOfRows < 0) { // error
|
||||
pSupporter->pState->code = numOfRows;
|
||||
quitAllSubquery(pParentSql, pSupporter);
|
||||
|
||||
pParentSql->res.code = numOfRows;
|
||||
tscQueueAsyncRes(pParentSql);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t length = pSupporter->totalLen + pRes->rspLen;
|
||||
assert(length > 0);
|
||||
|
||||
char* tmp = realloc(pSupporter->pIdTagList, length);
|
||||
assert(tmp != NULL);
|
||||
|
||||
pSupporter->pIdTagList = tmp;
|
||||
|
||||
memcpy(pSupporter->pIdTagList, pSql->res.data, pSql->res.rspLen);
|
||||
pSupporter->totalLen += pSql->res.rspLen;
|
||||
pSupporter->num += pSql->res.numOfRows;
|
||||
memcpy(pSupporter->pIdTagList, pRes->data, pRes->rspLen);
|
||||
pSupporter->totalLen += pRes->rspLen;
|
||||
pSupporter->num += pRes->numOfRows;
|
||||
|
||||
// continue retrieve data from vnode
|
||||
taos_fetch_rows_a(tres, joinRetrieveCallback, param);
|
||||
|
@ -684,18 +767,13 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (numOfRows == 0) {
|
||||
tSIntersectionAndLaunchSecQuery(pSupporter, pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
// write the compressed timestamp to disk file
|
||||
fwrite(pSql->res.data, pSql->res.numOfRows, 1, pSupporter->f);
|
||||
if (numOfRows > 0) { // write the compressed timestamp to disk file
|
||||
fwrite(pRes->data, pRes->numOfRows, 1, pSupporter->f);
|
||||
fclose(pSupporter->f);
|
||||
pSupporter->f = NULL;
|
||||
|
||||
STSBuf* pBuf = tsBufCreateFromFile(pSupporter->path, true);
|
||||
if (pBuf == NULL) {
|
||||
if (pBuf == NULL) { // in error process, close the fd
|
||||
tscError("%p invalid ts comp file from vnode, abort subquery, file size:%d", pSql, numOfRows);
|
||||
|
||||
pSupporter->pState->code = TSDB_CODE_TSC_APP_ERROR; // todo set the informative code
|
||||
|
@ -713,13 +791,40 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
tsBufMerge(pSupporter->pTSBuf, pBuf, pTableMetaInfo->vgroupIndex);
|
||||
tsBufDestory(pBuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (pSql->res.completed) {
|
||||
if (pRes->completed) {
|
||||
if (hasMoreVnodesToTry(pSql)) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
int32_t totalVgroups = pTableMetaInfo->vgroupList->numOfVgroups;
|
||||
pTableMetaInfo->vgroupIndex += 1;
|
||||
assert(pTableMetaInfo->vgroupIndex < totalVgroups);
|
||||
|
||||
tscTrace("%p results from vgroup index:%d completed, try next vgroup:%d. total vgroups:%d. current numOfRes:%d",
|
||||
pSql, pTableMetaInfo->vgroupIndex - 1, pTableMetaInfo->vgroupIndex, totalVgroups,
|
||||
pRes->numOfClauseTotal);
|
||||
|
||||
pCmd->command = TSDB_SQL_SELECT;
|
||||
tscResetForNextRetrieve(&pSql->res);
|
||||
|
||||
assert(pSupporter->f == NULL);
|
||||
getTmpfilePath("ts-join", pSupporter->path);
|
||||
pSupporter->f = fopen(pSupporter->path, "w");
|
||||
pRes->row = pRes->numOfRows;
|
||||
|
||||
// set the callback function
|
||||
pSql->fp = tscJoinQueryCallback;
|
||||
tscProcessSql(pSql);
|
||||
return;
|
||||
} else {
|
||||
tSIntersectionAndLaunchSecQuery(pSupporter, pSql);
|
||||
}
|
||||
|
||||
} else { // open a new file to save the incoming result
|
||||
getTmpfilePath("ts-join", pSupporter->path);
|
||||
pSupporter->f = fopen(pSupporter->path, "w");
|
||||
pSql->res.row = pSql->res.numOfRows;
|
||||
pRes->row = pRes->numOfRows;
|
||||
|
||||
taos_fetch_rows_a(tres, joinRetrieveCallback, param);
|
||||
}
|
||||
|
@ -730,7 +835,7 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
}
|
||||
|
||||
if (numOfRows >= 0) {
|
||||
pSql->res.numOfTotal += pSql->res.numOfRows;
|
||||
pRes->numOfTotal += pRes->numOfRows;
|
||||
}
|
||||
|
||||
if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && numOfRows == 0) {
|
||||
|
@ -833,7 +938,10 @@ void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
|
|||
}
|
||||
}
|
||||
} else { // has reach the limitation, no data anymore
|
||||
if (pRes->row >= pRes->numOfRows) {
|
||||
hasData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1055,9 +1163,7 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
|
|||
|
||||
// this data needs to be transfer to support struct
|
||||
memset(&pNewQueryInfo->fieldsInfo, 0, sizeof(SFieldInfo));
|
||||
|
||||
pSupporter->tagCond = pNewQueryInfo->tagCond;
|
||||
memset(&pNewQueryInfo->tagCond, 0, sizeof(STagCond));
|
||||
tscTagCondCopy(&pSupporter->tagCond, &pNewQueryInfo->tagCond);//pNewQueryInfo->tagCond;
|
||||
|
||||
pNew->cmd.numOfCols = 0;
|
||||
pNewQueryInfo->intervalTime = 0;
|
||||
|
@ -1071,39 +1177,34 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
|
|||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pNewQueryInfo, 0);
|
||||
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // return the tableId & tag
|
||||
SSchema s = {0};
|
||||
SColumnIndex index = {0};
|
||||
|
||||
size_t numOfTags = taosArrayGetSize(pTableMetaInfo->tagColList);
|
||||
for(int32_t i = 0; i < numOfTags; ++i) {
|
||||
SColumn* c = taosArrayGetP(pTableMetaInfo->tagColList, i);
|
||||
index = (SColumnIndex) {.tableIndex = 0, .columnIndex = c->colIndex.columnIndex};
|
||||
STagCond* pTagCond = &pSupporter->tagCond;
|
||||
assert(pTagCond->joinInfo.hasJoin);
|
||||
|
||||
SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta);
|
||||
s = pTagSchema[c->colIndex.columnIndex];
|
||||
int32_t tagColId = tscGetJoinTagColIdByUid(pTagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
SSchema* s = tscGetTableColumnSchemaById(pTableMetaInfo->pTableMeta, tagColId);
|
||||
|
||||
int16_t bytes = 0;
|
||||
int16_t type = 0;
|
||||
int32_t inter = 0;
|
||||
|
||||
getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0);
|
||||
getResultDataInfo(s->type, s->bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0);
|
||||
|
||||
s.type = type;
|
||||
s.bytes = bytes;
|
||||
pSupporter->tagSize = s.bytes;
|
||||
}
|
||||
SSchema s1 = {.colId = s->colId, .type = type, .bytes = bytes};
|
||||
pSupporter->tagSize = s1.bytes;
|
||||
assert(isValidDataType(s1.type) && s1.bytes > 0);
|
||||
|
||||
// set get tags query type
|
||||
TSDB_QUERY_SET_TYPE(pNewQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY);
|
||||
tscAddSpecialColumnForSelect(pNewQueryInfo, 0, TSDB_FUNC_TID_TAG, &index, &s, TSDB_COL_TAG);
|
||||
tscAddSpecialColumnForSelect(pNewQueryInfo, 0, TSDB_FUNC_TID_TAG, &index, &s1, TSDB_COL_TAG);
|
||||
size_t numOfCols = taosArrayGetSize(pNewQueryInfo->colList);
|
||||
|
||||
tscTrace(
|
||||
"%p subquery:%p tableIndex:%d, vgroupIndex:%d, type:%d, transfer to tid_tag query to retrieve (tableId, tags), "
|
||||
"exprInfo:%d, colList:%d, fieldsInfo:%d, name:%s",
|
||||
"exprInfo:%d, colList:%d, fieldsInfo:%d, tagIndex:%d, name:%s",
|
||||
pSql, pNew, tableIndex, pTableMetaInfo->vgroupIndex, pNewQueryInfo->type, tscSqlExprNumOfExprs(pNewQueryInfo),
|
||||
numOfCols, pNewQueryInfo->fieldsInfo.numOfOutput, pNewQueryInfo->pTableMetaInfo[0]->name);
|
||||
|
||||
numOfCols, pNewQueryInfo->fieldsInfo.numOfOutput, index.columnIndex, pNewQueryInfo->pTableMetaInfo[0]->name);
|
||||
} else {
|
||||
SSchema colSchema = {.type = TSDB_DATA_TYPE_BINARY, .bytes = 1};
|
||||
SColumnIndex index = {0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
|
@ -1112,10 +1213,11 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
|
|||
// set the tags value for ts_comp function
|
||||
SSqlExpr *pExpr = tscSqlExprGet(pNewQueryInfo, 0);
|
||||
|
||||
int16_t tagColIndex = tscGetJoinTagColIndexByUid(&pSupporter->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
|
||||
pExpr->param->i64Key = tagColIndex;
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
int16_t tagColId = tscGetJoinTagColIdByUid(&pSupporter->tagCond, pTableMetaInfo->pTableMeta->uid);
|
||||
pExpr->param->i64Key = tagColId;
|
||||
pExpr->numOfParams = 1;
|
||||
}
|
||||
|
||||
// add the filter tag column
|
||||
if (pSupporter->colList != NULL) {
|
||||
|
@ -1284,6 +1386,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
|
|||
if (pQueryInfo->tsBuf) {
|
||||
SQueryInfo *pNewQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
|
||||
pNewQueryInfo->tsBuf = tsBufClone(pQueryInfo->tsBuf);
|
||||
assert(pNewQueryInfo->tsBuf != NULL);
|
||||
}
|
||||
|
||||
tscTrace("%p sub:%p create subquery success. orderOfSub:%d", pSql, pNew, trs->subqueryIndex);
|
||||
|
@ -1437,7 +1540,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
|
|||
// in case of second stage join subquery, invoke its callback function instead of regular QueueAsyncRes
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pPObj->cmd, 0);
|
||||
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_JOIN_SEC_STAGE) == TSDB_QUERY_TYPE_JOIN_SEC_STAGE) {
|
||||
if (!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) {
|
||||
(*pPObj->fp)(pPObj->param, pPObj, pPObj->res.code);
|
||||
} else { // regular super table query
|
||||
if (pPObj->res.code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1458,7 +1561,7 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p
|
|||
|
||||
// data in from current vnode is stored in cache and disk
|
||||
uint32_t numOfRowsFromSubquery = trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->num;
|
||||
tscTrace("%p sub:%p all data retrieved from ip:%u,vgId:%d, numOfRows:%d, orderOfSub:%d", pPObj, pSql,
|
||||
tscTrace("%p sub:%p all data retrieved from ip:%s, vgId:%d, numOfRows:%d, orderOfSub:%d", pPObj, pSql,
|
||||
pTableMetaInfo->vgroupList->vgroups[0].ipAddr[0].fqdn, pTableMetaInfo->vgroupList->vgroups[0].vgId,
|
||||
numOfRowsFromSubquery, idx);
|
||||
|
||||
|
@ -1692,7 +1795,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
|||
|
||||
tscHandleSubqueryError(param, tres, pState->code);
|
||||
} else { // success, proceed to retrieve data from dnode
|
||||
tscTrace("%p sub:%p query complete, ip:%u, vgId:%d, orderOfSub:%d, retrieve data", trsupport->pParentSqlObj, pSql,
|
||||
tscTrace("%p sub:%p query complete, ip:%s, vgId:%d, orderOfSub:%d, retrieve data", trsupport->pParentSqlObj, pSql,
|
||||
pVgroup->ipAddr[0].fqdn, pVgroup->vgId, trsupport->subqueryIndex);
|
||||
|
||||
if (pSql->res.qhandle == 0) { // qhandle is NULL, code is TSDB_CODE_SUCCESS means no results generated from this vnode
|
||||
|
@ -1852,7 +1955,7 @@ void tscBuildResFromSubqueries(SSqlObj *pSql) {
|
|||
pRes->numOfClauseTotal++;
|
||||
break;
|
||||
} else { // continue retrieve data from vnode
|
||||
if (!tscHashRemainDataInSubqueryResultSet(pSql)) {
|
||||
if (!tscHasRemainDataInSubqueryResultSet(pSql)) {
|
||||
tscTrace("%p at least one subquery exhausted, free all other %d subqueries", pSql, pSql->numOfSubs - 1);
|
||||
SSubqueryState *pState = NULL;
|
||||
|
||||
|
@ -2002,7 +2105,7 @@ void **doSetResultRowData(SSqlObj *pSql, bool finalResult) {
|
|||
return pRes->tsrow;
|
||||
}
|
||||
|
||||
static UNUSED_FUNC bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
|
||||
static bool tscHasRemainDataInSubqueryResultSet(SSqlObj *pSql) {
|
||||
bool hasData = true;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
|
@ -2045,8 +2148,7 @@ static UNUSED_FUNC bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
|
|||
SQueryInfo *pQueryInfo1 = tscGetQueryInfoDetail(&pSql->pSubs[i]->cmd, 0);
|
||||
|
||||
if ((pRes1->row >= pRes1->numOfRows && tscHasReachLimitation(pQueryInfo1, pRes1) &&
|
||||
tscProjectionQueryOnTable(pQueryInfo1)) ||
|
||||
(pRes1->numOfRows == 0)) {
|
||||
tscIsProjectionQuery(pQueryInfo1)) || (pRes1->numOfRows == 0)) {
|
||||
hasData = false;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "tkey.h"
|
||||
#include "tmd5.h"
|
||||
#include "tscProfile.h"
|
||||
#include "tscSecondaryMerge.h"
|
||||
#include "tscLocalMerge.h"
|
||||
#include "tscSubquery.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tsclient.h"
|
||||
|
@ -70,13 +70,6 @@ void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) {
|
|||
taosArrayPush(pTagCond->pCond, &cond);
|
||||
}
|
||||
|
||||
bool tscQueryOnSTable(SSqlCmd* pCmd) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
|
||||
return ((pQueryInfo->type & TSDB_QUERY_TYPE_STABLE_QUERY) == TSDB_QUERY_TYPE_STABLE_QUERY) &&
|
||||
(pCmd->msgType == TSDB_MSG_TYPE_QUERY);
|
||||
}
|
||||
|
||||
bool tscQueryTags(SQueryInfo* pQueryInfo) {
|
||||
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
|
@ -95,32 +88,8 @@ bool tscQueryTags(SQueryInfo* pQueryInfo) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool tscIsSelectivityWithTagQuery(SSqlCmd* pCmd) {
|
||||
bool hasTags = false;
|
||||
int32_t numOfSelectivity = 0;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
|
||||
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
|
||||
int32_t functId = tscSqlExprGet(pQueryInfo, i)->functionId;
|
||||
if (functId == TSDB_FUNC_TAG_DUMMY) {
|
||||
hasTags = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((aAggs[functId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) != 0) {
|
||||
numOfSelectivity++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numOfSelectivity > 0 && hasTags) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void tscGetDBInfoFromMeterId(char* tableId, char* db) {
|
||||
// todo refactor, extract methods and move the common module
|
||||
void tscGetDBInfoFromTableFullName(char* tableId, char* db) {
|
||||
char* st = strstr(tableId, TS_PATH_DELIMITER);
|
||||
if (st != NULL) {
|
||||
char* end = strstr(st + 1, TS_PATH_DELIMITER);
|
||||
|
@ -181,8 +150,14 @@ bool tscIsProjectionQueryOnSTable(SQueryInfo* pQueryInfo, int32_t tableIndex) {
|
|||
|
||||
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||
int32_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
|
||||
if (functionId != TSDB_FUNC_PRJ && functionId != TSDB_FUNC_TAGPRJ && functionId != TSDB_FUNC_TAG &&
|
||||
functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_ARITHM) {
|
||||
|
||||
if (functionId != TSDB_FUNC_PRJ &&
|
||||
functionId != TSDB_FUNC_TAGPRJ &&
|
||||
functionId != TSDB_FUNC_TAG &&
|
||||
functionId != TSDB_FUNC_TS &&
|
||||
functionId != TSDB_FUNC_ARITHM &&
|
||||
functionId != TSDB_FUNC_TS_COMP &&
|
||||
functionId != TSDB_FUNC_TID_TAG) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -209,10 +184,14 @@ bool tscOrderedProjectionQueryOnSTable(SQueryInfo* pQueryInfo, int32_t tableInde
|
|||
return pQueryInfo->order.orderColId >= 0;
|
||||
}
|
||||
|
||||
bool tscProjectionQueryOnTable(SQueryInfo* pQueryInfo) {
|
||||
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
|
||||
bool tscIsProjectionQuery(SQueryInfo* pQueryInfo) {
|
||||
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
int32_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
|
||||
if (functionId != TSDB_FUNC_PRJ && functionId != TSDB_FUNC_TS) {
|
||||
|
||||
if (functionId != TSDB_FUNC_PRJ && functionId != TSDB_FUNC_TAGPRJ && functionId != TSDB_FUNC_TAG &&
|
||||
functionId != TSDB_FUNC_TS && functionId != TSDB_FUNC_ARITHM) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -225,9 +204,10 @@ bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) {
|
|||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
if (pExpr == NULL) {
|
||||
return false;
|
||||
}
|
||||
assert(pExpr != NULL);
|
||||
// if (pExpr == NULL) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
int32_t functionId = pExpr->functionId;
|
||||
if (functionId == TSDB_FUNC_TAG) {
|
||||
|
@ -238,6 +218,7 @@ bool tscIsPointInterpQuery(SQueryInfo* pQueryInfo) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1451,8 +1432,6 @@ bool tscShouldBeFreed(SSqlObj* pSql) {
|
|||
return false;
|
||||
}
|
||||
|
||||
assert(pSql->fp != NULL);
|
||||
|
||||
STscObj* pTscObj = pSql->pTscObj;
|
||||
if (pSql->pStream != NULL || pTscObj->pHb == pSql || pSql->pSubscription != NULL) {
|
||||
return false;
|
||||
|
@ -1774,7 +1753,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
SQueryInfo* pPrevQueryInfo = tscGetQueryInfoDetail(&pPrevSql->cmd, pPrevSql->cmd.clauseIndex);
|
||||
pNewQueryInfo->type = pPrevQueryInfo->type;
|
||||
} else {
|
||||
pNewQueryInfo->type |= TSDB_QUERY_TYPE_SUBQUERY; // it must be the subquery
|
||||
TSDB_QUERY_SET_TYPE(pNewQueryInfo->type, TSDB_QUERY_TYPE_SUBQUERY);// it must be the subquery
|
||||
}
|
||||
|
||||
uint64_t uid = pTableMetaInfo->pTableMeta->uid;
|
||||
|
@ -1800,18 +1779,25 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
|
||||
// make sure the the sqlExpr for each fields is correct
|
||||
// todo handle the agg arithmetic expression
|
||||
numOfExprs = tscSqlExprNumOfExprs(pNewQueryInfo);
|
||||
|
||||
for(int32_t f = 0; f < pNewQueryInfo->fieldsInfo.numOfOutput; ++f) {
|
||||
TAOS_FIELD* field = tscFieldInfoGetField(&pNewQueryInfo->fieldsInfo, f);
|
||||
numOfExprs = tscSqlExprNumOfExprs(pNewQueryInfo);
|
||||
bool matched = false;
|
||||
|
||||
for(int32_t k1 = 0; k1 < numOfExprs; ++k1) {
|
||||
SSqlExpr* pExpr1 = tscSqlExprGet(pNewQueryInfo, k1);
|
||||
|
||||
if (strcmp(field->name, pExpr1->aliasName) == 0) { // eatablish link according to the result field name
|
||||
if (strcmp(field->name, pExpr1->aliasName) == 0) { // establish link according to the result field name
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pNewQueryInfo->fieldsInfo, f);
|
||||
pInfo->pSqlExpr = pExpr1;
|
||||
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(matched);
|
||||
}
|
||||
|
||||
tscFieldInfoUpdateOffset(pNewQueryInfo);
|
||||
|
@ -1900,16 +1886,21 @@ void tscDoQuery(SSqlObj* pSql) {
|
|||
}
|
||||
|
||||
if (QUERY_IS_JOIN_QUERY(type)) {
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_SUBQUERY) == 0) {
|
||||
if (!TSDB_QUERY_HAS_TYPE(type, TSDB_QUERY_TYPE_SUBQUERY)) {
|
||||
tscHandleMasterJoinQuery(pSql);
|
||||
return;
|
||||
} else { // for first stage sub query, iterate all vnodes to get all timestamp
|
||||
if (!TSDB_QUERY_HAS_TYPE(type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) {
|
||||
tscProcessSql(pSql);
|
||||
} else { // secondary stage join query.
|
||||
if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) { // super table query
|
||||
tscHandleMasterSTableQuery(pSql);
|
||||
} else {
|
||||
// for first stage sub query, iterate all vnodes to get all timestamp
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_JOIN_SEC_STAGE) != TSDB_QUERY_TYPE_JOIN_SEC_STAGE) {
|
||||
// doProcessSql(pSql);
|
||||
assert(0);
|
||||
tscProcessSql(pSql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) { // super table query
|
||||
tscHandleMasterSTableQuery(pSql);
|
||||
return;
|
||||
|
@ -1919,11 +1910,13 @@ void tscDoQuery(SSqlObj* pSql) {
|
|||
}
|
||||
}
|
||||
|
||||
int16_t tscGetJoinTagColIndexByUid(STagCond* pTagCond, uint64_t uid) {
|
||||
int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) {
|
||||
if (pTagCond->joinInfo.left.uid == uid) {
|
||||
return pTagCond->joinInfo.left.tagCol;
|
||||
return pTagCond->joinInfo.left.tagColId;
|
||||
} else if (pTagCond->joinInfo.right.uid == uid) {
|
||||
return pTagCond->joinInfo.right.tagColId;
|
||||
} else {
|
||||
return pTagCond->joinInfo.right.tagCol;
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1980,10 +1973,9 @@ bool hasMoreVnodesToTry(SSqlObj* pSql) {
|
|||
return false;
|
||||
}
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
assert(pRes->completed);
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
// for normal table, no need to try any more if results are all retrieved from one vnode
|
||||
if (!UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo) || (pTableMetaInfo->vgroupList == NULL)) {
|
||||
|
@ -2006,7 +1998,6 @@ void tscTryQueryNextVnode(SSqlObj* pSql, __async_cb_func_t fp) {
|
|||
* if case of: multi-vnode super table projection query
|
||||
*/
|
||||
assert(pRes->numOfRows == 0 && tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0) && !tscHasReachLimitation(pQueryInfo, pRes));
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
int32_t totalVgroups = pTableMetaInfo->vgroupList->numOfVgroups;
|
||||
|
|
|
@ -24,19 +24,19 @@ TEST(testCase, parse_time) {
|
|||
|
||||
int64_t time = 0, time1 = 0;
|
||||
|
||||
taosParseTime(t1, &time, strlen(t1), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t1, &time, strlen(t1), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 1514739661952);
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, timezone * MILLISECOND_PER_SECOND);
|
||||
|
||||
char t2[] = "2018-1-1T1:1:1.952Z";
|
||||
taosParseTime(t2, &time, strlen(t2), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t2, &time, strlen(t2), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
|
||||
EXPECT_EQ(time, 1514739661952 + 28800000);
|
||||
|
||||
char t3[] = "2018-1-1 1:01:01.952";
|
||||
taosParseTime(t3, &time, strlen(t3), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t3, &time, strlen(t3), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 1514739661952);
|
||||
|
||||
char t4[] = "2018-1-1 1:01:01.9";
|
||||
|
@ -45,122 +45,122 @@ TEST(testCase, parse_time) {
|
|||
char t7[] = "2018-01-01 01:01:01.9";
|
||||
char t8[] = "2018-01-01 01:01:01.9007865";
|
||||
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t5, &time1, strlen(t5), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t5, &time1, strlen(t5), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t6, &time1, strlen(t6), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t6, &time1, strlen(t6), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t7, &time1, strlen(t7), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t7, &time1, strlen(t7), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taosParseTime(t5, &time, strlen(t5), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t8, &time1, strlen(t8), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t5, &time, strlen(t5), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t8, &time1, strlen(t8), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
char t9[] = "2017-4-3 1:1:2.980";
|
||||
char t10[] = "2017-4-3T2:1:2.98+9:00";
|
||||
taosParseTime(t9, &time, strlen(t9), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t9, &time, strlen(t9), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
char t11[] = "2017-4-3T2:1:2.98+09:00";
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
char t12[] = "2017-4-3T2:1:2.98+0900";
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "UTC");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 0);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
char t14[] = "1970-1-1T0:0:0Z";
|
||||
taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 0);
|
||||
|
||||
char t40[] = "1970-1-1 0:0:0.999999999";
|
||||
taosParseTime(t40, &time, strlen(t40), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t40, &time, strlen(t40), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 999 + timezone * MILLISECOND_PER_SECOND);
|
||||
|
||||
char t41[] = "1997-1-1 0:0:0.999999999";
|
||||
taosParseTime(t41, &time, strlen(t41), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t41, &time, strlen(t41), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 852048000999);
|
||||
|
||||
int64_t k = timezone;
|
||||
char t42[] = "1997-1-1T0:0:0.999999999Z";
|
||||
taosParseTime(t42, &time, strlen(t42), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t42, &time, strlen(t42), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 852048000999 - timezone * MILLISECOND_PER_SECOND);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// illegal timestamp format
|
||||
char t15[] = "2017-12-33 0:0:0";
|
||||
EXPECT_EQ(taosParseTime(t15, &time, strlen(t15), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t15, &time, strlen(t15), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t16[] = "2017-12-31 99:0:0";
|
||||
EXPECT_EQ(taosParseTime(t16, &time, strlen(t16), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t16, &time, strlen(t16), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t17[] = "2017-12-31T9:0:0";
|
||||
EXPECT_EQ(taosParseTime(t17, &time, strlen(t17), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t17, &time, strlen(t17), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t18[] = "2017-12-31T9:0:0.Z";
|
||||
EXPECT_EQ(taosParseTime(t18, &time, strlen(t18), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t18, &time, strlen(t18), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t19[] = "2017-12-31 9:0:0.-1";
|
||||
EXPECT_EQ(taosParseTime(t19, &time, strlen(t19), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t19, &time, strlen(t19), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t20[] = "2017-12-31 9:0:0.1+12:99";
|
||||
EXPECT_EQ(taosParseTime(t20, &time, strlen(t20), TSDB_TIME_PRECISION_MILLI), 0);
|
||||
EXPECT_EQ(taosParseTime(t20, &time, strlen(t20), TSDB_TIME_PRECISION_MILLI, 0), 0);
|
||||
EXPECT_EQ(time, 1514682000100);
|
||||
|
||||
char t21[] = "2017-12-31T9:0:0.1+12:99";
|
||||
EXPECT_EQ(taosParseTime(t21, &time, strlen(t21), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t21, &time, strlen(t21), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t22[] = "2017-12-31 9:0:0.1+13:1";
|
||||
EXPECT_EQ(taosParseTime(t22, &time, strlen(t22), TSDB_TIME_PRECISION_MILLI), 0);
|
||||
EXPECT_EQ(taosParseTime(t22, &time, strlen(t22), TSDB_TIME_PRECISION_MILLI, 0), 0);
|
||||
|
||||
char t23[] = "2017-12-31T9:0:0.1+13:1";
|
||||
EXPECT_EQ(taosParseTime(t23, &time, strlen(t23), TSDB_TIME_PRECISION_MILLI), 0);
|
||||
EXPECT_EQ(taosParseTime(t23, &time, strlen(t23), TSDB_TIME_PRECISION_MILLI, 0), 0);
|
||||
|
||||
|
||||
//======================== add some case ============================//
|
||||
|
||||
char b1[] = "9999-12-31 23:59:59.999";
|
||||
taosParseTime(b1, &time, strlen(b1), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(b1, &time, strlen(b1), TSDB_TIME_PRECISION_MILLI,0);
|
||||
EXPECT_EQ(time, 253402271999999);
|
||||
|
||||
|
||||
char b2[] = "2020-01-01 01:01:01.321";
|
||||
taosParseTime(b2, &time, strlen(b2), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(b2, &time, strlen(b2), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 1577811661321);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "America/New_York");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 18000 * MILLISECOND_PER_SECOND);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Tokyo");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, -32400 * MILLISECOND_PER_SECOND);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
|
||||
deltaToUtcInitOnce();
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, -28800 * MILLISECOND_PER_SECOND);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ extern "C" {
|
|||
|
||||
#define STR_WITH_MAXSIZE_TO_VARSTR(x, str, _maxs) \
|
||||
do { \
|
||||
char *_e = stpncpy(varDataVal(x), (str), (_maxs)); \
|
||||
char *_e = stpncpy(varDataVal(x), (str), (_maxs)-VARSTR_HEADER_SIZE); \
|
||||
varDataSetLen(x, (_e - (x)-VARSTR_HEADER_SIZE)); \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -170,6 +170,7 @@ extern char gitinfo[];
|
|||
extern char gitinfoOfInternal[];
|
||||
extern char buildinfo[];
|
||||
|
||||
extern int8_t tsDaylight;
|
||||
extern char tsTimezone[64];
|
||||
extern char tsLocale[64];
|
||||
extern char tsCharset[64]; // default encode string
|
||||
|
|
|
@ -106,7 +106,7 @@ void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, int32_t version) {
|
|||
}
|
||||
|
||||
int tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int16_t colId, int32_t bytes) {
|
||||
if (!isValidDataType(type, 0)) return -1;
|
||||
if (!isValidDataType(type)) return -1;
|
||||
|
||||
if (pBuilder->nCols >= pBuilder->tCols) {
|
||||
pBuilder->tCols *= 2;
|
||||
|
@ -589,7 +589,7 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
|
|||
if (kvRowNCols(nrow) - colIdx - 1 > 0) {
|
||||
for (int i = colIdx + 1; i < kvRowNCols(nrow); i++) {
|
||||
kvRowColIdxAt(nrow, i)->colId = kvRowColIdxAt(row, i)->colId;
|
||||
kvRowColIdxAt(nrow, i)->offset += diff;
|
||||
kvRowColIdxAt(nrow, i)->offset = kvRowColIdxAt(row, i)->offset + diff;
|
||||
}
|
||||
memcpy(kvRowColVal(nrow, kvRowColIdxAt(nrow, colIdx + 1)), kvRowColVal(row, kvRowColIdxAt(row, colIdx + 1)),
|
||||
POINTER_DISTANCE(kvRowEnd(row), kvRowColVal(row, kvRowColIdxAt(row, colIdx + 1))));
|
||||
|
|
|
@ -198,6 +198,7 @@ char tsMonitorDbName[TSDB_DB_NAME_LEN] = "log";
|
|||
char tsInternalPass[] = "secretkey";
|
||||
int32_t tsMonitorInterval = 30; // seconds
|
||||
|
||||
int8_t tsDaylight = 0;
|
||||
char tsTimezone[64] = {0};
|
||||
char tsLocale[TSDB_LOCALE_LEN] = {0};
|
||||
char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string
|
||||
|
|
|
@ -58,6 +58,7 @@ void tsSetTimeZone() {
|
|||
* (BST, +0100)
|
||||
*/
|
||||
sprintf(tsTimezone, "(%s, %s%02d00)", tzname[daylight], tz >= 0 ? "+" : "-", abs(tz));
|
||||
tsDaylight = daylight;
|
||||
|
||||
uPrint("timezone format changed to %s", tsTimezone);
|
||||
}
|
||||
|
|
|
@ -363,16 +363,8 @@ char tTokenTypeSwitcher[13] = {
|
|||
TSDB_DATA_TYPE_NCHAR, // TK_NCHAR
|
||||
};
|
||||
|
||||
bool isValidDataType(int32_t type, int32_t length) {
|
||||
if (type < TSDB_DATA_TYPE_NULL || type > TSDB_DATA_TYPE_NCHAR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
// return length >= 0 && length <= TSDB_MAX_BINARY_LEN;
|
||||
}
|
||||
|
||||
return true;
|
||||
bool isValidDataType(int32_t type) {
|
||||
return type >= TSDB_DATA_TYPE_NULL && type <= TSDB_DATA_TYPE_NCHAR;
|
||||
}
|
||||
|
||||
bool isNull(const char *val, int32_t type) {
|
||||
|
|
|
@ -256,12 +256,31 @@ static void cqProcessStreamRes(void *param, TAOS_RES *tres, TAOS_ROW row) {
|
|||
SDataRow trow = (SDataRow)pBlk->data;
|
||||
tdInitDataRow(trow, pSchema);
|
||||
|
||||
union {
|
||||
char buf[sizeof(int64_t)];
|
||||
tstr str;
|
||||
} nullVal;
|
||||
|
||||
for (int32_t i = 0; i < pSchema->numOfCols; i++) {
|
||||
STColumn *c = pSchema->columns + i;
|
||||
char* val = (char*)row[i];
|
||||
if (IS_VAR_DATA_TYPE(c->type)) {
|
||||
if (val == NULL) {
|
||||
val = nullVal.buf;
|
||||
if (c->type == TSDB_DATA_TYPE_BINARY) {
|
||||
setNull(nullVal.str.data, TSDB_DATA_TYPE_BINARY, 1);
|
||||
nullVal.str.len = 1;
|
||||
} else {
|
||||
setNull(nullVal.str.data, TSDB_DATA_TYPE_NCHAR, 4);
|
||||
nullVal.str.len = 4;
|
||||
}
|
||||
} else {
|
||||
val -= sizeof(VarDataLenT);
|
||||
}
|
||||
} else if (val == NULL) {
|
||||
val = nullVal.buf;
|
||||
setNull(val, c->type, c->bytes);
|
||||
}
|
||||
tdAppendColVal(trow, val, c->type, c->bytes, c->offset);
|
||||
}
|
||||
pBlk->len = htonl(dataRowLen(trow));
|
||||
|
|
|
@ -118,6 +118,8 @@ void dnodeDispatchToMnodeWriteQueue(SRpcMsg *pMsg) {
|
|||
|
||||
SMnodeMsg *pWrite = (SMnodeMsg *)taosAllocateQitem(sizeof(SMnodeMsg));
|
||||
mnodeCreateMsg(pWrite, pMsg);
|
||||
|
||||
dTrace("app:%p:%p, msg:%s is put into mwrite queue", pWrite->rpcMsg.ahandle, pWrite, taosMsg[pWrite->rpcMsg.msgType]);
|
||||
taosWriteQitem(tsMWriteQueue, TAOS_QTYPE_RPC, pWrite);
|
||||
}
|
||||
|
||||
|
@ -128,6 +130,7 @@ static void dnodeFreeMnodeWriteMsg(SMnodeMsg *pWrite) {
|
|||
|
||||
void dnodeSendRpcMnodeWriteRsp(void *pRaw, int32_t code) {
|
||||
SMnodeMsg *pWrite = pRaw;
|
||||
if (pWrite == NULL) return;
|
||||
if (code == TSDB_CODE_MND_ACTION_IN_PROGRESS) return;
|
||||
if (code == TSDB_CODE_MND_ACTION_NEED_REPROCESSED) {
|
||||
dnodeReprocessMnodeWriteMsg(pWrite);
|
||||
|
@ -146,19 +149,21 @@ void dnodeSendRpcMnodeWriteRsp(void *pRaw, int32_t code) {
|
|||
}
|
||||
|
||||
static void *dnodeProcessMnodeWriteQueue(void *param) {
|
||||
SMnodeMsg *pWriteMsg;
|
||||
SMnodeMsg *pWrite;
|
||||
int32_t type;
|
||||
void * unUsed;
|
||||
|
||||
while (1) {
|
||||
if (taosReadQitemFromQset(tsMWriteQset, &type, (void **)&pWriteMsg, &unUsed) == 0) {
|
||||
if (taosReadQitemFromQset(tsMWriteQset, &type, (void **)&pWrite, &unUsed) == 0) {
|
||||
dTrace("dnodeProcessMnodeWriteQueue: got no message from qset, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
dTrace("%p, msg:%s will be processed in mwrite queue", pWriteMsg->rpcMsg.ahandle, taosMsg[pWriteMsg->rpcMsg.msgType]);
|
||||
int32_t code = mnodeProcessWrite(pWriteMsg);
|
||||
dnodeSendRpcMnodeWriteRsp(pWriteMsg, code);
|
||||
dTrace("app:%p:%p, msg:%s will be processed in mwrite queue", pWrite->rpcMsg.ahandle, pWrite,
|
||||
taosMsg[pWrite->rpcMsg.msgType]);
|
||||
|
||||
int32_t code = mnodeProcessWrite(pWrite);
|
||||
dnodeSendRpcMnodeWriteRsp(pWrite, code);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -168,9 +173,15 @@ void dnodeReprocessMnodeWriteMsg(void *pMsg) {
|
|||
SMnodeMsg *pWrite = pMsg;
|
||||
|
||||
if (!mnodeIsRunning() || tsMWriteQueue == NULL) {
|
||||
dTrace("app:%p:%p, msg:%s is redirected for mnode not running, retry times:%d", pWrite->rpcMsg.ahandle, pWrite,
|
||||
taosMsg[pWrite->rpcMsg.msgType], pWrite->retry);
|
||||
|
||||
dnodeSendRedirectMsg(pMsg, true);
|
||||
dnodeFreeMnodeWriteMsg(pWrite);
|
||||
} else {
|
||||
dTrace("app:%p:%p, msg:%s is reput into mwrite queue, retry times:%d", pWrite->rpcMsg.ahandle, pWrite,
|
||||
taosMsg[pWrite->rpcMsg.msgType], pWrite->retry);
|
||||
|
||||
taosWriteQitem(tsMWriteQueue, TAOS_QTYPE_RPC, pWrite);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -617,6 +617,16 @@ static void dnodeSendStatusMsg(void *handle, void *tmrId) {
|
|||
pStatus->diskAvailable = tsAvailDataDirGB;
|
||||
pStatus->alternativeRole = (uint8_t) tsAlternativeRole;
|
||||
|
||||
// fill cluster cfg parameters
|
||||
pStatus->clusterCfg.numOfMnodes = tsNumOfMnodes;
|
||||
pStatus->clusterCfg.mnodeEqualVnodeNum = tsMnodeEqualVnodeNum;
|
||||
pStatus->clusterCfg.offlineThreshold = tsOfflineThreshold;
|
||||
pStatus->clusterCfg.statusInterval = tsStatusInterval;
|
||||
strcpy(pStatus->clusterCfg.arbitrator, tsArbitrator);
|
||||
strcpy(pStatus->clusterCfg.timezone, tsTimezone);
|
||||
strcpy(pStatus->clusterCfg.locale, tsLocale);
|
||||
strcpy(pStatus->clusterCfg.charset, tsCharset);
|
||||
|
||||
vnodeBuildStatusMsg(pStatus);
|
||||
contLen = sizeof(SDMStatusMsg) + pStatus->openVnodes * sizeof(SVnodeLoad);
|
||||
pStatus->openVnodes = htons(pStatus->openVnodes);
|
||||
|
|
|
@ -32,11 +32,11 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryTableMs
|
|||
|
||||
/**
|
||||
* Destroy QInfo object
|
||||
*
|
||||
* @param qinfo
|
||||
* @return
|
||||
* @param qinfo qhandle
|
||||
* @param fp destroy callback function, while the qhandle is destoried, invoke the fp
|
||||
* @param param free callback params
|
||||
*/
|
||||
void qDestroyQueryInfo(qinfo_t qinfo);
|
||||
void qDestroyQueryInfo(qinfo_t qinfo, void (*fp)(void*), void* param);
|
||||
|
||||
/**
|
||||
* the main query execution function, including query on both table and multitables,
|
||||
|
@ -45,7 +45,7 @@ void qDestroyQueryInfo(qinfo_t qinfo);
|
|||
* @param qinfo
|
||||
* @return
|
||||
*/
|
||||
void qTableQuery(qinfo_t qinfo);
|
||||
void qTableQuery(qinfo_t qinfo, void (*fp)(void*), void* param);
|
||||
|
||||
/**
|
||||
* Retrieve the produced results information, if current query is not paused or completed,
|
||||
|
@ -70,7 +70,8 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo);
|
|||
int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp** pRsp, int32_t* contLen);
|
||||
|
||||
/**
|
||||
* Decide if more results will be produced or not
|
||||
* 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
|
||||
|
@ -79,9 +80,12 @@ bool qHasMoreResultsToRetrieve(qinfo_t qinfo);
|
|||
|
||||
/**
|
||||
* kill current ongoing query and free query handle automatically
|
||||
* @param qinfo
|
||||
* @param qinfo qhandle
|
||||
* @param fp destroy callback function, while the qhandle is destoried, invoke the fp
|
||||
* @param param free callback params
|
||||
* @return
|
||||
*/
|
||||
int32_t qKillQuery(qinfo_t qinfo);
|
||||
int32_t qKillQuery(qinfo_t qinfo, void (*fp)(void*), void* param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef enum {
|
|||
typedef struct taosField {
|
||||
char name[65];
|
||||
uint8_t type;
|
||||
short bytes;
|
||||
uint16_t bytes;
|
||||
} TAOS_FIELD;
|
||||
|
||||
#ifdef _TD_GO_DLL_
|
||||
|
|
|
@ -156,7 +156,7 @@ typedef struct tDataTypeDescriptor {
|
|||
extern tDataTypeDescriptor tDataTypeDesc[11];
|
||||
#define POINTER_BYTES sizeof(void *) // 8 by default assert(sizeof(ptrdiff_t) == sizseof(void*)
|
||||
|
||||
bool isValidDataType(int32_t type, int32_t length);
|
||||
bool isValidDataType(int32_t type);
|
||||
bool isNull(const char *val, int32_t type);
|
||||
|
||||
void setVardataNull(char* val, int32_t type);
|
||||
|
|
|
@ -113,14 +113,19 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_QUERY_ID, 0, 0x030C, "mnode inva
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_STREAM_ID, 0, 0x030D, "mnode invalid stream id")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_CONN_ID, 0, 0x030E, "mnode invalid connection")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_OBJ_ALREADY_THERE, 0, 0x0320, "mnode object already there")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_ERROR, 0, 0x0321, "mnode sdb error")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_OBJ_ALREADY_THERE, 0, 0x0320, "[sdb] object already there")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_ERROR, 0, 0x0321, "[sdb] app error")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE, 0, 0x0322, "[sdb] invalid table type")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_OBJ_NOT_THERE, 0, 0x0323, "[sdb] object not there")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_INVAID_META_ROW, 0, 0x0324, "[sdb] invalid meta row")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SDB_INVAID_KEY_TYPE, 0, 0x0325, "[sdb] invalid key type")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_DNODE_ALREADY_EXIST, 0, 0x0330, "mnode dnode already exist")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_DNODE_NOT_EXIST, 0, 0x0331, "mnode dnode not exist")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_VGROUP_NOT_EXIST, 0, 0x0332, "mnode vgroup not exist")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_NO_REMOVE_MASTER, 0, 0x0333, "mnode cant not remove master")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_NO_ENOUGH_DNODES, 0, 0x0334, "mnode no enough dnodes")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_CLUSTER_CFG_INCONSISTENT, 0, 0x0335, "mnode cluster cfg inconsistent")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ACCT_ALREADY_EXIST, 0, 0x0340, "mnode accounts already exist")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_ACCT, 0, 0x0341, "mnode invalid account")
|
||||
|
@ -200,6 +205,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INVALID_MSG, 0, 0x0701, "query inva
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NO_DISKSPACE, 0, 0x0702, "query no diskspace")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_QRY_OUT_OF_MEMORY, 0, 0x0703, "query out of memory")
|
||||
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")
|
||||
|
||||
// grant
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_EXPIRED, 0, 0x0800, "grant expired")
|
||||
|
|
|
@ -250,7 +250,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
char tableId[TSDB_TABLE_ID_LEN];
|
||||
char db[TSDB_DB_NAME_LEN];
|
||||
char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN];
|
||||
int8_t igExists;
|
||||
int8_t getMeta;
|
||||
int16_t numOfTags;
|
||||
|
@ -268,7 +268,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
char tableId[TSDB_TABLE_ID_LEN];
|
||||
char db[TSDB_DB_NAME_LEN];
|
||||
char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN];
|
||||
int16_t type; /* operation type */
|
||||
int16_t numOfCols; /* number of schema */
|
||||
int32_t tagValLen;
|
||||
|
@ -455,7 +455,7 @@ typedef struct {
|
|||
int16_t orderType; // used in group by xx order by xxx
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
uint16_t queryType; // denote another query process
|
||||
uint32_t queryType; // denote another query process
|
||||
int16_t numOfOutput; // final output columns numbers
|
||||
int16_t tagNameRelType; // relation of tag criteria and tbname criteria
|
||||
int16_t fillType; // interpolate type
|
||||
|
@ -556,6 +556,17 @@ typedef struct {
|
|||
SDMMnodeInfo nodeInfos[TSDB_MAX_REPLICA];
|
||||
} SDMMnodeInfos;
|
||||
|
||||
typedef struct {
|
||||
int32_t numOfMnodes; // tsNumOfMnodes
|
||||
int32_t mnodeEqualVnodeNum; // tsMnodeEqualVnodeNum
|
||||
int32_t offlineThreshold; // tsOfflineThreshold
|
||||
int32_t statusInterval; // tsStatusInterval
|
||||
char arbitrator[TSDB_EP_LEN]; // tsArbitrator
|
||||
char timezone[64]; // tsTimezone
|
||||
char locale[TSDB_LOCALE_LEN]; // tsLocale
|
||||
char charset[TSDB_LOCALE_LEN]; // tsCharset
|
||||
} SClusterCfg;
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
int32_t dnodeId;
|
||||
|
@ -568,6 +579,7 @@ typedef struct {
|
|||
float diskAvailable; // GB
|
||||
uint8_t alternativeRole;
|
||||
uint8_t reserve[15];
|
||||
SClusterCfg clusterCfg;
|
||||
SVnodeLoad load[];
|
||||
} SDMStatusMsg;
|
||||
|
||||
|
@ -670,7 +682,7 @@ typedef struct {
|
|||
*/
|
||||
typedef struct {
|
||||
int8_t type;
|
||||
char db[TSDB_DB_NAME_LEN];
|
||||
char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN];
|
||||
uint16_t payloadLen;
|
||||
char payload[];
|
||||
} SCMShowMsg;
|
||||
|
|
|
@ -78,12 +78,13 @@ void rpcClose(void *);
|
|||
void *rpcMallocCont(int contLen);
|
||||
void rpcFreeCont(void *pCont);
|
||||
void *rpcReallocCont(void *ptr, int contLen);
|
||||
void rpcSendRequest(void *thandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg);
|
||||
void *rpcSendRequest(void *thandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg);
|
||||
void rpcSendResponse(const SRpcMsg *pMsg);
|
||||
void rpcSendRedirectRsp(void *pConn, const SRpcIpSet *pIpSet);
|
||||
int rpcGetConnInfo(void *thandle, SRpcConnInfo *pInfo);
|
||||
void rpcSendRecv(void *shandle, SRpcIpSet *pIpSet, const SRpcMsg *pReq, SRpcMsg *pRsp);
|
||||
void rpcReportProgress(void *pConn, char *pCont, int contLen);
|
||||
int rpcReportProgress(void *pConn, char *pCont, int contLen);
|
||||
void rpcCanelRequest(void *pContext);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -469,7 +469,6 @@ static int dumpResultToFile(const char* fname, TAOS_RES* result) {
|
|||
} while( row != NULL);
|
||||
|
||||
fclose(fp);
|
||||
taos_free_result(result);
|
||||
return numOfRows;
|
||||
}
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ void *deleteTable();
|
|||
|
||||
void *asyncWrite(void *sarg);
|
||||
|
||||
void generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary);
|
||||
int generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary);
|
||||
|
||||
void rand_string(char *str, int size);
|
||||
|
||||
|
@ -817,7 +817,7 @@ void queryDB(TAOS *taos, char *command) {
|
|||
i--;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (code != 0) {
|
||||
fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql));
|
||||
taos_free_result(pSql);
|
||||
|
||||
|
@ -846,14 +846,19 @@ void *syncWrite(void *sarg) {
|
|||
int k;
|
||||
for (k = 0; k < winfo->nrecords_per_request;) {
|
||||
int rand_num = rand() % 100;
|
||||
if (winfo->data_of_order ==1 && rand_num < winfo->data_of_rate)
|
||||
{
|
||||
int len = -1;
|
||||
if (winfo->data_of_order ==1 && rand_num < winfo->data_of_rate) {
|
||||
long d = tmp_time - rand() % 1000000 + rand_num;
|
||||
generateData(data, data_type, ncols_per_record, d, len_of_binary);
|
||||
} else
|
||||
{
|
||||
generateData(data, data_type, ncols_per_record, tmp_time += 1000, len_of_binary);
|
||||
len = generateData(data, data_type, ncols_per_record, d, len_of_binary);
|
||||
} else {
|
||||
len = generateData(data, data_type, ncols_per_record, tmp_time += 1000, len_of_binary);
|
||||
}
|
||||
|
||||
//assert(len + pstr - buffer < BUFFER_SIZE);
|
||||
if (len + pstr - buffer >= BUFFER_SIZE) { // too long
|
||||
break;
|
||||
}
|
||||
|
||||
pstr += sprintf(pstr, " %s", data);
|
||||
inserted++;
|
||||
k++;
|
||||
|
@ -968,7 +973,7 @@ double getCurrentTime() {
|
|||
return tv.tv_sec + tv.tv_usec / 1E6;
|
||||
}
|
||||
|
||||
void generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary) {
|
||||
int32_t generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary) {
|
||||
memset(res, 0, MAX_DATA_SIZE);
|
||||
char *pstr = res;
|
||||
pstr += sprintf(pstr, "(%" PRId64, timestamp);
|
||||
|
@ -1002,9 +1007,16 @@ void generateData(char *res, char **data_type, int num_of_cols, int64_t timestam
|
|||
rand_string(s, len_of_binary);
|
||||
pstr += sprintf(pstr, ", \"%s\"", s);
|
||||
}
|
||||
|
||||
if (pstr - res > MAX_DATA_SIZE) {
|
||||
perror("column length too long, abort");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
pstr += sprintf(pstr, ")");
|
||||
|
||||
return pstr - res;
|
||||
}
|
||||
|
||||
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK1234567890";
|
||||
|
|
|
@ -47,7 +47,7 @@ void mnodeDecDnodeRef(SDnodeObj *pDnode);
|
|||
void * mnodeGetDnode(int32_t dnodeId);
|
||||
void * mnodeGetDnodeByEp(char *ep);
|
||||
void mnodeUpdateDnode(SDnodeObj *pDnode);
|
||||
int32_t mnodeDropDnode(SDnodeObj *pDnode);
|
||||
int32_t mnodeDropDnode(SDnodeObj *pDnode, void *pMsg);
|
||||
|
||||
extern int32_t tsAccessSquence;
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ extern int32_t sdbDebugFlag;
|
|||
#define mLWarn(...) { monitorSaveLog(1, __VA_ARGS__); mWarn(__VA_ARGS__) }
|
||||
#define mLPrint(...) { monitorSaveLog(0, __VA_ARGS__); mPrint(__VA_ARGS__) }
|
||||
|
||||
#define sdbError(...) { if (sdbDebugFlag & DEBUG_ERROR) { taosPrintLog("ERROR MND-SDB ", 255, __VA_ARGS__); }}
|
||||
#define sdbWarn(...) { if (sdbDebugFlag & DEBUG_WARN) { taosPrintLog("WARN MND-SDB ", sdbDebugFlag, __VA_ARGS__); }}
|
||||
#define sdbTrace(...) { if (sdbDebugFlag & DEBUG_TRACE) { taosPrintLog("MND-SDB ", sdbDebugFlag, __VA_ARGS__);}}
|
||||
#define sdbPrint(...) { taosPrintLog("MND-SDB ", 255, __VA_ARGS__); }
|
||||
#define sdbError(...) { if (sdbDebugFlag & DEBUG_ERROR) { taosPrintLog("ERROR SDB ", 255, __VA_ARGS__); }}
|
||||
#define sdbWarn(...) { if (sdbDebugFlag & DEBUG_WARN) { taosPrintLog("WARN SDB ", sdbDebugFlag, __VA_ARGS__); }}
|
||||
#define sdbTrace(...) { if (sdbDebugFlag & DEBUG_TRACE) { taosPrintLog("SDB ", sdbDebugFlag, __VA_ARGS__);}}
|
||||
#define sdbPrint(...) { taosPrintLog("SDB ", 255, __VA_ARGS__); }
|
||||
|
||||
#define sdbLError(...) { monitorSaveLog(2, __VA_ARGS__); sdbError(__VA_ARGS__) }
|
||||
#define sdbLWarn(...) { monitorSaveLog(1, __VA_ARGS__); sdbWarn(__VA_ARGS__) }
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SMnodeMsg;
|
||||
|
||||
typedef enum {
|
||||
SDB_TABLE_DNODE = 0,
|
||||
SDB_TABLE_MNODE = 1,
|
||||
|
@ -48,8 +50,11 @@ typedef struct {
|
|||
ESdbOper type;
|
||||
void * table;
|
||||
void * pObj;
|
||||
int32_t rowSize;
|
||||
void * rowData;
|
||||
int32_t rowSize;
|
||||
int32_t retCode; // for callback in sdb queue
|
||||
int32_t (*cb)(struct SMnodeMsg *pMsg, int32_t code);
|
||||
struct SMnodeMsg *pMsg;
|
||||
} SSdbOper;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -28,7 +28,8 @@ void * mnodeGetNextUser(void *pIter, SUserObj **pUser);
|
|||
void mnodeIncUserRef(SUserObj *pUser);
|
||||
void mnodeDecUserRef(SUserObj *pUser);
|
||||
SUserObj *mnodeGetUserFromConn(void *pConn);
|
||||
int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass);
|
||||
char * mnodeGetUserFromMsg(void *pMnodeMsg);
|
||||
int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass, void *pMsg);
|
||||
void mnodeDropAllUsers(SAcctObj *pAcct);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -78,7 +78,9 @@ static int32_t mnodeAcctActionDecode(SSdbOper *pOper) {
|
|||
}
|
||||
|
||||
static int32_t mnodeAcctActionRestored() {
|
||||
if (dnodeIsFirstDeploy()) {
|
||||
int32_t numOfRows = sdbGetNumOfRows(tsAcctSdb);
|
||||
if (numOfRows <= 0 && dnodeIsFirstDeploy()) {
|
||||
mPrint("dnode first deploy, create root acct");
|
||||
int32_t code = mnodeCreateRootAcct();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
mError("failed to create root account, reason:%s", tstrerror(code));
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
static void * tsDbSdb = NULL;
|
||||
static int32_t tsDbUpdateSize;
|
||||
|
||||
static int32_t mnodeCreateDb(SAcctObj *pAcct, SCMCreateDbMsg *pCreate);
|
||||
static int32_t mnodeCreateDb(SAcctObj *pAcct, SCMCreateDbMsg *pCreate, void *pMsg);
|
||||
static int32_t mnodeDropDb(SMnodeMsg *newMsg);
|
||||
static int32_t mnodeSetDbDropping(SDbObj *pDb);
|
||||
static int32_t mnodeGetDbMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn);
|
||||
|
@ -84,8 +84,11 @@ static int32_t mnodeDbActionDelete(SSdbOper *pOper) {
|
|||
mnodeDropAllChildTables(pDb);
|
||||
mnodeDropAllSuperTables(pDb);
|
||||
mnodeDropAllDbVgroups(pDb);
|
||||
|
||||
if (pAcct) {
|
||||
mnodeDropDbFromAcct(pAcct, pDb);
|
||||
mnodeDecAcctRef(pAcct);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -308,7 +311,7 @@ static void mnodeSetDefaultDbCfg(SDbCfg *pCfg) {
|
|||
if (pCfg->replications < 0) pCfg->replications = tsReplications;
|
||||
}
|
||||
|
||||
static int32_t mnodeCreateDb(SAcctObj *pAcct, SCMCreateDbMsg *pCreate) {
|
||||
static int32_t mnodeCreateDb(SAcctObj *pAcct, SCMCreateDbMsg *pCreate, void *pMsg) {
|
||||
int32_t code = acctCheck(pAcct, ACCT_GRANT_DB);
|
||||
if (code != 0) return code;
|
||||
|
||||
|
@ -361,12 +364,15 @@ static int32_t mnodeCreateDb(SAcctObj *pAcct, SCMCreateDbMsg *pCreate) {
|
|||
.table = tsDbSdb,
|
||||
.pObj = pDb,
|
||||
.rowSize = sizeof(SDbObj),
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
code = sdbInsertRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tfree(pDb);
|
||||
code = TSDB_CODE_MND_SDB_ERROR;
|
||||
} else {
|
||||
mLPrint("db:%s, is created by %s", pDb->name, mnodeGetUserFromMsg(pMsg));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -610,7 +616,7 @@ static int32_t mnodeRetrieveDbs(SShowObj *pShow, char *data, int32_t rows, void
|
|||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
||||
char* name = mnodeGetDbStr(pDb->name);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, name, TSDB_DB_NAME_LEN - 1);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, name, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
@ -768,12 +774,7 @@ static int32_t mnodeProcessCreateDbMsg(SMnodeMsg *pMsg) {
|
|||
} else if (!pMsg->pUser->writeAuth) {
|
||||
code = TSDB_CODE_MND_NO_RIGHTS;
|
||||
} else {
|
||||
code = mnodeCreateDb(pMsg->pUser->pAcct, pCreate);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("db:%s, is created by %s", pCreate->db, pMsg->pUser->user);
|
||||
} else {
|
||||
mError("db:%s, failed to create, reason:%s", pCreate->db, tstrerror(code));
|
||||
}
|
||||
code = mnodeCreateDb(pMsg->pUser->pAcct, pCreate, pMsg);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -890,7 +891,31 @@ static SDbCfg mnodeGetAlterDbOption(SDbObj *pDb, SCMAlterDbMsg *pAlter) {
|
|||
return newCfg;
|
||||
}
|
||||
|
||||
static int32_t mnodeAlterDb(SDbObj *pDb, SCMAlterDbMsg *pAlter) {
|
||||
static int32_t mnodeAlterDbCb(SMnodeMsg *pMsg, int32_t code) {
|
||||
if (code != TSDB_CODE_SUCCESS) return code;
|
||||
SDbObj *pDb = pMsg->pDb;
|
||||
|
||||
void *pIter = NULL;
|
||||
while (1) {
|
||||
SVgObj *pVgroup = NULL;
|
||||
pIter = mnodeGetNextVgroup(pIter, &pVgroup);
|
||||
if (pVgroup == NULL) break;
|
||||
if (pVgroup->pDb == pDb) {
|
||||
mnodeSendCreateVgroupMsg(pVgroup, NULL);
|
||||
}
|
||||
mnodeDecVgroupRef(pVgroup);
|
||||
}
|
||||
sdbFreeIter(pIter);
|
||||
|
||||
mTrace("db:%s, all vgroups is altered", pDb->name);
|
||||
mLPrint("db:%s, is alterd by %s", pDb->name, mnodeGetUserFromMsg(pMsg));
|
||||
|
||||
balanceNotify();
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t mnodeAlterDb(SDbObj *pDb, SCMAlterDbMsg *pAlter, void *pMsg) {
|
||||
SDbCfg newCfg = mnodeGetAlterDbOption(pDb, pAlter);
|
||||
if (terrno != TSDB_CODE_SUCCESS) {
|
||||
return terrno;
|
||||
|
@ -901,38 +926,24 @@ static int32_t mnodeAlterDb(SDbObj *pDb, SCMAlterDbMsg *pAlter) {
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t oldReplica = pDb->cfg.replications;
|
||||
|
||||
if (memcmp(&newCfg, &pDb->cfg, sizeof(SDbCfg)) != 0) {
|
||||
pDb->cfg = newCfg;
|
||||
pDb->cfgVersion++;
|
||||
SSdbOper oper = {
|
||||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsDbSdb,
|
||||
.pObj = pDb
|
||||
.pObj = pDb,
|
||||
.pMsg = pMsg,
|
||||
.cb = mnodeAlterDbCb
|
||||
};
|
||||
|
||||
int32_t code = sdbUpdateRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_MND_SDB_ERROR;
|
||||
code = sdbUpdateRow(&oper);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
}
|
||||
|
||||
void *pIter = NULL;
|
||||
while (1) {
|
||||
SVgObj *pVgroup = NULL;
|
||||
pIter = mnodeGetNextVgroup(pIter, &pVgroup);
|
||||
if (pVgroup == NULL) break;
|
||||
mnodeSendCreateVgroupMsg(pVgroup, NULL);
|
||||
mnodeDecVgroupRef(pVgroup);
|
||||
}
|
||||
sdbFreeIter(pIter);
|
||||
|
||||
if (oldReplica != pDb->cfg.replications) {
|
||||
balanceNotify();
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mnodeProcessAlterDbMsg(SMnodeMsg *pMsg) {
|
||||
|
@ -945,14 +956,7 @@ static int32_t mnodeProcessAlterDbMsg(SMnodeMsg *pMsg) {
|
|||
return TSDB_CODE_MND_INVALID_DB;
|
||||
}
|
||||
|
||||
int32_t code = mnodeAlterDb(pMsg->pDb, pAlter);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
mError("db:%s, failed to alter, invalid db option", pAlter->db);
|
||||
return code;
|
||||
}
|
||||
|
||||
mTrace("db:%s, all vgroups is altered", pMsg->pDb->name);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
return mnodeAlterDb(pMsg->pDb, pAlter, pMsg);
|
||||
}
|
||||
|
||||
static int32_t mnodeDropDb(SMnodeMsg *pMsg) {
|
||||
|
@ -962,11 +966,14 @@ static int32_t mnodeDropDb(SMnodeMsg *pMsg) {
|
|||
SSdbOper oper = {
|
||||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsDbSdb,
|
||||
.pObj = pDb
|
||||
.pObj = pDb,
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
int32_t code = sdbDeleteRow(&oper);
|
||||
if (code != 0) {
|
||||
code = TSDB_CODE_MND_SDB_ERROR;
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("db:%s, is dropped by %s", pDb->name, mnodeGetUserFromMsg(pMsg));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return code;
|
||||
|
|
|
@ -44,7 +44,7 @@ static int32_t tsDnodeUpdateSize = 0;
|
|||
extern void * tsMnodeSdb;
|
||||
extern void * tsVgroupSdb;
|
||||
|
||||
static int32_t mnodeCreateDnode(char *ep);
|
||||
static int32_t mnodeCreateDnode(char *ep, SMnodeMsg *pMsg);
|
||||
static int32_t mnodeProcessCreateDnodeMsg(SMnodeMsg *pMsg);
|
||||
static int32_t mnodeProcessDropDnodeMsg(SMnodeMsg *pMsg);
|
||||
static int32_t mnodeProcessCfgDnodeMsg(SMnodeMsg *pMsg);
|
||||
|
@ -117,7 +117,8 @@ static int32_t mnodeDnodeActionDecode(SSdbOper *pOper) {
|
|||
static int32_t mnodeDnodeActionRestored() {
|
||||
int32_t numOfRows = sdbGetNumOfRows(tsDnodeSdb);
|
||||
if (numOfRows <= 0 && dnodeIsFirstDeploy()) {
|
||||
mnodeCreateDnode(tsLocalEp);
|
||||
mPrint("dnode first deploy, create dnode:%s", tsLocalEp);
|
||||
mnodeCreateDnode(tsLocalEp, NULL);
|
||||
SDnodeObj *pDnode = mnodeGetDnodeByEp(tsLocalEp);
|
||||
mnodeAddMnode(pDnode->dnodeId);
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
|
@ -277,6 +278,20 @@ static void mnodeProcessCfgDnodeMsgRsp(SRpcMsg *rpcMsg) {
|
|||
mPrint("cfg dnode rsp is received");
|
||||
}
|
||||
|
||||
static bool mnodeCheckClusterCfgPara(const SClusterCfg *clusterCfg) {
|
||||
if (clusterCfg->numOfMnodes != tsNumOfMnodes) return false;
|
||||
if (clusterCfg->mnodeEqualVnodeNum != tsMnodeEqualVnodeNum) return false;
|
||||
if (clusterCfg->offlineThreshold != tsOfflineThreshold) return false;
|
||||
if (clusterCfg->statusInterval != tsStatusInterval) return false;
|
||||
|
||||
if (0 != strncasecmp(clusterCfg->arbitrator, tsArbitrator, strlen(tsArbitrator))) return false;
|
||||
if (0 != strncasecmp(clusterCfg->timezone, tsTimezone, strlen(tsTimezone))) return false;
|
||||
if (0 != strncasecmp(clusterCfg->locale, tsLocale, strlen(tsLocale))) return false;
|
||||
if (0 != strncasecmp(clusterCfg->charset, tsCharset, strlen(tsCharset))) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
||||
SDMStatusMsg *pStatus = pMsg->rpcMsg.pCont;
|
||||
pStatus->dnodeId = htonl(pStatus->dnodeId);
|
||||
|
@ -312,7 +327,6 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
pDnode->alternativeRole = pStatus->alternativeRole;
|
||||
pDnode->totalVnodes = pStatus->numOfTotalVnodes;
|
||||
pDnode->moduleStatus = pStatus->moduleStatus;
|
||||
pDnode->lastAccess = tsAccessSquence;
|
||||
|
||||
if (pStatus->dnodeId == 0) {
|
||||
mTrace("dnode:%d %s, first access", pDnode->dnodeId, pDnode->dnodeEp);
|
||||
|
@ -338,6 +352,14 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
}
|
||||
|
||||
if (pDnode->status == TAOS_DN_STATUS_OFFLINE) {
|
||||
// Verify whether the cluster parameters are consistent when status change from offline to ready
|
||||
bool ret = mnodeCheckClusterCfgPara(&(pStatus->clusterCfg));
|
||||
if (false == ret) {
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
mError("dnode %s cluster cfg parameters inconsistent", pStatus->dnodeEp);
|
||||
return TSDB_CODE_MND_CLUSTER_CFG_INCONSISTENT;
|
||||
}
|
||||
|
||||
mTrace("dnode:%d, from offline to online", pDnode->dnodeId);
|
||||
pDnode->status = TAOS_DN_STATUS_READY;
|
||||
balanceUpdateMnode();
|
||||
|
@ -352,6 +374,8 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
return TSDB_CODE_MND_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pDnode->lastAccess = tsAccessSquence;
|
||||
|
||||
mnodeGetMnodeInfos(&pRsp->mnodes);
|
||||
|
||||
pRsp->dnodeCfg.dnodeId = htonl(pDnode->dnodeId);
|
||||
|
@ -368,7 +392,7 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t mnodeCreateDnode(char *ep) {
|
||||
static int32_t mnodeCreateDnode(char *ep, SMnodeMsg *pMsg) {
|
||||
int32_t grantCode = grantCheck(TSDB_GRANT_DNODE);
|
||||
if (grantCode != TSDB_CODE_SUCCESS) {
|
||||
return grantCode;
|
||||
|
@ -392,7 +416,8 @@ static int32_t mnodeCreateDnode(char *ep) {
|
|||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsDnodeSdb,
|
||||
.pObj = pDnode,
|
||||
.rowSize = sizeof(SDnodeObj)
|
||||
.rowSize = sizeof(SDnodeObj),
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
int32_t code = sdbInsertRow(&oper);
|
||||
|
@ -400,30 +425,32 @@ static int32_t mnodeCreateDnode(char *ep) {
|
|||
int dnodeId = pDnode->dnodeId;
|
||||
tfree(pDnode);
|
||||
mError("failed to create dnode:%d, result:%s", dnodeId, tstrerror(code));
|
||||
return TSDB_CODE_MND_SDB_ERROR;
|
||||
} else {
|
||||
mPrint("dnode:%d is created, result:%s", pDnode->dnodeId, tstrerror(code));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
mPrint("dnode:%d is created, result:%s", pDnode->dnodeId, tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t mnodeDropDnode(SDnodeObj *pDnode) {
|
||||
int32_t mnodeDropDnode(SDnodeObj *pDnode, void *pMsg) {
|
||||
SSdbOper oper = {
|
||||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsDnodeSdb,
|
||||
.pObj = pDnode
|
||||
.pObj = pDnode,
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
int32_t code = sdbDeleteRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
code = TSDB_CODE_MND_SDB_ERROR;
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("dnode:%d, is dropped from cluster, result:%s", pDnode->dnodeId, tstrerror(code));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
mLPrint("dnode:%d, is dropped from cluster, result:%s", pDnode->dnodeId, tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mnodeDropDnodeByEp(char *ep) {
|
||||
static int32_t mnodeDropDnodeByEp(char *ep, SMnodeMsg *pMsg) {
|
||||
SDnodeObj *pDnode = mnodeGetDnodeByEp(ep);
|
||||
if (pDnode == NULL) {
|
||||
mError("dnode:%s, is not exist", ep);
|
||||
|
@ -438,7 +465,7 @@ static int32_t mnodeDropDnodeByEp(char *ep) {
|
|||
|
||||
mPrint("dnode:%d, start to drop it", pDnode->dnodeId);
|
||||
#ifndef _SYNC
|
||||
return mnodeDropDnode(pDnode);
|
||||
return mnodeDropDnode(pDnode, pMsg);
|
||||
#else
|
||||
return balanceDropDnode(pDnode);
|
||||
#endif
|
||||
|
@ -450,17 +477,7 @@ static int32_t mnodeProcessCreateDnodeMsg(SMnodeMsg *pMsg) {
|
|||
if (strcmp(pMsg->pUser->user, "root") != 0) {
|
||||
return TSDB_CODE_MND_NO_RIGHTS;
|
||||
} else {
|
||||
int32_t code = mnodeCreateDnode(pCreate->ep);
|
||||
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
SDnodeObj *pDnode = mnodeGetDnodeByEp(pCreate->ep);
|
||||
mLPrint("dnode:%d, %s is created by %s", pDnode->dnodeId, pCreate->ep, pMsg->pUser->user);
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
} else {
|
||||
mError("failed to create dnode:%s, reason:%s", pCreate->ep, tstrerror(code));
|
||||
}
|
||||
|
||||
return code;
|
||||
return mnodeCreateDnode(pCreate->ep, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,15 +487,7 @@ static int32_t mnodeProcessDropDnodeMsg(SMnodeMsg *pMsg) {
|
|||
if (strcmp(pMsg->pUser->user, "root") != 0) {
|
||||
return TSDB_CODE_MND_NO_RIGHTS;
|
||||
} else {
|
||||
int32_t code = mnodeDropDnodeByEp(pDrop->ep);
|
||||
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("dnode:%s is dropped by %s", pDrop->ep, pMsg->pUser->user);
|
||||
} else {
|
||||
mError("failed to drop dnode:%s, reason:%s", pDrop->ep, tstrerror(code));
|
||||
}
|
||||
|
||||
return code;
|
||||
return mnodeDropDnodeByEp(pDrop->ep, pMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,7 +579,7 @@ static int32_t mnodeRetrieveDnodes(SShowObj *pShow, char *data, int32_t rows, vo
|
|||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDnode->dnodeEp, pShow->bytes[cols] - VARSTR_HEADER_SIZE);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDnode->dnodeEp, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
|
|
@ -401,9 +401,9 @@ static int32_t mnodeRetrieveMnodes(SShowObj *pShow, char *data, int32_t rows, vo
|
|||
|
||||
SDnodeObj *pDnode = mnodeGetDnode(pMnode->mnodeId);
|
||||
if (pDnode != NULL) {
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDnode->dnodeEp, pShow->bytes[cols] - VARSTR_HEADER_SIZE);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDnode->dnodeEp, pShow->bytes[cols]);
|
||||
} else {
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, "invalid ep", pShow->bytes[cols] - VARSTR_HEADER_SIZE);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, "invalid ep", pShow->bytes[cols]);
|
||||
}
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
|
||||
|
@ -411,7 +411,7 @@ static int32_t mnodeRetrieveMnodes(SShowObj *pShow, char *data, int32_t rows, vo
|
|||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
char* roles = mnodeGetMnodeRoleStr(pMnode->role);
|
||||
STR_TO_VARSTR(pWrite, roles);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, roles, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define CONN_KEEP_TIME (tsShellActivityTimer * 3)
|
||||
#define CONN_CHECK_TIME (tsShellActivityTimer * 2)
|
||||
#define QUERY_ID_SIZE 20
|
||||
#define QUERY_STREAM_SAVE_SIZE 20
|
||||
|
||||
extern void *tsMnodeTmr;
|
||||
static SCacheObj *tsMnodeConnCache = NULL;
|
||||
|
@ -138,7 +139,7 @@ SConnObj *mnodeAccquireConn(uint32_t connId, char *user, uint32_t ip, uint16_t p
|
|||
static void mnodeFreeConn(void *data) {
|
||||
SConnObj *pConn = data;
|
||||
tfree(pConn->pQueries);
|
||||
tfree(pConn->pQueries);
|
||||
tfree(pConn->pStreams);
|
||||
|
||||
mTrace("connId:%d, is destroyed", pConn->connId);
|
||||
}
|
||||
|
@ -235,14 +236,12 @@ static int32_t mnodeRetrieveConns(SShowObj *pShow, char *data, int32_t rows, voi
|
|||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
size_t size = sizeof(pConnObj->user);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port);
|
||||
size = sizeof(ipStr);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
@ -266,16 +265,27 @@ static int32_t mnodeRetrieveConns(SShowObj *pShow, char *data, int32_t rows, voi
|
|||
// not thread safe, need optimized
|
||||
int32_t mnodeSaveQueryStreamList(SConnObj *pConn, SCMHeartBeatMsg *pHBMsg) {
|
||||
pConn->numOfQueries = htonl(pHBMsg->numOfQueries);
|
||||
if (pConn->numOfQueries > 0 && pConn->numOfQueries < 20) {
|
||||
pConn->pQueries = calloc(sizeof(SQueryDesc), pConn->numOfQueries);
|
||||
memcpy(pConn->pQueries, pHBMsg->pData, pConn->numOfQueries * sizeof(SQueryDesc));
|
||||
if (pConn->numOfQueries > 0) {
|
||||
if (pConn->pQueries == NULL) {
|
||||
pConn->pQueries = calloc(sizeof(SQueryDesc), QUERY_STREAM_SAVE_SIZE);
|
||||
}
|
||||
|
||||
int32_t saveSize = MIN(QUERY_STREAM_SAVE_SIZE, pConn->numOfQueries) * sizeof(SQueryDesc);
|
||||
if (saveSize > 0 && pConn->pQueries != NULL) {
|
||||
memcpy(pConn->pQueries, pHBMsg->pData, saveSize);
|
||||
}
|
||||
}
|
||||
|
||||
pConn->numOfStreams = htonl(pHBMsg->numOfStreams);
|
||||
if (pConn->numOfStreams > 0 && pConn->numOfStreams < 20) {
|
||||
pConn->pStreams = calloc(sizeof(SStreamDesc), pConn->numOfStreams);
|
||||
memcpy(pConn->pStreams, pHBMsg->pData + pConn->numOfQueries * sizeof(SQueryDesc),
|
||||
pConn->numOfStreams * sizeof(SStreamDesc));
|
||||
if (pConn->numOfStreams > 0) {
|
||||
if (pConn->pStreams == NULL) {
|
||||
pConn->pStreams = calloc(sizeof(SStreamDesc), QUERY_STREAM_SAVE_SIZE);
|
||||
}
|
||||
|
||||
int32_t saveSize = MIN(QUERY_STREAM_SAVE_SIZE, pConn->numOfStreams) * sizeof(SStreamDesc);
|
||||
if (saveSize > 0 && pConn->pStreams != NULL) {
|
||||
memcpy(pConn->pStreams, pHBMsg->pData + pConn->numOfQueries * sizeof(SQueryDesc), saveSize);
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -356,18 +366,16 @@ static int32_t mnodeRetrieveQueries(SShowObj *pShow, char *data, int32_t rows, v
|
|||
|
||||
snprintf(ipStr, QUERY_ID_SIZE + 1, "%u:%u", pConnObj->connId, htonl(pDesc->queryId));
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, QUERY_ID_SIZE);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
size_t size = sizeof(pConnObj->user);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port);
|
||||
size = sizeof(ipStr);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
@ -379,7 +387,7 @@ static int32_t mnodeRetrieveQueries(SShowObj *pShow, char *data, int32_t rows, v
|
|||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDesc->sql, TSDB_SHOW_SQL_LEN);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDesc->sql, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
numOfRows++;
|
||||
|
@ -479,18 +487,16 @@ static int32_t mnodeRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, v
|
|||
|
||||
snprintf(ipStr, QUERY_ID_SIZE + 1, "%u:%u", pConnObj->connId, htonl(pDesc->streamId));
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, QUERY_ID_SIZE);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
size_t size = sizeof(pConnObj->user);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port);
|
||||
size = sizeof(ipStr);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
@ -506,7 +512,7 @@ static int32_t mnodeRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, v
|
|||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDesc->sql, TSDB_SHOW_SQL_LEN);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDesc->sql, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "tsync.h"
|
||||
#include "tglobal.h"
|
||||
#include "dnode.h"
|
||||
#include "mnode.h"
|
||||
#include "mnodeDef.h"
|
||||
#include "mnodeInt.h"
|
||||
#include "mnodeMnode.h"
|
||||
|
@ -31,6 +32,7 @@
|
|||
#include "mnodeSdb.h"
|
||||
|
||||
#define SDB_TABLE_LEN 12
|
||||
#define SDB_SYNC_HACK 16
|
||||
|
||||
typedef enum {
|
||||
SDB_ACTION_INSERT,
|
||||
|
@ -83,8 +85,29 @@ typedef struct {
|
|||
void * row;
|
||||
} SSdbRow;
|
||||
|
||||
typedef struct {
|
||||
pthread_t thread;
|
||||
int32_t workerId;
|
||||
} SSdbWriteWorker;
|
||||
|
||||
typedef struct {
|
||||
int32_t num;
|
||||
SSdbWriteWorker *writeWorker;
|
||||
} SSdbWriteWorkerPool;
|
||||
|
||||
static SSdbObject tsSdbObj = {0};
|
||||
static taos_qset tsSdbWriteQset;
|
||||
static taos_qall tsSdbWriteQall;
|
||||
static taos_queue tsSdbWriteQueue;
|
||||
static SSdbWriteWorkerPool tsSdbPool;
|
||||
|
||||
static int sdbWrite(void *param, void *data, int type);
|
||||
static int sdbWriteToQueue(void *param, void *data, int type);
|
||||
static void * sdbWorkerFp(void *param);
|
||||
static int32_t sdbInitWriteWorker();
|
||||
static void sdbCleanupWriteWorker();
|
||||
static int32_t sdbAllocWriteQueue();
|
||||
static void sdbFreeWritequeue();
|
||||
|
||||
int32_t sdbGetId(void *handle) {
|
||||
return ((SSdbTable *)handle)->autoIndex;
|
||||
|
@ -302,7 +325,7 @@ void sdbUpdateSync() {
|
|||
syncInfo.ahandle = NULL;
|
||||
syncInfo.getWalInfo = sdbGetWalInfo;
|
||||
syncInfo.getFileInfo = sdbGetFileInfo;
|
||||
syncInfo.writeToCache = sdbWrite;
|
||||
syncInfo.writeToCache = sdbWriteToQueue;
|
||||
syncInfo.confirmForward = sdbConfirmForward;
|
||||
syncInfo.notifyRole = sdbNotifyRole;
|
||||
tsSdbObj.cfg = syncCfg;
|
||||
|
@ -319,6 +342,10 @@ int32_t sdbInit() {
|
|||
pthread_mutex_init(&tsSdbObj.mutex, NULL);
|
||||
sem_init(&tsSdbObj.sem, 0, 0);
|
||||
|
||||
if (sdbInitWriteWorker() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sdbInitWal() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -340,6 +367,8 @@ void sdbCleanUp() {
|
|||
|
||||
tsSdbObj.status = SDB_STATUS_CLOSING;
|
||||
|
||||
sdbCleanupWriteWorker();
|
||||
|
||||
if (tsSdbObj.sync) {
|
||||
syncStop(tsSdbObj.sync);
|
||||
tsSdbObj.sync = NULL;
|
||||
|
@ -494,6 +523,7 @@ static int32_t sdbUpdateHash(SSdbTable *pTable, SSdbOper *pOper) {
|
|||
}
|
||||
|
||||
static int sdbWrite(void *param, void *data, int type) {
|
||||
SSdbOper *pOper = param;
|
||||
SWalHead *pHead = data;
|
||||
int32_t tableId = pHead->msgType / 10;
|
||||
int32_t action = pHead->msgType % 10;
|
||||
|
@ -531,21 +561,22 @@ static int sdbWrite(void *param, void *data, int type) {
|
|||
pthread_mutex_unlock(&tsSdbObj.mutex);
|
||||
return code;
|
||||
}
|
||||
walFsync(tsSdbObj.wal);
|
||||
|
||||
code = sdbForwardToPeer(pHead);
|
||||
pthread_mutex_unlock(&tsSdbObj.mutex);
|
||||
|
||||
// from app, oper is created
|
||||
if (param != NULL) {
|
||||
//sdbTrace("request from app is disposed, version:%" PRIu64 " code:%s", pHead->version, tstrerror(code));
|
||||
if (pOper != NULL) {
|
||||
sdbTrace("record from app is disposed, version:%" PRIu64 " result:%s", pHead->version, tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
// from wal or forward msg, oper not created, should add into hash
|
||||
if (tsSdbObj.sync != NULL) {
|
||||
sdbTrace("forward request is received, version:%" PRIu64 " result:%s, confirm it", pHead->version, tstrerror(code));
|
||||
sdbTrace("record from wal forward is disposed, version:%" PRIu64 " confirm it", pHead->version);
|
||||
syncConfirmForward(tsSdbObj.sync, pHead->version, code);
|
||||
} else {
|
||||
sdbTrace("record from wal restore is disposed, version:%" PRIu64 , pHead->version);
|
||||
}
|
||||
|
||||
if (action == SDB_ACTION_INSERT) {
|
||||
|
@ -568,7 +599,7 @@ static int sdbWrite(void *param, void *data, int type) {
|
|||
|
||||
int32_t sdbInsertRow(SSdbOper *pOper) {
|
||||
SSdbTable *pTable = (SSdbTable *)pOper->table;
|
||||
if (pTable == NULL) return -1;
|
||||
if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE;
|
||||
|
||||
if (sdbGetRowFromObj(pTable, pOper->pObj)) {
|
||||
sdbError("table:%s, failed to insert record:%s, already exist", pTable->tableName, sdbGetKeyStrFromObj(pTable, pOper->pObj));
|
||||
|
@ -587,9 +618,21 @@ int32_t sdbInsertRow(SSdbOper *pOper) {
|
|||
pthread_mutex_unlock(&pTable->mutex);
|
||||
}
|
||||
|
||||
if (pOper->type == SDB_OPER_GLOBAL) {
|
||||
int32_t size = sizeof(SWalHead) + pTable->maxRowSize;
|
||||
SWalHead *pHead = taosAllocateQitem(size);
|
||||
int32_t code = sdbInsertHash(pTable, pOper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbError("table:%s, failed to insert into hash", pTable->tableName);
|
||||
return code;
|
||||
}
|
||||
|
||||
// just insert data into memory
|
||||
if (pOper->type != SDB_OPER_GLOBAL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t size = sizeof(SSdbOper) + sizeof(SWalHead) + pTable->maxRowSize + SDB_SYNC_HACK;
|
||||
SSdbOper *pNewOper = taosAllocateQitem(size);
|
||||
|
||||
SWalHead *pHead = (void *)pNewOper + sizeof(SSdbOper) + SDB_SYNC_HACK;
|
||||
pHead->version = 0;
|
||||
pHead->len = pOper->rowSize;
|
||||
pHead->msgType = pTable->tableId * 10 + SDB_ACTION_INSERT;
|
||||
|
@ -598,28 +641,43 @@ int32_t sdbInsertRow(SSdbOper *pOper) {
|
|||
(*pTable->encodeFp)(pOper);
|
||||
pHead->len = pOper->rowSize;
|
||||
|
||||
int32_t code = sdbWrite(pOper, pHead, pHead->msgType);
|
||||
taosFreeQitem(pHead);
|
||||
if (code < 0) return code;
|
||||
memcpy(pNewOper, pOper, sizeof(SSdbOper));
|
||||
|
||||
if (pNewOper->pMsg != NULL) {
|
||||
sdbTrace("app:%p:%p, insert action is add to sdb queue", pNewOper->pMsg->rpcMsg.ahandle, pNewOper->pMsg);
|
||||
}
|
||||
|
||||
return sdbInsertHash(pTable, pOper);
|
||||
taosWriteQitem(tsSdbWriteQueue, TAOS_QTYPE_RPC, pNewOper);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t sdbDeleteRow(SSdbOper *pOper) {
|
||||
SSdbTable *pTable = (SSdbTable *)pOper->table;
|
||||
if (pTable == NULL) return -1;
|
||||
if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE;
|
||||
|
||||
SSdbRow *pMeta = sdbGetRowMetaFromObj(pTable, pOper->pObj);
|
||||
if (pMeta == NULL) {
|
||||
sdbTrace("table:%s, record is not there, delete failed", pTable->tableName);
|
||||
return -1;
|
||||
return TSDB_CODE_MND_SDB_OBJ_NOT_THERE;
|
||||
}
|
||||
|
||||
void *pMetaRow = pMeta->row;
|
||||
assert(pMetaRow != NULL);
|
||||
if (pMetaRow == NULL) {
|
||||
sdbError("table:%s, record meta is null", pTable->tableName);
|
||||
return TSDB_CODE_MND_SDB_INVAID_META_ROW;
|
||||
}
|
||||
|
||||
int32_t code = sdbDeleteHash(pTable, pOper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbError("table:%s, failed to delete from hash", pTable->tableName);
|
||||
return code;
|
||||
}
|
||||
|
||||
// just delete data from memory
|
||||
if (pOper->type != SDB_OPER_GLOBAL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (pOper->type == SDB_OPER_GLOBAL) {
|
||||
void * key = sdbGetObjKey(pTable, pOper->pObj);
|
||||
int32_t keySize = 0;
|
||||
switch (pTable->keyType) {
|
||||
|
@ -632,40 +690,59 @@ int32_t sdbDeleteRow(SSdbOper *pOper) {
|
|||
keySize = sizeof(uint32_t);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return TSDB_CODE_MND_SDB_INVAID_KEY_TYPE;
|
||||
}
|
||||
|
||||
int32_t size = sizeof(SWalHead) + keySize;
|
||||
SWalHead *pHead = taosAllocateQitem(size);
|
||||
int32_t size = sizeof(SSdbOper) + sizeof(SWalHead) + keySize + SDB_SYNC_HACK;
|
||||
SSdbOper *pNewOper = taosAllocateQitem(size);
|
||||
|
||||
SWalHead *pHead = (void *)pNewOper + sizeof(SSdbOper) + SDB_SYNC_HACK;
|
||||
pHead->version = 0;
|
||||
pHead->len = keySize;
|
||||
pHead->msgType = pTable->tableId * 10 + SDB_ACTION_DELETE;
|
||||
memcpy(pHead->cont, key, keySize);
|
||||
|
||||
int32_t code = sdbWrite(pOper, pHead, pHead->msgType);
|
||||
taosFreeQitem(pHead);
|
||||
if (code < 0) return code;
|
||||
memcpy(pNewOper, pOper, sizeof(SSdbOper));
|
||||
|
||||
if (pNewOper->pMsg != NULL) {
|
||||
sdbTrace("app:%p:%p, delete action is add to sdb queue", pNewOper->pMsg->rpcMsg.ahandle, pNewOper->pMsg);
|
||||
}
|
||||
|
||||
return sdbDeleteHash(pTable, pOper);
|
||||
taosWriteQitem(tsSdbWriteQueue, TAOS_QTYPE_RPC, pNewOper);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t sdbUpdateRow(SSdbOper *pOper) {
|
||||
SSdbTable *pTable = (SSdbTable *)pOper->table;
|
||||
if (pTable == NULL) return -1;
|
||||
if (pTable == NULL) return TSDB_CODE_MND_SDB_INVALID_TABLE_TYPE;
|
||||
|
||||
SSdbRow *pMeta = sdbGetRowMetaFromObj(pTable, pOper->pObj);
|
||||
if (pMeta == NULL) {
|
||||
sdbTrace("table:%s, record is not there, delete failed", pTable->tableName);
|
||||
return -1;
|
||||
sdbTrace("table:%s, record is not there, update failed", pTable->tableName);
|
||||
return TSDB_CODE_MND_SDB_OBJ_NOT_THERE;
|
||||
}
|
||||
|
||||
void *pMetaRow = pMeta->row;
|
||||
assert(pMetaRow != NULL);
|
||||
if (pMetaRow == NULL) {
|
||||
sdbError("table:%s, record meta is null", pTable->tableName);
|
||||
return TSDB_CODE_MND_SDB_INVAID_META_ROW;
|
||||
}
|
||||
|
||||
if (pOper->type == SDB_OPER_GLOBAL) {
|
||||
int32_t size = sizeof(SWalHead) + pTable->maxRowSize;
|
||||
SWalHead *pHead = taosAllocateQitem(size);
|
||||
int32_t code = sdbUpdateHash(pTable, pOper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbError("table:%s, failed to update hash", pTable->tableName);
|
||||
return code;
|
||||
}
|
||||
|
||||
// just update data in memory
|
||||
if (pOper->type != SDB_OPER_GLOBAL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t size = sizeof(SSdbOper) + sizeof(SWalHead) + pTable->maxRowSize + SDB_SYNC_HACK;
|
||||
SSdbOper *pNewOper = taosAllocateQitem(size);
|
||||
|
||||
SWalHead *pHead = (void *)pNewOper + sizeof(SSdbOper) + SDB_SYNC_HACK;
|
||||
pHead->version = 0;
|
||||
pHead->msgType = pTable->tableId * 10 + SDB_ACTION_UPDATE;
|
||||
|
||||
|
@ -673,12 +750,14 @@ int32_t sdbUpdateRow(SSdbOper *pOper) {
|
|||
(*pTable->encodeFp)(pOper);
|
||||
pHead->len = pOper->rowSize;
|
||||
|
||||
int32_t code = sdbWrite(pOper, pHead, pHead->msgType);
|
||||
taosFreeQitem(pHead);
|
||||
if (code < 0) return code;
|
||||
memcpy(pNewOper, pOper, sizeof(SSdbOper));
|
||||
|
||||
if (pNewOper->pMsg != NULL) {
|
||||
sdbTrace("app:%p:%p, update action is add to sdb queue", pNewOper->pMsg->rpcMsg.ahandle, pNewOper->pMsg);
|
||||
}
|
||||
|
||||
return sdbUpdateHash(pTable, pOper);
|
||||
taosWriteQitem(tsSdbWriteQueue, TAOS_QTYPE_RPC, pNewOper);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void *sdbFetchRow(void *handle, void *pNode, void **ppRow) {
|
||||
|
@ -775,3 +854,158 @@ void sdbCloseTable(void *handle) {
|
|||
free(pTable);
|
||||
}
|
||||
|
||||
int32_t sdbInitWriteWorker() {
|
||||
tsSdbPool.num = 1;
|
||||
tsSdbPool.writeWorker = (SSdbWriteWorker *)calloc(sizeof(SSdbWriteWorker), tsSdbPool.num);
|
||||
|
||||
if (tsSdbPool.writeWorker == NULL) return -1;
|
||||
for (int32_t i = 0; i < tsSdbPool.num; ++i) {
|
||||
SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i;
|
||||
pWorker->workerId = i;
|
||||
}
|
||||
|
||||
sdbAllocWriteQueue();
|
||||
|
||||
mPrint("sdb write is opened");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sdbCleanupWriteWorker() {
|
||||
for (int32_t i = 0; i < tsSdbPool.num; ++i) {
|
||||
SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i;
|
||||
if (pWorker->thread) {
|
||||
taosQsetThreadResume(tsSdbWriteQset);
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < tsSdbPool.num; ++i) {
|
||||
SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i;
|
||||
if (pWorker->thread) {
|
||||
pthread_join(pWorker->thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
sdbFreeWritequeue();
|
||||
|
||||
mPrint("sdb write is closed");
|
||||
}
|
||||
|
||||
int32_t sdbAllocWriteQueue() {
|
||||
tsSdbWriteQueue = taosOpenQueue();
|
||||
if (tsSdbWriteQueue == NULL) return TSDB_CODE_MND_OUT_OF_MEMORY;
|
||||
|
||||
tsSdbWriteQset = taosOpenQset();
|
||||
if (tsSdbWriteQset == NULL) {
|
||||
taosCloseQueue(tsSdbWriteQueue);
|
||||
return TSDB_CODE_MND_OUT_OF_MEMORY;
|
||||
}
|
||||
taosAddIntoQset(tsSdbWriteQset, tsSdbWriteQueue, NULL);
|
||||
|
||||
tsSdbWriteQall = taosAllocateQall();
|
||||
if (tsSdbWriteQall == NULL) {
|
||||
taosCloseQset(tsSdbWriteQset);
|
||||
taosCloseQueue(tsSdbWriteQueue);
|
||||
return TSDB_CODE_MND_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < tsSdbPool.num; ++i) {
|
||||
SSdbWriteWorker *pWorker = tsSdbPool.writeWorker + i;
|
||||
pWorker->workerId = i;
|
||||
|
||||
pthread_attr_t thAttr;
|
||||
pthread_attr_init(&thAttr);
|
||||
pthread_attr_setdetachstate(&thAttr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
if (pthread_create(&pWorker->thread, &thAttr, sdbWorkerFp, pWorker) != 0) {
|
||||
mError("failed to create thread to process sdb write queue, reason:%s", strerror(errno));
|
||||
taosFreeQall(tsSdbWriteQall);
|
||||
taosCloseQset(tsSdbWriteQset);
|
||||
taosCloseQueue(tsSdbWriteQueue);
|
||||
return TSDB_CODE_MND_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&thAttr);
|
||||
mTrace("sdb write worker:%d is launched, total:%d", pWorker->workerId, tsSdbPool.num);
|
||||
}
|
||||
|
||||
mTrace("sdb write queue:%p is allocated", tsSdbWriteQueue);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void sdbFreeWritequeue() {
|
||||
taosCloseQset(tsSdbWriteQueue);
|
||||
taosFreeQall(tsSdbWriteQall);
|
||||
taosCloseQset(tsSdbWriteQset);
|
||||
tsSdbWriteQall = NULL;
|
||||
tsSdbWriteQset = NULL;
|
||||
tsSdbWriteQueue = NULL;
|
||||
}
|
||||
|
||||
int sdbWriteToQueue(void *param, void *data, int type) {
|
||||
SWalHead *pHead = data;
|
||||
int size = sizeof(SWalHead) + pHead->len;
|
||||
SWalHead *pWal = (SWalHead *)taosAllocateQitem(size);
|
||||
memcpy(pWal, pHead, size);
|
||||
|
||||
taosWriteQitem(tsSdbWriteQueue, type, pWal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *sdbWorkerFp(void *param) {
|
||||
SWalHead *pHead;
|
||||
SSdbOper *pOper;
|
||||
int32_t type;
|
||||
int32_t numOfMsgs;
|
||||
void * item;
|
||||
void * unUsed;
|
||||
|
||||
while (1) {
|
||||
numOfMsgs = taosReadAllQitemsFromQset(tsSdbWriteQset, tsSdbWriteQall, &unUsed);
|
||||
if (numOfMsgs == 0) {
|
||||
sdbTrace("sdbWorkerFp: got no message from qset, exiting...");
|
||||
break;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfMsgs; ++i) {
|
||||
taosGetQitem(tsSdbWriteQall, &type, &item);
|
||||
if (type == TAOS_QTYPE_RPC) {
|
||||
pOper = (SSdbOper *)item;
|
||||
pHead = (void *)pOper + sizeof(SSdbOper) + SDB_SYNC_HACK;
|
||||
} else {
|
||||
pHead = (SWalHead *)item;
|
||||
pOper = NULL;
|
||||
}
|
||||
|
||||
if (pOper != NULL && pOper->pMsg != NULL) {
|
||||
sdbTrace("app:%p:%p, will be processed in sdb queue", pOper->pMsg->rpcMsg.ahandle, pOper->pMsg);
|
||||
}
|
||||
|
||||
int32_t code = sdbWrite(pOper, pHead, type);
|
||||
if (pOper) pOper->retCode = code;
|
||||
}
|
||||
|
||||
walFsync(tsSdbObj.wal);
|
||||
|
||||
// browse all items, and process them one by one
|
||||
taosResetQitems(tsSdbWriteQall);
|
||||
for (int32_t i = 0; i < numOfMsgs; ++i) {
|
||||
taosGetQitem(tsSdbWriteQall, &type, &item);
|
||||
if (type == TAOS_QTYPE_RPC) {
|
||||
pOper = (SSdbOper *)item;
|
||||
if (pOper != NULL && pOper->cb != NULL) {
|
||||
pOper->retCode = (*pOper->cb)(pOper->pMsg, pOper->retCode);
|
||||
}
|
||||
|
||||
if (pOper != NULL && pOper->pMsg != NULL) {
|
||||
sdbTrace("app:%p:%p, msg is processed, result:%s", pOper->pMsg->rpcMsg.ahandle, pOper->pMsg,
|
||||
tstrerror(pOper->retCode));
|
||||
}
|
||||
|
||||
dnodeSendRpcMnodeWriteRsp(pOper->pMsg, pOper->retCode);
|
||||
}
|
||||
taosFreeQitem(item);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -102,11 +102,13 @@ static int32_t mnodeUserActionDecode(SSdbOper *pOper) {
|
|||
}
|
||||
|
||||
static int32_t mnodeUserActionRestored() {
|
||||
if (dnodeIsFirstDeploy()) {
|
||||
int32_t numOfRows = sdbGetNumOfRows(tsUserSdb);
|
||||
if (numOfRows <= 0 && dnodeIsFirstDeploy()) {
|
||||
mPrint("dnode first deploy, create root user");
|
||||
SAcctObj *pAcct = mnodeGetAcct("root");
|
||||
mnodeCreateUser(pAcct, "root", "taosdata");
|
||||
mnodeCreateUser(pAcct, "monitor", tsInternalPass);
|
||||
mnodeCreateUser(pAcct, "_root", tsInternalPass);
|
||||
mnodeCreateUser(pAcct, "root", "taosdata", NULL);
|
||||
mnodeCreateUser(pAcct, "monitor", tsInternalPass, NULL);
|
||||
mnodeCreateUser(pAcct, "_root", tsInternalPass, NULL);
|
||||
mnodeDecAcctRef(pAcct);
|
||||
}
|
||||
|
||||
|
@ -170,22 +172,24 @@ void mnodeDecUserRef(SUserObj *pUser) {
|
|||
return sdbDecRef(tsUserSdb, pUser);
|
||||
}
|
||||
|
||||
static int32_t mnodeUpdateUser(SUserObj *pUser) {
|
||||
static int32_t mnodeUpdateUser(SUserObj *pUser, void *pMsg) {
|
||||
SSdbOper oper = {
|
||||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsUserSdb,
|
||||
.pObj = pUser
|
||||
.pObj = pUser,
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
int32_t code = sdbUpdateRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
code = TSDB_CODE_MND_SDB_ERROR;
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("user:%s, is altered by %s", pUser->user, mnodeGetUserFromMsg(pMsg));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass) {
|
||||
int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass, void *pMsg) {
|
||||
int32_t code = acctCheck(pAcct, ACCT_GRANT_USER);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
|
@ -226,28 +230,33 @@ int32_t mnodeCreateUser(SAcctObj *pAcct, char *name, char *pass) {
|
|||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsUserSdb,
|
||||
.pObj = pUser,
|
||||
.rowSize = sizeof(SUserObj)
|
||||
.rowSize = sizeof(SUserObj),
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
code = sdbInsertRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tfree(pUser);
|
||||
code = TSDB_CODE_MND_SDB_ERROR;
|
||||
} else {
|
||||
mLPrint("user:%s, is created by %s", pUser->user, mnodeGetUserFromMsg(pMsg));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mnodeDropUser(SUserObj *pUser) {
|
||||
static int32_t mnodeDropUser(SUserObj *pUser, void *pMsg) {
|
||||
SSdbOper oper = {
|
||||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsUserSdb,
|
||||
.pObj = pUser
|
||||
.pObj = pUser,
|
||||
.pMsg = pMsg
|
||||
};
|
||||
|
||||
int32_t code = sdbDeleteRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
code = TSDB_CODE_MND_SDB_ERROR;
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("user:%s, is dropped by %s", pUser->user, mnodeGetUserFromMsg(pMsg));
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -315,8 +324,7 @@ static int32_t mnodeRetrieveUsers(SShowObj *pShow, char *data, int32_t rows, voi
|
|||
cols = 0;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
size_t size = sizeof(pUser->user);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pUser->user, size);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pUser->user, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
@ -337,7 +345,7 @@ static int32_t mnodeRetrieveUsers(SShowObj *pShow, char *data, int32_t rows, voi
|
|||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pUser->acct, sizeof(pUser->user));
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pUser->acct, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
numOfRows++;
|
||||
|
@ -358,22 +366,25 @@ SUserObj *mnodeGetUserFromConn(void *pConn) {
|
|||
}
|
||||
}
|
||||
|
||||
char *mnodeGetUserFromMsg(void *pMsg) {
|
||||
SMnodeMsg *pMnodeMsg = pMsg;
|
||||
if (pMnodeMsg != NULL &&pMnodeMsg->pUser != NULL) {
|
||||
return pMnodeMsg->pUser->user;
|
||||
} else {
|
||||
return "system";
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t mnodeProcessCreateUserMsg(SMnodeMsg *pMsg) {
|
||||
int32_t code;
|
||||
SUserObj *pOperUser = pMsg->pUser;
|
||||
|
||||
if (pOperUser->superAuth) {
|
||||
SCMCreateUserMsg *pCreate = pMsg->rpcMsg.pCont;
|
||||
code = mnodeCreateUser(pOperUser->pAcct, pCreate->user, pCreate->pass);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("user:%s, is created by %s", pCreate->user, pOperUser->user);
|
||||
}
|
||||
return mnodeCreateUser(pOperUser->pAcct, pCreate->user, pCreate->pass, pMsg);
|
||||
} else {
|
||||
mError("user:%s, no rights to create user", pOperUser->user);
|
||||
code = TSDB_CODE_MND_NO_RIGHTS;
|
||||
return TSDB_CODE_MND_NO_RIGHTS;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mnodeProcessAlterUserMsg(SMnodeMsg *pMsg) {
|
||||
|
@ -410,8 +421,7 @@ static int32_t mnodeProcessAlterUserMsg(SMnodeMsg *pMsg) {
|
|||
if (hasRight) {
|
||||
memset(pUser->pass, 0, sizeof(pUser->pass));
|
||||
taosEncryptPass((uint8_t*)pAlter->pass, strlen(pAlter->pass), pUser->pass);
|
||||
code = mnodeUpdateUser(pUser);
|
||||
mLPrint("user:%s, password is altered by %s, result:%s", pUser->user, pOperUser->user, tstrerror(code));
|
||||
code = mnodeUpdateUser(pUser, pMsg);
|
||||
} else {
|
||||
mError("user:%s, no rights to alter user", pOperUser->user);
|
||||
code = TSDB_CODE_MND_NO_RIGHTS;
|
||||
|
@ -451,8 +461,7 @@ static int32_t mnodeProcessAlterUserMsg(SMnodeMsg *pMsg) {
|
|||
pUser->writeAuth = 1;
|
||||
}
|
||||
|
||||
code = mnodeUpdateUser(pUser);
|
||||
mLPrint("user:%s, privilege is altered by %s, result:%s", pUser->user, pOperUser->user, tstrerror(code));
|
||||
code = mnodeUpdateUser(pUser, pMsg);
|
||||
} else {
|
||||
mError("user:%s, no rights to alter user", pOperUser->user);
|
||||
code = TSDB_CODE_MND_NO_RIGHTS;
|
||||
|
@ -498,10 +507,7 @@ static int32_t mnodeProcessDropUserMsg(SMnodeMsg *pMsg) {
|
|||
}
|
||||
|
||||
if (hasRight) {
|
||||
code = mnodeDropUser(pUser);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
mLPrint("user:%s, is dropped by %s, result:%s", pUser->user, pOperUser->user, tstrerror(code));
|
||||
}
|
||||
code = mnodeDropUser(pUser, pMsg);
|
||||
} else {
|
||||
code = TSDB_CODE_MND_NO_RIGHTS;
|
||||
}
|
||||
|
|
|
@ -149,8 +149,7 @@ static int32_t mnodeVgroupActionUpdate(SSdbOper *pOper) {
|
|||
}
|
||||
}
|
||||
|
||||
memcpy(pVgroup, pNew, pOper->rowSize);
|
||||
free(pNew);
|
||||
memcpy(pVgroup, pNew, tsVgUpdateSize);
|
||||
|
||||
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
|
||||
SDnodeObj *pDnode = mnodeGetDnode(pVgroup->vnodeGid[i].dnodeId);
|
||||
|
@ -299,6 +298,27 @@ void *mnodeGetNextVgroup(void *pIter, SVgObj **pVgroup) {
|
|||
return sdbFetchRow(tsVgroupSdb, pIter, (void **)pVgroup);
|
||||
}
|
||||
|
||||
static int32_t mnodeCreateVgroupCb(SMnodeMsg *pMsg, int32_t code) {
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
pMsg->pVgroup = NULL;
|
||||
return code;
|
||||
}
|
||||
|
||||
SVgObj *pVgroup = pMsg->pVgroup;
|
||||
SDbObj *pDb = pMsg->pDb;
|
||||
|
||||
mPrint("vgId:%d, is created in mnode, db:%s replica:%d", pVgroup->vgId, pDb->name, pVgroup->numOfVnodes);
|
||||
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
|
||||
mPrint("vgId:%d, index:%d, dnode:%d", pVgroup->vgId, i, pVgroup->vnodeGid[i].dnodeId);
|
||||
}
|
||||
|
||||
mnodeIncVgroupRef(pVgroup);
|
||||
pMsg->expected = pVgroup->numOfVnodes;
|
||||
mnodeSendCreateVgroupMsg(pVgroup, pMsg);
|
||||
|
||||
return TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
int32_t mnodeCreateVgroup(SMnodeMsg *pMsg, SDbObj *pDb) {
|
||||
SVgObj *pVgroup = (SVgObj *)calloc(1, sizeof(SVgObj));
|
||||
strcpy(pVgroup->dbName, pDb->name);
|
||||
|
@ -314,26 +334,22 @@ int32_t mnodeCreateVgroup(SMnodeMsg *pMsg, SDbObj *pDb) {
|
|||
.type = SDB_OPER_GLOBAL,
|
||||
.table = tsVgroupSdb,
|
||||
.pObj = pVgroup,
|
||||
.rowSize = sizeof(SVgObj)
|
||||
.rowSize = sizeof(SVgObj),
|
||||
.pMsg = pMsg,
|
||||
.cb = mnodeCreateVgroupCb
|
||||
};
|
||||
|
||||
pMsg->pVgroup = pVgroup;
|
||||
|
||||
int32_t code = sdbInsertRow(&oper);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
pMsg->pVgroup = NULL;
|
||||
tfree(pVgroup);
|
||||
return TSDB_CODE_MND_SDB_ERROR;
|
||||
} else {
|
||||
if (pMsg != NULL) code = TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
mPrint("vgId:%d, is created in mnode, db:%s replica:%d", pVgroup->vgId, pDb->name, pVgroup->numOfVnodes);
|
||||
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
|
||||
mPrint("vgId:%d, index:%d, dnode:%d", pVgroup->vgId, i, pVgroup->vnodeGid[i].dnodeId);
|
||||
}
|
||||
|
||||
mnodeIncVgroupRef(pVgroup);
|
||||
pMsg->pVgroup = pVgroup;
|
||||
pMsg->expected = pVgroup->numOfVnodes;
|
||||
mnodeSendCreateVgroupMsg(pVgroup, pMsg);
|
||||
|
||||
return TSDB_CODE_MND_ACTION_IN_PROGRESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
void mnodeDropVgroup(SVgObj *pVgroup, void *ahandle) {
|
||||
|
@ -479,12 +495,12 @@ int32_t mnodeRetrieveVgroups(SShowObj *pShow, char *data, int32_t rows, void *pC
|
|||
|
||||
if (pDnode != NULL) {
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDnode->dnodeEp, pShow->bytes[cols] - VARSTR_HEADER_SIZE);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pDnode->dnodeEp, pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
char *role = mnodeGetMnodeRoleStr(pVgroup->vnodeGid[i].role);
|
||||
STR_TO_VARSTR(pWrite, role);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, role, pShow->bytes[cols]);
|
||||
cols++;
|
||||
} else {
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
|
@ -596,7 +612,6 @@ SRpcIpSet mnodeGetIpSetFromIp(char *ep) {
|
|||
}
|
||||
|
||||
void mnodeSendCreateVnodeMsg(SVgObj *pVgroup, SRpcIpSet *ipSet, void *ahandle) {
|
||||
mTrace("vgId:%d, send create vnode:%d msg, ahandle:%p db:%s", pVgroup->vgId, pVgroup->vgId, ahandle, pVgroup->dbName);
|
||||
SMDCreateVnodeMsg *pCreate = mnodeBuildCreateVnodeMsg(pVgroup);
|
||||
SRpcMsg rpcMsg = {
|
||||
.handle = ahandle,
|
||||
|
@ -609,9 +624,12 @@ void mnodeSendCreateVnodeMsg(SVgObj *pVgroup, SRpcIpSet *ipSet, void *ahandle) {
|
|||
}
|
||||
|
||||
void mnodeSendCreateVgroupMsg(SVgObj *pVgroup, void *ahandle) {
|
||||
mTrace("vgId:%d, send create all vnodes msg, ahandle:%p", pVgroup->vgId, ahandle);
|
||||
mTrace("vgId:%d, send create all vnodes msg, numOfVnodes:%d db:%s", pVgroup->vgId, pVgroup->numOfVnodes,
|
||||
pVgroup->dbName);
|
||||
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
|
||||
SRpcIpSet ipSet = mnodeGetIpSetFromIp(pVgroup->vnodeGid[i].pDnode->dnodeEp);
|
||||
mTrace("vgId:%d, index:%d, send create vnode msg to dnode %s, ahandle:%p", pVgroup->vgId,
|
||||
i, pVgroup->vnodeGid[i].pDnode->dnodeEp, ahandle);
|
||||
mnodeSendCreateVnodeMsg(pVgroup, &ipSet, ahandle);
|
||||
}
|
||||
}
|
||||
|
@ -729,6 +747,7 @@ static int32_t mnodeProcessVnodeCfgMsg(SMnodeMsg *pMsg) {
|
|||
}
|
||||
mnodeDecVgroupRef(pVgroup);
|
||||
|
||||
mTrace("vgId:%d, send create vnode msg to dnode %s for vnode cfg msg", pVgroup->vgId, pDnode->dnodeEp);
|
||||
SRpcIpSet ipSet = mnodeGetIpSetFromIp(pDnode->dnodeEp);
|
||||
mnodeSendCreateVnodeMsg(pVgroup, &ipSet, NULL);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ void mnodeAddWriteMsgHandle(uint8_t msgType, int32_t (*fp)(SMnodeMsg *mnodeMsg))
|
|||
|
||||
int32_t mnodeProcessWrite(SMnodeMsg *pMsg) {
|
||||
if (pMsg->rpcMsg.pCont == NULL) {
|
||||
mError("%p, msg:%s in mwrite queue, content is null", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]);
|
||||
mError("app:%p:%p, msg:%s content is null", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType]);
|
||||
return TSDB_CODE_MND_INVALID_MSG_LEN;
|
||||
}
|
||||
|
||||
|
@ -54,27 +54,31 @@ int32_t mnodeProcessWrite(SMnodeMsg *pMsg) {
|
|||
rpcRsp->rsp = ipSet;
|
||||
rpcRsp->len = sizeof(SRpcIpSet);
|
||||
|
||||
mTrace("%p, msg:%s in mwrite queue, will be redireced inUse:%d", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], ipSet->inUse);
|
||||
mTrace("app:%p:%p, msg:%s will be redireced inUse:%d", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType],
|
||||
ipSet->inUse);
|
||||
for (int32_t i = 0; i < ipSet->numOfIps; ++i) {
|
||||
mTrace("mnode index:%d ip:%s:%d", i, ipSet->fqdn[i], htons(ipSet->port[i]));
|
||||
mTrace("app:%p:%p, mnode index:%d ip:%s:%d", pMsg->rpcMsg.ahandle, pMsg, i, ipSet->fqdn[i],
|
||||
htons(ipSet->port[i]));
|
||||
}
|
||||
|
||||
return TSDB_CODE_RPC_REDIRECT;
|
||||
}
|
||||
|
||||
if (tsMnodeProcessWriteMsgFp[pMsg->rpcMsg.msgType] == NULL) {
|
||||
mError("%p, msg:%s in mwrite queue, not processed", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]);
|
||||
mError("app:%p:%p, msg:%s not processed", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType]);
|
||||
return TSDB_CODE_MND_MSG_NOT_PROCESSED;
|
||||
}
|
||||
|
||||
int32_t code = mnodeInitMsg(pMsg);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
mError("%p, msg:%s in mwrite queue, not processed reason:%s", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType], tstrerror(code));
|
||||
mError("app:%p:%p, msg:%s not processed, reason:%s", pMsg->rpcMsg.ahandle, pMsg, taosMsg[pMsg->rpcMsg.msgType],
|
||||
tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
if (!pMsg->pUser->writeAuth) {
|
||||
mError("%p, msg:%s in mwrite queue, not processed, no write auth", pMsg->rpcMsg.ahandle, taosMsg[pMsg->rpcMsg.msgType]);
|
||||
mError("app:%p:%p, msg:%s not processed, no write auth", pMsg->rpcMsg.ahandle, pMsg,
|
||||
taosMsg[pMsg->rpcMsg.msgType]);
|
||||
return TSDB_CODE_MND_NO_RIGHTS;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,15 +16,11 @@
|
|||
#ifndef TDENGINE_GC_HANDLE_H
|
||||
#define TDENGINE_GC_HANDLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "http.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpUtil.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpSql.h"
|
||||
|
||||
#define GC_ROOT_URL_POS 0
|
||||
#define GC_ACTION_URL_POS 1
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_TOKEN_H
|
||||
#define TDENGINE_HTTP_TOKEN_H
|
||||
|
||||
bool httpParseBasicAuthToken(HttpContext *pContext, char *token, int len);
|
||||
bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len);
|
||||
bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_CONTEXT_H
|
||||
#define TDENGINE_HTTP_CONTEXT_H
|
||||
|
||||
#include "httpInt.h"
|
||||
|
||||
bool httpInitContexts();
|
||||
void httpCleanupContexts();
|
||||
const char *httpContextStateStr(HttpContextState state);
|
||||
|
||||
HttpContext *httpCreateContext(int32_t fd);
|
||||
bool httpInitContext(HttpContext *pContext);
|
||||
HttpContext *httpGetContext(void * pContext);
|
||||
void httpReleaseContext(HttpContext *pContext);
|
||||
void httpCloseContextByServer(HttpContext *pContext);
|
||||
void httpCloseContextByApp(HttpContext *pContext);
|
||||
void httpNotifyContextClose(HttpContext *pContext);
|
||||
bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState);
|
||||
|
||||
#endif
|
|
@ -13,304 +13,11 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_SERVER_H
|
||||
#define TDENGINE_HTTP_SERVER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pthread.h"
|
||||
#include "semaphore.h"
|
||||
#include "tmempool.h"
|
||||
#include "taosdef.h"
|
||||
#include "tutil.h"
|
||||
#include "zlib.h"
|
||||
#include "http.h"
|
||||
#include "httpJson.h"
|
||||
|
||||
#define HTTP_MAX_CMD_SIZE 1024
|
||||
#define HTTP_MAX_BUFFER_SIZE 1024*1024
|
||||
|
||||
#define HTTP_LABEL_SIZE 8
|
||||
#define HTTP_MAX_EVENTS 10
|
||||
#define HTTP_BUFFER_SIZE 1024*65 //65k
|
||||
#define HTTP_DECOMPRESS_BUF_SIZE 1024*64
|
||||
#define HTTP_STEP_SIZE 1024 //http message get process step by step
|
||||
#define HTTP_MAX_URL 5 //http url stack size
|
||||
#define HTTP_METHOD_SCANNER_SIZE 7 //http method fp size
|
||||
#define HTTP_GC_TARGET_SIZE 512
|
||||
|
||||
#define HTTP_VERSION_10 0
|
||||
#define HTTP_VERSION_11 1
|
||||
//#define HTTP_VERSION_12 2
|
||||
|
||||
#define HTTP_UNCUNKED 0
|
||||
#define HTTP_CHUNKED 1
|
||||
|
||||
#define HTTP_KEEPALIVE_NO_INPUT 0
|
||||
#define HTTP_KEEPALIVE_ENABLE 1
|
||||
#define HTTP_KEEPALIVE_DISABLE 2
|
||||
|
||||
#define HTTP_REQTYPE_OTHERS 0
|
||||
#define HTTP_REQTYPE_LOGIN 1
|
||||
#define HTTP_REQTYPE_HEARTBEAT 2
|
||||
#define HTTP_REQTYPE_SINGLE_SQL 3
|
||||
#define HTTP_REQTYPE_MULTI_SQL 4
|
||||
|
||||
#define HTTP_CHECK_BODY_ERROR -1
|
||||
#define HTTP_CHECK_BODY_CONTINUE 0
|
||||
#define HTTP_CHECK_BODY_SUCCESS 1
|
||||
|
||||
#define HTTP_WRITE_RETRY_TIMES 500
|
||||
#define HTTP_WRITE_WAIT_TIME_MS 5
|
||||
#define HTTP_EXPIRED_TIME 60000
|
||||
#define HTTP_DELAY_CLOSE_TIME_MS 500
|
||||
|
||||
#define HTTP_COMPRESS_IDENTITY 0
|
||||
#define HTTP_COMPRESS_GZIP 2
|
||||
|
||||
#define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + TSDB_PASSWORD_LEN)
|
||||
|
||||
typedef enum {
|
||||
HTTP_CONTEXT_STATE_READY,
|
||||
HTTP_CONTEXT_STATE_HANDLING,
|
||||
HTTP_CONTEXT_STATE_DROPPING,
|
||||
HTTP_CONTEXT_STATE_CLOSED
|
||||
} HttpContextState;
|
||||
|
||||
struct HttpContext;
|
||||
struct HttpThread;
|
||||
|
||||
typedef struct {
|
||||
void *signature;
|
||||
int expire;
|
||||
int access;
|
||||
void *taos;
|
||||
char id[HTTP_SESSION_ID_LEN];
|
||||
} HttpSession;
|
||||
|
||||
typedef enum {
|
||||
HTTP_CMD_TYPE_UN_SPECIFIED,
|
||||
HTTP_CMD_TYPE_CREATE_DB,
|
||||
HTTP_CMD_TYPE_CREATE_STBALE,
|
||||
HTTP_CMD_TYPE_INSERT
|
||||
} HttpSqlCmdType;
|
||||
|
||||
typedef enum { HTTP_CMD_STATE_NOT_RUN_YET, HTTP_CMD_STATE_RUN_FINISHED } HttpSqlCmdState;
|
||||
|
||||
typedef enum { HTTP_CMD_RETURN_TYPE_WITH_RETURN, HTTP_CMD_RETURN_TYPE_NO_RETURN } HttpSqlCmdReturnType;
|
||||
|
||||
typedef struct {
|
||||
// used by single cmd
|
||||
char *nativSql;
|
||||
int32_t numOfRows;
|
||||
int32_t code;
|
||||
|
||||
// these are the locations in the buffer
|
||||
int32_t tagNames[TSDB_MAX_TAGS];
|
||||
int32_t tagValues[TSDB_MAX_TAGS];
|
||||
int32_t timestamp;
|
||||
int32_t metric;
|
||||
int32_t stable;
|
||||
int32_t table;
|
||||
int32_t values;
|
||||
int32_t sql;
|
||||
|
||||
// used by multi-cmd
|
||||
int8_t cmdType;
|
||||
int8_t cmdReturnType;
|
||||
int8_t cmdState;
|
||||
int8_t tagNum;
|
||||
} HttpSqlCmd;
|
||||
|
||||
typedef struct {
|
||||
HttpSqlCmd *cmds;
|
||||
int16_t pos;
|
||||
int16_t size;
|
||||
int16_t maxSize;
|
||||
int32_t bufferPos;
|
||||
int32_t bufferSize;
|
||||
char * buffer;
|
||||
} HttpSqlCmds;
|
||||
|
||||
typedef struct {
|
||||
char *module;
|
||||
bool (*decodeFp)(struct HttpContext *pContext);
|
||||
} HttpDecodeMethod;
|
||||
|
||||
typedef struct {
|
||||
void (*startJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result);
|
||||
void (*stopJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd);
|
||||
bool (*buildQueryJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result, int numOfRows);
|
||||
void (*buildAffectRowJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int affectRows);
|
||||
void (*initJsonFp)(struct HttpContext *pContext);
|
||||
void (*cleanJsonFp)(struct HttpContext *pContext);
|
||||
bool (*checkFinishedFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code);
|
||||
void (*setNextCmdFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code);
|
||||
} HttpEncodeMethod;
|
||||
|
||||
typedef struct {
|
||||
char *pos;
|
||||
int32_t len;
|
||||
} HttpBuf;
|
||||
|
||||
typedef struct {
|
||||
char buffer[HTTP_BUFFER_SIZE];
|
||||
int bufsize;
|
||||
char *pLast;
|
||||
char *pCur;
|
||||
HttpBuf method;
|
||||
HttpBuf path[HTTP_MAX_URL]; // url: dbname/meter/query
|
||||
HttpBuf data; // body content
|
||||
HttpBuf token; // auth token
|
||||
HttpDecodeMethod *pMethod;
|
||||
} HttpParser;
|
||||
|
||||
typedef struct HttpContext {
|
||||
void * signature;
|
||||
int fd;
|
||||
uint32_t accessTimes;
|
||||
uint32_t lastAccessTime;
|
||||
uint8_t httpVersion;
|
||||
uint8_t httpChunked;
|
||||
uint8_t httpKeepAlive; // http1.0 and not keep-alive, close connection immediately
|
||||
uint8_t fromMemPool;
|
||||
uint8_t acceptEncoding;
|
||||
uint8_t contentEncoding;
|
||||
uint8_t reqType;
|
||||
uint8_t parsed;
|
||||
int32_t state;
|
||||
char ipstr[22];
|
||||
char user[TSDB_USER_LEN]; // parsed from auth token or login message
|
||||
char pass[TSDB_PASSWORD_LEN];
|
||||
void *taos;
|
||||
HttpSession *session;
|
||||
z_stream gzipStream;
|
||||
HttpEncodeMethod *encodeMethod;
|
||||
HttpSqlCmd singleCmd;
|
||||
HttpSqlCmds *multiCmds;
|
||||
JsonBuf *jsonBuf;
|
||||
HttpParser parser;
|
||||
void *timer;
|
||||
struct HttpThread *pThread;
|
||||
struct HttpContext *prev;
|
||||
struct HttpContext *next;
|
||||
} HttpContext;
|
||||
|
||||
typedef struct HttpThread {
|
||||
pthread_t thread;
|
||||
HttpContext * pHead;
|
||||
pthread_mutex_t threadMutex;
|
||||
bool stop;
|
||||
int pollFd;
|
||||
int numOfFds;
|
||||
int threadId;
|
||||
char label[HTTP_LABEL_SIZE];
|
||||
bool (*processData)(HttpContext *pContext);
|
||||
struct HttpServer *pServer; // handle passed by upper layer during pServer initialization
|
||||
} HttpThread;
|
||||
|
||||
typedef struct HttpServer {
|
||||
char label[HTTP_LABEL_SIZE];
|
||||
uint32_t serverIp;
|
||||
uint16_t serverPort;
|
||||
bool online;
|
||||
int fd;
|
||||
int cacheContext;
|
||||
int sessionExpire;
|
||||
int numOfThreads;
|
||||
HttpDecodeMethod *methodScanner[HTTP_METHOD_SCANNER_SIZE];
|
||||
int methodScannerLen;
|
||||
pthread_mutex_t serverMutex;
|
||||
void *pSessionHash;
|
||||
void *pContextPool;
|
||||
void *expireTimer;
|
||||
HttpThread *pThreads;
|
||||
pthread_t thread;
|
||||
bool (*processData)(HttpContext *pContext);
|
||||
int requestNum;
|
||||
void *timerHandle;
|
||||
} HttpServer;
|
||||
|
||||
// http util method
|
||||
bool httpCheckUsedbSql(char *sql);
|
||||
void httpTimeToString(time_t t, char *buf, int buflen);
|
||||
|
||||
// http init method
|
||||
void *httpInitServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle);
|
||||
void httpCleanUpServer(HttpServer *pServer);
|
||||
|
||||
// http server connection
|
||||
void httpCleanUpConnect(HttpServer *pServer);
|
||||
bool httpInitConnect(HttpServer *pServer);
|
||||
|
||||
// http context for each client connection
|
||||
HttpContext *httpCreateContext(HttpServer *pServer);
|
||||
bool httpInitContext(HttpContext *pContext);
|
||||
void httpCloseContextByApp(HttpContext *pContext);
|
||||
void httpCloseContextByServer(HttpThread *pThread, HttpContext *pContext);
|
||||
|
||||
// http session method
|
||||
void httpCreateSession(HttpContext *pContext, void *taos);
|
||||
void httpAccessSession(HttpContext *pContext);
|
||||
void httpFetchSession(HttpContext *pContext);
|
||||
void httpRestoreSession(HttpContext *pContext);
|
||||
void httpRemoveExpireSessions(HttpServer *pServer);
|
||||
bool httpInitAllSessions(HttpServer *pServer);
|
||||
void httpRemoveAllSessions(HttpServer *pServer);
|
||||
void httpProcessSessionExpire(void *handle, void *tmrId);
|
||||
|
||||
// http request parser
|
||||
void httpAddMethod(HttpServer *pServer, HttpDecodeMethod *pMethod);
|
||||
|
||||
// http token method
|
||||
bool httpParseBasicAuthToken(HttpContext *pContext, char *token, int len);
|
||||
bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len);
|
||||
bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen);
|
||||
|
||||
// util
|
||||
bool httpUrlMatch(HttpContext *pContext, int pos, char *cmp);
|
||||
bool httpProcessData(HttpContext *pContext);
|
||||
bool httpReadDataImp(HttpContext *pContext);
|
||||
bool httpParseRequest(HttpContext* pContext);
|
||||
int httpCheckReadCompleted(HttpContext* pContext);
|
||||
void httpReadDirtyData(HttpContext *pContext);
|
||||
#ifndef TDENGINE_HTTP_HANDLE_H
|
||||
#define TDENGINE_HTTP_HANDLE_H
|
||||
|
||||
// http request handler
|
||||
void httpProcessRequest(HttpContext *pContext);
|
||||
|
||||
// http json printer
|
||||
JsonBuf *httpMallocJsonBuf(HttpContext *pContext);
|
||||
void httpFreeJsonBuf(HttpContext *pContext);
|
||||
|
||||
// http multicmds util
|
||||
|
||||
int32_t httpAddToSqlCmdBuffer(HttpContext *pContext, const char *const format, ...);
|
||||
int32_t httpAddToSqlCmdBufferNoTerminal(HttpContext *pContext, const char *const format, ...);
|
||||
int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize);
|
||||
int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext);
|
||||
|
||||
bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize);
|
||||
bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize);
|
||||
bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int bufferSize);
|
||||
void httpFreeMultiCmds(HttpContext *pContext);
|
||||
|
||||
HttpSqlCmd *httpNewSqlCmd(HttpContext *pContext);
|
||||
HttpSqlCmd *httpCurrSqlCmd(HttpContext *pContext);
|
||||
int httpCurSqlCmdPos(HttpContext *pContext);
|
||||
|
||||
void httpTrimTableName(char *name);
|
||||
int httpShrinkTableName(HttpContext *pContext, int pos, char *name);
|
||||
char *httpGetCmdsString(HttpContext *pContext, int pos);
|
||||
|
||||
int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData);
|
||||
int httpGzipCompressInit(HttpContext *pContext);
|
||||
int httpGzipCompress(HttpContext *pContext, char *inSrcData, int32_t inSrcDataLen,
|
||||
char *outDestData, int32_t *outDestDataLen, bool isTheLast);
|
||||
|
||||
extern const char *httpKeepAliveStr[];
|
||||
extern const char *httpVersionStr[];
|
||||
const char* httpContextStateStr(HttpContextState state);
|
||||
|
||||
bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState);
|
||||
void httpRemoveContextFromEpoll(HttpThread *pThread, HttpContext *pContext);
|
||||
bool httpProcessData(HttpContext *pContext);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_INT_H
|
||||
#define TDENGINE_HTTP_INT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pthread.h"
|
||||
#include "semaphore.h"
|
||||
#include "tmempool.h"
|
||||
#include "taosdef.h"
|
||||
#include "tutil.h"
|
||||
#include "zlib.h"
|
||||
#include "http.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpJson.h"
|
||||
|
||||
#define HTTP_MAX_CMD_SIZE 1024
|
||||
#define HTTP_MAX_BUFFER_SIZE 1024*1024
|
||||
|
||||
#define HTTP_LABEL_SIZE 8
|
||||
#define HTTP_MAX_EVENTS 10
|
||||
#define HTTP_BUFFER_SIZE 1024*65 //65k
|
||||
#define HTTP_DECOMPRESS_BUF_SIZE 1024*64
|
||||
#define HTTP_STEP_SIZE 1024 //http message get process step by step
|
||||
#define HTTP_MAX_URL 5 //http url stack size
|
||||
#define HTTP_METHOD_SCANNER_SIZE 7 //http method fp size
|
||||
#define HTTP_GC_TARGET_SIZE 512
|
||||
|
||||
#define HTTP_VERSION_10 0
|
||||
#define HTTP_VERSION_11 1
|
||||
//#define HTTP_VERSION_12 2
|
||||
|
||||
#define HTTP_UNCUNKED 0
|
||||
#define HTTP_CHUNKED 1
|
||||
|
||||
#define HTTP_KEEPALIVE_NO_INPUT 0
|
||||
#define HTTP_KEEPALIVE_ENABLE 1
|
||||
#define HTTP_KEEPALIVE_DISABLE 2
|
||||
|
||||
#define HTTP_REQTYPE_OTHERS 0
|
||||
#define HTTP_REQTYPE_LOGIN 1
|
||||
#define HTTP_REQTYPE_HEARTBEAT 2
|
||||
#define HTTP_REQTYPE_SINGLE_SQL 3
|
||||
#define HTTP_REQTYPE_MULTI_SQL 4
|
||||
|
||||
#define HTTP_CHECK_BODY_ERROR -1
|
||||
#define HTTP_CHECK_BODY_CONTINUE 0
|
||||
#define HTTP_CHECK_BODY_SUCCESS 1
|
||||
|
||||
#define HTTP_WRITE_RETRY_TIMES 500
|
||||
#define HTTP_WRITE_WAIT_TIME_MS 5
|
||||
#define HTTP_EXPIRED_TIME 60000
|
||||
#define HTTP_DELAY_CLOSE_TIME_MS 500
|
||||
|
||||
#define HTTP_COMPRESS_IDENTITY 0
|
||||
#define HTTP_COMPRESS_GZIP 2
|
||||
|
||||
#define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + TSDB_PASSWORD_LEN)
|
||||
|
||||
typedef enum {
|
||||
HTTP_SERVER_INIT,
|
||||
HTTP_SERVER_RUNNING,
|
||||
HTTP_SERVER_CLOSING,
|
||||
HTTP_SERVER_CLOSED
|
||||
} HttpServerStatus;
|
||||
|
||||
typedef enum {
|
||||
HTTP_CONTEXT_STATE_READY,
|
||||
HTTP_CONTEXT_STATE_HANDLING,
|
||||
HTTP_CONTEXT_STATE_DROPPING,
|
||||
HTTP_CONTEXT_STATE_CLOSED
|
||||
} HttpContextState;
|
||||
|
||||
struct HttpContext;
|
||||
struct HttpThread;
|
||||
|
||||
typedef struct {
|
||||
char id[HTTP_SESSION_ID_LEN];
|
||||
int refCount;
|
||||
void *taos;
|
||||
} HttpSession;
|
||||
|
||||
typedef enum {
|
||||
HTTP_CMD_TYPE_UN_SPECIFIED,
|
||||
HTTP_CMD_TYPE_CREATE_DB,
|
||||
HTTP_CMD_TYPE_CREATE_STBALE,
|
||||
HTTP_CMD_TYPE_INSERT
|
||||
} HttpSqlCmdType;
|
||||
|
||||
typedef enum { HTTP_CMD_STATE_NOT_RUN_YET, HTTP_CMD_STATE_RUN_FINISHED } HttpSqlCmdState;
|
||||
|
||||
typedef enum { HTTP_CMD_RETURN_TYPE_WITH_RETURN, HTTP_CMD_RETURN_TYPE_NO_RETURN } HttpSqlCmdReturnType;
|
||||
|
||||
typedef struct {
|
||||
// used by single cmd
|
||||
char *nativSql;
|
||||
int32_t numOfRows;
|
||||
int32_t code;
|
||||
|
||||
// these are the locations in the buffer
|
||||
int32_t tagNames[TSDB_MAX_TAGS];
|
||||
int32_t tagValues[TSDB_MAX_TAGS];
|
||||
int32_t timestamp;
|
||||
int32_t metric;
|
||||
int32_t stable;
|
||||
int32_t table;
|
||||
int32_t values;
|
||||
int32_t sql;
|
||||
|
||||
// used by multi-cmd
|
||||
int8_t cmdType;
|
||||
int8_t cmdReturnType;
|
||||
int8_t cmdState;
|
||||
int8_t tagNum;
|
||||
} HttpSqlCmd;
|
||||
|
||||
typedef struct {
|
||||
HttpSqlCmd *cmds;
|
||||
int16_t pos;
|
||||
int16_t size;
|
||||
int16_t maxSize;
|
||||
int32_t bufferPos;
|
||||
int32_t bufferSize;
|
||||
char * buffer;
|
||||
} HttpSqlCmds;
|
||||
|
||||
typedef struct {
|
||||
char *module;
|
||||
bool (*decodeFp)(struct HttpContext *pContext);
|
||||
} HttpDecodeMethod;
|
||||
|
||||
typedef struct {
|
||||
void (*startJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result);
|
||||
void (*stopJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd);
|
||||
bool (*buildQueryJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result, int numOfRows);
|
||||
void (*buildAffectRowJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int affectRows);
|
||||
void (*initJsonFp)(struct HttpContext *pContext);
|
||||
void (*cleanJsonFp)(struct HttpContext *pContext);
|
||||
bool (*checkFinishedFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code);
|
||||
void (*setNextCmdFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code);
|
||||
} HttpEncodeMethod;
|
||||
|
||||
typedef struct {
|
||||
char *pos;
|
||||
int32_t len;
|
||||
} HttpBuf;
|
||||
|
||||
typedef struct {
|
||||
char buffer[HTTP_BUFFER_SIZE];
|
||||
int bufsize;
|
||||
char *pLast;
|
||||
char *pCur;
|
||||
HttpBuf method;
|
||||
HttpBuf path[HTTP_MAX_URL]; // url: dbname/meter/query
|
||||
HttpBuf data; // body content
|
||||
HttpBuf token; // auth token
|
||||
HttpDecodeMethod *pMethod;
|
||||
} HttpParser;
|
||||
|
||||
typedef struct HttpContext {
|
||||
int32_t refCount;
|
||||
int fd;
|
||||
uint32_t accessTimes;
|
||||
uint32_t lastAccessTime;
|
||||
int32_t state;
|
||||
uint8_t httpVersion;
|
||||
uint8_t httpChunked;
|
||||
uint8_t httpKeepAlive; // http1.0 and not keep-alive, close connection immediately
|
||||
uint8_t acceptEncoding;
|
||||
uint8_t contentEncoding;
|
||||
uint8_t reqType;
|
||||
uint8_t parsed;
|
||||
char ipstr[22];
|
||||
char user[TSDB_USER_LEN]; // parsed from auth token or login message
|
||||
char pass[TSDB_PASSWORD_LEN];
|
||||
void * taos;
|
||||
void * ppContext;
|
||||
HttpSession *session;
|
||||
z_stream gzipStream;
|
||||
HttpParser parser;
|
||||
HttpSqlCmd singleCmd;
|
||||
HttpSqlCmds *multiCmds;
|
||||
JsonBuf * jsonBuf;
|
||||
void * timer;
|
||||
HttpEncodeMethod * encodeMethod;
|
||||
struct HttpThread *pThread;
|
||||
} HttpContext;
|
||||
|
||||
typedef struct HttpThread {
|
||||
pthread_t thread;
|
||||
HttpContext * pHead;
|
||||
pthread_mutex_t threadMutex;
|
||||
bool stop;
|
||||
int pollFd;
|
||||
int numOfFds;
|
||||
int threadId;
|
||||
char label[HTTP_LABEL_SIZE];
|
||||
bool (*processData)(HttpContext *pContext);
|
||||
} HttpThread;
|
||||
|
||||
typedef struct HttpServer {
|
||||
char label[HTTP_LABEL_SIZE];
|
||||
uint32_t serverIp;
|
||||
uint16_t serverPort;
|
||||
int fd;
|
||||
int numOfThreads;
|
||||
int methodScannerLen;
|
||||
int32_t requestNum;
|
||||
int32_t status;
|
||||
pthread_t thread;
|
||||
HttpThread * pThreads;
|
||||
void * contextCache;
|
||||
void * sessionCache;
|
||||
pthread_mutex_t serverMutex;
|
||||
HttpDecodeMethod *methodScanner[HTTP_METHOD_SCANNER_SIZE];
|
||||
bool (*processData)(HttpContext *pContext);
|
||||
} HttpServer;
|
||||
|
||||
extern const char *httpKeepAliveStr[];
|
||||
extern const char *httpVersionStr[];
|
||||
extern HttpServer tsHttpServer;
|
||||
|
||||
#endif
|
|
@ -97,4 +97,8 @@ void httpJsonPrint(JsonBuf* buf, const char* json, int len);
|
|||
// quick
|
||||
void httpJsonPairStatus(JsonBuf* buf, int code);
|
||||
|
||||
// http json printer
|
||||
JsonBuf* httpMallocJsonBuf(struct HttpContext* pContext);
|
||||
void httpFreeJsonBuf(struct HttpContext* pContext);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#ifndef TDENGINE_HTTP_RESP_H
|
||||
#define TDENGINE_HTTP_RESP_H
|
||||
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
|
||||
enum _httpRespTempl {
|
||||
HTTP_RESPONSE_JSON_OK,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_SERVER_H
|
||||
#define TDENGINE_HTTP_SERVER_H
|
||||
|
||||
#include "httpInt.h"
|
||||
|
||||
bool httpInitConnect();
|
||||
void httpCleanUpConnect();
|
||||
|
||||
void *httpInitServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle);
|
||||
void httpCleanUpServer(HttpServer *pServer);
|
||||
bool httpReadDataImp(HttpContext *pContext);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_SESSION_H
|
||||
#define TDENGINE_HTTP_SESSION_H
|
||||
|
||||
bool httpInitSessions();
|
||||
void httpCleanUpSessions();
|
||||
|
||||
// http session method
|
||||
void httpCreateSession(HttpContext *pContext, void *taos);
|
||||
void httpGetSession(HttpContext *pContext);
|
||||
void httpReleaseSession(HttpContext *pContext);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_SQL_H
|
||||
#define TDENGINE_HTTP_SQL_H
|
||||
|
||||
|
||||
int32_t httpAddToSqlCmdBuffer(HttpContext *pContext, const char *const format, ...);
|
||||
int32_t httpAddToSqlCmdBufferNoTerminal(HttpContext *pContext, const char *const format, ...);
|
||||
int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize);
|
||||
int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext);
|
||||
|
||||
bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize);
|
||||
bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize);
|
||||
bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int bufferSize);
|
||||
void httpFreeMultiCmds(HttpContext *pContext);
|
||||
|
||||
HttpSqlCmd *httpNewSqlCmd(HttpContext *pContext);
|
||||
HttpSqlCmd *httpCurrSqlCmd(HttpContext *pContext);
|
||||
int httpCurSqlCmdPos(HttpContext *pContext);
|
||||
|
||||
void httpTrimTableName(char *name);
|
||||
int httpShrinkTableName(HttpContext *pContext, int pos, char *name);
|
||||
char *httpGetCmdsString(HttpContext *pContext, int pos);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_HTTP_UTIL_H
|
||||
#define TDENGINE_HTTP_UTIL_H
|
||||
|
||||
bool httpCheckUsedbSql(char *sql);
|
||||
void httpTimeToString(time_t t, char *buf, int buflen);
|
||||
|
||||
bool httpUrlMatch(HttpContext *pContext, int pos, char *cmp);
|
||||
bool httpParseRequest(HttpContext *pContext);
|
||||
int httpCheckReadCompleted(HttpContext *pContext);
|
||||
void httpReadDirtyData(HttpContext *pContext);
|
||||
|
||||
int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData);
|
||||
int httpGzipCompressInit(HttpContext *pContext);
|
||||
int httpGzipCompress(HttpContext *pContext, char *inSrcData, int32_t inSrcDataLen,
|
||||
char *outDestData, int32_t *outDestDataLen, bool isTheLast);
|
||||
|
||||
// http request parser
|
||||
void httpAddMethod(HttpServer *pServer, HttpDecodeMethod *pMethod);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -16,15 +16,11 @@
|
|||
#ifndef TDENGINE_REST_HANDLE_H
|
||||
#define TDENGINE_REST_HANDLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "http.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpUtil.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpSql.h"
|
||||
|
||||
#define REST_ROOT_URL_POS 0
|
||||
#define REST_ACTION_URL_POS 1
|
||||
|
|
|
@ -16,16 +16,11 @@
|
|||
#ifndef TDENGINE_TG_HANDLE_H
|
||||
#define TDENGINE_TG_HANDLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "http.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpUtil.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpSql.h"
|
||||
|
||||
#define TG_ROOT_URL_POS 0
|
||||
#define TG_DB_URL_POS 1
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
#include "tkey.h"
|
||||
#include "tutil.h"
|
||||
#include "http.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpAuth.h"
|
||||
|
||||
#define KEY_DES_4 4971256377704625728L
|
||||
|
||||
|
@ -73,6 +73,7 @@ bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len) {
|
|||
unsigned char *base64 = base64_decode(token, len, &outlen);
|
||||
if (base64 == NULL || outlen == 0) {
|
||||
httpError("context:%p, fd:%d, ip:%s, taosd token:%s parsed error", pContext, pContext->fd, pContext->ipstr, token);
|
||||
if (base64) free(base64);
|
||||
return false;
|
||||
}
|
||||
if (outlen != (TSDB_USER_LEN + TSDB_PASSWORD_LEN)) {
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "os.h"
|
||||
#include "taosmsg.h"
|
||||
#include "tsocket.h"
|
||||
#include "tutil.h"
|
||||
#include "ttime.h"
|
||||
#include "ttimer.h"
|
||||
#include "tglobal.h"
|
||||
#include "tcache.h"
|
||||
#include "hash.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpSql.h"
|
||||
#include "httpSession.h"
|
||||
|
||||
static void httpRemoveContextFromEpoll(HttpContext *pContext) {
|
||||
HttpThread *pThread = pContext->pThread;
|
||||
if (pContext->fd >= 0) {
|
||||
epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL);
|
||||
taosCloseSocket(pContext->fd);
|
||||
pContext->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void httpDestroyContext(void *data) {
|
||||
HttpContext *pContext = *(HttpContext **)data;
|
||||
if (pContext->fd > 0) tclose(pContext->fd);
|
||||
|
||||
HttpThread *pThread = pContext->pThread;
|
||||
httpRemoveContextFromEpoll(pContext);
|
||||
httpReleaseSession(pContext);
|
||||
atomic_sub_fetch_32(&pThread->numOfFds, 1);
|
||||
|
||||
pContext->pThread = 0;
|
||||
pContext->state = HTTP_CONTEXT_STATE_CLOSED;
|
||||
|
||||
// avoid double free
|
||||
httpFreeJsonBuf(pContext);
|
||||
httpFreeMultiCmds(pContext);
|
||||
|
||||
httpTrace("context:%p, is destroyed, refCount:%d", pContext, pContext->refCount);
|
||||
tfree(pContext);
|
||||
}
|
||||
|
||||
bool httpInitContexts() {
|
||||
tsHttpServer.contextCache = taosCacheInitWithCb(2, httpDestroyContext);
|
||||
if (tsHttpServer.contextCache == NULL) {
|
||||
httpError("failed to init context cache");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void httpCleanupContexts() {
|
||||
if (tsHttpServer.contextCache != NULL) {
|
||||
SCacheObj *cache = tsHttpServer.contextCache;
|
||||
httpPrint("context cache is cleanuping, size:%d", taosHashGetSize(cache->pHashTable));
|
||||
taosCacheCleanup(tsHttpServer.contextCache);
|
||||
tsHttpServer.contextCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char *httpContextStateStr(HttpContextState state) {
|
||||
switch (state) {
|
||||
case HTTP_CONTEXT_STATE_READY:
|
||||
return "ready";
|
||||
case HTTP_CONTEXT_STATE_HANDLING:
|
||||
return "handling";
|
||||
case HTTP_CONTEXT_STATE_DROPPING:
|
||||
return "dropping";
|
||||
case HTTP_CONTEXT_STATE_CLOSED:
|
||||
return "closed";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void httpNotifyContextClose(HttpContext *pContext) {
|
||||
shutdown(pContext->fd, SHUT_WR);
|
||||
}
|
||||
|
||||
bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState) {
|
||||
return (atomic_val_compare_exchange_32(&pContext->state, srcState, destState) == srcState);
|
||||
}
|
||||
|
||||
HttpContext *httpCreateContext(int32_t fd) {
|
||||
HttpContext *pContext = calloc(1, sizeof(HttpContext));
|
||||
if (pContext == NULL) return NULL;
|
||||
|
||||
char contextStr[16] = {0};
|
||||
snprintf(contextStr, sizeof(contextStr), "%p", pContext);
|
||||
|
||||
pContext->fd = fd;
|
||||
pContext->httpVersion = HTTP_VERSION_10;
|
||||
pContext->lastAccessTime = taosGetTimestampSec();
|
||||
pContext->state = HTTP_CONTEXT_STATE_READY;
|
||||
|
||||
HttpContext **ppContext = taosCachePut(tsHttpServer.contextCache, contextStr, &pContext, sizeof(HttpContext *), 3);
|
||||
pContext->ppContext = ppContext;
|
||||
httpTrace("context:%p, fd:%d, is created, item:%p", pContext, fd, ppContext);
|
||||
|
||||
// set the ref to 0
|
||||
taosCacheRelease(tsHttpServer.contextCache, (void**)&ppContext, false);
|
||||
|
||||
return pContext;
|
||||
}
|
||||
|
||||
HttpContext *httpGetContext(void *ptr) {
|
||||
char contextStr[16] = {0};
|
||||
snprintf(contextStr, sizeof(contextStr), "%p", ptr);
|
||||
|
||||
HttpContext **ppContext = taosCacheAcquireByName(tsHttpServer.contextCache, contextStr);
|
||||
|
||||
if (ppContext) {
|
||||
HttpContext *pContext = *ppContext;
|
||||
if (pContext) {
|
||||
int32_t refCount = atomic_add_fetch_32(&pContext->refCount, 1);
|
||||
httpTrace("context:%p, fd:%d, is accquired, refCount:%d", pContext, pContext->fd, refCount);
|
||||
return pContext;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void httpReleaseContext(HttpContext *pContext) {
|
||||
int32_t refCount = atomic_sub_fetch_32(&pContext->refCount, 1);
|
||||
assert(refCount >= 0);
|
||||
httpTrace("context:%p, fd:%d, is releasd, refCount:%d", pContext, pContext->fd, refCount);
|
||||
|
||||
HttpContext **ppContext = pContext->ppContext;
|
||||
taosCacheRelease(tsHttpServer.contextCache, (void **)(&ppContext), false);
|
||||
}
|
||||
|
||||
bool httpInitContext(HttpContext *pContext) {
|
||||
pContext->accessTimes++;
|
||||
pContext->lastAccessTime = taosGetTimestampSec();
|
||||
pContext->httpVersion = HTTP_VERSION_10;
|
||||
pContext->httpKeepAlive = HTTP_KEEPALIVE_NO_INPUT;
|
||||
pContext->httpChunked = HTTP_UNCUNKED;
|
||||
pContext->acceptEncoding = HTTP_COMPRESS_IDENTITY;
|
||||
pContext->contentEncoding = HTTP_COMPRESS_IDENTITY;
|
||||
pContext->reqType = HTTP_REQTYPE_OTHERS;
|
||||
pContext->encodeMethod = NULL;
|
||||
pContext->timer = NULL;
|
||||
memset(&pContext->singleCmd, 0, sizeof(HttpSqlCmd));
|
||||
|
||||
HttpParser *pParser = &pContext->parser;
|
||||
memset(pParser, 0, sizeof(HttpParser));
|
||||
pParser->pCur = pParser->pLast = pParser->buffer;
|
||||
|
||||
httpTrace("context:%p, fd:%d, ip:%s, thread:%s, accessTimes:%d, parsed:%d",
|
||||
pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->accessTimes, pContext->parsed);
|
||||
return true;
|
||||
}
|
||||
|
||||
void httpCloseContextByApp(HttpContext *pContext) {
|
||||
pContext->parsed = false;
|
||||
|
||||
bool keepAlive = true;
|
||||
if (pContext->httpVersion == HTTP_VERSION_10 && pContext->httpKeepAlive != HTTP_KEEPALIVE_ENABLE) {
|
||||
keepAlive = false;
|
||||
} else if (pContext->httpVersion != HTTP_VERSION_10 && pContext->httpKeepAlive == HTTP_KEEPALIVE_DISABLE) {
|
||||
keepAlive = false;
|
||||
} else {}
|
||||
|
||||
if (keepAlive) {
|
||||
if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_READY)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:handling, keepAlive:true, reuse connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpRemoveContextFromEpoll(pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:dropping, keepAlive:true, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, reuse connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpRemoveContextFromEpoll(pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
} else {
|
||||
httpRemoveContextFromEpoll(pContext);
|
||||
httpError("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:true, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state);
|
||||
}
|
||||
} else {
|
||||
httpRemoveContextFromEpoll(pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:false, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state);
|
||||
}
|
||||
|
||||
httpReleaseContext(pContext);
|
||||
}
|
||||
|
||||
void httpCloseContextByServer(HttpContext *pContext) {
|
||||
if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_DROPPING)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll finished, still used by app", pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_DROPPING)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll already finished, wait app finished", pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll finished, close context", pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll finished, will be closed soon", pContext, pContext->fd, pContext->ipstr);
|
||||
} else {
|
||||
httpError("context:%p, fd:%d, ip:%s, unknown state:%d", pContext, pContext->fd, pContext->ipstr, pContext->state);
|
||||
}
|
||||
|
||||
pContext->parsed = false;
|
||||
httpRemoveContextFromEpoll(pContext);
|
||||
httpReleaseContext(pContext);
|
||||
}
|
|
@ -19,11 +19,12 @@
|
|||
#include "tglobal.h"
|
||||
#include "tsocket.h"
|
||||
#include "ttimer.h"
|
||||
#include "http.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpAuth.h"
|
||||
#include "httpServer.h"
|
||||
#include "httpContext.h"
|
||||
#include "httpHandle.h"
|
||||
|
||||
void httpToLowerUrl(char* url) {
|
||||
/*ignore case */
|
||||
|
@ -58,6 +59,10 @@ bool httpParseURL(HttpContext* pContext) {
|
|||
HttpParser* pParser = &pContext->parser;
|
||||
char* pSeek;
|
||||
char* pEnd = strchr(pParser->pLast, ' ');
|
||||
if (pEnd == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*pParser->pLast != '/') {
|
||||
httpSendErrorResp(pContext, HTTP_UNSUPPORT_URL);
|
||||
return false;
|
||||
|
@ -159,7 +164,7 @@ bool httpGetHttpMethod(HttpContext* pContext) {
|
|||
bool httpGetDecodeMethod(HttpContext* pContext) {
|
||||
HttpParser* pParser = &pContext->parser;
|
||||
|
||||
HttpServer* pServer = pContext->pThread->pServer;
|
||||
HttpServer* pServer = &tsHttpServer;
|
||||
int methodLen = pServer->methodScannerLen;
|
||||
for (int i = 0; i < methodLen; i++) {
|
||||
HttpDecodeMethod* method = pServer->methodScanner[i];
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "httpCode.h"
|
||||
#include "httpJson.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpUtil.h"
|
||||
|
||||
#define MAX_NUM_STR_SZ 25
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "httpResp.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpJson.h"
|
||||
#include "httpContext.h"
|
||||
|
||||
const char *httpKeepAliveStr[] = {"", "Connection: Keep-Alive\r\n", "Connection: Close\r\n"};
|
||||
|
||||
|
|
|
@ -21,244 +21,15 @@
|
|||
#include "ttime.h"
|
||||
#include "ttimer.h"
|
||||
#include "tglobal.h"
|
||||
#include "http.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpContext.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpUtil.h"
|
||||
|
||||
#ifndef EPOLLWAKEUP
|
||||
#define EPOLLWAKEUP (1u << 29)
|
||||
#endif
|
||||
|
||||
const char* httpContextStateStr(HttpContextState state) {
|
||||
switch (state) {
|
||||
case HTTP_CONTEXT_STATE_READY:
|
||||
return "ready";
|
||||
case HTTP_CONTEXT_STATE_HANDLING:
|
||||
return "handling";
|
||||
case HTTP_CONTEXT_STATE_DROPPING:
|
||||
return "dropping";
|
||||
case HTTP_CONTEXT_STATE_CLOSED:
|
||||
return "closed";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void httpRemoveContextFromEpoll(HttpThread *pThread, HttpContext *pContext) {
|
||||
if (pContext->fd >= 0) {
|
||||
epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL);
|
||||
taosCloseSocket(pContext->fd);
|
||||
pContext->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState) {
|
||||
return (atomic_val_compare_exchange_32(&pContext->state, srcState, destState) == srcState);
|
||||
}
|
||||
|
||||
void httpFreeContext(HttpServer *pServer, HttpContext *pContext);
|
||||
|
||||
/**
|
||||
* context will be reused while connection exist
|
||||
* multiCmds and jsonBuf will be malloc after taos_query_a called
|
||||
* and won't be freed until connection closed
|
||||
*/
|
||||
HttpContext *httpCreateContext(HttpServer *pServer) {
|
||||
HttpContext *pContext = (HttpContext *)taosMemPoolMalloc(pServer->pContextPool);
|
||||
if (pContext != NULL) {
|
||||
pContext->fromMemPool = 1;
|
||||
httpTrace("context:%p, is malloced from mempool", pContext);
|
||||
} else {
|
||||
pContext = (HttpContext *)malloc(sizeof(HttpContext));
|
||||
if (pContext == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
memset(pContext, 0, sizeof(HttpContext));
|
||||
}
|
||||
httpTrace("context:%p, is malloced from raw memory", pContext);
|
||||
}
|
||||
|
||||
pContext->signature = pContext;
|
||||
pContext->httpVersion = HTTP_VERSION_10;
|
||||
pContext->lastAccessTime = taosGetTimestampSec();
|
||||
pContext->state = HTTP_CONTEXT_STATE_READY;
|
||||
return pContext;
|
||||
}
|
||||
|
||||
void httpFreeContext(HttpServer *pServer, HttpContext *pContext) {
|
||||
if (pContext->fromMemPool) {
|
||||
httpTrace("context:%p, is freed from mempool", pContext);
|
||||
taosMemPoolFree(pServer->pContextPool, (char *)pContext);
|
||||
} else {
|
||||
httpTrace("context:%p, is freed from raw memory", pContext);
|
||||
tfree(pContext);
|
||||
}
|
||||
}
|
||||
|
||||
void httpCleanUpContextTimer(HttpContext *pContext) {
|
||||
if (pContext->timer != NULL) {
|
||||
taosTmrStopA(&pContext->timer);
|
||||
//httpTrace("context:%p, ip:%s, close timer:%p", pContext, pContext->ipstr, pContext->timer);
|
||||
pContext->timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void httpCleanUpContext(HttpContext *pContext, void *unused) {
|
||||
httpTrace("context:%p, start the clean up operation, sig:%p", pContext, pContext->signature);
|
||||
void *sig = atomic_val_compare_exchange_ptr(&pContext->signature, pContext, 0);
|
||||
if (sig == NULL) {
|
||||
httpTrace("context:%p is freed by another thread.", pContext);
|
||||
return;
|
||||
}
|
||||
|
||||
HttpThread *pThread = pContext->pThread;
|
||||
|
||||
httpCleanUpContextTimer(pContext);
|
||||
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
|
||||
httpRestoreSession(pContext);
|
||||
|
||||
pthread_mutex_lock(&pThread->threadMutex);
|
||||
|
||||
pThread->numOfFds--;
|
||||
if (pThread->numOfFds < 0) {
|
||||
httpError("context:%p, ip:%s, thread:%s, number of FDs:%d shall never be negative",
|
||||
pContext, pContext->ipstr, pThread->label, pThread->numOfFds);
|
||||
pThread->numOfFds = 0;
|
||||
}
|
||||
|
||||
// remove from the link list
|
||||
if (pContext->prev) {
|
||||
(pContext->prev)->next = pContext->next;
|
||||
} else {
|
||||
pThread->pHead = pContext->next;
|
||||
}
|
||||
|
||||
if (pContext->next) {
|
||||
(pContext->next)->prev = pContext->prev;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&pThread->threadMutex);
|
||||
|
||||
httpTrace("context:%p, ip:%s, thread:%s, numOfFds:%d, context is cleaned up", pContext, pContext->ipstr,
|
||||
pThread->label, pThread->numOfFds);
|
||||
|
||||
pContext->signature = 0;
|
||||
pContext->fd = -1;
|
||||
pContext->pThread = 0;
|
||||
pContext->prev = 0;
|
||||
pContext->next = 0;
|
||||
pContext->state = HTTP_CONTEXT_STATE_READY;
|
||||
|
||||
// avoid double free
|
||||
httpFreeJsonBuf(pContext);
|
||||
httpFreeMultiCmds(pContext);
|
||||
httpFreeContext(pThread->pServer, pContext);
|
||||
}
|
||||
|
||||
bool httpInitContext(HttpContext *pContext) {
|
||||
pContext->accessTimes++;
|
||||
pContext->lastAccessTime = taosGetTimestampSec();
|
||||
pContext->httpVersion = HTTP_VERSION_10;
|
||||
pContext->httpKeepAlive = HTTP_KEEPALIVE_NO_INPUT;
|
||||
pContext->httpChunked = HTTP_UNCUNKED;
|
||||
pContext->acceptEncoding = HTTP_COMPRESS_IDENTITY;
|
||||
pContext->contentEncoding = HTTP_COMPRESS_IDENTITY;
|
||||
pContext->reqType = HTTP_REQTYPE_OTHERS;
|
||||
pContext->encodeMethod = NULL;
|
||||
pContext->timer = NULL;
|
||||
memset(&pContext->singleCmd, 0, sizeof(HttpSqlCmd));
|
||||
|
||||
HttpParser *pParser = &pContext->parser;
|
||||
memset(pParser, 0, sizeof(HttpParser));
|
||||
pParser->pCur = pParser->pLast = pParser->buffer;
|
||||
|
||||
httpTrace("context:%p, fd:%d, ip:%s, thread:%s, accessTimes:%d, parsed:%d",
|
||||
pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->accessTimes, pContext->parsed);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void httpCloseContext(HttpThread *pThread, HttpContext *pContext) {
|
||||
taosTmrReset((TAOS_TMR_CALLBACK)httpCleanUpContext, HTTP_DELAY_CLOSE_TIME_MS, pContext, pThread->pServer->timerHandle, &pContext->timer);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s will be closed after:%d ms, timer:%p",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), HTTP_DELAY_CLOSE_TIME_MS, pContext->timer);
|
||||
}
|
||||
|
||||
void httpCloseContextByApp(HttpContext *pContext) {
|
||||
HttpThread *pThread = pContext->pThread;
|
||||
pContext->parsed = false;
|
||||
|
||||
bool keepAlive = true;
|
||||
if (pContext->httpVersion == HTTP_VERSION_10 && pContext->httpKeepAlive != HTTP_KEEPALIVE_ENABLE) {
|
||||
keepAlive = false;
|
||||
} else if (pContext->httpVersion != HTTP_VERSION_10 && pContext->httpKeepAlive == HTTP_KEEPALIVE_DISABLE) {
|
||||
keepAlive = false;
|
||||
} else {}
|
||||
|
||||
if (keepAlive) {
|
||||
if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_READY)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:handling, keepAlive:true, reuse connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:dropping, keepAlive:true, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
httpCloseContext(pThread, pContext);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, reuse connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr);
|
||||
httpCloseContext(pThread, pContext);
|
||||
} else {
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpError("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:true, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state);
|
||||
httpCloseContext(pThread, pContext);
|
||||
}
|
||||
} else {
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:false, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state);
|
||||
httpCloseContext(pThread, pContext);
|
||||
}
|
||||
}
|
||||
|
||||
void httpCloseContextByServer(HttpThread *pThread, HttpContext *pContext) {
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
pContext->parsed = false;
|
||||
|
||||
if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_DROPPING)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll finished, still used by app", pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_DROPPING)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll already finished, wait app finished", pContext, pContext->fd, pContext->ipstr);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll finished, close context", pContext, pContext->fd, pContext->ipstr);
|
||||
httpCloseContext(pThread, pContext);
|
||||
} else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, epoll finished, will be closed soon", pContext, pContext->fd, pContext->ipstr);
|
||||
httpCloseContext(pThread, pContext);
|
||||
} else {
|
||||
httpError("context:%p, fd:%d, ip:%s, unknown state:%d", pContext, pContext->fd, pContext->ipstr, pContext->state);
|
||||
httpCloseContext(pThread, pContext);
|
||||
}
|
||||
}
|
||||
|
||||
void httpCloseContextByServerForExpired(void *param, void *tmrId) {
|
||||
HttpContext *pContext = (HttpContext *)param;
|
||||
httpRemoveContextFromEpoll(pContext->pThread, pContext);
|
||||
httpError("context:%p, fd:%d, ip:%s, read http body error, time expired, timer:%p", pContext, pContext->fd, pContext->ipstr, tmrId);
|
||||
httpSendErrorResp(pContext, HTTP_PARSE_BODY_ERROR);
|
||||
httpCloseContextByServer(pContext->pThread, pContext);
|
||||
}
|
||||
|
||||
|
||||
static void httpStopThread(HttpThread* pThread) {
|
||||
pThread->stop = true;
|
||||
|
||||
|
@ -281,19 +52,13 @@ static void httpStopThread(HttpThread* pThread) {
|
|||
|
||||
close(pThread->pollFd);
|
||||
pthread_mutex_destroy(&(pThread->threadMutex));
|
||||
|
||||
//while (pThread->pHead) {
|
||||
// httpCleanUpContext(pThread->pHead, 0);
|
||||
//}
|
||||
}
|
||||
|
||||
void httpCleanUpConnect() {
|
||||
HttpServer *pServer = &tsHttpServer;
|
||||
if (pServer->pThreads == NULL) return;
|
||||
|
||||
void httpCleanUpConnect(HttpServer *pServer) {
|
||||
if (pServer == NULL) return;
|
||||
|
||||
shutdown(pServer->fd, SHUT_RD);
|
||||
pthread_join(pServer->thread, NULL);
|
||||
|
||||
for (int i = 0; i < pServer->numOfThreads; ++i) {
|
||||
HttpThread* pThread = pServer->pThreads + i;
|
||||
if (pThread != NULL) {
|
||||
|
@ -302,19 +67,10 @@ void httpCleanUpConnect(HttpServer *pServer) {
|
|||
}
|
||||
|
||||
tfree(pServer->pThreads);
|
||||
pServer->pThreads = NULL;
|
||||
httpTrace("http server:%s is cleaned up", pServer->label);
|
||||
}
|
||||
|
||||
// read all the data, then just discard it
|
||||
void httpReadDirtyData(HttpContext *pContext) {
|
||||
int fd = pContext->fd;
|
||||
char data[1024] = {0};
|
||||
int len = (int)taosReadSocket(fd, data, 1024);
|
||||
while (len >= sizeof(data)) {
|
||||
len = (int)taosReadSocket(fd, data, 1024);
|
||||
}
|
||||
}
|
||||
|
||||
bool httpReadDataImp(HttpContext *pContext) {
|
||||
HttpParser *pParser = &pContext->parser;
|
||||
|
||||
|
@ -338,11 +94,10 @@ bool httpReadDataImp(HttpContext *pContext) {
|
|||
}
|
||||
|
||||
if (pParser->bufsize >= (HTTP_BUFFER_SIZE - HTTP_STEP_SIZE)) {
|
||||
httpReadDirtyData(pContext);
|
||||
httpError("context:%p, fd:%d, ip:%s, thread:%s, request big than:%d",
|
||||
pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, HTTP_BUFFER_SIZE);
|
||||
httpRemoveContextFromEpoll(pContext->pThread, pContext);
|
||||
httpSendErrorResp(pContext, HTTP_REQUSET_TOO_BIG);
|
||||
httpNotifyContextClose(pContext);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +107,7 @@ bool httpReadDataImp(HttpContext *pContext) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool httpDecompressData(HttpContext *pContext) {
|
||||
static bool httpDecompressData(HttpContext *pContext) {
|
||||
if (pContext->contentEncoding != HTTP_COMPRESS_GZIP) {
|
||||
httpDump("context:%p, fd:%d, ip:%s, content:%s", pContext, pContext->fd, pContext->ipstr, pContext->parser.data.pos);
|
||||
return true;
|
||||
|
@ -382,45 +137,43 @@ bool httpDecompressData(HttpContext *pContext) {
|
|||
return ret == 0;
|
||||
}
|
||||
|
||||
bool httpReadData(HttpThread *pThread, HttpContext *pContext) {
|
||||
static bool httpReadData(HttpContext *pContext) {
|
||||
if (!pContext->parsed) {
|
||||
httpInitContext(pContext);
|
||||
}
|
||||
|
||||
if (!httpReadDataImp(pContext)) {
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpNotifyContextClose(pContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!httpParseRequest(pContext)) {
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpNotifyContextClose(pContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
int ret = httpCheckReadCompleted(pContext);
|
||||
if (ret == HTTP_CHECK_BODY_CONTINUE) {
|
||||
taosTmrReset(httpCloseContextByServerForExpired, HTTP_EXPIRED_TIME, pContext, pThread->pServer->timerHandle, &pContext->timer);
|
||||
//httpTrace("context:%p, fd:%d, ip:%s, not finished yet, try another times, timer:%p", pContext, pContext->fd, pContext->ipstr, pContext->timer);
|
||||
//httpTrace("context:%p, fd:%d, ip:%s, not finished yet, wait another event", pContext, pContext->fd, pContext->ipstr);
|
||||
return false;
|
||||
} else if (ret == HTTP_CHECK_BODY_SUCCESS){
|
||||
httpCleanUpContextTimer(pContext);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, thread:%s, read size:%d, dataLen:%d",
|
||||
pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->parser.bufsize, pContext->parser.data.len);
|
||||
if (httpDecompressData(pContext)) {
|
||||
return true;
|
||||
} else {
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpNotifyContextClose(pContext);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
httpCleanUpContextTimer(pContext);
|
||||
httpError("context:%p, fd:%d, ip:%s, failed to read http body, close connect", pContext, pContext->fd, pContext->ipstr);
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpNotifyContextClose(pContext);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void httpProcessHttpData(void *param) {
|
||||
static void httpProcessHttpData(void *param) {
|
||||
HttpServer *pServer = &tsHttpServer;
|
||||
HttpThread *pThread = (HttpThread *)param;
|
||||
HttpContext *pContext;
|
||||
int fdNum;
|
||||
|
@ -441,77 +194,72 @@ void httpProcessHttpData(void *param) {
|
|||
if (fdNum <= 0) continue;
|
||||
|
||||
for (int i = 0; i < fdNum; ++i) {
|
||||
pContext = events[i].data.ptr;
|
||||
if (pContext->signature != pContext || pContext->pThread != pThread || pContext->fd <= 0) {
|
||||
pContext = httpGetContext(events[i].data.ptr);
|
||||
if (pContext == NULL) {
|
||||
httpError("context:%p, is already released, close connect", events[i].data.ptr);
|
||||
//epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
|
||||
//tclose(events[i].data.fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].events & EPOLLPRI) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLPRI events occured, accessed:%d, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes);
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpCloseContextByServer(pContext);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].events & EPOLLRDHUP) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLRDHUP events occured, accessed:%d, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes);
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpCloseContextByServer(pContext);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].events & EPOLLERR) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLERR events occured, accessed:%d, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes);
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpCloseContextByServer(pContext);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (events[i].events & EPOLLHUP) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLHUP events occured, accessed:%d, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes);
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
httpCloseContextByServer(pContext);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, not in ready state, ignore read events",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state));
|
||||
httpReleaseContext(pContext);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pContext->pThread->pServer->online) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, server is not online, accessed:%d, close connect",
|
||||
pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes);
|
||||
httpRemoveContextFromEpoll(pThread, pContext);
|
||||
httpReadDirtyData(pContext);
|
||||
if (pServer->status != HTTP_SERVER_RUNNING) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, state:%s, server is not running, accessed:%d, close connect", pContext,
|
||||
pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes);
|
||||
httpSendErrorResp(pContext, HTTP_SERVER_OFFLINE);
|
||||
httpCloseContextByServer(pThread, pContext);
|
||||
continue;
|
||||
httpNotifyContextClose(pContext);
|
||||
} else {
|
||||
if (httpReadData(pThread, pContext)) {
|
||||
if (httpReadData(pContext)) {
|
||||
(*(pThread->processData))(pContext);
|
||||
atomic_fetch_add_32(&pThread->pServer->requestNum, 1);
|
||||
atomic_fetch_add_32(&pServer->requestNum, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* httpAcceptHttpConnection(void *arg) {
|
||||
static void *httpAcceptHttpConnection(void *arg) {
|
||||
int connFd = -1;
|
||||
struct sockaddr_in clientAddr;
|
||||
int threadId = 0;
|
||||
HttpThread * pThread;
|
||||
HttpServer * pServer;
|
||||
HttpContext * pContext;
|
||||
int totalFds;
|
||||
|
||||
pServer = (HttpServer *)arg;
|
||||
HttpServer * pServer = &tsHttpServer;
|
||||
HttpThread * pThread = NULL;
|
||||
HttpContext * pContext = NULL;
|
||||
int totalFds = 0;
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
|
@ -521,12 +269,12 @@ void* httpAcceptHttpConnection(void *arg) {
|
|||
pServer->fd = taosOpenTcpServerSocket(pServer->serverIp, pServer->serverPort);
|
||||
|
||||
if (pServer->fd < 0) {
|
||||
httpError("http server:%s, failed to open http socket, ip:%s:%u error:%s", pServer->label, taosIpStr(pServer->serverIp),
|
||||
pServer->serverPort, strerror(errno));
|
||||
httpError("http server:%s, failed to open http socket, ip:%s:%u error:%s", pServer->label,
|
||||
taosIpStr(pServer->serverIp), pServer->serverPort, strerror(errno));
|
||||
return NULL;
|
||||
} else {
|
||||
httpPrint("http service init success at %u", pServer->serverPort);
|
||||
pServer->online = true;
|
||||
httpPrint("http server init success at %u", pServer->serverPort);
|
||||
pServer->status = HTTP_SERVER_RUNNING;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
@ -534,10 +282,10 @@ void* httpAcceptHttpConnection(void *arg) {
|
|||
connFd = (int)accept(pServer->fd, (struct sockaddr *)&clientAddr, &addrlen);
|
||||
if (connFd == -1) {
|
||||
if (errno == EINVAL) {
|
||||
httpTrace("%s HTTP server socket was shutdown, exiting...", pServer->label);
|
||||
httpTrace("http server:%s socket was shutdown, exiting...", pServer->label);
|
||||
break;
|
||||
}
|
||||
httpError("http server:%s, accept connect failure, errno:%d, reason:%s", pServer->label, errno, strerror(errno));
|
||||
httpError("http server:%s, accept connect failure, errno:%d reason:%s", pServer->label, errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -547,8 +295,8 @@ void* httpAcceptHttpConnection(void *arg) {
|
|||
}
|
||||
|
||||
if (totalFds > tsHttpCacheSessions * 100) {
|
||||
httpError("fd:%d, ip:%s:%u, totalFds:%d larger than httpCacheSessions:%d*100, refuse connection",
|
||||
connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), totalFds, tsHttpCacheSessions);
|
||||
httpError("fd:%d, ip:%s:%u, totalFds:%d larger than httpCacheSessions:%d*100, refuse connection", connFd,
|
||||
inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), totalFds, tsHttpCacheSessions);
|
||||
taosCloseSocket(connFd);
|
||||
continue;
|
||||
}
|
||||
|
@ -559,7 +307,7 @@ void* httpAcceptHttpConnection(void *arg) {
|
|||
// pick up the thread to handle this connection
|
||||
pThread = pServer->pThreads + threadId;
|
||||
|
||||
pContext = httpCreateContext(pServer);
|
||||
pContext = httpCreateContext(connFd);
|
||||
if (pContext == NULL) {
|
||||
httpError("fd:%d, ip:%s:%u, no enough resource to allocate http context", connFd, inet_ntoa(clientAddr.sin_addr),
|
||||
htons(clientAddr.sin_port));
|
||||
|
@ -567,39 +315,24 @@ void* httpAcceptHttpConnection(void *arg) {
|
|||
continue;
|
||||
}
|
||||
|
||||
httpTrace("context:%p, fd:%d, ip:%s:%u, thread:%s, numOfFds:%d, totalFds:%d, accept a new connection",
|
||||
pContext, connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), pThread->label,
|
||||
pThread->numOfFds, totalFds);
|
||||
|
||||
pContext->fd = connFd;
|
||||
sprintf(pContext->ipstr, "%s:%d", inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port));
|
||||
pContext->pThread = pThread;
|
||||
sprintf(pContext->ipstr, "%s:%u", inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port));
|
||||
|
||||
struct epoll_event event;
|
||||
event.events = EPOLLIN | EPOLLPRI | EPOLLWAKEUP | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
|
||||
|
||||
event.data.ptr = pContext;
|
||||
if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, connFd, &event) < 0) {
|
||||
httpError("context:%p, fd:%d, ip:%s:%u, thread:%s, failed to add http fd for epoll, error:%s",
|
||||
pContext, connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), pThread->label,
|
||||
strerror(errno));
|
||||
httpFreeContext(pThread->pServer, pContext);
|
||||
tclose(connFd);
|
||||
httpError("context:%p, fd:%d, ip:%s, thread:%s, failed to add http fd for epoll, error:%s", pContext, connFd,
|
||||
pContext->ipstr, pThread->label, strerror(errno));
|
||||
tclose(pContext->fd);
|
||||
httpReleaseContext(pContext);
|
||||
continue;
|
||||
}
|
||||
|
||||
// notify the data process, add into the FdObj list
|
||||
pthread_mutex_lock(&(pThread->threadMutex));
|
||||
|
||||
pContext->next = pThread->pHead;
|
||||
|
||||
if (pThread->pHead) (pThread->pHead)->prev = pContext;
|
||||
|
||||
pThread->pHead = pContext;
|
||||
|
||||
pThread->numOfFds++;
|
||||
|
||||
pthread_mutex_unlock(&(pThread->threadMutex));
|
||||
atomic_add_fetch_32(&pThread->numOfFds, 1);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, thread:%s numOfFds:%d totalFds:%d, accept a new connection", pContext, connFd,
|
||||
pContext->ipstr, pThread->label, pThread->numOfFds, totalFds);
|
||||
|
||||
// pick up next thread for next connection
|
||||
threadId++;
|
||||
|
@ -610,21 +343,17 @@ void* httpAcceptHttpConnection(void *arg) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool httpInitConnect(HttpServer *pServer) {
|
||||
int i;
|
||||
HttpThread * pThread;
|
||||
|
||||
pServer->pThreads = (HttpThread *)malloc(sizeof(HttpThread) * (size_t)pServer->numOfThreads);
|
||||
bool httpInitConnect() {
|
||||
HttpServer *pServer = &tsHttpServer;
|
||||
pServer->pThreads = calloc(pServer->numOfThreads, sizeof(HttpThread));
|
||||
if (pServer->pThreads == NULL) {
|
||||
httpError("init error no enough memory");
|
||||
return false;
|
||||
}
|
||||
memset(pServer->pThreads, 0, sizeof(HttpThread) * (size_t)pServer->numOfThreads);
|
||||
|
||||
pThread = pServer->pThreads;
|
||||
for (i = 0; i < pServer->numOfThreads; ++i) {
|
||||
HttpThread *pThread = pServer->pThreads;
|
||||
for (int i = 0; i < pServer->numOfThreads; ++i) {
|
||||
sprintf(pThread->label, "%s%d", pServer->label, i);
|
||||
pThread->pServer = pServer;
|
||||
pThread->processData = pServer->processData;
|
||||
pThread->threadId = i;
|
||||
|
||||
|
@ -643,8 +372,8 @@ bool httpInitConnect(HttpServer *pServer) {
|
|||
pthread_attr_init(&thattr);
|
||||
pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
|
||||
if (pthread_create(&(pThread->thread), &thattr, (void *)httpProcessHttpData, (void *)(pThread)) != 0) {
|
||||
httpError("http thread:%s, failed to create HTTP process data thread, reason:%s",
|
||||
pThread->label, strerror(errno));
|
||||
httpError("http thread:%s, failed to create HTTP process data thread, reason:%s", pThread->label,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
pthread_attr_destroy(&thattr);
|
||||
|
|
|
@ -15,44 +15,29 @@
|
|||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "os.h"
|
||||
#include "hash.h"
|
||||
#include "taos.h"
|
||||
#include "ttime.h"
|
||||
#include "ttimer.h"
|
||||
#include "http.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpResp.h"
|
||||
|
||||
void httpAccessSession(HttpContext *pContext) {
|
||||
HttpServer *server = pContext->pThread->pServer;
|
||||
pthread_mutex_lock(&server->serverMutex);
|
||||
if (pContext->session == pContext->session->signature) {
|
||||
pContext->session->expire = (int) taosGetTimestampSec() + pContext->pThread->pServer->sessionExpire;
|
||||
}
|
||||
pthread_mutex_unlock(&server->serverMutex);
|
||||
}
|
||||
#include "tglobal.h"
|
||||
#include "tcache.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpContext.h"
|
||||
#include "httpSession.h"
|
||||
|
||||
void httpCreateSession(HttpContext *pContext, void *taos) {
|
||||
HttpServer *server = pContext->pThread->pServer;
|
||||
HttpServer *server = &tsHttpServer;
|
||||
httpReleaseSession(pContext);
|
||||
|
||||
pthread_mutex_lock(&server->serverMutex);
|
||||
|
||||
if (pContext->session != NULL && pContext->session == pContext->session->signature) {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, set exist session:%p:%p expired", pContext, pContext->fd,
|
||||
pContext->ipstr, pContext->user, pContext->session, pContext->session->taos);
|
||||
pContext->session->expire = 0;
|
||||
pContext->session->access--;
|
||||
}
|
||||
|
||||
HttpSession session;
|
||||
memset(&session, 0, sizeof(HttpSession));
|
||||
session.taos = taos;
|
||||
session.expire = (int)taosGetTimestampSec() + server->sessionExpire;
|
||||
session.access = 1;
|
||||
int sessionIdLen = snprintf(session.id, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass);
|
||||
session.refCount = 1;
|
||||
snprintf(session.id, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass);
|
||||
|
||||
taosHashPut(server->pSessionHash, session.id, sessionIdLen, (char *)(&session), sizeof(HttpSession));
|
||||
pContext->session = taosHashGet(server->pSessionHash, session.id, sessionIdLen);
|
||||
pContext->session = taosCachePut(server->sessionCache, session.id, &session, sizeof(HttpSession), tsHttpSessionExpire);
|
||||
// void *temp = pContext->session;
|
||||
// taosCacheRelease(server->sessionCache, (void **)&temp, false);
|
||||
|
||||
if (pContext->session == NULL) {
|
||||
httpError("context:%p, fd:%d, ip:%s, user:%s, error:%s", pContext, pContext->fd, pContext->ipstr, pContext->user,
|
||||
|
@ -62,26 +47,23 @@ void httpCreateSession(HttpContext *pContext, void *taos) {
|
|||
return;
|
||||
}
|
||||
|
||||
pContext->session->signature = pContext->session;
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p", pContext, pContext->fd, pContext->ipstr,
|
||||
pContext->user, pContext->session, pContext->session->taos);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p sessionRef:%d", pContext, pContext->fd,
|
||||
pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount);
|
||||
pthread_mutex_unlock(&server->serverMutex);
|
||||
}
|
||||
|
||||
void httpFetchSessionImp(HttpContext *pContext) {
|
||||
HttpServer *server = pContext->pThread->pServer;
|
||||
static void httpFetchSessionImp(HttpContext *pContext) {
|
||||
HttpServer *server = &tsHttpServer;
|
||||
pthread_mutex_lock(&server->serverMutex);
|
||||
|
||||
char sessionId[HTTP_SESSION_ID_LEN];
|
||||
int sessonIdLen = snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass);
|
||||
snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass);
|
||||
|
||||
pContext->session = taosHashGet(server->pSessionHash, sessionId, sessonIdLen);
|
||||
if (pContext->session != NULL && pContext->session == pContext->session->signature) {
|
||||
pContext->session->access++;
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, access:%d, expire:%d",
|
||||
pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session,
|
||||
pContext->session->taos, pContext->session->access, pContext->session->expire);
|
||||
pContext->session->expire = (int)taosGetTimestampSec() + server->sessionExpire;
|
||||
pContext->session = taosCacheAcquireByName(server->sessionCache, sessionId);
|
||||
if (pContext->session != NULL) {
|
||||
atomic_add_fetch_32(&pContext->session->refCount, 1);
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, sessionRef:%d", pContext, pContext->fd,
|
||||
pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount);
|
||||
} else {
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, session not found", pContext, pContext->fd, pContext->ipstr,
|
||||
pContext->user);
|
||||
|
@ -90,113 +72,54 @@ void httpFetchSessionImp(HttpContext *pContext) {
|
|||
pthread_mutex_unlock(&server->serverMutex);
|
||||
}
|
||||
|
||||
void httpFetchSession(HttpContext *pContext) {
|
||||
void httpGetSession(HttpContext *pContext) {
|
||||
if (pContext->session == NULL) {
|
||||
httpFetchSessionImp(pContext);
|
||||
} else {
|
||||
char sessionId[HTTP_SESSION_ID_LEN];
|
||||
snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass);
|
||||
if (strcmp(pContext->session->id, sessionId) != 0) {
|
||||
httpError("context:%p, fd:%d, ip:%s, user:%s, password may be changed", pContext, pContext->fd, pContext->ipstr, pContext->user);
|
||||
httpRestoreSession(pContext);
|
||||
httpReleaseSession(pContext);
|
||||
httpFetchSessionImp(pContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void httpRestoreSession(HttpContext *pContext) {
|
||||
HttpServer * server = pContext->pThread->pServer;
|
||||
void httpReleaseSession(HttpContext *pContext) {
|
||||
if (pContext == NULL || pContext->session == NULL) return;
|
||||
|
||||
// all access to the session is via serverMutex
|
||||
pthread_mutex_lock(&server->serverMutex);
|
||||
HttpSession *session = pContext->session;
|
||||
if (session == NULL || session != session->signature) {
|
||||
pthread_mutex_unlock(&server->serverMutex);
|
||||
return;
|
||||
}
|
||||
session->access--;
|
||||
httpTrace("context:%p, ip:%s, user:%s, restore session:%p:%p, access:%d, expire:%d",
|
||||
pContext, pContext->ipstr, pContext->user, session, session->taos,
|
||||
session->access, pContext->session->expire);
|
||||
int32_t refCount = atomic_sub_fetch_32(&pContext->session->refCount, 1);
|
||||
assert(refCount >= 0);
|
||||
httpTrace("context:%p, release session:%p:%p, sessionRef:%d", pContext, pContext->session, pContext->session->taos,
|
||||
pContext->session->refCount);
|
||||
|
||||
taosCacheRelease(tsHttpServer.sessionCache, (void **)&pContext->session, false);
|
||||
pContext->session = NULL;
|
||||
pthread_mutex_unlock(&server->serverMutex);
|
||||
}
|
||||
|
||||
void httpResetSession(HttpSession *pSession) {
|
||||
httpTrace("close session:%p:%p", pSession, pSession->taos);
|
||||
if (pSession->taos != NULL) {
|
||||
taos_close(pSession->taos);
|
||||
pSession->taos = NULL;
|
||||
static void httpDestroySession(void *data) {
|
||||
HttpSession *session = data;
|
||||
httpTrace("session:%p:%p, is destroyed, sessionRef:%d", session, session->taos, session->refCount);
|
||||
|
||||
if (session->taos != NULL) {
|
||||
taos_close(session->taos);
|
||||
session->taos = NULL;
|
||||
}
|
||||
pSession->signature = NULL;
|
||||
}
|
||||
|
||||
void httpRemoveAllSessions(HttpServer *pServer) {
|
||||
SHashMutableIterator *pIter = taosHashCreateIter(pServer->pSessionHash);
|
||||
|
||||
while (taosHashIterNext(pIter)) {
|
||||
HttpSession *pSession = taosHashIterGet(pIter);
|
||||
if (pSession == NULL) continue;
|
||||
httpResetSession(pSession);
|
||||
void httpCleanUpSessions() {
|
||||
if (tsHttpServer.sessionCache != NULL) {
|
||||
SCacheObj *cache = tsHttpServer.sessionCache;
|
||||
httpPrint("session cache is cleanuping, size:%d", taosHashGetSize(cache->pHashTable));
|
||||
taosCacheCleanup(tsHttpServer.sessionCache);
|
||||
tsHttpServer.sessionCache = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
taosHashDestroyIter(pIter);
|
||||
}
|
||||
|
||||
bool httpInitAllSessions(HttpServer *pServer) {
|
||||
if (pServer->pSessionHash == NULL) {
|
||||
pServer->pSessionHash = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true);
|
||||
}
|
||||
if (pServer->pSessionHash == NULL) {
|
||||
httpError("http init session pool failed");
|
||||
bool httpInitSessions() {
|
||||
tsHttpServer.sessionCache = taosCacheInitWithCb(5, httpDestroySession);
|
||||
if (tsHttpServer.sessionCache == NULL) {
|
||||
httpError("failed to init session cache");
|
||||
return false;
|
||||
}
|
||||
if (pServer->expireTimer == NULL) {
|
||||
taosTmrReset(httpProcessSessionExpire, 50000, pServer, pServer->timerHandle, &pServer->expireTimer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool httpSessionExpired(HttpSession *pSession) {
|
||||
time_t cur = taosGetTimestampSec();
|
||||
|
||||
if (pSession->taos != NULL) {
|
||||
if (pSession->expire > cur) {
|
||||
return false; // un-expired, so return false
|
||||
}
|
||||
if (pSession->access > 0) {
|
||||
httpTrace("session:%p:%p is expired, but still access:%d", pSession, pSession->taos,
|
||||
pSession->access);
|
||||
return false; // still used, so return false
|
||||
}
|
||||
httpTrace("need close session:%p:%p for it expired, cur:%d, expire:%d, invertal:%d",
|
||||
pSession, pSession->taos, cur, pSession->expire, cur - pSession->expire);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void httpRemoveExpireSessions(HttpServer *pServer) {
|
||||
SHashMutableIterator *pIter = taosHashCreateIter(pServer->pSessionHash);
|
||||
|
||||
while (taosHashIterNext(pIter)) {
|
||||
HttpSession *pSession = taosHashIterGet(pIter);
|
||||
if (pSession == NULL) continue;
|
||||
|
||||
pthread_mutex_lock(&pServer->serverMutex);
|
||||
if (httpSessionExpired(pSession)) {
|
||||
httpResetSession(pSession);
|
||||
taosHashRemove(pServer->pSessionHash, pSession->id, strlen(pSession->id));
|
||||
}
|
||||
pthread_mutex_unlock(&pServer->serverMutex);
|
||||
}
|
||||
|
||||
taosHashDestroyIter(pIter);
|
||||
}
|
||||
|
||||
void httpProcessSessionExpire(void *handle, void *tmrId) {
|
||||
HttpServer *pServer = (HttpServer *)handle;
|
||||
httpRemoveExpireSessions(pServer);
|
||||
taosTmrReset(httpProcessSessionExpire, 60000, pServer, pServer->timerHandle, &pServer->expireTimer);
|
||||
}
|
|
@ -18,11 +18,12 @@
|
|||
#include "tnote.h"
|
||||
#include "taos.h"
|
||||
#include "tsclient.h"
|
||||
#include "http.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpContext.h"
|
||||
#include "httpSql.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpAuth.h"
|
||||
#include "httpSession.h"
|
||||
|
||||
void *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
|
||||
void *param, void **taos);
|
||||
|
@ -30,7 +31,7 @@ void httpProcessMultiSql(HttpContext *pContext);
|
|||
|
||||
void httpProcessMultiSqlRetrieveCallBack(void *param, TAOS_RES *result, int numOfRows) {
|
||||
HttpContext *pContext = (HttpContext *)param;
|
||||
if (pContext == NULL || pContext->signature != pContext) return;
|
||||
if (pContext == NULL) return;
|
||||
|
||||
HttpSqlCmds * multiCmds = pContext->multiCmds;
|
||||
HttpEncodeMethod *encode = pContext->encodeMethod;
|
||||
|
@ -72,7 +73,7 @@ void httpProcessMultiSqlRetrieveCallBack(void *param, TAOS_RES *result, int numO
|
|||
|
||||
void httpProcessMultiSqlCallBack(void *param, TAOS_RES *result, int code) {
|
||||
HttpContext *pContext = (HttpContext *)param;
|
||||
if (pContext == NULL || pContext->signature != pContext) return;
|
||||
if (pContext == NULL) return;
|
||||
|
||||
HttpSqlCmds * multiCmds = pContext->multiCmds;
|
||||
HttpEncodeMethod *encode = pContext->encodeMethod;
|
||||
|
@ -172,7 +173,7 @@ void httpProcessMultiSql(HttpContext *pContext) {
|
|||
}
|
||||
|
||||
void httpProcessMultiSqlCmd(HttpContext *pContext) {
|
||||
if (pContext == NULL || pContext->signature != pContext) return;
|
||||
if (pContext == NULL) return;
|
||||
|
||||
HttpSqlCmds *multiCmds = pContext->multiCmds;
|
||||
if (multiCmds == NULL || multiCmds->size <= 0 || multiCmds->pos >= multiCmds->size || multiCmds->pos < 0) {
|
||||
|
@ -192,7 +193,7 @@ void httpProcessMultiSqlCmd(HttpContext *pContext) {
|
|||
|
||||
void httpProcessSingleSqlRetrieveCallBack(void *param, TAOS_RES *result, int numOfRows) {
|
||||
HttpContext *pContext = (HttpContext *)param;
|
||||
if (pContext == NULL || pContext->signature != pContext) return;
|
||||
if (pContext == NULL) return;
|
||||
|
||||
HttpEncodeMethod *encode = pContext->encodeMethod;
|
||||
|
||||
|
@ -230,7 +231,7 @@ void httpProcessSingleSqlRetrieveCallBack(void *param, TAOS_RES *result, int num
|
|||
|
||||
void httpProcessSingleSqlCallBack(void *param, TAOS_RES *result, int code) {
|
||||
HttpContext *pContext = (HttpContext *)param;
|
||||
if (pContext == NULL || pContext->signature != pContext) return;
|
||||
if (pContext == NULL) return;
|
||||
|
||||
HttpEncodeMethod *encode = pContext->encodeMethod;
|
||||
|
||||
|
@ -354,7 +355,7 @@ void httpExecCmd(HttpContext *pContext) {
|
|||
|
||||
void httpProcessRequestCb(void *param, TAOS_RES *result, int code) {
|
||||
HttpContext *pContext = param;
|
||||
if (pContext == NULL || pContext->signature != pContext) return;
|
||||
if (pContext == NULL) return;
|
||||
|
||||
if (code < 0) {
|
||||
httpError("context:%p, fd:%d, ip:%s, user:%s, login error, code:%s", pContext, pContext->fd, pContext->ipstr,
|
||||
|
@ -383,16 +384,14 @@ void httpProcessRequestCb(void *param, TAOS_RES *result, int code) {
|
|||
}
|
||||
|
||||
void httpProcessRequest(HttpContext *pContext) {
|
||||
httpFetchSession(pContext);
|
||||
httpGetSession(pContext);
|
||||
|
||||
if (pContext->session == NULL || pContext->session != pContext->session->signature ||
|
||||
pContext->reqType == HTTP_REQTYPE_LOGIN) {
|
||||
if (pContext->session == NULL || pContext->reqType == HTTP_REQTYPE_LOGIN) {
|
||||
taos_connect_a(NULL, pContext->user, pContext->pass, "", 0, httpProcessRequestCb, (void *)pContext,
|
||||
&(pContext->taos));
|
||||
httpTrace("context:%p, fd:%d, ip:%s, user:%s, try connect tdengine, taos:%p", pContext, pContext->fd,
|
||||
pContext->ipstr, pContext->user, pContext->taos);
|
||||
} else {
|
||||
httpAccessSession(pContext);
|
||||
httpExecCmd(pContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,84 +20,64 @@
|
|||
#include "tsocket.h"
|
||||
#include "ttimer.h"
|
||||
#include "tadmin.h"
|
||||
#include "http.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpContext.h"
|
||||
#include "httpSession.h"
|
||||
#include "httpServer.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpLog.h"
|
||||
#include "gcHandle.h"
|
||||
#include "httpHandle.h"
|
||||
#include "gcHandle.h"
|
||||
#include "restHandle.h"
|
||||
#include "tgHandle.h"
|
||||
|
||||
#ifndef _ADMIN
|
||||
|
||||
void adminInitHandle(HttpServer* pServer) {}
|
||||
void opInitHandle(HttpServer* pServer) {}
|
||||
|
||||
#endif
|
||||
|
||||
static HttpServer *httpServer = NULL;
|
||||
HttpServer tsHttpServer;
|
||||
void taosInitNote(int numOfNoteLines, int maxNotes, char* lable);
|
||||
|
||||
int httpInitSystem() {
|
||||
// taos_init();
|
||||
strcpy(tsHttpServer.label, "rest");
|
||||
tsHttpServer.serverIp = 0;
|
||||
tsHttpServer.serverPort = tsHttpPort;
|
||||
tsHttpServer.numOfThreads = tsHttpMaxThreads;
|
||||
tsHttpServer.processData = httpProcessData;
|
||||
|
||||
httpServer = (HttpServer *)malloc(sizeof(HttpServer));
|
||||
memset(httpServer, 0, sizeof(HttpServer));
|
||||
|
||||
strcpy(httpServer->label, "rest");
|
||||
httpServer->serverIp = 0;
|
||||
httpServer->serverPort = tsHttpPort;
|
||||
httpServer->cacheContext = tsHttpCacheSessions;
|
||||
httpServer->sessionExpire = tsHttpSessionExpire;
|
||||
httpServer->numOfThreads = tsHttpMaxThreads;
|
||||
httpServer->processData = httpProcessData;
|
||||
|
||||
pthread_mutex_init(&httpServer->serverMutex, NULL);
|
||||
pthread_mutex_init(&tsHttpServer.serverMutex, NULL);
|
||||
|
||||
if (tsHttpEnableRecordSql != 0) {
|
||||
taosInitNote(tsNumOfLogLines / 10, 1, (char*)"http_note");
|
||||
}
|
||||
restInitHandle(httpServer);
|
||||
adminInitHandle(httpServer);
|
||||
gcInitHandle(httpServer);
|
||||
tgInitHandle(httpServer);
|
||||
opInitHandle(httpServer);
|
||||
restInitHandle(&tsHttpServer);
|
||||
adminInitHandle(&tsHttpServer);
|
||||
gcInitHandle(&tsHttpServer);
|
||||
tgInitHandle(&tsHttpServer);
|
||||
opInitHandle(&tsHttpServer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int httpStartSystem() {
|
||||
httpPrint("starting to initialize http service ...");
|
||||
httpPrint("start http server ...");
|
||||
|
||||
if (httpServer == NULL) {
|
||||
httpError("http server is null");
|
||||
httpInitSystem();
|
||||
}
|
||||
|
||||
if (httpServer->pContextPool == NULL) {
|
||||
httpServer->pContextPool = taosMemPoolInit(httpServer->cacheContext, sizeof(HttpContext));
|
||||
}
|
||||
if (httpServer->pContextPool == NULL) {
|
||||
httpError("http init context pool failed");
|
||||
if (tsHttpServer.status != HTTP_SERVER_INIT) {
|
||||
httpError("http server is already started");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (httpServer->timerHandle == NULL) {
|
||||
httpServer->timerHandle = taosTmrInit(tsHttpCacheSessions * 100 + 100, 200, 60000, "http");
|
||||
}
|
||||
if (httpServer->timerHandle == NULL) {
|
||||
httpError("http init timer failed");
|
||||
if (!httpInitContexts()) {
|
||||
httpError("http init contexts failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!httpInitAllSessions(httpServer)) {
|
||||
if (!httpInitSessions()) {
|
||||
httpError("http init session failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!httpInitConnect(httpServer)) {
|
||||
if (!httpInitConnect()) {
|
||||
httpError("http init server failed");
|
||||
return -1;
|
||||
}
|
||||
|
@ -106,53 +86,23 @@ int httpStartSystem() {
|
|||
}
|
||||
|
||||
void httpStopSystem() {
|
||||
if (httpServer != NULL) {
|
||||
httpServer->online = false;
|
||||
}
|
||||
tsHttpServer.status = HTTP_SERVER_CLOSING;
|
||||
shutdown(tsHttpServer.fd, SHUT_RD);
|
||||
tgCleanupHandle();
|
||||
}
|
||||
|
||||
void httpCleanUpSystem() {
|
||||
httpPrint("http service cleanup");
|
||||
httpPrint("http server cleanup");
|
||||
httpStopSystem();
|
||||
|
||||
//#if 0
|
||||
if (httpServer == NULL) {
|
||||
return;
|
||||
}
|
||||
httpCleanupContexts();
|
||||
httpCleanUpSessions();
|
||||
httpCleanUpConnect();
|
||||
pthread_mutex_destroy(&tsHttpServer.serverMutex);
|
||||
|
||||
if (httpServer->expireTimer != NULL) {
|
||||
taosTmrStopA(&(httpServer->expireTimer));
|
||||
}
|
||||
|
||||
if (httpServer->timerHandle != NULL) {
|
||||
taosTmrCleanUp(httpServer->timerHandle);
|
||||
httpServer->timerHandle = NULL;
|
||||
}
|
||||
|
||||
if (httpServer->pThreads != NULL) {
|
||||
httpCleanUpConnect(httpServer);
|
||||
httpServer->pThreads = NULL;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
httpRemoveAllSessions(httpServer);
|
||||
|
||||
if (httpServer->pContextPool != NULL) {
|
||||
taosMemPoolCleanUp(httpServer->pContextPool);
|
||||
httpServer->pContextPool = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&httpServer->serverMutex);
|
||||
|
||||
tfree(httpServer);
|
||||
#endif
|
||||
tsHttpServer.status = HTTP_SERVER_CLOSED;
|
||||
}
|
||||
|
||||
int32_t httpGetReqCount() {
|
||||
if (httpServer != NULL) {
|
||||
return atomic_exchange_32(&httpServer->requestNum, 0);
|
||||
}
|
||||
return 0;
|
||||
return atomic_exchange_32(&tsHttpServer.requestNum, 0);
|
||||
}
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
#include "os.h"
|
||||
#include "tmd5.h"
|
||||
#include "taos.h"
|
||||
#include "http.h"
|
||||
#include "httpLog.h"
|
||||
#include "httpCode.h"
|
||||
#include "httpHandle.h"
|
||||
#include "httpInt.h"
|
||||
#include "httpResp.h"
|
||||
#include "httpSql.h"
|
||||
#include "httpUtil.h"
|
||||
|
||||
bool httpCheckUsedbSql(char *sql) {
|
||||
if (strstr(sql, "use ") != NULL) {
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
#include "tglobal.h"
|
||||
#include "taosdef.h"
|
||||
#include "taosmsg.h"
|
||||
#include "httpInt.h"
|
||||
#include "tgHandle.h"
|
||||
#include "tgJson.h"
|
||||
#include "httpLog.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
/*
|
||||
* taos.telegraf.cfg formats like
|
||||
|
|
|
@ -100,10 +100,10 @@ typedef struct STSBuf {
|
|||
typedef struct STSBufFileHeader {
|
||||
uint32_t magic; // file magic number
|
||||
uint32_t numOfVnode; // number of vnode stored in current file
|
||||
uint32_t tsOrder; // timestamp order in current file
|
||||
int32_t tsOrder; // timestamp order in current file
|
||||
} STSBufFileHeader;
|
||||
|
||||
STSBuf* tsBufCreate(bool autoDelete);
|
||||
STSBuf* tsBufCreate(bool autoDelete, int32_t order);
|
||||
STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete);
|
||||
STSBuf* tsBufCreateFromCompBlocks(const char* pData, int32_t numOfBlocks, int32_t len, int32_t tsOrder);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <taosmsg.h>
|
||||
#include "os.h"
|
||||
#include "qfill.h"
|
||||
|
||||
|
@ -847,7 +848,7 @@ static void blockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *
|
|||
}
|
||||
|
||||
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
|
||||
if (isIntervalQuery(pQuery)) {
|
||||
if (isIntervalQuery(pQuery) && tsCols != NULL) {
|
||||
int32_t offset = GET_COL_DATA_POS(pQuery, 0, step);
|
||||
TSKEY ts = tsCols[offset];
|
||||
|
||||
|
@ -919,12 +920,25 @@ static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, char *pDat
|
|||
|
||||
SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
|
||||
|
||||
int64_t v = -1;
|
||||
// not assign result buffer yet, add new result buffer
|
||||
switch(type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT: v = GET_INT8_VAL(pData); break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: v = GET_INT16_VAL(pData); break;
|
||||
case TSDB_DATA_TYPE_INT: v = GET_INT32_VAL(pData); break;
|
||||
case TSDB_DATA_TYPE_BIGINT: v = GET_INT64_VAL(pData); break;
|
||||
}
|
||||
|
||||
// assert(pRuntimeEnv->windowResInfo.hashList->size <= 2);
|
||||
SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, pData, bytes);
|
||||
if (pWindowRes == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// not assign result buffer yet, add new result buffer
|
||||
pWindowRes->window.skey = v;
|
||||
pWindowRes->window.ekey = v;
|
||||
|
||||
if (pWindowRes->pos.pageId == -1) {
|
||||
int32_t ret = addNewWindowResultBuf(pWindowRes, pResultBuf, GROUPRESULTID, pRuntimeEnv->numOfRowsPerPage);
|
||||
if (ret != 0) {
|
||||
|
@ -1022,12 +1036,16 @@ static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx
|
|||
return false;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST) {
|
||||
return !QUERY_IS_ASC_QUERY(pQuery);
|
||||
} else if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
|
||||
if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) {
|
||||
return QUERY_IS_ASC_QUERY(pQuery);
|
||||
}
|
||||
|
||||
// todo add comments
|
||||
if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) {
|
||||
return pCtx->param[0].i64Key == pQuery->order.order;
|
||||
// return !QUERY_IS_ASC_QUERY(pQuery);
|
||||
}
|
||||
|
||||
// in the supplementary scan, only the following functions need to be executed
|
||||
if (IS_REVERSE_SCAN(pRuntimeEnv)) {
|
||||
return false;
|
||||
|
@ -1072,7 +1090,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS
|
|||
// from top to bottom in desc
|
||||
// from bottom to top in asc order
|
||||
if (pRuntimeEnv->pTSBuf != NULL) {
|
||||
SQInfo *pQInfo = (SQInfo *)GET_QINFO_ADDR(pQuery);
|
||||
SQInfo *pQInfo = (SQInfo *)GET_QINFO_ADDR(pRuntimeEnv);
|
||||
qTrace("QInfo:%p process data rows, numOfRows:%d, query order:%d, ts comp order:%d", pQInfo, pDataBlockInfo->rows,
|
||||
pQuery->order.order, pRuntimeEnv->pTSBuf->cur.order);
|
||||
}
|
||||
|
@ -1382,7 +1400,7 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int16_t order
|
|||
pCtx->inputType = pQuery->colList[index].type;
|
||||
}
|
||||
|
||||
assert(isValidDataType(pCtx->inputType, pCtx->inputBytes));
|
||||
assert(isValidDataType(pCtx->inputType));
|
||||
pCtx->ptsOutputBuf = NULL;
|
||||
|
||||
pCtx->outputBytes = pQuery->pSelectExpr[i].bytes;
|
||||
|
@ -1479,19 +1497,6 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
|
|||
|
||||
static bool isQueryKilled(SQInfo *pQInfo) {
|
||||
return (pQInfo->code == TSDB_CODE_TSC_QUERY_CANCELLED);
|
||||
#if 0
|
||||
/*
|
||||
* check if the queried meter is going to be deleted.
|
||||
* if it will be deleted soon, stop current query ASAP.
|
||||
*/
|
||||
SMeterObj *pMeterObj = pQInfo->pObj;
|
||||
if (vnodeIsMeterState(pMeterObj, TSDB_METER_STATE_DROPPING)) {
|
||||
pQInfo->killed = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return (pQInfo->killed == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setQueryKilled(SQInfo *pQInfo) { pQInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED; }
|
||||
|
@ -1574,10 +1579,14 @@ static bool needReverseScan(SQuery *pQuery) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (((functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) && QUERY_IS_ASC_QUERY(pQuery)) ||
|
||||
((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery))) {
|
||||
if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) {
|
||||
int32_t order = pQuery->pSelectExpr[i].base.arg->argValue.i64;
|
||||
return order != pQuery->order.order;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -2030,6 +2039,34 @@ int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) {
|
|||
return midPos;
|
||||
}
|
||||
|
||||
static void ensureOutputBufferSimple(SQueryRuntimeEnv* pRuntimeEnv, int32_t capacity) {
|
||||
SQuery* pQuery = pRuntimeEnv->pQuery;
|
||||
|
||||
if (capacity < pQuery->rec.capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
|
||||
int32_t bytes = pQuery->pSelectExpr[i].bytes;
|
||||
assert(bytes > 0 && capacity > 0);
|
||||
|
||||
char *tmp = realloc(pQuery->sdata[i], bytes * capacity + sizeof(tFilePage));
|
||||
if (tmp == NULL) { // todo handle the oom
|
||||
assert(0);
|
||||
} else {
|
||||
pQuery->sdata[i] = (tFilePage *)tmp;
|
||||
}
|
||||
|
||||
// set the pCtx output buffer position
|
||||
pRuntimeEnv->pCtx[i].aOutputBuf = pQuery->sdata[i]->data;
|
||||
}
|
||||
|
||||
qTrace("QInfo:%p realloc output buffer to inc output buffer from: %d rows to:%d rows", GET_QINFO_ADDR(pRuntimeEnv),
|
||||
pQuery->rec.capacity, capacity);
|
||||
|
||||
pQuery->rec.capacity = capacity;
|
||||
}
|
||||
|
||||
static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pBlockInfo) {
|
||||
// in case of prj/diff query, ensure the output buffer is sufficient to accommodate the results of current block
|
||||
SQuery* pQuery = pRuntimeEnv->pQuery;
|
||||
|
@ -2152,8 +2189,7 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
|
|||
* set tag value in SQLFunctionCtx
|
||||
* e.g.,tag information into input buffer
|
||||
*/
|
||||
static void doSetTagValueInParam(void *tsdb, STableId* pTableId, int32_t tagColId, tVariant *tag, int16_t type,
|
||||
int16_t bytes) {
|
||||
static void doSetTagValueInParam(void *tsdb, STableId* pTableId, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes) {
|
||||
tVariantDestroy(tag);
|
||||
|
||||
if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
|
@ -2169,8 +2205,18 @@ static void doSetTagValueInParam(void *tsdb, STableId* pTableId, int32_t tagColI
|
|||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (isNull(varDataVal(val), type)) {
|
||||
tag->nType = TSDB_DATA_TYPE_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
tVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
|
||||
} else {
|
||||
if (isNull(val, type)) {
|
||||
tag->nType = TSDB_DATA_TYPE_NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
tVariantCreateFromBinary(tag, val, bytes, type);
|
||||
}
|
||||
}
|
||||
|
@ -2178,35 +2224,55 @@ static void doSetTagValueInParam(void *tsdb, STableId* pTableId, int32_t tagColI
|
|||
|
||||
void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, STableId* pTableId, void *tsdb) {
|
||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||
SQInfo* pQInfo = GET_QINFO_ADDR(pRuntimeEnv);
|
||||
|
||||
SExprInfo *pExprInfo = &pQuery->pSelectExpr[0];
|
||||
if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP) {
|
||||
|
||||
assert(pExprInfo->base.numOfParams == 1);
|
||||
doSetTagValueInParam(tsdb, pTableId, pExprInfo->base.arg->argValue.i64, &pRuntimeEnv->pCtx[0].tag,
|
||||
pExprInfo->type, pExprInfo->bytes);
|
||||
|
||||
// todo refactor extract function.
|
||||
int16_t type = -1, bytes = -1;
|
||||
for(int32_t i = 0; i < pQuery->numOfTags; ++i) {
|
||||
if (pQuery->tagColList[i].colId == pExprInfo->base.arg->argValue.i64) {
|
||||
type = pQuery->tagColList[i].type;
|
||||
bytes = pQuery->tagColList[i].bytes;
|
||||
}
|
||||
}
|
||||
|
||||
doSetTagValueInParam(tsdb, pTableId, pExprInfo->base.arg->argValue.i64, &pRuntimeEnv->pCtx[0].tag, type, bytes);
|
||||
} else {
|
||||
// set tag value, by which the results are aggregated.
|
||||
for (int32_t idx = 0; idx < pQuery->numOfOutput; ++idx) {
|
||||
SExprInfo* pExprInfo = &pQuery->pSelectExpr[idx];
|
||||
SExprInfo* pLocalExprInfo = &pQuery->pSelectExpr[idx];
|
||||
|
||||
// ts_comp column required the tag value for join filter
|
||||
if (!TSDB_COL_IS_TAG(pExprInfo->base.colInfo.flag)) {
|
||||
if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.colInfo.flag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo use tag column index to optimize performance
|
||||
doSetTagValueInParam(tsdb, pTableId, pExprInfo->base.colInfo.colId, &pRuntimeEnv->pCtx[idx].tag,
|
||||
pExprInfo->type, pExprInfo->bytes);
|
||||
doSetTagValueInParam(tsdb, pTableId, pLocalExprInfo->base.colInfo.colId, &pRuntimeEnv->pCtx[idx].tag,
|
||||
pLocalExprInfo->type, pLocalExprInfo->bytes);
|
||||
}
|
||||
|
||||
// set the join tag for first column
|
||||
SSqlFuncMsg *pFuncMsg = &pExprInfo->base;
|
||||
if (pFuncMsg->functionId == TSDB_FUNC_TS && pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX &&
|
||||
if ((pFuncMsg->functionId == TSDB_FUNC_TS || pFuncMsg->functionId == TSDB_FUNC_PRJ) && pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX &&
|
||||
pRuntimeEnv->pTSBuf != NULL) {
|
||||
assert(pFuncMsg->numOfParams == 1);
|
||||
assert(0); // to do fix me
|
||||
// doSetTagValueInParam(pTagSchema, pFuncMsg->arg->argValue.i64, pMeterSidInfo, &pRuntimeEnv->pCtx[0].tag);
|
||||
|
||||
// todo refactor
|
||||
int16_t type = -1, bytes = -1;
|
||||
for(int32_t i = 0; i < pQuery->numOfTags; ++i) {
|
||||
if (pQuery->tagColList[i].colId == pExprInfo->base.arg->argValue.i64) {
|
||||
type = pQuery->tagColList[i].type;
|
||||
bytes = pQuery->tagColList[i].bytes;
|
||||
}
|
||||
}
|
||||
|
||||
doSetTagValueInParam(tsdb, pTableId, pExprInfo->base.arg->argValue.i64, &pRuntimeEnv->pCtx[0].tag, type, bytes);
|
||||
qTrace("QInfo:%p set tag value for join comparison, colId:%d, val:%"PRId64, pQInfo, pExprInfo->base.arg->argValue.i64,
|
||||
pRuntimeEnv->pCtx[0].tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2917,7 +2983,6 @@ void skipResults(SQueryRuntimeEnv *pRuntimeEnv) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
updateNumOfResult(pRuntimeEnv, pQuery->rec.rows);
|
||||
}
|
||||
}
|
||||
|
@ -3054,7 +3119,7 @@ static void clearEnvAfterReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus
|
|||
pQuery->window = pTableQueryInfo->win;
|
||||
}
|
||||
|
||||
void scanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
|
||||
void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) {
|
||||
SQInfo *pQInfo = (SQInfo *) GET_QINFO_ADDR(pRuntimeEnv);
|
||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||
STableQueryInfo *pTableQueryInfo = pQuery->current;
|
||||
|
@ -3300,7 +3365,7 @@ void setWindowResOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *
|
|||
|
||||
int32_t setAdditionalInfo(SQInfo *pQInfo, STableId* pTableId, STableQueryInfo *pTableQueryInfo) {
|
||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||
assert(pTableQueryInfo->lastKey >= TSKEY_INITIAL_VAL);
|
||||
//assert(pTableQueryInfo->lastKey >= TSKEY_INITIAL_VAL);
|
||||
|
||||
setTagVal(pRuntimeEnv, pTableId, pQInfo->tsdb);
|
||||
|
||||
|
@ -3496,18 +3561,32 @@ void copyFromWindowResToSData(SQInfo *pQInfo, SWindowResult *result) {
|
|||
assert(pQuery->rec.rows <= pQuery->rec.capacity);
|
||||
}
|
||||
|
||||
static void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv, STableQueryInfo *pTableQueryInfo) {
|
||||
static UNUSED_FUNC void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv, STableQueryInfo *pTableQueryInfo) {
|
||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||
|
||||
// update the number of result for each, only update the number of rows for the corresponding window result.
|
||||
if (pQuery->intervalTime == 0) {
|
||||
int32_t g = pTableQueryInfo->groupIndex;
|
||||
assert(pRuntimeEnv->windowResInfo.size > 0);
|
||||
|
||||
SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, (char *)&g, sizeof(g));
|
||||
if (pWindowRes->numOfRows == 0) {
|
||||
pWindowRes->numOfRows = getNumOfResult(pRuntimeEnv);
|
||||
for (int32_t i = 0; i < pRuntimeEnv->windowResInfo.size; ++i) {
|
||||
SWindowResult *pResult = &pRuntimeEnv->windowResInfo.pResult[i];
|
||||
|
||||
for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
|
||||
int32_t functionId = pRuntimeEnv->pCtx[j].functionId;
|
||||
if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes);
|
||||
}
|
||||
}
|
||||
|
||||
// int32_t g = pTableQueryInfo->groupIndex;
|
||||
// assert(pRuntimeEnv->windowResInfo.size > 0);
|
||||
//
|
||||
// SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, (char *)&g, sizeof(g));
|
||||
// if (pWindowRes->numOfRows == 0) {
|
||||
// pWindowRes->numOfRows = getNumOfResult(pRuntimeEnv);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3519,7 +3598,7 @@ void stableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *
|
|||
SWindowResInfo * pWindowResInfo = &pTableQueryInfo->windowResInfo;
|
||||
pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0 : pDataBlockInfo->rows - 1;
|
||||
|
||||
if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL) {
|
||||
if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL || isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
|
||||
rowwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pWindowResInfo, pDataBlock);
|
||||
} else {
|
||||
blockwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pWindowResInfo, searchFn, pDataBlock);
|
||||
|
@ -3568,6 +3647,7 @@ bool queryHasRemainResults(SQueryRuntimeEnv* pRuntimeEnv) {
|
|||
|
||||
static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data) {
|
||||
SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
|
||||
|
||||
for (int32_t col = 0; col < pQuery->numOfOutput; ++col) {
|
||||
int32_t bytes = pQuery->pSelectExpr[col].bytes;
|
||||
|
||||
|
@ -4081,6 +4161,7 @@ static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) {
|
|||
SDataStatis *pStatis = NULL;
|
||||
SArray *pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, pQueryHandle, &blockInfo, &pStatis);
|
||||
|
||||
if (!isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
|
||||
if (!isIntervalQuery(pQuery)) {
|
||||
int32_t step = QUERY_IS_ASC_QUERY(pQuery)? 1:-1;
|
||||
setExecutionContext(pQInfo, &pTableQueryInfo->id, pTableQueryInfo->groupIndex, blockInfo.window.ekey + step);
|
||||
|
@ -4089,13 +4170,13 @@ static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) {
|
|||
setIntervalQueryRange(pQInfo, nextKey);
|
||||
/*int32_t ret = */setAdditionalInfo(pQInfo, &pTableQueryInfo->id, pTableQueryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
summary->totalRows += blockInfo.rows;
|
||||
stableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, pDataBlock, binarySearchForKey);
|
||||
|
||||
qTrace("QInfo:%p check data block, uid:%"PRId64", tid:%d, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, lastKey:%" PRId64,
|
||||
GET_QINFO_ADDR(pRuntimeEnv), blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey,
|
||||
blockInfo.rows, pQuery->current->lastKey);
|
||||
pQInfo, blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, pQuery->current->lastKey);
|
||||
}
|
||||
|
||||
int64_t et = taosGetTimestampMs();
|
||||
|
@ -4179,8 +4260,8 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
|
|||
while (pQInfo->groupIndex < numOfGroups) {
|
||||
SArray* group = taosArrayGetP(pQInfo->groupInfo.pGroupList, pQInfo->groupIndex);
|
||||
|
||||
qTrace("QInfo:%p last_row query on group:%d, total group:%d, current group:%d", pQInfo, pQInfo->groupIndex,
|
||||
numOfGroups);
|
||||
qTrace("QInfo:%p last_row query on group:%d, total group:%u, current group:%p", pQInfo, pQInfo->groupIndex,
|
||||
numOfGroups, group);
|
||||
|
||||
STsdbQueryCond cond = {
|
||||
.twindow = pQuery->window,
|
||||
|
@ -4213,14 +4294,15 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
|
|||
assert(taosArrayGetSize(s) >= 1);
|
||||
|
||||
setTagVal(pRuntimeEnv, (STableId*) taosArrayGet(s, 0), pQInfo->tsdb);
|
||||
|
||||
if (isFirstLastRowQuery(pQuery)) {
|
||||
assert(taosArrayGetSize(s) == 1);
|
||||
}
|
||||
|
||||
taosArrayDestroy(s);
|
||||
|
||||
// here we simply set the first table as current table
|
||||
pQuery->current = ((SGroupItem*) taosArrayGet(group, 0))->info;
|
||||
scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
|
||||
scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
|
||||
|
||||
int64_t numOfRes = getNumOfResult(pRuntimeEnv);
|
||||
if (numOfRes > 0) {
|
||||
|
@ -4233,10 +4315,85 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
|
|||
|
||||
// enable execution for next table, when handling the projection query
|
||||
enableExecutionForNextTable(pRuntimeEnv);
|
||||
|
||||
if (pQuery->rec.rows >= pQuery->rec.capacity) {
|
||||
setQueryStatus(pQuery, QUERY_RESBUF_FULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) { // group-by on normal columns query
|
||||
while (pQInfo->groupIndex < numOfGroups) {
|
||||
SArray* group = taosArrayGetP(pQInfo->groupInfo.pGroupList, pQInfo->groupIndex);
|
||||
|
||||
qTrace("QInfo:%p group by normal columns group:%d, total group:%d", pQInfo, pQInfo->groupIndex, numOfGroups);
|
||||
|
||||
STsdbQueryCond cond = {
|
||||
.twindow = pQuery->window,
|
||||
.colList = pQuery->colList,
|
||||
.order = pQuery->order.order,
|
||||
.numOfCols = pQuery->numOfCols,
|
||||
};
|
||||
|
||||
SArray *g1 = taosArrayInit(1, POINTER_BYTES);
|
||||
SArray *tx = taosArrayClone(group);
|
||||
taosArrayPush(g1, &tx);
|
||||
|
||||
STableGroupInfo gp = {.numOfTables = taosArrayGetSize(tx), .pGroupList = g1};
|
||||
|
||||
// include only current table
|
||||
if (pRuntimeEnv->pQueryHandle != NULL) {
|
||||
tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle);
|
||||
pRuntimeEnv->pQueryHandle = NULL;
|
||||
}
|
||||
|
||||
pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &gp, pQInfo);
|
||||
|
||||
SArray* s = tsdbGetQueriedTableIdList(pRuntimeEnv->pQueryHandle);
|
||||
assert(taosArrayGetSize(s) >= 1);
|
||||
|
||||
setTagVal(pRuntimeEnv, (STableId*) taosArrayGet(s, 0), pQInfo->tsdb);
|
||||
|
||||
// here we simply set the first table as current table
|
||||
scanMultiTableDataBlocks(pQInfo);
|
||||
pQInfo->groupIndex += 1;
|
||||
|
||||
SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
|
||||
|
||||
// no results generated for current group, continue to try the next group
|
||||
taosArrayDestroy(s);
|
||||
if (pWindowResInfo->size <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
|
||||
SWindowStatus *pStatus = &pWindowResInfo->pResult[i].status;
|
||||
pStatus->closed = true; // enable return all results for group by normal columns
|
||||
|
||||
SWindowResult *pResult = &pWindowResInfo->pResult[i];
|
||||
for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
|
||||
pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes);
|
||||
}
|
||||
}
|
||||
|
||||
qTrace("QInfo:%p generated groupby columns results %d rows for group %d completed", pQInfo, pWindowResInfo->size,
|
||||
pQInfo->groupIndex);
|
||||
int32_t currentGroupIndex = pQInfo->groupIndex;
|
||||
|
||||
pQuery->rec.rows = 0;
|
||||
pQInfo->groupIndex = 0;
|
||||
|
||||
ensureOutputBufferSimple(pRuntimeEnv, pWindowResInfo->size);
|
||||
copyFromWindowResToSData(pQInfo, pWindowResInfo->pResult);
|
||||
|
||||
pQInfo->groupIndex = currentGroupIndex; //restore the group index
|
||||
assert(pQuery->rec.rows == pWindowResInfo->size);
|
||||
|
||||
clearClosedTimeWindow(pRuntimeEnv);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 1. super table projection query, 2. group-by on normal columns query, 3. ts-comp query
|
||||
* 1. super table projection query, 2. ts-comp query
|
||||
* if the subgroup index is larger than 0, results generated by group by tbname,k is existed.
|
||||
* we need to return it to client in the first place.
|
||||
*/
|
||||
|
@ -4283,7 +4440,7 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
|
||||
scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
|
||||
skipResults(pRuntimeEnv);
|
||||
|
||||
// the limitation of output result is reached, set the query completed
|
||||
|
@ -4328,6 +4485,10 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pQInfo->tableIndex >= pQInfo->groupInfo.numOfTables) {
|
||||
setQueryStatus(pQuery, QUERY_COMPLETED);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4349,27 +4510,8 @@ static void sequentialTableProcess(SQInfo *pQInfo) {
|
|||
pRuntimeEnv->cur = pRuntimeEnv->pTSBuf->cur;
|
||||
}
|
||||
|
||||
// todo refactor
|
||||
if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
|
||||
SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
|
||||
|
||||
for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
|
||||
SWindowStatus *pStatus = &pWindowResInfo->pResult[i].status;
|
||||
pStatus->closed = true; // enable return all results for group by normal columns
|
||||
|
||||
SWindowResult *pResult = &pWindowResInfo->pResult[i];
|
||||
for (int32_t j = 0; j < pQuery->numOfOutput; ++j) {
|
||||
pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes);
|
||||
}
|
||||
}
|
||||
|
||||
pQInfo->groupIndex = 0;
|
||||
pQuery->rec.rows = 0;
|
||||
copyFromWindowResToSData(pQInfo, pWindowResInfo->pResult);
|
||||
}
|
||||
|
||||
qTrace(
|
||||
"QInfo %p numOfTables:%d, index:%d, numOfGroups:%d, %d points returned, total:%"PRId64", offset:%" PRId64,
|
||||
"QInfo %p numOfTables:%"PRIu64", index:%d, numOfGroups:%d, %"PRId64" points returned, total:%"PRId64", offset:%" PRId64,
|
||||
pQInfo, pQInfo->groupInfo.numOfTables, pQInfo->tableIndex, numOfGroups, pQuery->rec.rows, pQuery->rec.total,
|
||||
pQuery->limit.offset);
|
||||
}
|
||||
|
@ -4449,7 +4591,6 @@ static void multiTableQueryProcess(SQInfo *pQInfo) {
|
|||
*/
|
||||
if (isIntervalQuery(pQuery)) {
|
||||
copyResToQueryResultBuf(pQInfo, pQuery);
|
||||
|
||||
#ifdef _DEBUG_VIEW
|
||||
displayInterResult(pQuery->sdata, pRuntimeEnv, pQuery->sdata[0]->num);
|
||||
#endif
|
||||
|
@ -4457,7 +4598,7 @@ static void multiTableQueryProcess(SQInfo *pQInfo) {
|
|||
copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
|
||||
}
|
||||
|
||||
qTrace("QInfo:%p current:%lld, total:%lld", pQInfo, pQuery->rec.rows, pQuery->rec.total);
|
||||
qTrace("QInfo:%p current:%"PRId64", total:%"PRId64"", pQInfo, pQuery->rec.rows, pQuery->rec.total);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4527,7 +4668,7 @@ static void tableFixedOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
|
|||
|
||||
pQuery->current = pTableInfo; // set current query table info
|
||||
|
||||
scanAllDataBlocks(pRuntimeEnv, pTableInfo->lastKey);
|
||||
scanOneTableDataBlocks(pRuntimeEnv, pTableInfo->lastKey);
|
||||
finalizeQueryResult(pRuntimeEnv);
|
||||
|
||||
if (isQueryKilled(pQInfo)) {
|
||||
|
@ -4560,7 +4701,7 @@ static void tableMultiOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo)
|
|||
}
|
||||
|
||||
while (1) {
|
||||
scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
|
||||
scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey);
|
||||
finalizeQueryResult(pRuntimeEnv);
|
||||
|
||||
if (isQueryKilled(pQInfo)) {
|
||||
|
@ -4607,7 +4748,7 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start)
|
|||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||
|
||||
while (1) {
|
||||
scanAllDataBlocks(pRuntimeEnv, start);
|
||||
scanOneTableDataBlocks(pRuntimeEnv, start);
|
||||
|
||||
if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) {
|
||||
return;
|
||||
|
@ -4729,13 +4870,13 @@ static void tableQueryImpl(SQInfo *pQInfo) {
|
|||
clearFirstNTimeWindow(pRuntimeEnv, pQInfo->groupIndex);
|
||||
|
||||
if (pQuery->rec.rows > 0) {
|
||||
qTrace("QInfo:%p %d rows returned from group results, total:%d", pQInfo, pQuery->rec.rows, pQuery->rec.total);
|
||||
qTrace("QInfo:%p %"PRId64" rows returned from group results, total:%"PRId64"", pQInfo, pQuery->rec.rows, pQuery->rec.total);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qTrace("QInfo:%p query over, %d rows are returned", pQInfo, pQuery->rec.total);
|
||||
qTrace("QInfo:%p query over, %"PRId64" rows are returned", pQInfo, pQuery->rec.total);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4791,7 +4932,7 @@ static void stableQueryImpl(SQInfo *pQInfo) {
|
|||
pQInfo->runtimeEnv.summary.elapsedTime += (taosGetTimestampUs() - st);
|
||||
|
||||
if (pQuery->rec.rows == 0) {
|
||||
qTrace("QInfo:%p over, %d tables queried, %d rows are returned", pQInfo, pQInfo->groupInfo.numOfTables, pQuery->rec.total);
|
||||
qTrace("QInfo:%p over, %d tables queried, %"PRId64" rows are returned", pQInfo, pQInfo->groupInfo.numOfTables, pQuery->rec.total);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4915,7 +5056,7 @@ static int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SArray **pTableIdList,
|
|||
|
||||
pQueryMsg->order = htons(pQueryMsg->order);
|
||||
pQueryMsg->orderColId = htons(pQueryMsg->orderColId);
|
||||
pQueryMsg->queryType = htons(pQueryMsg->queryType);
|
||||
pQueryMsg->queryType = htonl(pQueryMsg->queryType);
|
||||
pQueryMsg->tagNameRelType = htons(pQueryMsg->tagNameRelType);
|
||||
|
||||
pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols);
|
||||
|
@ -4934,7 +5075,6 @@ static int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SArray **pTableIdList,
|
|||
}
|
||||
|
||||
char *pMsg = (char *)(pQueryMsg->colList) + sizeof(SColumnInfo) * pQueryMsg->numOfCols;
|
||||
|
||||
for (int32_t col = 0; col < pQueryMsg->numOfCols; ++col) {
|
||||
SColumnInfo *pColInfo = &pQueryMsg->colList[col];
|
||||
|
||||
|
@ -5084,11 +5224,11 @@ static int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SArray **pTableIdList,
|
|||
pMsg += len;
|
||||
}
|
||||
|
||||
qTrace("qmsg:%p query %d tables, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
|
||||
"outputCols:%d, numOfCols:%d, interval:%" PRId64 ", fillType:%d, comptsLen:%d, limit:%" PRId64 ", offset:%" PRId64,
|
||||
pQueryMsg, pQueryMsg->numOfTables, pQueryMsg->window.skey, pQueryMsg->window.ekey, pQueryMsg->numOfGroupCols,
|
||||
qTrace("qmsg:%p query %d tables, type:%d, qrange:%" PRId64 "-%" PRId64 ", numOfGroupbyTagCols:%d, order:%d, "
|
||||
"outputCols:%d, numOfCols:%d, interval:%" PRId64 ", fillType:%d, comptsLen:%d, compNumOfBlocks:%d, limit:%" PRId64 ", offset:%" PRId64,
|
||||
pQueryMsg, pQueryMsg->numOfTables, pQueryMsg->queryType, pQueryMsg->window.skey, pQueryMsg->window.ekey, pQueryMsg->numOfGroupCols,
|
||||
pQueryMsg->order, pQueryMsg->numOfOutput, pQueryMsg->numOfCols, pQueryMsg->intervalTime,
|
||||
pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->limit, pQueryMsg->offset);
|
||||
pQueryMsg->fillType, pQueryMsg->tsLen, pQueryMsg->tsNumOfBlocks, pQueryMsg->limit, pQueryMsg->offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -5174,7 +5314,7 @@ static int32_t createQFunctionExprFromMsg(SQueryTableMsg *pQueryMsg, SExprInfo *
|
|||
if (pExprs[i].base.functionId == TSDB_FUNC_TAG_DUMMY || pExprs[i].base.functionId == TSDB_FUNC_TS_DUMMY) {
|
||||
tagLen += pExprs[i].bytes;
|
||||
}
|
||||
assert(isValidDataType(pExprs[i].type, pExprs[i].bytes));
|
||||
assert(isValidDataType(pExprs[i].type));
|
||||
}
|
||||
|
||||
// TODO refactor
|
||||
|
@ -5274,6 +5414,7 @@ static int32_t createFilterInfo(void *pQInfo, SQuery *pQuery) {
|
|||
|
||||
if ((lower == TSDB_RELATION_GREATER_EQUAL || lower == TSDB_RELATION_GREATER) &&
|
||||
(upper == TSDB_RELATION_LESS_EQUAL || upper == TSDB_RELATION_LESS)) {
|
||||
assert(rangeFilterArray != NULL);
|
||||
if (lower == TSDB_RELATION_GREATER_EQUAL) {
|
||||
if (upper == TSDB_RELATION_LESS_EQUAL) {
|
||||
pSingleColFilter->fp = rangeFilterArray[4];
|
||||
|
@ -5288,11 +5429,12 @@ static int32_t createFilterInfo(void *pQInfo, SQuery *pQuery) {
|
|||
}
|
||||
}
|
||||
} else { // set callback filter function
|
||||
assert(filterArray != NULL);
|
||||
if (lower != TSDB_RELATION_INVALID) {
|
||||
pSingleColFilter->fp = filterArray[lower];
|
||||
|
||||
if (upper != TSDB_RELATION_INVALID) {
|
||||
qError("pQInfo:%p failed to get filter function, invalid filter condition", pQInfo, type);
|
||||
qError("pQInfo:%p failed to get filter function, invalid filter condition: %d", pQInfo, type);
|
||||
return TSDB_CODE_QRY_INVALID_MSG;
|
||||
}
|
||||
} else {
|
||||
|
@ -5765,23 +5907,20 @@ int32_t qCreateQueryInfo(void *tsdb, int32_t vgId, SQueryTableMsg *pQueryMsg, qi
|
|||
bool isSTableQuery = false;
|
||||
STableGroupInfo groupInfo = {0};
|
||||
|
||||
//todo multitable_query??
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryMsg->queryType, TSDB_QUERY_TYPE_MULTITABLE_QUERY|TSDB_QUERY_TYPE_TABLE_QUERY)) {
|
||||
isSTableQuery = TSDB_QUERY_HAS_TYPE(pQueryMsg->queryType, TSDB_QUERY_TYPE_MULTITABLE_QUERY);
|
||||
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryMsg->queryType, TSDB_QUERY_TYPE_TABLE_QUERY)) {
|
||||
STableIdInfo *id = taosArrayGet(pTableIdList, 0);
|
||||
qTrace("qmsg:%p query table, uid:%"PRId64", tid:%d", pQueryMsg, id->uid, id->tid);
|
||||
|
||||
qTrace("qmsg:%p query normal table, uid:%"PRId64", tid:%d", pQueryMsg, id->uid, id->tid);
|
||||
if ((code = tsdbGetOneTableGroup(tsdb, id->uid, &groupInfo)) != TSDB_CODE_SUCCESS) {
|
||||
goto _over;
|
||||
}
|
||||
} else if (TSDB_QUERY_HAS_TYPE(pQueryMsg->queryType, TSDB_QUERY_TYPE_STABLE_QUERY)) {
|
||||
} else if (TSDB_QUERY_HAS_TYPE(pQueryMsg->queryType, TSDB_QUERY_TYPE_MULTITABLE_QUERY|TSDB_QUERY_TYPE_STABLE_QUERY)) {
|
||||
isSTableQuery = true;
|
||||
// TODO: need a macro from TSDB to check if table is super table,
|
||||
// also note there's possiblity that only one table in the super table
|
||||
if (taosArrayGetSize(pTableIdList) == 1) {
|
||||
// TODO: need a macro from TSDB to check if table is super table
|
||||
|
||||
// also note there's possibility that only one table in the super table
|
||||
if (!TSDB_QUERY_HAS_TYPE(pQueryMsg->queryType, TSDB_QUERY_TYPE_MULTITABLE_QUERY)) {
|
||||
STableIdInfo *id = taosArrayGet(pTableIdList, 0);
|
||||
// if array size is 1 and assert super table
|
||||
|
||||
// group by normal column, do not pass the group by condition to tsdb to group table into different group
|
||||
int32_t numOfGroupByCols = pQueryMsg->numOfGroupCols;
|
||||
|
@ -5795,15 +5934,13 @@ int32_t qCreateQueryInfo(void *tsdb, int32_t vgId, SQueryTableMsg *pQueryMsg, qi
|
|||
goto _over;
|
||||
}
|
||||
} else {
|
||||
SArray* pTableGroup = taosArrayInit(1, POINTER_BYTES);
|
||||
groupInfo.pGroupList = taosArrayInit(1, POINTER_BYTES);
|
||||
groupInfo.numOfTables = taosArrayGetSize(pTableIdList);
|
||||
|
||||
SArray* sa = taosArrayInit(groupInfo.numOfTables, sizeof(STableId));
|
||||
for(int32_t i = 0; i < groupInfo.numOfTables; ++i) {
|
||||
STableIdInfo* tableId = taosArrayGet(pTableIdList, i);
|
||||
taosArrayPush(sa, tableId);
|
||||
}
|
||||
taosArrayPush(pTableGroup, &sa);
|
||||
groupInfo.pGroupList = pTableGroup;
|
||||
SArray* p = taosArrayClone(pTableIdList);
|
||||
taosArrayPush(groupInfo.pGroupList, &p);
|
||||
|
||||
qTrace("qmsg:%p query on %d tables in one group from client", pQueryMsg, groupInfo.numOfTables);
|
||||
}
|
||||
} else {
|
||||
assert(0);
|
||||
|
@ -5844,7 +5981,7 @@ static void doDestoryQueryInfo(SQInfo* pQInfo) {
|
|||
freeQInfo(pQInfo);
|
||||
}
|
||||
|
||||
void qDestroyQueryInfo(qinfo_t qHandle) {
|
||||
void qDestroyQueryInfo(qinfo_t qHandle, void (*fp)(void*), void* param) {
|
||||
SQInfo* pQInfo = (SQInfo*) qHandle;
|
||||
if (!isValidQInfo(pQInfo)) {
|
||||
return;
|
||||
|
@ -5855,10 +5992,14 @@ void qDestroyQueryInfo(qinfo_t qHandle) {
|
|||
|
||||
if (ref == 0) {
|
||||
doDestoryQueryInfo(pQInfo);
|
||||
|
||||
if (fp != NULL) {
|
||||
fp(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void qTableQuery(qinfo_t qinfo) {
|
||||
void qTableQuery(qinfo_t qinfo, void (*fp)(void*), void* param) {
|
||||
SQInfo *pQInfo = (SQInfo *)qinfo;
|
||||
|
||||
if (pQInfo == NULL || pQInfo->signature != pQInfo) {
|
||||
|
@ -5868,7 +6009,7 @@ void qTableQuery(qinfo_t qinfo) {
|
|||
|
||||
if (isQueryKilled(pQInfo)) {
|
||||
qTrace("QInfo:%p it is already killed, abort", pQInfo);
|
||||
qDestroyQueryInfo(pQInfo);
|
||||
qDestroyQueryInfo(pQInfo, fp, param);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5884,7 +6025,7 @@ void qTableQuery(qinfo_t qinfo) {
|
|||
}
|
||||
|
||||
sem_post(&pQInfo->dataReady);
|
||||
qDestroyQueryInfo(pQInfo);
|
||||
qDestroyQueryInfo(pQInfo, fp, param);
|
||||
}
|
||||
|
||||
int32_t qRetrieveQueryResultInfo(qinfo_t qinfo) {
|
||||
|
@ -5901,7 +6042,7 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo) {
|
|||
}
|
||||
|
||||
sem_wait(&pQInfo->dataReady);
|
||||
qTrace("QInfo:%p retrieve result info, rowsize:%d, rows:%d, code:%d", pQInfo, pQuery->rowSize, pQuery->rec.rows,
|
||||
qTrace("QInfo:%p retrieve result info, rowsize:%d, rows:%"PRId64", code:%d", pQInfo, pQuery->rowSize, pQuery->rec.rows,
|
||||
pQInfo->code);
|
||||
|
||||
return pQInfo->code;
|
||||
|
@ -5977,7 +6118,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t qKillQuery(qinfo_t qinfo) {
|
||||
int32_t qKillQuery(qinfo_t qinfo, void (*fp)(void*), void* param) {
|
||||
SQInfo *pQInfo = (SQInfo *)qinfo;
|
||||
|
||||
if (pQInfo == NULL || !isValidQInfo(pQInfo)) {
|
||||
|
@ -5985,7 +6126,7 @@ int32_t qKillQuery(qinfo_t qinfo) {
|
|||
}
|
||||
|
||||
setQueryKilled(pQInfo);
|
||||
qDestroyQueryInfo(pQInfo);
|
||||
qDestroyQueryInfo(pQInfo, fp, param);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -6015,6 +6156,17 @@ static void buildTagQueryResult(SQInfo* pQInfo) {
|
|||
int32_t rsize = pExprInfo->bytes;
|
||||
count = 0;
|
||||
|
||||
int16_t bytes = pExprInfo->bytes;
|
||||
int16_t type = pExprInfo->type;
|
||||
|
||||
for(int32_t i = 0; i < pQuery->numOfTags; ++i) {
|
||||
if (pQuery->tagColList[i].colId == pExprInfo->base.colInfo.colId) {
|
||||
bytes = pQuery->tagColList[i].bytes;
|
||||
type = pQuery->tagColList[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while(pQInfo->tableIndex < num && count < pQuery->rec.capacity) {
|
||||
int32_t i = pQInfo->tableIndex++;
|
||||
SGroupItem *item = taosArrayGet(pa, i);
|
||||
|
@ -6032,9 +6184,6 @@ static void buildTagQueryResult(SQInfo* pQInfo) {
|
|||
*(int32_t *)output = pQInfo->vgId;
|
||||
output += sizeof(pQInfo->vgId);
|
||||
|
||||
int16_t bytes = pExprInfo->bytes;
|
||||
int16_t type = pExprInfo->type;
|
||||
|
||||
if (pExprInfo->base.colInfo.colId == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
char *data = tsdbGetTableName(pQInfo->tsdb, &item->id);
|
||||
memcpy(output, data, varDataTLen(data));
|
||||
|
@ -6051,7 +6200,7 @@ static void buildTagQueryResult(SQInfo* pQInfo) {
|
|||
} else {
|
||||
if (val == NULL) {
|
||||
setNull(output, type, bytes);
|
||||
} else {
|
||||
} else { // todo here stop will cause client crash
|
||||
memcpy(output, val, bytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,9 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) {
|
|||
for (int32_t i = 0; i < num; ++i) {
|
||||
SWindowResult *pResult = &pWindowResInfo->pResult[i];
|
||||
if (pResult->status.closed) { // remove the window slot from hash table
|
||||
taosHashRemove(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE);
|
||||
taosHashRemove(pWindowResInfo->hashList, (const char *)&pResult->window.skey, pWindowResInfo->type);
|
||||
printf("remove ============>%ld, remain size:%ld\n", pResult->window.skey, pWindowResInfo->hashList->size);
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -133,14 +135,16 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) {
|
|||
}
|
||||
|
||||
pWindowResInfo->size = remain;
|
||||
|
||||
printf("---------------size:%ld\n", taosHashGetSize(pWindowResInfo->hashList));
|
||||
for (int32_t k = 0; k < pWindowResInfo->size; ++k) {
|
||||
SWindowResult *pResult = &pWindowResInfo->pResult[k];
|
||||
int32_t *p = (int32_t *)taosHashGet(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE);
|
||||
int32_t *p = (int32_t *)taosHashGet(pWindowResInfo->hashList, (const char *)&pResult->window.skey,
|
||||
tDataTypeDesc[pWindowResInfo->type].nSize);
|
||||
|
||||
int32_t v = (*p - num);
|
||||
assert(v >= 0 && v <= pWindowResInfo->size);
|
||||
taosHashPut(pWindowResInfo->hashList, (char *)&pResult->window.skey, TSDB_KEYSIZE, (char *)&v, sizeof(int32_t));
|
||||
taosHashPut(pWindowResInfo->hashList, (char *)&pResult->window.skey, tDataTypeDesc[pWindowResInfo->type].nSize,
|
||||
(char *)&v, sizeof(int32_t));
|
||||
}
|
||||
|
||||
pWindowResInfo->curIndex = -1;
|
||||
|
|
|
@ -496,7 +496,6 @@ static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) {
|
|||
printf("relation is like\n");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -511,7 +510,7 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
|
|||
if (cond.start != NULL) {
|
||||
iter = tSkipListCreateIterFromVal(pSkipList, (char*) cond.start->v, pSkipList->keyInfo.type, TSDB_ORDER_ASC);
|
||||
} else {
|
||||
iter = tSkipListCreateIterFromVal(pSkipList, (char*) cond.end->v, pSkipList->keyInfo.type, TSDB_ORDER_DESC);
|
||||
iter = tSkipListCreateIterFromVal(pSkipList, (char*)(cond.end ? cond.end->v: NULL), pSkipList->keyInfo.type, TSDB_ORDER_DESC);
|
||||
}
|
||||
|
||||
if (cond.start != NULL) {
|
||||
|
@ -578,8 +577,7 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
|
|||
assert(0);
|
||||
}
|
||||
} else {
|
||||
int32_t optr = cond.end->optr;
|
||||
|
||||
int32_t optr = cond.end ? cond.end->optr : TSDB_RELATION_INVALID;
|
||||
if (optr == TSDB_RELATION_LESS || optr == TSDB_RELATION_LESS_EQUAL) {
|
||||
bool comp = true;
|
||||
int32_t ret = 0;
|
||||
|
@ -601,6 +599,9 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
|
|||
}
|
||||
}
|
||||
}
|
||||
free(cond.start);
|
||||
free(cond.end);
|
||||
tSkipListDestroyIter(iter);
|
||||
}
|
||||
|
||||
int32_t merge(SArray *pLeft, SArray *pRight, SArray *pFinalRes) {
|
||||
|
@ -748,6 +749,7 @@ static void exprTreeTraverseImpl(tExprNode *pExpr, SArray *pResult, SExprTravers
|
|||
}
|
||||
|
||||
taosArrayCopy(pResult, array);
|
||||
taosArrayDestroy(array);
|
||||
}
|
||||
|
||||
static void tSQLBinaryTraverseOnSkipList(tExprNode *pExpr, SArray *pResult, SSkipList *pSkipList, SExprTraverseSupp *param ) {
|
||||
|
|
|
@ -896,6 +896,7 @@ void tColModelDisplay(SColumnModel *pModel, void *pData, int32_t numOfRows, int3
|
|||
char buf[4096] = {0};
|
||||
taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf);
|
||||
printf("%s\t", buf);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
printBinaryData(val, pModel->pFields[j].field.bytes);
|
||||
|
@ -947,6 +948,7 @@ void tColModelDisplayEx(SColumnModel *pModel, void *pData, int32_t numOfRows, in
|
|||
char buf[128] = {0};
|
||||
taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf);
|
||||
printf("%s\t", buf);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
printBinaryDataEx(val, pModel->pFields[j].field.bytes, ¶m[j]);
|
||||
|
|
|
@ -775,19 +775,14 @@ void setDCLSQLElems(SSqlInfo *pInfo, int32_t type, int32_t nParam, ...) {
|
|||
|
||||
while (nParam-- > 0) {
|
||||
SSQLToken *pToken = va_arg(va, SSQLToken *);
|
||||
(void)tTokenListAppend(pInfo->pDCLInfo, pToken);
|
||||
pInfo->pDCLInfo = tTokenListAppend(pInfo->pDCLInfo, pToken);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void setDropDBTableInfo(SSqlInfo *pInfo, int32_t type, SSQLToken* pToken, SSQLToken* existsCheck) {
|
||||
pInfo->type = type;
|
||||
|
||||
if (pInfo->pDCLInfo == NULL) {
|
||||
pInfo->pDCLInfo = calloc(1, sizeof(tDCLSQL));
|
||||
}
|
||||
|
||||
tTokenListAppend(pInfo->pDCLInfo, pToken);
|
||||
pInfo->pDCLInfo = tTokenListAppend(pInfo->pDCLInfo, pToken);
|
||||
pInfo->pDCLInfo->existsCheck = (existsCheck->n == 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,6 @@ void tBucketDoubleHash(tMemBucket *pBucket, void *value, int16_t *segIdx, int16_
|
|||
tMemBucket *tMemBucketCreate(int32_t totalSlots, int32_t nBufferSize, int16_t nElemSize, int16_t dataType,
|
||||
tOrderDescriptor *pDesc) {
|
||||
tMemBucket *pBucket = (tMemBucket *)malloc(sizeof(tMemBucket));
|
||||
|
||||
pBucket->nTotalSlots = totalSlots;
|
||||
pBucket->nSlotsOfSeg = 1 << 6; // 64 Segments, 16 slots each seg.
|
||||
pBucket->dataType = dataType;
|
||||
|
@ -258,6 +257,7 @@ tMemBucket *tMemBucketCreate(int32_t totalSlots, int32_t nBufferSize, int16_t nE
|
|||
pBucket->numOfTotalPages = pBucket->nTotalBufferSize / pBucket->pageSize;
|
||||
pBucket->numOfAvailPages = pBucket->numOfTotalPages;
|
||||
|
||||
pBucket->pSegs = NULL;
|
||||
pBucket->pOrderDesc = pDesc;
|
||||
|
||||
switch (pBucket->dataType) {
|
||||
|
@ -283,7 +283,7 @@ tMemBucket *tMemBucketCreate(int32_t totalSlots, int32_t nBufferSize, int16_t nE
|
|||
break;
|
||||
};
|
||||
default: {
|
||||
uError("MemBucket:%p,not support data type %d,failed", *pBucket, pBucket->dataType);
|
||||
uError("MemBucket:%p,not support data type %d,failed", pBucket, pBucket->dataType);
|
||||
tfree(pBucket);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ tMemBucket *tMemBucketCreate(int32_t totalSlots, int32_t nBufferSize, int16_t nE
|
|||
pBucket->pSegs[i].pBoundingEntries = NULL;
|
||||
}
|
||||
|
||||
uTrace("MemBucket:%p,created,buffer size:%d,elem size:%d", pBucket, pBucket->numOfTotalPages * DEFAULT_PAGE_SIZE,
|
||||
uTrace("MemBucket:%p,created,buffer size:%ld,elem size:%d", pBucket, pBucket->numOfTotalPages * DEFAULT_PAGE_SIZE,
|
||||
pBucket->nElemSize);
|
||||
|
||||
return pBucket;
|
||||
|
@ -751,7 +751,7 @@ double getPercentileImpl(tMemBucket *pMemBucket, int32_t count, double fraction)
|
|||
|
||||
char * thisVal = buffer->data + pMemBucket->nElemSize * currentIdx;
|
||||
char * nextVal = thisVal + pMemBucket->nElemSize;
|
||||
double td, nd;
|
||||
double td = 1.0, nd = 1.0;
|
||||
switch (pMemBucket->dataType) {
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
td = *(int16_t *)thisVal;
|
||||
|
|
|
@ -6,7 +6,12 @@
|
|||
#include "queryLog.h"
|
||||
|
||||
int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t size, int32_t rowSize, void* handle) {
|
||||
SDiskbasedResultBuf* pResBuf = calloc(1, sizeof(SDiskbasedResultBuf));
|
||||
*pResultBuf = calloc(1, sizeof(SDiskbasedResultBuf));
|
||||
SDiskbasedResultBuf* pResBuf = *pResultBuf;
|
||||
if (pResBuf == NULL) {
|
||||
return TSDB_CODE_COM_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pResBuf->numOfRowsPerPage = (DEFAULT_INTERN_BUF_PAGE_SIZE - sizeof(tFilePage)) / rowSize;
|
||||
pResBuf->numOfPages = size;
|
||||
|
||||
|
@ -46,7 +51,6 @@ int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t si
|
|||
qTrace("QInfo:%p create tmp file for output result, %s, %" PRId64 "bytes", handle, pResBuf->path,
|
||||
pResBuf->totalBufSize);
|
||||
|
||||
*pResultBuf = pResBuf;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -210,7 +214,7 @@ void destroyResultBuf(SDiskbasedResultBuf* pResultBuf, void* handle) {
|
|||
}
|
||||
|
||||
int32_t getLastPageId(SIDList *pList) {
|
||||
if (pList == NULL && pList->size <= 0) {
|
||||
if (pList == NULL || pList->size <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ static int32_t STSBufUpdateHeader(STSBuf* pTSBuf, STSBufFileHeader* pHeader);
|
|||
* @param path
|
||||
* @return
|
||||
*/
|
||||
STSBuf* tsBufCreate(bool autoDelete) {
|
||||
STSBuf* tsBufCreate(bool autoDelete, int32_t order) {
|
||||
STSBuf* pTSBuf = calloc(1, sizeof(STSBuf));
|
||||
if (pTSBuf == NULL) {
|
||||
return NULL;
|
||||
|
@ -40,7 +40,7 @@ STSBuf* tsBufCreate(bool autoDelete) {
|
|||
pTSBuf->cur.order = TSDB_ORDER_ASC;
|
||||
|
||||
pTSBuf->autoDelete = autoDelete;
|
||||
pTSBuf->tsOrder = -1;
|
||||
pTSBuf->tsOrder = order;
|
||||
|
||||
return pTSBuf;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
|
|||
// validate the file magic number
|
||||
STSBufFileHeader header = {0};
|
||||
fseek(pTSBuf->f, 0, SEEK_SET);
|
||||
fread(&header, 1, sizeof(header), pTSBuf->f);
|
||||
fread(&header, 1, sizeof(STSBufFileHeader), pTSBuf->f);
|
||||
|
||||
// invalid file
|
||||
if (header.magic != TS_COMP_FILE_MAGIC) {
|
||||
|
@ -119,7 +119,6 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) {
|
|||
|
||||
// ascending by default
|
||||
pTSBuf->cur.order = TSDB_ORDER_ASC;
|
||||
|
||||
pTSBuf->autoDelete = autoDelete;
|
||||
|
||||
// tscTrace("create tsBuf from file:%s, fd:%d, size:%d, numOfVnode:%d, autoDelete:%d", pTSBuf->path, fileno(pTSBuf->f),
|
||||
|
@ -533,10 +532,12 @@ STSVnodeBlockInfo* tsBufGetVnodeBlockInfo(STSBuf* pTSBuf, int32_t vnodeId) {
|
|||
}
|
||||
|
||||
int32_t STSBufUpdateHeader(STSBuf* pTSBuf, STSBufFileHeader* pHeader) {
|
||||
if ((pTSBuf->f == NULL) || pHeader == NULL || pHeader->numOfVnode < 0 || pHeader->magic != TS_COMP_FILE_MAGIC) {
|
||||
if ((pTSBuf->f == NULL) || pHeader == NULL || pHeader->numOfVnode == 0 || pHeader->magic != TS_COMP_FILE_MAGIC) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(pHeader->tsOrder == TSDB_ORDER_ASC || pHeader->tsOrder == TSDB_ORDER_DESC);
|
||||
|
||||
int64_t r = fseek(pTSBuf->f, 0, SEEK_SET);
|
||||
if (r != 0) {
|
||||
return -1;
|
||||
|
@ -754,7 +755,7 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf, int32_t vnodeId) {
|
|||
}
|
||||
|
||||
STSBuf* tsBufCreateFromCompBlocks(const char* pData, int32_t numOfBlocks, int32_t len, int32_t order) {
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, order);
|
||||
|
||||
STSVnodeBlockInfo* pBlockInfo = &(addOneVnodeInfo(pTSBuf, 0)->info);
|
||||
pBlockInfo->numOfBlocks = numOfBlocks;
|
||||
|
@ -846,6 +847,8 @@ STSBuf* tsBufClone(STSBuf* pTSBuf) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
tsBufFlush(pTSBuf);
|
||||
|
||||
return tsBufCreateFromFile(pTSBuf->path, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -357,7 +357,7 @@ static int32_t toBinary(tVariant *pVariant, char **pDest, int32_t *pDestSize) {
|
|||
if (pVariant->nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
size_t newSize = pVariant->nLen * TSDB_NCHAR_SIZE;
|
||||
if (pBuf != NULL) {
|
||||
if (newSize > INITIAL_ALLOC_SIZE) {
|
||||
if (newSize >= INITIAL_ALLOC_SIZE) {
|
||||
pBuf = realloc(pBuf, newSize + 1);
|
||||
}
|
||||
|
||||
|
@ -474,6 +474,7 @@ static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result
|
|||
free(pVariant->pz);
|
||||
pVariant->nLen = 0;
|
||||
}
|
||||
|
||||
setNull((char *)result, type, tDataTypeDesc[type].nSize);
|
||||
return 0;
|
||||
}
|
||||
|
@ -597,7 +598,7 @@ static int32_t convertToBool(tVariant *pVariant, int64_t *pDest) {
|
|||
* todo handle the return value
|
||||
*/
|
||||
int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix) {
|
||||
if (pVariant == NULL || (pVariant->nType != 0 && !isValidDataType(pVariant->nType, pVariant->nLen))) {
|
||||
if (pVariant == NULL || (pVariant->nType != 0 && !isValidDataType(pVariant->nType))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -800,12 +801,13 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
int32_t newlen = 0;
|
||||
if (!includeLengthPrefix) {
|
||||
if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
|
||||
*(uint32_t *)payload = TSDB_DATA_NCHAR_NULL;
|
||||
} else {
|
||||
if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
|
||||
toNchar(pVariant, &payload, &pVariant->nLen);
|
||||
toNchar(pVariant, &payload, &newlen);
|
||||
} else {
|
||||
wcsncpy((wchar_t *)payload, pVariant->wpz, pVariant->nLen);
|
||||
}
|
||||
|
@ -817,12 +819,13 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu
|
|||
char *p = varDataVal(payload);
|
||||
|
||||
if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) {
|
||||
toNchar(pVariant, &p, &pVariant->nLen);
|
||||
toNchar(pVariant, &p, &newlen);
|
||||
} else {
|
||||
wcsncpy((wchar_t *)p, pVariant->wpz, pVariant->nLen);
|
||||
newlen = pVariant->nLen;
|
||||
}
|
||||
|
||||
varDataSetLen(payload, pVariant->nLen); // the length may be changed after toNchar function called
|
||||
varDataSetLen(payload, newlen); // the length may be changed after toNchar function called
|
||||
assert(p == varDataVal(payload));
|
||||
}
|
||||
}
|
||||
|
@ -885,7 +888,7 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) {
|
|||
free(pVariant->pz);
|
||||
pVariant->dKey = v;
|
||||
} else if (pVariant->nType >= TSDB_DATA_TYPE_BOOL && pVariant->nType <= TSDB_DATA_TYPE_BIGINT) {
|
||||
pVariant->dKey = pVariant->i64Key;
|
||||
pVariant->dKey = (double)(pVariant->i64Key);
|
||||
}
|
||||
|
||||
pVariant->nType = TSDB_DATA_TYPE_DOUBLE;
|
||||
|
|
|
@ -29,7 +29,7 @@ int64_t* createTsList(int32_t num, int64_t start, int32_t step) {
|
|||
|
||||
// simple test
|
||||
void simpleTest() {
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
// write 10 ts points
|
||||
int32_t num = 10;
|
||||
|
@ -52,7 +52,7 @@ void simpleTest() {
|
|||
|
||||
// one large list of ts, the ts list need to be split into several small blocks
|
||||
void largeTSTest() {
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
// write 10 ts points
|
||||
int32_t num = 1000000;
|
||||
|
@ -75,7 +75,7 @@ void largeTSTest() {
|
|||
}
|
||||
|
||||
void multiTagsTest() {
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
int32_t num = 10000;
|
||||
int64_t tag = 1;
|
||||
|
@ -105,7 +105,7 @@ void multiTagsTest() {
|
|||
}
|
||||
|
||||
void multiVnodeTagsTest() {
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
int32_t num = 10000;
|
||||
int64_t start = 10000000;
|
||||
|
@ -143,7 +143,7 @@ void multiVnodeTagsTest() {
|
|||
}
|
||||
|
||||
void loadDataTest() {
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
int32_t num = 10000;
|
||||
int64_t oldStart = 10000000;
|
||||
|
@ -221,7 +221,7 @@ void TSTraverse() {
|
|||
int32_t step = 30;
|
||||
int32_t numOfVnode = 2;
|
||||
|
||||
STSBuf* pTSBuf = tsBufCreate(true);
|
||||
STSBuf* pTSBuf = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
for (int32_t j = 0; j < numOfVnode; ++j) {
|
||||
// vnodeId:0
|
||||
|
@ -359,8 +359,8 @@ void invalidFileTest() {
|
|||
}
|
||||
|
||||
void mergeDiffVnodeBufferTest() {
|
||||
STSBuf* pTSBuf1 = tsBufCreate(true);
|
||||
STSBuf* pTSBuf2 = tsBufCreate(true);
|
||||
STSBuf* pTSBuf1 = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
STSBuf* pTSBuf2 = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
int32_t step = 30;
|
||||
int32_t num = 1000;
|
||||
|
@ -391,8 +391,8 @@ void mergeDiffVnodeBufferTest() {
|
|||
}
|
||||
|
||||
void mergeIdenticalVnodeBufferTest() {
|
||||
STSBuf* pTSBuf1 = tsBufCreate(true);
|
||||
STSBuf* pTSBuf2 = tsBufCreate(true);
|
||||
STSBuf* pTSBuf1 = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
STSBuf* pTSBuf2 = tsBufCreate(true, TSDB_ORDER_ASC);
|
||||
|
||||
int32_t step = 30;
|
||||
int32_t num = 1000;
|
||||
|
|
|
@ -334,19 +334,19 @@ TEST(testCase, parse_time) {
|
|||
|
||||
int64_t time = 0, time1 = 0;
|
||||
|
||||
taosParseTime(t1, &time, strlen(t1), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t1, &time, strlen(t1), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 1514739661952);
|
||||
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, timezone * MILLISECOND_PER_SECOND);
|
||||
|
||||
char t2[] = "2018-1-1T1:1:1.952Z";
|
||||
taosParseTime(t2, &time, strlen(t2), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t2, &time, strlen(t2), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
|
||||
EXPECT_EQ(time, 1514739661952 + 28800000);
|
||||
|
||||
char t3[] = "2018-1-1 1:01:01.952";
|
||||
taosParseTime(t3, &time, strlen(t3), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t3, &time, strlen(t3), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 1514739661952);
|
||||
|
||||
char t4[] = "2018-1-1 1:01:01.9";
|
||||
|
@ -355,89 +355,89 @@ TEST(testCase, parse_time) {
|
|||
char t7[] = "2018-01-01 01:01:01.9";
|
||||
char t8[] = "2018-01-01 01:01:01.9007865";
|
||||
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t5, &time1, strlen(t5), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t5, &time1, strlen(t5), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t6, &time1, strlen(t6), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t6, &time1, strlen(t6), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t7, &time1, strlen(t7), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t4, &time, strlen(t4), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t7, &time1, strlen(t7), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taosParseTime(t5, &time, strlen(t5), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t8, &time1, strlen(t8), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t5, &time, strlen(t5), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t8, &time1, strlen(t8), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
char t9[] = "2017-4-3 1:1:2.980";
|
||||
char t10[] = "2017-4-3T2:1:2.98+9:00";
|
||||
taosParseTime(t9, &time, strlen(t9), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t9, &time, strlen(t9), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
char t11[] = "2017-4-3T2:1:2.98+09:00";
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t10, &time1, strlen(t10), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
char t12[] = "2017-4-3T2:1:2.98+0900";
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t11, &time, strlen(t11), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
taosParseTime(t12, &time1, strlen(t12), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, time1);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "UTC");
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t13, &time, strlen(t13), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 0);
|
||||
|
||||
taos_options(TSDB_OPTION_TIMEZONE, "Asia/Shanghai");
|
||||
char t14[] = "1970-1-1T0:0:0Z";
|
||||
taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t14, &time, strlen(t14), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 0);
|
||||
|
||||
char t40[] = "1970-1-1 0:0:0.999999999";
|
||||
taosParseTime(t40, &time, strlen(t40), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t40, &time, strlen(t40), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 999 + timezone * MILLISECOND_PER_SECOND);
|
||||
|
||||
char t41[] = "1997-1-1 0:0:0.999999999";
|
||||
taosParseTime(t41, &time, strlen(t41), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t41, &time, strlen(t41), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 852048000999);
|
||||
|
||||
int64_t k = timezone;
|
||||
char t42[] = "1997-1-1T0:0:0.999999999Z";
|
||||
taosParseTime(t42, &time, strlen(t42), TSDB_TIME_PRECISION_MILLI);
|
||||
taosParseTime(t42, &time, strlen(t42), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
EXPECT_EQ(time, 852048000999 - timezone * MILLISECOND_PER_SECOND);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// illegal timestamp format
|
||||
char t15[] = "2017-12-33 0:0:0";
|
||||
EXPECT_EQ(taosParseTime(t15, &time, strlen(t15), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t15, &time, strlen(t15), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t16[] = "2017-12-31 99:0:0";
|
||||
EXPECT_EQ(taosParseTime(t16, &time, strlen(t16), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t16, &time, strlen(t16), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t17[] = "2017-12-31T9:0:0";
|
||||
EXPECT_EQ(taosParseTime(t17, &time, strlen(t17), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t17, &time, strlen(t17), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t18[] = "2017-12-31T9:0:0.Z";
|
||||
EXPECT_EQ(taosParseTime(t18, &time, strlen(t18), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t18, &time, strlen(t18), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t19[] = "2017-12-31 9:0:0.-1";
|
||||
EXPECT_EQ(taosParseTime(t19, &time, strlen(t19), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t19, &time, strlen(t19), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t20[] = "2017-12-31 9:0:0.1+12:99";
|
||||
EXPECT_EQ(taosParseTime(t20, &time, strlen(t20), TSDB_TIME_PRECISION_MILLI), 0);
|
||||
EXPECT_EQ(taosParseTime(t20, &time, strlen(t20), TSDB_TIME_PRECISION_MILLI, 0), 0);
|
||||
EXPECT_EQ(time, 1514682000100);
|
||||
|
||||
char t21[] = "2017-12-31T9:0:0.1+12:99";
|
||||
EXPECT_EQ(taosParseTime(t21, &time, strlen(t21), TSDB_TIME_PRECISION_MILLI), -1);
|
||||
EXPECT_EQ(taosParseTime(t21, &time, strlen(t21), TSDB_TIME_PRECISION_MILLI, 0), -1);
|
||||
|
||||
char t22[] = "2017-12-31 9:0:0.1+13:1";
|
||||
EXPECT_EQ(taosParseTime(t22, &time, strlen(t22), TSDB_TIME_PRECISION_MILLI), 0);
|
||||
EXPECT_EQ(taosParseTime(t22, &time, strlen(t22), TSDB_TIME_PRECISION_MILLI, 0), 0);
|
||||
|
||||
char t23[] = "2017-12-31T9:0:0.1+13:1";
|
||||
EXPECT_EQ(taosParseTime(t23, &time, strlen(t23), TSDB_TIME_PRECISION_MILLI), 0);
|
||||
EXPECT_EQ(taosParseTime(t23, &time, strlen(t23), TSDB_TIME_PRECISION_MILLI, 0), 0);
|
||||
}
|
||||
|
||||
TEST(testCase, tvariant_convert) {
|
||||
|
|
|
@ -73,6 +73,7 @@ typedef struct {
|
|||
SRpcInfo *pRpc; // associated SRpcInfo
|
||||
SRpcIpSet ipSet; // ip list provided by app
|
||||
void *ahandle; // handle provided by app
|
||||
struct SRpcConn *pConn; // pConn allocated
|
||||
char msgType; // message type
|
||||
uint8_t *pCont; // content provided by app
|
||||
int32_t contLen; // content length
|
||||
|
@ -339,7 +340,7 @@ void *rpcReallocCont(void *ptr, int contLen) {
|
|||
return start + sizeof(SRpcReqContext) + sizeof(SRpcHead);
|
||||
}
|
||||
|
||||
void rpcSendRequest(void *shandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg) {
|
||||
void *rpcSendRequest(void *shandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg) {
|
||||
SRpcInfo *pRpc = (SRpcInfo *)shandle;
|
||||
SRpcReqContext *pContext;
|
||||
|
||||
|
@ -367,7 +368,7 @@ void rpcSendRequest(void *shandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg)
|
|||
|
||||
rpcSendReqToServer(pRpc, pContext);
|
||||
|
||||
return;
|
||||
return pContext;
|
||||
}
|
||||
|
||||
void rpcSendResponse(const SRpcMsg *pRsp) {
|
||||
|
@ -486,12 +487,37 @@ void rpcSendRecv(void *shandle, SRpcIpSet *pIpSet, const SRpcMsg *pMsg, SRpcMsg
|
|||
}
|
||||
|
||||
// this API is used by server app to keep an APP context in case connection is broken
|
||||
void rpcReportProgress(void *handle, char *pCont, int contLen) {
|
||||
int rpcReportProgress(void *handle, char *pCont, int contLen) {
|
||||
SRpcConn *pConn = (SRpcConn *)handle;
|
||||
int code = 0;
|
||||
|
||||
rpcLockConn(pConn);
|
||||
|
||||
if (pConn->user[0]) {
|
||||
// pReqMsg and reqMsgLen is re-used to store the context from app server
|
||||
pConn->pReqMsg = pCont;
|
||||
pConn->reqMsgLen = contLen;
|
||||
} else {
|
||||
tTrace("%s, rpc connection is already released", pConn->info);
|
||||
rpcFreeCont(pCont);
|
||||
code = -1;
|
||||
}
|
||||
|
||||
rpcUnlockConn(pConn);
|
||||
return code;
|
||||
}
|
||||
|
||||
/* todo: cancel process may have race condition, pContext may have been released
|
||||
just before app calls the rpcCancelRequest */
|
||||
void rpcCancelRequest(void *handle) {
|
||||
SRpcReqContext *pContext = handle;
|
||||
|
||||
if (pContext->pConn) {
|
||||
tTrace("%s, app trys to cancel request", pContext->pConn->info);
|
||||
rpcCloseConn(pContext->pConn);
|
||||
pContext->pConn = NULL;
|
||||
rpcFreeCont(pContext->pCont);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpcFreeMsg(void *msg) {
|
||||
|
@ -534,18 +560,10 @@ static SRpcConn *rpcOpenConn(SRpcInfo *pRpc, char *peerFqdn, uint16_t peerPort,
|
|||
return pConn;
|
||||
}
|
||||
|
||||
static void rpcCloseConn(void *thandle) {
|
||||
SRpcConn *pConn = (SRpcConn *)thandle;
|
||||
static void rpcReleaseConn(SRpcConn *pConn) {
|
||||
SRpcInfo *pRpc = pConn->pRpc;
|
||||
if (pConn->user[0] == 0) return;
|
||||
|
||||
rpcLockConn(pConn);
|
||||
|
||||
if (pConn->user[0] == 0) {
|
||||
rpcUnlockConn(pConn);
|
||||
return;
|
||||
}
|
||||
|
||||
pConn->user[0] = 0;
|
||||
if (taosCloseConn[pConn->connType]) (*taosCloseConn[pConn->connType])(pConn->chandle);
|
||||
|
||||
|
@ -570,7 +588,16 @@ static void rpcCloseConn(void *thandle) {
|
|||
taosFreeId(pRpc->idPool, pConn->sid);
|
||||
pConn->pContext = NULL;
|
||||
|
||||
tTrace("%s, rpc connection is closed", pConn->info);
|
||||
tTrace("%s, rpc connection is released", pConn->info);
|
||||
}
|
||||
|
||||
static void rpcCloseConn(void *thandle) {
|
||||
SRpcConn *pConn = (SRpcConn *)thandle;
|
||||
|
||||
rpcLockConn(pConn);
|
||||
|
||||
if (pConn->user[0])
|
||||
rpcReleaseConn(pConn);
|
||||
|
||||
rpcUnlockConn(pConn);
|
||||
}
|
||||
|
@ -674,6 +701,7 @@ static SRpcConn *rpcGetConnObj(SRpcInfo *pRpc, int sid, SRecvInfo *pRecv) {
|
|||
if (pConn) {
|
||||
if (pConn->linkUid != pHead->linkUid) {
|
||||
terrno = TSDB_CODE_RPC_MISMATCHED_LINK_ID;
|
||||
tError("%s %p %p, linkUid:0x%x is not matched with received:0x%x", pRpc->label, pConn, pHead->ahandle, pConn->linkUid, pHead->linkUid);
|
||||
pConn = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -867,6 +895,7 @@ static void rpcReportBrokenLinkToServer(SRpcConn *pConn) {
|
|||
SRpcMsg rpcMsg;
|
||||
rpcMsg.pCont = pConn->pReqMsg; // pReqMsg is re-used to store the APP context from server
|
||||
rpcMsg.contLen = pConn->reqMsgLen; // reqMsgLen is re-used to store the APP context length
|
||||
rpcMsg.ahandle = pConn->ahandle;
|
||||
rpcMsg.handle = pConn;
|
||||
rpcMsg.msgType = pConn->inType;
|
||||
rpcMsg.code = TSDB_CODE_RPC_NETWORK_UNAVAIL;
|
||||
|
@ -888,8 +917,8 @@ static void rpcProcessBrokenLink(SRpcConn *pConn) {
|
|||
|
||||
if (pConn->inType) rpcReportBrokenLinkToServer(pConn);
|
||||
|
||||
rpcReleaseConn(pConn);
|
||||
rpcUnlockConn(pConn);
|
||||
rpcCloseConn(pConn);
|
||||
}
|
||||
|
||||
static void *rpcProcessMsgFromPeer(SRecvInfo *pRecv) {
|
||||
|
@ -902,7 +931,7 @@ static void *rpcProcessMsgFromPeer(SRecvInfo *pRecv) {
|
|||
// underlying UDP layer does not know it is server or client
|
||||
pRecv->connType = pRecv->connType | pRpc->connType;
|
||||
|
||||
if (pRecv->ip == 0) {
|
||||
if (pRecv->msg == NULL) {
|
||||
rpcProcessBrokenLink(pConn);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -935,6 +964,7 @@ static void *rpcProcessMsgFromPeer(SRecvInfo *pRecv) {
|
|||
static void rpcNotifyClient(SRpcReqContext *pContext, SRpcMsg *pMsg) {
|
||||
SRpcInfo *pRpc = pContext->pRpc;
|
||||
|
||||
pContext->pConn = NULL;
|
||||
if (pContext->pRsp) {
|
||||
// for synchronous API
|
||||
memcpy(pContext->pSet, &pContext->ipSet, sizeof(SRpcIpSet));
|
||||
|
@ -1103,6 +1133,7 @@ static void rpcSendReqToServer(SRpcInfo *pRpc, SRpcReqContext *pContext) {
|
|||
return;
|
||||
}
|
||||
|
||||
pContext->pConn = pConn;
|
||||
pConn->ahandle = pContext->ahandle;
|
||||
rpcLockConn(pConn);
|
||||
|
||||
|
@ -1192,7 +1223,6 @@ static void rpcProcessConnError(void *param, void *id) {
|
|||
static void rpcProcessRetryTimer(void *param, void *tmrId) {
|
||||
SRpcConn *pConn = (SRpcConn *)param;
|
||||
SRpcInfo *pRpc = pConn->pRpc;
|
||||
int reportDisc = 0;
|
||||
|
||||
rpcLockConn(pConn);
|
||||
|
||||
|
@ -1208,31 +1238,33 @@ static void rpcProcessRetryTimer(void *param, void *tmrId) {
|
|||
} else {
|
||||
// close the connection
|
||||
tTrace("%s, failed to send msg:%s to %s:%hu", pConn->info, taosMsg[pConn->outType], pConn->peerFqdn, pConn->peerPort);
|
||||
reportDisc = 1;
|
||||
if (pConn->pContext) {
|
||||
pConn->pContext->code = TSDB_CODE_RPC_NETWORK_UNAVAIL;
|
||||
taosTmrStart(rpcProcessConnError, 0, pConn->pContext, pRpc->tmrCtrl);
|
||||
rpcReleaseConn(pConn);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tTrace("%s, retry timer not processed", pConn->info);
|
||||
}
|
||||
|
||||
rpcUnlockConn(pConn);
|
||||
|
||||
if (reportDisc && pConn->pContext) {
|
||||
pConn->pContext->code = TSDB_CODE_RPC_NETWORK_UNAVAIL;
|
||||
rpcProcessConnError(pConn->pContext, NULL);
|
||||
rpcCloseConn(pConn);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpcProcessIdleTimer(void *param, void *tmrId) {
|
||||
SRpcConn *pConn = (SRpcConn *)param;
|
||||
|
||||
rpcLockConn(pConn);
|
||||
|
||||
if (pConn->user[0]) {
|
||||
tTrace("%s, close the connection since no activity", pConn->info);
|
||||
if (pConn->inType) rpcReportBrokenLinkToServer(pConn);
|
||||
rpcCloseConn(pConn);
|
||||
rpcReleaseConn(pConn);
|
||||
} else {
|
||||
tTrace("%s, idle timer:%p not processed", pConn->info, tmrId);
|
||||
}
|
||||
|
||||
rpcUnlockConn(pConn);
|
||||
}
|
||||
|
||||
static void rpcProcessProgressTimer(void *param, void *tmrId) {
|
||||
|
|
|
@ -117,7 +117,7 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread
|
|||
code = pthread_mutex_init(&(pThreadObj->mutex), NULL);
|
||||
if (code < 0) {
|
||||
tError("%s failed to init TCP process data mutex(%s)", label, strerror(errno));
|
||||
break;;
|
||||
break;
|
||||
}
|
||||
|
||||
pThreadObj->pollFd = epoll_create(10); // size does not matter
|
||||
|
@ -367,7 +367,7 @@ static void taosReportBrokenLink(SFdObj *pFdObj) {
|
|||
recvInfo.ip = 0;
|
||||
recvInfo.port = 0;
|
||||
recvInfo.shandle = pThreadObj->shandle;
|
||||
recvInfo.thandle = pFdObj->thandle;;
|
||||
recvInfo.thandle = pFdObj->thandle;
|
||||
recvInfo.chandle = NULL;
|
||||
recvInfo.connType = RPC_CONN_TCP;
|
||||
(*(pThreadObj->processData))(&recvInfo);
|
||||
|
@ -414,7 +414,7 @@ static int taosReadTcpData(SFdObj *pFdObj, SRecvInfo *pInfo) {
|
|||
pInfo->ip = pFdObj->ip;
|
||||
pInfo->port = pFdObj->port;
|
||||
pInfo->shandle = pThreadObj->shandle;
|
||||
pInfo->thandle = pFdObj->thandle;;
|
||||
pInfo->thandle = pFdObj->thandle;
|
||||
pInfo->chandle = pFdObj;
|
||||
pInfo->connType = RPC_CONN_TCP;
|
||||
|
||||
|
|
|
@ -1936,8 +1936,7 @@ int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) {
|
|||
SColIndex* pColIndex = &pTableGroupSupp->pCols[i];
|
||||
int32_t colIndex = pColIndex->colIndex;
|
||||
|
||||
assert((colIndex >= 0 && colIndex < schemaNCols(pTableGroupSupp->pTagSchema)) ||
|
||||
(colIndex == TSDB_TBNAME_COLUMN_INDEX));
|
||||
assert(colIndex >= TSDB_TBNAME_COLUMN_INDEX);
|
||||
|
||||
char * f1 = NULL;
|
||||
char * f2 = NULL;
|
||||
|
@ -1957,6 +1956,19 @@ int32_t tableGroupComparFn(const void *p1, const void *p2, const void *param) {
|
|||
f2 = tdGetKVRowValOfCol(pTable2->tagVal, pCol->colId);
|
||||
}
|
||||
|
||||
// this tags value may be NULL
|
||||
if (f1 == NULL && f2 == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (f2 == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t ret = doCompare(f1, f2, type, bytes);
|
||||
if (ret == 0) {
|
||||
continue;
|
||||
|
@ -2118,8 +2130,8 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, const char* pT
|
|||
}
|
||||
|
||||
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);
|
||||
tsdbError("%p query normal tag not allowed, uid:%" PRIu64 ", tid:%d, name:%s", tsdb, uid, pTable->tableId.tid,
|
||||
pTable->name);
|
||||
|
||||
return TSDB_CODE_COM_OPS_NOT_SUPPORT; //basically, this error is caused by invalid sql issued by client
|
||||
}
|
||||
|
@ -2134,7 +2146,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, tsdb);
|
||||
|
||||
tsdbTrace("no tbname condition or tagcond, all tables belongs to one group, numOfTables:%d", pGroupInfo->numOfTables);
|
||||
tsdbTrace("%p no table name/tag condition, all tables belong to one group, numOfTables:%d", tsdb, pGroupInfo->numOfTables);
|
||||
} else {
|
||||
// todo add error
|
||||
}
|
||||
|
@ -2178,6 +2190,9 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, const char* pT
|
|||
pGroupInfo->numOfTables = taosArrayGetSize(res);
|
||||
pGroupInfo->pGroupList = createTableGroup(res, pTagSchema, pColIndex, numOfCols, tsdb);
|
||||
|
||||
tsdbTrace("%p stable tid:%d, uid:%"PRIu64" query, numOfTables:%d, belong to %d groups", tsdb, pTable->tableId.tid,
|
||||
pTable->tableId.uid, pGroupInfo->numOfTables, taosArrayGetSize(pGroupInfo->pGroupList));
|
||||
|
||||
taosArrayDestroy(res);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) {
|
|||
|
||||
int32_t getTimestampInUsFromStr(char* token, int32_t tokenlen, int64_t* ts);
|
||||
|
||||
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec);
|
||||
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth);
|
||||
void deltaToUtcInitOnce();
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -42,7 +42,8 @@ extern "C" {
|
|||
} \
|
||||
}
|
||||
|
||||
#define tstrncpy(dst, src, size) do { \
|
||||
#define tstrncpy(dst, src, size) \
|
||||
do { \
|
||||
strncpy((dst), (src), (size)); \
|
||||
(dst)[(size)-1] = 0; \
|
||||
} while (0);
|
||||
|
|
|
@ -63,10 +63,12 @@ static FORCE_INLINE void __cache_lock_destroy(SCacheObj *pCacheObj) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static FORCE_INLINE void taosFreeNode(void *data) {
|
||||
SCacheDataNode *pNode = *(SCacheDataNode **)data;
|
||||
free(pNode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @param key key of object for hash, usually a null-terminated string
|
||||
|
@ -241,7 +243,7 @@ SCacheObj *taosCacheInitWithCb(int64_t refreshTime, void (*freeCb)(void *data))
|
|||
}
|
||||
|
||||
// set free cache node callback function for hash table
|
||||
taosHashSetFreecb(pCacheObj->pHashTable, taosFreeNode);
|
||||
// taosHashSetFreecb(pCacheObj->pHashTable, taosFreeNode);
|
||||
|
||||
pCacheObj->freeFp = freeCb;
|
||||
pCacheObj->refreshTime = refreshTime * 1000;
|
||||
|
@ -565,6 +567,16 @@ void taosTrashCanEmpty(SCacheObj *pCacheObj, bool force) {
|
|||
|
||||
void doCleanupDataCache(SCacheObj *pCacheObj) {
|
||||
__cache_wr_lock(pCacheObj);
|
||||
|
||||
SHashMutableIterator *pIter = taosHashCreateIter(pCacheObj->pHashTable);
|
||||
while (taosHashIterNext(pIter)) {
|
||||
SCacheDataNode *pNode = *(SCacheDataNode **)taosHashIterGet(pIter);
|
||||
// if (pNode->expiredTime <= expiredTime && T_REF_VAL_GET(pNode) <= 0) {
|
||||
taosCacheReleaseNode(pCacheObj, pNode);
|
||||
//}
|
||||
}
|
||||
taosHashDestroyIter(pIter);
|
||||
|
||||
taosHashCleanup(pCacheObj->pHashTable);
|
||||
__cache_unlock(pCacheObj);
|
||||
|
||||
|
|
|
@ -736,7 +736,7 @@ static uint32_t table[16][256] = {
|
|||
0x9c221d09, 0x6e2e10f7, 0x7dd67004, 0x8fda7dfa}
|
||||
|
||||
};
|
||||
|
||||
#ifndef _TD_ARM_
|
||||
static uint32_t long_shifts[4][256] = {
|
||||
{0x00000000, 0xe040e0ac, 0xc56db7a9, 0x252d5705, 0x8f3719a3, 0x6f77f90f,
|
||||
0x4a5aae0a, 0xaa1a4ea6, 0x1b8245b7, 0xfbc2a51b, 0xdeeff21e, 0x3eaf12b2,
|
||||
|
@ -1090,7 +1090,7 @@ static uint32_t short_shifts[4][256] = {
|
|||
0x3c3f083d, 0x1984fde6, 0x7748e38b, 0x52f31650, 0xaad0df51, 0x8f6b2a8a,
|
||||
0xe1a734e7, 0xc41cc13c, 0x140cd014, 0x31b725cf, 0x5f7b3ba2, 0x7ac0ce79,
|
||||
0x82e30778, 0xa758f2a3, 0xc994ecce, 0xec2f1915}};
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
static uint32_t append_trivial(uint32_t crc, crc_stream input, size_t length) {
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
|
@ -1187,13 +1187,13 @@ uint32_t crc32c_sf(uint32_t crci, crc_stream input, size_t length) {
|
|||
}
|
||||
return (uint32_t)crc ^ 0xffffffff;
|
||||
}
|
||||
|
||||
#ifndef _TD_ARM_
|
||||
/* Apply the zeros operator table to crc. */
|
||||
static uint32_t shift_crc(uint32_t shift_table[][256], uint32_t crc) {
|
||||
return shift_table[0][crc & 0xff] ^ shift_table[1][(crc >> 8) & 0xff] ^
|
||||
shift_table[2][(crc >> 16) & 0xff] ^ shift_table[3][crc >> 24];
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Compute a CRC-32C. If the crc32 instruction is available, use the hardware
|
||||
version. Otherwise, use the software version. */
|
||||
uint32_t (*crc32c)(uint32_t crci, crc_stream bytes, size_t len) = crc32c_sf;
|
||||
|
|
|
@ -29,7 +29,7 @@ static FILE* fpAllocLog = NULL;
|
|||
// memory allocator which fails randomly
|
||||
|
||||
extern int32_t taosGetTimestampSec();
|
||||
static int32_t startTime = INT32_MAX;;
|
||||
static int32_t startTime = INT32_MAX;
|
||||
|
||||
static bool random_alloc_fail(size_t size, const char* file, uint32_t line) {
|
||||
if (taosGetTimestampSec() < startTime) {
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "taosdef.h"
|
||||
#include "ttime.h"
|
||||
#include "tutil.h"
|
||||
|
||||
/*
|
||||
* mktime64 - Converts date to seconds.
|
||||
* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
|
||||
|
@ -119,15 +118,21 @@ static int month[12] = {
|
|||
static int64_t parseFraction(char* str, char** end, int32_t timePrec);
|
||||
static int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec);
|
||||
static int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec);
|
||||
static int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec);
|
||||
|
||||
static int32_t (*parseLocaltimeFp[]) (char* timestr, int64_t* time, int32_t timePrec) = {
|
||||
parseLocaltime,
|
||||
parseLocaltimeWithDst
|
||||
};
|
||||
|
||||
int32_t taosGetTimestampSec() { return (int32_t)time(NULL); }
|
||||
|
||||
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec) {
|
||||
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t daylight) {
|
||||
/* parse datatime string in with tz */
|
||||
if (strnchr(timestr, 'T', len, false) != NULL) {
|
||||
return parseTimeWithTz(timestr, time, timePrec);
|
||||
} else {
|
||||
return parseLocaltime(timestr, time, timePrec);
|
||||
return (*parseLocaltimeFp[daylight])(timestr, time, timePrec);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,9 +309,6 @@ int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* mktime will be affected by TZ, set by using taos_options */
|
||||
//int64_t seconds = mktime(&tm);
|
||||
//int64_t seconds = (int64_t)user_mktime(&tm);
|
||||
int64_t seconds = user_mktime64(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||
|
||||
int64_t fraction = 0;
|
||||
|
@ -324,6 +326,32 @@ int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec) {
|
||||
*time = 0;
|
||||
struct tm tm = {0};
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
char* str = strptime(timestr, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
if (str == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* mktime will be affected by TZ, set by using taos_options */
|
||||
int64_t seconds = mktime(&tm);
|
||||
|
||||
int64_t fraction = 0;
|
||||
|
||||
if (*str == '.') {
|
||||
/* parse the second fraction part */
|
||||
if ((fraction = parseFraction(str + 1, &str, timePrec)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 : 1000000;
|
||||
*time = factor * seconds + fraction;
|
||||
return 0;
|
||||
}
|
||||
static int32_t getTimestampInUsFromStrImpl(int64_t val, char unit, int64_t* result) {
|
||||
*result = val;
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ int32_t vnodeCreate(SMDCreateVnodeMsg *pVnodeCfg) {
|
|||
tsdbCfg.minRowsPerFileBlock = pVnodeCfg->cfg.minRowsPerFileBlock;
|
||||
tsdbCfg.maxRowsPerFileBlock = pVnodeCfg->cfg.maxRowsPerFileBlock;
|
||||
tsdbCfg.precision = pVnodeCfg->cfg.precision;
|
||||
tsdbCfg.compression = pVnodeCfg->cfg.compression;;
|
||||
tsdbCfg.compression = pVnodeCfg->cfg.compression;
|
||||
|
||||
char tsdbDir[TSDB_FILENAME_LEN] = {0};
|
||||
sprintf(tsdbDir, "%s/vnode%d/tsdb", tsVnodeDir, pVnodeCfg->cfg.vgId);
|
||||
|
@ -321,6 +321,27 @@ void vnodeRelease(void *pVnodeRaw) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (pVnode->tsdb)
|
||||
tsdbCloseRepo(pVnode->tsdb, 1);
|
||||
pVnode->tsdb = NULL;
|
||||
|
||||
// stop continuous query
|
||||
if (pVnode->cq)
|
||||
cqClose(pVnode->cq);
|
||||
pVnode->cq = NULL;
|
||||
|
||||
if (pVnode->wal)
|
||||
walClose(pVnode->wal);
|
||||
pVnode->wal = NULL;
|
||||
|
||||
if (pVnode->wqueue)
|
||||
dnodeFreeVnodeWqueue(pVnode->wqueue);
|
||||
pVnode->wqueue = NULL;
|
||||
|
||||
if (pVnode->rqueue)
|
||||
dnodeFreeVnodeRqueue(pVnode->rqueue);
|
||||
pVnode->rqueue = NULL;
|
||||
|
||||
tfree(pVnode->rootDir);
|
||||
|
||||
if (pVnode->status == TAOS_VN_STATUS_DELETING) {
|
||||
|
@ -411,33 +432,16 @@ void vnodeBuildStatusMsg(void *param) {
|
|||
}
|
||||
|
||||
static void vnodeCleanUp(SVnodeObj *pVnode) {
|
||||
// remove from hash, so new messages wont be consumed
|
||||
taosHashRemove(tsDnodeVnodesHash, (const char *)&pVnode->vgId, sizeof(int32_t));
|
||||
|
||||
// stop replication module
|
||||
if (pVnode->sync) {
|
||||
syncStop(pVnode->sync);
|
||||
pVnode->sync = NULL;
|
||||
}
|
||||
|
||||
if (pVnode->tsdb)
|
||||
tsdbCloseRepo(pVnode->tsdb, 1);
|
||||
pVnode->tsdb = NULL;
|
||||
|
||||
if (pVnode->wal)
|
||||
walClose(pVnode->wal);
|
||||
pVnode->wal = NULL;
|
||||
|
||||
if (pVnode->cq)
|
||||
cqClose(pVnode->cq);
|
||||
pVnode->cq = NULL;
|
||||
|
||||
if (pVnode->wqueue)
|
||||
dnodeFreeVnodeWqueue(pVnode->wqueue);
|
||||
pVnode->wqueue = NULL;
|
||||
|
||||
if (pVnode->rqueue)
|
||||
dnodeFreeVnodeRqueue(pVnode->rqueue);
|
||||
pVnode->rqueue = NULL;
|
||||
|
||||
// release local resources only after cutting off outside connections
|
||||
vnodeRelease(pVnode);
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ int32_t vnodeProcessRead(void *param, SReadMsg *pReadMsg) {
|
|||
|
||||
// notify connection(handle) that current qhandle is created, if current connection from
|
||||
// client is broken, the query needs to be killed immediately.
|
||||
static void vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId) {
|
||||
static int32_t vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId) {
|
||||
SRetrieveTableMsg* killQueryMsg = rpcMallocCont(sizeof(SRetrieveTableMsg));
|
||||
killQueryMsg->qhandle = htobe64((uint64_t) qhandle);
|
||||
killQueryMsg->free = htons(1);
|
||||
|
@ -69,7 +69,7 @@ static void vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId)
|
|||
killQueryMsg->header.contLen = htonl(sizeof(SRetrieveTableMsg));
|
||||
|
||||
vTrace("QInfo:%p register qhandle to connect:%p", qhandle, handle);
|
||||
rpcReportProgress(handle, (char*) killQueryMsg, sizeof(SRetrieveTableMsg));
|
||||
return rpcReportProgress(handle, (char*) killQueryMsg, sizeof(SRetrieveTableMsg));
|
||||
}
|
||||
|
||||
static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
||||
|
@ -89,7 +89,10 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
|||
vWarn("QInfo:%p connection %p broken, kill query", killQueryMsg->qhandle, pReadMsg->rpcMsg.handle);
|
||||
assert(pReadMsg->rpcMsg.contLen > 0 && killQueryMsg->free == 1);
|
||||
|
||||
qKillQuery((qinfo_t) killQueryMsg->qhandle);
|
||||
// this message arrived here by means of the query message, so release the vnode is necessary
|
||||
qKillQuery((qinfo_t) killQueryMsg->qhandle, vnodeRelease, pVnode);
|
||||
vnodeRelease(pVnode);
|
||||
|
||||
return TSDB_CODE_TSC_QUERY_CANCELLED; // todo change the error code
|
||||
}
|
||||
|
||||
|
@ -106,7 +109,17 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
|||
pRet->len = sizeof(SQueryTableRsp);
|
||||
pRet->rsp = pRsp;
|
||||
|
||||
vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, pQInfo, pVnode->vgId);
|
||||
// current connect is broken
|
||||
if (vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, pQInfo, pVnode->vgId) != TSDB_CODE_SUCCESS) {
|
||||
vError("vgId:%d, QInfo:%p, dnode query discarded since link is broken, %p", pVnode->vgId, pQInfo, pReadMsg->rpcMsg.handle);
|
||||
pRsp->code = TSDB_CODE_RPC_NETWORK_UNAVAIL;
|
||||
|
||||
//NOTE: there two refcount, needs to kill twice, todo refactor
|
||||
qKillQuery(pQInfo, vnodeRelease, pVnode);
|
||||
qKillQuery(pQInfo, vnodeRelease, pVnode);
|
||||
|
||||
return pRsp->code;
|
||||
}
|
||||
|
||||
vTrace("vgId:%d, QInfo:%p, dnode query msg disposed", pVnode->vgId, pQInfo);
|
||||
} else {
|
||||
|
@ -118,7 +131,7 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
|||
|
||||
if (pQInfo != NULL) {
|
||||
vTrace("vgId:%d, QInfo:%p, do qTableQuery", pVnode->vgId, pQInfo);
|
||||
qTableQuery(pQInfo); // do execute query
|
||||
qTableQuery(pQInfo, vnodeRelease, pVnode); // do execute query
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -136,7 +149,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
|||
|
||||
if (pRetrieve->free == 1) {
|
||||
vTrace("vgId:%d, QInfo:%p, retrieve msg received to kill query and free qhandle", pVnode->vgId, pQInfo);
|
||||
int32_t ret = qKillQuery(pQInfo);
|
||||
int32_t ret = qKillQuery(pQInfo, vnodeRelease, pVnode);
|
||||
|
||||
pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp));
|
||||
pRet->len = sizeof(SRetrieveTableRsp);
|
||||
|
@ -165,8 +178,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) {
|
|||
pRet->qhandle = pQInfo;
|
||||
code = TSDB_CODE_VND_ACTION_NEED_REPROCESSED;
|
||||
} else { // no further execution invoked, release the ref to vnode
|
||||
qDestroyQueryInfo(pQInfo);
|
||||
vnodeRelease(pVnode);
|
||||
qDestroyQueryInfo(pQInfo, vnodeRelease, pVnode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
4. pip install ../src/connector/python/linux/python2 ; pip3 install
|
||||
../src/connector/python/linux/python3
|
||||
|
||||
5. pip install numpy; pip3 install numpy
|
||||
|
||||
> Note: Both Python2 and Python3 are currently supported by the Python test
|
||||
> framework. Since Python2 is no longer officially supported by Python Software
|
||||
> Foundation since January 1, 2020, it is recommended that subsequent test case
|
||||
|
|
|
@ -13,83 +13,13 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// TAOS standard API example. The same syntax as MySQL, but only a subet
|
||||
// TAOS standard API example. The same syntax as MySQL, but only a subset
|
||||
// to compile: gcc -o demo demo.c -ltaos
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <taos.h> // TAOS header file
|
||||
#include <sys/time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static int32_t doQuery(TAOS* taos, const char* sql) {
|
||||
struct timeval t1 = {0};
|
||||
gettimeofday(&t1, NULL);
|
||||
|
||||
TAOS_RES* res = taos_query(taos, sql);
|
||||
if (taos_errno(res) != 0) {
|
||||
printf("failed to execute query, reason:%s\n", taos_errstr(taos));
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAOS_ROW row = NULL;
|
||||
char buf[512] = {0};
|
||||
|
||||
int32_t numOfFields = taos_num_fields(res);
|
||||
TAOS_FIELD* pFields = taos_fetch_fields(res);
|
||||
|
||||
int32_t i = 0;
|
||||
while((row = taos_fetch_row(res)) != NULL) {
|
||||
taos_print_row(buf, row, pFields, numOfFields);
|
||||
printf("%d:%s\n", ++i, buf);
|
||||
memset(buf, 0, 512);
|
||||
}
|
||||
|
||||
taos_free_result(res);
|
||||
|
||||
struct timeval t2 = {0};
|
||||
gettimeofday(&t2, NULL);
|
||||
|
||||
printf("elapsed time:%"PRId64 " ms\n", ((t2.tv_sec*1000000 + t2.tv_usec) - (t1.tv_sec*1000000 + t1.tv_usec))/1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* oneLoader(void* param) {
|
||||
TAOS* conn = (TAOS*) param;
|
||||
|
||||
for(int32_t i = 0; i < 20000; ++i) {
|
||||
// doQuery(conn, "show databases");
|
||||
doQuery(conn, "use test");
|
||||
// doQuery(conn, "describe t12");
|
||||
// doQuery(conn, "show tables");
|
||||
// doQuery(conn, "create table if not exists abc (ts timestamp, k int)");
|
||||
// doQuery(conn, "select * from t12");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static __attribute__((unused)) void multiThreadTest(int32_t numOfThreads, void* conn) {
|
||||
pthread_attr_t thattr;
|
||||
pthread_attr_init(&thattr);
|
||||
pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
pthread_t* threadId = (pthread_t*)malloc(sizeof(pthread_t)*(uint32_t)numOfThreads);
|
||||
|
||||
for (int i = 0; i < numOfThreads; ++i) {
|
||||
pthread_create(&threadId[i], NULL, oneLoader, conn);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfThreads; ++i) {
|
||||
pthread_join(threadId[i], NULL);
|
||||
}
|
||||
|
||||
free(threadId);
|
||||
pthread_attr_destroy(&thattr);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
TAOS * taos;
|
||||
|
@ -102,32 +32,16 @@ int main(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
taos_options(TSDB_OPTION_CONFIGDIR, "~/sec/cfg");
|
||||
|
||||
// init TAOS
|
||||
taos_init();
|
||||
|
||||
taos = taos_connect(argv[1], "root", "taosdata", NULL, 0);
|
||||
if (taos == NULL) {
|
||||
printf("failed to connect to server, reason:%s\n", taos_errstr(NULL));
|
||||
printf("failed to connect to server, reason:%s\n", taos_errstr(taos));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("success to connect to server\n");
|
||||
// doQuery(taos, "select c1,count(*) from group_db0.group_mt0 where c1<8 group by c1");
|
||||
// doQuery(taos, "select * from test.m1");
|
||||
|
||||
// multiThreadTest(1, taos);
|
||||
// doQuery(taos, "select tbname from test.m1");
|
||||
// doQuery(taos, "select max(c1), min(c2), sum(c3), avg(c4), first(c7), last(c8), first(c9) from lm2_db0.lm2_stb0 where ts >= 1537146000000 and ts <= 1543145400000 and tbname in ('lm2_tb0') interval(1s) group by t1");
|
||||
// doQuery(taos, "select max(c1), min(c2), sum(c3), avg(c4), first(c7), last(c8), first(c9) from lm2_db0.lm2_stb0 where ts >= 1537146000000 and ts <= 1543145400000 and tbname in ('lm2_tb0', 'lm2_tb1', 'lm2_tb2') interval(1s)");
|
||||
for(int32_t i = 0; i < 200; ++i) {
|
||||
doQuery(taos, "select * from lm2_db0.lm2_stb0");
|
||||
}
|
||||
// doQuery(taos, "create table t1(ts timestamp, k binary(12), f nchar(2))");
|
||||
|
||||
taos_close(taos);
|
||||
return 0;
|
||||
|
||||
taos_query(taos, "drop database demo");
|
||||
if (taos_query(taos, "create database demo") != 0) {
|
||||
|
@ -136,10 +50,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
printf("success to create database\n");
|
||||
|
||||
|
||||
taos_query(taos, "use demo");
|
||||
|
||||
|
||||
// create table
|
||||
if (taos_query(taos, "create table m1 (ts timestamp, speed int)") != 0) {
|
||||
printf("failed to create table, reason:%s\n", taos_errstr(taos));
|
||||
|
@ -147,11 +59,9 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
printf("success to create table\n");
|
||||
|
||||
|
||||
// sleep for one second to make sure table is created on data node
|
||||
// taosMsleep(1000);
|
||||
|
||||
|
||||
// insert 10 records
|
||||
int i = 0;
|
||||
for (i = 0; i < 10; ++i) {
|
||||
|
@ -163,28 +73,20 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
printf("success to insert rows, total %d rows\n", i);
|
||||
|
||||
|
||||
// query the records
|
||||
sprintf(qstr, "SELECT * FROM m1");
|
||||
if (taos_query(taos, qstr) != 0) {
|
||||
printf("failed to select, reason:%s\n", taos_errstr(taos));
|
||||
result = taos_query(taos, qstr);
|
||||
if (result == NULL || taos_errno(result) != 0) {
|
||||
printf("failed to select, reason:%s\n", taos_errstr(result));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
printf("failed to get result, reason:%s\n", taos_errstr(taos));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// TAOS_ROW row;
|
||||
|
||||
TAOS_ROW row;
|
||||
int rows = 0;
|
||||
int num_fields = taos_field_count(taos);
|
||||
TAOS_FIELD *fields = taos_fetch_fields(result);
|
||||
char temp[256];
|
||||
|
||||
|
||||
printf("select * from table, result:\n");
|
||||
// fetch the records row by row
|
||||
while ((row = taos_fetch_row(result))) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue