diff --git a/cmake/install.inc b/cmake/install.inc index e9ad240a793b9736edbe5769c6af12276e13a1a6..7ea2ba8da0af79c15378cda956a330b357804c5a 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -32,7 +32,7 @@ ELSEIF (TD_WINDOWS) #INSTALL(TARGETS taos RUNTIME DESTINATION driver) #INSTALL(TARGETS shell RUNTIME DESTINATION .) IF (TD_MVN_INSTALLED) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.34-dist.jar DESTINATION connector/jdbc) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.35-dist.jar DESTINATION connector/jdbc) ENDIF () ELSEIF (TD_DARWIN) SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh") diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index df0cf15fe00eda5bc8e6004e2794733537b8aee0..cf53977103c3a9760286e70447d826f7026d7e53 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -10,6 +10,7 @@ AUX_SOURCE_DIRECTORY(src SRC) IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) # set the static lib name ADD_LIBRARY(taos_static STATIC ${SRC}) @@ -21,7 +22,7 @@ IF (TD_LINUX) ADD_LIBRARY(taos SHARED ${SRC}) TARGET_LINK_LIBRARIES(taos common query trpc tutil pthread m rt cJson) IF (TD_LINUX_64) - TARGET_LINK_LIBRARIES(taos lua) + TARGET_LINK_LIBRARIES(taos lua cJson) ENDIF () SET_TARGET_PROPERTIES(taos PROPERTIES CLEAN_DIRECT_OUTPUT 1) @@ -36,6 +37,7 @@ IF (TD_LINUX) ELSEIF (TD_DARWIN) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) # set the static lib name ADD_LIBRARY(taos_static STATIC ${SRC}) @@ -59,6 +61,7 @@ ELSEIF (TD_DARWIN) ELSEIF (TD_WINDOWS) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/windows) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/windows/win32) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) CONFIGURE_FILE("${TD_COMMUNITY_DIR}/src/client/src/taos.rc.in" "${TD_COMMUNITY_DIR}/src/client/src/taos.rc") @@ -75,6 +78,7 @@ ELSEIF (TD_WINDOWS) ELSEIF (TD_DARWIN) SET(CMAKE_MACOSX_RPATH 1) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) ADD_LIBRARY(taos_static STATIC ${SRC}) TARGET_LINK_LIBRARIES(taos_static query trpc tutil pthread m lua cJson) diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h index 7181c658ddcdfde3efe7df3c0784c20f18bd4c03..61ae5082f31cd9129a3cec1eaa1e0552ada7993b 100644 --- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h +++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h @@ -41,6 +41,14 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions (JNIEnv *, jclass, jint, jstring); +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: setConfigImp + * Signature: (Ljava/lang/String;)Lcom/taosdata/jdbc/TSDBException; + */ +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp + (JNIEnv *, jclass, jstring); + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: getTsCharset diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index 506c8d64b9f4213713656ecd08612a103e0b1b2d..925b7d75db9f88c9905270aa365c60990e9f45a3 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -200,6 +200,64 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *e jniDebug("jni initialized successfully, config directory: %s", configDir); } +JNIEXPORT jobject createTSDBException(JNIEnv *env, int code, char *msg) { + // find class + jclass exception_clazz = (*env)->FindClass(env, "com/taosdata/jdbc/TSDBException"); + // find methods + jmethodID init_method = (*env)->GetMethodID(env, exception_clazz, "", "()V"); + jmethodID setCode_method = (*env)->GetMethodID(env, exception_clazz, "setCode", "(I)V"); + jmethodID setMessage_method = (*env)->GetMethodID(env, exception_clazz, "setMessage", "(Ljava/lang/String;)V"); + // new exception + jobject exception_obj = (*env)->NewObject(env, exception_clazz, init_method); + // set code + (*env)->CallVoidMethod(env, exception_obj, setCode_method, code); + // set message + jstring message = (*env)->NewStringUTF(env, msg); + (*env)->CallVoidMethod(env, exception_obj, setMessage_method, message); + + return exception_obj; +} + +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: setConfigImp + * Signature: (Ljava/lang/String;)Lcom/taosdata/jdbc/TSDBException; + */ +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setConfigImp(JNIEnv *env, jclass jobj, + jstring config) { + /* + if (config == NULL) { + jniDebug("config value is null"); + return -1; + } + + const char *cfg = (*env)->GetStringUTFChars(env, config, NULL); + if (!cfg) { + return -1; + } + return 0; + */ + + if (config == NULL) { + char *msg = "config value is null"; + jniDebug("config value is null"); + return createTSDBException(env, -1, msg); + } + + const char *cfg = (*env)->GetStringUTFChars(env, config, NULL); + if (!cfg) { + char *msg = "config value is null"; + jniDebug("config value is null"); + return createTSDBException(env, -1, msg); + } + + setConfRet result = taos_set_config(cfg); + int code = result.retCode; + char * msg = result.retMsg; + + return createTSDBException(env, code, msg); +} + JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *env, jobject jobj, jint optionIndex, jstring optionValue) { if (optionValue == NULL) { diff --git a/src/client/src/taos.def b/src/client/src/taos.def index 7d3b8e80c20226c4a509c95ab5728f41852110f5..f1ff17a491e795120494b00f59a800aa6bbc889a 100644 --- a/src/client/src/taos.def +++ b/src/client/src/taos.def @@ -2,6 +2,7 @@ EXPORTS taos_init taos_cleanup taos_options +taos_set_config taos_connect taos_connect_auth taos_close diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index 8af340030cccee1431a82eb88344642011f2e019..b3b83db80a70c19f79d1cd6a732d729817436dd3 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -50,6 +50,7 @@ int tscLogFileNum = 10; static pthread_mutex_t rpcObjMutex; // mutex to protect open the rpc obj concurrently static pthread_once_t tscinit = PTHREAD_ONCE_INIT; +static pthread_mutex_t setConfMutex = PTHREAD_MUTEX_INITIALIZER; // pthread_once can not return result code, so result code is set to a global variable. static volatile int tscInitRes = 0; @@ -249,6 +250,7 @@ void taos_cleanup(void) { pthread_mutex_destroy(&rpcObjMutex); } + pthread_mutex_destroy(&setConfMutex); taosCacheCleanup(tscVgroupListBuf); tscVgroupListBuf = NULL; @@ -437,3 +439,66 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) { atomic_store_32(&lock, 0); return ret; } + +#include "cJSON.h" +static setConfRet taos_set_config_imp(const char *config){ + setConfRet ret = {SET_CONF_RET_SUCC, {0}}; + static bool setConfFlag = false; + if (setConfFlag) { + ret.retCode = SET_CONF_RET_ERR_ONLY_ONCE; + strcpy(ret.retMsg, "configuration can only set once"); + return ret; + } + taosInitGlobalCfg(); + cJSON *root = cJSON_Parse(config); + if (root == NULL){ + ret.retCode = SET_CONF_RET_ERR_JSON_PARSE; + strcpy(ret.retMsg, "parse json error"); + return ret; + } + + int size = cJSON_GetArraySize(root); + if(!cJSON_IsObject(root) || size == 0) { + ret.retCode = SET_CONF_RET_ERR_JSON_INVALID; + strcpy(ret.retMsg, "json content is invalid, must be not empty object"); + return ret; + } + + if(size >= 1000) { + ret.retCode = SET_CONF_RET_ERR_TOO_LONG; + strcpy(ret.retMsg, "json object size is too long"); + return ret; + } + + for(int i = 0; i < size; i++){ + cJSON *item = cJSON_GetArrayItem(root, i); + if(!item) { + ret.retCode = SET_CONF_RET_ERR_INNER; + strcpy(ret.retMsg, "inner error"); + return ret; + } + if(!taosReadConfigOption(item->string, item->valuestring, NULL, NULL, TAOS_CFG_CSTATUS_OPTION, TSDB_CFG_CTYPE_B_CLIENT)){ + ret.retCode = SET_CONF_RET_ERR_PART; + if (strlen(ret.retMsg) == 0){ + snprintf(ret.retMsg, RET_MSG_LENGTH, "part error|%s", item->string); + }else{ + int tmp = RET_MSG_LENGTH - 1 - (int)strlen(ret.retMsg); + size_t leftSize = tmp >= 0 ? tmp : 0; + strncat(ret.retMsg, "|", leftSize); + tmp = RET_MSG_LENGTH - 1 - (int)strlen(ret.retMsg); + leftSize = tmp >= 0 ? tmp : 0; + strncat(ret.retMsg, item->string, leftSize); + } + } + } + cJSON_Delete(root); + setConfFlag = true; + return ret; +} + +setConfRet taos_set_config(const char *config){ + pthread_mutex_lock(&setConfMutex); + setConfRet ret = taos_set_config_imp(config); + pthread_mutex_unlock(&setConfMutex); + return ret; +} diff --git a/src/client/tests/CMakeLists.txt b/src/client/tests/CMakeLists.txt index 24bfb44ac90e11e01ba99423aa68bd5a9511f746..5de18942acbb5b3ac59d2496728c500b63246fe9 100644 --- a/src/client/tests/CMakeLists.txt +++ b/src/client/tests/CMakeLists.txt @@ -17,5 +17,5 @@ IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) ADD_EXECUTABLE(cliTest ${SOURCE_LIST}) - TARGET_LINK_LIBRARIES(cliTest taos tutil common gtest pthread) + TARGET_LINK_LIBRARIES(cliTest taos cJson tutil common gtest pthread) ENDIF() diff --git a/src/client/tests/setConfigTest.cpp b/src/client/tests/setConfigTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb016715f6ad2f5311aa2d81b608c2043f86c4f0 --- /dev/null +++ b/src/client/tests/setConfigTest.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include "taos.h" +#include "tglobal.h" +#include "tconfig.h" + +/* test set config function */ +TEST(testCase, set_config_test1) { + const char *config = "{\"debugFlag\":\"131\"}"; + setConfRet ret = taos_set_config(config); + ASSERT_EQ(ret.retCode, 0); + printf("msg:%d->%s", ret.retCode, ret.retMsg); + + const char *config2 = "{\"debugFlag\":\"199\"}"; + ret = taos_set_config(config2); // not take effect + ASSERT_EQ(ret.retCode, -5); + printf("msg:%d->%s", ret.retCode, ret.retMsg); + + bool readResult = taosReadGlobalCfg(); // load file config, debugFlag not take effect + ASSERT_TRUE(readResult); + int32_t checkResult = taosCheckGlobalCfg(); + ASSERT_EQ(checkResult, 0); + + SGlobalCfg *cfg = taosGetConfigOption("debugFlag"); + ASSERT_EQ(cfg->cfgStatus, TAOS_CFG_CSTATUS_OPTION); + int32_t result = *(int32_t *)cfg->ptr; + ASSERT_EQ(result, 131); +} + +TEST(testCase, set_config_test2) { + const char *config = "{\"numOfCommitThreads\":\"10\"}"; + taos_set_config(config); + + bool readResult = taosReadGlobalCfg(); // load file config, debugFlag not take effect + ASSERT_TRUE(readResult); + int32_t checkResult = taosCheckGlobalCfg(); + ASSERT_EQ(checkResult, 0); + + SGlobalCfg *cfg = taosGetConfigOption("numOfCommitThreads"); + int32_t result = *(int32_t*)cfg->ptr; + ASSERT_NE(result, 10); // numOfCommitThreads not type of TSDB_CFG_CTYPE_B_CLIENT +} + +TEST(testCase, set_config_test3) { + const char *config = "{\"numOfCoitThreads\":\"10\", \"esdfa\":\"10\"}"; + setConfRet ret = taos_set_config(config); + ASSERT_EQ(ret.retCode, -1); + printf("msg:%d->%s", ret.retCode, ret.retMsg); +} + +TEST(testCase, set_config_test4) { + const char *config = "{null}"; + setConfRet ret = taos_set_config(config); + ASSERT_EQ(ret.retCode, -4); + printf("msg:%d->%s", ret.retCode, ret.retMsg); +} + +TEST(testCase, set_config_test5) { + const char *config = "\"ddd\""; + setConfRet ret = taos_set_config(config); + ASSERT_EQ(ret.retCode, -3); + printf("msg:%d->%s", ret.retCode, ret.retMsg); +} + +TEST(testCase, set_config_test6) { + const char *config = "{\"numOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitThreadsnumOfCoitT3333dd\":\"10\", \"esdfa\":\"10\"}"; + setConfRet ret = taos_set_config(config); + ASSERT_EQ(ret.retCode, -1); + printf("msg:%d->%s", ret.retCode, ret.retMsg); +} diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt index e432dac1cea593b371a173f334e5313236091ab3..1e5cede714820f29defe3c6b458b2daf467bc4d2 100644 --- a/src/connector/jdbc/CMakeLists.txt +++ b/src/connector/jdbc/CMakeLists.txt @@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED) ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME} POST_BUILD COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.34-dist.jar ${LIBRARY_OUTPUT_PATH} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.35-dist.jar ${LIBRARY_OUTPUT_PATH} COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml COMMENT "build jdbc driver") ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME}) diff --git a/src/connector/jdbc/deploy-pom.xml b/src/connector/jdbc/deploy-pom.xml index ef57198e78d2268faba526d5506b0dc384f5766f..7caf46848d18c4491cdea1ab50df31d8d2d26daf 100755 --- a/src/connector/jdbc/deploy-pom.xml +++ b/src/connector/jdbc/deploy-pom.xml @@ -5,7 +5,7 @@ com.taosdata.jdbc taos-jdbcdriver - 2.0.34 + 2.0.35 jar JDBCDriver diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml index 256fa614e0bd0a88e0c676a3ae13c9c177eb5215..810a85f8a33b3f244dab81e349b9df786ec50c21 100644 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.taosdata.jdbc taos-jdbcdriver - 2.0.34 + 2.0.35 jar JDBCDriver https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java index 521a88b128ff930510bf00cdcb6a12cbc3211742..307451e014c59c1c3419f1a9daff4f89e8b90d46 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBDriver.java @@ -118,9 +118,6 @@ public class TSDBDriver extends AbstractDriver { } public Connection connect(String url, Properties info) throws SQLException { - if (url == null) - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_URL_NOT_SET); - if (!acceptsURL(url)) return null; @@ -135,8 +132,7 @@ public class TSDBDriver extends AbstractDriver { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED); try { - TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE), - (String) props.get(PROPERTY_KEY_CHARSET), (String) props.get(PROPERTY_KEY_TIME_ZONE)); + TSDBJNIConnector.init(props); return new TSDBConnection(props, this.dbMetaData); } catch (SQLWarning sqlWarning) { sqlWarning.printStackTrace(); @@ -205,6 +201,7 @@ public class TSDBDriver extends AbstractDriver { String dbProductName = url.substring(0, beginningOfSlashes); dbProductName = dbProductName.substring(dbProductName.indexOf(":") + 1); dbProductName = dbProductName.substring(0, dbProductName.indexOf(":")); + urlProps.setProperty(TSDBDriver.PROPERTY_KEY_PRODUCT_NAME, dbProductName); // parse database name url = url.substring(beginningOfSlashes + 2); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java index bdb3ea410005cadd865de1d9e080dd5b9f20834f..0970148b1dfb6c6c1fb85330e312bf2c8168b3c7 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBError.java @@ -35,6 +35,7 @@ public class TSDBError { TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, "user is required"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, "password is required"); + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_INVALID_JSON_FORMAT, "invalid json format"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error"); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java index 2207db6f9379595e68b8ed00ea8f7298ca3b45ad..0f4427fa20e272917df0327552efd1a80cd56b4d 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java @@ -31,6 +31,7 @@ public class TSDBErrorNumbers { public static final int ERROR_RESTFul_Client_IOException = 0x2318; public static final int ERROR_USER_IS_REQUIRED = 0x2319; // user is required public static final int ERROR_PASSWORD_IS_REQUIRED = 0x231a; // password is required + public static final int ERROR_INVALID_JSON_FORMAT = 0x231b; public static final int ERROR_UNKNOWN = 0x2350; //unknown error @@ -72,6 +73,7 @@ public class TSDBErrorNumbers { errorNumbers.add(ERROR_RESTFul_Client_IOException); errorNumbers.add(ERROR_USER_IS_REQUIRED); errorNumbers.add(ERROR_PASSWORD_IS_REQUIRED); + errorNumbers.add(ERROR_INVALID_JSON_FORMAT); errorNumbers.add(ERROR_RESTFul_Client_Protocol_Exception); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBException.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBException.java new file mode 100644 index 0000000000000000000000000000000000000000..31299a1c6f37a8b75521a65e7de09f5162558dd6 --- /dev/null +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBException.java @@ -0,0 +1,22 @@ +package com.taosdata.jdbc; + +public class TSDBException { + private int code; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} \ No newline at end of file diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index 4a9e80ba53b096f057840eab67e61418332dbf81..aaada2e78ec284f4019b29465a38db109cf9d80a 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -16,18 +16,21 @@ */ package com.taosdata.jdbc; +import com.alibaba.fastjson.JSONObject; import com.taosdata.jdbc.utils.TaosInfo; import java.nio.ByteBuffer; import java.sql.SQLException; import java.sql.SQLWarning; import java.util.List; +import java.util.Properties; /** * JNI connector */ public class TSDBJNIConnector { - private static volatile Boolean isInitialized = false; + private static final Object LOCK = new Object(); + private static volatile boolean isInitialized; private final TaosInfo taosInfo = TaosInfo.getInstance(); private long taos = TSDBConstants.JNI_NULL_POINTER; // Connection pointer used in C @@ -38,24 +41,27 @@ public class TSDBJNIConnector { System.loadLibrary("taos"); } - public boolean isClosed() { - return this.taos == TSDBConstants.JNI_NULL_POINTER; - } + public static void init(Properties props) throws SQLWarning { + synchronized (LOCK) { + if (!isInitialized) { - public boolean isResultsetClosed() { - return this.isResultsetClosed; - } + JSONObject configJSON = new JSONObject(); + for (String key : props.stringPropertyNames()) { + configJSON.put(key, props.getProperty(key)); + } + setConfigImp(configJSON.toJSONString()); - public static void init(String configDir, String locale, String charset, String timezone) throws SQLWarning { - synchronized (isInitialized) { - if (!isInitialized) { - initImp(configDir); + initImp(props.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, null)); + + String locale = props.getProperty(TSDBDriver.PROPERTY_KEY_LOCALE); if (setOptions(0, locale) < 0) { throw TSDBError.createSQLWarning("Failed to set locale: " + locale + ". System default will be used."); } + String charset = props.getProperty(TSDBDriver.PROPERTY_KEY_CHARSET); if (setOptions(1, charset) < 0) { throw TSDBError.createSQLWarning("Failed to set charset: " + charset + ". System default will be used."); } + String timezone = props.getProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE); if (setOptions(2, timezone) < 0) { throw TSDBError.createSQLWarning("Failed to set timezone: " + timezone + ". System default will be used."); } @@ -65,11 +71,13 @@ public class TSDBJNIConnector { } } - public static native void initImp(String configDir); + private static native void initImp(String configDir); + + private static native int setOptions(int optionIndex, String optionValue); - public static native int setOptions(int optionIndex, String optionValue); + private static native String getTsCharset(); - public static native String getTsCharset(); + private static native TSDBException setConfigImp(String config); public boolean connect(String host, int port, String dbName, String user, String password) throws SQLException { if (this.taos != TSDBConstants.JNI_NULL_POINTER) { @@ -159,6 +167,14 @@ public class TSDBJNIConnector { private native long isUpdateQueryImp(long connection, long pSql); + public boolean isClosed() { + return this.taos == TSDBConstants.JNI_NULL_POINTER; + } + + public boolean isResultsetClosed() { + return this.isResultsetClosed; + } + /** * Free result set operation from C to release result set pointer by JNI */ @@ -351,4 +367,6 @@ public class TSDBJNIConnector { } private native int insertLinesImp(String[] lines, long conn); + + } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SetConfigurationInJNITest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SetConfigurationInJNITest.java new file mode 100644 index 0000000000000000000000000000000000000000..6a983cd5bdd6d886dcac01f6085c70eade4f7cf5 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SetConfigurationInJNITest.java @@ -0,0 +1,249 @@ +package com.taosdata.jdbc; + +import org.junit.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + + +public class SetConfigurationInJNITest { + + private String host = "127.0.0.1"; + private String dbname = "test_set_config"; + + @Test + public void setConfigInUrl() { + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata&debugFlag=143&rpcTimer=500"); + Statement stmt = conn.createStatement(); + + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void setConfigInProperties() { + try { + Properties props = new Properties(); + props.setProperty("debugFlag", "143"); + props.setProperty("r pcTimer", "500"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + //test case1:set debugFlag=135 + //expect:debugFlag:135 + //result:pass + public void setConfigfordebugFlag() { + try { + Properties props = new Properties(); + //set debugFlag=135 + props.setProperty("debugFlag", "135"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + //test case2:set debugFlag=abc (wrong type) + //expect:debugFlag:135 + //result:pass + public void setConfigforwrongtype() { + try { + Properties props = new Properties(); + //set debugFlag=135 + props.setProperty("debugFlag", "abc"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + //test case3:set rpcTimer=0 (smaller than the boundary conditions) + //expect:rpcTimer:300 + //result:pass + public void setConfigrpcTimer() { + try { + Properties props = new Properties(); + //set rpcTimer=0 + props.setProperty("rpcTimer", "0"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + //test case4:set rpcMaxTime=10000 (bigger than the boundary conditions) + //expect:rpcMaxTime:600 + //result:pass + public void setConfigforrpcMaxTime() { + try { + Properties props = new Properties(); + //set rpcMaxTime=10000 + props.setProperty("rpcMaxTime", "10000"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + //test case5:set numOfThreadsPerCore=aaa (wrong type) + //expect:numOfThreadsPerCore:1.0 + //result:pass + public void setConfigfornumOfThreadsPerCore() { + try { + Properties props = new Properties(); + //set numOfThreadsPerCore=aaa + props.setProperty("numOfThreadsPerCore", "aaa"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + //test case6:set numOfThreadsPerCore=100000 (bigger than the boundary conditions) + //expect:numOfThreadsPerCore:1.0 + //result:pass + public void setConfignumOfThreadsPerCore() { + try { + Properties props = new Properties(); + //set numOfThreadsPerCore=100000 + props.setProperty("numOfThreadsPerCore", "100000"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + // test case7:set both true and wrong config(debugFlag=0,rpcDebugFlag=143,cDebugFlag=143,rpcTimer=100000) + // expect:rpcDebugFlag:143,cDebugFlag:143,rpcTimer:300 + // result:pass + public void setConfigformaxTmrCtrl() { + try { + Properties props = new Properties(); + props.setProperty("debugFlag", "0"); + props.setProperty("rpcDebugFlag", "143"); + props.setProperty("cDebugFlag", "143"); + props.setProperty("rpcTimer", "100000"); + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata", props); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + @Test + //test case 8:use url to set with wrong type(debugFlag=abc,rpcTimer=abc) + //expect:default value + //result:pass + public void setConfigInUrlwithwrongtype() { + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root&password=taosdata&debugFlag=abc&rpcTimer=abc"); + Statement stmt = conn.createStatement(); + + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("drop database if exists " + dbname); + + stmt.close(); + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java index 88ff5d3a811e17aaabbeb0a451fbff010307ab6d..8be6ae6b1c566abcd7ec398e7df3f5308e29e1b1 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBJNIConnectorTest.java @@ -5,9 +5,9 @@ import org.junit.Test; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.sql.SQLException; -import java.sql.SQLWarning; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -19,25 +19,25 @@ public class TSDBJNIConnectorTest { @Test public void test() { try { - try { //change sleepSeconds when debugging with attach to process to find PID int sleepSeconds = -1; - if (sleepSeconds>0) { + if (sleepSeconds > 0) { RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); String jvmName = runtimeBean.getName(); long pid = Long.valueOf(jvmName.split("@")[0]); System.out.println("JVM PID = " + pid); - Thread.sleep(sleepSeconds*1000); + Thread.sleep(sleepSeconds * 1000); } - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); } // init - TSDBJNIConnector.init("/etc/taos", null, null, null); + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "/etc/taos"); + TSDBJNIConnector.init(properties); // connect TSDBJNIConnector connector = new TSDBJNIConnector(); @@ -45,12 +45,12 @@ public class TSDBJNIConnectorTest { // setup String setupSqlStrs[] = {"create database if not exists d precision \"us\"", - "create table if not exists d.t(ts timestamp, f int)", - "create database if not exists d2", - "create table if not exists d2.t2(ts timestamp, f int)", - "insert into d.t values(now+100s, 100)", - "insert into d2.t2 values(now+200s, 200)" - }; + "create table if not exists d.t(ts timestamp, f int)", + "create database if not exists d2", + "create table if not exists d2.t2(ts timestamp, f int)", + "insert into d.t values(now+100s, 100)", + "insert into d2.t2 values(now+200s, 200)" + }; for (String setupSqlStr : setupSqlStrs) { long setupSql = connector.executeQuery(setupSqlStr); @@ -115,15 +115,13 @@ public class TSDBJNIConnectorTest { } // close statement connector.executeQuery("use d"); - String[] lines = new String[] {"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", - "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns"}; + String[] lines = new String[]{"st,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", + "st,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns"}; connector.insertLines(lines); // close connection connector.closeConnection(); - } catch (SQLWarning throwables) { - throwables.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } @@ -140,11 +138,7 @@ public class TSDBJNIConnectorTest { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL); } else if (code == TSDBConstants.JNI_NUM_OF_FIELDS_0) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0); - } else if (code == TSDBConstants.JNI_FETCH_END) { - return false; - } else { - return true; - } + } else return code != TSDBConstants.JNI_FETCH_END; } } diff --git a/src/inc/taos.h b/src/inc/taos.h index edb1552b811a2ff4b8c78c19523cc6f2ad82ba74..be5123797069696ffad817c0db7bc2c8c03e9606 100644 --- a/src/inc/taos.h +++ b/src/inc/taos.h @@ -62,6 +62,22 @@ typedef struct taosField { int16_t bytes; } TAOS_FIELD; +typedef enum { + SET_CONF_RET_SUCC = 0, + SET_CONF_RET_ERR_PART = -1, + SET_CONF_RET_ERR_INNER = -2, + SET_CONF_RET_ERR_JSON_INVALID = -3, + SET_CONF_RET_ERR_JSON_PARSE = -4, + SET_CONF_RET_ERR_ONLY_ONCE = -5, + SET_CONF_RET_ERR_TOO_LONG = -6 +} SET_CONF_RET_CODE; + +#define RET_MSG_LENGTH 1024 +typedef struct setConfRet { + SET_CONF_RET_CODE retCode; + char retMsg[RET_MSG_LENGTH]; +} setConfRet; + #ifdef _TD_GO_DLL_ #define DLL_EXPORT __declspec(dllexport) #else @@ -71,6 +87,7 @@ typedef struct taosField { DLL_EXPORT int taos_init(); DLL_EXPORT void taos_cleanup(void); DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...); +DLL_EXPORT setConfRet taos_set_config(const char *config); DLL_EXPORT TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port); DLL_EXPORT TAOS *taos_connect_auth(const char *ip, const char *user, const char *auth, const char *db, uint16_t port); DLL_EXPORT void taos_close(TAOS *taos); diff --git a/src/kit/shell/CMakeLists.txt b/src/kit/shell/CMakeLists.txt index bf2bbca14d25aff3b3717c7b9785f1dc470a013a..bca1b72a1bc2c1f5b3da311baad38cd1d55ddaed 100644 --- a/src/kit/shell/CMakeLists.txt +++ b/src/kit/shell/CMakeLists.txt @@ -19,9 +19,9 @@ ELSE () ENDIF () IF (TD_SOMODE_STATIC) - TARGET_LINK_LIBRARIES(shell taos_static lua ${LINK_JEMALLOC}) + TARGET_LINK_LIBRARIES(shell taos_static cJson lua ${LINK_JEMALLOC}) ELSE () - TARGET_LINK_LIBRARIES(shell taos lua ${LINK_JEMALLOC}) + TARGET_LINK_LIBRARIES(shell taos cJson lua ${LINK_JEMALLOC}) ENDIF () SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) @@ -30,7 +30,7 @@ ELSEIF (TD_WINDOWS) LIST(APPEND SRC ./src/shellMain.c) LIST(APPEND SRC ./src/shellWindows.c) ADD_EXECUTABLE(shell ${SRC}) - TARGET_LINK_LIBRARIES(shell taos_static) + TARGET_LINK_LIBRARIES(shell taos_static cJson) IF (TD_POWER) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME power) @@ -46,7 +46,7 @@ ELSEIF (TD_DARWIN) LIST(APPEND SRC ./src/shellCheck.c) ADD_EXECUTABLE(shell ${SRC}) # linking with dylib - TARGET_LINK_LIBRARIES(shell taos) + TARGET_LINK_LIBRARIES(shell taos cJson) # linking taos statically # TARGET_LINK_LIBRARIES(shell taos_static) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) diff --git a/src/kit/taosdump/CMakeLists.txt b/src/kit/taosdump/CMakeLists.txt index 51f4748eab462c8e883e83cd5923f38dd7fb9b5a..c3c914e96fc096f59aa701d3496455c754356aa8 100644 --- a/src/kit/taosdump/CMakeLists.txt +++ b/src/kit/taosdump/CMakeLists.txt @@ -9,9 +9,9 @@ AUX_SOURCE_DIRECTORY(. SRC) IF (TD_LINUX) ADD_EXECUTABLE(taosdump ${SRC}) IF (TD_SOMODE_STATIC) - TARGET_LINK_LIBRARIES(taosdump taos_static) + TARGET_LINK_LIBRARIES(taosdump taos_static cJson) ELSE () - TARGET_LINK_LIBRARIES(taosdump taos) + TARGET_LINK_LIBRARIES(taosdump taos cJson) ENDIF () ENDIF () @@ -19,8 +19,8 @@ IF (TD_DARWIN) # missing for macosx # ADD_EXECUTABLE(taosdump ${SRC}) # IF (TD_SOMODE_STATIC) - # TARGET_LINK_LIBRARIES(taosdump taos_static) + # TARGET_LINK_LIBRARIES(taosdump taos_static cJson) # ELSE () - # TARGET_LINK_LIBRARIES(taosdump taos) + # TARGET_LINK_LIBRARIES(taosdump taos cJson) # ENDIF () ENDIF () diff --git a/src/os/tests/CMakeLists.txt b/src/os/tests/CMakeLists.txt index 3c477641899994bf34237e93122c3d83f0365fad..9ec5076b7201b2d5ed9b2b6eb682eea7d6a83827 100644 --- a/src/os/tests/CMakeLists.txt +++ b/src/os/tests/CMakeLists.txt @@ -17,5 +17,5 @@ IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) ADD_EXECUTABLE(osTest ${SOURCE_LIST}) - TARGET_LINK_LIBRARIES(osTest taos os tutil common gtest pthread) + TARGET_LINK_LIBRARIES(osTest taos os cJson tutil common gtest pthread) ENDIF() diff --git a/src/query/tests/CMakeLists.txt b/src/query/tests/CMakeLists.txt index 349d511f1570e3df835494ebd4e3e86d7795c873..8c4b9c2e6a2e9a5f6835baf411ecc94e6889fcbe 100644 --- a/src/query/tests/CMakeLists.txt +++ b/src/query/tests/CMakeLists.txt @@ -18,7 +18,7 @@ IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR)) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) ADD_EXECUTABLE(queryTest ${SOURCE_LIST}) - TARGET_LINK_LIBRARIES(queryTest taos query gtest pthread) + TARGET_LINK_LIBRARIES(queryTest taos cJson query gtest pthread) ENDIF() SET_SOURCE_FILES_PROPERTIES(./astTest.cpp PROPERTIES COMPILE_FLAGS -w) diff --git a/src/util/inc/tconfig.h b/src/util/inc/tconfig.h index cf8977ce06c898fcdee8d21eedf5ed8d0f47f263..2c632d4a17f5394dc28df72414948855b89bc001 100644 --- a/src/util/inc/tconfig.h +++ b/src/util/inc/tconfig.h @@ -89,6 +89,7 @@ void taosDumpGlobalCfg(); void taosInitConfigOption(SGlobalCfg cfg); SGlobalCfg * taosGetConfigOption(const char *option); +bool taosReadConfigOption(const char *option, char *value, char *value2, char *value3, int8_t cfgStatus, int8_t sourceType); #ifdef __cplusplus } diff --git a/src/util/src/tconfig.c b/src/util/src/tconfig.c index 5a3dc3f9bcdee41f974e48f22b27beb2a1eb5a35..6ed9cff9fbabad06d00cb883933fefae443a1f5f 100644 --- a/src/util/src/tconfig.c +++ b/src/util/src/tconfig.c @@ -26,6 +26,11 @@ SGlobalCfg tsGlobalConfig[TSDB_CFG_MAX_NUM] = {{0}}; int32_t tsGlobalConfigNum = 0; +#define ATOI_JUDGE if ( !value && strcmp(input_value, "0") != 0) { \ + uError("atoi error, input value:%s",input_value); \ + return false; \ + } + static char *tsGlobalUnit[] = { " ", "(%)", @@ -44,12 +49,14 @@ char *tsCfgStatusStr[] = { "program argument list" }; -static void taosReadFloatConfig(SGlobalCfg *cfg, char *input_value) { +static bool taosReadFloatConfig(SGlobalCfg *cfg, char *input_value) { float value = (float)atof(input_value); + ATOI_JUDGE float *option = (float *)cfg->ptr; if (value < cfg->minValue || value > cfg->maxValue) { uError("config option:%s, input value:%s, out of range[%f, %f], use default value:%f", cfg->option, input_value, cfg->minValue, cfg->maxValue, *option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { *option = value; @@ -57,16 +64,20 @@ static void taosReadFloatConfig(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %f", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], *option); + return false; } } + return true; } -static void taosReadDoubleConfig(SGlobalCfg *cfg, char *input_value) { +static bool taosReadDoubleConfig(SGlobalCfg *cfg, char *input_value) { double value = atof(input_value); + ATOI_JUDGE double *option = (double *)cfg->ptr; if (value < cfg->minValue || value > cfg->maxValue) { uError("config option:%s, input value:%s, out of range[%f, %f], use default value:%f", cfg->option, input_value, cfg->minValue, cfg->maxValue, *option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { *option = value; @@ -74,17 +85,21 @@ static void taosReadDoubleConfig(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %f", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], *option); + return false; } } + return true; } -static void taosReadInt32Config(SGlobalCfg *cfg, char *input_value) { +static bool taosReadInt32Config(SGlobalCfg *cfg, char *input_value) { int32_t value = atoi(input_value); + ATOI_JUDGE int32_t *option = (int32_t *)cfg->ptr; if (value < cfg->minValue || value > cfg->maxValue) { uError("config option:%s, input value:%s, out of range[%f, %f], use default value:%d", cfg->option, input_value, cfg->minValue, cfg->maxValue, *option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { *option = value; @@ -92,16 +107,20 @@ static void taosReadInt32Config(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %d", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], *option); + return false; } } + return true; } -static void taosReadInt16Config(SGlobalCfg *cfg, char *input_value) { +static bool taosReadInt16Config(SGlobalCfg *cfg, char *input_value) { int32_t value = atoi(input_value); + ATOI_JUDGE int16_t *option = (int16_t *)cfg->ptr; if (value < cfg->minValue || value > cfg->maxValue) { uError("config option:%s, input value:%s, out of range[%f, %f], use default value:%d", cfg->option, input_value, cfg->minValue, cfg->maxValue, *option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { *option = (int16_t)value; @@ -109,16 +128,20 @@ static void taosReadInt16Config(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %d", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], *option); + return false; } } + return true; } -static void taosReadUInt16Config(SGlobalCfg *cfg, char *input_value) { +static bool taosReadUInt16Config(SGlobalCfg *cfg, char *input_value) { int32_t value = atoi(input_value); + ATOI_JUDGE uint16_t *option = (uint16_t *)cfg->ptr; if (value < cfg->minValue || value > cfg->maxValue) { uError("config option:%s, input value:%s, out of range[%f, %f], use default value:%d", cfg->option, input_value, cfg->minValue, cfg->maxValue, *option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { *option = (uint16_t)value; @@ -126,16 +149,20 @@ static void taosReadUInt16Config(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %d", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], *option); + return false; } } + return true; } -static void taosReadInt8Config(SGlobalCfg *cfg, char *input_value) { +static bool taosReadInt8Config(SGlobalCfg *cfg, char *input_value) { int32_t value = atoi(input_value); + ATOI_JUDGE int8_t *option = (int8_t *)cfg->ptr; if (value < cfg->minValue || value > cfg->maxValue) { uError("config option:%s, input value:%s, out of range[%f, %f], use default value:%d", cfg->option, input_value, cfg->minValue, cfg->maxValue, *option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { *option = (int8_t)value; @@ -143,8 +170,10 @@ static void taosReadInt8Config(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %d", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], *option); + return false; } } + return true; } static bool taosReadDirectoryConfig(SGlobalCfg *cfg, char *input_value) { @@ -191,12 +220,13 @@ static bool taosReadDirectoryConfig(SGlobalCfg *cfg, char *input_value) { return true; } -static void taosReadIpStrConfig(SGlobalCfg *cfg, char *input_value) { +static bool taosReadIpStrConfig(SGlobalCfg *cfg, char *input_value) { uint32_t value = taosInetAddr(input_value); char * option = (char *)cfg->ptr; if (value == INADDR_NONE) { uError("config option:%s, input value:%s, is not a valid ip address, use default value:%s", cfg->option, input_value, option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { strncpy(option, input_value, cfg->ptrLength); @@ -204,16 +234,19 @@ static void taosReadIpStrConfig(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], option); + return false; } } + return true; } -static void taosReadStringConfig(SGlobalCfg *cfg, char *input_value) { +static bool taosReadStringConfig(SGlobalCfg *cfg, char *input_value) { int length = (int) strlen(input_value); char *option = (char *)cfg->ptr; if (length <= 0 || length > cfg->ptrLength) { uError("config option:%s, input value:%s, length out of range[0, %d], use default value:%s", cfg->option, input_value, cfg->ptrLength, option); + return false; } else { if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) { strncpy(option, input_value, cfg->ptrLength); @@ -221,8 +254,10 @@ static void taosReadStringConfig(SGlobalCfg *cfg, char *input_value) { } else { uWarn("config option:%s, input value:%s, is configured by %s, use %s", cfg->option, input_value, tsCfgStatusStr[cfg->cfgStatus], option); + return false; } } + return true; } static void taosReadLogOption(char *option, char *value) { @@ -258,51 +293,59 @@ SGlobalCfg *taosGetConfigOption(const char *option) { return NULL; } -static void taosReadConfigOption(const char *option, char *value, char *value2, char *value3) { +bool taosReadConfigOption(const char *option, char *value, char *value2, char *value3, + int8_t cfgStatus, int8_t sourceType) { + bool ret = false; for (int i = 0; i < tsGlobalConfigNum; ++i) { SGlobalCfg *cfg = tsGlobalConfig + i; if (!(cfg->cfgType & TSDB_CFG_CTYPE_B_CONFIG)) continue; + if (sourceType != 0 && !(cfg->cfgType & sourceType)) continue; if (strcasecmp(cfg->option, option) != 0) continue; switch (cfg->valType) { case TAOS_CFG_VTYPE_INT8: - taosReadInt8Config(cfg, value); + ret = taosReadInt8Config(cfg, value); break; case TAOS_CFG_VTYPE_INT16: - taosReadInt16Config(cfg, value); + ret = taosReadInt16Config(cfg, value); break; case TAOS_CFG_VTYPE_INT32: - taosReadInt32Config(cfg, value); + ret = taosReadInt32Config(cfg, value); break; case TAOS_CFG_VTYPE_UINT16: - taosReadUInt16Config(cfg, value); + ret = taosReadUInt16Config(cfg, value); break; case TAOS_CFG_VTYPE_FLOAT: - taosReadFloatConfig(cfg, value); + ret = taosReadFloatConfig(cfg, value); break; case TAOS_CFG_VTYPE_DOUBLE: - taosReadDoubleConfig(cfg, value); + ret = taosReadDoubleConfig(cfg, value); break; case TAOS_CFG_VTYPE_STRING: - taosReadStringConfig(cfg, value); + ret = taosReadStringConfig(cfg, value); break; case TAOS_CFG_VTYPE_IPSTR: - taosReadIpStrConfig(cfg, value); + ret = taosReadIpStrConfig(cfg, value); break; case TAOS_CFG_VTYPE_DIRECTORY: - taosReadDirectoryConfig(cfg, value); + ret = taosReadDirectoryConfig(cfg, value); break; case TAOS_CFG_VTYPE_DATA_DIRCTORY: if (taosReadDirectoryConfig(cfg, value)) { - taosReadDataDirCfg(value, value2, value3); + taosReadDataDirCfg(value, value2, value3); + ret = true; } + ret = false; break; default: uError("config option:%s, input value:%s, can't be recognized", option, value); - break; + ret = false; + } + if(ret && cfgStatus == TAOS_CFG_CSTATUS_OPTION){ + cfg->cfgStatus = TAOS_CFG_CSTATUS_OPTION; } - break; } + return ret; } void taosInitConfigOption(SGlobalCfg cfg) { @@ -437,7 +480,7 @@ bool taosReadGlobalCfg() { if (vlen3 != 0) value3[vlen3] = 0; } - taosReadConfigOption(option, value, value2, value3); + taosReadConfigOption(option, value, value2, value3, TAOS_CFG_CSTATUS_FILE, 0); } fclose(fp); @@ -560,4 +603,4 @@ void taosDumpGlobalCfg() { taosDumpCfg(cfg); } -} +} \ No newline at end of file diff --git a/tests/examples/c/-g b/tests/examples/c/-g new file mode 100755 index 0000000000000000000000000000000000000000..3909909e8fe531a7b6d35ca315b8277e7270bb02 Binary files /dev/null and b/tests/examples/c/-g differ diff --git a/tests/examples/c/clientcfgtest-taosd.c b/tests/examples/c/clientcfgtest-taosd.c new file mode 100644 index 0000000000000000000000000000000000000000..fbfbd8935a34481c23e806bbe461882ed9a10437 --- /dev/null +++ b/tests/examples/c/clientcfgtest-taosd.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config to wrong type + const char config1[128] = "{\"cache\":\"4\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("cache");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config cache to '4'success!\n"); + else + printf("config cache failure!\n"); + return 0 ; + +} diff --git a/tests/examples/c/clientcfgtest-wrongjson.c b/tests/examples/c/clientcfgtest-wrongjson.c new file mode 100644 index 0000000000000000000000000000000000000000..eecb5dae6d27c213731afdea005af3fc265dd47f --- /dev/null +++ b/tests/examples/c/clientcfgtest-wrongjson.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config with wrong JSON + //The result is failure + const char config1[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\135\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + cfg1 = taosGetConfigOption("firstEp");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config firstEp 'BCC-2:6030'success!\n"); + else + printf("config firstEp failure!\n"); + SGlobalCfg *cfg2 ; + cfg2 = taosGetConfigOption("debugFlag");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '135'success!\n"); + else + printf("config debugFlag failure!\n"); + + + //case2: + //repair the JSON and try again + //The result is success + const char config2[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\"135\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg3 ; + + cfg3 = taosGetConfigOption("firstEp");//check the option result + if(cfg3->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config firstEp 'BCC-2:6030'success!\n"); + else + printf("config firstEp failure!\n"); + + SGlobalCfg *cfg4 ; + + cfg4 = taosGetConfigOption("debugFlag");//check the option result + if(cfg4->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '135'success!\n"); + else + printf("config debugFlag failure!\n"); + return 0 ; + +} diff --git a/tests/examples/c/clientcfgtest-wrongtype.c b/tests/examples/c/clientcfgtest-wrongtype.c new file mode 100644 index 0000000000000000000000000000000000000000..d88cbeebe8e5114ed4836e77b9494de1cc54aba8 --- /dev/null +++ b/tests/examples/c/clientcfgtest-wrongtype.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config to wrong type + //The result is failure + const char config1[128] = "{\"debugFlag\":\"9999999999999999999999999\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("debugFlag");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '9999999999999999999999999\n"); + else + printf("config debugFlag failure!\n"); + + //case2: + //Try again with right parameter + //The result is failure + const char config2[128] = "{\"debugFlag\":\"135\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg2 ; + + cfg2 = taosGetConfigOption("debugFlag");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugflag '135'success!\n"); + else + printf("config debugflag failure!\n"); + return 0 ; + +} diff --git a/tests/examples/c/clientcfgtest-wrongvalue.c b/tests/examples/c/clientcfgtest-wrongvalue.c new file mode 100644 index 0000000000000000000000000000000000000000..f0d44a47f62696d14844ea12276b74da7d0ff408 --- /dev/null +++ b/tests/examples/c/clientcfgtest-wrongvalue.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config to wrong type + const char config1[128] = "{\"rpcTimer\":\"0\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("rpcTimer");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config rpcTimer to '0'success!\n"); + else + printf("config rpcTimer failure!\n"); + + //case2: + //Try again with right parameter + const char config2[128] = "{\"rpcTimer\":\"400\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg2 ; + + cfg2 = taosGetConfigOption("rpcTimer");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config rpcTimer '400'success!\n"); + else + printf("config rpcTimer failure!\n"); + return 0 ; + +} diff --git a/tests/examples/c/clientcfgtest.c b/tests/examples/c/clientcfgtest.c new file mode 100644 index 0000000000000000000000000000000000000000..5f8f51cdb1156a25544273fc6419f65b86ea4ecc --- /dev/null +++ b/tests/examples/c/clientcfgtest.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include "os.h" +#include "taosdef.h" +#include "taoserror.h" +#include "tconfig.h" +#include "tglobal.h" +#include "tulog.h" +#include "tsocket.h" +#include "tutil.h" +extern SGlobalCfg *taosGetConfigOption(const char *option) ; +int main( int argc, char *argv[]){ + + printf("start to test\n"); + + //case1: + //Test config firstEp success + const char config1[128] = "{\"firstEp\":\"BCC-2:6030\",\"debugFlag\":\"135\"}";//input the parameter which want to be configured + taos_set_config(config1); //configure the parameter + + SGlobalCfg *cfg1 ; + + cfg1 = taosGetConfigOption("firstEp");//check the option result + if(cfg1->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config firstEp 'BCC-2:6030'success!\n"); + else + printf("config firstEp failure!\n"); + + + SGlobalCfg *cfg2 ; + + cfg2 = taosGetConfigOption("debugFlag");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config debugFlag '135' success!\n"); + else + printf("config debugFlag failure!\n"); + //case2: + //Test config only useful at the first time + //The result is failure + const char config2[128] = "{\"fqdn\":\"BCC-3\"}";//input the parameter which want to be configured + taos_set_config(config2); //configure the parameter + + SGlobalCfg *cfg3 ; + + cfg2 = taosGetConfigOption("fqdn");//check the option result + if(cfg2->cfgStatus == 3) //If cfgStatus is 3,it means configure is success + printf("config fqdn to 'BCC-3'success!\n"); + else + printf("config fqdn failure!\n"); + return 0 ; + +} diff --git a/tests/examples/c/makefile b/tests/examples/c/makefile index c85eb4adc515e5fb4e875b8e8e955222bc09190e..f364eb76fc34ab0975c00dcae2b8348e58b38517 100644 --- a/tests/examples/c/makefile +++ b/tests/examples/c/makefile @@ -17,6 +17,12 @@ exe: gcc $(CFLAGS) ./stream.c -o $(ROOT)stream $(LFLAGS) gcc $(CFLAGS) ./subscribe.c -o $(ROOT)subscribe $(LFLAGS) gcc $(CFLAGS) ./apitest.c -o $(ROOT)apitest $(LFLAGS) + gcc $(CFLAGS) ./clientcfgtest.c -o $(ROOT)clientcfgtest $(LFLAGS) + gcc $(CFLAGS) ./clientcfgtest-wrongtype.c -o $(ROOT)clientcfgtest-wrongtype $(LFLAGS) + gcc $(CFLAGS) ./clientcfgtest-wrongjson.c -o $(ROOT)clientcfgtest-wrongjson $(LFLAGS) + gcc $(CFLAGS) ./clientcfgtest-wrongvalue.c -o $(ROOT)clientcfgtest-wrongvalue $(LFLAGS) + gcc $(CFLAGS) ./clientcfgtest-taosd.c -o $(ROOT)clientcfgtest-taosd $(LFLAGS) + clean: rm $(ROOT)asyncdemo @@ -26,3 +32,9 @@ clean: rm $(ROOT)stream rm $(ROOT)subscribe rm $(ROOT)apitest + rm $(ROOT)clientcfgtest + rm $(ROOT)clientcfgtest-wrongtype + rm $(ROOT)clientcfgtest-wrongjson + rm $(ROOT)clientcfgtest-wrongvalue + rm $(ROOT)clientcfgtest-taosd +