From 7aef49638e48326fbf4f55be72ba4b266ec491f7 Mon Sep 17 00:00:00 2001 From: wangmm0220 Date: Fri, 15 Nov 2024 19:44:03 +0800 Subject: [PATCH] feat:[TD-32642] add timezone logic --- contrib/CMakeLists.txt | 2 +- include/client/taos.h | 10 +- include/common/ttime.h | 2 +- include/os/osSocket.h | 5 +- include/os/osTime.h | 3 + include/os/osTimezone.h | 16 +- include/util/taoserror.h | 3 + include/util/tconfig.h | 3 +- include/util/tutil.h | 5 - source/client/inc/clientInt.h | 8 +- source/client/src/clientEnv.c | 1 + source/client/src/clientMain.c | 97 +++++++ source/client/test/clientTests.cpp | 155 +++++++++++ source/common/src/tglobal.c | 18 +- source/common/src/ttime.c | 6 +- source/common/test/commonTests.cpp | 6 +- source/dnode/mgmt/mgmt_dnode/src/dmHandle.c | 4 +- source/dnode/mnode/impl/src/mndMain.c | 2 +- source/dnode/mnode/impl/src/mndProfile.c | 22 +- source/libs/command/src/command.c | 2 +- source/libs/parser/src/parInsertSql.c | 2 +- source/libs/parser/src/parTranslater.c | 2 +- source/libs/scalar/src/sclvector.c | 2 +- source/os/src/osEnv.c | 11 +- source/os/src/osSocket.c | 3 +- source/os/src/osTime.c | 122 ++++++++ source/os/src/osTimezone.c | 290 ++++++-------------- source/util/src/tconfig.c | 16 +- source/util/src/terror.c | 3 + source/util/src/tutil.c | 19 -- 30 files changed, 547 insertions(+), 293 deletions(-) diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index e52a5b4120..1380f036da 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -635,7 +635,7 @@ if(${TD_LINUX} AND ${BUILD_WITH_S3}) endif() execute_process( - COMMAND make TZDIR=${SHARE_OUTPUT_PATH}/timezone all posix_only + COMMAND make TZDIR=${SHARE_OUTPUT_PATH}/timezone clean all posix_only WORKING_DIRECTORY "${TD_CONTRIB_DIR}/tz" ) diff --git a/include/client/taos.h b/include/client/taos.h index f820536983..57fb6cfc0a 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -64,6 +64,14 @@ typedef enum { TSDB_MAX_OPTIONS } TSDB_OPTION; +typedef enum { + TSDB_OPTION_CONNECTION_CHARSET, // charset, Same as the scope supported by the system + TSDB_OPTION_CONNECTION_TIMEZONE, // timezone, Same as the scope supported by the system + TSDB_OPTION_CONNECTION_USER_IP, // user ip + TSDB_OPTION_CONNECTION_USER_APP, // user app + TSDB_MAX_CONNECTION_OPTIONS = 100 +} TSDB_OPTION_CONNECTION; + typedef enum { TSDB_OPTION_CONNECT_CHARSET, TSDB_OPTION_CONNECT_TIMEZONE, @@ -166,7 +174,7 @@ typedef struct TAOS_STMT_OPTIONS { DLL_EXPORT void taos_cleanup(void); DLL_EXPORT int taos_options(TSDB_OPTION option, const void *arg, ...); -DLL_EXPORT int taos_options_connect(TAOS *taos, TSDB_OPTION_CONNECT option, const void *arg, ...); +DLL_EXPORT int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...); DLL_EXPORT setConfRet taos_set_config(const char *config); DLL_EXPORT int taos_init(void); DLL_EXPORT TAOS *taos_connect(const char *ip, const char *user, const char *pass, const char *db, uint16_t port); diff --git a/include/common/ttime.h b/include/common/ttime.h index 8df4ebb5df..65cbc34fc3 100644 --- a/include/common/ttime.h +++ b/include/common/ttime.h @@ -81,7 +81,7 @@ int32_t taosTimeCountIntervalForFill(int64_t skey, int64_t ekey, int64_t interva int32_t parseAbsoluteDuration(const char* token, int32_t tokenlen, int64_t* ts, char* unit, int32_t timePrecision); int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit, int32_t timePrecision, bool negativeAllow); -int32_t taosParseTime(const char* timestr, int64_t* pTime, int32_t len, int32_t timePrec, int8_t dayligth); +int32_t taosParseTime(const char* timestr, int64_t* pTime, int32_t len, int32_t timePrec); void deltaToUtcInitOnce(); char getPrecisionUnit(int32_t precision); diff --git a/include/os/osSocket.h b/include/os/osSocket.h index 49acf285ee..ef5b700784 100644 --- a/include/os/osSocket.h +++ b/include/os/osSocket.h @@ -26,7 +26,6 @@ #define epoll_create EPOLL_CREATE_FUNC_TAOS_FORBID #define epoll_ctl EPOLL_CTL_FUNC_TAOS_FORBID #define epoll_wait EPOLL_WAIT_FUNC_TAOS_FORBID -#define inet_addr INET_ADDR_FUNC_TAOS_FORBID #define inet_ntoa INET_NTOA_FUNC_TAOS_FORBID #endif @@ -55,10 +54,11 @@ #define __BIG_ENDIAN BIG_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #define __PDP_ENDIAN PDP_ENDIAN - +#include #else #include #include +#include #if defined(_TD_DARWIN_64) #include @@ -163,7 +163,6 @@ int32_t taosBlockSIGPIPE(); int32_t taosGetIpv4FromFqdn(const char *fqdn, uint32_t *ip); int32_t taosGetFqdn(char *); void tinet_ntoa(char *ipstr, uint32_t ip); -uint32_t ip2uint(const char *const ip_addr); int32_t taosIgnSIGPIPE(); const char *taosInetNtoa(struct in_addr ipInt, char *dstStr, int32_t len); diff --git a/include/os/osTime.h b/include/os/osTime.h index 5d74146e9c..6142edcfa7 100644 --- a/include/os/osTime.h +++ b/include/os/osTime.h @@ -42,6 +42,7 @@ extern "C" { #define MILLISECOND_PER_SECOND ((int64_t)1000LL) #endif +#include "osTimezone.h" #define MILLISECOND_PER_MINUTE (MILLISECOND_PER_SECOND * 60) #define MILLISECOND_PER_HOUR (MILLISECOND_PER_MINUTE * 60) #define MILLISECOND_PER_DAY (MILLISECOND_PER_HOUR * 24) @@ -98,6 +99,8 @@ time_t taosMktime(struct tm *timep); int64_t user_mktime64(const uint32_t year, const uint32_t mon, const uint32_t day, const uint32_t hour, const uint32_t min, const uint32_t sec, int64_t time_zone); +struct tm *taosLocalTimeRz(timezone_t state, const time_t *timep, struct tm *result); +time_t taosMktimeRz(timezone_t state, struct tm *timep); #ifdef __cplusplus } #endif diff --git a/include/os/osTimezone.h b/include/os/osTimezone.h index cf3ca6a96a..52f7f661af 100644 --- a/include/os/osTimezone.h +++ b/include/os/osTimezone.h @@ -1160,13 +1160,7 @@ struct tzhead { # define TZDEFAULT "/etc/localtime" /* default zone */ #endif #ifndef TZDIR -# define TZDIR "/usr/local/share/timezone" /* TZif directory */ -#endif - -// If the error is in a third-party library, place this header file under the third-party library header file. -// When you want to use this feature, you should find or add the same function in the following section. -#ifndef ALLOW_FORBID_FUNC -#define tzset TZSET_FUNC_TAOS_FORBID +# define TZDIR "/Users/mingmingwanng/source_code/TDengine/debug/build/share/timezone" /* TZif directory */ #endif enum TdTimezone { @@ -1197,9 +1191,13 @@ enum TdTimezone { TdEastZone12 }; -int32_t taosGetSystemTimezone(char *outTimezone, enum TdTimezone *tsTimezone); -int32_t taosSetSystemTimezone(const char *inTimezone, char *outTimezone, int8_t *outDaylight, enum TdTimezone *tsTimezone); +void getTimezoneStr(char *tz); + +int32_t taosGetSystemTimezone(char *outTimezone); +int32_t taosSetGlobalTimezone(const char *tz); +int32_t taosFormatTimezoneStr(time_t t, const char* tzStr, timezone_t sp, char *outTimezoneStr); +int32_t taosIsValidateTimezone(const char *tz); #ifdef __cplusplus } #endif diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 9a8b39b84c..f712a06bfd 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -1023,6 +1023,9 @@ int32_t taosGetErrSize(); #define TSDB_CODE_AUDIT_FAIL_SEND_AUDIT_RECORD TAOS_DEF_ERROR_CODE(0, 0x6101) #define TSDB_CODE_AUDIT_FAIL_GENERATE_JSON TAOS_DEF_ERROR_CODE(0, 0x6102) +//TIMEZONE +#define TSDB_CODE_INVALID_TIMEZONE TAOS_DEF_ERROR_CODE(0, 0x6200) + #ifdef __cplusplus } #endif diff --git a/include/util/tconfig.h b/include/util/tconfig.h index 3fc247982f..947ef67902 100644 --- a/include/util/tconfig.h +++ b/include/util/tconfig.h @@ -34,7 +34,8 @@ typedef enum { CFG_STYPE_APOLLO_URL, CFG_STYPE_ARG_LIST, CFG_STYPE_TAOS_OPTIONS, - CFG_STYPE_ALTER_CMD, + CFG_STYPE_ALTER_CLIENT_CMD, + CFG_STYPE_ALTER_SERVER_CMD, } ECfgSrcType; typedef enum { diff --git a/include/util/tutil.h b/include/util/tutil.h index 87710b091d..3d243f3e31 100644 --- a/include/util/tutil.h +++ b/include/util/tutil.h @@ -48,11 +48,6 @@ int32_t taosHexStrToByteArray(char hexstr[], char bytes[]); int32_t tintToHex(uint64_t val, char hex[]); int32_t titoa(uint64_t val, size_t radix, char str[]); -char *taosIpStr(uint32_t ipInt); -uint32_t ip2uint(const char *const ip_addr); -void taosIp2String(uint32_t ip, char *str); -void taosIpPort2String(uint32_t ip, uint16_t port, char *str); - void *tmemmem(const char *haystack, int hlen, const char *needle, int nlen); int32_t parseCfgReal(const char *str, float *out); diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index e651d5b37e..6da950df5d 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -149,11 +149,11 @@ typedef struct { } SWhiteListInfo; typedef struct { -// TIMEZONE *tz; - char charset[TD_LOCALE_LEN]; + timezone_t timezone; + char charset[TD_CHARSET_LEN]; char app[TSDB_APP_NAME_LEN]; uint32_t ip; -}optionInfo; +}SOptionInfo; typedef struct STscObj { char user[TSDB_USER_LEN]; @@ -177,6 +177,7 @@ typedef struct STscObj { SPassInfo passInfo; SWhiteListInfo whiteListInfo; STscNotifyInfo userDroppedInfo; + SOptionInfo optionInfo; } STscObj; typedef struct STscDbg { @@ -341,6 +342,7 @@ extern int32_t clientReqRefPool; extern int32_t clientConnRefPool; extern int32_t timestampDeltaLimit; extern int64_t lastClusterId; +extern SHashObj* pTimezoneMap; __async_send_cb_fn_t getMsgRspHandle(int32_t msgType); diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c index 43b7382645..9e08e3e249 100644 --- a/source/client/src/clientEnv.c +++ b/source/client/src/clientEnv.c @@ -70,6 +70,7 @@ int64_t lastClusterId = 0; int32_t clientReqRefPool = -1; int32_t clientConnRefPool = -1; int32_t clientStop = -1; +SHashObj* pTimezoneMap = NULL; int32_t timestampDeltaLimit = 900; // s diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 64631fd754..2ee094bc18 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -51,6 +51,103 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) { atomic_store_32(&lock, 0); return ret; } + +static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char* val){ + if (taos == NULL) { + return TSDB_CODE_INVALID_PARA; + } + + if (option != TSDB_MAX_CONNECTION_OPTIONS && (option < TSDB_OPTION_CONNECTION_CHARSET && option > TSDB_OPTION_CONNECTION_USER_APP)){ + return TSDB_CODE_INVALID_PARA; + } + + STscObj *pObj = acquireTscObj(*(int64_t *)taos); + if (NULL == pObj) { + tscError("invalid parameter for %s", __func__); + return terrno; + } + + int32_t code = 0; + if (option == TSDB_OPTION_CONNECTION_CHARSET) { + if (val != NULL) { + if (!taosValidateEncodec(val)) { + code = terrno; + goto END; + } + tstrncpy(pObj->optionInfo.charset, val, TD_CHARSET_LEN); + }else{ + pObj->optionInfo.charset[0] = 0; + } + } else if (option == TSDB_OPTION_CONNECTION_TIMEZONE) { + if (val != NULL){ + if (strlen(val) == 0){ + code = TSDB_CODE_INVALID_PARA; + goto END; + } + timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val)); + if (tmp && *tmp){ + pObj->optionInfo.timezone = *tmp; + goto END; + } + + tscDebug("set timezone to %s", val); + timezone_t tz = tzalloc(val); + if (!tz) { + tscError("%s unknown timezone %s", __func__, val); + code = TAOS_SYSTEM_ERROR(errno); + goto END; + } + code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t)); + if (code != 0){ + tzfree(tz); + goto END; + } + pObj->optionInfo.timezone = tz; + } else { + pObj->optionInfo.timezone = NULL; + } + } else if (option == TSDB_OPTION_CONNECTION_USER_APP) { + if (val != NULL) { + tstrncpy(pObj->optionInfo.app, val, TSDB_APP_NAME_LEN); + } else { + pObj->optionInfo.app[0] = 0; + } + } else if (option == TSDB_OPTION_CONNECTION_USER_IP) { + if (val != NULL) { + pObj->optionInfo.ip = inet_addr(val); + } else { + pObj->optionInfo.ip = 0; + } + } + +END: + releaseTscObj(*(int64_t *)taos); + return code; +} + +int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...){ + static int32_t lock_c = 0; + + for (int i = 1; atomic_val_compare_exchange_32(&lock_c, 0, 1) != 0; ++i) { + if (i % 1000 == 0) { + tscInfo("haven't acquire lock after spin %d times.", i); + (void)sched_yield(); + } + } + + if (pTimezoneMap == NULL){ + pTimezoneMap = taosHashInit(0, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); + if (pTimezoneMap == NULL) { + atomic_store_32(&lock_c, 0); + return terrno; + } + taosHashSetFreeFp(pTimezoneMap, (_hash_free_fn_t)tzfree); + } + int ret = setConnectionOption(taos, option, (const char *)arg); + atomic_store_32(&lock_c, 0); + return ret; +} + // this function may be called by user or system, or by both simultaneously. void taos_cleanup(void) { tscDebug("start to cleanup client environment"); diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index 307ef7e06f..125df8f6b0 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -1610,4 +1610,159 @@ TEST(clientCase, timezone_Test) { } } +time_t time_winter = 1731323281; // 2024-11-11 19:08:01+0800 +time_t time_summer = 1731323281 - 120 * 24 * 60 * 60; + +struct test_times +{ + const char *name; + time_t t; + const char *timezone; +} test_tz[] = { + {"", time_winter, " (UTC, +0000)"}, + {"America/New_York", time_winter, "America/New_York (EST, -0500)"}, // 2024-11-11 19:08:01+0800 + {"America/New_York", time_summer, "America/New_York (EDT, -0400)"}, + {"Asia/Kolkata", time_winter, "Asia/Kolkata (IST, +0530)"}, + {"Asia/Shanghai", time_winter, "Asia/Shanghai (CST, +0800)"}, + {"Europe/London", time_winter, "Europe/London (GMT, +0000)"}, + {"Europe/London", time_summer, "Europe/London (BST, +0100)"} +}; + +void timezone_str_test(const char* tz, time_t t, const char* tzStr) { + int code = setenv("TZ", tz, 1); + ASSERT(-1 != code); + tzset(); + + char str1[TD_TIMEZONE_LEN] = {0}; + ASSERT(taosFormatTimezoneStr(t, tz, NULL, str1) == 0); + ASSERT_STREQ(str1, tzStr); +} + +void timezone_rz_str_test(const char* tz, time_t t, const char* tzStr) { + timezone_t sp = tzalloc(tz); + ASSERT(sp); + + char str1[TD_TIMEZONE_LEN] = {0}; + ASSERT(taosFormatTimezoneStr(t, tz, sp, str1) == 0); + ASSERT_STREQ(str1, tzStr); + tzfree(sp); +} + +TEST(clientCase, format_timezone_Test) { + for (unsigned int i = 0; i < sizeof (test_tz) / sizeof (test_tz[0]); ++i){ + timezone_str_test(test_tz[i].name, test_tz[i].t, test_tz[i].timezone); + timezone_str_test(test_tz[i].name, test_tz[i].t, test_tz[i].timezone); + } +} + +TEST(clientCase, get_tz_Test) { + { + char tz[TD_TIMEZONE_LEN] = {0}; + getTimezoneStr(tz); + ASSERT_STREQ(tz, "Asia/Shanghai"); + +// getTimezoneStr(tz); +// ASSERT_STREQ(tz, "Asia/Shanghai"); +// +// getTimezoneStr(tz); +// ASSERT_STREQ(tz, "n/a"); + } +} + +struct { + const char * env; + time_t expected; +} test_mk[] = { + {"MST", 832935315}, + {"", 832910115}, + {":UTC", 832910115}, + {"UTC", 832910115}, + {"UTC0", 832910115} +}; + + +TEST(clientCase, mktime_Test){ + struct tm tm; + time_t t; + + memset (&tm, 0, sizeof (tm)); + tm.tm_isdst = 0; + tm.tm_year = 96; /* years since 1900 */ + tm.tm_mon = 4; + tm.tm_mday = 24; + tm.tm_hour = 3; + tm.tm_min = 55; + tm.tm_sec = 15; + + for (unsigned int i = 0; i < sizeof (test_mk) / sizeof (test_mk[0]); ++i) + { + setenv ("TZ", test_mk[i].env, 1); + t = taosMktime (&tm); + ASSERT (t == test_mk[i].expected); + } +} + +TEST(clientCase, mktime_rz_Test){ + struct tm tm; + time_t t; + + memset (&tm, 0, sizeof (tm)); + tm.tm_isdst = 0; + tm.tm_year = 96; /* years since 1900 */ + tm.tm_mon = 4; + tm.tm_mday = 24; + tm.tm_hour = 3; + tm.tm_min = 55; + tm.tm_sec = 15; + + for (unsigned int i = 0; i < sizeof (test_mk) / sizeof (test_mk[0]); ++i) + { + timezone_t tz = tzalloc(test_mk[i].env); + ASSERT(tz); + t = taosMktimeRz(tz, &tm); + ASSERT (t == test_mk[i].expected); + tzfree(tz); + } +} + +TEST(testCase, localtime_performance_Test) { + timezone_t sp = tzalloc("Asia/Shanghai"); + ASSERT(sp); + + int cnt = 10000000; + int times = 10; + int64_t time_localtime = 0; + int64_t time_localtime_rz = 0; +// int cnt = 1000000; + for (int i = 0; i < times; ++i) { + int64_t t1 = taosGetTimestampNs(); + for (int j = 0; j < cnt; ++j) { + time_t t = time_winter - j; + struct tm tm1; + ASSERT (taosLocalTime(&t, &tm1, NULL, 0)); + } + int64_t tmp = taosGetTimestampNs() - t1; + printf("localtime cost:%" PRId64 " ns, run %" PRId64 " times", tmp, cnt); + time_localtime += tmp/cnt; + + timezone; + printf("\n"); + + + + int64_t t2 = taosGetTimestampNs(); + for (int j = 0; j < cnt; ++j) { + time_t t = time_winter - j; + struct tm tm1; + ASSERT (taosLocalTimeRz(sp, &t, &tm1)); + } + tmp = taosGetTimestampNs() - t2; + printf("localtime_rz cost:%" PRId64 " ns, run %" PRId64 " times", tmp, cnt); + time_localtime_rz += tmp/cnt; + printf("\n\n"); + } + printf("average: localtime cost:%" PRId64 " ns, localtime_rz cost:%" PRId64 " ns", time_localtime/times, time_localtime_rz/times); + tzfree(sp); +} + #pragma GCC diagnostic pop diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index 834615bdaa..57b3a7d67c 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -652,6 +652,7 @@ static int32_t taosAddClientCfg(SConfig *pCfg) { static int32_t taosAddSystemCfg(SConfig *pCfg) { SysNameInfo info = taosGetSysNameInfo(); + (void)taosGetSystemTimezone(tsTimezoneStr); TAOS_CHECK_RETURN(cfgAddTimezone(pCfg, "timezone", tsTimezoneStr, CFG_SCOPE_BOTH, CFG_DYN_CLIENT)); TAOS_CHECK_RETURN(cfgAddLocale(pCfg, "locale", tsLocale, CFG_SCOPE_BOTH, CFG_DYN_CLIENT)); TAOS_CHECK_RETURN(cfgAddCharset(pCfg, "charset", tsCharset, CFG_SCOPE_BOTH, CFG_DYN_NONE)); @@ -1311,15 +1312,6 @@ static int32_t taosSetClientCfg(SConfig *pCfg) { static int32_t taosSetSystemCfg(SConfig *pCfg) { SConfigItem *pItem = NULL; - TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "timezone"); - if (0 == strlen(pItem->str)) { - uError("timezone is not set"); - } else { - TAOS_CHECK_RETURN(osSetTimezone(pItem->str)); - uDebug("timezone format changed from %s to %s", pItem->str, tsTimezoneStr); - } - TAOS_CHECK_RETURN(cfgSetItem(pCfg, "timezone", tsTimezoneStr, pItem->stype, true)); - TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "locale"); const char *locale = pItem->str; @@ -2239,13 +2231,7 @@ static int32_t taosCfgDynamicOptionsForClient(SConfig *pCfg, const char *name) { break; } case 't': { - if (strcasecmp("timezone", name) == 0) { - TAOS_CHECK_GOTO(osSetTimezone(pItem->str), &lino, _out); - uInfo("%s set from %s to %s", name, tsTimezoneStr, pItem->str); - - TAOS_CHECK_GOTO(cfgSetItem(pCfg, "timezone", tsTimezoneStr, pItem->stype, false), &lino, _out); - matched = true; - } else if (strcasecmp("tempDir", name) == 0) { + if (strcasecmp("tempDir", name) == 0) { uInfo("%s set from %s to %s", name, tsTempDir, pItem->str); tstrncpy(tsTempDir, pItem->str, PATH_MAX); TAOS_CHECK_GOTO(taosExpandDir(tsTempDir, tsTempDir, PATH_MAX), &lino, _out); diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index 638f0411b7..c18ac32e46 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -36,7 +36,7 @@ static int32_t parseTimezone(char* str, int64_t* tzOffset); static int32_t (*parseLocaltimeFp[])(char* timestr, int32_t len, int64_t* utime, int32_t timePrec, char delim) = { parseLocaltime, parseLocaltimeDst}; -int32_t taosParseTime(const char* timestr, int64_t* utime, int32_t len, int32_t timePrec, int8_t day_light) { +int32_t taosParseTime(const char* timestr, int64_t* utime, int32_t len, int32_t timePrec) { /* parse datatime string in with tz */ if (strnchr(timestr, 'T', len, false) != NULL) { if (checkTzPresent(timestr, len)) { @@ -532,7 +532,7 @@ int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec TAOS_RETURN(terrno); } (void)memcpy(newColData, varDataVal(inputData), charLen); - int32_t ret = taosParseTime(newColData, timeVal, charLen, (int32_t)timePrec, tsDaylight); + int32_t ret = taosParseTime(newColData, timeVal, charLen, (int32_t)timePrec); if (ret != TSDB_CODE_SUCCESS) { taosMemoryFree(newColData); TAOS_RETURN(TSDB_CODE_INVALID_TIMESTAMP); @@ -549,7 +549,7 @@ int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec TAOS_RETURN(TSDB_CODE_FAILED); } newColData[len] = 0; - int32_t ret = taosParseTime(newColData, timeVal, len, (int32_t)timePrec, tsDaylight); + int32_t ret = taosParseTime(newColData, timeVal, len, (int32_t)timePrec); if (ret != TSDB_CODE_SUCCESS) { taosMemoryFree(newColData); TAOS_RETURN(ret); diff --git a/source/common/test/commonTests.cpp b/source/common/test/commonTests.cpp index b85af42d1c..054c3d5f58 100644 --- a/source/common/test/commonTests.cpp +++ b/source/common/test/commonTests.cpp @@ -442,15 +442,15 @@ TEST(timeTest, timestamp2tm) { int64_t ts, tmp_ts = 0; struct STm tm; - ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ns, &ts, strlen(ts_str_ns), TSDB_TIME_PRECISION_NANO, 0)); + ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ns, &ts, strlen(ts_str_ns), TSDB_TIME_PRECISION_NANO)); test_timestamp_tm_conversion(ts, TSDB_TIME_PRECISION_NANO, 2023 - 1900, 9 /* mon start from 0*/, 12, 11, 29, 0, 775726171L); - ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_us, &ts, strlen(ts_str_us), TSDB_TIME_PRECISION_MICRO, 0)); + ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_us, &ts, strlen(ts_str_us), TSDB_TIME_PRECISION_MICRO)); test_timestamp_tm_conversion(ts, TSDB_TIME_PRECISION_MICRO, 2023 - 1900, 9 /* mon start from 0*/, 12, 11, 29, 0, 775726000L); - ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ms, &ts, strlen(ts_str_ms), TSDB_TIME_PRECISION_MILLI, 0)); + ASSERT_EQ(TSDB_CODE_SUCCESS, taosParseTime(ts_str_ms, &ts, strlen(ts_str_ms), TSDB_TIME_PRECISION_MILLI)); test_timestamp_tm_conversion(ts, TSDB_TIME_PRECISION_MILLI, 2023 - 1900, 9 /* mon start from 0*/, 12, 11, 29, 0, 775000000L); diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c index 1446faab77..f65fe290a2 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c @@ -198,7 +198,7 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) { req.clusterCfg.monitorParas.tsSlowLogThresholdTest = tsSlowLogThresholdTest; tstrncpy(req.clusterCfg.monitorParas.tsSlowLogExceptDb, tsSlowLogExceptDb, TSDB_DB_NAME_LEN); char timestr[32] = "1970-01-01 00:00:00.00"; - if (taosParseTime(timestr, &req.clusterCfg.checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0) != 0) { + if (taosParseTime(timestr, &req.clusterCfg.checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI) != 0) { dError("failed to parse time since %s", tstrerror(code)); } memcpy(req.clusterCfg.timezone, tsTimezoneStr, TD_TIMEZONE_LEN); @@ -356,7 +356,7 @@ int32_t dmProcessConfigReq(SDnodeMgmt *pMgmt, SRpcMsg *pMsg) { SConfig *pCfg = taosGetCfg(); - code = cfgSetItem(pCfg, cfgReq.config, cfgReq.value, CFG_STYPE_ALTER_CMD, true); + code = cfgSetItem(pCfg, cfgReq.config, cfgReq.value, CFG_STYPE_ALTER_SERVER_CMD, true); if (code != 0) { if (strncasecmp(cfgReq.config, "resetlog", strlen("resetlog")) == 0) { code = 0; diff --git a/source/dnode/mnode/impl/src/mndMain.c b/source/dnode/mnode/impl/src/mndMain.c index 08ebf52ec6..c2edf6d6d8 100644 --- a/source/dnode/mnode/impl/src/mndMain.c +++ b/source/dnode/mnode/impl/src/mndMain.c @@ -713,7 +713,7 @@ SMnode *mndOpen(const char *path, const SMnodeOpt *pOption) { } char timestr[24] = "1970-01-01 00:00:00.00"; - code = taosParseTime(timestr, &pMnode->checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0); + code = taosParseTime(timestr, &pMnode->checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI); if (code < 0) { mError("failed to parse time since %s", tstrerror(code)); (void)taosThreadRwlockDestroy(&pMnode->lock); diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c index a1ffee9b06..fd44e223b9 100644 --- a/source/dnode/mnode/impl/src/mndProfile.c +++ b/source/dnode/mnode/impl/src/mndProfile.c @@ -232,7 +232,7 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) { SConnObj *pConn = NULL; int32_t code = 0; SConnectReq connReq = {0}; - char ip[24] = {0}; + char ip[TD_IP_LEN] = {0}; const STraceId *trace = &pReq->info.traceId; if ((code = tDeserializeSConnectReq(pReq->pCont, pReq->contLen, &connReq)) != 0) { @@ -244,7 +244,7 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) { goto _OVER; } - taosIp2String(pReq->info.conn.clientIp, ip); + tinet_ntoa(ip, pReq->info.conn.clientIp); if ((code = mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CONNECT)) != 0) { mGError("user:%s, failed to login from %s since %s", pReq->info.conn.user, ip, tstrerror(code)); goto _OVER; @@ -896,9 +896,10 @@ static int32_t mndRetrieveConns(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl return code; } - char endpoint[TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; - (void)sprintf(&endpoint[VARSTR_HEADER_SIZE], "%s:%d", taosIpStr(pConn->ip), pConn->port); - varDataLen(endpoint) = strlen(&endpoint[VARSTR_HEADER_SIZE]); + char endpoint[TD_IP_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; + tinet_ntoa(varDataVal(endpoint), pConn->ip); + (void)sprintf(varDataVal(endpoint) + strlen(varDataVal(endpoint)), ":%d", pConn->port); + varDataLen(endpoint) = strlen(varDataVal(endpoint)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); code = colDataSetVal(pColInfo, numOfRows, (const char *)endpoint, false); if (code != 0) { @@ -1006,8 +1007,9 @@ static int32_t packQueriesIntoBlock(SShowObj *pShow, SConnObj *pConn, SSDataBloc return code; } - char endpoint[TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; - (void)sprintf(&endpoint[VARSTR_HEADER_SIZE], "%s:%d", taosIpStr(pConn->ip), pConn->port); + char endpoint[TD_IP_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; + tinet_ntoa(varDataVal(endpoint), pConn->ip); + (void)sprintf(varDataVal(endpoint) + strlen(varDataVal(endpoint)), ":%d", pConn->port); varDataLen(endpoint) = strlen(&endpoint[VARSTR_HEADER_SIZE]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); code = colDataSetVal(pColInfo, curRowIndex, (const char *)endpoint, false); @@ -1165,9 +1167,9 @@ static int32_t mndRetrieveApps(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlo return code; } - char ip[TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; - (void)sprintf(&ip[VARSTR_HEADER_SIZE], "%s", taosIpStr(pApp->ip)); - varDataLen(ip) = strlen(&ip[VARSTR_HEADER_SIZE]); + char ip[TD_IP_LEN + VARSTR_HEADER_SIZE] = {0}; + tinet_ntoa(varDataVal(ip), pApp->ip); + varDataLen(ip) = strlen(varDataVal(ip)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); code = colDataSetVal(pColInfo, numOfRows, (const char *)ip, false); if (code != 0) { diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 716296345f..62cdd5d7ab 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -901,7 +901,7 @@ static int32_t execAlterLocal(SAlterLocalStmt* pStmt) { return terrno; } - if (cfgSetItem(tsCfg, pStmt->config, pStmt->value, CFG_STYPE_ALTER_CMD, true)) { + if (cfgSetItem(tsCfg, pStmt->config, pStmt->value, CFG_STYPE_ALTER_CLIENT_CMD, true)) { return terrno; } diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 1c26a7c70e..81deefcaf1 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -267,7 +267,7 @@ static int parseTimestampOrInterval(const char** end, SToken* pToken, int16_t ti } } else { // parse the RFC-3339/ISO-8601 timestamp format string *isTs = true; - if (taosParseTime(pToken->z, ts, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { + if (taosParseTime(pToken->z, ts, pToken->n, timePrec) != TSDB_CODE_SUCCESS) { if ((pToken->n == 0) || (pToken->type != TK_NK_STRING && pToken->type != TK_NK_HEX && pToken->type != TK_NK_BIN)) { return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index e475d34055..824764a9f6 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1949,7 +1949,7 @@ static int32_t parseTimeFromValueNode(STranslateContext* pCxt, SValueNode* pVal) return TSDB_CODE_SUCCESS; } else if (IS_VAR_DATA_TYPE(pVal->node.resType.type) || TSDB_DATA_TYPE_TIMESTAMP == pVal->node.resType.type) { if (TSDB_CODE_SUCCESS == taosParseTime(pVal->literal, &pVal->datum.i, pVal->node.resType.bytes, - pVal->node.resType.precision, tsDaylight)) { + pVal->node.resType.precision)) { return TSDB_CODE_SUCCESS; } char* pEnd = NULL; diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index 8db0562c63..7e37d00bfe 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -242,7 +242,7 @@ int32_t getVectorBigintValueFn(int32_t srcType, _getBigintValue_fn_t *p) { static FORCE_INLINE int32_t varToTimestamp(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { int64_t value = 0; int32_t code = TSDB_CODE_SUCCESS; - if (taosParseTime(buf, &value, strlen(buf), pOut->columnData->info.precision, tsDaylight) != TSDB_CODE_SUCCESS) { + if (taosParseTime(buf, &value, strlen(buf), pOut->columnData->info.precision) != TSDB_CODE_SUCCESS) { value = 0; code = TSDB_CODE_SCALAR_CONVERT_ERROR; } diff --git a/source/os/src/osEnv.c b/source/os/src/osEnv.c index 05c9936c2e..1550e75432 100644 --- a/source/os/src/osEnv.c +++ b/source/os/src/osEnv.c @@ -28,7 +28,6 @@ char tsTimezoneStr[TD_TIMEZONE_LEN] = {0}; enum TdTimezone tsTimezone = TdZeroZone; char tsLocale[TD_LOCALE_LEN] = {0}; char tsCharset[TD_CHARSET_LEN] = {0}; -int8_t tsDaylight = 0; bool tsEnableCoreFile = 1; int64_t tsPageSizeKB = 0; int64_t tsOpenMax = 0; @@ -49,14 +48,6 @@ int32_t osDefaultInit() { taosSeedRand(taosSafeRand()); taosGetSystemLocale(tsLocale, tsCharset); - code = taosGetSystemTimezone(tsTimezoneStr, &tsTimezone); - if(code != 0) { - return code; - } - if (strlen(tsTimezoneStr) > 0) { // ignore empty timezone - if ((code = taosSetSystemTimezone(tsTimezoneStr, tsTimezoneStr, &tsDaylight, &tsTimezone)) != TSDB_CODE_SUCCESS) - return code; - } taosGetSystemInfo(); @@ -124,7 +115,7 @@ bool osDataSpaceSufficient() { return tsDataSpace.size.avail > tsDataSpace.reser bool osTempSpaceSufficient() { return tsTempSpace.size.avail > tsTempSpace.reserved; } -int32_t osSetTimezone(const char *tz) { return taosSetSystemTimezone(tz, tsTimezoneStr, &tsDaylight, &tsTimezone); } +int32_t osSetTimezone(const char *tz) { return taosSetGlobalTimezone(tz); } void osSetSystemLocale(const char *inLocale, const char *inCharSet) { (void)memcpy(tsLocale, inLocale, strlen(inLocale) + 1); diff --git a/source/os/src/osSocket.c b/source/os/src/osSocket.c index 5f983d5480..d1f43ea05f 100644 --- a/source/os/src/osSocket.c +++ b/source/os/src/osSocket.c @@ -384,7 +384,8 @@ int32_t taosGetFqdn(char *fqdn) { } void tinet_ntoa(char *ipstr, uint32_t ip) { - (void)snprintf(ipstr, TD_IP_LEN, "%d.%d.%d.%d", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24); + unsigned char *bytes = (unsigned char *) &ip; + (void)snprintf(ipstr, TD_IP_LEN, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); } int32_t taosIgnSIGPIPE() { diff --git a/source/os/src/osTime.c b/source/os/src/osTime.c index d4d9936154..3798a96e9d 100644 --- a/source/os/src/osTime.c +++ b/source/os/src/osTime.c @@ -539,6 +539,128 @@ struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int3 return result; } +time_t taosMktimeRz(timezone_t state, struct tm *timep) { +#ifdef WINDOWS + #if 0 + struct tm tm1 = {0}; + LARGE_INTEGER t; + FILETIME f; + SYSTEMTIME s; + FILETIME ff; + SYSTEMTIME ss; + LARGE_INTEGER offset; + + time_t tt = 0; + localtime_s(&tm1, &tt); + ss.wYear = tm1.tm_year + 1900; + ss.wMonth = tm1.tm_mon + 1; + ss.wDay = tm1.tm_mday; + ss.wHour = tm1.tm_hour; + ss.wMinute = tm1.tm_min; + ss.wSecond = tm1.tm_sec; + ss.wMilliseconds = 0; + SystemTimeToFileTime(&ss, &ff); + offset.QuadPart = ff.dwHighDateTime; + offset.QuadPart <<= 32; + offset.QuadPart |= ff.dwLowDateTime; + + s.wYear = timep->tm_year + 1900; + s.wMonth = timep->tm_mon + 1; + s.wDay = timep->tm_mday; + s.wHour = timep->tm_hour; + s.wMinute = timep->tm_min; + s.wSecond = timep->tm_sec; + s.wMilliseconds = 0; + SystemTimeToFileTime(&s, &f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + + t.QuadPart -= offset.QuadPart; + return (time_t)(t.QuadPart / 10000000); +#else + time_t result = mktime(timep); + if (result != -1) { + return result; + } +#ifdef _MSC_VER +#if _MSC_VER >= 1900 + int64_t tz = _timezone; +#endif +#endif + return user_mktime64(timep->tm_year + 1900, timep->tm_mon + 1, timep->tm_mday, timep->tm_hour, timep->tm_min, + timep->tm_sec, tz); +#endif +#else + time_t r = mktime_z(state, timep); + if (r == (time_t)-1) { + terrno = TAOS_SYSTEM_ERROR(errno); + } + return r; +#endif +} + +struct tm *taosLocalTimeRz(timezone_t state, const time_t *timep, struct tm *result) { + struct tm *res = NULL; + if (timep == NULL || result == NULL) { + return NULL; + } +#ifdef WINDOWS + if (*timep < -2208988800LL) { + if (buf != NULL) { + snprintf(buf, bufSize, "NaN"); + } + return NULL; + } else if (*timep < 0) { + SYSTEMTIME ss, s; + FILETIME ff, f; + + LARGE_INTEGER offset; + struct tm tm1; + time_t tt = 0; + if (localtime_s(&tm1, &tt) != 0) { + if (buf != NULL) { + snprintf(buf, bufSize, "NaN"); + } + return NULL; + } + ss.wYear = tm1.tm_year + 1900; + ss.wMonth = tm1.tm_mon + 1; + ss.wDay = tm1.tm_mday; + ss.wHour = tm1.tm_hour; + ss.wMinute = tm1.tm_min; + ss.wSecond = tm1.tm_sec; + ss.wMilliseconds = 0; + SystemTimeToFileTime(&ss, &ff); + offset.QuadPart = ff.dwHighDateTime; + offset.QuadPart <<= 32; + offset.QuadPart |= ff.dwLowDateTime; + offset.QuadPart += *timep * 10000000; + f.dwLowDateTime = offset.QuadPart & 0xffffffff; + f.dwHighDateTime = (offset.QuadPart >> 32) & 0xffffffff; + FileTimeToSystemTime(&f, &s); + result->tm_sec = s.wSecond; + result->tm_min = s.wMinute; + result->tm_hour = s.wHour; + result->tm_mday = s.wDay; + result->tm_mon = s.wMonth - 1; + result->tm_year = s.wYear - 1900; + result->tm_wday = s.wDayOfWeek; + result->tm_yday = 0; + result->tm_isdst = 0; + } else { + if (localtime_s(result, timep) != 0) { + if (buf != NULL) { + snprintf(buf, bufSize, "NaN"); + } + return NULL; + } + } +#else + return localtime_rz(state, timep, result); +#endif +} + static int isLeapYear(time_t year) { if (year % 4) return 0; diff --git a/source/os/src/osTimezone.c b/source/os/src/osTimezone.c index f9a9dac85e..1b54f3a42c 100644 --- a/source/os/src/osTimezone.c +++ b/source/os/src/osTimezone.c @@ -740,8 +740,6 @@ char *tz_win[554][2] = {{"Asia/Shanghai", "China Standard Time"}, #include #endif -static int isdst_now = 0; - void parseTimeStr(char *p, char to[5]) { for (int i = 0; i < 5; ++i) { if (strlen(p) > i) { @@ -756,27 +754,16 @@ void parseTimeStr(char *p, char to[5]) { } } -int32_t taosSetSystemTimezone(const char *inTimezoneStr, char *outTimezoneStr, int8_t *outDaylight, - enum TdTimezone *tsTimezone) { - if (inTimezoneStr == NULL || inTimezoneStr[0] == 0) { - terrno = TSDB_CODE_INVALID_PARA; - return terrno; - } +int32_t taosIsValidateTimezone(const char *tz) { + return true; +} - int32_t code = TSDB_CODE_SUCCESS; - size_t len = strlen(inTimezoneStr); - if (len >= TD_TIMEZONE_LEN) { +int32_t taosSetGlobalTimezone(const char *tz) { + if (tz == NULL || tz[0] == 0) { terrno = TSDB_CODE_INVALID_PARA; return terrno; } - char buf[TD_TIMEZONE_LEN] = {0}; - for (int32_t i = 0; i < len; i++) { - if (inTimezoneStr[i] == ' ' || inTimezoneStr[i] == '(') { - buf[i] = 0; - break; - } - buf[i] = inTimezoneStr[i]; - } + int32_t code = TSDB_CODE_SUCCESS; #ifdef WINDOWS char winStr[TD_LOCALE_LEN * 2]; @@ -825,44 +812,100 @@ int32_t taosSetSystemTimezone(const char *inTimezoneStr, char *outTimezoneStr, i if (outTimezoneStr != inTimezoneStr) { tstrncpy(outTimezoneStr, inTimezoneStr, TD_TIMEZONE_LEN); } - *outDaylight = 0; - -#elif defined(_TD_DARWIN_64) - - code = setenv("TZ", buf, 1); - if (-1 == code) { - terrno = TAOS_SYSTEM_ERROR(errno); - return terrno; - } - tzset(); - int32_t tz = (int32_t)((-timezone * MILLISECOND_PER_SECOND) / MILLISECOND_PER_HOUR); - *tsTimezone = tz; - tz += isdst_now; - - snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %s%02d00)", buf, tzname[isdst_now], tz >= 0 ? "+" : "-", abs(tz)); - *outDaylight = isdst_now; - +// *outDaylight = 0; #else - code = setenv("TZ", buf, 1); + code = setenv("TZ", tz, 1); if (-1 == code) { terrno = TAOS_SYSTEM_ERROR(errno); return terrno; } tzset(); - int32_t tz = (int32_t)((-timezone * MILLISECOND_PER_SECOND) / MILLISECOND_PER_HOUR); - *tsTimezone = tz; - tz += isdst_now; - (void)snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %s%02d00)", buf, tzname[isdst_now], tz >= 0 ? "+" : "-", abs(tz)); - *outDaylight = isdst_now; + time_t tx1 = taosGetTimestampSec(); + return taosFormatTimezoneStr(tx1, tz, NULL, tsTimezoneStr); #endif - return code; } -int32_t taosGetSystemTimezone(char *outTimezoneStr, enum TdTimezone *tsTimezone) { - int32_t code = 0; +int32_t taosFormatTimezoneStr(time_t t, const char* tz, timezone_t sp, char *outTimezoneStr){ + struct tm tm1; + if (sp == NULL) { + if (taosLocalTime(&t, &tm1, NULL, 0) == NULL) { + uError("failed to get local time"); + return TSDB_CODE_TIME_ERROR; + } + } else { + if (taosLocalTimeRz(sp, &t, &tm1) == NULL) { + uError("failed to get rz time"); + return TSDB_CODE_TIME_ERROR; + } + } + + /* + * format example: + * + * Asia/Shanghai (CST, +0800) + * Europe/London (BST, +0100) + * n/a (UTC, +0000) + */ + + char str1[TD_TIMEZONE_LEN] = {0}; + if (strftime(str1, sizeof(str1), "%Z", &tm1) == 0){ + uError("failed to get timezone name"); + return TSDB_CODE_TIME_ERROR; + } + + char str2[TD_TIMEZONE_LEN] = {0}; + if (strftime(str2, sizeof(str2), "%z", &tm1) == 0){ + uError("failed to get timezone offset"); + return TSDB_CODE_TIME_ERROR; + } + (void)snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %s)", tz, str1, str2); + return 0; +} + +void getTimezoneStr(char *tz) { + do { + int n = readlink("/r/localtime", tz, TD_TIMEZONE_LEN - 1); + if (n < 0) { + uWarn("[tz] failed to readlink /etc/localtime, reason:%s", strerror(errno)); + break; + } + + char *zi = strstr(tz, "zoneinfo"); + if (zi == NULL) { + uWarn("[tz] failed to find zoneinfo in /etc/localtime"); + break; + } + zi += sizeof("zoneinfo"); + memcpy(tz, zi, TD_TIMEZONE_LEN - (zi - tz)); + goto END; + } while (0); + + + TdFilePtr pFile = taosOpenFile("/etc/timezone", TD_FILE_READ); + if (pFile == NULL) { + uWarn("[tz] failed to open /etc/timezone, reason:%s", strerror(errno)); + goto END; + } + int len = taosReadFile(pFile, tz, TD_TIMEZONE_LEN - 1); + TAOS_UNUSED(taosCloseFile(&pFile)); + if (len <= 0) { + uWarn("[tz] failed to read /etc/timezone, len:%d", len); + goto END; + } + if (tz[len - 1] == '\n') { + tz[len - 1] = '\0'; + } + +END: + if (tz[0] == '\0') { + memcpy(tz, "n/a", sizeof("n/a")); + } +} + +int32_t taosGetSystemTimezone(char *outTimezoneStr) { #ifdef WINDOWS char value[100]; char keyPath[100]; @@ -895,162 +938,11 @@ int32_t taosGetSystemTimezone(char *outTimezoneStr, enum TdTimezone *tsTimezone) } } return 0; -#elif defined(_TD_DARWIN_64) - char buf[4096] = {0}; - char *tz = NULL; - { - int n = readlink("/etc/localtime", buf, sizeof(buf)); - if (n < 0) { - return TSDB_CODE_TIME_ERROR; - } - buf[n] = '\0'; - - char *zi = strstr(buf, "zoneinfo"); - if (!zi) { - return TSDB_CODE_TIME_ERROR; - } - tz = zi + strlen("zoneinfo") + 1; - - code = setenv("TZ", tz, 1); - if (-1 == code) { - terrno = TAOS_SYSTEM_ERROR(errno); - return terrno; - } - tzset(); - } - - /* - * NOTE: do not remove it. - * Enforce set the correct daylight saving time(DST) flag according - * to current time - */ - time_t tx1 = taosGetTimestampSec(); - struct tm tm1; - if (taosLocalTime(&tx1, &tm1, NULL, 0) == NULL) { - return TSDB_CODE_TIME_ERROR; - } - daylight = tm1.tm_isdst; - isdst_now = tm1.tm_isdst; - - /* - * format example: - * - * Asia/Shanghai (CST, +0800) - * Europe/London (BST, +0100) - */ - snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %+03ld00)", tz, tm1.tm_isdst ? tzname[daylight] : tzname[0], - -timezone / 3600); - return 0; #else - - char buf[4096] = {0}; - char *tz = NULL; - { - int n = readlink("/etc/localtime", buf, sizeof(buf)-1); - if (n < 0) { - if (taosCheckExistFile("/etc/timezone")) { - /* - * NOTE: do not remove it. - * Enforce set the correct daylight saving time(DST) flag according - * to current time - */ - time_t tx1 = taosGetTimestampSec(); - struct tm tm1; - if(taosLocalTime(&tx1, &tm1, NULL, 0) == NULL) { - return TSDB_CODE_TIME_ERROR; - } - /* load time zone string from /etc/timezone */ - // FILE *f = fopen("/etc/timezone", "r"); - errno = 0; - TdFilePtr pFile = taosOpenFile("/etc/timezone", TD_FILE_READ); - char buf[68] = {0}; - if (pFile != NULL) { - int len = taosReadFile(pFile, buf, 64); - if (len < 0) { - TAOS_UNUSED(taosCloseFile(&pFile)); - return TSDB_CODE_TIME_ERROR; - } - - TAOS_UNUSED(taosCloseFile(&pFile)); - - buf[sizeof(buf) - 1] = 0; - char *lineEnd = strstr(buf, "\n"); - if (lineEnd != NULL) { - *lineEnd = 0; - } - - // for CentOS system, /etc/timezone does not exist. Ignore the TZ environment variables - if (strlen(buf) > 0) { - code = setenv("TZ", buf, 1); - if (-1 == code) { - terrno = TAOS_SYSTEM_ERROR(errno); - return terrno; - } - } - } - // get and set default timezone - tzset(); - /* - * get CURRENT time zone. - * system current time zone is affected by daylight saving time(DST) - * - * e.g., the local time zone of London in DST is GMT+01:00, - * otherwise is GMT+00:00 - */ - int32_t tz = (-timezone * MILLISECOND_PER_SECOND) / MILLISECOND_PER_HOUR; - *tsTimezone = tz; - tz += daylight; - - /* - * format example: - * - * Asia/Shanghai (CST, +0800) - * Europe/London (BST, +0100) - */ - (void)snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %s%02d00)", buf, tzname[daylight], tz >= 0 ? "+" : "-", - abs(tz)); - } else { - return TSDB_CODE_TIME_ERROR; - } - return 0; - } - buf[n] = '\0'; - - char *zi = strstr(buf, "zoneinfo"); - if (!zi) { - return TSDB_CODE_TIME_ERROR; - } - tz = zi + strlen("zoneinfo") + 1; - - code = setenv("TZ", tz, 1); - if (-1 == code) { - terrno = TAOS_SYSTEM_ERROR(errno); - return terrno; - } - tzset(); - } - - /* - * NOTE: do not remove it. - * Enforce set the correct daylight saving time(DST) flag according - * to current time - */ + char tz[TD_TIMEZONE_LEN] = {0}; + getTimezoneStr(tz); time_t tx1 = taosGetTimestampSec(); - struct tm tm1; - if(taosLocalTime(&tx1, &tm1, NULL, 0) == NULL) { - return TSDB_CODE_TIME_ERROR; - } - isdst_now = tm1.tm_isdst; - - /* - * format example: - * - * Asia/Shanghai (CST, +0800) - * Europe/London (BST, +0100) - */ - (void)snprintf(outTimezoneStr, TD_TIMEZONE_LEN, "%s (%s, %+03ld00)", tz, tm1.tm_isdst ? tzname[daylight] : tzname[0], - -timezone / 3600); - return 0; + return taosFormatTimezoneStr(tx1, tz, NULL, outTimezoneStr); #endif } diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index d6852b0566..96056e3678 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -245,6 +245,17 @@ static int32_t doSetConf(SConfigItem *pItem, const char *value, ECfgSrcType styp } static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType stype) { + if (stype == CFG_STYPE_ALTER_SERVER_CMD || (pItem->dynScope & CFG_DYN_CLIENT) == 0){ + uError("failed to config timezone, not support"); + TAOS_RETURN(TSDB_CODE_INVALID_CFG); + } + + if(!taosIsValidateTimezone(value)){ + uError("invalid timezone:%s", value); + TAOS_RETURN(TSDB_CODE_INVALID_TIMEZONE); + } + TAOS_CHECK_RETURN(osSetTimezone(value)); + TAOS_CHECK_RETURN(doSetConf(pItem, value, stype)); if (strlen(value) == 0) { uError("cfg:%s, type:%s src:%s, value:%s, skip to set timezone", pItem->name, cfgDtypeStr(pItem->dtype), @@ -252,7 +263,6 @@ static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType TAOS_RETURN(TSDB_CODE_SUCCESS); } - TAOS_CHECK_RETURN(osSetTimezone(value)); TAOS_RETURN(TSDB_CODE_SUCCESS); } @@ -634,6 +644,10 @@ const char *cfgStypeStr(ECfgSrcType type) { return "taos_options"; case CFG_STYPE_ENV_CMD: return "env_cmd"; + case CFG_STYPE_ALTER_CLIENT_CMD: + return "alter_client_cmd"; + case CFG_STYPE_ALTER_SERVER_CMD: + return "alter_server_cmd"; default: return "invalid"; } diff --git a/source/util/src/terror.c b/source/util/src/terror.c index d660edd0b8..e74157ef66 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -866,6 +866,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_UTIL_QUEUE_OUT_OF_MEMORY, "Queue out of memory TAOS_DEFINE_ERROR(TSDB_CODE_AUDIT_NOT_FORMAT_TO_JSON, "can't format to json") TAOS_DEFINE_ERROR(TSDB_CODE_AUDIT_FAIL_SEND_AUDIT_RECORD, "Failed to send out audit record") TAOS_DEFINE_ERROR(TSDB_CODE_AUDIT_FAIL_GENERATE_JSON, "Failed to generate json") + +//TIMEZONE +TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_TIMEZONE, "Invalid timezone") #ifdef TAOS_ERROR_C }; #endif diff --git a/source/util/src/tutil.c b/source/util/src/tutil.c index 48338e7996..898112647d 100644 --- a/source/util/src/tutil.c +++ b/source/util/src/tutil.c @@ -416,25 +416,6 @@ int32_t taosHexStrToByteArray(char hexstr[], char bytes[]) { return 0; } -char *taosIpStr(uint32_t ipInt) { - static char ipStrArray[3][30]; - static int32_t ipStrIndex = 0; - - char *ipStr = ipStrArray[(ipStrIndex++) % 3]; - // sprintf(ipStr, "0x%x:%u.%u.%u.%u", ipInt, ipInt & 0xFF, (ipInt >> 8) & 0xFF, (ipInt >> 16) & 0xFF, (uint8_t)(ipInt - // >> 24)); - sprintf(ipStr, "%u.%u.%u.%u", ipInt & 0xFF, (ipInt >> 8) & 0xFF, (ipInt >> 16) & 0xFF, (uint8_t)(ipInt >> 24)); - return ipStr; -} - -void taosIp2String(uint32_t ip, char *str) { - sprintf(str, "%u.%u.%u.%u", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (uint8_t)(ip >> 24)); -} - -void taosIpPort2String(uint32_t ip, uint16_t port, char *str) { - sprintf(str, "%u.%u.%u.%u:%u", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (uint8_t)(ip >> 24), port); -} - size_t tstrncspn(const char *str, size_t size, const char *reject, size_t rsize) { if (rsize == 0 || rsize == 1) { char *p = strnchr(str, reject[0], size, false);