diff --git a/cmake/define.inc b/cmake/define.inc index f6438c08736c7cc63cdd1734e016f9a0945df631..b1e8f097beb45a199f1d2490211154b215ea0960 100755 --- a/cmake/define.inc +++ b/cmake/define.inc @@ -29,41 +29,10 @@ IF (TD_RANDOM_NETWORK_FAIL) ADD_DEFINITIONS(-DTAOS_RANDOM_NETWORK_FAIL) ENDIF () -IF (TD_ARM) - ADD_DEFINITIONS(-D_TD_ARM_) - IF (TD_ARM_64) - ADD_DEFINITIONS(-D_TD_ARM_64_) - ENDIF () - IF (TD_ARM_32) - ADD_DEFINITIONS(-D_TD_ARM_32_) - ENDIF () -ENDIF () - -IF (TD_MIPS) - ADD_DEFINITIONS(-D_TD_MIPS_) - IF (TD_MIPS_64) - ADD_DEFINITIONS(-D_TD_MIPS_64_) - ENDIF () - IF (TD_MIPS_32) - ADD_DEFINITIONS(-D_TD_MIPS_32_) - ENDIF () -ENDIF () - IF (TD_LINUX_64) ADD_DEFINITIONS(-D_M_X64) ADD_DEFINITIONS(-D_TD_LINUX_64) - IF (NOT TD_ARM) - #IF ((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR (${CMAKE_CXX_COMPILER_ID} MATCHES "clang")) - # SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -Wno-missing-braces -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") - #ELSE () - # SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -malign-double -g3 -gdwarf-2 -malign-stringops -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") - #ENDIF () - SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") - ELSE () - SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") - ENDIF () - MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID}) - MESSAGE(STATUS "COMMON_FLAGS: " ${COMMON_FLAGS}) + SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") FIND_PATH(ICONV_INCLUDE_EXIST iconv.h /usr/include/ /usr/local/include/) IF (ICONV_INCLUDE_EXIST) @@ -75,13 +44,39 @@ IF (TD_LINUX_32) ADD_DEFINITIONS(-D_TD_LINUX_32) ADD_DEFINITIONS(-DUSE_LIBICONV) SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -munaligned-access -fpack-struct=8 -latomic -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") - IF (NOT TD_ARM) - EXIT () - ENDIF () +ENDIF () + +IF (TD_ARM_64) + ADD_DEFINITIONS(-D_TD_ARM_64_) + ADD_DEFINITIONS(-D_TD_ARM_) + SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") +ENDIF () + +IF (TD_ARM_32) + ADD_DEFINITIONS(-D_TD_ARM_32_) + ADD_DEFINITIONS(-D_TD_ARM_) + SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") +ENDIF () + +IF (TD_MIPS_64) + ADD_DEFINITIONS(-D_TD_MIPS_64_) + SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") +ENDIF () + +IF (TD_MIPS_32) + ADD_DEFINITIONS(-D_TD_MIPS_32_) + SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE") +ENDIF () + +IF (TD_APLHINE) + SET(COMMON_FLAGS "${COMMON_FLAGS} -largp") + link_libraries(/usr/lib/libargp.a) + ADD_DEFINITIONS(-D_ALPINE) ENDIF () IF (TD_LINUX) ADD_DEFINITIONS(-DLINUX) + ADD_DEFINITIONS(-D_LINUX) ADD_DEFINITIONS(-D_TD_LINUX) ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT) @@ -94,12 +89,9 @@ IF (TD_LINUX) SET(GCC_COVERAGE_LINK_FLAGS "-lgcov --coverage") SET(COMMON_FLAGS "${COMMON_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}") ENDIF () -ENDIF () -IF (TD_APLHINE) - SET(COMMON_FLAGS "${COMMON_FLAGS} -largp") - link_libraries(/usr/lib/libargp.a) - ADD_DEFINITIONS(-D_ALPINE) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) ENDIF () IF (TD_DARWIN_64) @@ -124,6 +116,12 @@ IF (TD_WINDOWS) SET(DEBUG_FLAGS "/Zi /W3 /GL") SET(RELEASE_FLAGS "/W0 /GL") ENDIF () + + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/wepoll/inc) + INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MsvcLibX/include) ENDIF () IF (TD_WINDOWS_64) @@ -136,3 +134,9 @@ IF (TD_WINDOWS_32) ADD_DEFINITIONS(-D_TD_WINDOWS_32) ENDIF () +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) + +MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID}) diff --git a/cmake/install.inc b/cmake/install.inc index 8d3acde45d1f614657b23ec563a511a0c67a9f20..98a60ace7b9fe1a9a83df7b9c5f9e69306d5b663 100755 --- a/cmake/install.inc +++ b/cmake/install.inc @@ -27,7 +27,7 @@ ELSEIF (TD_WINDOWS_64) #INSTALL(TARGETS taos RUNTIME DESTINATION driver) #INSTALL(TARGETS shell RUNTIME DESTINATION .) IF (TD_MVN_INSTALLED) - INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-1.0.2-dist.jar DESTINATION connector/jdbc) + INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.0-dist.jar DESTINATION connector/jdbc) ENDIF () ELSE () INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/libtaos.dll DESTINATION driver) diff --git a/cmake/platform.inc b/cmake/platform.inc index 07282e34cacbde22dd16ed04151549bf6130b51e..4cb6262471f580f0734f5adb1526b0626d2b4854 100755 --- a/cmake/platform.inc +++ b/cmake/platform.inc @@ -15,42 +15,18 @@ PROJECT(TDengine) # Set macro definitions according to os platform SET(TD_LINUX FALSE) -SET(TD_LINUX_64 FALSE) -SET(TD_LINUX_32 FALSE) -SET(TD_ARM FALSE) -SET(TD_ARM_64 FALSE) -SET(TD_ARM_32 FALSE) -SET(TD_MIPS FALSE) -SET(TD_MIPS_64 FALSE) -SET(TD_MIPS_32 FALSE) + SET(TD_LINUX_64 FALSE) + SET(TD_LINUX_32 FALSE) + SET(TD_ARM_64 FALSE) + SET(TD_ARM_32 FALSE) + SET(TD_MIPS_64 FALSE) + SET(TD_MIPS_32 FALSE) + SET(TD_APLHINE FALSE) SET(TD_WINDOWS FALSE) -SET(TD_WINDOWS_64 FALSE) -SET(TD_WINDOWS_32 FALSE) -SET(TD_DARWIN_64 FALSE) -SET(TD_APLHINE FALSE) - -# if generate ARM version: -# cmake -DCPUTYPE=aarch32 .. or cmake -DCPUTYPE=aarch64 -IF (${CPUTYPE} MATCHES "aarch32") - SET(TD_ARM TRUE) - SET(TD_ARM_32 TRUE) - SET(TD_PAGMODE_LITE TRUE) - MESSAGE(STATUS "input cpuType: aarch32") -ELSEIF (${CPUTYPE} MATCHES "aarch64") - SET(TD_ARM TRUE) - SET(TD_ARM_64 TRUE) - MESSAGE(STATUS "input cpuType: aarch64") -ELSEIF (${CPUTYPE} MATCHES "mips64") - SET(TD_MIPS TRUE) - SET(TD_MIPS_64 TRUE) - MESSAGE(STATUS "input cpuType: mips64") -ELSEIF (${CPUTYPE} MATCHES "x64") - MESSAGE(STATUS "input cpuType: x64") -ELSEIF (${CPUTYPE} MATCHES "x86") - MESSAGE(STATUS "input cpuType: x86") -ELSE () - MESSAGE(STATUS "input cpuType unknown " ${CPUTYPE}) -ENDIF () + SET(TD_WINDOWS_64 FALSE) + SET(TD_WINDOWS_32 FALSE) +SET(TD_DARWIN FALSE) + SET(TD_DARWIN_64 FALSE) IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") # @@ -66,12 +42,8 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") MESSAGE(STATUS "The current platform is Linux 64-bit") ELSEIF (${CMAKE_SIZEOF_VOID_P} MATCHES 4) SET(TD_LINUX_32 TRUE) - IF (TD_ARM) - MESSAGE(STATUS "The current platform is Linux 32-bit") - ELSE () - MESSAGE(FATAL_ERROR "The current platform is Linux 32-bit, but no ARM not supported yet") - EXIT () - ENDIF () + MESSAGE(STATUS "The current platform is Linux 32-bit") + ELSE () MESSAGE(FATAL_ERROR "The current platform is Linux neither 32-bit nor 64-bit, not supported yet") EXIT () @@ -82,6 +54,7 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux") MESSAGE(STATUS "The current OS is Alpine, append extra flags") ENDIF() ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(TD_DARWIN TRUE) IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8) SET(TD_DARWIN_64 TRUE) MESSAGE(STATUS "The current platform is Darwin 64-bit") @@ -103,3 +76,25 @@ ELSE() MESSAGE(FATAL_ERROR "The current platform is not Linux/Darwin/Windows, stop compile") EXIT () ENDIF () + +# if generate ARM version: +# cmake -DCPUTYPE=aarch32 .. or cmake -DCPUTYPE=aarch64 +IF (${CPUTYPE} MATCHES "aarch32") + SET(TD_LINUX TRUE) + SET(TD_ARM_32 TRUE) + MESSAGE(STATUS "input cpuType: aarch32") +ELSEIF (${CPUTYPE} MATCHES "aarch64") + SET(TD_LINUX TRUE) + SET(TD_ARM_64 TRUE) + MESSAGE(STATUS "input cpuType: aarch64") +ELSEIF (${CPUTYPE} MATCHES "mips64") + SET(TD_LINUX TRUE) + SET(TD_MIPS_64 TRUE) + MESSAGE(STATUS "input cpuType: mips64") +ELSEIF (${CPUTYPE} MATCHES "x64") + MESSAGE(STATUS "input cpuType: x64") +ELSEIF (${CPUTYPE} MATCHES "x86") + MESSAGE(STATUS "input cpuType: x86") +ELSE () + MESSAGE(STATUS "input cpuType unknown " ${CPUTYPE}) +ENDIF () diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index f5911ca0c9e81eb3d51278cbf148014e07784125..64930b29d2880ba70348e1fd50c4bd953ba2d980 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -7,8 +7,9 @@ ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(iconv) ADD_SUBDIRECTORY(lz4) ADD_SUBDIRECTORY(cJson) -#ADD_SUBDIRECTORY(MsvcLibX) +ADD_SUBDIRECTORY(wepoll) +ADD_SUBDIRECTORY(MsvcLibX) -IF (NOT TD_WINDOWS) +IF (TD_LINUX) ADD_SUBDIRECTORY(MQTT-C) ENDIF () \ No newline at end of file diff --git a/deps/MsvcLibX/CMakeLists.txt b/deps/MsvcLibX/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc77a3b447d337cf0b1e4343c9fb2f9d97fd423c --- /dev/null +++ b/deps/MsvcLibX/CMakeLists.txt @@ -0,0 +1,8 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_WINDOWS) + INCLUDE_DIRECTORIES(include) + AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(MsvcLibXw64 ${SRC}) +ENDIF () diff --git a/deps/MsvcLibX/include/msvcDebugm.h b/deps/MsvcLibX/include/msvcDebugm.h new file mode 100644 index 0000000000000000000000000000000000000000..5b3c38f45be3168b6d3b52a9600fd98e0e524c15 --- /dev/null +++ b/deps/MsvcLibX/include/msvcDebugm.h @@ -0,0 +1,206 @@ +/*****************************************************************************\ +* * +* Filename: debugm.h * +* * +* Description: Debug macros * +* * +* Notes: Macros inspired by my Tcl/Bash/Batch debugging libraries. * +* The idea is to output the function call stack, indenting * +* subroutines proportionally to the call depth. * +* To ease reading the output, it must look like real C code.* +* * +* DEBUG_GLOBALS Define global variables used by macros below: * +* int iDebug = FALSE; Global variable enabling debug output if TRUE.* +* int iIndent = 0; Global variable controlling debug indentation.* +* * +* DEBUG_PRINTF((format, ...)) Print a debug string if debug is on. * +* The double parenthesis are necessary * +* because C90 does not support macros * +* with variable list of arguments. * +* DEBUG_ENTER((format, ...)) Print a function name and arguments. * +* Increase indentation of further calls.* +* It's the caller's responsibility to * +* format the routine name and arguments.* +* DEBUG_LEAVE((format, ...)) Print a function return value. * +* Decrease indentation of further calls.* +* It's the caller's responsibility to * +* format the return instruction & value.* +* * +* Any call to DEBUG_ENTER MUST be matched by one call to * +* DEBUG_LEAVE or RETURN_... when the function returns. * * +* * +* History: * +* 2012-01-16 JFL jf.larvoire@hp.com created this file. * +* 2012-02-03 JFL Renamed DEBUG_IF_IS_ON DEBUG_CODE_IF_ON. * +* Renamed file from debug.h to debugm.h because of a file * +* name collision with another library on my PC. * +* 2014-02-10 JFL Added macros for an extra debug mode. * +* 2014-07-02 JFL renamed macro RETURN() as RETURN_CONST(), and defined * +* new macro RETURN() to return nothing. * +* Idem for RETURN_COMMENT() as RETURN_CONST_COMMENT(). * +* 2016-09-09 JFL Flush every DEBUG_PRINTF output, to make sure to see * +* every debug string printed before a program crash. * +* 2016-09-13 JFL Added macros DEBUG_WSTR2NEWUTF8() and DEBUG_FREEUTF8(). * +* 2016-10-04 JFL Added macros DEBUG_OFF(), DEBUG_MORE(), DEBUG_LESS(). * +* Allow using DEBUG_ON()/MORE()/LESS()/OFF() in release mode. +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _DEBUGM_H +#define _DEBUGM_H 1 + +#include /* Macros use printf */ + +#ifdef _MSC_VER +#pragma warning(disable:4127) /* Avoid warnings on while(0) below */ +#endif + +#define DEBUG_DO(code) do {code} while (0) +#define DEBUG_DO_NOTHING() do {} while (0) + +/* Conditional compilation based on Microsoft's standard _DEBUG definition */ +#if defined(_DEBUG) + +#define DEBUG_VERSION " Debug" + +#define DEBUG_GLOBALS \ +int iDebug = 0; /* Global variable enabling debug output if TRUE. */ \ +int iIndent = 0; /* Global variable controlling debug indentation. */ + +extern int iDebug; /* Global variable enabling of disabling debug messages */ +#define DEBUG_ON() iDebug = 1 /* Turn debug mode on */ +#define DEBUG_MORE() iDebug += 1 /* Increase the debug level */ +#define DEBUG_LESS() iDebug -= 1 /* Decrease the debug level */ +#define DEBUG_OFF() iDebug = 0 /* Turn debug mode off */ +#define DEBUG_IS_ON() (iDebug > 0) /* Check if the debug mode is enabled */ +#define XDEBUG_ON() iDebug = 2 /* Turn extra debug mode on. Same as calling DEBUG_MORE() twice. */ +#define XDEBUG_IS_ON() (iDebug > 1) /* Check if the extra debug mode is enabled */ + +#define DEBUG_CODE(code) code /* Code included in the _DEBUG version only */ +#define DEBUG_CODE_IF_ON(code) DEBUG_CODE(if (DEBUG_IS_ON()) {code}) /* + Debug code executed if debug mode is on */ +#define XDEBUG_CODE_IF_ON(code) DEBUG_CODE(if (XDEBUG_IS_ON()) {code}) /* + Debug code executed if extra debug mode is on */ + +extern int iIndent; /* Debug messages indentation */ +#define DEBUG_INDENT_STEP 2 /* How many spaces to add for each indentation level */ +#define DEBUG_PRINT_INDENT() printf("%*s", iIndent, "") + +/* Debug code, conditionally printing a string based on global variable 'debug' */ +/* The enter and leave variants print, then respectively increase or decrease indentation, + to make recursive calls easier to review. */ +#define DEBUG_FPRINTF(args) DEBUG_DO(if (DEBUG_IS_ON()) {DEBUG_PRINT_INDENT(); fprintf args;}) +#define DEBUG_PRINTF(args) DEBUG_DO(if (DEBUG_IS_ON()) {DEBUG_PRINT_INDENT(); printf args; fflush(stdout);}) +#define XDEBUG_PRINTF(args) DEBUG_DO(if (XDEBUG_IS_ON()) {DEBUG_PRINT_INDENT(); printf args; fflush(stdout);}) +#define DEBUG_ENTER(args) DEBUG_DO(DEBUG_PRINTF(args); iIndent += DEBUG_INDENT_STEP;) +#define DEBUG_LEAVE(args) DEBUG_DO(DEBUG_PRINTF(args); iIndent -= DEBUG_INDENT_STEP;) + +#define DEBUG_RETURN_INT(i, comment) DEBUG_DO(int DEBUG_i = (i); \ + DEBUG_LEAVE(("return %d; // " comment "\n", DEBUG_i)); return DEBUG_i;) + +/* print return instruction and decrease indent */ +#define RETURN() DEBUG_DO(DEBUG_LEAVE(("return;\n")); return;) +#define RETURN_CONST(value) DEBUG_DO(DEBUG_LEAVE(("return %s;\n", #value)); return value;) +#define RETURN_INT(i) DEBUG_DO(int DEBUG_i = (i); \ + DEBUG_LEAVE(("return %d;\n", DEBUG_i)); return DEBUG_i;) +#define RETURN_STRING(s) DEBUG_DO(char *DEBUG_s = (s); \ + DEBUG_LEAVE(("return \"%s\";\n", DEBUG_s)); return DEBUG_s;) +#define RETURN_CHAR(c) DEBUG_DO(char DEBUG_c = (c); \ + DEBUG_LEAVE(("return '%c';\n", DEBUG_c)); return DEBUG_c;) +#define RETURN_BOOL(b) DEBUG_DO(int DEBUG_b = (b); \ + DEBUG_LEAVE(("return %s;\n", DEBUG_b ? "TRUE" : "FALSE")); return DEBUG_b;) + +#define RETURN_COMMENT(args) DEBUG_DO(DEBUG_LEAVE(("return; // ")); \ + if (DEBUG_IS_ON()) printf args; return;) +#define RETURN_CONST_COMMENT(value, args) DEBUG_DO(DEBUG_LEAVE(("return %s; // ", #value)); \ + if (DEBUG_IS_ON()) printf args; return value;) +#define RETURN_INT_COMMENT(i, args) DEBUG_DO(int DEBUG_i = (i); \ + DEBUG_LEAVE(("return %d; // ", DEBUG_i)); if (DEBUG_IS_ON()) printf args; return DEBUG_i;) +#define RETURN_BOOL_COMMENT(b, args) DEBUG_DO(int DEBUG_b = (b); \ + DEBUG_LEAVE(("return %s; // ", DEBUG_b ? "TRUE" : "FALSE")); if (DEBUG_IS_ON()) printf args; return DEBUG_b;) + +#else /* !defined(_DEBUG) */ + +#define DEBUG_VERSION "" /* Non debug version: Simply don't say it */ + +#define DEBUG_GLOBALS + +#define DEBUG_ON() (void)0 +#define DEBUG_MORE() (void)0 +#define DEBUG_LESS() (void)0 +#define DEBUG_OFF() (void)0 +#define DEBUG_IS_ON() 0 +#define XDEBUG_IS_ON() 0 +#define DEBUG_CODE(code) /* Code included in _DEBUG version only */ +#define DEBUG_CODE_IF_ON(code) /* Code included in _DEBUG version only */ +#define XDEBUG_CODE_IF_ON(code) /* Code included in _DEBUG version only */ + +#define DEBUG_PRINT_INDENT() DEBUG_DO_NOTHING() /* Print call-depth spaces */ + +#define DEBUG_FPRINTF(args) DEBUG_DO_NOTHING() /* Print a debug string to a stream */ +#define DEBUG_PRINTF(args) DEBUG_DO_NOTHING() /* Print a debug string to stdout */ +#define XDEBUG_PRINTF(args) DEBUG_DO_NOTHING() /* Print an extra debug string to stdout */ +#define DEBUG_ENTER(args) DEBUG_DO_NOTHING() /* Print and increase indent */ +#define DEBUG_LEAVE(args) DEBUG_DO_NOTHING() /* Print and decrease indent */ + +#define DEBUG_RETURN_INT(i, comment) return(i) + +/* print return instruction and decrease indent */ +#define RETURN() return +#define RETURN_CONST(value) return(value) +#define RETURN_INT(i) return(i) +#define RETURN_STRING(s) return(s) +#define RETURN_CHAR(c) return(c) +#define RETURN_BOOL(b) return(b) + +#define RETURN_COMMENT(args) return +#define RETURN_CONST_COMMENT(value, args) return(value) +#define RETURN_INT_COMMENT(i, args) return(i) +#define RETURN_BOOL_COMMENT(b, args) return(b) + +#endif /* defined(_DEBUG) */ + +#define STRINGIZE(s) #s /* Convert a macro name to a string */ +#define VALUEIZE(s) STRINGIZE(s) /* Convert a macro value to a string */ +#define MACRODEF(s) "#define " #s " " STRINGIZE(s) + +/* Display a macro name and value. */ +#define DEBUG_PRINT_MACRO(name) DEBUG_DO( \ + const char *pszName = #name; /* Don't use STRINGIZE because we're already inside a macro */ \ + const char *pszValue = STRINGIZE(name); /* Don't use VALUEIZE because we're already inside a macro */ \ + DEBUG_PRINT_INDENT(); \ + if (strcmp(pszName, pszValue)) { \ + printf("#define %s %s\n", pszName, pszValue); \ + } else { /* Not 100% certain, but most likely. */ \ + printf("#undef %s\n", pszName); \ + } \ +) + +#ifdef _WIN32 + +/* Helper macros for displaying Unicode strings */ +#define DEBUG_WSTR2UTF8(from, to, toSize) DEBUG_CODE( \ + WideCharToMultiByte(CP_UTF8, 0, from, lstrlenW(from)+1, to, toSize, NULL, NULL); \ +) + +/* Dynamically allocate a new buffer, then convert a Unicode string to UTF-8 */ +/* The dynamic allocation is useful in modules using lots of UTF-16 pathnames. + This avoids having many local buffers of length UTF8_PATH_MAX, which may + make the stack grow too large and overflow. */ +#define DEBUG_WSTR2NEWUTF8(pwStr, pUtf8) \ + DEBUG_CODE( \ + do { \ + int nUtf8 = (int)lstrlenW(pwStr) * 2 + 1; \ + pUtf8 = malloc(nUtf8); \ + DEBUG_WSTR2UTF8(pwStr, pUtf8, nUtf8); \ + } while (0); \ + ) /* DEBUG_FREE(pUtf8) MUST be used to free the UTF-8 string after use, else there will be a memory leak */ + +#define DEBUG_FREEUTF8(pUtf8) DEBUG_CODE(free(pUtf8)) + +#endif /* defined(_WIN32) */ + +#endif /* !defined(_DEBUGM_H) */ + diff --git a/deps/MsvcLibX/include/msvcDirect.h b/deps/MsvcLibX/include/msvcDirect.h new file mode 100644 index 0000000000000000000000000000000000000000..31017ce50cfc36457176d148f9188bc3c15cb067 --- /dev/null +++ b/deps/MsvcLibX/include/msvcDirect.h @@ -0,0 +1,27 @@ +/*****************************************************************************\ +* * +* Filename: direct.h * +* * +* Description: MsvcLibX extensions to direct.h. * +* * +* Notes: * +* * +* History: * +* 2014-03-24 JFL Created this file, with content moved from unistd.h. * +* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_DIRECT_H +#define _MSVCLIBX_DIRECT_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +#undef mkdir /* This MSVC macro is incompatible with mkdir() function in unistd.h */ + +#endif /* defined(_MSVCLIBX_DIRECT_H) */ + diff --git a/deps/MsvcLibX/include/msvcDirent.h b/deps/MsvcLibX/include/msvcDirent.h new file mode 100644 index 0000000000000000000000000000000000000000..db146a599811d52c0f94ddf937dc74c961598d74 --- /dev/null +++ b/deps/MsvcLibX/include/msvcDirent.h @@ -0,0 +1,282 @@ +/*****************************************************************************\ +* * +* Filename: dirent.h * +* * +* Description: DOS/WIN32 port of standard C library's dirent.h. * +* * +* Notes: There are also remains of an OS/2 implementation here. * +* This code did work c. 1990, in an OS/2 1.3 port of dirc.c.* +* It's not maintained anymore, and unlikely to still work. * +* Left in as a historic reference, in the very unlikely * +* case somebody wants to revive it. * +* * +* History: * +* 2012-01-09 JFL Created this file, based on dirc and other programs. * +* 2013-03-09 JFL Rewrote the stat/fstat/lstat and fseeko/ftello definitions* +* based on _FILE_OFFSET_BITS, _LARGEFILE_SOURCE, and * +* _LARGEFILE_SOURCE64 definitions. * +* 2014-02-06 JFL Moved stat extensions to statx.h. * +* 2014-02-27 JFL Use a WIN32_FIND_DATAW in Windows, to support UTF-8 names.* +* 2014-03-20 JFL Restructured Windows opendir and readdir functions into * +* Wide and MultiByte versions, and changed the Unicode and * +* Ansi versions to macros. * +* 2014-06-06 JFL Fixed macro _D_EXACT_NAMLEN(). * +* 2015-12-07 JFL Added the conditional definition of symlink constants, so * +* that our code builds even in XP and older Windows SDKs. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _DIRENT_H +#define _DIRENT_H 1 + +#include "msvclibx.h" + +#define _DIRENT_FOR_DOS_WINDOWS /* Uniquely identify this module */ + +#include +#include +#include +#include +#include + +#ifndef ENAMETOOLONG /* Not defined in DOS' errno.h */ +#define ENAMETOOLONG 38 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macros to extract size information from a struct dirent */ +#define _D_EXACT_NAMLEN(d) (strlen((d)->d_name)) /* Name length, not including NUL */ + +#define _DIRENT_HAVE_D_TYPE /* We commit to providing this field */ + +/************************ MS-DOS-specific definitions ************************/ + +#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ + +#include + +#define NAME_MAX 12 + +#pragma pack(1) +struct _fileinfo { /* MS-DOS structure returning file search results */ + uint8_t fiReserved[21]; + uint8_t fiAttribute; /* Attributes of file found */ + uint16_t fiFileTime; /* Time of last write */ + uint16_t fiFileDate; /* Time of last write */ + uint32_t fiSize; /* File Size */ + char fiFileName[13]; /* File name and extension */ +}; +#pragma pack() +typedef struct _fileinfo fileinfo; + +#pragma pack(1) +struct dirent { /* Standard C library structure returning directory entries. */ + /* Standard fields */ + _ino_t d_ino; /* We don't need it, but it's required by the spec */ + unsigned char d_type; /* File type. Values defined in macros DT_xxxx */ + /* unsigned char d_namlen; /* File name length, not including NUL */ + /* OS-specific extensions (allowed by the Posix specification) */ + /* Matches exactly the struc _fileinfo above, to avoid doing any copying */ + uint8_t d_reserved[21]; + uint8_t d_attribs; /* Attribute of file found */ + uint16_t d_time; /* Time of last write */ + uint16_t d_date; /* Time of last write */ + uint32_t d_filesize; /* File Size */ + /* Standard field: The file name, which must be last in the dirent structure */ + char d_name[NAME_MAX+1]; /* Null-terminated file name. Must be last */ +}; +#pragma pack() + +#pragma pack(1) +struct _dirhandle { /* Private structure, not for use by users */ + struct dirent sDirent; + /* char dta_buf[128]; /* Protection area, in case MS-DOS uses the whole DTA, and not just the struct _fileinfo ahead of it. */ + char wildcards[4]; /* Leave room for the "\*.*" that we append initially. This field MUST follow sDirent. */ + char first; /* Tracks if this is the first search call */ +}; +#pragma pack() + +/* Macros to extract size information from a struct dirent */ +#define _D_ALLOC_NAMLEN(d) 13 /* Upper bound of the block size to alloc for a name */ + +/* MS-DOS compatible functions for searching with a specific attribute */ +int srch1st(char *pszFile, uint16_t wAttr, fileinfo *pFI); /* Search first matching file */ +int srchnext(fileinfo *pFI); /* Search next matching file */ +#define DOS_SEARCH_FUNCTIONS_DEFINED 1 + +#endif /* defined(_MSDOS) */ + +/************************ Win32-specific definitions *************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#ifndef WINVER +#define WINVER 0x0400 +#endif + +#include +#include + +/* Add symlink definitions, that may be missing in XP and older Windows SDKs */ +#ifndef IO_REPARSE_TAG_SYMLINK +#define IO_REPARSE_TAG_SYMLINK 0xA000000CL +#endif +#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY +#define SYMBOLIC_LINK_FLAG_DIRECTORY 1 +#endif +#ifndef FSCTL_SET_REPARSE_POINT +#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#endif +#ifndef FSCTL_GET_REPARSE_POINT +#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif +#ifndef FSCTL_DELETE_REPARSE_POINT +#define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#endif + +#define NAME_MAX (4 * FILENAME_MAX) /* Worst case using UTF-8 encoding: 4 bytes/WCHAR */ + +struct dirent { /* Structure used to return information about directory entries. */ + /* OS-specific extensions */ + uint32_t d_attribs; + uint32_t d_ReparseTag; + FILETIME d_CreationTime; + FILETIME d_LastAccessTime; + FILETIME d_LastWriteTime; + uint64_t d_filesize; + char d_shortname[14*sizeof(WCHAR)]; + /* Standard fields */ + _ino_t d_ino; /* We don't need it, but it's required by the spec */ + unsigned char d_type; /* File type. Values defined in macros DT_xxxx */ + /* unsigned char d_namlen; /* File name length, not including NUL */ + char d_name[(NAME_MAX+1)*sizeof(WCHAR)]; /* Null-terminated file name */ +}; + +struct _dirhandle { /* Private structure, not for use by users */ + struct dirent sDirent; + WCHAR wszDirName[MAX_PATH+1]; /* Null-terminated directory name */ + HANDLE hFindFile; /* Search handle */ + WIN32_FIND_DATAW wfd; /* Where Win32 will store the file information */ +}; + +/* Macros to extract size information from a struct dirent */ +#define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN(d)+1) /* Upper bound of the block size to alloc for a name */ + +#endif /* defined(_WIN32) */ + +/************************* OS/2-specific definitions *************************/ + +#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */ + +#include + +#define INCL_DOSFILEMGR +#define INCL_DOSMISC +#define INCL_VIO +#include "os2.h" + +#define NAME_MAX CCHMAXPATHCOMP + +struct dirent { /* Structure used to return information about directory entries. */ + _ino_t d_ino; /* We don't need it, but it's required by the spec */ + /* Non standard extensions, to ease adapting old DOS/WIN32 apps */ + uintmax_t d_filesize; /* File size */ + uint16_t time; /* MS-DOS time */ + uint16_t date; /* MS-DOS date */ + uint8_t attribs; /* Attributes, the MS-DOS way */ + /* Standard fields */ + unsigned char d_type; /* File type. Values defined in macros DT_xxxx */ + /* unsigned char d_namlen; /* File name length, not including NUL */ + char d_name[NAME_MAX+1]; /* Null-terminated file name. Must be last */ +}; + +struct _dirhandle { /* Private structure, not for use by users */ + struct dirent sDirent; + short hDir; /* Directory handle */ + FILEFINDBUF buf; /* Where OS/2 will store the file information */ +}; + +/* Macros to extract size information from a struct dirent */ +#define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN(d)+1) /* Upper bound of the block size to alloc for a name */ + +#endif /* defined(_OS2) */ + +/********************** End of OS-specific definitions ***********************/ + +typedef struct _dirhandle DIR; /* Directory enumerator handle */ +typedef struct dirent _dirent; /* Directory entry */ + +#define MAXNAMELEN NAME_MAX /* Alias used by some Unix versions */ + +/* File types for struct dirent d_type. Must match the S_IFMT field in sys/stat.h. */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 /* Fifo (not used in DOS/Windows dirs) */ +#define DT_CHR 2 /* Character device (not used in DOS/Windows) */ +#define DT_DIR 4 /* Directory */ +#define DT_BLK 6 /* Block device (not used in DOS/Windows) */ +#define DT_REG 8 /* Normal file */ +#define DT_LNK 10 /* Symbolic link */ +#define DT_SOCK 12 /* Socket (not used in DOS/Windows dirs) */ +#define DT_VOLID 15 /* Volume ID (non-standard extension for MS-DOS FAT) */ + +/* Functions operating on directories */ +#if defined(_MSDOS) + +extern DIR *opendir(const char *name); /* Open a directory */ +extern int closedir(DIR *pDir); /* Close the directory. Return 0 if successful, -1 if not. */ +extern _dirent *readdir(DIR *pDir); /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */ + +#elif defined(_WIN32) + +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define opendir opendirU +#define readdir readdirU +#define scandir scandirU +#else /* _ANSI_SOURCE */ +#define opendir opendirA +#define readdir readdirA +#define scandir scandirA +#endif +extern DIR *opendirW(const WCHAR *name); /* Open a directory - Wide char version */ +extern DIR *opendirM(const char *name, UINT cp); /* Open a directory - MultiByte char version */ +#define opendirA(name) opendirM(name, CP_ACP) /* Open a directory - ANSI version */ +#define opendirU(name) opendirM(name, CP_UTF8) /* Open a directory - UTF-8 version */ +extern int closedir(DIR *pDir); /* Close the directory. Return 0 if successful, -1 if not. */ +extern _dirent *readdirW(DIR *pDir); /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */ +extern _dirent *readdirM(DIR *pDir, UINT cp); /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */ +#define readdirA(pDir) readdirM(pDir, CP_ACP) /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */ +#define readdirU(pDir) readdirM(pDir, CP_UTF8) /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */ + +#endif /* defined(_WIN32) */ + +/* extern int readdir_r(DIR *pDir, _dirent *__entry, _dirent **__result); /* Reentrant readdir */ +/* extern void rewinddir(DIR *pDir); /* Rewind DIRP to the beginning of the directory. */ +/* extern void seekdir(DIR *pDir, long lPos); /* Seek to position POS on DIRP. */ +/* extern long telldir(DIR *pDir); /* Return the current position of DIRP. */ +/* extern int dirfd(DIR *pDir); /* Return the file descriptor used by DIRP. */ + +/* Scan the directory dir, calling cbSelect() on each directory entry. + Entries for which cbSelect() returns nonzero are individually malloc'd, + sorted using qsort with cbCompare(), and collected in a malloc'd array in + *namelist. Returns the number of entries selected, or -1 on error. */ +extern int scandir(const char *dir, + _dirent ***namelist, + int (*cbSelect) (const _dirent *), + int (__cdecl *cbCompare) (const _dirent **, + const _dirent **)); + +/* Function to compare two `struct dirent's alphabetically. */ +extern int __cdecl alphasort (const _dirent **ppDE1, const _dirent **ppDEe2); +/* extern int versionsort (const _dirent **ppDE1, const _dirent **ppDEe2); */ + +#ifdef __cplusplus +} +#endif + +#endif /* defined(_DIRENT_H) */ + diff --git a/deps/MsvcLibX/include/msvcError.h b/deps/MsvcLibX/include/msvcError.h new file mode 100644 index 0000000000000000000000000000000000000000..9a0a790a9af3caeb761abc6aa06cc152b6fb889a --- /dev/null +++ b/deps/MsvcLibX/include/msvcError.h @@ -0,0 +1,25 @@ +/*****************************************************************************\ +* * +* Filename: error.h * +* * +* Description: DOS/WIN32 port of the GNU CoreUtils library error funct. * +* * +* Notes: Gotcha: * +* The Windows SDK also contains a file called error.h * +* See C:\Program Files\Microsoft SDKs\Windows\v7.0\INCLUDE * +* * +* History: * +* 2012-10-21 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _ERROR_H_ +#define _ERROR_H_ + +#include "msvclibx.h" + +extern void error(int status, int errnum, const char *format, ...); + +#endif diff --git a/deps/MsvcLibX/include/msvcFadvise.h b/deps/MsvcLibX/include/msvcFadvise.h new file mode 100644 index 0000000000000000000000000000000000000000..89600ebd058cd59b52278ef1bdcfdc191a08eaff --- /dev/null +++ b/deps/MsvcLibX/include/msvcFadvise.h @@ -0,0 +1,30 @@ +/*****************************************************************************\ +* * +* Filename: fadvise.h * +* * +* Description: WIN32 makeshift version of Coreutils' fadvise.h. * +* * +* Notes: Gives hints to the kernel about future uses of a file. * +* Define constants, and replace functions by void macros. * +* * +* History: * +* 2012-10-17 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +enum fadvice_t { + FADVISE_NORMAL, + FADVISE_SEQUENTIAL, + FADVISE_NOREUSE, + FADVISE_DONTNEED, + FADVISE_WILLNEED, + FADVISE_RANDOM +}; + +/* void fdadvise(int fd, off_t offset, off_t len, fadvice_t advice) */ +#define fdadvise(fd, offset, len, advice) + +/* void fadvise(FILE *fp, fadvice_t advice) */ +#define fadvise(fp, advice) diff --git a/deps/MsvcLibX/include/msvcFcntl.h b/deps/MsvcLibX/include/msvcFcntl.h new file mode 100644 index 0000000000000000000000000000000000000000..fc981b5fc9304e1d5f8f8656aadd3f8b36e9bef5 --- /dev/null +++ b/deps/MsvcLibX/include/msvcFcntl.h @@ -0,0 +1,40 @@ +/*****************************************************************************\ +* * +* Filename: fcntl.h * +* * +* Description: MsvcLibX extensions to fcntl.h. * +* * +* Notes: * +* * +* History: * +* 2017-02-16 JFL Created this file. * +* * +* Copyright 2017 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_FCNTL_H +#define _MSVCLIBX_FCNTL_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +/* Microsoft defines _open() in io.h */ +#include + +#if defined(_MSDOS) +#define open _open +#endif + +#if defined(_WIN32) +extern int openA(const char *, int, ...); /* MsvcLibX ANSI version of open */ +extern int openU(const char *, int, ...); /* MsvcLibX UTF-8 version of open */ +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define open openU +#else /* _ANSI_SOURCE */ +#define open openA +#endif /* defined(_UTF8_SOURCE) */ +#endif /* defined(_WIN32) */ + +#endif /* defined(_MSVCLIBX_FCNTL_H) */ diff --git a/deps/MsvcLibX/include/msvcFnmatch.h b/deps/MsvcLibX/include/msvcFnmatch.h new file mode 100644 index 0000000000000000000000000000000000000000..4b7d15b2e8c9e12abab7a3d5b21726ffb99c694e --- /dev/null +++ b/deps/MsvcLibX/include/msvcFnmatch.h @@ -0,0 +1,50 @@ +/*****************************************************************************\ +* * +* Filename: fnmatch.h * +* * +* Description: DOS/WIN32 port of standard C library's fnmatch.h. * +* * +* Notes: Reference for fnmatch and glob: * +* http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_9.html * +* * +* History: * +* 2012-01-17 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#include "msvclibx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Bits set in the FLAGS argument to fnmatch() */ +#define FNM_PATHNAME 0x01 /* Wildcards don't match '/' or '\\' */ +#define FNM_FILE_NAME FNM_PATHNAME /* Equivalent GNU name */ +#define FNM_NOESCAPE 0x02 /* Backslashes don't quote special chars (Irrelevant in DOS/Windows) */ +#define FNM_PERIOD 0x04 /* Wildcards don't match leading dots */ +#define FNM_LEADING_DIR 0x08 /* Match up to the first '/' or '\\' */ +#define FNM_CASEFOLD 0x10 /* Case-insentitive comparison */ + +/* Values returned by fnmatch() */ +#define FNM_MATCH 0 /* Non standard, but makes fnmatch.c more readable */ +#define FNM_NOMATCH 1 + +/* Value returned by fnmatch() if unsupported */ +#define FNM_NOSYS (-1) + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch(const char *pszPattern, const char *pszName, int iFlags); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_FNMATCH_H) */ + diff --git a/deps/MsvcLibX/include/msvcGetopt.h b/deps/MsvcLibX/include/msvcGetopt.h new file mode 100644 index 0000000000000000000000000000000000000000..fa0d75b3ff6a95ab7054fefb691c97f44ba6b429 --- /dev/null +++ b/deps/MsvcLibX/include/msvcGetopt.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +/* + * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#ifdef __cplusplus +extern "C" { +#endif + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +int getopt_long(int, char * const *, const char *, + const struct option *, int *); + +extern int optreset; +extern char *optarg; +extern int opterr; +extern int optind; +extern int optopt; + +#ifdef __cplusplus +}; +#endif + +#endif /* !_GETOPT_H_ */ + diff --git a/deps/MsvcLibX/include/msvcIconv.h b/deps/MsvcLibX/include/msvcIconv.h new file mode 100644 index 0000000000000000000000000000000000000000..8ad5e2f67f47941ed5f08d4d7549c8a74118912a --- /dev/null +++ b/deps/MsvcLibX/include/msvcIconv.h @@ -0,0 +1,45 @@ +/*****************************************************************************\ +* * +* Filename iconv.h * +* * +* Description: WIN32 port of standard C library's iconv() * +* * +* Notes: Define here a number of routines, that will eventually * +* be used by iconv(). * +* * +* History: * +* 2014-02-27 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _ICONV_H +#define _ICONV_H 1 + +#include "msvclibx.h" + +#include + +#if defined(_MSDOS) + +/* Count the number of characters (not bytes!) in a string */ +/* For now, assume the # of characters is the same as the # of bytes */ +/* TO DO: Add support for DOS code pages! */ +#define CountCharacters(string, cp) (int)strlen(string) + +#endif /* defined(_MSDOS) */ + + +#if defined(_WIN32) + +#include + +int ConvertString(char *buf, size_t nBytes, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar); +int CountCharacters(const char *string, UINT cp); +char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar); + +#endif /* defined(_WIN32) */ + +#endif /* !defined(_ICONV_H) */ + diff --git a/deps/MsvcLibX/include/msvcInttypes.h b/deps/MsvcLibX/include/msvcInttypes.h new file mode 100644 index 0000000000000000000000000000000000000000..addc380ed0e0e65ab9209454589639da2dce49de --- /dev/null +++ b/deps/MsvcLibX/include/msvcInttypes.h @@ -0,0 +1,314 @@ +/*****************************************************************************\ +* * +* Filename inttypes.h * +* * +* Description ISO C9x compliant inttypes.h for Microsoft Visual Studio * +* * +* Notes TO DO: Move imaxdiv to its own C file. * +* * +* History * +* 2014-02-07 JFL Added definitions for PRIdMAX and PRIiMAX. * +* 2016-01-07 JFL Restructured and improved support for MS-DOS. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSC_VER +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif + +#ifndef _MSC_INTTYPES_H_ +#define _MSC_INTTYPES_H_ + +#include + +/* 7.8 Format conversion of integer types */ + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +/* 7.8.1 Macros for format specifiers */ + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) /* [ See footnote 185 at page 198 */ + +#if defined(_WIN64) +#define __I64_PREFIX "I64" +#define __I32_PREFIX "I32" +#define __PTR_PREFIX "I64" +#define __MAX_PREFIX "I64" +#elif defined(_WIN32) +#define __I64_PREFIX "I64" +#define __I32_PREFIX "I32" +#define __PTR_PREFIX "I32" +#define __MAX_PREFIX "I64" +#elif defined(_MSDOS) +#define __I64_PREFIX "ll" /* MSVC 1.5 actually ignores the second l */ +#define __I32_PREFIX "l" +#if defined(_M_I86CM) || defined(_M_I86LM) || defined(_M_I86HM) /* Long pointer memory models */ +#define __PTR_PREFIX "l" +#else /* Short pointer memory models */ +#define __PTR_PREFIX "" +#endif +#define __MAX_PREFIX "l" +#endif + +/* printf macros for integers */ +#define PRId8 "d" +#define PRIi8 "i" +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" + +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" + +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" + +#define PRIdLEAST16 PRId16 +#define PRIiLEAST16 PRIi16 +#define PRIoLEAST16 PRIo16 +#define PRIuLEAST16 PRIu16 +#define PRIxLEAST16 PRIx16 +#define PRIXLEAST16 PRIX16 + +#define PRIdFAST16 PRId16 +#define PRIiFAST16 PRIi16 +#define PRIoFAST16 PRIo16 +#define PRIuFAST16 PRIu16 +#define PRIxFAST16 PRIx16 +#define PRIXFAST16 PRIX16 + +#define PRId32 __I32_PREFIX "d" +#define PRIi32 __I32_PREFIX "i" +#define PRIo32 __I32_PREFIX "o" +#define PRIu32 __I32_PREFIX "u" +#define PRIx32 __I32_PREFIX "x" +#define PRIX32 __I32_PREFIX "X" + +#define PRIdLEAST32 PRId32 +#define PRIiLEAST32 PRIi32 +#define PRIoLEAST32 PRIo32 +#define PRIuLEAST32 PRIu32 +#define PRIxLEAST32 PRIx32 +#define PRIXLEAST32 PRIX32 + +#define PRIdFAST32 PRId32 +#define PRIiFAST32 PRIi32 +#define PRIoFAST32 PRIo32 +#define PRIuFAST32 PRIu32 +#define PRIxFAST32 PRIx32 +#define PRIXFAST32 PRIX32 + +#define PRId64 __I64_PREFIX "d" +#define PRIi64 __I64_PREFIX "i" +#define PRIo64 __I64_PREFIX "o" +#define PRIu64 __I64_PREFIX "u" +#define PRIx64 __I64_PREFIX "x" +#define PRIX64 __I64_PREFIX "X" + +#define PRIdLEAST64 PRId64 +#define PRIiLEAST64 PRIi64 +#define PRIoLEAST64 PRIo64 +#define PRIuLEAST64 PRIu64 +#define PRIxLEAST64 PRIx64 +#define PRIXLEAST64 PRIX64 + +#define PRIdFAST64 PRId64 +#define PRIiFAST64 PRIi64 +#define PRIoFAST64 PRIo64 +#define PRIuFAST64 PRIu64 +#define PRIxFAST64 PRIx64 +#define PRIXFAST64 PRIX64 + +#define PRIdMAX __MAX_PREFIX "d" +#define PRIiMAX __MAX_PREFIX "i" +#define PRIoMAX __MAX_PREFIX "o" +#define PRIuMAX __MAX_PREFIX "u" +#define PRIxMAX __MAX_PREFIX "x" +#define PRIXMAX __MAX_PREFIX "X" + +#define PRIdPTR __PTR_PREFIX "d" +#define PRIiPTR __PTR_PREFIX "i" +#define PRIoPTR __PTR_PREFIX "o" +#define PRIuPTR __PTR_PREFIX "u" +#define PRIxPTR __PTR_PREFIX "x" +#define PRIXPTR __PTR_PREFIX "X" + +/* scanf macros for integers */ +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" + +#define SCNdLEAST8 SCNd8 +#define SCNiLEAST8 SCNi8 +#define SCNoLEAST8 SCNo8 +#define SCNuLEAST8 SCNu8 +#define SCNxLEAST8 SCNx8 +#define SCNXLEAST8 SCNX8 + +#define SCNdFAST8 SCNd8 +#define SCNiFAST8 SCNi8 +#define SCNoFAST8 SCNo8 +#define SCNuFAST8 SCNu8 +#define SCNxFAST8 SCNx8 +#define SCNXFAST8 SCNX8 + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" + +#define SCNdLEAST16 SCNd16 +#define SCNiLEAST16 SCNi16 +#define SCNoLEAST16 SCNo16 +#define SCNuLEAST16 SCNu16 +#define SCNxLEAST16 SCNx16 +#define SCNXLEAST16 SCNX16 + +#define SCNdFAST16 SCNd16 +#define SCNiFAST16 SCNi16 +#define SCNoFAST16 SCNo16 +#define SCNuFAST16 SCNu16 +#define SCNxFAST16 SCNx16 +#define SCNXFAST16 SCNX16 + +#define SCNd32 __I32_PREFIX "d" +#define SCNi32 __I32_PREFIX "i" +#define SCNo32 __I32_PREFIX "o" +#define SCNu32 __I32_PREFIX "u" +#define SCNx32 __I32_PREFIX "x" +#define SCNX32 __I32_PREFIX "X" + +#define SCNdLEAST32 SCNd32 +#define SCNiLEAST32 SCNi32 +#define SCNoLEAST32 SCNo32 +#define SCNuLEAST32 SCNu32 +#define SCNxLEAST32 SCNx32 +#define SCNXLEAST32 SCNX32 + +#define SCNdFAST32 SCNd32 +#define SCNiFAST32 SCNi32 +#define SCNoFAST32 SCNo32 +#define SCNuFAST32 SCNu32 +#define SCNxFAST32 SCNx32 +#define SCNXFAST32 SCNX32 + +#define SCNd64 __I64_PREFIX "d" +#define SCNi64 __I64_PREFIX "i" +#define SCNo64 __I64_PREFIX "o" +#define SCNu64 __I64_PREFIX "u" +#define SCNx64 __I64_PREFIX "x" +#define SCNX64 __I64_PREFIX "X" + +#define SCNdLEAST64 SCNd64 +#define SCNiLEAST64 SCNi64 +#define SCNoLEAST64 SCNo64 +#define SCNuLEAST64 SCNu64 +#define SCNxLEAST64 SCNx64 +#define SCNXLEAST64 SCNX64 + +#define SCNdFAST64 SCNd64 +#define SCNiFAST64 SCNi64 +#define SCNoFAST64 SCNo64 +#define SCNuFAST64 SCNu64 +#define SCNxFAST64 SCNx64 +#define SCNXFAST64 SCNX64 + +#define SCNdMAX __MAX_PREFIX "d" +#define SCNiMAX __MAX_PREFIX "i" +#define SCNoMAX __MAX_PREFIX "o" +#define SCNuMAX __MAX_PREFIX "u" +#define SCNxMAX __MAX_PREFIX "x" +#define SCNXMAX __MAX_PREFIX "X" + +#define SCNdPTR __PTR_PREFIX "d" +#define SCNiPTR __PTR_PREFIX "i" +#define SCNoPTR __PTR_PREFIX "o" +#define SCNuPTR __PTR_PREFIX "u" +#define SCNxPTR __PTR_PREFIX "x" +#define SCNXPTR __PTR_PREFIX "X" + +#endif /* __STDC_FORMAT_MACROS ] */ + +/* 7.8.2 Functions for greatest-width integer types */ + +/* 7.8.2.1 imaxabs() */ +#if defined(_WIN32) +#define imaxabs _abs64 +#elif defined(_MSDOS) +#define imaxabs abs +#endif + +/* 7.8.2.2 imaxdiv() */ + +/* This is modified version of div() function from Microsoft's div.c found */ +/* in %MSVC.NET%\crt\src\div.c */ +#if defined(_MSDOS) && !defined(STATIC_IMAXDIV) && !defined(__cplusplus) +/* MSVC 1.52 compiler for MS-DOS does not support inline for C */ +extern imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom); +#else +#ifdef STATIC_IMAXDIV /* [ */ +static +#else /* STATIC_IMAXDIV ][ */ +_inline +#endif /* STATIC_IMAXDIV ] */ +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + /* did division wrong; must fix up */ + ++result.quot; + result.rem -= denom; + } + + return result; +} +#endif /* defined(_MSDOS) && !defined(STATIC_IMAXDIV) && !defined(__cplusplus) */ + +/* 7.8.2.3 strtoimax() and strtoumax() */ +#if defined(_WIN32) +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 +#elif defined(_MSDOS) +#define strtoimax strtol +#define strtoumax strtoul +#endif + +/* 7.8.2.4 wcstoimax() and wcstoumax() */ +#if defined(_WIN32) +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 +#elif defined(_MSDOS) +#define wcstoimax wcstol +#define wcstoumax wcstoul +#endif + +#endif /* _MSC_INTTYPES_H_ */ diff --git a/deps/MsvcLibX/include/msvcLibgen.h b/deps/MsvcLibX/include/msvcLibgen.h new file mode 100644 index 0000000000000000000000000000000000000000..c3051a2fb2c828fe3215e1ef0b42812cf5fc5625 --- /dev/null +++ b/deps/MsvcLibX/include/msvcLibgen.h @@ -0,0 +1,22 @@ +/*****************************************************************************\ +* * +* Filename: libgen.h * +* * +* Description: DOS/WIN32 port of standard C library's libgen.h. * +* * +* Notes: * +* * +* History: * +* 2016-09-08 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _LIBGEN_H +#define _LIBGEN_H + +char *basename(char *pszPathname); /* Modifies pathname; Not thread-safe */ +char *dirname(char *pszPathname); /* Modifies pathname; Not thread-safe */ + +#endif /* !defined(_LIBGEN_H) */ diff --git a/deps/MsvcLibX/include/msvcLimits.h b/deps/MsvcLibX/include/msvcLimits.h new file mode 100644 index 0000000000000000000000000000000000000000..496fe9f24c6250cf29cce0c0878c853a5ca48a19 --- /dev/null +++ b/deps/MsvcLibX/include/msvcLimits.h @@ -0,0 +1,54 @@ +/*****************************************************************************\ +* * +* Filename: limits.h * +* * +* Description: MsvcLibX extensions to limits.h. * +* * +* Notes: * +* * +* History: * +* 2014-06-30 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_LIMITS_H +#define _MSVCLIBX_LIMITS_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +/************************ MS-DOS-specific definitions ************************/ + +#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ + +#define PATH_MAX 255 /* Many APIs actually limit it to 128 bytes, but longer paths paths are legal. */ + +#endif /* defined(_MSDOS) */ + +/************************ Win32-specific definitions *************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#undef PATH_MAX + +#define ANSI_PATH_MAX 260 /* Number of ANSI characters, including final NUL ( = Windef.h MAX_PATH) */ +#define UNICODE_PATH_MAX 32768 /* Number of Unicode characters, including final NUL */ +#define UTF8_PATH_MAX (4 * UNICODE_PATH_MAX) /* Worst UTF-8 case is 4 bytes / Unicode char */ + +#define PATH_MAX UNICODE_PATH_MAX /* MsvcLibX uses Unicode internally for file management */ + +#endif /* defined(_WIN32) */ + +/************************* OS/2-specific definitions *************************/ + +#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */ + +#endif /* defined(_OS2) */ + +/********************** End of OS-specific definitions ***********************/ + +#endif /* defined(_MSVCLIBX_LIMITS_H) */ + diff --git a/deps/MsvcLibX/include/msvcNetdb.h b/deps/MsvcLibX/include/msvcNetdb.h new file mode 100644 index 0000000000000000000000000000000000000000..cc874580e1eb894349db36502a3c547bb71e9945 --- /dev/null +++ b/deps/MsvcLibX/include/msvcNetdb.h @@ -0,0 +1,26 @@ +/*****************************************************************************\ +* * +* Filename: netdb.h * +* * +* Description: Network definitions * +* * +* Notes: * +* * +* History: * +* 2012-01-24 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _NETDB_H +#define _NETDB_H 1 + +/* Absolute file name for network data base files. */ +#define _PATH_HOSTS "C:/Windows/System32/drivers/etc/hosts" +#define _PATH_NETWORKS "C:/Windows/System32/drivers/etc/networks" +#define _PATH_PROTOCOLS "C:/Windows/System32/drivers/etc/protocols" +#define _PATH_SERVICES "C:/Windows/System32/drivers/etc/services" + +#endif /* _NETDB_H */ + diff --git a/deps/MsvcLibX/include/msvcProcess.h b/deps/MsvcLibX/include/msvcProcess.h new file mode 100644 index 0000000000000000000000000000000000000000..66cf94de144045c0b0124d44ea13ae297d71c43c --- /dev/null +++ b/deps/MsvcLibX/include/msvcProcess.h @@ -0,0 +1,34 @@ +/*****************************************************************************\ +* * +* Filename: process.h * +* * +* Description: MsvcLibX extensions to process.h. * +* * +* Notes: * +* * +* History: * +* 2014-03-27 JFL Created this file. * +* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_PROCESS_H +#define _MSVCLIBX_PROCESS_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +#if defined(_WIN32) +extern intptr_t _spawnvpU(int iMode, const char *pszCommand, char *const *argv); +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define _spawnvp _spawnvpU +#else /* _ANSI_SOURCE */ +#define _spawnvp _spawnvp +#endif /* defined(_UTF8_SOURCE) */ +#endif /* defined(_WIN32) */ + +#endif /* defined(_MSVCLIBX_PROCESS_H) */ + diff --git a/deps/MsvcLibX/include/msvcRegex.h b/deps/MsvcLibX/include/msvcRegex.h new file mode 100644 index 0000000000000000000000000000000000000000..66dd78fbc350f38564497d27aa964bbaab181155 --- /dev/null +++ b/deps/MsvcLibX/include/msvcRegex.h @@ -0,0 +1,89 @@ +#ifndef _HSREGEX_H_ +#define _HSREGEX_H_ +#ifndef _HSREGEX_H +#define _HSREGEX_H /* never again */ + +#include /* JFL 2012-01-24 Added definition of types used below */ +#pragma comment( lib, "regex.lib" ) + +/* ========= begin header generated by ././mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === regex2.h === */ +#ifdef WIN32 +#define API_EXPORT(type) __declspec(dllexport) type __stdcall +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define API_EXPORT(type) __attribute__ ((visibility("default"))) type +#else +#define API_EXPORT(type) type +#endif + +typedef off_t regoff_t; +typedef struct { + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + const char *re_endp; /* end pointer for REG_PEND */ + struct re_guts *re_g; /* none of your business :-) */ +} regex_t; +typedef struct { + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + + +/* === regcomp.c === */ +API_EXPORT(int) regcomp(regex_t *, const char *, int); +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 + + +/* === regerror.c === */ +#define REG_OKAY 0 +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 +#define REG_EMPTY 14 +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ +API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t); + + +/* === regexec.c === */ +API_EXPORT(int) regexec(const regex_t *, const char *, size_t, regmatch_t [], int); +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 +#define REG_TRACE 00400 /* tracing of execution */ +#define REG_LARGE 01000 /* force large representation */ +#define REG_BACKR 02000 /* force use of backref code */ + + +/* === regfree.c === */ +API_EXPORT(void) regfree(regex_t *); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ././mkh ========= */ +#endif +#endif diff --git a/deps/MsvcLibX/include/msvcReparsept.h b/deps/MsvcLibX/include/msvcReparsept.h new file mode 100644 index 0000000000000000000000000000000000000000..04ba02f9a2010e4e3ebe5db820bd26f91d050bad --- /dev/null +++ b/deps/MsvcLibX/include/msvcReparsept.h @@ -0,0 +1,125 @@ +/*****************************************************************************\ +* * +* Filename: reparsept.h * +* * +* Description: Definitions for WIN32 reparse points. * +* * +* Notes: * +* * +* History: * +* 2014-02-28 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* Reparse point iocontrol data buffer */ +/* See http://msdn.microsoft.com/en-us/library/cc232006.aspx */ +/* and http://msdn.microsoft.com/en-us/library/cc232007.aspx */ + +#include + +/* NTFS reparse point definitions */ + +/* Constants from http://msdn.microsoft.com/en-us/library/dd541667.aspx */ +/* Some, but not all, of them also defined in recent versions of winnt.h. */ +/* Since the list varies a lot, redefine them one by one as needed */ + +#ifndef IO_REPARSE_TAG_RESERVED_ZERO +#define IO_REPARSE_TAG_RESERVED_ZERO 0x00000000 /* Reserved reparse tag value */ +#endif +#ifndef IO_REPARSE_TAG_RESERVED_ONE +#define IO_REPARSE_TAG_RESERVED_ONE 0x00000001 /* Reserved reparse tag value */ +#endif +#ifndef IO_REPARSE_TAG_MOUNT_POINT +#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 /* Used for mount point support */ +#endif +#ifndef IO_REPARSE_TAG_HSM +#define IO_REPARSE_TAG_HSM 0xC0000004 /* Obsolete. Used by legacy Hierarchical Storage Manager Product */ +#endif +#ifndef IO_REPARSE_TAG_DRIVER_EXTENDER +#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005 /* Home server drive extender */ +#endif +#ifndef IO_REPARSE_TAG_HSM2 +#define IO_REPARSE_TAG_HSM2 0x80000006 /* Obsolete. Used by legacy Hierarchical Storage Manager Product */ +#endif +#ifndef IO_REPARSE_TAG_SIS +#define IO_REPARSE_TAG_SIS 0x80000007 /* Used by single-instance storage (SIS) filter driver. Server-side interpretation only, not meaningful over the wire */ +#endif +#ifndef IO_REPARSE_TAG_WIM +#define IO_REPARSE_TAG_WIM 0x80000008 /* Mounted Windows boot Image File? */ +#endif +#ifndef IO_REPARSE_TAG_CSV +#define IO_REPARSE_TAG_CSV 0x80000009 /* Cluster Shared Volume? */ +#endif +#ifndef IO_REPARSE_TAG_DFS +#define IO_REPARSE_TAG_DFS 0x8000000A /* Used by the DFS filter. The DFS is described in the Distributed File System (DFS): Referral Protocol Specification [MS-DFSC]. Server-side interpretation only, not meaningful over the wire */ +#endif +#ifndef IO_REPARSE_TAG_FILTER_MANAGER +#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B /* Used by filter manager test harness */ +#endif +#ifndef IO_REPARSE_TAG_SYMLINK +#define IO_REPARSE_TAG_SYMLINK 0xA000000C /* Used for symbolic link support */ +#endif +#ifndef IO_REPARSE_TAG_DFSR +#define IO_REPARSE_TAG_DFSR 0x80000012 /* Used by the DFS filter. The DFS is described in [MS-DFSC]. Server-side interpretation only, not meaningful over the wire */ +#endif +#ifndef IO_REPARSE_TAG_DEDUP +#define IO_REPARSE_TAG_DEDUP 0x80000013 /* Mounted deduplicated volume? */ +#endif +#ifndef IO_REPARSE_TAG_NFS +#define IO_REPARSE_TAG_NFS 0x80000014 /* Mounted NFS share? */ +#endif + +#if 0 +#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005 /* Home server drive extender */ +#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B /* Used by filter manager test harness */ +#endif + +#pragma pack(1) +typedef struct _REPARSE_READ_BUFFER { + DWORD ReparseTag; + WORD ReparseDataLength; + WORD Reserved; + UCHAR DataBuffer[1]; +} REPARSE_READ_BUFFER, *PREPARSE_READ_BUFFER; +#define REPARSE_READ_BUFFER_HEADER_SIZE (sizeof(REPARSE_READ_BUFFER) - sizeof(UCHAR)) + +typedef struct _REPARSE_SYMLINK_READ_BUFFER { + DWORD ReparseTag; + WORD ReparseDataLength; + WORD Reserved; + WORD SubstituteNameOffset; + WORD SubstituteNameLength; + WORD PrintNameOffset; + WORD PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; +} SYMLINK_READ_BUFFER, *PSYMLINK_READ_BUFFER; +#define SYMLINK_READ_BUFFER_HEADER_SIZE (sizeof(SYMLINK_READ_BUFFER) - sizeof(WCHAR)) + +typedef struct _REPARSE_MOUNTPOINT_READ_BUFFER { + DWORD ReparseTag; + WORD ReparseDataLength; + WORD Reserved; + WORD SubstituteNameOffset; + WORD SubstituteNameLength; + WORD PrintNameOffset; + WORD PrintNameLength; + WCHAR PathBuffer[1]; +} MOUNTPOINT_READ_BUFFER, *PMOUNTPOINT_READ_BUFFER; +#define MOUNTPOINT_READ_BUFFER_HEADER_SIZE (sizeof(MOUNTPOINT_READ_BUFFER) - sizeof(WCHAR)) + +typedef struct _REPARSE_MOUNTPOINT_WRITE_BUFFER { + DWORD ReparseTag; + DWORD ReparseDataLength; + WORD Reserved; + WORD ReparseTargetLength; + WORD ReparseTargetMaximumLength; + WORD Reserved1; + WCHAR ReparseTarget[1]; +} MOUNTPOINT_WRITE_BUFFER, *PMOUNTPOINT_WRITE_BUFFER; +#define MOUNTPOINT_WRITE_BUFFER_HEADER_SIZE (sizeof(MOUNTPOINT_WRITE_BUFFER) - sizeof(WCHAR)) +#pragma pack() + + diff --git a/deps/MsvcLibX/include/msvcStdbool.h b/deps/MsvcLibX/include/msvcStdbool.h new file mode 100644 index 0000000000000000000000000000000000000000..85b42c6585de680810816c6cbe5375ac2e8d09e3 --- /dev/null +++ b/deps/MsvcLibX/include/msvcStdbool.h @@ -0,0 +1,25 @@ +/*****************************************************************************\ +* * +* Filename: stdbool.h * +* * +* Description: Standard boolean definitions * +* * +* Notes: Set standard values. May need to be adapted for C++? * +* * +* History: * +* 2012-10-17 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _STDBOOL_H +#define _STDBOOL_H + +/* #define bool int /* Spec says _Bool */ +typedef int bool; +#define true 1 +#define false 0 +#define __bool_true_false_are_defined 1 + +#endif diff --git a/deps/MsvcLibX/include/msvcStdint.h b/deps/MsvcLibX/include/msvcStdint.h new file mode 100644 index 0000000000000000000000000000000000000000..55b75fe46f2592f0d6a99912749e587bcd8e87a3 --- /dev/null +++ b/deps/MsvcLibX/include/msvcStdint.h @@ -0,0 +1,322 @@ +/*****************************************************************************\ +* * +* Filename stdint.h * +* * +* Description ISO C9x compliant stdint.h for Microsoft Visual Studio * +* * +* Notes * +* * +* ISO C9x compliant stdint.h for Microsoft Visual Studio * +* Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 * +* * +* Copyright (c) 2006-2008 Alexander Chemeris * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, * +* this list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright * +* notice, this list of conditions and the following disclaimer in the * +* documentation and/or other materials provided with the distribution. * +* * +* 3. The name of the author may be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED* +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,* +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * +* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* History * +* 2008-07-17 AC Initial implementation by Alexander Chemeris. * +* 2011-05-23 JFL Added support for 16-bits compilers for MS-DOS. * +* 2011-05-28 JFL Added support for 16-bits compilers for MS-DOS. * +* 2012-01-18 JFL Added error messages if target is not DOS or Windows. * +* 2015-12-04 JFL Define _UINTPTR_T_DEFINED to tell MSVC99 it's done already* +* * +\*****************************************************************************/ + +#ifndef _MSC_VER +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif /* _MSC_VER */ + +#ifndef _MSC_STDINT_H_ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +/* +// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +*/ +/* 2015-12-04 JFL Bug fix: With VS14/VC19, MSVC's wchar.h includes inttypes.h, + which in turn includes this stdint.h, causing loop issues */ +#if (_MSC_VER < 1900) && defined(_WIN32) /* Both WIN32 and WIN64 */ +# if (_MSC_VER < 1300) && defined(__cplusplus) + extern "C++" { +# endif +# include +# if (_MSC_VER < 1300) && defined(__cplusplus) + } +# endif +#endif + +/* Define _W64 macros to mark types changing their size, like intptr_t. */ +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +/* 7.18.1 Integer types */ + +#ifndef _INTEGRAL_MAX_BITS +#define _INTEGRAL_MAX_BITS 32 +#endif + +/* 7.18.1.1 Exact-width integer types */ +#if defined(_WIN32) /* Both WIN32 and WIN64 */ +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#elif defined(_MSDOS) /* MS-DOS */ +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +#else +#error "I don't know what the integer types are in this case!" +#endif + +/* 7.18.1.2 Minimum-width integer types */ +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +#ifdef LLONG_MAX +typedef int64_t int_least64_t; +#endif +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +#ifdef LLONG_MAX +typedef uint64_t uint_least64_t; +#endif + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +#ifdef LLONG_MAX +typedef int64_t int_fast64_t; +#endif +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +#ifdef LLONG_MAX +typedef uint64_t uint_fast64_t; +#endif + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#if defined(_WIN64) /* _WIN64 */ +# define _POINTER_BITS 64 + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#elif defined(_WIN32) /* _WIN32 */ +# define _POINTER_BITS 32 + typedef _W64 int intptr_t; + typedef _W64 unsigned int uintptr_t; +#elif defined(_MSDOS) /* _MSDOS */ +# if defined(_M_I86TM) || defined(_M_I86SM) /* Tiny or short memory models */ +# define _POINTER_BITS 16 + typedef int intptr_t; + typedef unsigned int uintptr_t; +# else /* Compact, medium, large or huge memory models */ +# define _POINTER_BITS 32 + typedef long intptr_t; + typedef unsigned long uintptr_t; +# endif +#else +#error "I don't know what the pointer types are in this case!" +#endif /* _WIN64 */ +#define _INTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED /* Prevent MSVC99 from redefining it */ + +/* 7.18.1.5 Greatest-width integer types */ +#ifdef LLONG_MAX +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#else +typedef int32_t intmax_t; +typedef uint32_t uintmax_t; +#endif + + +/* 7.18.2 Limits of specified-width integer types */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* See footnote 220 at page 257 and footnote 221 at page 259 */ + +#ifdef _MSDOS +#define _I8_MIN SCHAR_MIN /* minimum signed 8 bit value */ +#define _I8_MAX SCHAR_MAX /* maximum signed 8 bit value */ +#define _UI8_MAX UCHAR_MAX /* maximum unsigned 8 bit value */ + +#define _I16_MIN SHRT_MIN /* minimum signed 16 bit value */ +#define _I16_MAX SHRT_MAX /* maximum signed 16 bit value */ +#define _UI16_MAX USHRT_MAX /* maximum unsigned 16 bit value */ + +#define _I32_MIN LONG_MIN /* minimum signed 32 bit value */ +#define _I32_MAX LONG_MAX /* maximum signed 32 bit value */ +#define _UI32_MAX ULONG_MAX /* maximum unsigned 32 bit value */ +#endif + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#ifdef LLONG_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#endif +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#ifdef LLONG_MAX +#define UINT64_MAX _UI64_MAX +#endif + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#ifdef LLONG_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#endif +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#ifdef LLONG_MAX +#define UINT_LEAST64_MAX UINT64_MAX +#endif + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#ifdef LLONG_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#endif +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#ifdef LLONG_MAX +#define UINT_FAST64_MAX UINT64_MAX +#endif + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ +#define INTPTR_MIN INT##_POINTER_BITS##MIN +#define INTPTR_MAX INT##_POINTER_BITS##_MAX +#define UINTPTR_MAX UINT##_POINTER_BITS##_MAX + +/* 7.18.2.5 Limits of greatest-width integer types */ +#ifdef LLONG_MAX +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX +#else +#define INTMAX_MIN INT32_MIN +#define INTMAX_MAX INT32_MAX +#define UINTMAX_MAX UINT32_MAX +#endif + +/* 7.18.3 Limits of other integer types */ +#define PTRDIFF_MIN _I##_POINTER_BITS##_MIN +#define PTRDIFF_MAX _I##_POINTER_BITS##_MAX + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX +# define SIZE_MAX _UI##_POINTER_BITS##_MAX +#endif + +/* WCHAR_MIN and WCHAR_MAX are also defined in */ +#ifndef WCHAR_MIN +# define WCHAR_MIN 0 +#endif +#ifndef WCHAR_MAX +# define WCHAR_MAX _UI16_MAX +#endif + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif /* __STDC_LIMIT_MACROS */ + + +/* 7.18.4 Limits of other integer types */ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* See footnote 224 at page 260 */ + +/* 7.18.4.1 Macros for minimum-width integer constants */ + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#ifdef LLONG_MAX +#define INT64_C(val) val##i64 +#endif + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#ifdef LLONG_MAX +#define UINT64_C(val) val##ui64 +#endif + +/* 7.18.4.2 Macros for greatest-width integer constants */ +#ifdef LLONG_MAX +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C +#else +#define INTMAX_C INT32_C +#define UINTMAX_C UINT32_C +#endif + +#endif /* __STDC_CONSTANT_MACROS */ + + +#endif /* _MSC_STDINT_H_ */ diff --git a/deps/MsvcLibX/include/msvcStdio.h b/deps/MsvcLibX/include/msvcStdio.h new file mode 100644 index 0000000000000000000000000000000000000000..65af04340d2f7036b0ad5d3702710f30fb1f7cae --- /dev/null +++ b/deps/MsvcLibX/include/msvcStdio.h @@ -0,0 +1,125 @@ +/*****************************************************************************\ +* * +* Filename: stdio.h * +* * +* Description: MsvcLibX extensions to stdio.h. * +* * +* Notes: * +* * +* History: * +* 2014-06-03 JFL Created this file. * +* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. +* 2015-12-09 JFL Alias fputs to fputsU, and vfprintf to vfprintfU. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_stdio_H +#define _MSVCLIBX_stdio_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define snprintf _snprintf /* This one _is_ standard */ +#define popen _popen /* This one _is_ standard */ +#define pclose _pclose /* This one _is_ standard */ + +/************************ MS-DOS-specific definitions ************************/ + +#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ + +/* Define functions fseeko and ftello */ +#if defined(_LARGEFILE_SOURCE) + #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + /* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */ + #else + #endif + /* For now, use the MSVC 32-bits functions in all cases */ + #define fseeko fseek + #define ftello ftell +#endif + +/* Define standard 64-bits functions */ +#if defined(_LARGEFILE_SOURCE64) + #define fseeko64 _fseek + #define ftello64 _ftell +#endif + +#endif /* defined(_MSDOS) */ + +/************************ Win32-specific definitions *************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define vfprintf vfprintfU /* For outputing UTF-8 strings */ +#define fprintf fprintfU /* For outputing UTF-8 strings */ +#define printf printfU /* For outputing UTF-8 strings */ +#define fputs fputsU /* For outputing UTF-8 strings */ +/* The UTF-8 output routines are defined in iconv.c */ +extern int vfprintfU(FILE *f, const char *pszFormat, va_list vl); +extern int fprintfU(FILE *f, const char *pszFormat, ...); +extern int printfU(const char *pszFormat, ...); +extern int fputsU(const char *buf, FILE *f); +extern UINT codePage; +#endif + +/* Define functions fseeko and ftello */ +#if defined(_LARGEFILE_SOURCE) + #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + #define fseeko _fseeki64 /* _CONCAT(_fseeki64,_NS_SUFFIX) */ + #define ftello _ftelli64 /* _CONCAT(_ftelli64,_NS_SUFFIX) */ + #else + #define fseeko fseek + #define ftello ftell + #endif +#endif + +/* Define standard 64-bits functions */ +#if defined(_LARGEFILE_SOURCE64) + #define fseeko64 _fseeki64 /* _CONCAT(_fseeki64,_NS_SUFFIX) */ + #define ftello64 _ftelli64 /* _CONCAT(_ftelli64,_NS_SUFFIX) */ +#endif + +#define fileno _fileno /* Avoid a warning about the deprecated name */ + +#endif /* defined(_WIN32) */ + +/************************* OS/2-specific definitions *************************/ + +#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */ + +/* Define functions fseeko and ftello */ +#if defined(_LARGEFILE_SOURCE) + #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + #else + #endif + #define fseeko fseek + #define ftello ftell +#endif + +/* Define standard 64-bits functions */ +#if defined(_LARGEFILE_SOURCE64) + /* For now, hide the fact that DOS does not support 64-bits lengths */ + #define fseeko64 _fseek + #define ftello64 _ftell +#endif + +#endif /* defined(_OS2) */ + +/********************** End of OS-specific definitions ***********************/ + +#ifdef __cplusplus +} +#endif + +#endif /* defined(_MSVCLIBX_stdio_H) */ + diff --git a/deps/MsvcLibX/include/msvcStdlib.h b/deps/MsvcLibX/include/msvcStdlib.h new file mode 100644 index 0000000000000000000000000000000000000000..b9bcc83f2dd9c46ba6ad4f1c3f931bdbd012ccd0 --- /dev/null +++ b/deps/MsvcLibX/include/msvcStdlib.h @@ -0,0 +1,52 @@ +/*****************************************************************************\ +* * +* Filename: stdlib.h * +* * +* Description: MsvcLibX extensions to stdlib.h. * +* * +* Notes: * +* * +* History: * +* 2016-09-13 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_stdlib_H +#define _MSVCLIBX_stdlib_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************ MS-DOS-specific definitions ************************/ + +#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ + +#endif /* defined(_MSDOS) */ + +/************************ Win32-specific definitions *************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +extern char *_fullpathU(char *absPath, const char *relPath, size_t maxLength); + +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define _fullpath _fullpathU /* For processing UTF-8 pathnames */ +#endif + +#endif /* defined(_WIN32) */ + +/********************** End of OS-specific definitions ***********************/ + +#ifdef __cplusplus +} +#endif + +#endif /* defined(_MSVCLIBX_stdlib_H) */ + diff --git a/deps/MsvcLibX/include/msvcSystem.h b/deps/MsvcLibX/include/msvcSystem.h new file mode 100644 index 0000000000000000000000000000000000000000..59c875b11467822bfc6cb79af0e2448b4332303d --- /dev/null +++ b/deps/MsvcLibX/include/msvcSystem.h @@ -0,0 +1,2 @@ +/* CoreUtils global system configuration definitions */ + diff --git a/deps/MsvcLibX/include/msvcTime.h b/deps/MsvcLibX/include/msvcTime.h new file mode 100644 index 0000000000000000000000000000000000000000..1897da58570cf503b05502d0a15c899f1f126015 --- /dev/null +++ b/deps/MsvcLibX/include/msvcTime.h @@ -0,0 +1,47 @@ +/*****************************************************************************\ +* * +* Filename: time.h * +* * +* Description: MsvcLibX extensions to time.h. * +* * +* Notes: * +* * +* History: * +* 2014-06-04 JFL Created this file. * +* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_TIME_H +#define _MSVCLIBX_TIME_H 1 + +#include "msvclibx.h" + +#include +#include /* Include MSVC's own file */ + + +#ifdef _MSDOS + +/* Check for the definition of _STRUCT_TIMESPEC before using clock_gettime(). + If it's not defined, use time() instead, which is supported by all OSs. */ + +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +#include "sys\msvcTime.h" /* for struct timespec */ + +typedef int clockid_t; +/* Supported values for clockid_t */ +#define CLOCK_REALTIME 0 + +int clock_gettime(clockid_t clock_id, struct timespec *tp); + +#endif /* defined(_WIN32) */ + +#endif /* defined(_MSVCLIBX_TIME_H) */ + diff --git a/deps/MsvcLibX/include/msvcUnistd.h b/deps/MsvcLibX/include/msvcUnistd.h new file mode 100644 index 0000000000000000000000000000000000000000..9ad60625e07be8e9b749d1951375a3a501832366 --- /dev/null +++ b/deps/MsvcLibX/include/msvcUnistd.h @@ -0,0 +1,182 @@ +/*****************************************************************************\ +* * +* Filename: unistd.h * +* * +* Description: DOS/WIN32 port of standard C library's unistd.h. * +* * +* Notes: * +* * +* History: * +* 2012-01-18 JFL Created this file. * +* 2012-10-17 JFL Added standard functions getcwd, chdir, getpid, access. * +* Added Microsoft-specific functions getdrive, chdrive. * +* 2013-03-27 JFL Updated getpid() and added getppid(). * +* 2014-02-03 JFL Added readlink(). * +* 2014-03-20 JFL Restructured Windows link management functions into Wide * +* and MultiByte versions, and changed the Unicode and Ansi * +* versions to macros. * +* 2014-06-30 JFL Moved PATH_MAX definition to limits.h. * +* 2016-08-25 JFL Implemented ResolveLinksA(). * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#ifndef _MSC_VER +#error This include file is designed for use with the Microsoft C tools only. +#endif + +#include "msvclibx.h" /* Generate a library search record to load MsvcLibX.lib. */ +#include "sys/msvcTypes.h" /* Define pid_t and getppid(). */ +#include "msvcDirent.h" /* Define pid_t and getppid(). */ +#include /* For functions like _chdir() and _getcwd() */ +#include /* For _getpid() */ + +/* Microsoft tools think these are non standard, but they are standard! */ +/* #define getcwd _getcwd */ +/* #define chdir _chdir */ +/* Actually use the improved versions in MsvcLibX */ +#undef getcwd /* MSVC _does_ define a getcwd macro, in addition to the getcwd function! */ +#if defined(_MSDOS) +#define getcwd(path, size) _getcwd(path, (int)(size)) /* Use MSVC LIB's own, changing argument 2 type */ +#elif defined(_WIN32) +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define getcwd getcwdU +#define _getdcwd _getdcwdU +#define chdir chdirU +#else /* _ANSI_SOURCE */ +#define getcwd getcwdA +#define _getdcwd _getdcwdA +#define chdir chdirA +#endif +char *getcwdA(char *buf, size_t bufSize); /* Can't use the getcwd name, as MSVC has an incompatible prototype for it */ +char *_getdcwdA(int iDrive, char *buf, int iBuflen); +char *getcwdU(char *buf, size_t bufSize); /* Can't use the getcwd name, as MSVC has an incompatible prototype for it */ +char *_getdcwdU(int iDrive, char *buf, int iBuflen); +#endif /* defined(_MSDOS) */ +int chdir(const char *path); + +/* These are non standard indeed, but the leading _ is annoying */ +#define getdrive _getdrive +#define chdrive _chdrive + +#include /* For low level I/O functions like read() & write() */ + +/* Microsoft tools think access is non standard, but it is standard! */ +#if defined(_MSDOS) +#define access _access +#elif defined(_WIN32) +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define access _accessU +int _accessU(const char *pszFilename, int iAccessMode); +#else /* _ANSI_SOURCE */ +#define access _access +#endif +#endif +#define F_OK 0 /* test for the existence of the file */ +#define X_OK 1 /* test for execute permission */ +#define R_OK 2 /* test for read permission */ +#define W_OK 4 /* test for read permission */ + +/* getpid() and getppid() */ +#define getpid() ((pid_t)(_getpid())) +pid_t getppid(void); /* Get parent PID */ +/* Contrary to in Unix, the above functions can fail in Windows. In this case they return INVALID_PID. */ +#define INVALID_PID ((pid_t)-1L) + +/* Path management */ +#if defined(_WIN32) +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define realpath realpathU +#define CompactPath CompactPathU +#else /* _ANSI_SOURCE */ +#define realpath realpathA +#define CompactPath CompactPathA +#endif +#endif /* defined(_WIN32) */ +char *realpath(const char *path, char *buf); /* Posix routine, normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */ +int CompactPath(const char *path, char *outbuf, size_t bufsize); /* A proprietary subroutine, that cleans up . and .. parts. */ + +/* Signed size type */ +#ifndef _SSIZE_T_DEFINED +#if defined(_MSDOS) +typedef int ssize_t; +#elif defined(_WIN32) +#include +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif /* defined(_WIN64) */ +#endif /* defined(_WIN32) */ +#define _SSIZE_T_DEFINED +#endif /* !_SSIZE_T_DEFINED */ + +/* Link management functions */ +#if defined(_WIN32) +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define readlink readlinkU +#define symlink symlinkU +#define symlinkd symlinkdU +#define junction junctionU +#define GetReparseTag GetReparseTagU +#define ResolveLinks ResolveLinksU +#else /* _ANSI_SOURCE */ +#define readlink readlinkA +#define symlink symlinkA +#define symlinkd symlinkdA +#define junction junctionA +#define GetReparseTag GetReparseTagA +#define ResolveLinks ResolveLinksA +#endif +ssize_t readlinkW(const WCHAR *path, WCHAR *buf, size_t bufsiz); /* Posix routine readlink - Wide char version */ +ssize_t readlinkM(const char *path, char *buf, size_t bufsiz, UINT cp); /* Posix routine readlink - Multibyte char version */ +#define readlinkA(path, buf, bufsiz) readlinkM(path, buf, bufsiz, CP_ACP) /* Posix routine readlink - ANSI version */ +#define readlinkU(path, buf, bufsiz) readlinkM(path, buf, bufsiz, CP_UTF8) /* Posix routine readlink - UTF-8 version */ +int symlinkW(const WCHAR *targetname, const WCHAR *newlinkname); /* Posix routine symlink - Wide char version */ +int symlinkM(const char *targetname, const char *newlinkname, UINT cp); /* Posix routine symlink - Multibyte char version */ +#define symlinkA(target, newlink) symlinkM(target, newlink, CP_ACP) /* Posix routine symlink - ANSI version */ +#define symlinkU(target, newlink) symlinkM(target, newlink, CP_UTF8) /* Posix routine symlink - UTF-8 version */ +int symlinkdW(const WCHAR *targetname, const WCHAR *newlinkname); /* MsvcLibX Create an NTFS symlinkd - Wide char version */ +int symlinkdM(const char *targetname, const char *newlinkname, UINT cp); /* MsvcLibX Create an NTFS symlinkd - Multibyte char version */ +#define symlinkdA(target, newlink) symlinkdM(target, newlink, CP_ACP) /* MsvcLibX Create an NTFS symlinkd - ANSI version */ +#define symlinkdU(target, newlink) symlinkdM(target, newlink, CP_UTF8) /* MsvcLibX Create an NTFS symlinkd - UTF-8 version */ +int junctionW(const WCHAR *targetname, const WCHAR *junctionName); /* MsvcLibX Create an NTFS junction - Wide char version */ +int junctionM(const char *targetname, const char *junctionName, UINT cp); /* MsvcLibX Create an NTFS junction - Multibyte char version */ +#define junctionA(target, newjunc) junctionM(target, newjunc, CP_ACP) /* MsvcLibX Create an NTFS junction - ANSI version */ +#define junctionU(target, newjunc) junctionM(target, newjunc, CP_UTF8) /* MsvcLibX Create an NTFS junction - UTF-8 version */ +DWORD GetReparseTagW(const WCHAR *path); /* MsvcLibX Get a Repase Point tag - Wide char version */ +DWORD GetReparseTagM(const char *path, UINT cp); /* MsvcLibX Get a Repase Point tag - MultiByte char version */ +#define GetReparseTagA(path) GetReparseTagM(path, CP_ACP) /* MsvcLibX Get a Repase Point tag - ANSI version */ +#define GetReparseTagU(path) GetReparseTagM(path, CP_UTF8) /* MsvcLibX Get a Repase Point tag - ANSI version */ +int ResolveLinksA(const char *path, char *buf, size_t bufsize); /* Resolve pathnames with symlinks, symlinkds, and junctions */ +int ResolveLinksU(const char *path, char *buf, size_t bufsize); /* Resolve pathnames with symlinks, symlinkds, and junctions */ +#ifndef ELOOP +/* +// Unix defines ELOOP as errno 40. +// MS Visual C++ 1.52 for DOS is standard up to errno 34, then diverges up to errno 36. +// Many errnos within the list are actually unused, and for them _sys_errlist[] = "". +// MS Visual C++ 9 for Windows is standard up to errno 34, then diverges up to errno 43. +// Also MSVC9 does not define errno: +// 15 // The posix standard ENOTBLK "Block device required" +// 26 // The posix standard ETXTBSY "Text file busy" +// 35 // Positioned between standard ERANGE and EDEADLK +// 37 // Positioned between standard EDEADLK and ENAMETOOLONG +// 43 // Positioned last, after standard ENOTEMPTY +// The _sys_errlist[] pointer for all the above points to a single string "Unknown error". +*/ +#define ELOOP 35 /* Using the first available slot */ /* Update _sys_errlist[ELOOP] accordingly in any routine that generates ELOOP! */ +#endif /* !defined(ELOOP) */ +#define SYMLOOP_MAX 31 /* Maximum depth of symbolic name resolution, to avoid stack overflows. Windows is documented to allow 31: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365460(v=vs.85).aspx */ +#endif /* defined(_WIN32) */ + +/* Standard file descriptor numbers, for low level I/O functions */ +#define STDIN_FILENO 0 /* Standard input file number */ +#define STDOUT_FILENO 1 /* Standard output file number */ +#define STDERR_FILENO 2 /* Standard error file number */ + +#endif /* _UNISTD_H */ + diff --git a/deps/MsvcLibX/include/msvcUtime.h b/deps/MsvcLibX/include/msvcUtime.h new file mode 100644 index 0000000000000000000000000000000000000000..ec846871675fc619fc5da690b5690168996e5bec --- /dev/null +++ b/deps/MsvcLibX/include/msvcUtime.h @@ -0,0 +1,86 @@ +/*****************************************************************************\ +* * +* Filename: utime.h * +* * +* Description: DOS/WIN32 adaptation of standard C library's utime.h. * +* * +* Notes: The Unix standard now standardizes utime.h location in * +* the include directory itself. * +* Microsoft put it in the include/sys subdirectory. * +* * +* History: * +* 2014-12-13 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVXLIBX_UTIME_H +#define _MSVXLIBX_UTIME_H + +/* In MS-DOS, simply use MSVC's sys/utime.h. */ + +#ifdef _MSDOS + +#include + +#define lutime utime /* There are no links in MS-DOS, so lutime() is the same as utime() */ + +#endif /* _MSDOS */ + + +/* In Windows, we use MSVC's sys/utime.h, but redefine the utime*() functions. */ + +#ifdef _WIN32 + +#include "msvclibx.h" /* Generate a library search record to load MsvcLibX.lib. */ + +/* Save the initial definition and value of __STDC__ */ +#ifdef __STDC__ +#define _UTIME__STDC__WAS_DEFINED 1 +#pragma push_macro("__STDC__") +#undef __STDC__ +#else +#define _UTIME__STDC__WAS_DEFINED 0 +#endif + +#define __STDC__ 1 /* Prevents from defining structures and functions without _ */ + +#include + +#ifdef _USE_32BIT_TIME_T +#define utimbuf __utimbuf32 +#define utime _utime32x +#error "32-bits time_t not supported in MsvcLibX' utime." +#else +#define utimbuf __utimbuf64 +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define utime utimeU +#define lutime lutimeU +#else /* _ANSI_SOURCE */ +#define utime utimeA +#define lutime lutimeA +#endif +#endif + +/* Our redefinition in utime.c */ +int utimeA(const char * pszFilename, const struct utimbuf * pUtimbuf); +int lutimeA(const char * pszFilename, const struct utimbuf * pUtimbuf); +int utimeU(const char * pszFilename, const struct utimbuf * pUtimbuf); +int lutimeU(const char * pszFilename, const struct utimbuf * pUtimbuf); +int utimeW(const WCHAR * pszFilename, const struct utimbuf * pUtimbuf); +int lutimeW(const WCHAR * pszFilename, const struct utimbuf * pUtimbuf); +int futime(int fd, const struct utimbuf * pUtimbuf); + +#undef __STDC__ + +/* Restore the initial definition and value of __STDC__ */ +#if _UTIME__STDC__WAS_DEFINED +#pragma pop_macro("__STDC__") +#endif +#undef _UTIME__STDC__WAS_DEFINED + +#endif /* _WIN32 */ + +#endif /* _MSVXLIBX_UTIME_H */ + diff --git a/deps/MsvcLibX/include/msvcWindows.h b/deps/MsvcLibX/include/msvcWindows.h new file mode 100644 index 0000000000000000000000000000000000000000..1c2d72554b25289113ed37aa1ce3a350889289aa --- /dev/null +++ b/deps/MsvcLibX/include/msvcWindows.h @@ -0,0 +1,60 @@ +/*****************************************************************************\ +* * +* Filename: windows.h * +* * +* Description: Define MsvcLibX' extensions to the WIN32 API functions * +* * +* Notes: * +* * +* History: * +* 2016-09-12 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_WINDOWS_H +#define _MSVCLIBX_WINDOWS_H 1 + +#include "msvclibx.h" + +#ifdef _WIN32 + +#include /* Include Windows SDK's own windows.h */ + +/****************** Define UTF-8 versions of WIN32 routines ******************/ + +#ifdef __cplusplus +extern "C" { +#endif + +DWORD WINAPI GetFileAttributesU(LPCTSTR lpFileName); +BOOL WINAPI GetFileAttributesExU(LPCTSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation); +DWORD WINAPI GetFullPathNameU(LPCTSTR lpName, DWORD nBufferLength, LPTSTR lpBuf, LPTSTR *lpFilePart); +DWORD WINAPI GetLongPathNameU(LPCTSTR lpShortName, LPTSTR lpBuf, DWORD nBufferLength); + +#ifdef __cplusplus +} +#endif + +/********** Redefine the legacy names to point to the UTF-8 version **********/ + +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) + +#undef GetFileAttributes +#define GetFileAttributes GetFileAttributesU + +#undef GetFileAttributesEx +#define GetFileAttributesEx GetFileAttributesExU + +#undef GetFullPathName +#define GetFullPathName GetFullPathNameU + +#undef GetLongPathName +#define GetLongPathName GetLongPathNameU + +#endif /* defined(_UTF8_SOURCE) ... */ + +#endif /* defined(_WIN32) */ + +#endif /* defined(_MSVCLIBX_WINDOWS_H) */ diff --git a/deps/MsvcLibX/include/msvcXfreopen.h b/deps/MsvcLibX/include/msvcXfreopen.h new file mode 100644 index 0000000000000000000000000000000000000000..89fb5425640709419e882d1a67516b4ee342718b --- /dev/null +++ b/deps/MsvcLibX/include/msvcXfreopen.h @@ -0,0 +1,19 @@ +/*****************************************************************************\ +* * +* Filename: error.h * +* * +* Description: DOS/WIN32 port of the GNU CoreUtils library xfreopen func.* +* * +* Notes: msvclibx: Implement using freopen or _setmode. * +* * +* History: * +* 2014-02-10 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvclibx.h" /* Generate a library search record to load MsvcLibX.lib. */ + +extern FILE *xfreopen(const char *filename, const char *mode, FILE *stream); + diff --git a/deps/MsvcLibX/include/msvclibx.h b/deps/MsvcLibX/include/msvclibx.h new file mode 100644 index 0000000000000000000000000000000000000000..4f5fc2733b7ee766603ff82803a24486c3f9d108 --- /dev/null +++ b/deps/MsvcLibX/include/msvclibx.h @@ -0,0 +1,117 @@ +/*****************************************************************************\ +* * +* Filename MsvcLibX.h * +* * +* Description MsvcLibX-specific definitions * +* * +* Notes Generates a library search record to load MsvcLibX.lib. * +* * +* History: * +* 2013 JFL Created this file. * +* 2014-05-30 JFL Added macros to work around the lack of a #include_next. * +* 2015-11-15 JFL Added macro UCRT_INCLUDE_FILE for Visual Studio 2015. * +* 2016-09-15 JFL Added macro WINSDK_INCLUDE_FILE for Windows SDK. * +* 2016-09-20 JFL Added workaround preventing warnings in WIN95 builds. * +* 2016-09-28 JFL Can also be included by MS' Resource Compiler. * +* 2017-02-05 JFL Changed the UTF-8 programs initialization method. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* Generate a library search record to load MsvcLibX.lib */ + +#ifndef _MSVCLIBX_H_ +#define _MSVCLIBX_H_ + +#if !(defined(_MSC_VER) || defined(RC_INVOKED)) +#error The msvclibx library is designed for use with the Microsoft Visual C/C++ tools only. +#endif + +/* Compute the OS-specific suffix */ +#if defined(_WIN64) +# define _MSVCLIBX_LIB_OS_SUFFIX "w64" +#elif defined(_WIN95) +# define _MSVCLIBX_LIB_OS_SUFFIX "w95" +#elif defined(_WIN32) +# define _MSVCLIBX_LIB_OS_SUFFIX "w32" +#elif defined(_MSDOS) +# if defined(_M_I86TM) +# define _MSVCLIBX_LIB_OS_SUFFIX "dt" +# elif defined(_M_I86SM) +# define _MSVCLIBX_LIB_OS_SUFFIX "ds" +# elif defined(_M_I86LM) +# define _MSVCLIBX_LIB_OS_SUFFIX "dl" +# else +# error No msvclibx.lib version yet for this DOS memory model. +# endif +#else +# error No msvclibx.lib version for this target OS. +#endif + +/* Compute the debug-mode-specific suffix */ +#if defined(_DEBUG) +# define _MSVCLIBX_LIB_DBG_SUFFIX "d" +#else +# define _MSVCLIBX_LIB_DBG_SUFFIX "" +#endif + +/* Generate the OS-and-debug-mode-specific library name */ +#define _MSVCLIBX_LIB "MsvcLibX" _MSVCLIBX_LIB_OS_SUFFIX _MSVCLIBX_LIB_DBG_SUFFIX ".lib" +//#pragma message("Adding pragma comment(lib, \"" _MSVCLIBX_LIB "\")") +#pragma comment(lib, _MSVCLIBX_LIB) + +/* Library-specific routine used internally by many standard routines */ +#if defined(_WIN32) +extern int Win32ErrorToErrno(); /* Converts the last WIN32 error to a Posix error code */ +#ifndef ELOOP /* Defined in VS10's errno.h, but not in VS9 */ +#define ELOOP 114 +#endif +/* Convert an ANSI or UTF-8 or OEM pathname to a Unicode string. Defined in mb2wpath.c. */ +typedef unsigned int UINT; /* Defined in windef.h */ +typedef const char* LPCSTR; /* Defined in winnt.h */ +#ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; /* Defined in crtdefs.h */ +#define _WCHAR_T_DEFINED +#endif +typedef wchar_t* LPWSTR; /* Defined in winnt.h */ +extern int MultiByteToWidePath(UINT nCodePage, LPCSTR pszName, LPWSTR pwszName, int nWideBufSize); +#endif +/* Count the number of elements in an array */ +#define COUNTOF(array) (sizeof(array)/sizeof(array[0])) + +/* Workaround for missing __pragma() directive in old versions of Visual Studio */ +#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER <= 1400) /* For Visual C++ versions up to Visual Studio 2005 */ +#define __pragma(x) +#endif /* (_MSC_VER <= 1400) */ + +/* Macros for working around the lack of a #include_next directive */ +#define MSVCLIBX_CONCAT1(a,b) a##b /* Concatenate the raw arguments */ +#define MSVCLIBX_CONCAT(a,b) MSVCLIBX_CONCAT1(a,b) /* Substitute the arguments, then concatenate the values */ +#define MSVCLIBX_STRINGIZE1(x) #x /* Convert the raw argument to a string */ +#define MSVCLIBX_STRINGIZE(x) MSVCLIBX_STRINGIZE1(x) /* Substitute the argument, then convert its value to a string */ +/* Up to VS2013, both kinds of include files were in the same directory. Then in VS2015, they were split in two dirs. */ +#define MSVC_INCLUDE_FILE(relpath) MSVCLIBX_STRINGIZE(MSVCLIBX_CONCAT(MSVCINCLUDE,MSVCLIBX_CONCAT(/,relpath))) /* C compiler include files */ +#define UCRT_INCLUDE_FILE(relpath) MSVCLIBX_STRINGIZE(MSVCLIBX_CONCAT(UCRTINCLUDE,MSVCLIBX_CONCAT(/,relpath))) /* C runtime library include files */ +#define WINSDK_INCLUDE_FILE(relpath) MSVCLIBX_STRINGIZE(MSVCLIBX_CONCAT(WSDKINCLUDE,MSVCLIBX_CONCAT(/,relpath))) /* Windows SDK include files */ + +/* Support for external linker symbols */ +#if defined(_WIN64) +#define PUBLIC_SYMBOL_NAME(s) s +#else /* _MSDOS or _WIN32 */ +#define PUBLIC_SYMBOL_NAME(s) _##s +#endif + +/* Support for UTF-8 command lines */ +#if defined(_WIN32) +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +/* Force linking in MsvcLibX' UTF-8 initialization module */ +#pragma comment(linker, "/include:" MSVCLIBX_STRINGIZE(PUBLIC_SYMBOL_NAME(_initU))) +#endif /* defined(_UTF8_SOURCE) ... */ +#endif /* defined(_WIN32) */ + +/* Prevent an incompatibility with . See MsvcLibX' "sys/time.h" for explanations. */ +#define _WINSOCKAPI_ /* Prevent the inclusion of winsock.h in windows.h */ + +#endif /* _MSVCLIBX_H_ */ + diff --git a/deps/MsvcLibX/include/sys/msvcParam.h b/deps/MsvcLibX/include/sys/msvcParam.h new file mode 100644 index 0000000000000000000000000000000000000000..096af578cd86c4ca7b0c2c6eb3acf1876dac526c --- /dev/null +++ b/deps/MsvcLibX/include/sys/msvcParam.h @@ -0,0 +1,36 @@ +/*****************************************************************************\ +* * +* Filename sys/param.h * +* * +* Description DOS/WIN32 port of standard C library's sys/param.h. * +* * +* Notes * +* * +* History * +* 2014-06-10 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + + +#ifdef _MSDOS + +#define _POSIX_ARG_MAX 127 /* Maximum command line size */ + +#endif + + +#ifdef _WIN32 + +/* #include MSVC_INCLUDE_FILE(sys\param.h) /* Include MSVC's own file */ + +#define _POSIX_ARG_MAX 8191 + +#endif /* defined(_WIN32) */ + +#endif /* !defined(_SYS_PARAM_H) */ + diff --git a/deps/MsvcLibX/include/sys/msvcStat.h b/deps/MsvcLibX/include/sys/msvcStat.h new file mode 100644 index 0000000000000000000000000000000000000000..b2b82d0be8fc68f0d2e2391a2d494bc25e6b9607 --- /dev/null +++ b/deps/MsvcLibX/include/sys/msvcStat.h @@ -0,0 +1,422 @@ +/*****************************************************************************\ +* * +* Filename: stat.h * +* * +* Description: MsvcLibX extensions to sys/stat.h. * +* * +* Notes: * +* * +* History: * +* 2014-02-06 JFL Moved stat extensions from dirent.h. * +* 2014-02-26 JFL Added proprietary routines for managing file times. * +* 2014-03-24 JFL Added a mechanism to also include MSVC's own sys/stat.h. * +* Renamed this file from statx.h to sys/stat.h. * +* 2014-05-27 JFL Added dummy definitions for S_TYPEISSHM() & S_TYPEISTMO().* +* 2014-06-03 JFL Moved struct timespec definition to sys/time.h. * +* 2014-06-06 JFL Moved mode_t & off*_t definition to sys/types.h. * +* Moved fseeko* & ftello* functions definitions to stdio.h. * +* 2014-06-24 JFL Added fstat and fstat64 external references. * +* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. +* 2016-09-15 JFL Fixed a warning in Visual Studio 2015. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_STAT_H +#define _MSVCLIBX_STAT_H 1 + +#include "msvclibx.h" + +#include "sys/msvcTypes.h" +#include /* Include MSVC's own file */ +#include "msvcDirent.h" /* For dirent2stat() arguments definitions */ +#include "msvcTime.h" /* for time_t definition */ +#include "sys/msvcTime.h" /* for timespec definition */ +/* Include MsvcLibX's override, to avoid conflict with the standard mkdir defined here, + should be manually included later on in the C source */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/************************ MS-DOS-specific definitions ************************/ + +#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ + +/* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */ +/* #undef stat /* Not normally defined by MSVC */ +/* #undef fstat /* Not normally defined by MSVC */ +#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + /* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */ +#else +#endif +/* For now, use the MSVC 32-bits functions in all cases */ +#define stat _stat +#define fstat _fstat +#define lstat stat + +/* Define standard 64-bits structures and functions */ +#if defined(_LARGEFILE_SOURCE64) + /* For now, hide the fact that DOS does not support 64-bits lengths */ + #define off64_t _off_t + #define stat64 _stat + #define fstat64 _fstat + #define lstat64 stat64 +#endif + +/* Proprietary function for recovering available infos without calling stat */ +extern int dirent2stat(struct dirent *pDE, struct _stat *pStat); +#define dirent2stat64 dirent2stat /* The current versions are the same */ +#define _DIRENT2STAT_DEFINED 1 + +/* MS-DOS always reports local file times. MsvcLibX DOS version generates a + pseudo GMT time for files using mktime(), which can then be undone by localtime(). */ +#define LocalFileTime localtime + +/* Proprietary function for converting a DOS date/time to a Posix time_t */ +extern time_t Filetime2Timet(uint16_t date, uint16_t time); +/* Proprietary function for generating a string with the local file time, in the ISO 8601 date/time format */ +extern char *Filetime2String(uint16_t date, uint16_t time, char *pBuf, size_t nBufSize); + +#endif /* defined(_MSDOS) */ + +/************************ Win32-specific definitions *************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +/* Visual C++ sys/stat.h defines a series of _statXY functions and structures: + XY = 32 st_*time is 32-bits __time32_t & st_size is 32-bits _off_t + XY = 32i64 st_*time is 32-bits __time32_t & st_size is 64-bits __int64 + XY = 64i32 st_*time is 64-bits __time64_t & st_size is 32-bits _off_t + XY = 64 st_*time is 64-bits __time64_t & st_size is 64-bits __int64 + Then it defines additional _statZ macros generating _statXY, based on: + XY = 32 if _USE_32BIT_TIME_T defined & Z is "" + XY = 32i64 if _USE_32BIT_TIME_T defined & Z is i64 + XY = 64i32 if _USE_32BIT_TIME_T undefined & Z is "" + XY = 64 if _USE_32BIT_TIME_T undefined & Z is i64 + Special case: In 64-bits windows, _USE_32BIT_TIME_T defined is ignored and #undef(ined) +*/ + +/* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */ +/* #undef stat /* Not normally defined by MSVC */ +/* #undef fstat /* Not normally defined by MSVC */ + +#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + #define _STAT_FILE_SIZE 64 + #define _STAT_SUFFIX i64 +#else + #define _STAT_FILE_SIZE 32 + #define _STAT_SUFFIX +#endif + +#define _USE_EXTENDED_STAT_STRUCT 1 + +#define _VALUEOF(a) a /* Get the token value */ +#define _CONCAT2T(a,b) a##b /* Concatenate two tokens (does not expand their values) */ +#define _CONCAT3T(a,b,c) a##b##c /* Concatenate three tokens (does not expand their values) */ +#define _CONCAT4T(a,b,c,d) a##b##c##d /* Concatenate four tokens (does not expand their values) */ +#define _CONCAT(a,b) _CONCAT2T(a,b) /* Concatenate two tokens values */ +#define _CONCAT3(a,b,c) _CONCAT3T(a,b,c) /* Concatenate three tokens values */ +#define _CONCAT4(a,b,c,d) _CONCAT4T(a,b,c,d) /* Concatenate four tokens values */ +#define _CON_STAT_CAT1(pre,post) pre##stat##post +#define _CON_STAT_CAT(pre,post) _CON_STAT_CAT1(pre,post) + +/* Define what stat, fstat, lstat, stat64 macros would be, + if we were to use MSVC's own stat structures and routines */ +/* Avoid concatenating tokens _stat and _fstat, as these are already macros + that would be expanded, and we do not want this as this stage. */ +#define _MSVC_stat _CON_STAT_CAT(_ , _STAT_SUFFIX) +#define _MSVC_fstat _CON_STAT_CAT(_f, _STAT_SUFFIX) +#define _MSVC_lstat _CON_STAT_CAT(_l, _STAT_SUFFIX) +#define _MSVC_stat64 _CON_STAT_CAT(_ , i64) +#define _MSVC_lstat64 _CON_STAT_CAT(_l, i64) + +#ifdef _USE_32BIT_TIME_T +#define _lstat _lstat32 +#define _lstati64 _lstat32i64 +#define _lstat_ns _lstat32_ns +#define _lstati64_ns _lstat32i64_ns +#else +#define _lstat _lstat64i32 +#define _lstati64 _lstat64 +#define _lstat_ns _lstat64i32_ns +#define _lstati64_ns _lstat64_ns +#endif + +#if !_USE_EXTENDED_STAT_STRUCT + #define _NS_SUFFIX +#else /* _USE_EXTENDED_STAT_STRUCT */ + #define _MSVCLIBX_STAT_DEFINED 1 + #define _NS_SUFFIX _ns + /* Define what stat, fstat, lstat, stat64 macros and structures would be, + if we were to use MsvcLibX extended stat structures and routines */ + #define _LIBX_stat _CONCAT(_MSVC_stat,_ns) + #define _LIBX_stat64 _CONCAT(_MSVC_stat64,_ns) +#include "msvcDebugm.h" +#pragma message("Defining type struct " VALUEIZE(_LIBX_stat)) + struct _LIBX_stat { + /* MSVC standard stat structure fields */ + _dev_t st_dev; + _ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + _dev_t st_rdev; + off_t st_size; + /* End of MSVC standard stat structure fields */ + struct timespec st_ctim; /* File creation date/time, w. ns resolution */ + struct timespec st_mtim; /* File modification date/time, w. ns resolution */ + struct timespec st_atim; /* File access date/time, w. ns resolution */ + unsigned int st_Win32Attrs; /* Win32 file attributes */ + unsigned int st_ReparseTag; /* Reparse point tag */ + }; + /* Compatibility with old Unix fields */ + #define st_ctime st_ctim.tv_sec + #define st_mtime st_mtim.tv_sec + #define st_atime st_atim.tv_sec + /* Compatibility with intermediate Unix fields */ + #define st_ctimensec st_ctim.tv_nsec /* Nanosecond part of the file creation time */ + #define st_mtimensec st_mtim.tv_nsec /* Nanosecond part of the file modification time */ + #define st_atimensec st_atim.tv_nsec /* Nanosecond part of the file access time */ + + #if (_STAT_FILE_SIZE != 64) /* Else it's the same as struct stat */ +#pragma message("Defining type struct " VALUEIZE(_LIBX_stat64)) + struct _LIBX_stat64 { + /* MSVC standard stat structure fields */ + _dev_t st_dev; + _ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + _dev_t st_rdev; + off64_t st_size; + /* End of MSVC standard stat structure fields */ + struct timespec st_ctim; /* File creation date/time, w. ns resolution */ + struct timespec st_mtim; /* File modification date/time, w. ns resolution */ + struct timespec st_atim; /* File access date/time, w. ns resolution */ + unsigned int st_Win32Attrs; /* Win32 file attributes */ + unsigned int st_ReparseTag; /* Reparse point tag */ + }; + #endif +#endif /* !_USE_EXTENDED_STAT_STRUCT */ + +/* Define standard stat, fstat, lstat macros */ +#define stat _CONCAT(_MSVC_stat,_NS_SUFFIX) +#define fstat _CONCAT(_MSVC_fstat,_NS_SUFFIX) +#define lstat _CONCAT(_MSVC_lstat,_NS_SUFFIX) + +/* Reference standard stat, fstat, lstat functions that we redefine */ +#if _USE_EXTENDED_STAT_STRUCT /* Else we'll use MSVC's version */ +extern int stat(const char *path, struct stat *buf); +extern int fstat(int nFile, struct stat *buf); +#endif +extern int lstat(const char *path, struct stat *buf); + +/* Define standard 64-bits macros and functions */ +#if defined(_LARGEFILE_SOURCE64) + #define stat64 _CONCAT(_stati64,_NS_SUFFIX) + #define fstat64 _CONCAT(_fstati64,_NS_SUFFIX) + #define lstat64 _CONCAT(_lstati64,_NS_SUFFIX) + + #if (_STAT_FILE_SIZE != 64) /* Else they're the same as functions stat & lstat */ + #if _USE_EXTENDED_STAT_STRUCT /* Else we'll use MSVC's version */ + extern int stat64(const char *path, struct stat64 *buf); + extern int fstat64(int nFile, struct stat *buf); + #endif + extern int lstat64(const char *path, struct stat64 *buf); + #endif +#endif + +/* Proprietary function for recovering dirent infos without calling stat */ +/* Note: MSDOS has a single stat version, and its dirent2stat implementation is in dirent.c */ +#ifdef _USE_32BIT_TIME_T +#if (_STAT_FILE_SIZE != 64) /* Else if _STAT_FILE_SIZE=64, then struct _stat32_ns isn't defined */ +extern int _CONCAT(_dirent2_stat32,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat32,_NS_SUFFIX) *pStat); +#endif +extern int _CONCAT(_dirent2_stat32i64,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat32i64,_NS_SUFFIX) *pStat); +#else +#if (_STAT_FILE_SIZE != 64) /* Else if _STAT_FILE_SIZE=64, then struct _stat64i32_ns isn't defined */ +extern int _CONCAT(_dirent2_stat64i32,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat64i32,_NS_SUFFIX) *pStat); +#endif +extern int _CONCAT(_dirent2_stat64,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat64,_NS_SUFFIX) *pStat); +#endif +#define dirent2stat _CONCAT(_dirent2,stat) +#define _DIRENT2STAT_DEFINED 1 + +#define unlink _CONCAT(_unlink_, stat) +#define rmdir _CONCAT(_rmdir_, stat) +extern int unlink(const char *path); +extern int rmdir(const char *path); + +/* Proprietary function for generating a printable local file time, + using Windows' specific algorithm, to match cmd.exe dir output. */ +extern struct tm *LocalFileTime(const time_t *pt); + +/* Proprietary function for converting a Win32 FILETIME to a Posix time_t */ +extern time_t Filetime2Timet(const FILETIME *pFT); +/* Proprietary function for converting a Posix time_t to a Win32 FILETIME */ +extern void Timet2Filetime(time_t s, FILETIME *pFT); + +/* Proprietary function for converting a Win32 FILETIME to a Posix {time_t,nanosecond} */ +extern void Filetime2Timespec(const FILETIME *pFT, struct timespec *pTS); +/* Proprietary function for converting a Posix {time_t,nanosecond} to a Win32 FILETIME */ +extern void Timespec2Filetime(const struct timespec *pTS, FILETIME *pFT); + +/* Proprietary function for generating a string with the local file time, in the ISO 8601 date/time format */ +extern char *Filetime2String(const FILETIME *pFT, char *pBuf, size_t nBufSize); + +#endif /* defined(_WIN32) */ + +/************************* OS/2-specific definitions *************************/ + +#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */ + +/* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */ +/* #undef stat /* Not normally defined by MSVC */ +/* #undef fstat /* Not normally defined by MSVC */ +#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + /* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */ +#else +#endif +/* For now, use the MSVC 32-bits functions in all cases */ +#define off_t _off_t +#define stat _stat +#define fstat _fstat +#define lstat stat + +/* Define standard 64-bits functions */ +#if defined(_LARGEFILE_SOURCE64) + /* For now, hide the fact that DOS does not support 64-bits lengths */ + #define off64_t _off_t + #define stat64 _stat + #define fstat64 _fstat + #define lstat64 stat64 +#endif + +/* Proprietary function for recovering available infos without calling stat */ +/* extern int dirent2stat(struct dirent *pDE, struct _stat *pStat); */ +/* #define dirent2stat64 dirent2stat /* The current versions are the same */ +/* #define _DIRENT2STAT_DEFINED 1 */ + +/* To do: Check if OS/2 uses local or GMT times, and implement LocalFileTime() if needed. */ +#define LocalFileTime localtime + +#endif /* defined(_OS2) */ + +/********************** End of OS-specific definitions ***********************/ + +#define lchmod chmod /* MSVC is buggy and chmod() applies to the link itself */ + +/* Structure stat standard st_mode values not defined in DOS/Windows' sys/stat.h */ +/* Must match the d_type field types in dirent.h. */ +/* #define S_IFMT 0xF000 /* Mask for the 4-bit file type */ +#define S_IFIFO 0x1000 /* FIFO */ +/* #define S_IFCHR 0x2000 /* Character device */ +/* #define S_IFDIR 0x4000 /* Directory */ +#define S_IFBLK 0x6000 /* Block device */ +/* #define S_IFREG 0x8000 /* Regular file */ +#define S_IFLNK 0xA000 /* Symbolic link */ +#define S_IFSOCK 0xC000 /* Socket */ + +/* Structure stat standard st_mode type test macros */ +/* The existence of these macros can be used to test for the OS support of the feature */ +#define S_ISTYPE(m, TYPE) ((m & S_IFMT) == TYPE) +/* Both DOS and Windows support these file types */ +#define S_ISCHR(m) S_ISTYPE(m, S_IFCHR) /* Test for a character device */ +#define S_ISDIR(m) S_ISTYPE(m, S_IFDIR) /* Test for a directory */ +#define S_ISREG(m) S_ISTYPE(m, S_IFREG) /* Test for a regular file */ +#ifdef _WIN32 /* Only Windows supports these */ +#define S_ISLNK(m) S_ISTYPE(m, S_IFLNK) /* Test for a symbolic link */ +#endif +#if 0 /* Only Unix supports these? At least MsvcLibX does not support them now. */ +#define S_ISBLK(m) S_ISTYPE(m, S_IFBLK) /* Test for a block device */ +#define S_ISFIFO(m) S_ISTYPE(m, S_IFIFO) /* Test for a pipe or FIFO */ +#define S_ISSOCK(m) S_ISTYPE(m, S_IFSOCK) /* Test for a socket */ +#endif + +#define S_ISBLK(m) 0 /* Test for a block device */ +#define S_ISCTG(m) 0 /* Test for a high performance ("contiguous data") file */ +#define S_ISDOOR(m) 0 /* Test for a door */ +#define S_ISFIFO(m) 0 /* Test for a pipe or FIFO */ +#define S_ISMPB(m) 0 /* Test for a multiplexed block device */ +#define S_ISMPC(m) 0 /* Test for a multiplexed character device */ +#define S_ISNWK(m) 0 /* Test for a network special file (HP-UX) */ +#define S_ISPORT(m) 0 /* Test for a port */ +#define S_ISSOCK(m) 0 /* Test for a socket */ +#define S_ISWHT(m) 0 /* Test for a whiteout (4.4BSD) */ + + +/* Other optional file types that some operating systems support */ +#define S_TYPEISMQ(pStat) 0 /* Test for a message queue */ +#define S_TYPEISSEM(pStat) 0 /* Test for a semaphore */ +#define S_TYPEISSHM(pStat) 0 /* Test for a shared memory object */ +#define S_TYPEISTMO(pStat) 0 /* Test for a typed memory object */ + +/* Structure stat standard st_mode flags */ +#define S_ISUID 04000 /* Set UID bit */ +#define S_ISGID 02000 /* Set-group-ID bit */ +#define S_ISVTX 01000 /* Sticky bit */ + +#define S_IRWXU 0700 /* Mask for file owner permissions */ +#define S_IRUSR 0400 /* Owner has read permission. Alias S_IREAD */ +#define S_IWUSR 0200 /* Owner has write permission. Alias S_IWRITE */ +#define S_IXUSR 0100 /* Owner has execute permission. Alias S_IEXEC */ + +#define S_IRWXG 070 /* Mask for group permissions */ +#define S_IRGRP 040 /* Group has read permission */ +#define S_IWGRP 020 /* Group has write permission */ +#define S_IXGRP 010 /* Group has execute permission */ + +#define S_IRWXO 07 /* Mask for permissions for others (not in group) */ +#define S_IROTH 04 /* Others have read permission */ +#define S_IWOTH 02 /* Others have write permission */ +#define S_IXOTH 01 /* Others have execute permission */ + +#define S_IRWXUGO 00777 /* S_IRWXU|S_IRWXG|S_IRWXO */ +#define S_IALLUGO 07777 /* S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO */ +#define S_IRUGO 00444 /* S_IRUSR|S_IRGRP|S_IROTH */ +#define S_IWUGO 00222 /* S_IWUSR|S_IWGRP|S_IWOTH */ +#define S_IXUGO 00111 /* S_IXUSR|S_IXGRP|S_IXOTH */ + +/* Structure stat extensions for DOS/Windows file attributes */ +#define S_IFVOLID 0xF000 /* Volume ID pseudo-file, defined in FAT root dir */ +#define S_ISVOLID(m) S_ISTYPE(m, S_IFVOLID) /* Test for a FAT volume ID */ +#define S_HIDDEN 01 /* Reuse permissions bit not used in DOS/Windows */ +#define S_ARCHIVE 02 /* Reuse permissions bit not used in DOS/Windows */ +#define S_SYSTEM 04 /* Reuse permissions bit not used in DOS/Windows */ +#define S_COMPRESSED 010 /* Reuse permissions bit not used in DOS/Windows */ +#define S_ENCRYPTED 020 /* Reuse permissions bit not used in DOS/Windows */ +#define S_NOT_CONTENT_INDEXED 040 /* Reuse permissions bit not used in DOS/Windows */ +#define S_OFFLINE 01000 /* Reuse sticky bit, not used in DOS/Windows */ +#define S_SPARSE_FILE 02000 /* Reuse GID bit, not used in DOS/Windows */ +#define S_MOUNT_POINT 04000 /* Reuse UID bit, not used in DOS/Windows */ +/* #define S_TEMPORARY /* Reuse UID bit, not used in DOS/Windows */ +/* #define S_VIRTUAL /* No bit left for this one */ + +#if defined(_MSDOS) +#define _mkdirx(path, mode) _mkdir(path) +#elif defined(_WIN32) +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define _mkdirx(path, mode) mkdirU(path, mode) +#else /* _ANSI_SOURCE */ +#define _mkdirx(path, mode) mkdirA(path, mode) +#endif /* defined(_UTF8_SOURCE) */ +extern int mkdirU(const char *path, mode_t mode); +extern int mkdirA(const char *path, mode_t mode); +#endif /* defined(_MSDOS) */ +#define mkdir(path, mode) _mkdirx(path, mode) + +/* Special values for futimens() and utimensat(). Must not be in [0...((10^9)-1)] */ +#define UTIME_NOW 1000000001 +#define UTIME_OMIT 1000000002 + +#ifdef __cplusplus +} +#endif + +#endif /* defined(_MSVCLIBX_STAT_H) */ + diff --git a/deps/MsvcLibX/include/sys/msvcTime.h b/deps/MsvcLibX/include/sys/msvcTime.h new file mode 100644 index 0000000000000000000000000000000000000000..d538f6aa7646864cda3482fd2dcd2acfba8dda3e --- /dev/null +++ b/deps/MsvcLibX/include/sys/msvcTime.h @@ -0,0 +1,114 @@ +/*****************************************************************************\ +* * +* Filename sys/time.h * +* * +* Description DOS/WIN32 port of standard C library's sys/time.h. * +* * +* Notes MUST be included before any direct or indirect inclusion * +* of , as this sys/time.h file has a definition * +* of struct timeval conflicting with that in , * +* and as a workaround it defines _WINSOCKAPI_ to prevent * +* from loading . * +* * +* The same conflict exists with , but this one * +* is not loaded automatically, and hence should not be * +* visible to Unix apps built with the MsvcLibX library. * +* * +* History * +* 2014-02-11 JFL Created this file. * +* 2014-05-30 JFL Added the workaround for the conflict with . * +* 2014-06-03 JFL Moved struct timespec definition from sys/stat.h. * +* Added macros TIMEVAL_TO_TIMESPEC & TIMESPEC_TO_TIMEVAL. * +* 2016-07-06 JFL Avoid error if winsocks2.h has been previously included. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include /* for time_t definition */ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#ifdef _MSDOS +/* MS-DOS only has a 2-second resolution on file times. + Use the existence of macro _STRUCT_TIMEVAL to test if it's possible + to use utimes(), else use utime(), which is supported by all OSs */ +#endif + +#ifdef _WIN32 + +/* There's a conflict with the timeval definition in winsock.h, which uses + a long instead of a time_t for tv_sec. See: + C:\Pgm64\Microsoft SDKs\Windows\v7.0\INCLUDE\winsock.h +*/ +#define _WINSOCKAPI_ /* Prevent the inclusion of winsock.h in windows.h */ +/* Could also #define WIN32_LEAN_AND_MEAN /* Avoid including many optional Windows features, including winsock.h */ + +#include /* For WCHAR */ + +#ifndef _STRUCT_TIMEVAL +#define _STRUCT_TIMEVAL 1 + +#ifndef _WINSOCK2API_ /* Prevent compilation errors if winsocks2.h has been previously included */ +/* A time value with microsecond precision */ +struct timeval { + time_t tv_sec; /* Seconds */ + int tv_usec; /* Signed count of microseconds */ +}; +#endif /* _WINSOCK2API */ + +#endif /* !defined(_STRUCT_TIMEVAL) */ + +/* 2015-12-04 JFL Bug fix: With VS14/VC19, the UCRT defines timespec, with a long tv_nsec */ +#ifndef _UCRT +#ifndef _STRUCT_TIMESPEC +#define _STRUCT_TIMESPEC + +/* A time value with nanosecond precision */ +struct timespec { + time_t tv_sec; /* Seconds */ + int tv_nsec; /* Signed count of nanoseconds */ +}; +#define _TIMESPEC_DEFINED /* Some packages test this before redefining it */ + +#endif /* !defined(_STRUCT_TIMESPEC) */ +#endif /* !defined(_UCRT) */ + +#define TIMEVAL_TO_TIMESPEC(ptv, pts) { \ + (pts)->tv_sec = (ptv)->tv_sec; \ + (pts)->tv_nsec = (ptv)->tv_usec * 1000; \ +} +#define TIMESPEC_TO_TIMEVAL(ptv, pts) { \ + (ptv)->tv_sec = (pts)->tv_sec; \ + (ptv)->tv_usec = (pts)->tv_nsec / 1000; \ +} + +/* Change the file access time to tvp[0] and its modification time to tvp[1]. */ +int utimesA(const char *file, const struct timeval tvp[2]); +int utimesU(const char *file, const struct timeval tvp[2]); +int utimesW(const WCHAR *file, const struct timeval tvp[2]); + +/* Same as 'utimes', but does not follow symbolic links. */ +int lutimesA(const char *path, const struct timeval tvp[2]); +int lutimesU(const char *path, const struct timeval tvp[2]); +int lutimesW(const WCHAR *path, const struct timeval tvp[2]); + +/* Same as 'utimes', but takes an open file descriptor instead of a name. */ +int futimes(int fd, const struct timeval tvp[2]); + +#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define utimes utimesU +#define lutimes lutimesU +#else /* _ANSI_SOURCE */ +#define utimes utimesA +#define lutimes lutimesA +#endif + +/* Get the current date and time into a struct timeval */ +int gettimeofday(struct timeval *ptv, void *pTimeZone); + +#endif /* defined(_WIN32) */ + +#endif /* !defined(_SYS_TIME_H) */ + diff --git a/deps/MsvcLibX/include/sys/msvcTsname.h b/deps/MsvcLibX/include/sys/msvcTsname.h new file mode 100644 index 0000000000000000000000000000000000000000..41d97a3719e9f615024f5f20f703a6d7082b1184 --- /dev/null +++ b/deps/MsvcLibX/include/sys/msvcTsname.h @@ -0,0 +1,31 @@ +/*****************************************************************************\ +* * +* Filename: sys/utsname.h * +* * +* Description: Defines structure utsname and function uname(). * +* * +* Notes: * +* * +* History: * +* 2014-05-30 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H 1 + +#include "msvclibx.h" + +struct utsname { + char *sysname; /* Name of this implementation of the operating system */ + char *nodename; /* Name of this node on the network */ + char *release; /* Current release level of this implementation */ + char *version; /* Current version level of this release */ + char *machine; /* Name of the hardware type on which the system is running */ +}; + +int uname(struct utsname *); + +#endif /* _SYS_UTSNAME_H */ diff --git a/deps/MsvcLibX/include/sys/msvcTypes.h b/deps/MsvcLibX/include/sys/msvcTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..bde2ac9a8a168465bbea940c0505c4a9654c4d51 --- /dev/null +++ b/deps/MsvcLibX/include/sys/msvcTypes.h @@ -0,0 +1,99 @@ +/*****************************************************************************\ +* * +* Filename: sys/types.h * +* * +* Description: Add missing definitions in MSVC's sys/types.h. * +* * +* Notes: * +* * +* History: * +* 2014-05-26 JFL Created this file. * +* 2014-06-06 JFL Moved mode_t & off*_t definitions here, from sys\stat.h. * +* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT. +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _MSVCLIBX_SYS_TYPES_H +#define _MSVCLIBX_SYS_TYPES_H 1 + +#include "msvclibx.h" + +#include /* Include MSVC's own file */ + +/************************ MS-DOS-specific definitions ************************/ + +#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */ + + + +/* File offset type */ +/* For now, use the MSVC 32-bits functions in all cases */ +#define off_t _off_t + +typedef int pid_t; /* The pid is the PSP segment. MSVC's process.h defines it as int. */ + +#endif /* defined(_MSDOS) */ + +/************************ Win32-specific definitions *************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +/* File offset types */ +#define off64_t __int64 /* Don't use a typedef because MSVC's _fseeki64 doesn't like it */ + +#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) + #define off_t off64_t +#else + #define off_t _off_t +#endif + +typedef unsigned long DWORD; /* Don't include to get DWORD definition, as this draws too much, + including things we want to override in other parts of MsvcLibX */ + +typedef DWORD pid_t; /* Windows defines it as a DWORD */ + +#endif /* defined(_WIN32) */ + +/************************* OS/2-specific definitions *************************/ + +#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */ + +/* File offset type */ +/* For now, use the MSVC 32-bits functions in all cases */ +#define off_t _off_t + + +#endif /* defined(_OS2) */ + +/********************** End of OS-specific definitions ***********************/ + +/* Signed size type */ +#ifndef _SSIZE_T_DEFINED +#if defined(_MSDOS) +typedef int ssize_t; +#elif defined(_WIN32) +#include +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif /* defined(_WIN64) */ +#endif /* defined(_WIN32) */ +#define _SSIZE_T_DEFINED +#endif /* !_SSIZE_T_DEFINED */ + +/* MsvcLibX handles uid_t and gid_t in pwd.c and grp.c */ +typedef int gid_t; +typedef int uid_t; + +/* MsvcLibX uses mode_t in sys/stat.h */ +typedef int mode_t; +#define HAVE_MODE_T + +/* File link counts type (not used by MsvcLibX so far) */ +typedef int nlink_t; /* Is short in some Unix versions */ + +#endif /* !defined(_MSVCLIBX_SYS_TYPES_H) */ + diff --git a/deps/MsvcLibX/src/GetFileAttributes.c b/deps/MsvcLibX/src/GetFileAttributes.c new file mode 100644 index 0000000000000000000000000000000000000000..386114ed70d1fd7ab50b5b027b7f469f8a6b33cd --- /dev/null +++ b/deps/MsvcLibX/src/GetFileAttributes.c @@ -0,0 +1,67 @@ +/*****************************************************************************\ +* * +* Filename GetFileAttributes.c * +* * +* Description: UTF-8 version of WIN32's GetFileAttributes() * +* * +* Notes: * +* * +* History: * +* 2016-09-12 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#include /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include "msvcLimits.h" + +/*---------------------------------------------------------------------------*\ +* * +| Function: GetFileAttributesU | +| | +| Description: Get atributes for a UTF-8 path. | +| | +| Parameters: See WIN32's GetFileAttributes() | +| | +| Return value: The file attributes flags | +| | +| Notes: | +| | +| History: | +| 2014-07-02 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +DWORD WINAPI GetFileAttributesU(LPCTSTR lpFileName) { + WCHAR *pwszName; + DWORD dwAttrs; + int n; + + /* Allocate a buffer large enough for any Unicode pathname */ + pwszName = (void *)LocalAlloc(LMEM_FIXED, UNICODE_PATH_MAX * sizeof(WCHAR)); + if (!pwszName) return 0; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + lpFileName, /* lpMultiByteStr, */ + pwszName, /* lpWideCharStr, */ + UNICODE_PATH_MAX /* cchWideChar, */ + ); + if (!n) { + LocalFree((HLOCAL)pwszName); + return 0; + } + + /* Get the file attributes, using the Unicode version of the function */ + dwAttrs = GetFileAttributesW(pwszName); + + /* Cleanup and return */ + LocalFree((HLOCAL)pwszName); + return dwAttrs; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/GetFileAttributesEx.c b/deps/MsvcLibX/src/GetFileAttributesEx.c new file mode 100644 index 0000000000000000000000000000000000000000..caf3c27342eab0b09e9b2e00eb0b22dd80d5ea37 --- /dev/null +++ b/deps/MsvcLibX/src/GetFileAttributesEx.c @@ -0,0 +1,72 @@ +/*****************************************************************************\ +* * +* Filename GetFileAttributesEx.c * +* * +* Description: UTF-8 version of WIN32's GetFileAttributesEx() * +* * +* Notes: * +* * +* History: * +* 2016-09-12 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#include /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include "msvcLimits.h" + +/*---------------------------------------------------------------------------*\ +* * +| Function: GetFileAttributesExU | +| | +| Description: Get file information for a UTF-8 pathname. | +| | +| Parameters: See WIN32's GetFileAttributesEx() | +| | +| Return value: 1 = done, or 0 if error | +| | +| Notes: Sets the file length, dates, attributes, etc. | +| | +| History: | +| 2016-09-12 JFL Created this routine. | +* * +\*---------------------------------------------------------------------------*/ + +BOOL WINAPI GetFileAttributesExU( + LPCTSTR lpFileName, + GET_FILEEX_INFO_LEVELS fInfoLevelId, + LPVOID lpFileInformation +) { + WIN32_FILE_ATTRIBUTE_DATA *lpFileData = lpFileInformation; + WCHAR *pwszName; + BOOL bDone; + int n; + + /* Allocate a buffer large enough for any Unicode pathname */ + pwszName = (void *)LocalAlloc(LMEM_FIXED, UNICODE_PATH_MAX * sizeof(WCHAR)); + if (!pwszName) return 0; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + lpFileName, /* lpMultiByteStr, */ + pwszName, /* lpWideCharStr, */ + UNICODE_PATH_MAX /* cchWideChar, */ + ); + if (!n) { + LocalFree((HLOCAL)pwszName); + return 0; + } + + /* Get the file information, using the Unicode version of the function */ + bDone = GetFileAttributesExW(pwszName, fInfoLevelId, lpFileData); + + /* Cleanup and return */ + LocalFree((HLOCAL)pwszName); + return bDone; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/GetFullPathName.c b/deps/MsvcLibX/src/GetFullPathName.c new file mode 100644 index 0000000000000000000000000000000000000000..4e9afeec3e9f197d66bdc587bddeeff98b24da8d --- /dev/null +++ b/deps/MsvcLibX/src/GetFullPathName.c @@ -0,0 +1,96 @@ +/*****************************************************************************\ +* * +* Filename GetFullPathName.c * +* * +* Description: UTF-8 version of WIN32's GetFullPathName() * +* * +* Notes: * +* * +* History: * +* 2016-09-12 JFL Created this file, from the routine in truename.c. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#include /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include "msvcLimits.h" +#include "msvcDebugm.h" /* MsvcLibX debugging macros */ + +/*---------------------------------------------------------------------------*\ +* * +| Function: GetFullPathNameU | +| | +| Description: Get the absolute pathname for a relative UTF-8 path. | +| | +| Parameters: See WIN32's GetFullPathName() | +| | +| Return value: The length of the full pathname, or 0 if error | +| | +| Notes: Warning: Windows' GetFullPathname trims trailing dots and | +| spaces from the path. | +| This derived function reproduces the bug. | +| The caller MUST add trailing dots & spaces back if needed.| +| | +| History: | +| 2014-02-07 JFL Created this routine. | +* * +\*---------------------------------------------------------------------------*/ + +DWORD WINAPI GetFullPathNameU(LPCTSTR lpName, DWORD nBufferLength, LPTSTR lpBuf, LPTSTR *lpFilePart) { + WCHAR wszName[MAX_PATH]; + WCHAR wszBuf[MAX_PATH]; + char szName[MAX_PATH*4]; /* Worst case for UTF-8 is 4 bytes/Unicode character */ + int n; + DWORD dwResult; + WCHAR *wlpFilePart; + + DEBUG_ENTER(("GetFullPathNameU(\"%s\", %d, %p, %p);\n", lpName, nBufferLength, lpBuf, lpFilePart)); + + n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + lpName, /* lpMultiByteStr, */ + lstrlen(lpName)+1, /* cbMultiByte, */ + wszName, /* lpWideCharStr, */ + MAX_PATH /* cchWideChar, */ + ); + if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the name to Unicode\n")); + + dwResult = GetFullPathNameW(wszName, MAX_PATH, wszBuf, &wlpFilePart); + if (!dwResult) RETURN_INT_COMMENT(0, ("GetFullPathNameW() failed\n")); + + /* nRead = UnicodeToBytes(pwStr, len, buf, bufsize); */ + n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + wszBuf, /* lpWideCharStr, */ + (int)dwResult + 1, /* cchWideChar, */ + lpBuf, /* lpMultiByteStr, */ + (int)nBufferLength, /* cbMultiByte, */ + NULL, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the full name from Unicode\n")); + + if (lpFilePart) { /* Convert the file part, and get the length of the converted string */ + int m; /* Length of the converted string */ + m = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + wlpFilePart, /* lpWideCharStr, */ + lstrlenW(wlpFilePart), /* cchWideChar, */ + szName, /* lpMultiByteStr, */ + sizeof(szName), /* cbMultiByte, */ + NULL, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + /* (n-1) is the length of the full UTF-8 pathname */ + /* So ((n-1) - m) is the offset of the file part in the full UTF-8 pathname */ + *lpFilePart = lpBuf + (n - 1) - m; + } + + RETURN_INT_COMMENT(n-1, ("\"%s\" \"%s\"\n", lpBuf, lpFilePart?*lpFilePart:"(NULL)")); +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/GetLongPathName.c b/deps/MsvcLibX/src/GetLongPathName.c new file mode 100644 index 0000000000000000000000000000000000000000..b0bbc245d94ebe0aa5f50ba37b394daa0d97f3e8 --- /dev/null +++ b/deps/MsvcLibX/src/GetLongPathName.c @@ -0,0 +1,75 @@ +/*****************************************************************************\ +* * +* Filename GetLongPathName.c * +* * +* Description: UTF-8 version of WIN32's GetLongPathName() * +* * +* Notes: * +* * +* History: * +* 2016-09-12 JFL Created this file, from the routine in truename.c. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#include /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include "msvcLimits.h" +#include "msvcDebugm.h" /* MsvcLibX debugging macros */ + +/*---------------------------------------------------------------------------*\ +* * +| Function: GetLongPathNameU | +| | +| Description: Get the long pathname for a short UTF-8 path. | +| | +| Parameters: See WIN32's GetLongPathName() | +| | +| Return value: The length of the full pathname, or 0 if error | +| | +| Notes: | +| | +| History: | +| 2015-12-18 JFL Created this routine. | +* * +\*---------------------------------------------------------------------------*/ + +DWORD WINAPI GetLongPathNameU(LPCTSTR lpShortName, LPTSTR lpBuf, DWORD nBufferLength) { + WCHAR wszShortName[MAX_PATH]; + WCHAR wszBuf[MAX_PATH]; + int n; + DWORD dwResult; + + DEBUG_ENTER(("GetLongPathNameU(\"%s\", %p, %d);\n", lpShortName, lpBuf, nBufferLength)); + + n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + lpShortName, /* lpMultiByteStr, */ + lstrlen(lpShortName)+1, /* cbMultiByte, */ + wszShortName, /* lpWideCharStr, */ + MAX_PATH /* cchWideChar, */ + ); + if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the short name to Unicode\n")); + + dwResult = GetLongPathNameW(wszShortName, wszBuf, MAX_PATH); + if (!dwResult) RETURN_INT_COMMENT(0, ("GetLongPathNameW() failed\n")); + + /* nRead = UnicodeToBytes(pwStr, len, buf, bufsize); */ + n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + wszBuf, /* lpWideCharStr, */ + (int)dwResult + 1, /* cchWideChar, */ + lpBuf, /* lpMultiByteStr, */ + (int)nBufferLength, /* cbMultiByte, */ + NULL, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the Long name from Unicode\n")); + + RETURN_INT_COMMENT(n-1, ("\"%s\"\n", lpBuf)); +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/access.c b/deps/MsvcLibX/src/access.c new file mode 100644 index 0000000000000000000000000000000000000000..77f0b8341066c0a8a1e34c87f5eeffa8c174bd81 --- /dev/null +++ b/deps/MsvcLibX/src/access.c @@ -0,0 +1,68 @@ +/*****************************************************************************\ +* * +* Filename access.c * +* * +* Description: WIN32 UTF-8 version of access * +* * +* Notes: * +* * +* History: * +* 2014-03-24 JFL Created this module. * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include +#include "msvcStdio.h" +#include "msvclibx.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function access | +| | +| Description UTF-8 version of access | +| | +| Parameters char *pszName File name | +| int iMode Access mode to test | +| | +| Returns File handle | +| | +| Notes | +| | +| History | +| 2014-03-24 JFL Created this routine. | +| 2014-07-02 JFL Added support for pathnames >= 260 characters. | +* * +\*---------------------------------------------------------------------------*/ + +int _accessU(const char *pszName, int iMode) { + WCHAR wszName[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszName, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + COUNTOF(wszName) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + + return _waccess(wszName, iMode); +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/basename.c b/deps/MsvcLibX/src/basename.c new file mode 100644 index 0000000000000000000000000000000000000000..c442a40626e61c441bb38c44ff61d09ce495370f --- /dev/null +++ b/deps/MsvcLibX/src/basename.c @@ -0,0 +1,59 @@ +/*****************************************************************************\ +* * +* Filename basename.c * +* * +* Description Get the file name part of a file pathname * +* * +* Notes Uses a static buffer in some cases. Not thread safe! * +* Posix spec authorizes this, and also authorizes to modify * +* the input string, which we do. => Always do an strdup() * +* before calling basename(), and call basename(copy). * +* * +* History * +* 2016-09-08 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvclibx.h" + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ 2005 security warnings */ + +#include +#include +#include "msvcStdlib.h" +#include "msvcLibgen.h" +#include "msvcLimits.h" + +#define TRUE 1 +#define FALSE 0 + +char *basename(char *pszPathname) { + char *pszPath = pszPathname; + size_t len; + char *pc; + char *pc2; + + /* A NULL pathname is assumed to refer to the current directory */ + if (!pszPathname) return "."; + /* Skip the drive if present */ + len = strlen(pszPathname); + if ((len >= 2) && (pszPathname[1] == ':')) { + pszPath += 2; + len -= 2; + } + if (!len) return "."; + /* Remove trailing path separators */ + while ((len > 1) && ((pszPath[len-1] == '\\') || (pszPath[len-1] == '/'))) { + pszPath[--len] = '\0'; + } + /* Find the beginning of the file name */ + pc = strrchr(pszPath, '\\'); + pc2 = strrchr(pszPath, '/'); + if (pc2 > pc) pc = pc2; + if (pc) pc += 1; else pc = pszPath; + if (!*pc) return pszPath; /* No file name left. This is the root directory */ + /* Done */ + return pc; +} diff --git a/deps/MsvcLibX/src/chdir.c b/deps/MsvcLibX/src/chdir.c new file mode 100644 index 0000000000000000000000000000000000000000..8d562f885f6ac5071e554916dba49671e5c65260 --- /dev/null +++ b/deps/MsvcLibX/src/chdir.c @@ -0,0 +1,149 @@ +/*****************************************************************************\ +* * +* Filename chdir.c * +* * +* Description: WIN32 port of standard C library's chdir() * +* * +* Notes: * +* * +* History: * +* 2014-02-28 JFL Created this module. * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +/* Microsoft C libraries include files */ +#include +#include +/* MsvcLibX library extensions */ +#include "msvcStdio.h" +#include "msvcUnistd.h" +#include "msvcIconv.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" +#include "sys/msvcTypes.h" + +#if defined(_MSDOS) + +/*---------------------------------------------------------------------------*\ +| * +| Function: chdir | +| | +| Description: Change directory, overcoming the 64-character DOS limit | +| | +| Parameters: char *pszDir Target directory pathname | +| | +| Returns: 0=Done; Else OS error code. | +| | +| Notes: Unfortunately this works only in a DOS box within Win9X. | +| | +| History: | +| 2000-12-04 JFL Initial implementation. | +* * +\*---------------------------------------------------------------------------*/ + +int chdir(const char *pszDir) + { + char szBuf[64]; + char *pszBuf = szBuf; + char *pc; + int iDirLen; + int iStrLen; + int iErr = 0; + + iDirLen = strlen(pszDir); + /* Copy the drive letter if specified, and leave it ahead of the buffer. */ + if ((iDirLen>2) && (pszDir[1]==':')) + { + szBuf[0] = pszDir[0]; + szBuf[1] = ':'; + pszDir += 2; + pszBuf += 2; + } + /* Repeat relative moves down the directory tree */ + while (iDirLen > 60) + { + pc = strchr(pszDir+45, '\\'); /* There has to be one in segment [45:60]. */ + iStrLen = pc-pszDir; /* Segment length */ + strncpy(pszBuf, pszDir, iStrLen); /* Copy until the \ found */ + pszBuf[iStrLen] = '\0'; + iErr = chdir(szBuf); + if (iErr) return iErr; + pszDir += iStrLen+1; + iDirLen -= iStrLen+1; + } ; + + if (iDirLen) + { + strcpy(pszBuf, pszDir); + iErr = chdir(szBuf); + } + + return iErr; + } + +#endif /* defined(_MSDOS) */ + + +#if defined(_WIN32) + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: chdir | +| | +| Description: Set the current directory, encoded in UTF-8 | +| | +| Parameters: const char *pszDir Target directory pathname | +| | +| Returns: 0=Done; Else OS error code. | +| | +| History: | +| 2014-02-28 JFL Created this routine | +| 2014-07-02 JFL Added support for pathnames >= 260 characters. | +* * +\*---------------------------------------------------------------------------*/ + +int chdirA(const char *pszDir) { + WCHAR wszDir[PATH_MAX]; + BOOL bDone; + int n; + DEBUG_PRINTF(("chdir(\"%s\");\n", pszDir)); + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszDir, /* lpMultiByteStr, */ + wszDir, /* lpWideCharStr, */ + COUNTOF(wszDir) /* cchWideChar, */ + ); + bDone = SetCurrentDirectoryW(wszDir); + if (!bDone) { + errno = Win32ErrorToErrno(); + } + return bDone ? 0 : -1; +} + +int chdirU(const char *pszDir) { + WCHAR wszDir[PATH_MAX]; + BOOL bDone; + int n; + DEBUG_PRINTF(("chdir(\"%s\");\n", pszDir)); + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszDir, /* lpMultiByteStr, */ + wszDir, /* lpWideCharStr, */ + COUNTOF(wszDir) /* cchWideChar, */ + ); + bDone = SetCurrentDirectoryW(wszDir); + if (!bDone) { + errno = Win32ErrorToErrno(); + } + return bDone ? 0 : -1; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/clock_gettime.c b/deps/MsvcLibX/src/clock_gettime.c new file mode 100644 index 0000000000000000000000000000000000000000..fee7532e2e552ec08b615e61e3f4d79276ea6cfc --- /dev/null +++ b/deps/MsvcLibX/src/clock_gettime.c @@ -0,0 +1,48 @@ +/*****************************************************************************\ +* * +* Filename: clock_gettime.c * +* * +* Description: WIN32 port of standard C library's clock_gettime(). * +* * +* Notes: * +* * +* History: * +* 2014-06-04 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvclibx.h" + +#include +#include + + +#ifdef _MSDOS + +/* Check for the definition of _STRUCT_TIMESPEC before using clock_gettime(). + If it's not defined, use time() instead, which is supported by all OSs. */ + +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN /* Avoid lots of unnecessary inclusions */ +#include +#include "msvcTime.h" +#include "sys/msvcStat.h" /* For MsvcLibX's Filetime2Timespec */ + +int clock_gettime(clockid_t clock_id, struct timespec *pTS) { + FILETIME ft; + if (clock_id != CLOCK_REALTIME) { + errno = EINVAL; + return -1; + } + GetSystemTimeAsFileTime(&ft); + Filetime2Timespec(&ft, pTS); + return 0; +} + +#endif /* defined(_WIN32) */ diff --git a/deps/MsvcLibX/src/debugv.c b/deps/MsvcLibX/src/debugv.c new file mode 100644 index 0000000000000000000000000000000000000000..5d410c1309f8e1f99d133865b0d0272958e766ce --- /dev/null +++ b/deps/MsvcLibX/src/debugv.c @@ -0,0 +1,23 @@ +/*****************************************************************************\ +* * +* Filename: debugv.c * +* * +* Description: Define debug variables used by MsvcLibX.lib in debug mode * +* * +* Notes: * +* * +* History: * +* 2013-03-27 JFL jf.larvoire@hp.com created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvcDebugm.h" + +#if defined(_DEBUG) + +DEBUG_GLOBALS + +#endif /* !defined(_DEBUG) */ + diff --git a/deps/MsvcLibX/src/dirent.c b/deps/MsvcLibX/src/dirent.c new file mode 100644 index 0000000000000000000000000000000000000000..1ab2e9c002d67f4c0c703f8294e997d9e4b5b641 --- /dev/null +++ b/deps/MsvcLibX/src/dirent.c @@ -0,0 +1,709 @@ +/*****************************************************************************\ +* * +* Filename: dirent.c * +* * +* Description: DOS/WIN32 port of standard C library's dirent.h functions * +* * +* Notes: TO DO: Make Wide & MultiByte versions of scandir 4 Windows* +* * +* There are also remains of an OS/2 implementation here. * +* It's not maintained anymore. Left in as a historic * +* reference, in the unlikely case somebody needs it. * +* * +* History: * +* 2012-01-09 JFL Created this file, based on dirc and other programs. * +* 2012-01-19 JFL Added standard errno management. * +* 2012-05-22 JFL Fixed a bug in the DOS version, which failed if the * +* directory name was longer than 12 bytes. * +* 2012-05-23 JFL Fixed opendir to return errors as per the C lib spec. * +* 2013-02-12 JFL Added code to filter reparse points, and keep only * +* real junctions and symlinks. * +* 2013-02-13 JFL Moved dirent2stat() to lstat.c, as there must actually * +* be 4 WIN32 versions, for the four versions of struct stat.* +* 2013-02-26 JFL Moved the proprietary file time management routines to * +* the new filetime.c module. * +* 2014-02-27 JFL Changed the WIN32 output name encoding to UTF-8. * +* 2014-03-20 JFL Restructured Windows opendir and readdir functions into * +* Wide and MultiByte versions, and changed the Unicode and * +* Ansi versions to macros. * +* 2014-03-24 JFL Renamed "statx.h" as the standard . * +* 2015-12-14 JFL Bug fix: WIN32 readdirW always read the root on "D:". * +* Bug fix: DOS opendir failed on root dirs, like "D:\". * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of WIN32 printf & scandir */ + +#include "msvcDirent.h" /* Include our associated .h, in the same dir as this .c. Do not use <>. */ +#ifndef _DIRENT_FOR_DOS_WINDOWS +#error "This requires MsvcLibX own version of dirent.h for DOS/Windows" +#endif +/* Microsoft C libraries include files */ +#include +#include +#include +#include +#include +/* MsvcLibX library extensions */ +#include "msvcUnistd.h" /* For readlink() */ +#include "sys/msvcStat.h" /* For Filetime2String() */ +#include "msvcDebugm.h" /* Use our house debugging framework */ +#include "msvcLimits.h" /* Use our house debugging framework */ + +/*****************************************************************************\ +* * +* MS_DOS Version * +* * +\*****************************************************************************/ + +#ifdef _MSDOS + +#define OFFSET_OF(pointer) ((uint16_t)(uint32_t)(void far *)pointer) +#define SEGMENT_OF(pointer) ((uint16_t)(((uint32_t)(void far *)pointer) >> 16)) + +void put_dta(char *p_dta) { /* Set the MS-DOS Disk Transfer Address */ + union REGS inreg; + union REGS outreg; + struct SREGS sregs; + + inreg.h.ah = 0x1a; + inreg.x.dx = OFFSET_OF(p_dta); + sregs.ds = SEGMENT_OF(p_dta); + + intdosx(&inreg, &outreg, &sregs); +} + +#define CF 0x0001 /* Carry flag bit mask */ + +int get_file_attributes(const char *name, unsigned *pAttr) { /* Get File Attributes */ + union REGS inreg; + union REGS outreg; + struct SREGS sregs; + + inreg.x.ax = 0x4300; + inreg.x.dx = OFFSET_OF(name); + sregs.ds = SEGMENT_OF(name); + + intdosx(&inreg, &outreg, &sregs); + + if (CF & outreg.x.cflag) { + errno = outreg.x.ax; + return errno; + } + + *pAttr = outreg.x.cx; + return 0; +} + +/* Workaround for a VMWare player shared folders bug: + DOS function 4e (search next) sometimes returns several times the same entry. */ +static fileinfo previousFI; +#ifdef _DEBUG +static int report_workaround(char *s) { + DEBUG_PRINTF((s)); + return 1; +} +#define REPORT_WORKAROUND(args) report_workaround args +#else +#define REPORT_WORKAROUND(args) 1 +#endif + +int srch1st(char *pszFile, uint16_t wAttr, fileinfo *pInfo) { /* Search first matching file */ + union REGS inreg; + union REGS outreg; + struct SREGS sregs; + + DEBUG_ENTER(("srch1st(\"%s\", 0x%04X, 0x%p);\n", pszFile, wAttr, pInfo)); + + /* Make sure the DTA is assigned before calling DOS functions 4E and 4F */ + put_dta((char *)pInfo); + + inreg.h.ah = 0x4e; + inreg.x.cx = wAttr; + inreg.x.dx = OFFSET_OF(pszFile); + sregs.ds = SEGMENT_OF(pszFile); + + intdosx(&inreg, &outreg, &sregs); + + if (CF & outreg.x.cflag) { + DEBUG_LEAVE(("return %d; // DOS error code\n", outreg.x.ax)); + return (int)(outreg.x.ax); + } + + previousFI = *pInfo; /* Save it for the workaround for the VMWare player bug */ + + DEBUG_LEAVE(("return 0; // Success\n")); + return 0; +} + +int srchnext(fileinfo *pInfo) { /* Search next matching file */ + union REGS inreg; + union REGS outreg; + + DEBUG_ENTER(("srchnext(0x%p);\n", pInfo)); + + /* Make sure the DTA is assigned before calling DOS functions 4E and 4F */ + put_dta((char *)pInfo); + + inreg.h.ah = 0x4f; + + do { + intdos(&inreg, &outreg); + + if (CF & outreg.x.cflag) { + DEBUG_LEAVE(("return %d; // DOS error code\n", outreg.x.ax)); + return(outreg.x.ax); + } + } while ((!strncmp(previousFI.fiFileName, pInfo->fiFileName, sizeof(previousFI))) + && REPORT_WORKAROUND(("// Skipped one duplicate entry\n"))); + + previousFI = *pInfo; /* Save it for the workaround for the VMWare player bug */ + + DEBUG_LEAVE(("return 0; // Success\n")); + return 0; +} + +DIR *opendir(const char *name) { /* Open a directory */ + DIR *pDir = NULL; + size_t lName; + unsigned attr; + char *pszWildCards = "\\*.*"; + char *pszCopy; + DEBUG_ENTER(("opendir(\"%s\");\n", name)); + lName = strlen(name); + if (lName == 0) { +opendir_noent: + errno = ENOENT; +opendir_failed: + if (!_sys_errlist[ENOTDIR][0]) _sys_errlist[ENOTDIR] = "Not a directory"; /* Workaround for the missing entry in MSVC list */ + if (pDir) free(pDir); + DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno))); + return NULL; + } + pDir = (DIR *)malloc(sizeof(DIR) + lName + 5); /* + 5 for wildcards suffix */ + if (!pDir) goto opendir_failed; + /* Work on a copy of the directory name */ + pszCopy = (char *)(pDir + 1); + strcpy(pszCopy, name); + /* First change: Except for the root, Remove the trailing \s, which confuses get_file_attributes() */ + while ((lName > 1) && (name[lName-1] == '\\') && (name[lName-2] != ':')) pszCopy[--lName] = '\0'; + if (get_file_attributes(pszCopy, &attr)) goto opendir_noent; + if (!(attr & _A_SUBDIR)) { + errno = ENOTDIR; + goto opendir_failed; + } + if (name[lName-1] == '\\') pszWildCards += 1; /* Avoid duplicating the \ */ + strcpy(pszCopy+lName, pszWildCards); + pDir->first = 1; + DEBUG_LEAVE(("return 0x%p;\n", pDir)); + return pDir; +} + +int closedir(DIR *pDir) { /* Close the directory. Return 0 if successful, -1 if not. */ + DEBUG_PRINTF(("closedir(0x%p);\n", pDir)); + if (pDir) free(pDir); + return 0; +} + +_dirent *readdir(DIR *pDir) { /* Read a directory entry. Return pDir, or NULL for EOF or error. */ + int iErr; + _dirent *pDirent = &pDir->sDirent; + fileinfo *pFI = (fileinfo *)(pDirent->d_reserved); /* Address of the fileinfo structure embedded there */ +#ifdef _DEBUG + char szTime[40]; +#endif + + DEBUG_ENTER(("readdir(0x%p);\n", pDir)); + if (pDir->first) { /* First search */ + iErr = srch1st((char *)(pDir+1), 0x3F, pFI); + pDir->first = 0; + } else { + iErr = srchnext(pFI); + } + if (!iErr) { + pDirent->d_type = DT_REG; /* A normal file by default */ + if (pDirent->d_attribs & _A_SUBDIR) pDirent->d_type = DT_DIR; /* Subdirectory */ + if (pDirent->d_attribs & _A_VOLID) pDirent->d_type = DT_VOLID; /* Volume ID file */ + DEBUG_LEAVE(("return 0x%p; // %s %02X %10ld %s\n", + pDirent, + Filetime2String(pDirent->d_date, pDirent->d_time, szTime, sizeof(szTime)), + pDirent->d_attribs, + pDirent->d_filesize, + pDirent->d_name)); + return &pDir->sDirent; + } + switch (iErr) { /* Correct a few errors that do not map well to C library errors */ + case ESRCH: iErr = ENOTDIR; break; + case EXDEV: iErr = 0; break; /* End of files is NOT an error */ + } + if (iErr) { + errno = iErr; /* MS-DOS' errno.h maps C-library errnos to DOS' errors */ + DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno))); + } else { + DEBUG_LEAVE(("return NULL; // End of directory\n")); + } + return NULL; +} + +#endif /* defined(_MSDOS) */ + +/*****************************************************************************\ +* * +* WIN32 Version * +* * +\*****************************************************************************/ + +#ifdef _WIN32 + +#include + +/* Requires including windows.h and especially the kernel section */ + +DIR *opendirW(const WCHAR *wszName) { /* Open a directory - Wide char version */ + DIR *pDir; + int err; + DWORD dw; + DEBUG_CODE( + char szUtf8[UTF8_PATH_MAX]; + ) + + DEBUG_WSTR2UTF8(wszName, szUtf8, sizeof(szUtf8)); + DEBUG_ENTER(("opendir(\"%s\");\n", szUtf8)); + + dw = GetFileAttributesW(wszName); + err = 0; + if (dw == INVALID_FILE_ATTRIBUTES) { + err = errno = Win32ErrorToErrno(); + } else { + if (!(dw & _A_SUBDIR)) { + err = errno = ENOTDIR; + } + } + if (err) { + RETURN_CONST_COMMENT(NULL, ("errno=%d - %s\n", errno, strerror(errno))); + } + if (lstrlenW(wszName) >= sizeof(pDir->wszDirName)) { + errno = ENAMETOOLONG; + RETURN_CONST_COMMENT(NULL, ("errno=%d - %s\n", errno, strerror(errno))); + } + pDir = malloc(sizeof(DIR)); + if (!pDir) { + errno = ENOMEM; + RETURN_CONST_COMMENT(NULL, ("errno=%d - %s\n", errno, strerror(errno))); + } + pDir->hFindFile = INVALID_HANDLE_VALUE; + lstrcpyW(pDir->wszDirName, wszName); + DEBUG_LEAVE(("return 0x%p; // Success\n", pDir)); + return pDir; +} + +DIR *opendirM(const char *name, UINT cp) { /* Open a directory - MultiByte char version */ + WCHAR wszName[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + name, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + COUNTOF(wszName) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("opendirM(\"%s\"); // Can't convert name to Unicode: errno=%d - %s\n", name, errno, strerror(errno))); + return NULL; + } + + return opendirW(wszName); +} + +int closedir(DIR *pDir) { /* Close the directory. Return 0 if successful, -1 if not. */ + DEBUG_PRINTF(("closedir(0x%p);\n", pDir)); + if (pDir) { + if (pDir->hFindFile != INVALID_HANDLE_VALUE) FindClose(pDir->hFindFile); + pDir->hFindFile = INVALID_HANDLE_VALUE; + free(pDir); + } + return 0; +} + +/* Read a directory entry. Return pDir, or NULL for EOF or error. Wide char version. */ +_dirent *readdirW(DIR *pDir) { + int iErr = 0; + _dirent *pDirent = &pDir->sDirent; + int bIsJunction = FALSE; + int bIsMountPoint = FALSE; + DWORD dwTag = 0; /* Reparse points tag */ + DWORD dwAttr; + int n; + DEBUG_CODE( + char szTime[40]; + char szUtf8[UTF8_PATH_MAX]; + ) + + DEBUG_ENTER(("readdir(0x%p);\n", pDir)); + + if (pDir->hFindFile == INVALID_HANDLE_VALUE) { + WCHAR wszPattern[MAX_PATH+5]; + lstrcpyW(wszPattern, pDir->wszDirName); + n = lstrlenW(wszPattern); + if (n && (wszPattern[n-1] != L'\\') && (wszPattern[n-1] != L':')) wszPattern[n++] = L'\\'; + lstrcpyW(wszPattern+n, L"*.*"); + pDir->hFindFile = FindFirstFileW(wszPattern, &pDir->wfd); + if (pDir->hFindFile == INVALID_HANDLE_VALUE) { + iErr = Win32ErrorToErrno(); + if (!iErr) iErr = ENOENT; + } + } else { + iErr = !FindNextFileW(pDir->hFindFile, &pDir->wfd); + if (iErr) { + iErr = Win32ErrorToErrno(); + if (!iErr) iErr = ENOENT; + } + } + if (iErr) { + switch (iErr) { /* Correct a few errors that do not map well to C library errors */ + case ESRCH: iErr = ENOTDIR; break; + case EXDEV: iErr = 0; break; /* End of files is NOT an error */ + } + if (iErr) { + errno = iErr; /* Windows' errno.h maps C-library errnos to Windows' errors */ + DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno))); + } else { + DEBUG_LEAVE(("return NULL; // End of directory\n")); + } + return NULL; + } + + /* Set the standard fields */ + lstrcpyW((WCHAR *)(pDirent->d_name), pDir->wfd.cFileName); + dwAttr = pDir->wfd.dwFileAttributes; +check_attr_again: + if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT) { + /* JUNCTIONs and SYMLINKDs both have the FILE_ATTRIBUTE_DIRECTORY flag also set. + // Test the FILE_ATTRIBUTE_REPARSE_POINT flag first, to make sure they're seen as symbolic links. + // + // All symlinks are reparse points, but not all reparse points are symlinks. */ + dwTag = pDir->wfd.dwReserved0; /* No need to call GetReparseTag(), we got it already. */ + switch (dwTag) { + case IO_REPARSE_TAG_MOUNT_POINT: /* NTFS junction or mount point */ + { /* We must read the link to distinguish junctions from mount points. */ + WCHAR wszPath[PATH_MAX]; + WCHAR wszBuf[PATH_MAX]; + ssize_t n = lstrlenW(pDir->wszDirName); + if ((n + 1 + lstrlenW(pDir->wfd.cFileName)) >= PATH_MAX) { + errno = ENAMETOOLONG; /* DIRNAME\LINKNAME won't fit in wszPath[] */ + DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno))); + } + bIsMountPoint = TRUE; + lstrcpyW(wszPath, pDir->wszDirName); + if (n && (wszPath[n-1] != L'\\')) wszPath[n++] = L'\\'; + lstrcpyW(wszPath+n, pDir->wfd.cFileName); + n = readlinkW(wszPath, wszBuf, COUNTOF(wszBuf)); + /* Junction targets are absolute pathnames, starting with a drive letter. Ex: C: */ + /* readlink() fails if the reparse point does not target a valid pathname */ + if (n < 0) goto this_is_not_a_symlink; /* This is not a junction. */ + bIsJunction = TRUE; /* Else this is a junction. Fall through to the symlink case. */ + } + case IO_REPARSE_TAG_SYMLINK: /* NTFS symbolic link */ + pDirent->d_type = DT_LNK; /* Symbolic link */ + break; + default: /* Anything else is definitely not like a Unix symlink */ +this_is_not_a_symlink: + dwAttr &= ~FILE_ATTRIBUTE_REPARSE_POINT; + goto check_attr_again; + } + } else if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) + pDirent->d_type = DT_DIR; /* Subdirectory */ + else if (dwAttr & FILE_ATTRIBUTE_DEVICE) + pDirent->d_type = DT_CHR; /* Device (we don't know if character or block) */ + else + pDirent->d_type = DT_REG; /* A normal file by default */ + + /* Set the OS-specific extensions */ + lstrcpyW((WCHAR *)(pDirent->d_shortname), pDir->wfd.cAlternateFileName); + pDirent->d_attribs = dwAttr; + pDirent->d_ReparseTag = dwTag; + pDirent->d_CreationTime = pDir->wfd.ftCreationTime; + pDirent->d_LastAccessTime = pDir->wfd.ftLastAccessTime; + pDirent->d_LastWriteTime = pDir->wfd.ftLastWriteTime; + (*(ULARGE_INTEGER *)&(pDirent->d_filesize)).LowPart = pDir->wfd.nFileSizeLow; + (*(ULARGE_INTEGER *)&(pDirent->d_filesize)).HighPart = pDir->wfd.nFileSizeHigh; + + DEBUG_WSTR2UTF8((WCHAR *)(pDirent->d_name), szUtf8, sizeof(szUtf8)); + DEBUG_LEAVE(("return 0x%p; // %s 0x%05X %10lld %s\n", + pDirent, + Filetime2String(&pDirent->d_LastWriteTime, szTime, sizeof(szTime)), + (int)(pDirent->d_attribs), + pDirent->d_filesize, + szUtf8)); + return &(pDir->sDirent); +} + +/* Read a directory entry. Return pDir, or NULL for EOF or error. MultiByte char version. */ +_dirent *readdirM(DIR *pDir, UINT cp) { + _dirent *pDirent; + int n; + char *pszDefaultChar; + + pDirent = readdirW(pDir); + if (!pDirent) return NULL; + + /* Convert the name field back to MultiByte encoding */ + pszDefaultChar = (cp == CP_UTF8) ? NULL : "?"; + n = WideCharToMultiByte(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + pDir->wfd.cFileName, /* lpWideCharStr, */ + lstrlenW(pDir->wfd.cFileName)+1, /* cchWideChar, */ + pDirent->d_name, /* lpMultiByteStr, */ + sizeof(pDirent->d_name), /* cbMultiByte, */ + pszDefaultChar, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("readdirM(0x%p); // Error converting name back from Unicode. errno=%d - %s\n", pDir, errno, strerror(errno))); + return NULL; + } + + /* Convert the short name field back to MultiByte encoding */ + n = WideCharToMultiByte(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + pDir->wfd.cAlternateFileName, /* lpWideCharStr, */ + lstrlenW(pDir->wfd.cAlternateFileName)+1, /* cchWideChar, */ + pDirent->d_shortname, /* lpMultiByteStr, */ + sizeof(pDirent->d_shortname), /* cbMultiByte, */ + pszDefaultChar, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("readdirM(0x%p); // Error converting short name back from Unicode. errno=%d - %s\n", pDir, errno, strerror(errno))); + return NULL; + } + + return pDirent; +} + +#endif + +/*****************************************************************************\ +* * +* OS/2 1.x Version * +* * +\*****************************************************************************/ + +#ifdef _OS2 + +/* Requires including os2.h at the beginning of this file, and before that + defining the INCL_DOSFILEMGR constant to enable the necessary section */ + +int SetDirent(DIR *pDir) { /* Convert the FILEFINDBUF to a dirent structure */ + char *pc; + _dirent *pDirent = &pDir->sDirent; + FILEFINDBUF *pbuf = &pDir->buf; + + pbuf->achName[pbuf->cchName] = '\0'; + pc = strrchr(pbuf->achName, '\\'); /* Directory separator character */ + if (!pc) + pc = &pbuf->achName[0]; + else + pc += 1; /* Skip the \ */ + + pDirent->d_name = malloc(strlen(pc)+1); + if (!pDirent->d_name) return ENOMEM; + strcpy(pDirent->d_name, pc); + pDirent->attribs = pbuf->attrFile; + pDirent->d_type = Atype2Dtype(pDirent->attribs); + pDirent->time = *(uint16_t *)&pbuf->ftimeLastWrite; + pDirent->date = *(uint16_t *)&pbuf->fdateLastWrite; + pDirent->filesize = pbuf->cbFile; + + return 0; +} + +int srch1st(char *pszFile, uint8_t bAttrReq, uint8_t bAttrCmp, DIR *pDir) { /* Search first matching file */ + int n; + int err; + + pDir->hDir = -1; + + n = 1; /* Get one file */ + err = DosFindFirst2(pszFile, &pDir->hDir, bAttrReq & 0x7F, &pDir->buf, + sizeof(FILEFINDBUF), &n, FIL_STANDARD, 0L); + if (err || !n) return 1; + + return SetDirent(pDir); +} + +int srchnext(DIR *pDir) { /* Search next matching file */ + int n; + int err; + + n = 1; /* Get one file */ + err = DosFindNext(pDir->hDir, &pDir->buf, sizeof(FILEFINDBUF), &n); + if (err || !n) return 1; + + return SetDirent(&buf); +} + +int srchdone(DIR *pDir) { + int err; + + err = DosFindClose(pDir->hDir); + pDir->hDir = -1; + + return err; +} + +DIR *opendir(const char *name) { /* Open a directory */ + DIR *pDir; + DEBUG_ENTER(("opendir(\"%s\");\n", name)); + err = _access(name, 0); + /* To do: Get the file attributes, and check that it's a directory */ + if (err) { + DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno))); + return NULL; + } + pDir = malloc(sizeof(DIR)); + if (pDir) { + pDir->hDir = -1; + pDir->bAttrReq = _A_HIDDEN | _A_SYSTEM | _A_SUBDIR; + pDir->bAttrCmp = 0; + strcpy(pDir->sDirent.d_name, name); + } + DEBUG_LEAVE(("return 0x%p;\n", pDir)); + return pDir; +} + +int closedir(DIR *pDir) { /* Close the directory. Return 0 if successful, -1 if not. */ + DEBUG_PRINTF(("closedir(0x%p);\n", pDir)); + if (pDir) { + srchdone(pDir); + free(pDir); + } + return 0; +} + +_dirent *readdir(DIR *pDir) { /* Read a directory entry. Return pDir, or NULL for EOF or error. */ + int iErr; + DEBUG_ENTER(("readdir(0x%p);\n", pDir)); + if (pDir->hDir == -1) { + iErr = srch1st(pDir->sDirent.d_name, pDir->bAttrReq, pDir->bAttrCmp, pDir); + } else { + iErr = srchnext(pDir); + } + if (iErr) { + DEBUG_LEAVE(("return NULL; // OS/2 found nothing\n", + return NULL; + } + + DEBUG_LEAVE(("return 0x%p; // OS/2 found: %04X %04X %02X %10lld %s\n", + &pDir->sDirent + (int)(pDirent->time), + (int)(pDirent->date), + (int)(pDirent->attribs), + pDirent->filesize, + pDirent->d_name)); + + + return &pDir->sDirent; +} + +#endif + +/*****************************************************************************\ +* * +* End of OS-specific opendir/readdir/closedir versions * +* * +\*****************************************************************************/ + +/*****************************************************************************\ +* * +* Function: scandir * +* * +* Description: Select entries in a directory * +* * +* Arguments: const char *name Directory name * +* _dirent ***namelist where to store the result array * +* int (*cbSelect)() Selection callback function * +* int (*cbCompare)() Comparison function for sorting it * +* * +* Return value: # of entries in the array, or -1 if error. * +* * +* Notes: * +* * +* History: * +* 2012-01-11 JFL Initial implementation * +* * +\*****************************************************************************/ + +#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */ +int scandir(const char *pszName, + _dirent ***resultList, + int (*cbSelect) (const _dirent *), + int (__cdecl *cbCompare) (const _dirent **, + const _dirent **)) { + int n = 0; + DIR *pDir; + _dirent *pDirent; + _dirent *pDirent2; + _dirent **pList = NULL; + _dirent **pList2; + + DEBUG_ENTER(("scandir(\"%s\", 0x%p, 0x%p, 0x%p);\n", pszName, resultList, cbSelect, cbCompare)); + + pDir = opendir(pszName); + if (!pDir) { + DEBUG_LEAVE(("return -1; // errno=%d\n", errno)); + return -1; + } + + while (pDirent = readdir(pDir)) { + if (cbSelect && !cbSelect(pDirent)) continue; /* We don't want this one. Continue search. */ + /* OK, we've selected this one. So append a copy of this _dirent to the list. */ + n += 1; + pList2 = (_dirent **)realloc(pList, n * sizeof(_dirent *)); + pDirent2 = malloc(sizeof(_dirent)); + if (!pList2 || !pDirent2) { + if (pDirent2) free(pDirent2); + for (n-=1; n>0; ) free(pList[--n]); + /* errno = ENOMEM; /* Out of memory. Should already be set by malloc failure */ + DEBUG_LEAVE(("return -1; // errno=%d\n", errno)); + return -1; + } + *pDirent2 = *pDirent; + pList = pList2; + pList[n-1] = pDirent2; + } + + closedir(pDir); + +/* 2016-09-23 JFL I don't understand why this warning still fires, so leaving it enabled for now */ +#ifdef M_I86TM /* This warning appears only when compiling for the DOS tiny memory model ?!? */ +/* #pragma warning(disable:4220) /* Ignore the "varargs matches remaining parameters" warning */ +#endif + if (cbCompare) qsort(pList, n, sizeof(_dirent *), cbCompare); +#ifdef M_I86TM +#pragma warning(default:4220) /* Ignore the "varargs matches remaining parameters" warning */ +#endif + *resultList = pList; + DEBUG_LEAVE(("return %d;\n", n)); + return n; +} +#pragma warning(default:4706) + +int __cdecl alphasort(const _dirent **ppDE1, const _dirent **ppDE2) { + int ret; + /* Sort names a-la Windows, that is case insensitive */ + ret = _strnicmp((*ppDE1)->d_name, (*ppDE2)->d_name, NAME_MAX); + if (ret) return ret; + /* For the remote chance that we're accessing a Unix share */ + ret = _strnicmp((*ppDE1)->d_name, (*ppDE2)->d_name, NAME_MAX); + if (ret) return ret; + return 0; +} + diff --git a/deps/MsvcLibX/src/dirname.c b/deps/MsvcLibX/src/dirname.c new file mode 100644 index 0000000000000000000000000000000000000000..1bdc9d9ba3e42f7afffc20cf3f7a988ae791450c --- /dev/null +++ b/deps/MsvcLibX/src/dirname.c @@ -0,0 +1,74 @@ +/*****************************************************************************\ +* * +* Filename dirname.c * +* * +* Description Get the parent directory name of a file pathname * +* * +* Notes Uses a static buffer in some cases. Not thread safe! * +* Posix spec authorizes this, and also authorizes to modify * +* the input string, which we do. => Always do an strdup() * +* before calling dirname(), and call dirname(copy). * +* * +* History * +* 2016-09-08 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvclibx.h" + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ 2005 security warnings */ + +#include +#include +#include +#include "msvcLibgen.h" +#include "msvcLimits.h" + +#define TRUE 1 +#define FALSE 0 + +char szLastDriveDirName[4] = "C:."; + +char *dirname(char *pszPathname) { + char *pszPath = pszPathname; + size_t len; + char *pc; + char *pc2; + + /* A NULL pathname is assumed to refer to the current directory */ + if (!pszPathname) return szLastDriveDirName + 2; /* "." */ + /* Skip the drive if present */ + len = strlen(pszPathname); + if (!len) return szLastDriveDirName + 2; /* "." */ + if ((len >= 2) && (pszPathname[1] == ':')) { + pszPath += 2; + len -= 2; + if (!len) { + szLastDriveDirName[0] = pszPathname[0]; /* Warning: Not thread safe! */ + return szLastDriveDirName; /* "D:." */ + } + } + /* Remove trailing path separators */ + while ((len > 1) && ((pszPath[len-1] == '\\') || (pszPath[len-1] == '/'))) { + pszPath[--len] = '\0'; + } + /* Remove the file name */ + pc = strrchr(pszPath, '\\'); + pc2 = strrchr(pszPath, '/'); + if (pc2 > pc) pc = pc2; + if (pc) pc += 1; else pc = pszPath; + *pc = '\0'; + len = pc - pszPath; + if (!len) { + strcpy(pc, "."); /* Yes, the spec says that the dirname of .. is . */ + len = 1; + } + /* Remove trailing path separators */ + while ((len > 1) && ((pszPath[len-1] == '\\') || (pszPath[len-1] == '/'))) { + pszPath[--len] = '\0'; + } + /* Done */ + return pszPathname; +} diff --git a/deps/MsvcLibX/src/err2errno.c b/deps/MsvcLibX/src/err2errno.c new file mode 100644 index 0000000000000000000000000000000000000000..306160f66432a5c8e2e5ddcdaaa3809f773db737 --- /dev/null +++ b/deps/MsvcLibX/src/err2errno.c @@ -0,0 +1,120 @@ +/*****************************************************************************\ +* * +* Filename err2errno.c * +* * +* Description: Convert a WIN32 error to a Unix errno * +* * +* Notes: * +* * +* History: * +* 2014-02-17 JFL Created this module. * +* 2016-10-05 JFL Fixed compatibility with Visual Studio 2003 and older. * +* Removed a few useless special cases, and added EZERO case.* +* Make sure the global errno is _not_ changed by this funct.* +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* Microsoft C libraries include files */ +#include +#include +/* MsvcLibX library extensions */ +#include "msvcDebugm.h" + + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: Win32ErrorToErrno | +| | +| Description: Convert a Win32 system error code to a Posix errno | +| | +| Parameters: DWORD dwError The Win32 error code | +| | +| Returns: The corresponding Posix errno | +| | +| Notes: There's no 1-to-1 correspondance between Windows and | +| Posix errors. This routine attempts to convert codes for | +| the most likely errors for MsvcLibX. | +| Please add those you encounter, that end up in the | +| default category, and incorrectly return EIO by default. | +| | +| Does not change errno. (Contrary to _dosmaperr, etc) | +| You must set errno thereafter if desired. | +| | +| History: | +| 2014-02-05 JFL Created this routine | +| 2014-03-05 JFL Added the default call to _get_errno_from_oserr(). | +| 2015-12-07 JFL Use the new error conversion routine name in the UCRT. | +* * +\*---------------------------------------------------------------------------*/ + +#if defined(_UCRT) /* Visual Studio 14 and later */ +#define _get_errno_from_oserr __acrt_errno_from_os_error /* The name changed in the UCRT */ +#endif + +#if (_MSC_VER < 1400) /* Anything older than Visual Studio 8 (= VS 2003 and older) */ +#pragma message("Defining our own _get_errno_from_oserr()") +extern void __cdecl _dosmaperr(unsigned long); +int _get_errno_from_oserr(unsigned long dwErr) { + _dosmaperr(dwErr); /* Sets errno from WIN32 error */ + return errno; +} +#else +/* Equivalent function in MSVC library. Does not know about symlink errors. */ +extern int __cdecl _get_errno_from_oserr(unsigned long oserrno); +#endif + +int Win32ErrorToErrno() { + DWORD dwError = GetLastError(); + + DEBUG_CODE({ + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, 0, NULL); + DEBUG_PRINTF(("// Win32 error %d (0x%X): %s", dwError, dwError, lpMsgBuf ? lpMsgBuf : "Unknown\n")); + LocalFree( lpMsgBuf ); + }); + + switch (dwError) { + case ERROR_SUCCESS: + return 0; + case ERROR_PRIVILEGE_NOT_HELD: /* Not running with the SE_CREATE_SYMBOLIC_LINK_NAME privilege */ + case ERROR_REPARSE_ATTRIBUTE_CONFLICT: + return EACCES; + case ERROR_INSUFFICIENT_BUFFER: + return E2BIG; + case ERROR_FILE_EXISTS: + case ERROR_ALREADY_EXISTS: + return EEXIST; + case ERROR_WRITE_PROTECT: + return EROFS; + case ERROR_HANDLE_DISK_FULL: + return ENOSPC; + case ERROR_NOT_A_REPARSE_POINT: + case ERROR_REPARSE_TAG_MISMATCH: + case ERROR_INVALID_FLAGS: + case ERROR_INVALID_PARAMETER: + return EINVAL; + case ERROR_INVALID_REPARSE_DATA: + case ERROR_REPARSE_TAG_INVALID: + return EBADF; /* Not supposed to happen in Posix OSs, but may happen when experimenting with junction() IOCTLs. */ + case ERROR_NO_UNICODE_TRANSLATION: + return EILSEQ; + default: { + int errno0, errno1; + errno0 = errno; /* Preserve the initial errno */ + errno1 = _get_errno_from_oserr(dwError); /* Let MSVC library decide. May change errno. */ + errno = errno0; /* Restore the initial errno */ + return errno1; + } + } +} + +#endif /* _WIN32 */ + diff --git a/deps/MsvcLibX/src/filetime.c b/deps/MsvcLibX/src/filetime.c new file mode 100644 index 0000000000000000000000000000000000000000..084b5eef671c0cc17135746bd7d7e7fb6ed68156 --- /dev/null +++ b/deps/MsvcLibX/src/filetime.c @@ -0,0 +1,261 @@ +/*****************************************************************************\ +* * +* Filename filetime.c * +* * +* Description: MsvcLibX internal routines for managing file times * +* * +* Notes: * +* * +* History: * +* 2014-02-26 JFL Created this module. * +* 2014-03-24 JFL Renamed "statx.h" as the standard . * +* 2014-07-03 JFL Filetime2String: Output time with �s precision if possib. * +* 2016-09-13 JFL Fixed a warning. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include "msvcTime.h" /* Define time_t */ +#include "sys/msvcStat.h" + +#ifdef _MSDOS + +/* + Convert a DOS date/time to a Unix time_t + DOS dates start from January 1, 1980. DOS times have a 2-second resolution. + A Unix time_t is the number of 1-second intervals since January 1, 1970. + time_ts are expressed in the GMT time zone. DOS times in the current local time. +*/ +time_t Filetime2Timet(uint16_t date, uint16_t time) { + unsigned int year, month, day, hour, minute, second; + struct tm stm; + + /* Decode fields */ + year = 1980 + ((date & 0xFE00) >> 9); + month = (date & 0x1E0) >> 5; + day = date & 0x1F; + hour = (time & 0xF800) >> 11; + minute = (time & 0x7E0) >> 5; + second = 2 * (time & 0x1F); + + stm.tm_year = (int)year - 1900; + stm.tm_mon = (int)month - 1; + stm.tm_mday = (int)day; + stm.tm_hour = (int)hour; + stm.tm_min = (int)minute; + stm.tm_sec = (int)second; + stm.tm_isdst = -1; /* Let mktime decide if DST is in effect or not */ + + return mktime(&stm); +} + +#if 0 +/* Older version of the same, trying to generate the time_t manually. + Did not handle DST well */ +time_t Filetime2Timet(uint16_t date, uint16_t time) { + unsigned int year, month, day, hour, minute, second; + unsigned int olympiads; /* 4-year periods */ + unsigned long t = 0; + + /* Decode fields */ + year = 1980 + ((date & 0xFE00) >> 9); + month = (date & 0x1E0) >> 5; + day = date & 0x1F; + hour = (time & 0xF800) >> 11; + minute = (time & 0x7E0) >> 5; + second = 2 * (time & 0x1F); + + /* Count days */ + year -= 1970; /* Start of Unix time_t epoch */ + olympiads = year / 4; + year = year % 4; + t = olympiads * (365 + 365 + 366 + 365); + switch (year) { + case 3: t += 366; + case 2: t += 365; + case 1: t += 365; + } + switch (month) { + case 12: t += 30; + case 11: t += 31; + case 10: t += 30; + case 9: t += 31; + case 8: t += 31; + case 7: t += 30; + case 6: t += 31; + case 5: t += 30; + case 4: t += 31; + case 3: t += (year == 2) ? 29 : 28; + case 2: t += 31; + } + t += day-1; + + /* Count seconds */ + t *= 24; + t += hour; + t *= 60; + t += minute; + t *= 60; + t += second; + + /* Correct for the timezone (As DOS returns local times, but time_t is UTC-based) */ + t += timezone; + + /* Still need correction for DST */ + + return (time_t)t; +} +#endif + +/* Generate a string with the local file time, in the ISO 8601 date/time format */ +char *Filetime2String(uint16_t date, uint16_t time, char *pBuf, size_t nBufSize) { + unsigned int year, month, day, hour, minute, second; + + /* Decode fields */ + year = 1980 + ((date & 0xFE00) >> 9); + month = (date & 0x1E0) >> 5; + day = date & 0x1F; + hour = (time & 0xF800) >> 11; + minute = (time & 0x7E0) >> 5; + second = 2 * (time & 0x1F); + + if (nBufSize >= 20) { + sprintf(pBuf, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + } else { + return "Buffer too small"; + } + return pBuf; +} + +#endif /* defined(_MSDOS) */ + +/*****************************************************************************/ + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: LocalFileTime | +| | +| Description: Convert a file GMT time to the local struct tm to display | +| | +| Parameters: const time_t *t The file GMT time_t | +| | +| Returns: struct tm * | +| | +| Notes: This routine is a replacement for Posix' localtime(), | +| using Windows' specific algorithm for generating local | +| file times. | +| | +| Windows displays file times based on the current | +| difference between the local time and GMT. | +| Linux displays file times as the local time when the | +| the file was created. | +| The two times shown may be different if DST was different | +| then and now. (Ex: Displaying in winter the date/time of | +| a file created the previous summer.) | +| The advantage of Windows' method is that apparent | +| relative times will always be correct, even for files | +| created around the winter/summer time transitions. | +| The advantage of Linux method is that the time displayed | +| for a file never changes. The drawback is that files | +| created 1 hour apart around the Winter/summer time | +| transition may be shown with the exact same time. | +| | +| History: | +| 2014-02-26 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +/* + Convert a Windows FILETIME to a Unix time_t. + A FILETIME is the number of 100-nanosecond intervals since January 1, 1601. + A time_t is the number of 1-second intervals since January 1, 1970. + Both Windows and Linux file times are expressed in the GMT time zone. +*/ +time_t Filetime2Timet(const FILETIME *pFT) { + ULARGE_INTEGER ull; + ull.LowPart = pFT->dwLowDateTime; + ull.HighPart = pFT->dwHighDateTime; + return ull.QuadPart / 10000000ULL - 11644473600ULL; +} + +/* Convert a Unix time_t to a Windows FILETIME */ +void Timet2Filetime(time_t t, FILETIME *pFT) { + ULARGE_INTEGER ull; + ull.QuadPart = (t * 10000000ULL) + 116444736000000000ULL; + pFT->dwLowDateTime = ull.LowPart; + pFT->dwHighDateTime = ull.HighPart; + return; +} + +/* + Convert a Windows FILETIME to a Unix struct timespec. + A FILETIME is the number of 100-nanosecond intervals since January 1, 1601. + A struct timespec contains a time_t and a number of nanoseconds. + Both Windows and Linux file times are expressed in the GMT time zone. +*/ +void Filetime2Timespec(const FILETIME *pFT, struct timespec *pTS) { + ULARGE_INTEGER ull; + ull.LowPart = pFT->dwLowDateTime; + ull.HighPart = pFT->dwHighDateTime; + pTS->tv_sec = (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL); + pTS->tv_nsec = (int)(ull.QuadPart % 10000000ULL) * 100; + return; +} + +/* Convert a Unix time_t to a Windows FILETIME */ +void Timespec2Filetime(const struct timespec *pTS, FILETIME *pFT) { + ULARGE_INTEGER ull; + ull.QuadPart = (pTS->tv_sec * 10000000ULL) + 116444736000000000ULL + (pTS->tv_nsec / 100); + pFT->dwLowDateTime = ull.LowPart; + pFT->dwHighDateTime = ull.HighPart; + return; +} + +/* Convert a file GMT time to a struct tm with the local time to display */ +struct tm *LocalFileTime(const time_t *pt) { + FILETIME ft, lft; + time_t lt; + + Timet2Filetime(*pt, &ft); + FileTimeToLocalFileTime(&ft, &lft); + lt = Filetime2Timet(&lft); + return gmtime(<); +} + +/* Generate a string with the local file time, in the ISO 8601 date/time format */ +/* 2014-07-03 Output time with �s precision if possible */ +char *Filetime2String(const FILETIME *pFT, char *pBuf, size_t nBufSize) { + FILETIME lft; + SYSTEMTIME sTime; + + FileTimeToLocalFileTime(pFT, &lft); + FileTimeToSystemTime(&lft, &sTime); + if (nBufSize >= 20) { + wsprintf(pBuf, "%04d-%02d-%02d %02d:%02d:%02d", sTime.wYear, sTime.wMonth, sTime.wDay, + sTime.wHour, sTime.wMinute, sTime.wSecond); + if (nBufSize >= 27) { + ULARGE_INTEGER uli; + int iFraction; /* Fraction of a second */ + uli.LowPart = lft.dwLowDateTime; + uli.HighPart = lft.dwHighDateTime; + iFraction = (int)(uli.QuadPart % 10000000); /* FILETIME has 100ns resolution */ + iFraction /= 10; /* Convert 100ns resolution to 1�s resolution */ + wsprintf(pBuf+19, ".%06d", iFraction); + } else if (nBufSize >= 24) { + wsprintf(pBuf+19, ".%03d", sTime.wMilliseconds); + } + } else { + return NULL; /* Buffer too small */ + } + return pBuf; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/fnmatch.c b/deps/MsvcLibX/src/fnmatch.c new file mode 100644 index 0000000000000000000000000000000000000000..d6f640f4c0529122b46b2826c0ded6e3d933e63e --- /dev/null +++ b/deps/MsvcLibX/src/fnmatch.c @@ -0,0 +1,124 @@ +/*****************************************************************************\ +* * +* Filename: fnmatch.c * +* * +* Description: DOS/WIN32 port of standard C library's fnmatch() * +* * +* Notes: TO DO: Manage FNM_PATHNAME, FNM_PERIOD, FNM_LEADING_DIR. * +* * +* History: * +* 2012-01-17 JFL Created this file. * +* 2013-03-10 JFL In DOS/Windows, the pattern "*.*" actually means "*". * +* 2014-02-13 JFL Removed warnings. * +* 2014-02-14 JFL In DOS/Windows, the pattern "*." means no extension. * +* 2014-02-17 JFL Wildcards match the empty string. * +* 2014-02-20 JFL Fixed "*." pattern matching. * +* 2014-02-28 JFL Added support for UTF-8 pathnames. * +* 2014-03-05 JFL In debug mode, hide recursive calls. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +#include +#include +#include + +#include "msvcFnmatch.h" /* Include our associated .h, in the same dir as this .c. Do not use <>. */ +#include "msvcDebugm.h" + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */ +int fnmatch(const char *pszPattern, const char *pszName, int iFlags) { + char cp, cn; + size_t l; + const char *pc; + int iErr; + DEBUG_CODE( + int iHideRecursions = FALSE; + ) + + DEBUG_ENTER(("fnmatch(\"%s\", \"%s\", 0x%x);\n", pszPattern, pszName, iFlags)); + + DEBUG_CODE(if(DEBUG_IS_ON() && !XDEBUG_IS_ON()) iHideRecursions = TRUE;) + + /* Special case in DOS/Windows: "*.*" will actually match any name, even without a dot */ + if (!strcmp(pszPattern, "*.*")) pszPattern = "*"; + + /* Special case in DOS/Windows: "anything." means anything without extension */ + l = strlen(pszPattern); + if (l && (pszPattern[l-1] == '.')) { + int i; + int lName = (int)strlen(pszName); + /* First eliminate the case of forbidden extensions <==> A '.' anywhere before the last character */ + for (i=0; i<(lName-1); i++) { /* Search for a '.' in the name */ + if (pszName[i] == '.') RETURN_CONST_COMMENT(FNM_NOMATCH, ("Forbidden extension found\n")); + } + /* If the name doesn't end with a dot, Remove the pattern's trailing '.' */ + if (lName && (pszName[lName-1] != '.')) { + char *pszPattern2; + pszPattern2 = _strdup(pszPattern); + pszPattern2[--l] = '\0'; + /* Recursively do the pattern matching with the new pattern */ + DEBUG_CODE(if (iHideRecursions) iDebug -= 1;) + iErr = fnmatch(pszPattern2, pszName, iFlags); + DEBUG_CODE(if (iHideRecursions) iDebug += 1;) + free(pszPattern2); + RETURN_INT(iErr); + } + } + + for ( ; (cp = *pszPattern) && (cn = *pszName); pszPattern++, pszName++) { + XDEBUG_PRINTF(("// cp='%c' cn='%c'\n", cp, cn)); + switch (cp) { + case '?': + if (cn == '.') RETURN_CONST_COMMENT(FNM_NOMATCH, ("? does not match a .\n")); + break; /* Anything else matches. Continue analysing the pattern. */ + case '*': + cp = *(++pszPattern); + if (!cp) RETURN_CONST_COMMENT(FNM_MATCH, ("'*' matches whatever remains in the string\n")); + for ( ; cn = *pszName; pszName++) { + DEBUG_CODE(if (iHideRecursions) iDebug -= 1;) + iErr = fnmatch(pszPattern, pszName, iFlags); + DEBUG_CODE(if (iHideRecursions) iDebug += 1;) + if (iErr == FNM_MATCH) RETURN_CONST(FNM_MATCH); + } + RETURN_CONST_COMMENT(FNM_NOMATCH, ("No tail string matches the remainder of the pattern\n")); + default: + if (iFlags & FNM_CASEFOLD) { + cp = (char)toupper(cp); + cn = (char)toupper(cn); + } + if (cp != cn) RETURN_CONST_COMMENT(FNM_NOMATCH, ("Character mismatch\n")); + break; /* The character matches. Continue analysing the pattern. */ + } + } + /* '*' and '?' match the empty string */ + if (*pszPattern && !*pszName) { + int bOnlyWildCards = TRUE; + for (pc=pszPattern; cp=*pc; pc++) { + if ((cp != '*') && (cp != '?')) { + bOnlyWildCards = FALSE; + break; + } + } + if (bOnlyWildCards) { + RETURN_CONST_COMMENT(FNM_MATCH, ("WildCards match the empty string\n")); + } + } + + /* Special case in DOS/Windows: trailing dot allowed in pattern */ + if ((*pszPattern == '.') && (!*(pszPattern+1)) && (!*pszName)) RETURN_CONST_COMMENT(FNM_MATCH, ("trailing dot matches empty string\n")); + + if (*pszPattern || *pszName) RETURN_CONST_COMMENT(FNM_NOMATCH, ("Something remains that did not match\n")); + + RETURN_CONST_COMMENT(FNM_MATCH, ("Complete match\n")); +} +#pragma warning(default:4706) + diff --git a/deps/MsvcLibX/src/fstat.c b/deps/MsvcLibX/src/fstat.c new file mode 100644 index 0000000000000000000000000000000000000000..124eda81195c777f19cff89a08018cca13eb006e --- /dev/null +++ b/deps/MsvcLibX/src/fstat.c @@ -0,0 +1,118 @@ +/*****************************************************************************\ +* * +* Filename fstat.c * +* * +* Description: Redefinitions of standard C library's fstat() * +* * +* Notes: * +* * +* History: * +* 2014-06-24 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +/* Microsoft C libraries include files */ +#include +#include +#include +#include +/* MsvcLibX library extensions */ +#include "sys/msvcStat.h" +#include "msvcDebugm.h" + + +#if defined(_MSDOS) + +/* Nothing needs to be redefined */ + +#endif /* defined(_MSDOS) */ + + +#if defined(_WIN32) + +/* ------------ Display the *stat* macro values at compile time ------------ */ + +#pragma message(MACRODEF(_MSVC_stat)) +#pragma message(MACRODEF(_MSVC_fstat)) +#pragma message(MACRODEF(_MSVC_lstat)) +#pragma message(MACRODEF(_MSVC_stat64)) + +#if _MSVCLIBX_STAT_DEFINED + #pragma message(MACRODEF(_LIBX_stat)) + #pragma message(MACRODEF(_LIBX_stat64)) +#endif + +#pragma message(MACRODEF(stat)) +#pragma message(MACRODEF(fstat)) +#pragma message(MACRODEF(lstat)) + +#if defined(_LARGEFILE_SOURCE64) + #pragma message(MACRODEF(stat64)) + #pragma message(MACRODEF(fstat64)) + #pragma message(MACRODEF(lstat64)) +#endif + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: fstat | +| | +| Description: Redefine the standard _fstatXY() functions | +| | +| Parameters: int nFile The file handle | +| struct stat *buf Output buffer | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: See sys/stat.h for a description of how the stat and fstat| +| macros work. | +| | +| History: | +| 2014-06-24 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +int fstat(int nFile, struct stat *pStat) { + int iErr; + struct _MSVC_stat msStat; + DEBUG_CODE( + struct tm *pTime; + char szTime[100]; + ) + + DEBUG_ENTER((STRINGIZE(fstat) "(%d, 0x%p);\n", nFile, pStat)); + + iErr = _MSVC_fstat(nFile, &msStat); + if (!iErr) { + ZeroMemory(pStat, sizeof(struct stat)); + pStat->st_mode = msStat.st_mode; + pStat->st_size = msStat.st_size; + pStat->st_ctime = +#undef st_ctime + msStat.st_ctime; + pStat->st_mtime = +#undef st_mtime + msStat.st_mtime; + pStat->st_atime = +#undef st_atime + msStat.st_atime; + DEBUG_CODE( + pTime = LocalFileTime(&(msStat.st_mtime)); + strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", pTime); + ) + RETURN_INT_COMMENT(0, ("%s mode = 0x%04X size = %I64d bytes\n", szTime, pStat->st_mode, (__int64)(pStat->st_size))); + } + /* TO DO: Get the nanosecond time resolution using Windows functions */ + + RETURN_INT_COMMENT(iErr, ("%s\n", strerror(errno))); +} + +#endif /* _WIN32 */ + diff --git a/deps/MsvcLibX/src/fstat64.c b/deps/MsvcLibX/src/fstat64.c new file mode 100644 index 0000000000000000000000000000000000000000..5a54962c8833f24aa64e9b41038d2c91851f8da4 --- /dev/null +++ b/deps/MsvcLibX/src/fstat64.c @@ -0,0 +1,21 @@ +/*****************************************************************************\ +* * +* Filename fstat64.c * +* * +* Description: Redefinitions of standard C library's fstat64() * +* * +* Notes: * +* * +* History: * +* 2014-06-24 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* st_*time is 64-bits __time64_t & st_size is 64-bits __off64_t */ + +#undef _USE_32BIT_TIME_T +#define _FILE_OFFSET_BITS 64 + +#include "fstat.c" diff --git a/deps/MsvcLibX/src/fstat64i32.c b/deps/MsvcLibX/src/fstat64i32.c new file mode 100644 index 0000000000000000000000000000000000000000..cb1dfd445dde9faeb69c6fda2b119d71579c487d --- /dev/null +++ b/deps/MsvcLibX/src/fstat64i32.c @@ -0,0 +1,21 @@ +/*****************************************************************************\ +* * +* Filename fstat64i32.c * +* * +* Description: Redefinitions of standard C library's fstat64i32() * +* * +* Notes: * +* * +* History: * +* 2014-06-24 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* st_*time is 64-bits __time64_t & st_size is 32-bits __off32_t */ + +#undef _USE_32BIT_TIME_T +#define _FILE_OFFSET_BITS 32 + +#include "fstat.c" diff --git a/deps/MsvcLibX/src/fullpath.c b/deps/MsvcLibX/src/fullpath.c new file mode 100644 index 0000000000000000000000000000000000000000..1cc2bf42712c65912298168ddd39094e5bef4363 --- /dev/null +++ b/deps/MsvcLibX/src/fullpath.c @@ -0,0 +1,68 @@ +/*****************************************************************************\ +* * +* Filename fullpath.c * +* * +* Description Get the absolute pathname for a relative UTF-8 path * +* * +* Notes * +* * +* History * +* 2016-09-13 JFL Created this module with routine from truename.c. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +#include +#include +#include "msvcLimits.h" + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#include "msvcWindows.h" /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ + +/*---------------------------------------------------------------------------*\ +* * +| Function: _fullpathU | +| | +| Description: Get the absolute pathname for a relative UTF-8 path | +| | +| Parameters: See MSVC's _fullpath() in stdlib.h | +| | +| Return value: Pointer to the full pathname, or NULL if error | +| | +| Notes: Warning: Windows' GetFullPathname and MSVC's _fullpath | +| trim trailing dots and spaces from the path. | +| This derived function reproduces the bug. | +| The caller MUST add trailing dots & spaces back if needed.| +| | +| History: | +| 2014-03-25 JFL Created this routine. | +| 2017-01-30 JFL Fixed bug when the output buffer is allocated here. | +* * +\*---------------------------------------------------------------------------*/ + +char *_fullpathU(char *absPath, const char *relPath, size_t maxLength) { + char *absPath0 = absPath; + DWORD n; + if (!absPath) { /* Then allocate a buffer for the output string */ + maxLength = UTF8_PATH_MAX; + absPath = malloc(maxLength); /* Worst case for UTF-8 is 4 bytes/Unicode character */ + if (!absPath) return NULL; + } + n = GetFullPathNameU(relPath, (DWORD)maxLength, absPath, NULL); + if (!n) { + errno = Win32ErrorToErrno(); + if (!absPath0) free(absPath); + return NULL; + } + if (!absPath0) absPath = realloc(absPath, strlen(absPath) + 1); + return absPath; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/getcwd.c b/deps/MsvcLibX/src/getcwd.c new file mode 100644 index 0000000000000000000000000000000000000000..314c59504a4ff9e299a02ecf8ce0880925803ff5 --- /dev/null +++ b/deps/MsvcLibX/src/getcwd.c @@ -0,0 +1,153 @@ +/*****************************************************************************\ +* * +* Filename getcwd.c * +* * +* Description: WIN32 port of standard C library's getcwd() * +* * +* Notes: * +* * +* History: * +* 2014-02-28 JFL Created this module. * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +/* Microsoft C libraries include files */ +#include +#include +/* MsvcLibX library extensions */ +#include "msvcUnistd.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#if defined(_MSDOS) + +/* DOS own getcwd() is OK. */ + +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: getcwd | +| | +| Description: Get the current directory, encoded in UTF-8 | +| | +| Parameters: char *buf Buffer for the output | +| size_t bufSize Buffer size | +| | +| Returns: The converted string size. -1=error, and errno set. | +| | +| Notes: We can't use the getcwd name, as MSVC has an incompatible | +| prototype for it. So a getcwd macro calls this routine. | +| | +| History: | +| 2014-02-28 JFL Created this routine | +| 2014-07-02 JFL Added support for pathnames >= 260 characters. | +* * +\*---------------------------------------------------------------------------*/ + +char *getcwdA(char *buf, size_t bufSize) { + int n; + WCHAR wbuf[PATH_MAX]; + DWORD dwSize; + + dwSize = GetCurrentDirectoryW(COUNTOF(wbuf), wbuf); + if (!dwSize) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: GetCurrentDirectoryW() Failed\n", buf, bufSize)); + return NULL; + } + + n = WideCharToMultiByte(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + wbuf, /* lpWideCharStr, */ + dwSize+1, /* cchWideChar, */ + buf, /* lpMultiByteStr, */ + (int)bufSize, /* cbMultiByte, */ + NULL, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: WideCharToMultiByte() Failed\n", buf, bufSize)); + return NULL; + } + + DEBUG_PRINTF(("getcwd(0x%p, %d); // \"%s\"\n", buf, bufSize, buf)); + return buf; +} + +char *getcwdU(char *buf, size_t bufSize) { + int n; + WCHAR wbuf[PATH_MAX]; + DWORD dwSize; + + dwSize = GetCurrentDirectoryW(COUNTOF(wbuf), wbuf); + if (!dwSize) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: GetCurrentDirectoryW() Failed\n", buf, bufSize)); + return NULL; + } + + n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + wbuf, /* lpWideCharStr, */ + dwSize+1, /* cchWideChar, */ + buf, /* lpMultiByteStr, */ + (int)bufSize, /* cbMultiByte, */ + NULL, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: WideCharToMultiByte() Failed\n", buf, bufSize)); + return NULL; + } + + DEBUG_PRINTF(("getcwd(0x%p, %d); // \"%s\"\n", buf, bufSize, buf)); + return buf; +} + +char *_getdcwdA(int iDrive, char *buf, int iBuflen) { + char *pBuf; + int iDrive0 = _getdrive(); + if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive); + pBuf = getcwdA(buf, iBuflen); + if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive0); + DEBUG_CODE( + if (pBuf) { + DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // \"%s\"\n", iDrive, buf, iBuflen, pBuf)); + } else { + DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // Failed\n", iDrive, buf, iBuflen, pBuf)); + } + ) + return pBuf; +} + +char *_getdcwdU(int iDrive, char *buf, int iBuflen) { + char *pBuf; + int iDrive0 = _getdrive(); + if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive); + pBuf = getcwdU(buf, iBuflen); + if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive0); + DEBUG_CODE( + if (pBuf) { + DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // \"%s\"\n", iDrive, buf, iBuflen, pBuf)); + } else { + DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // Failed\n", iDrive, buf, iBuflen, pBuf)); + } + ) + return pBuf; +} + +#endif /* _WIN32 */ + diff --git a/deps/MsvcLibX/src/getopt.c b/deps/MsvcLibX/src/getopt.c new file mode 100644 index 0000000000000000000000000000000000000000..ba0b2ccb33eed34944fcb503c4ae5a763ed09fc2 --- /dev/null +++ b/deps/MsvcLibX/src/getopt.c @@ -0,0 +1,500 @@ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: getopt_long.c,v 1.11 2009/04/14 17:34:41 joerg Exp $ + * 2016-09-15 JFL Adapted v 1.11 for use in the MsvcLibX library + */ + +/* 2016-09-15 JFL Begin changes */ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include +#include +#include +#include +#include +#include "msvcGetopt.h" + +#ifndef _DIAGASSERT +#ifdef NDEBUG +#define _DIAGASSERT(test) +#else +#define _DIAGASSERT(test) assert(test) +#endif +#endif + +#undef __UNCONST +#define __UNCONST(a) ((void *)/*(size_t)*/(const void *)(a)) + +static const char *progname; + +/* Replacement for warnx(3) for systems without it. */ +static void warnx(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (progname) + (void) fprintf(stderr, "%s: ", progname); + if (fmt) + (void) vfprintf(stderr, fmt, ap); + (void) fprintf(stderr, "\n"); + va_end(ap); +} + +#define REPLACE_GETOPT + +/* 2016-09-15 JFL End of changes */ + +#ifdef REPLACE_GETOPT +#ifdef __weak_alias +__weak_alias(getopt,_getopt) +#endif +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +char *optarg; /* argument associated with option */ +#endif +#if !HAVE_DECL_OPTRESET +int optreset; /* reset getopt */ +#endif + +#if 0 +#ifdef __weak_alias +__weak_alias(getopt_long,_getopt_long) +#endif +#endif + +#define IGNORE_FIRST (*options == '-' || *options == '+') +#define PRINT_ERROR ((opterr) && ((*options != ':') \ + || (IGNORE_FIRST && options[1] != ':'))) +#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) +#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) +/* XXX: GNU ignores PC if *options == '-' */ +#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((IGNORE_FIRST && options[1] == ':') \ + || (*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char **, const char *); +static int gcd(int, int); +static void permute_args(int, int, int, char **); + +static const char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return b; +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, char **nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + _DIAGASSERT(nargv != NULL); + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + nargv[pos] = nargv[cstart]; + nargv[cstart] = swap; + } + } +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + * Returns -2 if -- is found (can be long option or end of options marker). + */ +static int +getopt_internal(int nargc, char **nargv, const char *options) +{ + char *oli; /* option letter list index */ + int optchar; + + _DIAGASSERT(nargv != NULL); + _DIAGASSERT(options != NULL); + + optarg = NULL; + + /* + * XXX Some programs (like rsyncd) expect to be able to + * XXX re-initialize optind to 0 and have getopt_long(3) + * XXX properly function again. Work around this braindamage. + */ + if (optind == 0) + optind = 1; + + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return -1; + } + if ((*(place = nargv[optind]) != '-') + || (place[1] == '\0')) { /* found non-option */ + place = EMSG; + if (IN_ORDER) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return INORDER; + } + if (!PERMUTE) { + /* + * if no permutation wanted, stop parsing + * at first non-option + */ + return -1; + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + if (place[1] && *++place == '-') { /* found "--" */ + place++; + return -2; + } + } + if ((optchar = (int)*place++) == (int)':' || + (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { + /* option letter unknown or ':' */ + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return BADCH; + } + if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ + /* XXX: what if no long options provided (called by getopt)? */ + if (*place) + return -2; + + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return BADARG; + } else /* white space */ + place = nargv[optind]; + /* + * Handle -W arg the same as --arg (which causes getopt to + * stop parsing). + */ + return -2; + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = __UNCONST(place); + /* XXX: disable test for :: if PC? (GNU doesn't) */ + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return BADARG; + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return optchar; +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the real getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + int retval; + + _DIAGASSERT(nargv != NULL); + _DIAGASSERT(options != NULL); + + retval = getopt_internal(nargc, __UNCONST(nargv), options); + if (retval == -2) { + ++optind; + /* + * We found an option (--), so if we skipped non-options, + * we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, + (char **)nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + retval = -1; + } + return retval; +} +#endif + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + int retval; + +#define IDENTICAL_INTERPRETATION(_x, _y) \ + (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ + long_options[(_x)].flag == long_options[(_y)].flag && \ + long_options[(_x)].val == long_options[(_y)].val) + + _DIAGASSERT(nargv != NULL); + _DIAGASSERT(options != NULL); + _DIAGASSERT(long_options != NULL); + /* idx may be NULL */ + + retval = getopt_internal(nargc, __UNCONST(nargv), options); + if (retval == -2) { + char *current_argv, *has_equal; + size_t current_argv_len; + int i, ambiguous, match; + + current_argv = __UNCONST(place); + match = -1; + ambiguous = 0; + + optind++; + place = EMSG; + + if (*current_argv == '\0') { /* found "--" */ + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, __UNCONST(nargv)); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return -1; + } + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == + (unsigned)current_argv_len) { + /* exact match */ + match = i; + ambiguous = 0; + break; + } + if (match == -1) /* partial match */ + match = i; + else if (!IDENTICAL_INTERPRETATION(i, match)) + ambiguous = 1; + } + if (ambiguous) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return BADCH; + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of + * flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return BADARG; + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use + * next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' + * indicates no error should be generated + */ + if (PRINT_ERROR) + warnx(recargstring, current_argv); + /* + * XXX: GNU sets optopt to val regardless + * of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return BADARG; + } + } else { /* unknown option */ + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return BADCH; + } + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + retval = 0; + } else + retval = long_options[match].val; + if (idx) + *idx = match; + } + return retval; +#undef IDENTICAL_INTERPRETATION +} diff --git a/deps/MsvcLibX/src/getppid.c b/deps/MsvcLibX/src/getppid.c new file mode 100644 index 0000000000000000000000000000000000000000..062beff3b040a1138767df727c1124a8b1db11cb --- /dev/null +++ b/deps/MsvcLibX/src/getppid.c @@ -0,0 +1,66 @@ +/*****************************************************************************\ +* * +* Filename getppid.c * +* * +* Description: WIN32 port of standard C library's getppid() * +* * +* Notes: TO DO: Add a DOS version, using the PSP for the pid. * +* * +* During the development of this routine, I found a bug * +* in Windows SDK's tlhelp32.h include file in WIN64: * +* If packcking has been changed somewhere before including * +* tlhelp32.h, either due to a #pragma pack directive, or to * +* a compiler /Zp option, it will generate a PROCESSENTRY32 * +* structure with the wrong size. Then anything can happen, * +* including Process32First failures, or even crashes. * +* * +* History: * +* 2013-03-27 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvcUnistd.h" + +#ifdef _WIN32 + +#include +#pragma pack(push,8) /* Work around a bug in tlhelp32.h in WIN64, which generates the wrong structure if packing has been changed */ +#include +#pragma pack(pop) + +/* +pid_t getpid(void) { + return (pid_t)GetCurrentProcessId(); +} +*/ + +pid_t getppid(void) { + pid_t ppid = INVALID_PID; + pid_t pid = getpid(); + HANDLE h; + BOOL bFound; + PROCESSENTRY32 pe = {0}; + + h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (h == INVALID_HANDLE_VALUE) { + return ppid; + } + + pe.dwSize = sizeof(PROCESSENTRY32); + for (bFound=Process32First(h, &pe); bFound; bFound=Process32Next(h, &pe)) { + if ((pid_t)(pe.th32ProcessID) == pid) { + ppid = pe.th32ParentProcessID; + break; + } + } + + CloseHandle(h); + + return ppid; +} + +#endif + + diff --git a/deps/MsvcLibX/src/gettimeofday.c b/deps/MsvcLibX/src/gettimeofday.c new file mode 100644 index 0000000000000000000000000000000000000000..b485edeb9ea805c06f119c7ce2dfa6d47850db29 --- /dev/null +++ b/deps/MsvcLibX/src/gettimeofday.c @@ -0,0 +1,40 @@ +/*****************************************************************************\ +* * +* Filename gettimeofday.c * +* * +* Description DOS/WIN32 port of standard C library's gettimeofday(). * +* * +* Notes * +* * +* History * +* 2014-06-04 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "msvclibx.h" + +#include "msvcTime.h" +#include "sys/msvcTime.h" + +#ifdef _MSDOS +/* MS-DOS only has a 1-second resolution on system time. + Use the existence of macro _STRUCT_TIMEVAL to test if it's possible + to use gettimeofday(), else use time(), which is supported by all OSs */ +#endif + +#if 0 + +/* Get the current date and time into a struct timeval */ +int gettimeofday(struct timeval *ptv, void *pTimeZone) { + struct timespec ts; + int iErr; + if (pTimeZone) pTimeZone = _timezone; /* Ignore it, and prevent compilation warning */ + iErr = clock_gettime(CLOCK_REALTIME, &ts); + if (iErr) return iErr; + TIMESPEC_TO_TIMEVAL(ptv, &ts); + return 0; +} + +#endif /* defined(_WIN32) */ diff --git a/deps/MsvcLibX/src/iconv.c b/deps/MsvcLibX/src/iconv.c new file mode 100644 index 0000000000000000000000000000000000000000..40b6e6462d9d0a6dc53509e8645cfba50b446256 --- /dev/null +++ b/deps/MsvcLibX/src/iconv.c @@ -0,0 +1,229 @@ +/*****************************************************************************\ +* * +* Filename iconv.c * +* * +* Description: WIN32 port of standard C library's iconv() * +* * +* Notes: Define here a number of routines, that will eventually * +* be used by iconv(). * +* * +* History: * +* 2014-02-27 JFL Created this module. * +* 2015-12-09 JFL Added routines fputsU and vfprintfU. * +* 2016-09-13 JFL Fixed warnings in fputsU. Do not change the input buffer. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +/* Microsoft C libraries include files */ +#include +#include +#include +/* MsvcLibX library extensions */ +#include "msvcIconv.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#if defined(_MSDOS) + +/* TO DO: Add support for DOS code pages! */ + +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: ConvertString | +| | +| Description: Convert a string from one MBCS encoding to another | +| | +| Parameters: char *buf Buffer containg a NUL-terminated string | +| size_t nBytes Buffer size | +| UINT cpFrom Initial Windows code page identifier | +| UINT cpTo Final Windows code page identifier | +| LPCSTR lpDfltC Pointer to the Default Character to use | +| (NULL = Use the default default!) | +| | +| Returns: The converted string size. -1=error, and errno set. | +| | +| Notes: See the list of Windows code page identifiers there: | +| http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx +| | +| History: | +| 2014-02-27 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +int ConvertString(char *buf, size_t nBytes, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) { + int n = (int)lstrlen(buf); + if (cpFrom != cpTo) { + WCHAR *pWBuf = (WCHAR *)malloc(sizeof(WCHAR)*nBytes); + if (!pWBuf) { + errno = ENOMEM; + return -1; + } + n = MultiByteToWideChar(cpFrom, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + buf, /* lpMultiByteStr, */ + n+1, /* cbMultiByte, +1 to copy the final NUL */ + pWBuf, /* lpWideCharStr, */ + (int)nBytes /* cchWideChar, */ + ); + n = WideCharToMultiByte(cpTo, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + pWBuf, /* lpWideCharStr, */ + n, /* cchWideChar, */ + buf, /* lpMultiByteStr, */ + (int)nBytes, /* cbMultiByte, */ + lpDefaultChar, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + free(pWBuf); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + n -= 1; /* Output string size, not counting the final NUL */ + } + return n; +} + +char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) { + int nBytes; + char *pBuf; + nBytes = 4 * ((int)lstrlen(string) + 1); /* Worst case for the size needed */ + pBuf = (char *)malloc(nBytes); + if (!pBuf) { + errno = ENOMEM; + return NULL; + } + lstrcpy(pBuf, string); + nBytes = ConvertString(pBuf, nBytes, cpFrom, cpTo, lpDefaultChar); + if (nBytes == -1) { + free(pBuf); + return NULL; + } + pBuf = realloc(pBuf, nBytes+1); + return pBuf; +} + +int CountCharacters(const char *string, UINT cp) { + int n; + WCHAR *pWBuf; + + n = (int)lstrlen(string); + if (!n) return 0; + + pWBuf = (WCHAR *)malloc(sizeof(WCHAR)*n); + if (!pWBuf) { + errno = ENOMEM; + return -1; + } + + n = MultiByteToWideChar(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + string, /* lpMultiByteStr, */ + n, /* cbMultiByte, */ + pWBuf, /* lpWideCharStr, */ + n /* cchWideChar, */ + ); + free(pWBuf); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + return n; +} + +UINT codePage = 0; + +/*---------------------------------------------------------------------------*\ +* * +| Functions: fputsU, vfprintfU, fprintfU, printfU | +| | +| Description: Output UTF-8 strings | +| | +| Parameters: Same as fputs, vfprintf, fprintf, printf | +| | +| Returns: Same as fputs, vfprintf, fprintf, printf | +| | +| Notes: Converts the string to the output code page if needed. | +| | +| History: | +| 2014-02-27 JFL Created fprintfU and printfU. | +| 2015-12-09 JFL Restructured them over vfprintfU, itself over fputsU. | +| 2016-09-13 JFL Fixed warnings. | +| Do not change the input buffer. | +* * +\*---------------------------------------------------------------------------*/ + +/* Make sure we're calling Microsoft routines, not our aliases */ +#undef printf +#undef fprintf +#undef vfprintf +#undef fputs + +int fputsU(const char *buf, FILE *f) { /* fputs a UTF-8 string */ + int iRet; + char *pBuf = NULL; + + if (!codePage) codePage = GetConsoleOutputCP(); + if (codePage != CP_UTF8) { + pBuf = DupAndConvert(buf, CP_UTF8, codePage, NULL); + } else { + pBuf = (char *)buf; + } + if (pBuf) { /* If no error, and something to output */ + iRet = fputs(pBuf, f); + if ((iRet >= 0) && DEBUG_IS_ON()) fflush(f); /* Slower, but ensures we get everything before crashes! */ + if (pBuf != buf) free(pBuf); + } else { + iRet = -1; /* Could not convert the string to output */ + } + return iRet; /* Return the error (n<0) or success (n>=0) */ +} + +int vfprintfU(FILE *f, const char *pszFormat, va_list vl) { /* vfprintf UTF-8 strings */ + int n; + char buf[UNICODE_PATH_MAX + 4096]; + + n = _vsnprintf(buf, sizeof(buf), pszFormat, vl); + if (n > 0) { /* If no error (n>=0), and something to output (n>0), do output */ + int iErr = fputsU(buf, f); + if (iErr < 0) n = iErr; + } + + return n; +} + +int fprintfU(FILE *f, const char *pszFormat, ...) { /* fprintf UTF-8 strings */ + va_list vl; + int n; + + va_start(vl, pszFormat); + n = vfprintfU(f, pszFormat, vl); + va_end(vl); + + return n; +} + +int printfU(const char *pszFormat, ...) { /* printf UTF-8 strings */ + va_list vl; + int n; + + va_start(vl, pszFormat); + n = vfprintfU(stdout, pszFormat, vl); + va_end(vl); + + return n; +} + +#endif /* _WIN32 */ + diff --git a/deps/MsvcLibX/src/lstat.c b/deps/MsvcLibX/src/lstat.c new file mode 100644 index 0000000000000000000000000000000000000000..e107fd87063a85b87d4ddc57d3b72f0c0ec880e6 --- /dev/null +++ b/deps/MsvcLibX/src/lstat.c @@ -0,0 +1,432 @@ +/*****************************************************************************\ +* * +* Filename lstat.c * +* * +* Description: WIN32 port of standard C library's lstat() * +* Also contains unlink() and rmdir(), which do use lstat. * +* * +* Notes: TO DO: Make 3 versions for Windows: ANSI, WSTR, UTF8 * +* * +* History: * +* 2014-02-06 JFL Created this module. * +* 2014-02-12 JFL Added code to filter reparse points, and keep only * +* real junctions and symlinks. * +* 2014-02-13 JFL Moved dirent2stat() from dirent.c, as there must actually * +* be 4 WIN32 versions, for the four versions of struct stat.* +* 2014-02-28 JFL Added support for UTF-8 pathnames. * +* 2014-03-24 JFL Renamed "statx.h" as the standard . * +* 2014-06-30 JFL Added support for 32K Unicode paths. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +/* Microsoft C libraries include files */ +#include +#include +#include +#include +/* MsvcLibX library extensions */ +#include "msvclibx.h" +#include +#include "msvcDirent.h" +#include "msvcUnistd.h" /* For ResolveLinks() definition */ +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#if defined(_MSDOS) +/* Make sure it's only defined it in one of the lstatxxx versions */ +#if !defined(_USE_32BIT_TIME_T) && (_FILE_OFFSET_BITS == 32) + +int dirent2stat(_dirent *pDirent, struct _stat *pStat) { + memset(pStat, 0, sizeof(struct stat)); + + /* Set times */ + pStat->st_mtime = Filetime2Timet(pDirent->d_date, pDirent->d_time); + /* Size */ + pStat->st_size = pDirent->d_filesize; + /* Standard attributes */ + pStat->st_mode |= (pDirent->d_type << 12); /* Set the 4-bit type field */ + pStat->st_mode |= _S_IREAD | _S_IWRITE | _S_IEXEC; /* Assume it's fully accessible */ + if (pDirent->d_attribs & _A_RDONLY) pStat->st_mode &= ~_S_IWRITE; + /* DOS-specific attributes */ + if (pDirent->d_attribs & _A_HIDDEN) pStat->st_mode |= S_HIDDEN; + if (pDirent->d_attribs & _A_ARCH) pStat->st_mode |= S_ARCHIVE; + if (pDirent->d_attribs & _A_SYSTEM) pStat->st_mode |= S_SYSTEM; + + return 0; +} + +#endif /* defined(_USE_32BIT_TIME_T) && (_FILE_OFFSET_BITS == 32) */ +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +/* ------------ Display the *stat* macro values at compile time ------------ */ + +#pragma message(MACRODEF(_MSVC_stat)) +#pragma message(MACRODEF(_MSVC_fstat)) +#pragma message(MACRODEF(_MSVC_lstat)) +#pragma message(MACRODEF(_MSVC_stat64)) + +#if _MSVCLIBX_STAT_DEFINED + #pragma message(MACRODEF(_LIBX_stat)) + #pragma message(MACRODEF(_LIBX_stat64)) +#endif + +#pragma message(MACRODEF(stat)) +#pragma message(MACRODEF(fstat)) +#pragma message(MACRODEF(lstat)) + +#if 0 +#pragma message(MACRODEF(_lstat)) +#pragma message(MACRODEF(_lstati64)) +#if _MSVCLIBX_STAT_DEFINED + #pragma message(MACRODEF(_lstat_ns)) + #pragma message(MACRODEF(_lstati64_ns)) +#endif +#endif + +#if defined(_LARGEFILE_SOURCE64) + #pragma message(MACRODEF(stat64)) + #pragma message(MACRODEF(fstat64)) + #pragma message(MACRODEF(lstat64)) +#endif + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function: lstat | +| | +| Description: Common definition of all _lstatXY() functions | +| | +| Parameters: const char *path The symlink name | +| struct stat *buf Output buffer | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: See statx.h for a description of how the stat and lstat | +| macros work. | +| | +| History: | +| 2014-02-06 JFL Created this routine | +| 2014-02-28 JFL Added support for UTF-8 pathnames. | +* * +\*---------------------------------------------------------------------------*/ + +int lstat(const char *path, struct stat *pStat) { + BOOL bDone; + DWORD dwAttr; + WIN32_FILE_ATTRIBUTE_DATA fileData; + unsigned __int64 qwSize; + int bIsJunction = FALSE; + int bIsMountPoint = FALSE; + DWORD dwTag = 0; + DEBUG_CODE( + char szTime[100]; + ) + WCHAR wszName[UNICODE_PATH_MAX]; + int n; + + DEBUG_ENTER((STRINGIZE(lstat) "(\"%s\", 0x%p);\n", path, pStat)); + +#if USE_MSVC_STAT + dwAttr = GetFileAttributes(path); + DEBUG_PRINTF(("GetFileAttributes() = 0x%lX\n", dwAttr)); + if (dwAttr == INVALID_FILE_ATTRIBUTES) { + errno = ENOENT; + RETURN_INT_COMMENT(-1, ("File does not exist\n")); + } + + if (!(dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)) { + int iErr = stat(path, pStat); + RETURN_INT(iErr); + } +#endif + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + UNICODE_PATH_MAX /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + + bDone = GetFileAttributesExW(wszName, GetFileExInfoStandard, &fileData); + if (!bDone) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("GetFileAttributesEx(); // Failed\n")); + } + XDEBUG_PRINTF(("GetFileAttributesEx(); // Success\n")); + dwAttr = fileData.dwFileAttributes; + XDEBUG_PRINTF(("dwFileAttributes = 0x%lX\n", dwAttr)); + DEBUG_CODE_IF_ON(Filetime2String(&fileData.ftLastWriteTime, szTime, sizeof(szTime));); + XDEBUG_PRINTF(("ftLastWriteTime = %s\n", szTime)); + qwSize = ((unsigned __int64)fileData.nFileSizeHigh << 32) | fileData.nFileSizeLow; + XDEBUG_PRINTF(("nFileSize = %I64d\n", qwSize)); + + ZeroMemory(pStat, sizeof(struct stat)); + /* Set times */ +#if _MSVCLIBX_STAT_DEFINED + Filetime2Timespec(&fileData.ftCreationTime, &(pStat->st_ctim)); /* Windows = Create time; Unix = Permissions change time */ + Filetime2Timespec(&fileData.ftLastWriteTime, &(pStat->st_mtim)); + Filetime2Timespec(&fileData.ftLastAccessTime, &(pStat->st_atim)); +#else + Filetime2Timet(&fileData.ftCreationTime, &(pStat->st_ctime)); /* Windows = Create time; Unix = Permissions change time */ + Filetime2Timet(&fileData.ftLastWriteTime, &(pStat->st_mtime)); + Filetime2Timet(&fileData.ftLastAccessTime, &(pStat->st_atime)); +#endif + /* Size */ + /* NOTE: There is loss of data here if the file size is > 2GB, and off_t is 32-bits */ + pStat->st_size = (off_t)qwSize; +#if (_STAT_FILE_SIZE < 64) +#define _MAX_FILE_SIZE 0x7FFFFFFFL + if (qwSize > _MAX_FILE_SIZE) pStat->st_size = (off_t)_MAX_FILE_SIZE; +#endif + /* Standard attributes */ + /* File type */ +check_attr_again: + if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT) { + /* JUNCTIONs and SYMLINKDs both have the FILE_ATTRIBUTE_DIRECTORY flag also set. + // Test the FILE_ATTRIBUTE_REPARSE_POINT flag first, to make sure they're seen as symbolic links. + // + // All symlinks are reparse points, but not all reparse points are symlinks. */ + dwTag = GetReparseTagU(path); + switch (dwTag) { + case IO_REPARSE_TAG_MOUNT_POINT: /* NTFS junction or mount point */ + { /* We must read the link to distinguish junctions from mount points. */ + WCHAR wbuf[UNICODE_PATH_MAX]; + ssize_t n; + bIsMountPoint = TRUE; + n = readlinkW(wszName, wbuf, UNICODE_PATH_MAX); + /* Junction targets are absolute pathnames, starting with a drive letter. Ex: C: */ + /* readlink() fails if the reparse point does not target a valid pathname */ + if (n < 0) goto this_is_not_a_symlink; /* This is not a junction. */ + bIsJunction = TRUE; /* Else this is a junction. Fall through to the symlink case. */ + } + case IO_REPARSE_TAG_SYMLINK: /* NTFS symbolic link */ + pStat->st_mode |= S_IFLNK; /* Symbolic link */ + break; + default: /* Anything else is definitely not like a Unix symlink */ +this_is_not_a_symlink: + dwAttr &= ~FILE_ATTRIBUTE_REPARSE_POINT; + goto check_attr_again; + } + } else if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) + pStat->st_mode |= S_IFDIR; /* Subdirectory */ + else if (dwAttr & FILE_ATTRIBUTE_DEVICE) + pStat->st_mode |= S_IFCHR; /* Device (we don't know if character or block) */ + else + pStat->st_mode |= S_IFREG; /* A normal file by default */ + /* pStat->st_mode |= (pDirent->d_type << 12); /* Set the 4-bit type field */ + pStat->st_mode |= _S_IREAD | _S_IWRITE | _S_IEXEC; /* Assume it's fully accessible */ + if (dwAttr & FILE_ATTRIBUTE_READONLY) pStat->st_mode &= ~_S_IWRITE; + /* DOS-specific attributes */ + if (dwAttr & FILE_ATTRIBUTE_HIDDEN) pStat->st_mode |= S_HIDDEN; + if (dwAttr & FILE_ATTRIBUTE_ARCHIVE) pStat->st_mode |= S_ARCHIVE; + if (dwAttr & FILE_ATTRIBUTE_SYSTEM) pStat->st_mode |= S_SYSTEM; + /* Windows-specific attributes */ + if (dwAttr & FILE_ATTRIBUTE_COMPRESSED) pStat->st_mode |= S_COMPRESSED; + if (dwAttr & FILE_ATTRIBUTE_ENCRYPTED) pStat->st_mode |= S_ENCRYPTED; + if (dwAttr & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) pStat->st_mode |= S_NOT_CONTENT_INDEXED; + if (dwAttr & FILE_ATTRIBUTE_OFFLINE) pStat->st_mode |= S_OFFLINE; + if (dwAttr & FILE_ATTRIBUTE_SPARSE_FILE) pStat->st_mode |= S_SPARSE_FILE; + if (bIsMountPoint) pStat->st_mode |= S_MOUNT_POINT; /* Will allow to distinguish junctions from mount points */ + /* if (dwAttr & FILE_ATTRIBUTE_TEMPORARY) pStat->st_mode |= S_TEMPORARY; */ + /* if (dwAttr & FILE_ATTRIBUTE_VIRTUAL) pStat->st_mode |= S_VIRTUAL; */ +#if _MSVCLIBX_STAT_DEFINED + pStat->st_Win32Attrs = dwAttr; + pStat->st_ReparseTag = dwTag; +#endif + + RETURN_INT_COMMENT(0, ("%s mode = 0x%04X size = %I64d bytes\n", szTime, pStat->st_mode, qwSize)); +} + +#if !USE_MSVC_STAT +int stat(const char *path, struct stat *pStat) { + char buf[UTF8_PATH_MAX]; + int iErr; + + DEBUG_ENTER((STRINGIZE(stat) "(\"%s\", 0x%p);\n", path, pStat)); + + iErr = ResolveLinksU(path, buf, sizeof(buf)); + if (!iErr) lstat(buf, pStat); + + RETURN_INT(iErr); +} +#endif /* !USE_MSVC_STAT */ + +int dirent2stat(_dirent *pDirent, struct stat *pStat) { + memset(pStat, 0, sizeof(struct stat)); + + /* Set times */ +#if _MSVCLIBX_STAT_DEFINED + Filetime2Timespec(&pDirent->d_CreationTime, &(pStat->st_ctim)); /* Windows = Create time; Unix = Permissions change time */ + Filetime2Timespec(&pDirent->d_LastWriteTime, &(pStat->st_mtim)); + Filetime2Timespec(&pDirent->d_LastAccessTime, &(pStat->st_atim)); +#else + Filetime2Timet(&pDirent->d_CreationTime, &(pStat->st_ctime)); /* Windows = Create time; Unix = Permissions change time */ + Filetime2Timet(&pDirent->d_LastWriteTime, &(pStat->st_mtime)); + Filetime2Timet(&pDirent->d_LastAccessTime, &(pStat->st_atime)); +#endif + /* Size */ + /* NOTE: There is loss of data here if the file size is > 2GB, and off_t is 32-bits */ + pStat->st_size = (off_t)(pDirent->d_filesize); +#if (_STAT_FILE_SIZE < 64) +#define _MAX_FILE_SIZE 0x7FFFFFFFL + if (pDirent->d_filesize > _MAX_FILE_SIZE) pStat->st_size = (off_t)_MAX_FILE_SIZE; +#endif + /* Standard attributes */ + pStat->st_mode |= (pDirent->d_type << 12); /* Set the 4-bit type field */ + pStat->st_mode |= _S_IREAD | _S_IWRITE | _S_IEXEC; /* Assume it's fully accessible */ + if (pDirent->d_attribs & FILE_ATTRIBUTE_READONLY) pStat->st_mode &= ~_S_IWRITE; + /* DOS-specific attributes */ + if (pDirent->d_attribs & FILE_ATTRIBUTE_HIDDEN) pStat->st_mode |= S_HIDDEN; + if (pDirent->d_attribs & FILE_ATTRIBUTE_ARCHIVE) pStat->st_mode |= S_ARCHIVE; + if (pDirent->d_attribs & FILE_ATTRIBUTE_SYSTEM) pStat->st_mode |= S_SYSTEM; + /* Windows-specific attributes */ + if (pDirent->d_attribs & FILE_ATTRIBUTE_COMPRESSED) pStat->st_mode |= S_COMPRESSED; + if (pDirent->d_attribs & FILE_ATTRIBUTE_ENCRYPTED) pStat->st_mode |= S_ENCRYPTED; + if (pDirent->d_attribs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) pStat->st_mode |= S_NOT_CONTENT_INDEXED; + if (pDirent->d_attribs & FILE_ATTRIBUTE_OFFLINE) pStat->st_mode |= S_OFFLINE; + if (pDirent->d_attribs & FILE_ATTRIBUTE_SPARSE_FILE) pStat->st_mode |= S_SPARSE_FILE; + /* Special case of junction and mount points */ + if (pDirent->d_ReparseTag) pStat->st_mode |= S_MOUNT_POINT; + /* if (pDirent->d_attribs & FILE_ATTRIBUTE_TEMPORARY) pStat->st_mode |= S_TEMPORARY; */ + /* if (pDirent->d_attribs & FILE_ATTRIBUTE_VIRTUAL) pStat->st_mode |= S_VIRTUAL; */ +#if _MSVCLIBX_STAT_DEFINED + pStat->st_Win32Attrs = pDirent->d_attribs; + pStat->st_ReparseTag = pDirent->d_ReparseTag; +#endif + + return 0; +} + +/*---------------------------------------------------------------------------*\ +* * +| Function: unlink | +| | +| Description: Remove a file or a symbolic link | +| | +| Parameters: const char *path The file or symlink name | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: | +| | +| History: | +| 2014-02-17 JFL Created this routine | +| 2014-02-28 JFL Added support for UTF-8 pathnames. | +* * +\*---------------------------------------------------------------------------*/ + +int unlink(const char *path) { + int iErr; + BOOL bDone; + struct stat st; + WCHAR wszName[UNICODE_PATH_MAX]; + int n; + + DEBUG_ENTER(("unlink(\"%s\");\n", path)); + + iErr = lstat(path, &st); + if (iErr) RETURN_INT(iErr); + + if ((!S_ISREG(st.st_mode)) && (!S_ISLNK(st.st_mode))) { + errno = ENOENT; + RETURN_INT_COMMENT(-1, ("Pathname exists, but is not a file or a link\n")); + } + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + UNICODE_PATH_MAX /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + +#if _MSVCLIBX_STAT_DEFINED + if (S_ISLNK(st.st_mode) && (st.st_Win32Attrs & FILE_ATTRIBUTE_DIRECTORY)) { + /* This link is a junction or a symlinkd */ + bDone = RemoveDirectoryW(wszName); + } else +#endif + bDone = DeleteFileW(wszName); + + if (bDone) { + RETURN_INT_COMMENT(0, ("Success\n")); + } else { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("Failed\n")); + } +} + +/*---------------------------------------------------------------------------*\ +* * +| Function: rmdir | +| | +| Description: Remove a directory | +| | +| Parameters: const char *path The directory name | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: | +| | +| History: | +| 2014-03-05 JFL Created this routine with support for UTF-8 pathnames. | +* * +\*---------------------------------------------------------------------------*/ + +int rmdir(const char *path) { + int iErr; + BOOL bDone; + struct stat st; + WCHAR wszName[UNICODE_PATH_MAX]; + int n; + + DEBUG_ENTER(("rmdir(\"%s\");\n", path)); + + iErr = lstat(path, &st); + if (iErr) RETURN_INT(iErr); + + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + RETURN_INT_COMMENT(-1, ("Pathname exists, but is not a directory\n")); + } + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + UNICODE_PATH_MAX /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + + bDone = RemoveDirectoryW(wszName); + + if (bDone) { + RETURN_INT_COMMENT(0, ("Success\n")); + } else { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("Failed\n")); + } +} + +#endif /* _WIN32 */ + diff --git a/deps/MsvcLibX/src/lstat32.c b/deps/MsvcLibX/src/lstat32.c new file mode 100644 index 0000000000000000000000000000000000000000..67023ea2bd2ddf1fe3accd8086168ffee99d3944 --- /dev/null +++ b/deps/MsvcLibX/src/lstat32.c @@ -0,0 +1,24 @@ +/*****************************************************************************\ +* * +* Filename lstat32.c * +* * +* Description: Redefinitions of standard C library's lstat32() * +* * +* Notes: * +* * +* History: * +* 2014-02-14 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _WIN64 /* WIN64 does not support 32-bits time_t */ + +/* st_*time is 32-bits __time32_t & st_size is 32-bits __off32_t */ + +#define _USE_32BIT_TIME_T +#define _FILE_OFFSET_BITS 32 + +#include "lstat.c" +#endif diff --git a/deps/MsvcLibX/src/lstat32i64.c b/deps/MsvcLibX/src/lstat32i64.c new file mode 100644 index 0000000000000000000000000000000000000000..483ff471a2253f333ecca71fc42302d8fec1e83a --- /dev/null +++ b/deps/MsvcLibX/src/lstat32i64.c @@ -0,0 +1,24 @@ +/*****************************************************************************\ +* * +* Filename lstat32i64.c * +* * +* Description: Redefinitions of standard C library's lstat32i64() * +* * +* Notes: * +* * +* History: * +* 2014-02-14 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#ifndef _WIN64 /* WIN64 does not support 32-bits time_t */ + +/* st_*time is 32-bits __time32_t & st_size is 64-bits __off64_t */ + +#define _USE_32BIT_TIME_T +#define _FILE_OFFSET_BITS 64 + +#include "lstat.c" +#endif diff --git a/deps/MsvcLibX/src/lstat64.c b/deps/MsvcLibX/src/lstat64.c new file mode 100644 index 0000000000000000000000000000000000000000..56cd0e91a9b143b647b46fac5219ea7099e5bced --- /dev/null +++ b/deps/MsvcLibX/src/lstat64.c @@ -0,0 +1,21 @@ +/*****************************************************************************\ +* * +* Filename lstat.c * +* * +* Description: Redefinitions of standard C library's lstat() * +* * +* Notes: * +* * +* History: * +* 2014-02-14 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* st_*time is 64-bits __time64_t & st_size is 64-bits __off64_t */ + +#undef _USE_32BIT_TIME_T +#define _FILE_OFFSET_BITS 64 + +#include "lstat.c" diff --git a/deps/MsvcLibX/src/lstat64i32.c b/deps/MsvcLibX/src/lstat64i32.c new file mode 100644 index 0000000000000000000000000000000000000000..6c86979191aa96f6234635e2252bd443b338b090 --- /dev/null +++ b/deps/MsvcLibX/src/lstat64i32.c @@ -0,0 +1,21 @@ +/*****************************************************************************\ +* * +* Filename lstat64i32.c * +* * +* Description: Redefinitions of standard C library's lstat64i32() * +* * +* Notes: * +* * +* History: * +* 2014-02-14 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +/* st_*time is 64-bits __time64_t & st_size is 32-bits __off32_t */ + +#undef _USE_32BIT_TIME_T +#define _FILE_OFFSET_BITS 32 + +#include "lstat.c" diff --git a/deps/MsvcLibX/src/main.c b/deps/MsvcLibX/src/main.c new file mode 100644 index 0000000000000000000000000000000000000000..f366b081ad688e15dc62dd0c8a7ccf9bb409afe0 --- /dev/null +++ b/deps/MsvcLibX/src/main.c @@ -0,0 +1,225 @@ +/*****************************************************************************\ +* * +* Filename main.c * +* * +* Description: Main routine for WIN32 UTF-8 programs * +* * +* Notes: TO DO: Also set the environment with _setenvp() ? * +* * +* History: * +* 2014-03-03 JFL Created this module. * +* 2016-09-20 JFL Bug fix: Empty arguments "" did not get recorded. * +* 2017-02-05 JFL Redesigned to override libc's _setargv(). This avoids * +* having to encapsulate the main() routine with one here. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE +#define _CRT_SECURE_NO_WARNINGS /* Avoid depreciation warnings */ + +#include "msvclibx.h" +#include "msvcStdio.h" + +#ifdef _WIN32 + +#include +#include "msvcIconv.h" /* For MsvcLibX' codePage global variable */ + +/*---------------------------------------------------------------------------*\ +* * +| Function BreakArgLine | +| | +| Description Break the Windows command line into standard C arguments | +| | +| Parameters LPSTR pszCmdLine NUL-terminated argument line | +| char *pszArg[] Array of arguments pointers | +| | +| Returns int argc Number of arguments found. -1 = Error | +| | +| Notes MSVC library startup \" parsing rule is: | +| 2N backslashes + " ==> N backslashes and begin/end quote | +| 2N+1 backslashes + " ==> N backslashes + literal " | +| N backslashes ==> N backslashes | +| | +| History | +| 1993-10-05 JFL Initial implementation within devmain(). | +| 1994-04-14 JFL Extracted from devmain, and created this routine. | +| 1995-04-07 JFL Extracted from llkinit.c. | +| 1996-09-26 JFL Adapted to Win32 programs. | +| 1996-12-11 JFL Use Windows string routines. | +| 2001-09-18 JFL Set argv[0] with actual module file name. | +| Manage quoted strings as a single argument. | +| 2001-09-25 JFL Only process \x inside strings. | +| 2014-03-04 JFL Removed the C-style \-quoting of characters, which was | +| convenient, but incompatible with MSVC argument parsing. | +| Removed the limitation on the # of arguments. | +| Made the code compatible with ANSI and UTF-8 encodings. | +| 2017-02-05 JFL Check memory allocation errors, and if so return -1. | +* * +\*---------------------------------------------------------------------------*/ + +int BreakArgLine(LPSTR pszCmdLine, char ***pppszArg) { + int i, j; + int argc = 0; + char c, c0; + char *pszCopy; + int iString = FALSE; /* TRUE = string mode; FALSE = non-string mode */ + int nBackslash = 0; + char **ppszArg; + int iArg = FALSE; /* TRUE = inside an argument; FALSE = between arguments */ + + ppszArg = (char **)malloc((argc+1)*sizeof(char *)); + if (!ppszArg) return -1; + + /* Make a local copy of the argument line */ + /* Break down the local copy into standard C arguments */ + + pszCopy = malloc(lstrlen(pszCmdLine) + 1); + if (!pszCopy) return -1; + /* Copy the string, managing quoted characters */ + for (i=0, j=0, c0='\0'; ; i++) { + c = pszCmdLine[i]; + if (!c) { /* End of argument line */ + for ( ; nBackslash; nBackslash--) pszCopy[j++] = '\\'; /* Output pending \s */ + pszCopy[j++] = c; + break; + } + if ((!iArg) && (c != ' ') && (c != '\t')) { /* Beginning of a new argument */ + iArg = TRUE; + ppszArg[argc++] = pszCopy+j; + ppszArg = (char **)realloc(ppszArg, (argc+1)*sizeof(char *)); + if (!ppszArg) return -1; + pszCopy[j] = c0 = '\0'; + } + if (c == '\\') { /* Escaped character in string (maybe) */ + nBackslash += 1; + continue; + } + if (c == '"') { + if (nBackslash & 1) { /* Output N/2 \ and a literal " */ + for (nBackslash >>= 1; nBackslash; nBackslash--) pszCopy[j++] = '\\'; + pszCopy[j++] = c0 = c; + continue; + } + if (nBackslash) { /* Output N/2 \ and switch string mode */ + for (nBackslash >>= 1; nBackslash; nBackslash--) pszCopy[j++] = '\\'; + } + iString = !iString; + continue; + } + for ( ; nBackslash; nBackslash--) pszCopy[j++] = '\\'; /* Output pending \s */ + if ((!iString) && ((c == ' ') || (c == '\t'))) { /* End of an argument */ + iArg = FALSE; + c = '\0'; + } + pszCopy[j++] = c0 = c; + } + + ppszArg[argc] = NULL; + *pppszArg = ppszArg; + + return argc; +} + +/*---------------------------------------------------------------------------*\ +* * +| Function _setargv | +| | +| Description Msft standard CRT routine for parsing the command line. | +| | +| Parameters char *_acmdln Command line parameters. | +| | +| Returns __argc = Number of arguments. -1 = Error. | +| __argv = Array of arguments | +| _pgmptr = The program pathname | +| | +| Notes When linked in, replaces the default routine from the CRT.| +| | +| History | +| 2001-09-25 JFL Created this routine | +| 2016-12-31 JFL Changed the return type from void to int, else the WIN64 | +| version fails with message: | +| runtime error R6008 - not enough space for arguments | +| 2017-02-05 JFL Adapted for UTF-8 arguments initialization. | +* * +\*---------------------------------------------------------------------------*/ + +/* Global CRT variables defined in stdlib.h */ +/* Do not include stdlib.h here, to avoid getting unwanted macros hiding these */ +_CRTIMP extern int __argc; +_CRTIMP extern char **__argv; +_CRTIMP extern char *_acmdln; +_CRTIMP extern char *_pgmptr; + +int _initU(void); /* Forward reference */ + +int _setargv(void) { + int err = _initU(); + if (err) return err; + __argc = BreakArgLine(_acmdln, &__argv); + _pgmptr = __argv[0]; + return __argc; +} + +/*---------------------------------------------------------------------------*\ +* * +| Function _initU | +| | +| Description UTF-8 program initializations | +| | +| Parameters None | +| | +| Returns 0=Success. -1 = Error. | +| _acmdln = UTF-8 command line | +| codePage = Console Code Page | +| | +| Notes Forcibly linked in C programs that define _UTF8_SOURCE, | +| etc, which drags in _setargv() above with it. | +| | +| History | +| 2017-02-05 JFL Adapted from the abandonned _mainU0 routine. | +* * +\*---------------------------------------------------------------------------*/ + +int _initU(void) { + LPWSTR lpwCommandLine; + int n; + WCHAR wc; + + /* Get the Unicode command line */ + lpwCommandLine = GetCommandLineW(); + /* Trim tail spaces */ + n = lstrlenW(lpwCommandLine); + while (n && ((wc = lpwCommandLine[n-1]) != L'\0') && ((wc == L' ') || (wc == L'\t'))) lpwCommandLine[--n] = L'\0'; + /* Allocate space for the UTF8 copy */ + n += 1; /* Count the final NUL */ + _acmdln = malloc(4 * n); /* Worst case */ + if (!_acmdln) return -1; /* Memory allocation failed */ + /* Convert the Unicode command line to UTF-8 */ + n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + lpwCommandLine, /* lpWideCharStr, */ + n, /* cchWideChar, */ + _acmdln, /* lpMultiByteStr, */ + (4 * n), /* cbMultiByte, */ + NULL, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) { +#undef fprintf /* Use the real fprintf, to avoid further conversion errors! */ + fprintf(stderr, "Warning: Can't convert the argument line to UTF-8\n"); + _acmdln[0] = '\0'; + } + realloc(_acmdln, n+1); /* Resize the memory block to fit the UTF-8 line */ + /* Should not fail since we make it smaller */ + + /* Record the console code page, to allow converting the output accordingly */ + codePage = GetConsoleOutputCP(); + + return 0; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/mb2wpath.c b/deps/MsvcLibX/src/mb2wpath.c new file mode 100644 index 0000000000000000000000000000000000000000..097d3e736717dd54b9e9558f18fca51707bef1d3 --- /dev/null +++ b/deps/MsvcLibX/src/mb2wpath.c @@ -0,0 +1,86 @@ +/*****************************************************************************\ +* * +* Filename mb2wpath.c * +* * +* Description: WIN32 utility routine MultiByteToWidePath() * +* * +* Notes: Used to overcome the 260-byte limitation of many Windows * +* file management APIs. * +* * +* History: * +* 2014-07-01 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of printf routines */ + +#include "msvclibx.h" +#include "msvcDebugm.h" + +#if defined(_WIN32) + +#include +#include /* For _getdrive() */ + +int MultiByteToWidePath( + UINT nCodePage, + LPCSTR pszName, + LPWSTR pwszName, + int nWideBufSize +) { + int n; + int iNameLength = lstrlen(pszName); + DEBUG_CODE( + LPWSTR pwszName0 = pwszName; + ); + + if (iNameLength >= MAX_PATH) { /* Then processing this pathname requires prepending a special prefix */ + /* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx */ + if (!strncmp(pszName, "\\\\?\\", 4)) { /* The name is in the Win32 file namespace */ + /* Do nothing, the "\\?\" extended-length prefix is already there */ + } else if (!strncmp(pszName, "\\\\.\\", 4)) { /* The name is in the Win32 device namespace */ + /* Do nothing, devices names should not be changed */ + } else if (!strncmp(pszName, "\\\\", 2)) { /* The name is a UNC path */ + /* Then prepend it with "\\?\UNC\" to get 32K Unicode paths instead of 260-byte ANSI paths */ + lstrcpyW(pwszName, L"\\\\?\\UNC\\"); + pwszName += 8; + nWideBufSize -= 8; + pszName += 2; /* Skip the initial \\ in the UNC name */ + iNameLength -= 2; + } else if (pszName[0] == '\\') { /* The name is an absolute path with no drive */ + /* Then prepend it with "\\?\" to get 32K Unicode paths instead of 260-byte ANSI paths */ + lstrcpyW(pwszName, L"\\\\?\\"); + /* And also add the drive, as it's required in the Win32 file namespace */ + pwszName[4] = L'@' + (wchar_t)_getdrive(); /* _getdrive() returns 1 for drive A, 2 for B, etc */ + pwszName[5] = L':'; + pwszName += 6; + nWideBufSize -= 6; + } else if (pszName[0] && (pszName[1] == ':') && (pszName[2] == '\\')) { /* The name is an absolute path */ + /* Then prepend it with "\\?\" to get 32K Unicode paths instead of 260-byte ANSI paths */ + lstrcpyW(pwszName, L"\\\\?\\"); + pwszName += 4; + nWideBufSize -= 4; + } /* Else this is a relative pathname. Extended-length is not supported for them. */ + } + + n = MultiByteToWideChar(nCodePage, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + pszName, /* lpMultiByteStr, */ + iNameLength+1, /* cbMultiByte, */ /* +1 to include the final NUL */ + pwszName, /* lpWideCharStr, */ + nWideBufSize /* cchWideChar, */ + ); + DEBUG_CODE( + if (pwszName != pwszName0) { + char szUtf8[UTF8_PATH_MAX]; + DEBUG_WSTR2UTF8(pwszName0, szUtf8, sizeof(szUtf8)); + DEBUG_PRINTF(("MultiByteToWidePath(); // Long name changed to \"%s\"\n", szUtf8)); + } + ); + return n; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/mkdir.c b/deps/MsvcLibX/src/mkdir.c new file mode 100644 index 0000000000000000000000000000000000000000..24e98a52ba806374b584d79730e2449295bd4380 --- /dev/null +++ b/deps/MsvcLibX/src/mkdir.c @@ -0,0 +1,103 @@ +/*****************************************************************************\ +* * +* Filename mkdir.c * +* * +* Description: WIN32 UTF-8 version of mkdir * +* * +* Notes: * +* * +* History: * +* 2014-03-04 JFL Created this module. * +* 2014-03-24 JFL Renamed "statx.h" as the standard . * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +/* Microsoft C libraries include files */ +#include +#include /* For _mkdir() */ +#include +/* MsvcLibX library extensions */ +#include +#include "msvclibx.h" +#include "msvcLimits.h" + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function mkdir | +| | +| Description UTF-8 version of mkdir | +| | +| Parameters char *pszName File name | +| mode_t iMode File permission bits | +| | +| Returns 0 = Success; -1 = Error and errno set. | +| | +| Notes | +| | +| History | +| 2014-03-04 JFL Created this routine. | +| 2014-07-02 JFL Added support for pathnames >= 260 characters. | +* * +\*---------------------------------------------------------------------------*/ + +#pragma warning(disable:4100) /* Ignore the "unreferenced formal parameter" warning */ + +int mkdirU(const char *pszName, mode_t iMode) { + WCHAR wszName[PATH_MAX]; + int n; + BOOL bDone; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszName, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + COUNTOF(wszName) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + + bDone = CreateDirectoryW(wszName, NULL); + if (!bDone) { + errno = Win32ErrorToErrno(); + return -1; + } + return 0; +} + +int mkdirA(const char *pszName, mode_t iMode) { + WCHAR wszName[PATH_MAX]; + int n; + BOOL bDone; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszName, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + COUNTOF(wszName) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + + bDone = CreateDirectoryW(wszName, NULL); + if (!bDone) { + errno = Win32ErrorToErrno(); + return -1; + } + return 0; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/mkdtemp.c b/deps/MsvcLibX/src/mkdtemp.c new file mode 100644 index 0000000000000000000000000000000000000000..86bfbf25cfb2a825f1d2d90aeb8d54ba9506088d --- /dev/null +++ b/deps/MsvcLibX/src/mkdtemp.c @@ -0,0 +1,50 @@ +/*****************************************************************************\ +* * +* Filename mkdtemp.c * +* * +* Description: WIN32 port of standard C library's mkdtemp() * +* * +* Notes: * +* * +* History: * +* 2014-02-13 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include +#include +#include +#include +#include "msvcUnistd.h" + +char *mkdtemp(char *pszName) { + char *pszXXX, *pc; + int iErr = 0; + char *base32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; + int i; + + /* Find the XXX placeholder at the end of the string */ + for (pszXXX=pszName; pszXXX && *pszXXX; pszXXX++) ; + while ((pszXXX > pszName) && (*(pszXXX-1) == 'X')) pszXXX--; + if (!pszXXX || (*pszXXX != 'X')) { + errno = EINVAL; + return NULL; + } + + /* Seed the random number generator */ + srand((unsigned)getpid() + ((unsigned)time(NULL) << 10)); + + /* Try random file names until one file gets successfully created */ + for (i=0; i<10; i++) { + for (pc = pszXXX; *pc; pc++) { + *pc = base32[rand() % 32]; + } + iErr = _mkdir(pszName); + if (!iErr) break; + } + + return iErr ? NULL : pszName; +} + diff --git a/deps/MsvcLibX/src/mkstemp.c b/deps/MsvcLibX/src/mkstemp.c new file mode 100644 index 0000000000000000000000000000000000000000..f587cff48d35a631dd2e963468f5e32cd32a8396 --- /dev/null +++ b/deps/MsvcLibX/src/mkstemp.c @@ -0,0 +1,53 @@ +/*****************************************************************************\ +* * +* Filename mkstemp.c * +* * +* Description: WIN32 port of standard C library's mkstemp() * +* * +* Notes: * +* * +* History: * +* 2014-03-03 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include "msvcUnistd.h" +#include +#include +#include +#include +#include +#include +#include + +int mkstemp(char *pszName) { + char *pszXXX, *pc; + int hFile = -1; + char *base32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; + + /* Find the XXX placeholder at the end of the string */ + for (pszXXX=pszName; pszXXX && *pszXXX; pszXXX++) ; + while ((pszXXX > pszName) && (*(pszXXX-1) == 'X')) pszXXX--; + if (!pszXXX || (*pszXXX != 'X')) { + errno = EINVAL; + return -1; + } + + /* Seed the random number generator */ + srand((unsigned)getpid() + ((unsigned)time(NULL) << 10)); + + /* Try random file names until one file gets successfully created */ + while (hFile == -1) { + for (pc = pszXXX; *pc; pc++) { + *pc = base32[rand() % 32]; + } + hFile = _open(pszName, O_CREAT|O_EXCL|O_RDWR, S_IREAD|S_IWRITE); + } + + return hFile; +} + diff --git a/deps/MsvcLibX/src/open.c b/deps/MsvcLibX/src/open.c new file mode 100644 index 0000000000000000000000000000000000000000..dd70409410f6db9b03f2496e12831364139bad3a --- /dev/null +++ b/deps/MsvcLibX/src/open.c @@ -0,0 +1,84 @@ +/*****************************************************************************\ +* * +* Filename open.c * +* * +* Description: WIN32 UTF-8 version of open * +* * +* Notes: * +* * +* History: * +* 2017-02-16 JFL Created this module. * +* * +* Copyright 2017 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of printf routines */ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include "msvclibx.h" +#include "msvcFcntl.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function open | +| | +| Description UTF-8 or ANSI file name open(), with long path support | +| | +| Parameters char *pszName File name | +| int iFlags Opening mode | +| int iPerm Permission mode for file creation | +| | +| Returns File number | +| | +| Notes Prefixes long names with "\\?\" to enable long path suppt.| +| | +| History | +| 2017-02-16 JFL Created this routine. | +* * +\*---------------------------------------------------------------------------*/ + +int openM(UINT cp, const char *pszName, int iFlags, int iPerm) { + WCHAR wszName[UNICODE_PATH_MAX]; + int n; + int iFile; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszName, /* lpMultiByteStr, */ + wszName, /* lpWideCharStr, */ + COUNTOF(wszName) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + +/* return _wopen(wszName, iFlags, iPerm); */ + DEBUG_PRINTF(("_wopen(\"%s\", 0x%X, 0x%X);\n", pszName, iFlags, iPerm)); + iFile = _wopen(wszName, iFlags, iPerm); + DEBUG_PRINTF((" return %d;\n", iFile)); + return iFile; +} + +#pragma warning(disable:4212) /* Ignore the "nonstandard extension used : function declaration used ellipsis" warning */ + +int openA(const char *pszName, int iFlags, int iPerm) { + return openM(CP_ACP, pszName, iFlags, iPerm); +} + +int openU(const char *pszName, int iFlags, int iPerm) { + return openM(CP_UTF8, pszName, iFlags, iPerm); +} + +#pragma warning(default:4212) /* Restore the "nonstandard extension used : function declaration used ellipsis" warning */ + +#endif /* defined(_WIN32) */ diff --git a/deps/MsvcLibX/src/readlink.c b/deps/MsvcLibX/src/readlink.c new file mode 100644 index 0000000000000000000000000000000000000000..4abc91e8e22acef502236c530423b54683652913 --- /dev/null +++ b/deps/MsvcLibX/src/readlink.c @@ -0,0 +1,509 @@ +/*****************************************************************************\ +* * +* Filename readlink.c * +* * +* Description: WIN32 port of standard C library's readlink() * +* * +* Notes: * +* * +* History: * +* 2014-02-03 JFL Created this module. * +* 2014-02-27 JFL Changed the output name encoding to UTF-8. * +* 2014-03-02 JFL Split the functions into a WSTR and an UTF-8 version. * +* 2014-03-11 JFL Bug fix in junctions targets relativization. * +* 2014-03-13 JFL Allow reading junctions targets in first level shares. * +* 2014-03-19 JFL Split routine ReadReparsePointW() from readlinkW(). * +* 2014-03-20 JFL Restructured Windows readlink function into Wide and * +* MultiByte versions, and changed the Unicode and Ansi * +* versions to macros. * +* 2014-07-03 JFL Added support for pathnames >= 260 characters. * +* 2016-09-09 JFL Fixed a crash in debug mode, due to stack overflows. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +#include "msvcUnistd.h" +#pragma comment(lib, "Mpr.lib") + +#include +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#ifdef _WIN32 + +#include +#include "msvcReparsept.h" + +/* Get the Reparse Point Tag for a mount point - Wide char version */ +/* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365511(v=vs.85).aspx */ +DWORD GetReparseTagW(const WCHAR *pwszPath) { + HANDLE hFind; + WIN32_FIND_DATAW findFileData; + DWORD dwTag = 0; + + hFind = FindFirstFileW(pwszPath, &findFileData); + if (hFind == INVALID_HANDLE_VALUE ) return 0; + CloseHandle(hFind); + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + dwTag = findFileData.dwReserved0; + } + return dwTag; +} + +/* Get the Reparse Point Tag for a mount point - MultiByte char version */ +DWORD GetReparseTagM(const char *path, UINT cp) { + WCHAR wszPath[PATH_MAX]; + int n; + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszPath, /* lpWideCharStr, */ + COUNTOF(wszPath) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("GetReparseTagM(\"%s\", %d); // Conversion to Unicode failed. errno=%d - %s\n", path, cp, errno, strerror(errno))); + return 0; + } + return GetReparseTagW(wszPath); +} + +/*---------------------------------------------------------------------------*\ +* * +| Function: readlink | +| | +| Description: WIN32 port of standard C library's readlink() | +| | +| Parameters: const TCHAR *path The link name | +| TCHAR *buf Buffer for the link target | +| size_t bufsize Number of TCHAR in buf | +| | +| Returns: >0 = Link target size in TCHARS, Success, -1 = Failure | +| | +| Notes: Supports NTFS link types: symlink, symlinkd, junction. | +| | +| Converts junction targets to relative links if possible. | +| | +| On network drives, junctions that cannot be resolved on | +| the client side are returned unchanged: readlink() | +| returns the link name as its own target. This allows | +| resolving pathnames with such junctions successfully, | +| and still accessing files behind these junctions. | +| Note that this is incompatible with Unix, which fails | +| with errno = ELOOP if a link points to itself. | +| Windows-aware applications supporting this can detect | +| this case by comparing linkName and targetName when | +| readlink() succeeds. | +| Function ResolveLinks() in resolvelinks.c relies on this. | +| | +| Using XDEBUG macros to debug readlink() itself, | +| and DEBUG macros to display information useful for | +| debugging applications using readlink(). | +| | +| History: | +| 2014-02-04 JFL Created this routine | +| 2014-02-18 JFL Fix junctions targets on network drives. | +| Convert junction targets to relative paths, if they're | +| on the same drive as the junction itself. | +| 2014-03-11 JFL Bug fix in junctions targets relativization: Use a case- | +| insensitive path comparison. | +| 2014-03-13 JFL Allow reading junctions targets in \\server\Public shares.| +| 2014-03-19 JFL Split routine ReadReparsePointW() from readlinkW(). | +| Fail in case a junction target is on another server drive.| +| | +* * +\*---------------------------------------------------------------------------*/ + +#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */ + +/* Get the reparse point target, and return the tag. 0=failure */ +DWORD ReadReparsePointW(const WCHAR *path, WCHAR *buf, size_t bufsize) { + DWORD dwAttr; + HANDLE hLink; + BOOL done; + DWORD dwRead; + char iobuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + DWORD dwFlagsAndAttributes; + DWORD dwTag; + WCHAR *pwStr; + PREPARSE_READ_BUFFER pIoctlBuf; + PMOUNTPOINT_READ_BUFFER pMountpointBuf; + PSYMLINK_READ_BUFFER pSymlinkBuf; + unsigned short offset, len = 0; + DEBUG_CODE( + char *pszUtf8; + ) + + DEBUG_WSTR2NEWUTF8(path, pszUtf8); + DEBUG_ENTER(("ReadReparsePointW(\"%s\", 0x%p, %d);\n", pszUtf8, buf, bufsize)); + DEBUG_FREEUTF8(pszUtf8); + + dwAttr = GetFileAttributesW(path); + XDEBUG_PRINTF(("GetFileAttributes() = 0x%lX\n", dwAttr)); + if (dwAttr == INVALID_FILE_ATTRIBUTES) { + errno = ENOENT; + RETURN_INT_COMMENT(0, ("File does not exist\n")); + } + + if (!(dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)) { + errno = EINVAL; + RETURN_INT_COMMENT(0, ("File is not a link\n")); + } + + dwFlagsAndAttributes = FILE_FLAG_OPEN_REPARSE_POINT; + if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS; + hLink = CreateFileW(path, /* lpFileName, */ + 0, /* dwDesiredAccess, */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode, */ + NULL, /* lpSecurityAttributes, */ + OPEN_EXISTING, /* dwCreationDisposition, */ + dwFlagsAndAttributes, /* dwFlagsAndAttributes, */ + NULL /* hTemplateFile */ + ); + XDEBUG_PRINTF(("CreateFile() = 0x%lX\n", hLink)); + if (hLink == INVALID_HANDLE_VALUE) { + errno = EPERM; + RETURN_INT_COMMENT(0, ("Cannot open the link\n")); + } + + done = DeviceIoControl(hLink, /* hDevice, */ + FSCTL_GET_REPARSE_POINT, /* dwIoControlCode, */ + NULL, /* lpInBuffer, */ + 0, /* nInBufferSize, */ + iobuf, /* lpOutBuffer, */ + sizeof(iobuf), /* nOutBufferSize, */ + &dwRead, /* lpBytesReturned, */ + NULL /* lpOverlapped */ + ); + CloseHandle(hLink); + + if (!done) { + errno = EPERM; + RETURN_INT_COMMENT(0, ("DeviceIoControl() failed\n")); + } + + XDEBUG_PRINTF(("DeviceIoControl() returned %d bytes\n", dwRead)); + + /* Make sur the header tag & length fields are valid */ + if (dwRead < 8) { + errno = EBADF; + RETURN_INT_COMMENT(0, ("Invalid reparse data buffer\n")); + } + pIoctlBuf = (PREPARSE_READ_BUFFER)iobuf; + dwTag = pIoctlBuf->ReparseTag; + DEBUG_CODE_IF_ON( + char *pType = ""; + switch (dwTag) { + case IO_REPARSE_TAG_RESERVED_ZERO: pType = "Reserved"; break; + case IO_REPARSE_TAG_RESERVED_ONE: pType = "Reserved"; break; + case IO_REPARSE_TAG_MOUNT_POINT: pType = "Mount point or junction"; break; + case IO_REPARSE_TAG_HSM: pType = "Hierarchical Storage Manager"; break; + case IO_REPARSE_TAG_DRIVER_EXTENDER: pType = "Home server drive extender"; break; + case IO_REPARSE_TAG_HSM2: pType = "Hierarchical Storage Manager Product #2"; break; + case IO_REPARSE_TAG_SIS: pType = "Single-instance storage filter driver"; break; + case IO_REPARSE_TAG_WIM: pType = "Windows boot Image File"; break; + case IO_REPARSE_TAG_CSV: pType = "Cluster Shared Volume"; break; + case IO_REPARSE_TAG_DFS: pType = "Distributed File System"; break; + case IO_REPARSE_TAG_FILTER_MANAGER: pType = "Filter manager test harness"; break; + case IO_REPARSE_TAG_SYMLINK: pType = "Symbolic link"; break; + case IO_REPARSE_TAG_DFSR: pType = "Distributed File System R filter"; break; + case IO_REPARSE_TAG_DEDUP: pType = "Deduplicated volume"; break; + case IO_REPARSE_TAG_NFS: pType = "NFS share"; break; + default: pType = "Unknown type! Please report its value and update readlink.c."; break; + } + DEBUG_PRINT_INDENT(); + printf("ReparseTag = 0x%04X; // %s\n", (unsigned)(dwTag), pType); + ) + XDEBUG_PRINTF(("ReparseDataLength = 0x%04X\n", (unsigned)(pIoctlBuf->ReparseDataLength))); + + /* Process the supported tag types */ + switch (dwTag) { + case IO_REPARSE_TAG_SYMLINK: + pSymlinkBuf = (PSYMLINK_READ_BUFFER)iobuf; + XDEBUG_PRINTF(("SubstituteNameOffset = 0x%04X\n", (unsigned)(pSymlinkBuf->SubstituteNameOffset))); + XDEBUG_PRINTF(("SubstituteNameLength = 0x%04X\n", (unsigned)(pSymlinkBuf->SubstituteNameLength))); + XDEBUG_PRINTF(("PrintNameOffset = 0x%04X\n", (unsigned)(pSymlinkBuf->PrintNameOffset))); + XDEBUG_PRINTF(("PrintNameLength = 0x%04X\n", (unsigned)(pSymlinkBuf->PrintNameLength))); + XDEBUG_PRINTF(("Flags = 0x%04X\n", (unsigned)(pSymlinkBuf->Flags))); + + pwStr = pSymlinkBuf->PathBuffer; + offset = pSymlinkBuf->SubstituteNameOffset / 2; /* Convert byte offset to wide characters offset */ + len = pSymlinkBuf->SubstituteNameLength / 2; /* Convert bytes to wide characters count */ + break; + + case IO_REPARSE_TAG_MOUNT_POINT: /* aka. junctions */ + pMountpointBuf = (PMOUNTPOINT_READ_BUFFER)iobuf; + XDEBUG_PRINTF(("SubstituteNameOffset = 0x%04X\n", (unsigned)(pMountpointBuf->SubstituteNameOffset))); + XDEBUG_PRINTF(("SubstituteNameLength = 0x%04X\n", (unsigned)(pMountpointBuf->SubstituteNameLength))); + XDEBUG_PRINTF(("PrintNameOffset = 0x%04X\n", (unsigned)(pMountpointBuf->PrintNameOffset))); + XDEBUG_PRINTF(("PrintNameLength = 0x%04X\n", (unsigned)(pMountpointBuf->PrintNameLength))); + + pwStr = pMountpointBuf->PathBuffer; + offset = pMountpointBuf->SubstituteNameOffset / 2; /* Convert byte offset to wide characters offset */ + len = pMountpointBuf->SubstituteNameLength / 2; /* Convert bytes to wide characters count */ + break; + + default: + errno = EINVAL; + RETURN_INT_COMMENT(0, ("Unsupported reparse point type\n")); + } + if (len) { + if (len >= bufsize) { + errno = ENAMETOOLONG; + RETURN_INT_COMMENT(0, ("The output buffer is too small. The link size is %d bytes.\n", len)); + } + CopyMemory(buf, pwStr+offset, len*sizeof(WCHAR)); + } + buf[len] = L'\0'; + + DEBUG_WSTR2NEWUTF8(buf, pszUtf8); + DEBUG_LEAVE(("return 0x%X; // \"%s\"\n", dwTag, pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + return dwTag; +} + +/* Posix routine readlink - Wide char version */ +ssize_t readlinkW(const WCHAR *path, WCHAR *buf, size_t bufsize) { + ssize_t nRead; + UINT drvType; + DWORD dwTag; + DEBUG_CODE( + char *pszUtf8; + ) + + DEBUG_WSTR2NEWUTF8(path, pszUtf8); + DEBUG_ENTER(("readlink(\"%s\", 0x%p, %d);\n", pszUtf8, buf, bufsize)); + DEBUG_FREEUTF8(pszUtf8); + + dwTag = ReadReparsePointW(path, buf, bufsize); + if (!dwTag) { + RETURN_INT_COMMENT(-1, ("ReadReparsePointW() failed.\n")); + } + + /* Special case for junctions to other local directories: Remove their '\??\' header. + // Note: Also seen once on a symlink. I don't know why in most cases symlinks don't have it. + // Note: These junctions begin with '\??\C:\' (or another drive letter). + // Other types of junctions/mount points do not continue with a drive letter. + // For example: '\??\Volume{5e58015c-ba64-4048-928d-06aa03c983f9}\' */ + nRead = lstrlenW(buf); +#define strncmpW(s1, s2, l) (CompareStringW(LOCALE_INVARIANT, 0, s1, l, s2, l)-2) + if ((nRead >= 7) && (!strncmpW(buf, L"\\??\\", 4))) { + if (!strncmpW(buf+5, L":\\", 2)) { + nRead -= 4; + CopyMemory(buf, buf+4, (nRead+1)*sizeof(WCHAR)); + DEBUG_WSTR2NEWUTF8(buf, pszUtf8); + XDEBUG_PRINTF(("buf = \"%s\"; // Removed '\\\\?\\': \n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + } else { /* Return an error for other types, as Posix SW cannot handle them successfully. */ + errno = EINVAL; + DEBUG_WSTR2NEWUTF8(buf+4, pszUtf8); + DEBUG_LEAVE(("return -1; // Unsupported mount point type: %s\n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + return -1; + } + } + + /* Fix junctions targets */ + /* Windows resolves junctions on the server side, + but symlinks and symlinkds on the client side. */ + if (dwTag == IO_REPARSE_TAG_MOUNT_POINT) { + char szRootDir[4] = "C:\\"; + WCHAR wszAbsPath[PATH_MAX]; + WCHAR wszAbsPath2[PATH_MAX]; + WCHAR *p1; + WCHAR *p2; + WCHAR *pc1 = L"A"; + WCHAR *pc2 = L"a"; + + DEBUG_WSTR2NEWUTF8(buf, pszUtf8); + XDEBUG_PRINTF(("rawJunctionTarget = \"%s\"\n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + + GetFullPathNameW(path, PATH_MAX, wszAbsPath, NULL); /* Get the drive letter in the full path */ + szRootDir[0] = (char)(wszAbsPath[0]); /* Copy the drive letter */ + drvType = GetDriveType(szRootDir); + XDEBUG_PRINTF(("GetDriveType(\"%s\") = %d // %s drive\n", szRootDir, drvType, (drvType == DRIVE_REMOTE) ? "Network" : "Local")); + + /* 1) On network drives, the target should reference the network drive itself, + not a local drive on the remote machine */ + if (drvType == DRIVE_REMOTE) { + /* Then check if the junction target is relative to the same network drive. (Not always true!) */ + int iTargetFound = FALSE; + if (buf[0] && (buf[1] == L':')) { + WCHAR wszLocalName[] = L"X:"; + WCHAR wszRemoteName[PATH_MAX]; + DWORD dwErr; + DWORD dwLength = PATH_MAX; + wszLocalName[0] = wszAbsPath[0]; + dwErr = WNetGetConnectionW(wszLocalName, wszRemoteName, &dwLength); + if (dwErr == NO_ERROR) { + WCHAR *pwsz; + DEBUG_WSTR2NEWUTF8(wszRemoteName, pszUtf8); + XDEBUG_PRINTF(("net use %c: %s\n", (char)(wszLocalName[0]), pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + if ((wszRemoteName[0] == L'\\') && (wszRemoteName[1] == L'\\')) { + pwsz = wcschr(wszRemoteName+2, L'\\'); + if (pwsz) { + if ((pwsz[2] == L'$') && !pwsz[3]) { /* This is the root of a shared drive. Ex: \\server\D$ -> D: */ + char c1, c2; + XDEBUG_PRINTF(("// Checking if it's the root of an X$ shared drive\n")); + c1 = (char)toupper((char)pwsz[1]); /* The server-side drive letter of the network share */ + c2 = (char)toupper((char)buf[0]); /* The server-side drive letter of the junction target */ + if (c1 == c2) { /* OK, the target is in the same share drive */ + buf[0] = wszLocalName[0]; /* Make the target accessible locally */ + iTargetFound = TRUE; + XDEBUG_PRINTF(("// Confirmed it's the root of the shared drive\n")); + } /* Else the target is not accessible locally via its target name */ + } else { /* Heuristic: Assume the share name is an alias to the root on the network drive. Ex: \\server\DROOT -> D:\ */ + DWORD dwAttr; + XDEBUG_PRINTF(("// Checking if it's an alias of the root of the shared drive\n")); + buf[0] = wszAbsPath[0]; + dwAttr = GetFileAttributesW(buf); + DEBUG_WSTR2NEWUTF8(buf, pszUtf8); + XDEBUG_PRINTF(("GetFileAttributes(\"%s\") = 0x%lX\n", pszUtf8, dwAttr)); + DEBUG_FREEUTF8(pszUtf8); + if (dwAttr != INVALID_FILE_ATTRIBUTES) { + iTargetFound = TRUE; + XDEBUG_PRINTF(("// Confirmed it's an alias of the root of the shared drive\n")); + } else { /* Heuristic: Assume the share name is a subdirectory name on the network drive. Ex: \\server\Public -> C:\Public */ + WCHAR *pwsz2; + XDEBUG_PRINTF(("// Checking if it's first level shared directory\n")); + pwsz2 = wcschr(buf+3, L'\\'); + if (pwsz2) { + CopyMemory(buf+2, pwsz2, (lstrlenW(pwsz2)+1)*sizeof(WCHAR)); + dwAttr = GetFileAttributesW(buf); + DEBUG_WSTR2NEWUTF8(buf, pszUtf8); + XDEBUG_PRINTF(("GetFileAttributes(\"%s\") = 0x%lX\n", pszUtf8, dwAttr)); + DEBUG_FREEUTF8(pszUtf8); + if (dwAttr != INVALID_FILE_ATTRIBUTES) { + iTargetFound = TRUE; + XDEBUG_PRINTF(("// Confirmed it's a first level shared directory\n")); + } + } + } + } + /* To do: + The above code works for network drives shared at the root level and one level below. + Ex: N: is \\server\C$ + junction target C:\Public\Temp\target.txt on N: + Resolves to N:\Public\Temp\target.txt + Ex: If N: is \\server\Public, which is shared directory C:\Public, + junction target C:\Public\Temp\target.txt on N: + Should resolve to N:\Temp\target.txt + Actually this could be extended by checking every possible parent path, + to support cases where the junction is on a shared level2 or below subdirectory. + Note that the share name is not always the same as the subdirectory + name, nor is it even in the server's root. + */ + } + } + } + } + if (!iTargetFound) { +#if 0 /* Initial implementation, which would have cause problems */ + lstrcpynW(buf, path, (int)bufsize); /* Report the target as identical to the source, to allow resolving it on the server side */ + buf[bufsize-1] = L'\0'; + nRead = lstrlenW(path); + RETURN_INT_COMMENT((int)nRead, ("Cannot get to the real target, which is on another server drive.\n")); +#else + errno = EINVAL; + RETURN_INT_COMMENT(-1, ("Inaccessible junction target, on another server drive.\n")); +#endif + } + } + + /* 2) Convert absolute junction targets to relative links, if possible. + This is useful because junctions are often used as substitutes + for symlinkds. But Windows always records absolute target paths, + even when relative paths were used for creating them. */ + GetFullPathNameW(buf, PATH_MAX, wszAbsPath2, NULL); + DEBUG_WSTR2NEWUTF8(wszAbsPath, pszUtf8); + XDEBUG_PRINTF(("szAbsPath = \"%s\"\n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + DEBUG_WSTR2NEWUTF8(wszAbsPath2, pszUtf8); + XDEBUG_PRINTF(("szAbsPath2 = \"%s\"\n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + /* Find the first (case insensitive) difference */ + for (p1=wszAbsPath, p2=wszAbsPath2; (*pc1 = *p1) && (*pc2 = *p2); p1++, p2++) { + CharLowerW(pc1); + CharLowerW(pc2); + if (*pc1 != *pc2) break; + } + if (p1 != wszAbsPath) { /* Both are on the same drive. Can be made relative. */ + WCHAR *pc; + /* Backtrack to the last \ */ + for ( ; *(p1-1) != L'\\'; p1--, p2--) ; + DEBUG_WSTR2NEWUTF8(p1, pszUtf8); + XDEBUG_PRINTF(("szRelPath1 = \"%s\"\n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + DEBUG_WSTR2NEWUTF8(p2, pszUtf8); + XDEBUG_PRINTF(("szRelPath2 = \"%s\"\n", pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + buf[0] = '\0'; + /* Count the # of parent directories that remain in path 1 */ + for (pc=p1; *pc; pc++) if (*pc == L'\\') lstrcatW(buf, L"..\\"); + /* Append what remains in path 2 */ + lstrcatW(buf, p2); + /* That's the relative link */ + nRead = lstrlenW(buf); + } /* Else the drives differ. Paths cannot be relative. Don't change buf. */ + } + + DEBUG_WSTR2NEWUTF8(buf, pszUtf8); + DEBUG_LEAVE(("return %d; // \"%s\"\n", (int)nRead, pszUtf8)); + DEBUG_FREEUTF8(pszUtf8); + return (int)nRead; +} + +#pragma warning(default:4706) + +/* Posix routine readlink - MultiByte char version */ +ssize_t readlinkM(const char *path, char *buf, size_t bufsize, UINT cp) { + WCHAR wszPath[PATH_MAX]; + WCHAR wszTarget[PATH_MAX]; + int n; + ssize_t nResult; + char *pszDefaultChar; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszPath, /* lpWideCharStr, */ + COUNTOF(wszPath) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("readlinkM(\"%s\", ...); // Conversion to Unicode failed. errno=%d - %s\n", path, errno, strerror(errno))); + return -1; + } + + nResult = readlinkW(wszPath, wszTarget, PATH_MAX); + if (nResult <= 0) return nResult; + + pszDefaultChar = (cp == CP_UTF8) ? NULL : "?"; + n = WideCharToMultiByte(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + wszTarget, /* lpWideCharStr, */ + (int)nResult + 1, /* cchWideChar, */ + buf, /* lpMultiByteStr, */ + (int)bufsize, /* cbMultiByte, */ + pszDefaultChar, /* lpDefaultChar, */ + NULL /* lpUsedDefaultChar */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_PRINTF(("readlinkM(\"%s\", ...); // Conversion back from Unicode failed. errno=%d - %s\n", path, errno, strerror(errno))); + return -1; + } + + return n; +} + +#endif + + diff --git a/deps/MsvcLibX/src/realpath.c b/deps/MsvcLibX/src/realpath.c new file mode 100644 index 0000000000000000000000000000000000000000..5fbcf773a24d0950ac8099cd9274fcbb3157a954 --- /dev/null +++ b/deps/MsvcLibX/src/realpath.c @@ -0,0 +1,600 @@ +/*****************************************************************************\ +* * +* Filename realpath.c * +* * +* Description Resolve links and remove . and .. parts in pathnames * +* * +* Notes TO DO: Make Wide & MultiByte versions for Windows * +* * +* TO DO: Microsoft provides a convenient routine, for which * +* we could provide a MultiByte version: (in MSVC's stdlib.h)* +* char *_fullpath(char *absPath, const char *relPath, size_t maxLength); * +* * +* History * +* 2014-02-10 JFL Created this module with routine ResolveLinks() for Win32.* +* 2014-02-19 JFL Added OS-independant CompactPath() subroutine. * +* 2014-02-20 JFL Implemented realpath() for both DOS and Windows. * +* 2014-03-06 JFL Check for buffer overflows, and return ENAMETOOLONG. * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* 2016-08-25 JFL Added routine ResolveLinksA(). * +* 2016-09-12 JFL Moved GetFileAttributesU() to its own module. * +* Bug fix: Add the drive letter if it's not specified. * +* Bug fix: Detect and report output buffer overflows. * +* Convert short WIN32 paths to long paths. * +* 2016-09-13 JFL Resize output buffers, to avoid wasting lots of memory. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +#include +#include +#include +#include /* For _getdcwd() */ +#include /* For toupper() */ +#include "msvcDebugm.h" +#include "msvcLimits.h" +#include "msvcUnistd.h" +#include "msvcWindows.h" + +#define TRUE 1 +#define FALSE 0 + +/*---------------------------------------------------------------------------*\ +* * +| Function CompactPath | +| | +| Description Remove all ., .., and extra / or \ separators in a path | +| | +| Parameters const char *path Pathname to cleanup | +| char *buf Output buffer | +| size_t bufsize Size of the output buffer | +| | +| Notes Allows having path = outbuf, ie. in-place compacting. | +| Supports both relative and absolute paths. | +| | +| Returns 0 = success, or -1 = error, with errno set | +| | +| History | +| 2014-02-19 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +int CompactPath(const char *path, char *outbuf, size_t bufsize) { + const char *pcIn; + char *pcOut; + int i, j, inSize, outSize; + char c = '\0'; + char lastc = '\0'; +#define MAX_SUBDIRS (PATH_MAX / 2) /* Worst case is: \1\1\1\1\1\1... */ + const char *pParts[MAX_SUBDIRS]; + int lParts[MAX_SUBDIRS]; + int lPart = 0; + int nParts = 0; + int isAbsolute = FALSE; + int nDotDotParts = 0; + + pcIn = path; + inSize = (int)strlen(path) + 1; + pcOut = outbuf; + outSize = (int)bufsize; + + if (*pcIn && (pcIn[1] == ':')) { /* There's a drive letter */ + *(pcOut++) = *(pcIn++); /* Copy it */ + *(pcOut++) = *(pcIn++); + inSize -= 2; + outSize -= 2; + } + + /* Scan the input pathname, recording pointers to every part of the pathname */ + for (i=0; i outSize) goto not_compact_enough; + if (pcOut != pParts[0]) strncpy(pcOut, pParts[0], lParts[0]); + pcOut += lParts[0]; + outSize -= lParts[0]; + } else { + if (pcOut == outbuf) { + if (!outSize) goto not_compact_enough; + *(pcOut++) = '.'; /* Special case for "subdir\..", which is "." and not "" */ + outSize -= 1; + } + } + for (i=1; i outSize) goto not_compact_enough; + if (pcOut != pParts[i]) strncpy(pcOut, pParts[i], lParts[i]); + pcOut += lParts[i]; + outSize -= lParts[i]; + } + *pcOut = '\0'; + + return (int)(pcOut - outbuf); +} + + +#ifdef _MSDOS + +/* Standard C library routine realpath() */ +/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */ +char *realpath(const char *path, char *outbuf) { + char *pOutbuf = outbuf; + int iErr; + const char *pc; + + if (!pOutbuf) pOutbuf = malloc(PATH_MAX); + if (!pOutbuf) { + errno = ENOMEM; + return NULL; + } + + /* Convert relative paths to absolute paths */ + pc = path; + if (pc[0] && (pc[1] == ':')) pc += 2; /* Skip the drive letter, if any */ + if ((*pc != '/') && (*pc != '\\')) { /* This is a relative path */ + int iDrive = 0; + if (pc != path) { /* A drive was specified */ + iDrive = _toupper(path[0]) - '@'; /* A=1, B=2, ... */ + } + _getdcwd(iDrive, pOutbuf, PATH_MAX); + if ((strlen(pOutbuf) + strlen(pc) + 2) > PATH_MAX) { +realpath_failed: + errno = ENAMETOOLONG; + if (!outbuf) free(pOutbuf); + return NULL; + } + strcat(pOutbuf, "\\"); + strcat(pOutbuf, pc); + path = pOutbuf; + } else if (pc == path) { /* This is an absolute path without a drive letter */ + pOutbuf[0] = (char)(_getdrive() + 0x40); + pOutbuf[1] = ':'; + if ((strlen(path) + 3) > PATH_MAX) goto realpath_failed; + strcpy(pOutbuf+2, path); + path = pOutbuf; + } + + /* TO DO: Resolve substituted drives */ + + /* TO DO: Convert short paths to long paths, and correct the name case */ + + /* Remove useless parts in the absolute path */ + iErr = CompactPath(path, pOutbuf, PATH_MAX); + if (iErr == -1) { /* CompactPath() sets errno */ + if (!outbuf) free(pOutbuf); + return NULL; + } + + if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1); + return pOutbuf; +} + +#endif + + +#ifdef _WIN32 + +#include /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ + +/*---------------------------------------------------------------------------*\ +* * +| Function ResolveLinks | +| | +| Description Resolve all link names within a pathname | +| | +| Parameters const char *path Pathname to resolve | +| char *buf Output buffer | +| size_t bufsize Size of the output buffer | +| | +| Notes Description of the official path resolution process: | +| http://man7.org/linux/man-pages/man7/path_resolution.7.html +| | +| This function always returns a valid string in the output | +| buffer, even when it fails. This allows displaying a clue | +| about at which stage of the resolution things went wrong. | +| | +| Returns 0 = success, or -1 = error, with errno set | +| | +| History | +| 2014-02-07 JFL Created this routine | +| 2014-07-02 JFL Added support for pathnames >= 260 characters. | +* * +\*---------------------------------------------------------------------------*/ + +/* Linked list of previous pathnames */ +typedef struct _NAMELIST { + struct _NAMELIST *prev; + char *path; +} NAMELIST; + +/* Get the canonic name of a file, after resolving all links in its pathname */ +int ResolveLinksU1(const char *path, char *buf, size_t bufsize, NAMELIST *prev, int iDepth) { + char target[UTF8_PATH_MAX]; + int i; + int iErr = 0; + DWORD dwAttr; + char c = '\0'; + int iPath = 0; + int bFirst = 1; + ssize_t nRead; + int iBuf = 0; + NAMELIST list; + NAMELIST *pList; + + DEBUG_ENTER(("ResolveLinks1(\"%s\", 0x%p, %ld, 0x%p, %d);\n", path, buf, bufsize, prev, iDepth)); + + while (path[iPath]) { + /* int iPath0 = iPath; */ + /* int iBuf0 = iBuf; */ + int iBuf1; + /* Append the first name section to the output buffer */ + if (bFirst) { + bFirst = 0; + /* Special case of absolute pathnames */ + if (path[0] == '\\') { + if ((iBuf+1U) >= bufsize) { +resolves_too_long: + errno = ENAMETOOLONG; + RETURN_INT_COMMENT(-1, ("Name too long\n")); + } + c = buf[iBuf++] = path[iPath++]; /* Copy the root \ . */ + /* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */ + } else if (path[0] && (path[1] == ':')) { + if ((iBuf+1U) >= bufsize) goto resolves_too_long; + c = buf[iBuf++] = path[iPath++]; /* Copy the drive letter */ + /* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */ + if ((iBuf+1U) >= bufsize) goto resolves_too_long; + c = buf[iBuf++] = path[iPath++]; /* and the : */ + /* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */ + if (path[iPath] == '\\') { + if ((iBuf+1U) >= bufsize) goto resolves_too_long; + c = buf[iBuf++] = path[iPath++]; + /* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */ + } + } /* Else it's a relative pathname, handled in the common code below */ + } else { /* It's a continuation section in the path */ + if ((iBuf+1U) >= bufsize) goto resolves_too_long; + buf[iBuf++] = '\\'; + } + iBuf1 = iBuf; /* Index of the beginning of the node name we're about to add */ + for (i=0; (size_t)(iBuf+i) < (bufsize-1) ;i++) { + c = path[iPath+i]; + if (!c) break; + /* if (c == '/') break; */ + if (c == '\\') break; + /* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf+i, c)); */ + buf[iBuf+i] = c; + } + iBuf += i; + buf[iBuf] = '\0'; + while (c && (/* (c == '/') || */ (c == '\\'))) c=path[iPath + ++i]; /* Skip extra /, if any */ + iPath += i; + /* DEBUG_PRINTF(("// Removed %d characters from path\n", iPath - iPath0)); */ + /* Get the file type */ + dwAttr = GetFileAttributesU(buf); + DEBUG_PRINTF(("// \"%s\" is %s\n", buf, (dwAttr == INVALID_FILE_ATTRIBUTES)?"not found":( + (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)?"a reparse point":( + (dwAttr & FILE_ATTRIBUTE_DIRECTORY)?"a directory":"a file")))); + if (dwAttr == INVALID_FILE_ATTRIBUTES) { + errno = ENOENT; + if (path[iPath]) { /* Append the remainder of the input path, even though we know it's invalid */ + if ((iBuf+1U+lstrlen(path+iPath)) < bufsize) { + buf[iBuf++] = '\\'; + lstrcpy(buf+iBuf, path+iPath); + } + } + RETURN_INT_COMMENT(-1, ("No such file: \"%s\"\n", buf)); + } + if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT) { + nRead = readlinkU(buf, target, sizeof(target)); + if (nRead == -1) { + if (errno == EINVAL) { /* This is a reparse point, but not a symlink or a junction */ + goto file_or_directory; + } + /* Anything else is a real error, and resolution cannot be done. */ + if (path[iPath]) { /* Append the remainder of the input path, even though we know it's invalid */ + if ((iBuf+1U+lstrlen(path+iPath)) < bufsize) { + buf[iBuf++] = '\\'; + lstrcpy(buf+iBuf, path+iPath); + } + } + RETURN_INT_COMMENT(-1, ("Dangling link: \"%s\"\n", buf)); + } + if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) && !lstrcmp(buf, target)) { + /* This is probably a junction pointing to an otherwise inaccessible area. + (See readlink() header in readlink.c for details about this case.) + Handle this junction like if it were a real directory, instead of a symlink. */ + goto file_or_directory; + } + if ( ((target[0] == '\\') /* || (target[0] == '/') */ ) + || (target[1] == ':')) { /* This is an absolute pathname */ + DEBUG_PRINTF(("// Absolute link to \"%s\"\n", target)); + iBuf = (int)lstrlen(target); /* Anticipate the new position after copying */ + if ((size_t)iBuf >= bufsize) goto resolves_too_long; + lstrcpy(buf, target); + } else { /* This is a relative pathname */ + DEBUG_PRINTF(("// Relative link to \"%s\"\n", target)); + /* So it'll replace the tail name in the output path */ + iBuf = iBuf1; /* The index right after the last path separator */ + DEBUG_PRINTF(("AppendPath(\"%.*s\", \"%s\"); // Target tail\n", iBuf, buf, target)); + if (((size_t)iBuf+lstrlen(target)) >= bufsize) goto resolves_too_long; + lstrcpy(buf+iBuf, target); + iBuf = CompactPath(buf, buf, bufsize); + } + /* Append the remainder of the input path, if any */ + DEBUG_PRINTF(("AppendPath(\"%s\", \"%s\"); // Path tail\n", buf, path+iPath)); + if (path[iPath]) { + if (iBuf && (buf[iBuf-1] != '\\')) { + if ((iBuf+1U) >= bufsize) goto resolves_too_long; + buf[iBuf++] = '\\'; + } + if (((size_t)iBuf+lstrlen(path+iPath)) >= bufsize) goto resolves_too_long; + lstrcpy(buf+iBuf, path+iPath); + iBuf = CompactPath(buf, buf, bufsize); + } + /* Check for max depth */ + if (iDepth == SYMLOOP_MAX) { + errno = ELOOP; + RETURN_INT_COMMENT(-1, ("Max symlink depth reached: \"%s\"\n", buf)); + } + /* Check for loops */ + for (pList = prev ; pList; pList = pList->prev) { + if (!lstrcmpi(buf, pList->path)) { + errno = ELOOP; + RETURN_INT_COMMENT(-1, ("Loop found: \"%s\"\n", buf)); + } + } + /* OK, no loop, so repeat the process for that new path */ + lstrcpy(target, buf); /* Keep that as a reference in the linked list, in case there are further links */ + list.prev = prev; + list.path = target; + iErr = ResolveLinksU1(target, buf, bufsize, &list, iDepth+1); + RETURN_INT_COMMENT(iErr, ("\"%s\"\n", buf)); + } else { /* It's a normal file or directory */ +file_or_directory: + if ((path[iPath]) && !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { + errno = ENOTDIR; + if ((iBuf+1U+lstrlen(path+iPath)) < bufsize) { + buf[iBuf++] = '\\'; + lstrcpy(buf+iBuf, path+iPath); + } + RETURN_INT_COMMENT(-1, ("File where dir expected: \"%s\"\n", buf)); + } + } + } + + RETURN_INT_COMMENT(0, ("Success: \"%s\"\n", buf)); +} + +int ResolveLinksU(const char *path, char *buf, size_t bufsize) { + char path1[UTF8_PATH_MAX]; + int nSize; + NAMELIST root; + int iErr; + + DEBUG_ENTER(("ResolveLinks(\"%s\", 0x%p, %ld);\n", path, buf, bufsize)); + + buf[0] = '\0'; /* Always output a valid string */ + + if (!*path) { /* Spec says an empty pathname is invalid */ + errno = ENOENT; + RETURN_INT_COMMENT(-1, ("Empty pathname\n")); + } + + /* Normalize the input path, using a single \ as path separator */ + nSize = CompactPath(path, path1, sizeof(path1)); + if (nSize == -1) { /* CompactPath() already sets errno = ENAMETOOLONG */ + RETURN_INT_COMMENT(-1, ("Path too long\n")); + } + if (path1[nSize-1] == '\\') { /* Spec says resolution must implicitly add a trailing dot, */ + if (nSize == sizeof(path1)) { /* to ensure that the last component is a directory. */ + errno = ENAMETOOLONG; + RETURN_INT_COMMENT(-1, ("Path too long after adding .\n")); + } + path1[nSize++] = '.'; /* So add it explicitely */ + path1[nSize] = '\0'; + } + root.path = path1; + root.prev = NULL; + iErr = ResolveLinksU1(path1, buf, bufsize, &root, 0); + nSize = lstrlen(buf); + /* Remove the final dot added above, if needed. */ + if ((nSize >= 2) && (buf[nSize-2] == '\\') && (buf[nSize-1] == '.')) buf[--nSize] = '\0'; + RETURN_INT_COMMENT(iErr, ("\"%s\"\n", buf)); +} + +/* ANSI version of the same, built upon the UTF-8 version */ +int ResolveLinksA(const char *path, char *buf, size_t bufsize) { + char pathU[UTF8_PATH_MAX]; + char pathU2[UTF8_PATH_MAX]; + WCHAR wszPath[PATH_MAX]; + int n; + int iErr; + + /* Convert the pathname to a unicode string */ + n = MultiByteToWideChar(CP_ACP, 0, path, (int)strlen(path) + 1, wszPath, PATH_MAX); + /* Convert it back to UTF-8 characters */ + if (n) n = WideCharToMultiByte(CP_UTF8, 0, wszPath, n, pathU, UTF8_PATH_MAX, NULL, NULL); + /* Check (unlikely) conversion errors */ + if (!n) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + + /* Resolve the links */ + iErr = ResolveLinksU(pathU, pathU2, UTF8_PATH_MAX); + + /* Convert the result back to ANSI */ + if (!iErr) { + n = MultiByteToWideChar(CP_UTF8, 0, pathU2, (int)strlen(pathU2) + 1, wszPath, PATH_MAX); + if (n) n = WideCharToMultiByte(CP_ACP, 0, wszPath, n, buf, (int)bufsize, NULL, NULL); + if (!n) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + } + + return iErr; +} + +/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */ +char *realpathU(const char *path, char *outbuf) { + char *pOutbuf = outbuf; + char *pPath1 = NULL; + char *pPath2 = NULL; + int iErr; + const char *pc; + size_t nSize; + DEBUG_CODE( + char *pszCause = "Out of memory"; + ) + int n; + + DEBUG_ENTER(("realpath(\"%s\", 0x%p);\n", path, outbuf)); + + if (!pOutbuf) pOutbuf = malloc(UTF8_PATH_MAX); + if (!pOutbuf) { +realpathU_failed: + if (!outbuf) free(pOutbuf); + free(pPath1); + free(pPath2); + errno = ENOMEM; + RETURN_CONST_COMMENT(NULL, ("%s\n", pszCause)); + } + + pPath1 = malloc(UTF8_PATH_MAX); + if (!pPath1) goto realpathU_failed; + + pPath2 = malloc(UTF8_PATH_MAX); + if (!pPath2) goto realpathU_failed; + + /* Convert relative paths to absolute paths */ + pc = path; + if (pc[0] && (pc[1] == ':')) pc += 2; /* Skip the drive letter, if any */ + if ((*pc != '/') && (*pc != '\\')) { /* This is a relative path */ + int iDrive = 0; + if (pc != path) { /* A drive was specified */ + iDrive = toupper(path[0]) - '@'; /* A=1, B=2, ... */ + } + _getdcwdU(iDrive, pPath1, UTF8_PATH_MAX); + nSize = UTF8_PATH_MAX - lstrlen(pPath1); + if ((lstrlen(pc) + 2U) > nSize) { + errno = ENAMETOOLONG; + DEBUG_CODE(pszCause = "Path too long after concatenating current dir"); + goto realpathU_failed; + } + strcat(pPath1, "\\"); + strcat(pPath1, pc); + path = pPath1; + } else if (pc == path) { /* This is an absolute path without a drive letter */ + pPath1[0] = (char)(_getdrive() + 0x40); + pPath1[1] = ':'; + if (strlen(path) > (UTF8_PATH_MAX-3)) { + errno = ENAMETOOLONG; + DEBUG_CODE(pszCause = "Path too long after adding drive"); + goto realpathU_failed; + } + strcpy(pPath1+2, path); + path = pPath1; + } + + /* Resolve links in the absolute path */ + iErr = ResolveLinksU(path, pPath2, UTF8_PATH_MAX); + if (iErr == -1) { + DEBUG_CODE(pszCause = "Resolution failed"); + goto realpathU_failed; + } + + /* Change short names to long names, and correct the name case */ + n = GetLongPathNameU(pPath2, pOutbuf, UTF8_PATH_MAX); /* This will NOT correct long names case */ + if (!n) { + DEBUG_CODE(pszCause = "Can't get long pathnames";) + goto realpathU_failed; + } + + DEBUG_LEAVE(("return 0x%p; // \"%s\"\n", pOutbuf, pOutbuf)); + if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1); + free(pPath1); + free(pPath2); + return pOutbuf; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/spawn.c b/deps/MsvcLibX/src/spawn.c new file mode 100644 index 0000000000000000000000000000000000000000..1dede9b712c7f12597ff9a61238ba9c4ea461089 --- /dev/null +++ b/deps/MsvcLibX/src/spawn.c @@ -0,0 +1,118 @@ +/*****************************************************************************\ +* * +* Filename spawn.c * +* * +* Description: WIN32 UTF-8 version of spawn * +* * +* Notes: * +* * +* History: * +* 2014-03-27 JFL Created this module. * +* 2014-07-03 JFL Added support for pathnames >= 260 characters. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +/* Microsoft C libraries include files */ +#include +/* MsvcLibX library extensions */ +#include "msvcDebugm.h" +#include "msvclibx.h" +#include "msvcLimits.h" + +#ifdef _WIN32 + +#include +#include + +/*---------------------------------------------------------------------------*\ +* * +| Function _spawnvpU | +| | +| Description UTF-8 version of Microsoft's _spawnvp | +| | +| Parameters: int iMode Spawning mode. P_WAIT or P_NOWAIT | +| char *pszCommand Program to start | +| char **argv List of arguments, terminated by NULL | +| | +| Returns: The exit code (if P_WAIT) or the process ID (if P_NOWAIT) | +| | +| Notes | +| | +| History | +| 2014-03-04 JFL Created this routine. | +* * +\*---------------------------------------------------------------------------*/ + +intptr_t _spawnvpU(int iMode, const char *pszCommand, char *const *argv) { + WCHAR wszCommand[PATH_MAX]; + WCHAR **wszArgv; + int n; + int nArgs; + int iArg; + intptr_t iRet; + + DEBUG_CODE({ + int i; + DEBUG_PRINTF(("_spawnvpU(%d, \"%s\", {", iMode, pszCommand)); + if (DEBUG_IS_ON()) { + for (i=0; argv[i]; i++) { + if (i) printf(", "); + printf("\"%s\"", argv[i]); + } + printf("});\n"); + } + }) + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + pszCommand, /* lpMultiByteStr, */ + wszCommand, /* lpWideCharStr, */ + COUNTOF(wszCommand) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + + for (nArgs=0; argv[nArgs]; nArgs++) ; /* Count the number of arguments */ + wszArgv = (WCHAR **)malloc((nArgs+1) * sizeof(WCHAR *)); + if (!wszArgv) return -1; /* errno already set by malloc */ + + for (iArg=0; argv[iArg]; iArg++) { /* Convert every argument */ + int iArgBufSize = lstrlen(argv[iArg]) + 1; + wszArgv[iArg] = malloc(sizeof(WCHAR)*iArgBufSize); + if (!wszArgv[iArg]) { + while (iArg) free(wszArgv[--iArg]); /* Free the partial arg list */ + free(wszArgv); + return -1; /* errno already set by malloc */ + } + /* Convert the argument to a unicode string. This is not a pathname, so just do a plain conversion */ + n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + 0, /* dwFlags, */ + argv[iArg], /* lpMultiByteStr, */ + iArgBufSize, /* cbMultiByte, */ + wszArgv[iArg], /* lpWideCharStr, */ + iArgBufSize /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + while (iArg >= 0) free(wszArgv[iArg--]); /* Free the partial arg list */ + free(wszArgv); + return -1; + } + } + wszArgv[nArgs] = NULL; + + iRet = _wspawnvp(iMode, wszCommand, wszArgv); + + while (nArgs) free(wszArgv[--nArgs]); /* Free the full arg list */ + free(wszArgv); + return iRet; +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/strerror.c b/deps/MsvcLibX/src/strerror.c new file mode 100644 index 0000000000000000000000000000000000000000..a10fc45753bae73043e051cedc434204eeb832b8 --- /dev/null +++ b/deps/MsvcLibX/src/strerror.c @@ -0,0 +1,54 @@ +/*****************************************************************************\ +* * +* Filename strerror.c * +* * +* Description: WIN32 update of strerror * +* * +* Notes: MSVC defines error messages only up to errno 42 EILSEQ * +* * +* History: * +* 2014-03-06 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include +#include "msvclibx.h" + +#ifdef _WIN32 + +/*---------------------------------------------------------------------------*\ +* * +| Function strerror | +| | +| Description UTF-8 version of strerror | +| | +| Parameters int errnum Error number | +| | +| Returns Pointer to the corresponding error message. | +| | +| Notes | +| | +| History | +| 2014-03-06 JFL Created this routine. | +* * +\*---------------------------------------------------------------------------*/ + +#pragma warning(disable:4100) /* Ignore the "unreferenced formal parameter" warning */ + +char *strerror(int errnum) { + switch (errnum) { + case ELOOP: + return "Symbolic links loop found"; /* Workaround for the missing entry in MSVC list */ + default: + if (errnum > _sys_nerr) errnum = _sys_nerr; + return _sys_errlist[errnum]; + } +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/strndup.c b/deps/MsvcLibX/src/strndup.c new file mode 100644 index 0000000000000000000000000000000000000000..2c75cb9ed58b946620dd43875d2f72245d810145 --- /dev/null +++ b/deps/MsvcLibX/src/strndup.c @@ -0,0 +1,34 @@ +/*****************************************************************************\ +* * +* Filename strndup.c * +* * +* Description: WIN32 port of standard C library's strndup() * +* * +* Notes: * +* * +* History: * +* 2014-02-13 JFL Created this module. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include + +/* Duplicate a string, up to at most size characters */ +char *strndup(const char *s, size_t size) { + size_t l; + char *s2; + l = strlen(s); + if (l > size) l=size; + s2 = malloc(l+1); + if (s2) { + strncpy(s2, s, l); + s2[l] = '\0'; + } + return s2; +} + diff --git a/deps/MsvcLibX/src/strptime.c b/deps/MsvcLibX/src/strptime.c new file mode 100644 index 0000000000000000000000000000000000000000..716b573a345884b76b73e4b6c006846bcce371cf --- /dev/null +++ b/deps/MsvcLibX/src/strptime.c @@ -0,0 +1,396 @@ +/*****************************************************************************\ +* * +* Filename strptime.c * +* * +* Description: WIN32 port of standard C library's strptime() * +* * +* Notes: * +* * +* History: * +* 2014-02-17 JFL Created this module. * +* * +\*****************************************************************************/ + +#include +#include +#include + +/* + * We do not implement alternate representations. However, we always + * check whether a given modifier is allowed for a certain conversion. + */ +#define ALT_E 0x01 +#define ALT_O 0x02 +/* #define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } */ +#define LEGAL_ALT(x) { ; } +#define TM_YEAR_BASE (1970) + +static int conv_num(const char **, int *, int, int); +static int strncasecmp(char *s1, char *s2, size_t n); + +static const char *day[7] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" +}; +static const char *abday[7] = { + "Sun","Mon","Tue","Wed","Thu","Fri","Sat" +}; +static const char *mon[12] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" +}; +static const char *abmon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +static const char *am_pm[2] = { + "AM", "PM" +}; + + +#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */ +char * strptime(const char *buf, const char *fmt, struct tm *tm) +{ + char c; + const char *bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') + { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (isspace(c)) + { + while (isspace(*bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + +again: switch (c = *fmt++) + { + case '%': /* "%%" is converted to "%". */ + literal: + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, "%x %X", tm))) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%m/%d/%y", tm))) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%H:%M", tm))) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%I:%M:%S %p", tm))) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, "%m/%d/%y", tm))) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) + { + /* Full name. */ + len = strlen(day[i]); + if (strncasecmp((char *)(day[i]), (char *)bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abday[i]); + if (strncasecmp((char *)(abday[i]), (char *)bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) + { + /* Full name. */ + + len = strlen(mon[i]); + if (strncasecmp((char *)(mon[i]), (char *)bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abmon[i]); + if (strncasecmp((char *)(abmon[i]),(char *) bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) + { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; + + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; +/* +// case 'p': /* The locale's equivalent of AM/PM. */ +/* LEGAL_ALT(0); +// /* AM? */ +/* if (strcasecmp(am_pm[0], bp) == 0) +// { +// if (tm->tm_hour > 11) +// return (0); +// +// bp += strlen(am_pm[0]); +// break; +// } +// /* PM? */ +/* else if (strcasecmp(am_pm[1], bp) == 0) +// { +// if (tm->tm_hour > 11) +// return (0); +// +// tm->tm_hour += 12; +// bp += strlen(am_pm[1]); +// break; +// } +// +// /* Nothing matched. */ +/* return (0); +*/ + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) + { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (isspace(*bp)) + bp++; + break; + + + default: /* Unknown/unsupported conversion. */ + return (0); + } + + } + + /* LINTED functional specification */ + return ((char *)bp); +} +#pragma warning(default:4706) + + +static int conv_num(const char **buf, int *dest, int llim, int ulim) +{ + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} + +int strncasecmp(char *s1, char *s2, size_t n) +{ + if (n == 0) + return 0; + + while (n-- != 0 && tolower(*s1) == tolower(*s2)) + { + if (n == 0 || *s1 == '\0' || *s2 == '\0') + break; + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} diff --git a/deps/MsvcLibX/src/symlink.c b/deps/MsvcLibX/src/symlink.c new file mode 100644 index 0000000000000000000000000000000000000000..ce2bbe58a26deb1a61936b9d0ef5a26d24cf7731 --- /dev/null +++ b/deps/MsvcLibX/src/symlink.c @@ -0,0 +1,455 @@ +/*****************************************************************************\ +* * +* Filename symlink.c * +* * +* Description: WIN32 port of standard C library's symlink() * +* * +* Notes: Requires SE_CREATE_SYMBOLIC_LINK_NAME privilege. * +* * +* * +* History: * +* 2014-02-05 JFL Created this module. * +* 2014-03-02 JFL Split the functions into a WSTR and an UTF-8 version. * +* 2014-03-20 JFL Restructured Windows link management functions into Wide * +* and MultiByte versions, and changed the Unicode and Ansi * +* versions to macros. * +* 2014-07-03 JFL Added support for pathnames >= 260 characters. * +* 2015-12-14 JFL Added a workaround allowing to link support for symlinks * +* in all apps, even when targeting XP or older systems that * +* do not support symlinks. * +* 2016-08-25 JFL Fixed two warnings. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */ + +#include "msvcUnistd.h" +#pragma comment(lib, "Mpr.lib") + +#include +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#ifdef _WIN32 + +#include + +#include "msvcReparsept.h" + +/*---------------------------------------------------------------------------*\ +* * +| Function: junction | +| | +| Description: Create an NTFS junction | +| | +| Parameters: const char *targetName The junction target name | +| const char *junctionName The junction name | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: Uses the undocumented FSCTL_SET_REPARSE_POINT structure | +| Win2K uses for mount points and junctions. | +| | +| History: | +| 2014-02-05 JFL Adapted from Mark Russinovitch CreateJuction sample | +* * +\*---------------------------------------------------------------------------*/ + +/* MsvcLibX-specific routine to create an NTFS junction - Wide char version */ +int junctionW(const WCHAR *targetName, const WCHAR *junctionName) { + WCHAR wszReparseBuffer[PATH_MAX*3]; + WCHAR wszVolumeName[] = L"X:\\"; + WCHAR wszJunctionFullName[PATH_MAX]; + WCHAR wszFileSystem[PATH_MAX] = L""; + WCHAR wszTargetTempName[PATH_MAX]; + WCHAR wszTargetFullName[PATH_MAX]; + WCHAR wszTargetNativeName[PATH_MAX]; + WCHAR *pwszFilePart; + size_t lNativeName; + HANDLE hFile; + DWORD dwReturnedLength; + PMOUNTPOINT_WRITE_BUFFER reparseInfo = (PMOUNTPOINT_WRITE_BUFFER)wszReparseBuffer; + DEBUG_CODE( + char szJunction8[UTF8_PATH_MAX]; + char szTarget8[UTF8_PATH_MAX]; + char szTemp8[UTF8_PATH_MAX]; + ) + UINT uiDriveType; + DWORD dwFileSystemFlags; + + DEBUG_WSTR2UTF8(junctionName, szJunction8, sizeof(szJunction8)); + DEBUG_WSTR2UTF8(targetName, szTarget8, sizeof(szTarget8)); + DEBUG_ENTER(("junction(\"%s\", \"%s\");\n", szTarget8, szJunction8)); + + /* Get the full path of the junction */ + if (!GetFullPathNameW(junctionName, PATH_MAX, wszJunctionFullName, &pwszFilePart)) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("%s is an invalid junction name\n", junctionName)); + } + + /* Convert relative paths to absolute paths relative to the junction. */ + /* Note: I tested creating relative targets: They can be created, but Windows can't follow them. */ + if ((targetName[0] != '\\') && (targetName[1] != ':')) { + size_t lTempName = PATH_MAX; + lstrcpyW(wszTargetTempName, wszJunctionFullName); + lTempName -= lstrlenW(wszJunctionFullName); + if (lTempName < (size_t)(lstrlenW(targetName) + 5)) { + errno = ENAMETOOLONG; + RETURN_INT_COMMENT(-1, ("Intermediate target name too long\n")); + } + lstrcatW(wszTargetTempName, L"\\..\\"); + lstrcatW(wszTargetTempName, targetName); + if (!GetFullPathNameW(wszTargetTempName, PATH_MAX, wszTargetFullName, &pwszFilePart)) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("%s is an invalid target directory name\n", szTarget8)); + } + DEBUG_WSTR2UTF8(wszTargetFullName, szTemp8, sizeof(szTemp8)); + XDEBUG_PRINTF(("wszTargetFullName = \"%s\"; // After absolutization relative to the junction\n", szTemp8)); + } else { /* Already an absolute name. Just make sure it's canonic. (Without . or ..) */ + if (!GetFullPathNameW(targetName, PATH_MAX, wszTargetFullName, &pwszFilePart)) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("%s is an invalid target directory name\n", szTarget8)); + } + DEBUG_WSTR2UTF8(wszTargetFullName, szTemp8, sizeof(szTemp8)); + XDEBUG_PRINTF(("wszTargetFullName = \"%s\"; // After direct reabsolutization\n", szTemp8)); + } + /* Make sure the target drive letter is upper case */ +#pragma warning(disable:4305) /* truncation from 'LPSTR' to 'WCHAR' */ +#pragma warning(disable:4306) /* conversion from 'WCHAR' to 'WCHAR *' of greater size */ + wszTargetFullName[0] = (WCHAR)CharUpperW((WCHAR *)(wszTargetFullName[0])); +#pragma warning(default:4706) +#pragma warning(default:4705) + + /* Make sure that the junction is on a file system that supports reparse points (Ex: NTFS) */ + wszVolumeName[0] = wszJunctionFullName[0]; + GetVolumeInformationW(wszVolumeName, NULL, 0, NULL, NULL, &dwFileSystemFlags, wszFileSystem, sizeof(wszFileSystem)/sizeof(WCHAR)); + if (!(dwFileSystemFlags & FILE_SUPPORTS_REPARSE_POINTS)) { + errno = EDOM; + DEBUG_WSTR2UTF8(wszFileSystem, szTemp8, sizeof(szTemp8)); + RETURN_INT_COMMENT(-1, ("Junctions are not supported on %s volumes\n", szTemp8)); + } + + /* On network drives, make sure the target refers to the local drive on the server */ + /* Note: The local path on the server can be inferred in simple cases, but not in the general case */ + uiDriveType = GetDriveTypeW(wszVolumeName); + DEBUG_WSTR2UTF8(wszVolumeName, szTemp8, sizeof(szTemp8)); + XDEBUG_PRINTF(("GetDriveType(\"%s\") = %d // %s drive\n", szTemp8, uiDriveType, (uiDriveType == DRIVE_REMOTE) ? "Network" : "Local")); + if (uiDriveType == DRIVE_REMOTE) { + WCHAR wszLocalName[] = L"X:"; + WCHAR wszRemoteName[PATH_MAX]; + DWORD dwErr; + DWORD dwLength = PATH_MAX; + wszLocalName[0] = wszJunctionFullName[0]; + dwErr = WNetGetConnectionW(wszLocalName, wszRemoteName, &dwLength); + if (dwErr == NO_ERROR) { + WCHAR *pwsz; + DEBUG_CODE( + char szRemote8[UTF8_PATH_MAX]; + ) + DEBUG_WSTR2UTF8(wszRemoteName, szRemote8, sizeof(szRemote8)); + XDEBUG_PRINTF(("net use %c: %s\n", (char)(wszLocalName[0]), szRemote8)); + if ((wszRemoteName[0] == L'\\') && (wszRemoteName[1] == L'\\')) { + pwsz = wcschr(wszRemoteName+2, L'\\'); + if (pwsz) { + if ((pwsz[2] == L'$') && !pwsz[3]) { /* This is the root of a shared drive. Ex: \\server\D$ -> D: */ + wszTargetFullName[0] = pwsz[1]; /* Local drive name on the server */ + } else { /* Heuristic: Assume the share name is a subdirectory name on the C: drive. Ex: \\server\Public -> C:\Public */ + int lTempName = PATH_MAX; + wszTargetTempName[0] = L'C'; /* Local drive name on the server */ + wszTargetTempName[1] = L':'; + lstrcpyW(wszTargetTempName+2, pwsz); + lTempName -= lstrlenW(wszTargetTempName); + if (lTempName > lstrlenW(wszTargetFullName+2)) { + lstrcatW(wszTargetTempName, wszTargetFullName+2); + lstrcpyW(wszTargetFullName, wszTargetTempName); + } + } + } + } + } else { + XDEBUG_PRINTF(("WNetGetConnection(\"%s\") failed: Error %d\n", szTemp8, dwErr)); + } + } + + /* Make the native target name */ + lNativeName = wsprintfW(wszTargetNativeName, L"\\??\\%s", wszTargetFullName ); + if ( (wszTargetNativeName[lNativeName-1] == L'\\') && + (wszTargetNativeName[lNativeName-2] != L':')) { + wszTargetNativeName[lNativeName-1] = L'\0'; + lNativeName -= 1; + } + + /* Create the link - ignore errors since it might already exist */ + DEBUG_WSTR2UTF8(wszJunctionFullName, szJunction8, sizeof(szJunction8)); + DEBUG_WSTR2UTF8(wszTargetNativeName, szTarget8, sizeof(szTarget8)); + DEBUG_PRINTF(("// Creating junction \"%s\" -> \"%s\"\n", szJunction8, szTarget8)); + CreateDirectoryW(junctionName, NULL); + hFile = CreateFileW(junctionName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL ); + if (hFile == INVALID_HANDLE_VALUE) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("Error creating %s:\n", szJunction8)); + } + + /* Build the reparse info */ + ZeroMemory(reparseInfo, sizeof( *reparseInfo )); + reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + reparseInfo->ReparseTargetLength = (WORD)(lNativeName * sizeof(WCHAR)); + reparseInfo->ReparseTargetMaximumLength = reparseInfo->ReparseTargetLength + sizeof(WCHAR); + reparseInfo->ReparseDataLength = reparseInfo->ReparseTargetLength + MOUNTPOINT_WRITE_BUFFER_HEADER_SIZE - 4; + lstrcpynW(reparseInfo->ReparseTarget, wszTargetNativeName, PATH_MAX); + + /* Set the link */ + if (!DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo, + /* reparseInfo->ReparseDataLength + 4, */ + reparseInfo->ReparseDataLength + 8, + NULL, 0, &dwReturnedLength, NULL )) { + errno = Win32ErrorToErrno(); + CloseHandle(hFile); + RemoveDirectoryW(junctionName); + RETURN_INT_COMMENT(-1, ("Error setting junction for %s:\n", szJunction8)); + } + + CloseHandle(hFile); + RETURN_INT_COMMENT(0, ("Created \"%s\" -> \"%s\"\n", szJunction8, szTarget8)); +} + +/* MsvcLibX-specific routine to create an NTFS junction - MultiByte char version */ +int junctionM(const char *targetName, const char *junctionName, UINT cp) { + WCHAR wszJunction[PATH_MAX]; + WCHAR wszTarget[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + junctionName, /* lpMultiByteStr, */ + wszJunction, /* lpWideCharStr, */ + COUNTOF(wszJunction) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + targetName, /* lpMultiByteStr, */ + wszTarget, /* lpWideCharStr, */ + COUNTOF(wszTarget) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + return junctionW(wszTarget, wszJunction); +} + +/*---------------------------------------------------------------------------*\ +* * +| Function: symlink | +| | +| Description: Create an NTFS symbolic link | +| | +| Parameters: const TCHAR *targetName The symlink target name | +| const TCHAR *linkName The symlink name | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: | +| | +| History: | +| 2014-02-04 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +/* Symbolic links first appeared in Vista WINVER 0x600. + Add support for both old and new versions, by using Windows' CreateSymbolicLink + function if it exists, or else a short stub that fails every time if not. */ +#if WINVER < 0x600 /* This mechanism is only necessary when targeting older versions of Windows */ + +typedef BOOLEAN (WINAPI *LPCREATESYMBOLICLINK)(LPCWSTR lpSymlinkName, LPCWSTR lpTargetName, DWORD dwFlags); + +/* Default routine to use if Windows does not have CreateSymbolicLinkW */ +#pragma warning(disable:4100) /* 'dwFlags' : unreferenced formal parameter */ +BOOLEAN WINAPI DefaultCreateSymbolicLinkW(LPCWSTR lpSymlinkName, LPCWSTR lpTargetName, DWORD dwFlags) { + DWORD dwAttr = GetFileAttributesW(lpTargetName); + if (dwAttr != INVALID_FILE_ATTRIBUTES) { /* If the target exists */ + if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { /* And if the target is a directory */ + /* Try creating a junction as a workaround */ + int iRet = junctionW(lpTargetName, lpSymlinkName); /* 0=Success, -1=Failure */ + return (BOOLEAN)(iRet + 1); /* 1=Success, 0=Failure */ + } + } + /* Else fail, as symlinks to files aren't supported by this Windows version */ + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +} +#pragma warning(default:4105) + +/* Initialization routine. Tries using Windows' CreateSymbolicLinkW if present, else uses our default above */ +BOOLEAN WINAPI InitCreateSymbolicLink(LPCWSTR lpSymlinkName, LPCWSTR lpTargetName, DWORD dwFlags) { + extern LPCREATESYMBOLICLINK lpCreateSymbolicLinkW; + lpCreateSymbolicLinkW = (LPCREATESYMBOLICLINK) GetProcAddress( + GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW"); + if (!lpCreateSymbolicLinkW) { /* This is XP or older, not supporting symlinks */ + lpCreateSymbolicLinkW = DefaultCreateSymbolicLinkW; + } + return (*lpCreateSymbolicLinkW)(lpSymlinkName, lpTargetName, dwFlags); +} + +LPCREATESYMBOLICLINK lpCreateSymbolicLinkW = InitCreateSymbolicLink; + +/* Make sure all uses of CreateSymbolicLinkW below go through our static pointer above */ +#undef CreateSymbolicLinkW +#define CreateSymbolicLinkW (*lpCreateSymbolicLinkW) + +#endif /* WINVER < 0x600 */ + +/* Posix routine symlink - Wide char version */ +int symlinkW(const WCHAR *targetName, const WCHAR *linkName) { + DWORD dwAttr; + BOOL done; + DWORD dwFlags; + int err; + DEBUG_CODE( + char szLink8[UTF8_PATH_MAX]; + char szTarget8[UTF8_PATH_MAX]; + ) + + DEBUG_WSTR2UTF8(linkName, szLink8, sizeof(szLink8)); + DEBUG_WSTR2UTF8(targetName, szTarget8, sizeof(szTarget8)); + DEBUG_ENTER(("symlink(\"%s\", \"%s\");\n", szTarget8, szLink8)); + + /* Work around an incompatibility between Unix and Windows: + // Windows needs to know if the target is a file or a directory; + // But Unix allows creating dangling links, in which case we cannot guess what type it'll be. */ + dwAttr = GetFileAttributesW(targetName); + DEBUG_PRINTF(("GetFileAttributes() = 0x%lX\n", dwAttr)); + dwFlags = 0; + if (dwAttr != INVALID_FILE_ATTRIBUTES) { /* File exists */ + if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + } else { /* Target does not exst. Use a heuristic: Names with trailing / or \ are directories */ + size_t len = lstrlenW(targetName); + if (len) { + WCHAR c = targetName[len-1]; + if ((c == L'/') || (c == L'\\')) dwFlags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + } + } + + done = CreateSymbolicLinkW(linkName, targetName, dwFlags); + + if (done) { + err = 0; + } else { + errno = Win32ErrorToErrno(); + err = -1; + } + RETURN_INT_COMMENT(err, ("%s\n", err?"Failed to create link":"Created link successfully")); +} + +/* Posix routine symlink - MultiByte char version */ +int symlinkM(const char *targetName, const char *linkName, UINT cp) { + WCHAR wszLink[PATH_MAX]; + WCHAR wszTarget[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + linkName, /* lpMultiByteStr, */ + wszLink, /* lpWideCharStr, */ + COUNTOF(wszLink) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + targetName, /* lpMultiByteStr, */ + wszTarget, /* lpWideCharStr, */ + COUNTOF(wszTarget) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + return symlinkW(wszTarget, wszLink); +} + +/*---------------------------------------------------------------------------*\ +* * +| Function: symlinkd | +| | +| Description: Create an NTFS symbolic directory link | +| | +| Parameters: const TCHAR *targetName The symlink target name | +| const TCHAR *linkName The symlink name | +| | +| Returns: 0 = Success, -1 = Failure | +| | +| Notes: | +| | +| History: | +| 2014-03-04 JFL Created this routine | +* * +\*---------------------------------------------------------------------------*/ + +/* MsvcLibX-specific routine to create an NTFS symlinkd - Wide char version */ +int symlinkdW(const WCHAR *targetName, const WCHAR *linkName) { + BOOL done; + int err; + DEBUG_CODE( + char szLink8[UTF8_PATH_MAX]; + char szTarget8[UTF8_PATH_MAX]; + ) + + DEBUG_WSTR2UTF8(linkName, szLink8, sizeof(szLink8)); + DEBUG_WSTR2UTF8(targetName, szTarget8, sizeof(szTarget8)); + DEBUG_ENTER(("symlinkd(\"%s\", \"%s\");\n", szTarget8, szLink8)); + + done = CreateSymbolicLinkW(linkName, targetName, SYMBOLIC_LINK_FLAG_DIRECTORY); + + if (done) { + err = 0; + } else { + errno = Win32ErrorToErrno(); + err = -1; + } + RETURN_INT_COMMENT(err, ("%s\n", err?"Failed to create link":"Created link successfully")); +} + +/* MsvcLibX-specific routine to create an NTFS symlinkd - MultiByte char version */ +int symlinkdM(const char *targetName, const char *linkName, UINT cp) { + WCHAR wszLink[PATH_MAX]; + WCHAR wszTarget[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + linkName, /* lpMultiByteStr, */ + wszLink, /* lpWideCharStr, */ + COUNTOF(wszLink) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + targetName, /* lpMultiByteStr, */ + wszTarget, /* lpWideCharStr, */ + COUNTOF(wszTarget) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + return -1; + } + return symlinkdW(wszTarget, wszLink); +} + +#endif + + diff --git a/deps/MsvcLibX/src/uname.c b/deps/MsvcLibX/src/uname.c new file mode 100644 index 0000000000000000000000000000000000000000..afa2ef0d5e0b25e4ba7c04f71f2fe3b8c2a10cf3 --- /dev/null +++ b/deps/MsvcLibX/src/uname.c @@ -0,0 +1,79 @@ +/*****************************************************************************\ +* * +* Filename: uname.c * +* * +* Description: Get the name of the current system. * +* * +* Notes: TO DO: Fix the Win32 windows version for Windows >= 8.1, * +* as explained in MSDN's GetVersion function page. * +* * +* TO DO: Do not rely on PROCESSOR_ARCHITECTURE to get the * +* processor architecture, because the WIN32 version * +* always sees "x86", even on "AMD64" systems. * +* * +* TO DO: Implement sysinfo.c, moving some of the code from * +* here to there, and use it. * +* * +* History: * +* 2014-05-30 JFL Created this file. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#include "sys/msvcTsname.h" +#include /* For itoa() */ + +static char major[4] = {0}; +static char minor[4] = {0}; + +#ifdef _MSDOS + +#include + +static char name[16] = {0}; + +int uname(struct utsname *pun) { + unsigned int wVersion = _bdos(0x30, 0, 0); /* int 21H ah=30H Get DOS version */ + + _itoa((int)(wVersion & 0x0F), major, 10); + _itoa((int)((wVersion >> 8) & 0x0F), minor, 10); + + /* Use _bdos instead of _intdosx, because even in large memory mode, static variables will be allocated in the default data segment */ + _bdos(0x5E, (unsigned short)(unsigned long)(char far *)name, 0); /* int 21H ax=5E00H ds:dx=&buf Get Machine Name */ + + pun->sysname = "MS-DOS"; /* Name of this operating system */ + pun->nodename = name; /* Name of this node on the network */ /* TO DO: Get it from LAN Manager */ + pun->release = major; /* Current release level of this implementation */ + pun->version = minor; /* Current version level of this release */ + pun->machine = "x86"; /* Name of the hardware type on which the system is running */ + + return 0; +} + +#endif /* defined(_MSDOS) */ + +/*---------------------------------------------------------------------------*/ + +#ifdef _WIN32 + +#include + +#pragma warning(disable:4996) /* Ignore the "This function or variable may be unsafe" warning for itoa() and getenv() */ + +int uname(struct utsname *pun) { + DWORD dwVersion = GetVersion(); + + _itoa((int)(dwVersion & 0x0F), major, 10); + _itoa((int)((dwVersion >> 8) & 0x0F), minor, 10); + + pun->sysname = getenv("OS"); /* Name of this operating system */ + pun->nodename = getenv("COMPUTERNAME"); /* Name of this node on the network */ + pun->release = major; /* Current release level of this implementation */ + pun->version = minor; /* Current version level of this release */ + pun->machine = getenv("PROCESSOR_ARCHITECTURE"); /* Name of the hardware type on which the system is running */ + + return 0; +} + +#endif /* defined(_WIN32) */ diff --git a/deps/MsvcLibX/src/utime.c b/deps/MsvcLibX/src/utime.c new file mode 100644 index 0000000000000000000000000000000000000000..cbddfecb01f9dd858a9ef03d9da7107c7116de15 --- /dev/null +++ b/deps/MsvcLibX/src/utime.c @@ -0,0 +1,216 @@ +/*****************************************************************************\ +* * +* Filename utime.c * +* * +* Description Updated utime() and port of standard C library's lutime() * +* * +* Notes TO DO: Create W, A, U versions of ResolveLinks(), then * +* create W, A, U versions of utime(). * +* * +* History * +* 2014-02-12 JFL Created this module. * +* 2014-06-04 JFL Fixed minors issues in debugging code. * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* 2016-08-25 JFL Added missing routine utimeA(). * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of Windows print routines */ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include "sys/msvcTime.h" /* Must be included before any direct or indirect inclusion */ +#include "msvcUtime.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#if defined(_DEBUG) +#include +#endif /* defined(_DEBUG) */ + +#ifdef _WIN32 + +#include +#include /* For MSVC's _get_osfhandle() */ +#include "msvcUnistd.h" /* For MsvcLibX's ResolveLinks() */ + +/* Convert a Windows FILETIME to a Unix time_t. + A FILETIME is the number of 100-nanosecond intervals since January 1, 1601. + A time_t is the number of 1-second intervals since January 1, 1970. */ + +time_t Filetime2Time_t(FILETIME *pFT) { + ULARGE_INTEGER ull; + ull.LowPart = pFT->dwLowDateTime; + ull.HighPart = pFT->dwHighDateTime; + return (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL); +} + +void Time_t2Filetime(time_t ft, FILETIME *pFT) { + ULARGE_INTEGER ull; + ull.QuadPart = ft + 11644473600ULL; + ull.QuadPart *= 10000000UL; + pFT->dwLowDateTime = ull.LowPart; + pFT->dwHighDateTime = ull.HighPart; +} + +DEBUG_CODE( + int Utimbuf2String(char *buf, size_t bufsize, const struct utimbuf *times) { + struct tm *pTime; + int n; + if (!times) { + return _snprintf(buf, bufsize, "NULL"); + } + pTime = localtime(&(times->modtime)); /* Time of last data modification */ + n = _snprintf(buf, bufsize, "{%4d-%02d-%02d %02d:%02d:%02d, ...}", + pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday, + pTime->tm_hour, pTime->tm_min, pTime->tm_sec); + return n; + } +); + +/* Low level subroutine used by all the other routines below. */ +int hutime(HANDLE hFile, const struct utimbuf *times) { + FILETIME ftLastAccess; /* last access time */ + FILETIME ftLastWrite; /* last write time */ + int iErr; + struct utimbuf now; + + if (!times) { + now.actime = now.modtime = time(NULL); + times = &now; + } + + Time_t2Filetime(times->actime, &ftLastAccess); + Time_t2Filetime(times->modtime, &ftLastWrite); + iErr = !SetFileTime(hFile, NULL, &ftLastAccess, &ftLastWrite); + if (iErr) { + errno = Win32ErrorToErrno(); + return -1; + } + return 0; +} + +/* Same as 'utime', but does not follow symbolic links. */ +int lutimeW(const WCHAR *path, const struct utimbuf *times) { + DWORD dwAttr; + DWORD dwFlagsAndAttributes; + int iErr; + HANDLE hLink; + + DEBUG_CODE({ + char buf[100]; + char szUtf8[UTF8_PATH_MAX]; + Utimbuf2String(buf, sizeof(buf), times); + DEBUG_WSTR2UTF8(path, szUtf8, sizeof(szUtf8)); + DEBUG_ENTER(("lutime(\"%s\", %s);\n", szUtf8, buf)); + }); + + dwAttr = GetFileAttributesW(path); + if (dwAttr == INVALID_FILE_ATTRIBUTES) { + errno = ENOENT; + RETURN_INT_COMMENT(-1, ("File does not exist\n")); + } + + dwFlagsAndAttributes = FILE_FLAG_OPEN_REPARSE_POINT; + if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS; + hLink = CreateFileW(path, /* lpFileName, */ + FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess, */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode, */ + NULL, /* lpSecurityAttributes, */ + OPEN_EXISTING, /* dwCreationDisposition, */ + dwFlagsAndAttributes, /* dwFlagsAndAttributes, */ + NULL /* hTemplateFile */ + ); + XDEBUG_PRINTF(("CreateFile() = 0x%p\n", hLink)); + if (hLink == INVALID_HANDLE_VALUE) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("Cannot open the pathname\n")); + } + + iErr = hutime(hLink, times); + CloseHandle(hLink); + RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0)); +} + +int lutimeA(const char *path, const struct utimbuf *times) { + WCHAR wszPath[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszPath, /* lpWideCharStr, */ + COUNTOF(wszPath) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_ENTER(("lutimeA(\"%s\", %p);\n", path, times)); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + return lutimeW(wszPath, times); +} + +int lutimeU(const char *path, const struct utimbuf *times) { + WCHAR wszPath[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszPath, /* lpWideCharStr, */ + COUNTOF(wszPath) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_ENTER(("lutimeU(\"%s\", %p);\n", path, times)); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + return lutimeW(wszPath, times); +} + +/* Same as 'utime', but takes an open file descriptor instead of a name. */ +int futime(int fd, const struct utimbuf *times) { + return hutime((HANDLE)_get_osfhandle(fd), times); +} + +/* Change the file access time to times->actime and its modification time to times->modtime. */ +int utimeA(const char *file, const struct utimbuf *times) { + char buf[PATH_MAX]; + int iErr; + + DEBUG_CODE({ + char buf[100]; + Utimbuf2String(buf, sizeof(buf), times); + DEBUG_ENTER(("utime(\"%s\", %s);\n", file, buf)); + }); + + iErr = ResolveLinksA(file, buf, sizeof(buf)); + if (iErr) RETURN_INT_COMMENT(iErr, ("Cannot resolve the link\n")); + + iErr = lutimeA(buf, times); + RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0)); +} + +/* Change the file access time to times->actime and its modification time to times->modtime. */ +int utimeU(const char *file, const struct utimbuf *times) { + char buf[UTF8_PATH_MAX]; + int iErr; + + DEBUG_CODE({ + char buf[100]; + Utimbuf2String(buf, sizeof(buf), times); + DEBUG_ENTER(("utime(\"%s\", %s);\n", file, buf)); + }); + + iErr = ResolveLinksU(file, buf, sizeof(buf)); + if (iErr) RETURN_INT_COMMENT(iErr, ("Cannot resolve the link\n")); + + iErr = lutimeU(buf, times); + RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0)); +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/utimes.c b/deps/MsvcLibX/src/utimes.c new file mode 100644 index 0000000000000000000000000000000000000000..9326bb5f74283abb59389a44300f621f2b79ff52 --- /dev/null +++ b/deps/MsvcLibX/src/utimes.c @@ -0,0 +1,219 @@ +/*****************************************************************************\ +* * +* Filename utimes.c * +* * +* Description: WIN32 port of standard C library's *utimes() * +* * +* Notes: TO DO: Create W, A, U versions of ResolveLinks(), then * +* create W, A, U versions of utimes(). * +* * +* History: * +* 2014-02-07 JFL Created this module. * +* 2014-03-24 JFL Renamed "statx.h" as the standard . * +* 2014-06-03 JFL Added support for WIDE, ANSI and UTF8 versions. * +* 2014-06-04 JFL Added handling of UTIME_NOW and UTIME_OMIT. * +* 2014-07-02 JFL Added support for pathnames >= 260 characters. * +* * +* Copyright 2016 Hewlett Packard Enterprise Development LP * +* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 * +\*****************************************************************************/ + +#define _UTF8_SOURCE /* Generate the UTF-8 version of Windows print routines */ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include "sys/msvcTime.h" /* Must be included before any direct or indirect inclusion */ +#include "sys/msvcStat.h" +#include "msvcDebugm.h" +#include "msvcLimits.h" + +#if defined(_DEBUG) +#include +#endif /* defined(_DEBUG) */ + +#ifdef _WIN32 + +#include +#include /* For MSVC's _get_osfhandle() */ +#include "msvcUnistd.h" /* For MsvcLibX's ResolveLinks() */ + +DEBUG_CODE( + int Timeval2String(char *buf, size_t bufsize, const struct timeval *tvp) { + struct tm *pTime; + int n; + if (tvp->tv_usec == UTIME_NOW) { + return _snprintf(buf, bufsize, "UTIME_NOW"); + } + if (tvp->tv_usec == UTIME_OMIT) { + return _snprintf(buf, bufsize, "UTIME_OMIT"); + } + pTime = localtime(&(tvp->tv_sec)); /* Time of last data modification */ + n = _snprintf(buf, bufsize, "{%4d-%02d-%02d %02d:%02d:%02d.%06d, ...}", + pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday, + pTime->tm_hour, pTime->tm_min, pTime->tm_sec, tvp->tv_usec); + return n; + } +); + +/* Convert a Windows FILETIME to a Unix timeval + A FILETIME is the number of 100-nanosecond intervals since January 1, 1601. + A time_t is the number of 1-second intervals since January 1, 1970. */ + +void Filetime2Timeval(const FILETIME *pFT, struct timeval *ptv) { + ULARGE_INTEGER ull; + ull.LowPart = pFT->dwLowDateTime; + ull.HighPart = pFT->dwHighDateTime; + ptv->tv_sec = (long)(ull.QuadPart / 10000000ULL - 11644473600ULL); + ptv->tv_usec = (int32_t)((ull.QuadPart % 10000000ULL)/10); +} + +void Timeval2Filetime(const struct timeval *ptv, FILETIME *pFT) { + ULARGE_INTEGER ull; + struct timeval now; + if (ptv->tv_usec == UTIME_NOW) { + gettimeofday(&now, NULL); /* Get the current time into a struct timeval */ + DEBUG_CODE({ + char buf[100]; + Timeval2String(buf, sizeof(buf), &now); + DEBUG_PRINTF(("// UTIME_NOW -> %s\n", buf)); + }); + ptv = &now; + } + ull.QuadPart = ptv->tv_sec + 11644473600ULL; + ull.QuadPart *= 1000000UL; + ull.QuadPart += ptv->tv_usec; + ull.QuadPart *= 10UL; + pFT->dwLowDateTime = ull.LowPart; + pFT->dwHighDateTime = ull.HighPart; +} + +/* Low level subroutine used by all the other routines below. */ +int hutimes(HANDLE hFile, const struct timeval tvp[2]) { + FILETIME ftLastAccess; /* last access time */ + FILETIME ftLastWrite; /* last write time */ + FILETIME *pftLastAccess = &ftLastAccess; + FILETIME *pftLastWrite = &ftLastWrite; + int iErr; + + if (tvp[0].tv_usec != UTIME_OMIT) { + Timeval2Filetime(tvp+0, pftLastAccess); + } else { + pftLastAccess = NULL; /* Do not set this value */ + } + if (tvp[1].tv_usec != UTIME_OMIT) { + Timeval2Filetime(tvp+1, pftLastWrite); + } else { + pftLastWrite = NULL; /* Do not set this value */ + } + iErr = !SetFileTime(hFile, NULL, pftLastAccess, pftLastWrite); + if (iErr) { + errno = Win32ErrorToErrno(); + return -1; + } + return 0; +} + +/* Same as 'utimes', but does not follow symbolic links. */ +int lutimesW(const WCHAR *path, const struct timeval tvp[2]) { + DWORD dwAttr; + DWORD dwFlagsAndAttributes; + int iErr; + HANDLE hLink; + + DEBUG_CODE({ + char buf[100]; + char szUtf8[UTF8_PATH_MAX]; + Timeval2String(buf, sizeof(buf), tvp+1); + DEBUG_WSTR2UTF8(path, szUtf8, sizeof(szUtf8)); + DEBUG_ENTER(("lutimes(\"%s\", %s);\n", szUtf8, buf)); + }); + + dwAttr = GetFileAttributesW(path); + if (dwAttr == INVALID_FILE_ATTRIBUTES) { + errno = ENOENT; + RETURN_INT_COMMENT(-1, ("File does not exist\n")); + } + + dwFlagsAndAttributes = FILE_FLAG_OPEN_REPARSE_POINT; + if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS; + hLink = CreateFileW(path, /* lpFileName, */ + FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess, */ + FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode, */ + NULL, /* lpSecurityAttributes, */ + OPEN_EXISTING, /* dwCreationDisposition, */ + dwFlagsAndAttributes, /* dwFlagsAndAttributes, */ + NULL /* hTemplateFile */ + ); + XDEBUG_PRINTF(("CreateFile() = 0x%p\n", hLink)); + if (hLink == INVALID_HANDLE_VALUE) { + errno = Win32ErrorToErrno(); + RETURN_INT_COMMENT(-1, ("Cannot open the pathname\n")); + } + + iErr = hutimes(hLink, tvp); + CloseHandle(hLink); + RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0)); +} + +int lutimesA(const char *path, const struct timeval tvp[2]) { + WCHAR wszPath[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszPath, /* lpWideCharStr, */ + COUNTOF(wszPath) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_ENTER(("lutimesA(\"%s\", %p);\n", path, tvp)); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + return lutimesW(wszPath, tvp); +} + +int lutimesU(const char *path, const struct timeval tvp[2]) { + WCHAR wszPath[PATH_MAX]; + int n; + + /* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */ + n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */ + path, /* lpMultiByteStr, */ + wszPath, /* lpWideCharStr, */ + COUNTOF(wszPath) /* cchWideChar, */ + ); + if (!n) { + errno = Win32ErrorToErrno(); + DEBUG_ENTER(("lutimesU(\"%s\", %p);\n", path, tvp)); + RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno))); + } + return lutimesW(wszPath, tvp); +} + +/* Same as 'utimes', but takes an open file descriptor instead of a name. */ +int futimes(int fd, const struct timeval tvp[2]) { + return hutimes((HANDLE)_get_osfhandle(fd), tvp); +} + +/* Change the file access time to tvp[0] and its modification time to tvp[1]. */ +int utimes(const char *file, const struct timeval tvp[2]) { + char buf[UTF8_PATH_MAX]; + int iErr; + + DEBUG_CODE({ + char buf[100]; + Timeval2String(buf, sizeof(buf), tvp+1); + DEBUG_ENTER(("utimes(\"%s\", %s);\n", file, buf)); + }); + + iErr = ResolveLinksU(file, buf, sizeof(buf)); + if (iErr) RETURN_INT_COMMENT(iErr, ("Cannot resolve the link\n")); + + iErr = lutimesU(buf, tvp); + RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0)); +} + +#endif /* defined(_WIN32) */ + diff --git a/deps/MsvcLibX/src/xfreopen.c b/deps/MsvcLibX/src/xfreopen.c new file mode 100644 index 0000000000000000000000000000000000000000..80311bbac6d1e1900785bb2fde3fc570e3808fbd --- /dev/null +++ b/deps/MsvcLibX/src/xfreopen.c @@ -0,0 +1,47 @@ +/*****************************************************************************\ +* * +* Filename xfreopen.c * +* * +* Description: WIN32 port of GNU CoreUtils library's xfreopen() * +* * +* Notes: The GNU CoreUtils library extends the freopen function. * +* msvclibx: Use the standard freopen, or _setmode. * +* * +* History: * +* 2014-03-03 JFL Created this module. * +* * +\*****************************************************************************/ + +#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */ + +#include +#include +#include +#include +#include "msvcXfreopen.h" + +FILE *xfreopen(const char *filename, const char *mode, FILE *stream) { + int iMode = 0; + if (filename) return freopen(filename, mode, stream); + if (strstr(mode, "r+")) { + iMode = _O_RDWR; + } else if (strstr(mode, "w+")) { + iMode = _O_WRONLY | _O_CREAT | _O_TRUNC; + } else if (strstr(mode, "a+")) { + iMode = _O_RDWR | _O_CREAT | _O_APPEND; + } else if (strchr(mode, 'r')) { + iMode = _O_RDONLY; + } else if (strchr(mode, 'w')) { + iMode = _O_WRONLY | _O_CREAT; + } else if (strchr(mode, 'a')) { + iMode = _O_WRONLY | _O_CREAT | _O_APPEND; + } + if (strchr(mode, 'b')) { + iMode = _O_BINARY; + } else if (strchr(mode, 't')) { + iMode = _O_TEXT; + } + _setmode(_fileno(stream), iMode); + return stream; +} + diff --git a/deps/iconv/relocatable.c b/deps/iconv/relocatable.c index 79906a399c7af9a1e078c4a3e53bd52d0efe8537..5676eb703faac0e2b9511586df3f0f772c0fce6e 100644 --- a/deps/iconv/relocatable.c +++ b/deps/iconv/relocatable.c @@ -360,7 +360,7 @@ find_shared_library_fullname () ungetc (c, fp); shared_library_fullname = NULL; size = 0; - len = getline (&shared_library_fullname, &size, fp); + len = getline(&shared_library_fullname, &size, fp); if (len >= 0) { /* Success: filled shared_library_fullname. */ diff --git a/deps/pthread/config.h b/deps/pthread/config.h index 7331e0775f094fe45add4ba7363c36ec936ad51c..057ecfa04a44dc1dc40d79c3da88e6222228964d 100644 --- a/deps/pthread/config.h +++ b/deps/pthread/config.h @@ -8,6 +8,7 @@ *********************************************************************/ /* We're building the pthreads-win32 library */ +#undef PTW32_BUILD #define PTW32_BUILD /* Do we know about the C type sigset_t? */ diff --git a/deps/pthread/pthread.h b/deps/pthread/pthread.h index e08bf22abcdfc003505e1a3055c84b0d8fd5cd58..87673398d029fd7804f40746308288720a490ba6 100644 --- a/deps/pthread/pthread.h +++ b/deps/pthread/pthread.h @@ -228,6 +228,8 @@ typedef unsigned long ULONG_PTR; #include "config.h" #endif /* HAVE_PTW32_CONFIG_H */ +#include "msvcTime.h" + #if !defined(NEED_FTIME) #include #else /* NEED_FTIME */ diff --git a/deps/pthread/sched.h b/deps/pthread/sched.h index 8c1096d887a0ddb35bb5adea0e557075f0a95bf7..d9bcc2d27f02080434365e0619cc5e54f7fe8b78 100644 --- a/deps/pthread/sched.h +++ b/deps/pthread/sched.h @@ -100,18 +100,19 @@ #endif #endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */ -#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) -# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX -/* For pid_t */ -# include -/* Required by Unix 98 */ -# include -# else - typedef int pid_t; -# endif -#else - typedef int pid_t; -#endif +// #if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN) +// # if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX +// /* For pid_t */ +// # include +// /* Required by Unix 98 */ +// # include +// # else +// typedef int pid_t; +// # endif +// #else +// typedef int pid_t; +// #endif +#include /* Thread scheduling policies */ diff --git a/deps/pthread/semaphore.h b/deps/pthread/semaphore.h index ecc29fc33d289c6c1caff0e57dbd33b321ada563..9714365b613badd1371a1731c0d421f43f633b24 100644 --- a/deps/pthread/semaphore.h +++ b/deps/pthread/semaphore.h @@ -99,6 +99,8 @@ #endif #endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */ +#include "sys/msvcTypes.h" + #define _POSIX_SEMAPHORES #if defined(__cplusplus) diff --git a/deps/wepoll/CMakeLists.txt b/deps/wepoll/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a81fd782bbc4b05a1158273a7fcc6701bc4d980d --- /dev/null +++ b/deps/wepoll/CMakeLists.txt @@ -0,0 +1,9 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_WINDOWS) + INCLUDE_DIRECTORIES(inc) + INCLUDE_DIRECTORIES(inc/sys) + AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(wepoll ${SRC}) +ENDIF () diff --git a/deps/wepoll/inc/wepoll.h b/deps/wepoll/inc/wepoll.h new file mode 100644 index 0000000000000000000000000000000000000000..afe2e14a6d17696548d91dd4c1e0fbd633314347 --- /dev/null +++ b/deps/wepoll/inc/wepoll.h @@ -0,0 +1,111 @@ +/* + * wepoll - epoll for Windows + * https://github.com/piscisaureus/wepoll + * + * Copyright 2012-2020, Bert Belder + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WEPOLL_H_ +#define WEPOLL_H_ + +#define WEPOLL_EXPORT + +#include + +enum EPOLL_EVENTS { + EPOLLIN = (int) (1U << 0), + EPOLLPRI = (int) (1U << 1), + EPOLLOUT = (int) (1U << 2), + EPOLLERR = (int) (1U << 3), + EPOLLHUP = (int) (1U << 4), + EPOLLRDNORM = (int) (1U << 6), + EPOLLRDBAND = (int) (1U << 7), + EPOLLWRNORM = (int) (1U << 8), + EPOLLWRBAND = (int) (1U << 9), + EPOLLMSG = (int) (1U << 10), /* Never reported. */ + EPOLLRDHUP = (int) (1U << 13), + EPOLLONESHOT = (int) (1U << 31) +}; + +#define EPOLLIN (1U << 0) +#define EPOLLPRI (1U << 1) +#define EPOLLOUT (1U << 2) +#define EPOLLERR (1U << 3) +#define EPOLLHUP (1U << 4) +#define EPOLLRDNORM (1U << 6) +#define EPOLLRDBAND (1U << 7) +#define EPOLLWRNORM (1U << 8) +#define EPOLLWRBAND (1U << 9) +#define EPOLLMSG (1U << 10) +#define EPOLLRDHUP (1U << 13) +#define EPOLLONESHOT (1U << 31) + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_MOD 2 +#define EPOLL_CTL_DEL 3 + +typedef void* HANDLE; +//typedef uintptr_t SOCKET; + +typedef union epoll_data { + void* ptr; + int fd; + uint32_t u32; + uint64_t u64; + SOCKET sock; /* Windows specific */ + HANDLE hnd; /* Windows specific */ +} epoll_data_t; + +struct epoll_event { + uint32_t events; /* Epoll events and flags */ + epoll_data_t data; /* User data variable */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +WEPOLL_EXPORT HANDLE epoll_create(int size); +WEPOLL_EXPORT HANDLE epoll_create1(int flags); + +WEPOLL_EXPORT int epoll_close(SOCKET ephnd); + +WEPOLL_EXPORT int epoll_ctl(SOCKET ephnd, + int op, + SOCKET sock, + struct epoll_event* event); + +WEPOLL_EXPORT int epoll_wait(SOCKET ephnd, + struct epoll_event* events, + int maxevents, + int timeout); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* WEPOLL_H_ */ diff --git a/deps/wepoll/src/wepoll.c b/deps/wepoll/src/wepoll.c new file mode 100644 index 0000000000000000000000000000000000000000..efe68624e2ef30fa5bb15124f6f877d1ba162d17 --- /dev/null +++ b/deps/wepoll/src/wepoll.c @@ -0,0 +1,2258 @@ +/* + * wepoll - epoll for Windows + * https://github.com/piscisaureus/wepoll + * + * Copyright 2012-2020, Bert Belder + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define WEPOLL_EXPORT + +#include + +enum EPOLL_EVENTS { + EPOLLIN = (int) (1U << 0), + EPOLLPRI = (int) (1U << 1), + EPOLLOUT = (int) (1U << 2), + EPOLLERR = (int) (1U << 3), + EPOLLHUP = (int) (1U << 4), + EPOLLRDNORM = (int) (1U << 6), + EPOLLRDBAND = (int) (1U << 7), + EPOLLWRNORM = (int) (1U << 8), + EPOLLWRBAND = (int) (1U << 9), + EPOLLMSG = (int) (1U << 10), /* Never reported. */ + EPOLLRDHUP = (int) (1U << 13), + EPOLLONESHOT = (int) (1U << 31) +}; + +#define EPOLLIN (1U << 0) +#define EPOLLPRI (1U << 1) +#define EPOLLOUT (1U << 2) +#define EPOLLERR (1U << 3) +#define EPOLLHUP (1U << 4) +#define EPOLLRDNORM (1U << 6) +#define EPOLLRDBAND (1U << 7) +#define EPOLLWRNORM (1U << 8) +#define EPOLLWRBAND (1U << 9) +#define EPOLLMSG (1U << 10) +#define EPOLLRDHUP (1U << 13) +#define EPOLLONESHOT (1U << 31) + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_MOD 2 +#define EPOLL_CTL_DEL 3 + +typedef void* HANDLE; +typedef uintptr_t SOCKET; + +typedef union epoll_data { + void* ptr; + int fd; + uint32_t u32; + uint64_t u64; + SOCKET sock; /* Windows specific */ + HANDLE hnd; /* Windows specific */ +} epoll_data_t; + +struct epoll_event { + uint32_t events; /* Epoll events and flags */ + epoll_data_t data; /* User data variable */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +WEPOLL_EXPORT HANDLE epoll_create(int size); +WEPOLL_EXPORT HANDLE epoll_create1(int flags); + +WEPOLL_EXPORT int epoll_close(SOCKET ephnd); + +WEPOLL_EXPORT int epoll_ctl(SOCKET ephnd, + int op, + SOCKET sock, + struct epoll_event* event); + +WEPOLL_EXPORT int epoll_wait(SOCKET ephnd, + struct epoll_event* events, + int maxevents, + int timeout); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include + +#include + +#define WEPOLL_INTERNAL static +#define WEPOLL_INTERNAL_VAR static + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif + +#define _WIN32_WINNT 0x0600 + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifndef __GNUC__ +#pragma warning(push, 1) +#endif + +#include +#include +#include + +#ifndef __GNUC__ +#pragma warning(pop) +#endif + +WEPOLL_INTERNAL int nt_global_init(void); + +typedef LONG NTSTATUS; +typedef NTSTATUS* PNTSTATUS; + +#ifndef NT_SUCCESS +#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) +#endif + +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) +#endif + +#ifndef STATUS_PENDING +#define STATUS_PENDING ((NTSTATUS) 0x00000103L) +#endif + +#ifndef STATUS_CANCELLED +#define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L) +#endif + +#ifndef STATUS_NOT_FOUND +#define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L) +#endif + +typedef struct _IO_STATUS_BLOCK { + NTSTATUS Status; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef VOID(NTAPI* PIO_APC_ROUTINE)(PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +#define RTL_CONSTANT_STRING(s) \ + { sizeof(s) - sizeof((s)[0]), sizeof(s), s } + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + +#define RTL_CONSTANT_OBJECT_ATTRIBUTES(ObjectName, Attributes) \ + { sizeof(OBJECT_ATTRIBUTES), NULL, ObjectName, Attributes, NULL, NULL } + +#ifndef FILE_OPEN +#define FILE_OPEN 0x00000001UL +#endif + +#define KEYEDEVENT_WAIT 0x00000001UL +#define KEYEDEVENT_WAKE 0x00000002UL +#define KEYEDEVENT_ALL_ACCESS \ + (STANDARD_RIGHTS_REQUIRED | KEYEDEVENT_WAIT | KEYEDEVENT_WAKE) + +#define NT_NTDLL_IMPORT_LIST(X) \ + X(NTSTATUS, \ + NTAPI, \ + NtCancelIoFileEx, \ + (HANDLE FileHandle, \ + PIO_STATUS_BLOCK IoRequestToCancel, \ + PIO_STATUS_BLOCK IoStatusBlock)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtCreateFile, \ + (PHANDLE FileHandle, \ + ACCESS_MASK DesiredAccess, \ + POBJECT_ATTRIBUTES ObjectAttributes, \ + PIO_STATUS_BLOCK IoStatusBlock, \ + PLARGE_INTEGER AllocationSize, \ + ULONG FileAttributes, \ + ULONG ShareAccess, \ + ULONG CreateDisposition, \ + ULONG CreateOptions, \ + PVOID EaBuffer, \ + ULONG EaLength)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtCreateKeyedEvent, \ + (PHANDLE KeyedEventHandle, \ + ACCESS_MASK DesiredAccess, \ + POBJECT_ATTRIBUTES ObjectAttributes, \ + ULONG Flags)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtDeviceIoControlFile, \ + (HANDLE FileHandle, \ + HANDLE Event, \ + PIO_APC_ROUTINE ApcRoutine, \ + PVOID ApcContext, \ + PIO_STATUS_BLOCK IoStatusBlock, \ + ULONG IoControlCode, \ + PVOID InputBuffer, \ + ULONG InputBufferLength, \ + PVOID OutputBuffer, \ + ULONG OutputBufferLength)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtReleaseKeyedEvent, \ + (HANDLE KeyedEventHandle, \ + PVOID KeyValue, \ + BOOLEAN Alertable, \ + PLARGE_INTEGER Timeout)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtWaitForKeyedEvent, \ + (HANDLE KeyedEventHandle, \ + PVOID KeyValue, \ + BOOLEAN Alertable, \ + PLARGE_INTEGER Timeout)) \ + \ + X(ULONG, WINAPI, RtlNtStatusToDosError, (NTSTATUS Status)) + +#define X(return_type, attributes, name, parameters) \ + WEPOLL_INTERNAL_VAR return_type(attributes* name) parameters; +NT_NTDLL_IMPORT_LIST(X) +#undef X + +#define AFD_POLL_RECEIVE 0x0001 +#define AFD_POLL_RECEIVE_EXPEDITED 0x0002 +#define AFD_POLL_SEND 0x0004 +#define AFD_POLL_DISCONNECT 0x0008 +#define AFD_POLL_ABORT 0x0010 +#define AFD_POLL_LOCAL_CLOSE 0x0020 +#define AFD_POLL_ACCEPT 0x0080 +#define AFD_POLL_CONNECT_FAIL 0x0100 + +typedef struct _AFD_POLL_HANDLE_INFO { + HANDLE Handle; + ULONG Events; + NTSTATUS Status; +} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; + +typedef struct _AFD_POLL_INFO { + LARGE_INTEGER Timeout; + ULONG NumberOfHandles; + ULONG Exclusive; + AFD_POLL_HANDLE_INFO Handles[1]; +} AFD_POLL_INFO, *PAFD_POLL_INFO; + +WEPOLL_INTERNAL int afd_create_helper_handle(HANDLE iocp_handle, + HANDLE* afd_helper_handle_out); + +WEPOLL_INTERNAL int afd_poll(HANDLE afd_helper_handle, + AFD_POLL_INFO* poll_info, + IO_STATUS_BLOCK* io_status_block); +WEPOLL_INTERNAL int afd_cancel_poll(HANDLE afd_helper_handle, + IO_STATUS_BLOCK* io_status_block); + +#define return_map_error(value) \ + do { \ + err_map_win_error(); \ + return (value); \ + } while (0) + +#define return_set_error(value, error) \ + do { \ + err_set_win_error(error); \ + return (value); \ + } while (0) + +WEPOLL_INTERNAL void err_map_win_error(void); +WEPOLL_INTERNAL void err_set_win_error(DWORD error); +WEPOLL_INTERNAL int err_check_handle(HANDLE handle); + +#define IOCTL_AFD_POLL 0x00012024 + +static UNICODE_STRING afd__helper_name = + RTL_CONSTANT_STRING(L"\\Device\\Afd\\Wepoll"); + +static OBJECT_ATTRIBUTES afd__helper_attributes = + RTL_CONSTANT_OBJECT_ATTRIBUTES(&afd__helper_name, 0); + +int afd_create_helper_handle(HANDLE iocp_handle, + HANDLE* afd_helper_handle_out) { + HANDLE afd_helper_handle; + IO_STATUS_BLOCK iosb; + NTSTATUS status; + + /* By opening \Device\Afd without specifying any extended attributes, we'll + * get a handle that lets us talk to the AFD driver, but that doesn't have an + * associated endpoint (so it's not a socket). */ + status = NtCreateFile(&afd_helper_handle, + SYNCHRONIZE, + &afd__helper_attributes, + &iosb, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + if (status != STATUS_SUCCESS) + return_set_error(-1, RtlNtStatusToDosError(status)); + + if (CreateIoCompletionPort(afd_helper_handle, iocp_handle, 0, 0) == NULL) + goto error; + + if (!SetFileCompletionNotificationModes(afd_helper_handle, + FILE_SKIP_SET_EVENT_ON_HANDLE)) + goto error; + + *afd_helper_handle_out = afd_helper_handle; + return 0; + +error: + CloseHandle(afd_helper_handle); + return_map_error(-1); +} + +int afd_poll(HANDLE afd_helper_handle, + AFD_POLL_INFO* poll_info, + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS status; + + /* Blocking operation is not supported. */ + assert(io_status_block != NULL); + + io_status_block->Status = STATUS_PENDING; + status = NtDeviceIoControlFile(afd_helper_handle, + NULL, + NULL, + io_status_block, + io_status_block, + IOCTL_AFD_POLL, + poll_info, + sizeof *poll_info, + poll_info, + sizeof *poll_info); + + if (status == STATUS_SUCCESS) + return 0; + else if (status == STATUS_PENDING) + return_set_error(-1, ERROR_IO_PENDING); + else + return_set_error(-1, RtlNtStatusToDosError(status)); +} + +int afd_cancel_poll(HANDLE afd_helper_handle, + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS cancel_status; + IO_STATUS_BLOCK cancel_iosb; + + /* If the poll operation has already completed or has been cancelled earlier, + * there's nothing left for us to do. */ + if (io_status_block->Status != STATUS_PENDING) + return 0; + + cancel_status = + NtCancelIoFileEx(afd_helper_handle, io_status_block, &cancel_iosb); + + /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed + * just before calling NtCancelIoFileEx(). This is not an error. */ + if (cancel_status == STATUS_SUCCESS || cancel_status == STATUS_NOT_FOUND) + return 0; + else + return_set_error(-1, RtlNtStatusToDosError(cancel_status)); +} + +WEPOLL_INTERNAL int epoll_global_init(void); + +WEPOLL_INTERNAL int init(void); + +typedef struct port_state port_state_t; +typedef struct queue queue_t; +typedef struct sock_state sock_state_t; +typedef struct ts_tree_node ts_tree_node_t; + +WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_handle_out); +WEPOLL_INTERNAL int port_close(port_state_t* port_state); +WEPOLL_INTERNAL int port_delete(port_state_t* port_state); + +WEPOLL_INTERNAL int port_wait(port_state_t* port_state, + struct epoll_event* events, + int maxevents, + int timeout); + +WEPOLL_INTERNAL int port_ctl(port_state_t* port_state, + int op, + SOCKET sock, + struct epoll_event* ev); + +WEPOLL_INTERNAL int port_register_socket(port_state_t* port_state, + sock_state_t* sock_state, + SOCKET socket); +WEPOLL_INTERNAL void port_unregister_socket(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL sock_state_t* port_find_socket(port_state_t* port_state, + SOCKET socket); + +WEPOLL_INTERNAL void port_request_socket_update(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL void port_cancel_socket_update(port_state_t* port_state, + sock_state_t* sock_state); + +WEPOLL_INTERNAL void port_add_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL void port_remove_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state); + +WEPOLL_INTERNAL HANDLE port_get_iocp_handle(port_state_t* port_state); +WEPOLL_INTERNAL queue_t* port_get_poll_group_queue(port_state_t* port_state); + +WEPOLL_INTERNAL port_state_t* port_state_from_handle_tree_node( + ts_tree_node_t* tree_node); +WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( + port_state_t* port_state); + +/* The reflock is a special kind of lock that normally prevents a chunk of + * memory from being freed, but does allow the chunk of memory to eventually be + * released in a coordinated fashion. + * + * Under normal operation, threads increase and decrease the reference count, + * which are wait-free operations. + * + * Exactly once during the reflock's lifecycle, a thread holding a reference to + * the lock may "destroy" the lock; this operation blocks until all other + * threads holding a reference to the lock have dereferenced it. After + * "destroy" returns, the calling thread may assume that no other threads have + * a reference to the lock. + * + * Attemmpting to lock or destroy a lock after reflock_unref_and_destroy() has + * been called is invalid and results in undefined behavior. Therefore the user + * should use another lock to guarantee that this can't happen. + */ + +typedef struct reflock { + volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ +} reflock_t; + +WEPOLL_INTERNAL int reflock_global_init(void); + +WEPOLL_INTERNAL void reflock_init(reflock_t* reflock); +WEPOLL_INTERNAL void reflock_ref(reflock_t* reflock); +WEPOLL_INTERNAL void reflock_unref(reflock_t* reflock); +WEPOLL_INTERNAL void reflock_unref_and_destroy(reflock_t* reflock); + +#include + +/* N.b.: the tree functions do not set errno or LastError when they fail. Each + * of the API functions has at most one failure mode. It is up to the caller to + * set an appropriate error code when necessary. */ + +typedef struct tree tree_t; +typedef struct tree_node tree_node_t; + +typedef struct tree { + tree_node_t* root; +} tree_t; + +typedef struct tree_node { + tree_node_t* left; + tree_node_t* right; + tree_node_t* parent; + uintptr_t key; + bool red; +} tree_node_t; + +WEPOLL_INTERNAL void tree_init(tree_t* tree); +WEPOLL_INTERNAL void tree_node_init(tree_node_t* node); + +WEPOLL_INTERNAL int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key); +WEPOLL_INTERNAL void tree_del(tree_t* tree, tree_node_t* node); + +WEPOLL_INTERNAL tree_node_t* tree_find(const tree_t* tree, uintptr_t key); +WEPOLL_INTERNAL tree_node_t* tree_root(const tree_t* tree); + +typedef struct ts_tree { + tree_t tree; + SRWLOCK lock; +} ts_tree_t; + +typedef struct ts_tree_node { + tree_node_t tree_node; + reflock_t reflock; +} ts_tree_node_t; + +WEPOLL_INTERNAL void ts_tree_init(ts_tree_t* rtl); +WEPOLL_INTERNAL void ts_tree_node_init(ts_tree_node_t* node); + +WEPOLL_INTERNAL int ts_tree_add(ts_tree_t* ts_tree, + ts_tree_node_t* node, + uintptr_t key); + +WEPOLL_INTERNAL ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, + uintptr_t key); +WEPOLL_INTERNAL ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, + uintptr_t key); + +WEPOLL_INTERNAL void ts_tree_node_unref(ts_tree_node_t* node); +WEPOLL_INTERNAL void ts_tree_node_unref_and_destroy(ts_tree_node_t* node); + +static ts_tree_t epoll__handle_tree; + +int epoll_global_init(void) { + ts_tree_init(&epoll__handle_tree); + return 0; +} + +static HANDLE epoll__create(void) { + port_state_t* port_state; + HANDLE ephnd; + ts_tree_node_t* tree_node; + + if (init() < 0) + return NULL; + + port_state = port_new(&ephnd); + if (port_state == NULL) + return NULL; + + tree_node = port_state_to_handle_tree_node(port_state); + if (ts_tree_add(&epoll__handle_tree, tree_node, (uintptr_t) ephnd) < 0) { + /* This should never happen. */ + port_delete(port_state); + return_set_error(NULL, ERROR_ALREADY_EXISTS); + } + + return ephnd; +} + +HANDLE epoll_create(int size) { + if (size <= 0) + return_set_error(NULL, ERROR_INVALID_PARAMETER); + + return epoll__create(); +} + +HANDLE epoll_create1(int flags) { + if (flags != 0) + return_set_error(NULL, ERROR_INVALID_PARAMETER); + + return epoll__create(); +} + +int epoll_close(SOCKET ephnd) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + + if (init() < 0) + return -1; + + tree_node = ts_tree_del_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } + + port_state = port_state_from_handle_tree_node(tree_node); + port_close(port_state); + + ts_tree_node_unref_and_destroy(tree_node); + + return port_delete(port_state); + +err: + err_check_handle((HANDLE)ephnd); + return -1; +} + +int epoll_ctl(SOCKET ephnd, int op, SOCKET sock, struct epoll_event* ev) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + int r; + + if (init() < 0) + return -1; + + tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } + + port_state = port_state_from_handle_tree_node(tree_node); + r = port_ctl(port_state, op, sock, ev); + + ts_tree_node_unref(tree_node); + + if (r < 0) + goto err; + + return 0; + +err: + /* On Linux, in the case of epoll_ctl(), EBADF takes priority over other + * errors. Wepoll mimics this behavior. */ + err_check_handle((HANDLE) ephnd); + err_check_handle((HANDLE) sock); + return -1; +} + +int epoll_wait(SOCKET ephnd, + struct epoll_event* events, + int maxevents, + int timeout) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + int num_events; + + if (maxevents <= 0) + return_set_error(-1, ERROR_INVALID_PARAMETER); + + if (init() < 0) + return -1; + + tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } + + port_state = port_state_from_handle_tree_node(tree_node); + num_events = port_wait(port_state, events, maxevents, timeout); + + ts_tree_node_unref(tree_node); + + if (num_events < 0) + goto err; + + return num_events; + +err: + err_check_handle((HANDLE) ephnd); + return -1; +} + +#include + +#define ERR__ERRNO_MAPPINGS(X) \ + X(ERROR_ACCESS_DENIED, EACCES) \ + X(ERROR_ALREADY_EXISTS, EEXIST) \ + X(ERROR_BAD_COMMAND, EACCES) \ + X(ERROR_BAD_EXE_FORMAT, ENOEXEC) \ + X(ERROR_BAD_LENGTH, EACCES) \ + X(ERROR_BAD_NETPATH, ENOENT) \ + X(ERROR_BAD_NET_NAME, ENOENT) \ + X(ERROR_BAD_NET_RESP, ENETDOWN) \ + X(ERROR_BAD_PATHNAME, ENOENT) \ + X(ERROR_BROKEN_PIPE, EPIPE) \ + X(ERROR_CANNOT_MAKE, EACCES) \ + X(ERROR_COMMITMENT_LIMIT, ENOMEM) \ + X(ERROR_CONNECTION_ABORTED, ECONNABORTED) \ + X(ERROR_CONNECTION_ACTIVE, EISCONN) \ + X(ERROR_CONNECTION_REFUSED, ECONNREFUSED) \ + X(ERROR_CRC, EACCES) \ + X(ERROR_DIR_NOT_EMPTY, ENOTEMPTY) \ + X(ERROR_DISK_FULL, ENOSPC) \ + X(ERROR_DUP_NAME, EADDRINUSE) \ + X(ERROR_FILENAME_EXCED_RANGE, ENOENT) \ + X(ERROR_FILE_NOT_FOUND, ENOENT) \ + X(ERROR_GEN_FAILURE, EACCES) \ + X(ERROR_GRACEFUL_DISCONNECT, EPIPE) \ + X(ERROR_HOST_DOWN, EHOSTUNREACH) \ + X(ERROR_HOST_UNREACHABLE, EHOSTUNREACH) \ + X(ERROR_INSUFFICIENT_BUFFER, EFAULT) \ + X(ERROR_INVALID_ADDRESS, EADDRNOTAVAIL) \ + X(ERROR_INVALID_FUNCTION, EINVAL) \ + X(ERROR_INVALID_HANDLE, EBADF) \ + X(ERROR_INVALID_NETNAME, EADDRNOTAVAIL) \ + X(ERROR_INVALID_PARAMETER, EINVAL) \ + X(ERROR_INVALID_USER_BUFFER, EMSGSIZE) \ + X(ERROR_IO_PENDING, EINPROGRESS) \ + X(ERROR_LOCK_VIOLATION, EACCES) \ + X(ERROR_MORE_DATA, EMSGSIZE) \ + X(ERROR_NETNAME_DELETED, ECONNABORTED) \ + X(ERROR_NETWORK_ACCESS_DENIED, EACCES) \ + X(ERROR_NETWORK_BUSY, ENETDOWN) \ + X(ERROR_NETWORK_UNREACHABLE, ENETUNREACH) \ + X(ERROR_NOACCESS, EFAULT) \ + X(ERROR_NONPAGED_SYSTEM_RESOURCES, ENOMEM) \ + X(ERROR_NOT_ENOUGH_MEMORY, ENOMEM) \ + X(ERROR_NOT_ENOUGH_QUOTA, ENOMEM) \ + X(ERROR_NOT_FOUND, ENOENT) \ + X(ERROR_NOT_LOCKED, EACCES) \ + X(ERROR_NOT_READY, EACCES) \ + X(ERROR_NOT_SAME_DEVICE, EXDEV) \ + X(ERROR_NOT_SUPPORTED, ENOTSUP) \ + X(ERROR_NO_MORE_FILES, ENOENT) \ + X(ERROR_NO_SYSTEM_RESOURCES, ENOMEM) \ + X(ERROR_OPERATION_ABORTED, EINTR) \ + X(ERROR_OUT_OF_PAPER, EACCES) \ + X(ERROR_PAGED_SYSTEM_RESOURCES, ENOMEM) \ + X(ERROR_PAGEFILE_QUOTA, ENOMEM) \ + X(ERROR_PATH_NOT_FOUND, ENOENT) \ + X(ERROR_PIPE_NOT_CONNECTED, EPIPE) \ + X(ERROR_PORT_UNREACHABLE, ECONNRESET) \ + X(ERROR_PROTOCOL_UNREACHABLE, ENETUNREACH) \ + X(ERROR_REM_NOT_LIST, ECONNREFUSED) \ + X(ERROR_REQUEST_ABORTED, EINTR) \ + X(ERROR_REQ_NOT_ACCEP, EWOULDBLOCK) \ + X(ERROR_SECTOR_NOT_FOUND, EACCES) \ + X(ERROR_SEM_TIMEOUT, ETIMEDOUT) \ + X(ERROR_SHARING_VIOLATION, EACCES) \ + X(ERROR_TOO_MANY_NAMES, ENOMEM) \ + X(ERROR_TOO_MANY_OPEN_FILES, EMFILE) \ + X(ERROR_UNEXP_NET_ERR, ECONNABORTED) \ + X(ERROR_WAIT_NO_CHILDREN, ECHILD) \ + X(ERROR_WORKING_SET_QUOTA, ENOMEM) \ + X(ERROR_WRITE_PROTECT, EACCES) \ + X(ERROR_WRONG_DISK, EACCES) \ + X(WSAEACCES, EACCES) \ + X(WSAEADDRINUSE, EADDRINUSE) \ + X(WSAEADDRNOTAVAIL, EADDRNOTAVAIL) \ + X(WSAEAFNOSUPPORT, EAFNOSUPPORT) \ + X(WSAECONNABORTED, ECONNABORTED) \ + X(WSAECONNREFUSED, ECONNREFUSED) \ + X(WSAECONNRESET, ECONNRESET) \ + X(WSAEDISCON, EPIPE) \ + X(WSAEFAULT, EFAULT) \ + X(WSAEHOSTDOWN, EHOSTUNREACH) \ + X(WSAEHOSTUNREACH, EHOSTUNREACH) \ + X(WSAEINPROGRESS, EBUSY) \ + X(WSAEINTR, EINTR) \ + X(WSAEINVAL, EINVAL) \ + X(WSAEISCONN, EISCONN) \ + X(WSAEMSGSIZE, EMSGSIZE) \ + X(WSAENETDOWN, ENETDOWN) \ + X(WSAENETRESET, EHOSTUNREACH) \ + X(WSAENETUNREACH, ENETUNREACH) \ + X(WSAENOBUFS, ENOMEM) \ + X(WSAENOTCONN, ENOTCONN) \ + X(WSAENOTSOCK, ENOTSOCK) \ + X(WSAEOPNOTSUPP, EOPNOTSUPP) \ + X(WSAEPROCLIM, ENOMEM) \ + X(WSAESHUTDOWN, EPIPE) \ + X(WSAETIMEDOUT, ETIMEDOUT) \ + X(WSAEWOULDBLOCK, EWOULDBLOCK) \ + X(WSANOTINITIALISED, ENETDOWN) \ + X(WSASYSNOTREADY, ENETDOWN) \ + X(WSAVERNOTSUPPORTED, ENOSYS) + +static errno_t err__map_win_error_to_errno(DWORD error) { + switch (error) { +#define X(error_sym, errno_sym) \ + case error_sym: \ + return errno_sym; + ERR__ERRNO_MAPPINGS(X) +#undef X + } + return EINVAL; +} + +void err_map_win_error(void) { + errno = err__map_win_error_to_errno(GetLastError()); +} + +void err_set_win_error(DWORD error) { + SetLastError(error); + errno = err__map_win_error_to_errno(error); +} + +int err_check_handle(HANDLE handle) { + DWORD flags; + + /* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check + * for this condition explicitly. */ + if (handle == INVALID_HANDLE_VALUE) + return_set_error(-1, ERROR_INVALID_HANDLE); + + if (!GetHandleInformation(handle, &flags)) + return_map_error(-1); + + return 0; +} + +#include + +#define array_count(a) (sizeof(a) / (sizeof((a)[0]))) + +#define container_of(ptr, type, member) \ + ((type*) ((uintptr_t) (ptr) - offsetof(type, member))) + +#define unused_var(v) ((void) (v)) + +/* Polyfill `inline` for older versions of msvc (up to Visual Studio 2013) */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define inline __inline +#endif + +WEPOLL_INTERNAL int ws_global_init(void); +WEPOLL_INTERNAL SOCKET ws_get_base_socket(SOCKET socket); + +static bool init__done = false; +static INIT_ONCE init__once = INIT_ONCE_STATIC_INIT; + +static BOOL CALLBACK init__once_callback(INIT_ONCE* once, + void* parameter, + void** context) { + unused_var(once); + unused_var(parameter); + unused_var(context); + + /* N.b. that initialization order matters here. */ + if (ws_global_init() < 0 || nt_global_init() < 0 || + reflock_global_init() < 0 || epoll_global_init() < 0) + return FALSE; + + init__done = true; + return TRUE; +} + +int init(void) { + if (!init__done && + !InitOnceExecuteOnce(&init__once, init__once_callback, NULL, NULL)) + /* `InitOnceExecuteOnce()` itself is infallible, and it doesn't set any + * error code when the once-callback returns FALSE. We return -1 here to + * indicate that global initialization failed; the failing init function is + * resposible for setting `errno` and calling `SetLastError()`. */ + return -1; + + return 0; +} + +/* Set up a workaround for the following problem: + * FARPROC addr = GetProcAddress(...); + * MY_FUNC func = (MY_FUNC) addr; <-- GCC 8 warning/error. + * MY_FUNC func = (MY_FUNC) (void*) addr; <-- MSVC warning/error. + * To compile cleanly with either compiler, do casts with this "bridge" type: + * MY_FUNC func = (MY_FUNC) (nt__fn_ptr_cast_t) addr; */ +#ifdef __GNUC__ +typedef void* nt__fn_ptr_cast_t; +#else +typedef FARPROC nt__fn_ptr_cast_t; +#endif + +#define X(return_type, attributes, name, parameters) \ + WEPOLL_INTERNAL return_type(attributes* name) parameters = NULL; +NT_NTDLL_IMPORT_LIST(X) +#undef X + +int nt_global_init(void) { + HMODULE ntdll; + FARPROC fn_ptr; + + ntdll = GetModuleHandleW(L"ntdll.dll"); + if (ntdll == NULL) + return -1; + +#define X(return_type, attributes, name, parameters) \ + fn_ptr = GetProcAddress(ntdll, #name); \ + if (fn_ptr == NULL) \ + return -1; \ + name = (return_type(attributes*) parameters)(nt__fn_ptr_cast_t) fn_ptr; + NT_NTDLL_IMPORT_LIST(X) +#undef X + + return 0; +} + +#include + +typedef struct poll_group poll_group_t; + +typedef struct queue_node queue_node_t; + +WEPOLL_INTERNAL poll_group_t* poll_group_acquire(port_state_t* port); +WEPOLL_INTERNAL void poll_group_release(poll_group_t* poll_group); + +WEPOLL_INTERNAL void poll_group_delete(poll_group_t* poll_group); + +WEPOLL_INTERNAL poll_group_t* poll_group_from_queue_node( + queue_node_t* queue_node); +WEPOLL_INTERNAL HANDLE + poll_group_get_afd_helper_handle(poll_group_t* poll_group); + +typedef struct queue_node { + queue_node_t* prev; + queue_node_t* next; +} queue_node_t; + +typedef struct queue { + queue_node_t head; +} queue_t; + +WEPOLL_INTERNAL void queue_init(queue_t* queue); +WEPOLL_INTERNAL void queue_node_init(queue_node_t* node); + +WEPOLL_INTERNAL queue_node_t* queue_first(const queue_t* queue); +WEPOLL_INTERNAL queue_node_t* queue_last(const queue_t* queue); + +WEPOLL_INTERNAL void queue_prepend(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_append(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_move_to_start(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_move_to_end(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_remove(queue_node_t* node); + +WEPOLL_INTERNAL bool queue_is_empty(const queue_t* queue); +WEPOLL_INTERNAL bool queue_is_enqueued(const queue_node_t* node); + +static const size_t POLL_GROUP__MAX_GROUP_SIZE = 32; + +typedef struct poll_group { + port_state_t* port_state; + queue_node_t queue_node; + HANDLE afd_helper_handle; + size_t group_size; +} poll_group_t; + +static poll_group_t* poll_group__new(port_state_t* port_state) { + HANDLE iocp_handle = port_get_iocp_handle(port_state); + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + + poll_group_t* poll_group = malloc(sizeof *poll_group); + if (poll_group == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + + memset(poll_group, 0, sizeof *poll_group); + + queue_node_init(&poll_group->queue_node); + poll_group->port_state = port_state; + + if (afd_create_helper_handle(iocp_handle, &poll_group->afd_helper_handle) < + 0) { + free(poll_group); + return NULL; + } + + queue_append(poll_group_queue, &poll_group->queue_node); + + return poll_group; +} + +void poll_group_delete(poll_group_t* poll_group) { + assert(poll_group->group_size == 0); + CloseHandle(poll_group->afd_helper_handle); + queue_remove(&poll_group->queue_node); + free(poll_group); +} + +poll_group_t* poll_group_from_queue_node(queue_node_t* queue_node) { + return container_of(queue_node, poll_group_t, queue_node); +} + +HANDLE poll_group_get_afd_helper_handle(poll_group_t* poll_group) { + return poll_group->afd_helper_handle; +} + +poll_group_t* poll_group_acquire(port_state_t* port_state) { + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + poll_group_t* poll_group = + !queue_is_empty(poll_group_queue) + ? container_of( + queue_last(poll_group_queue), poll_group_t, queue_node) + : NULL; + + if (poll_group == NULL || + poll_group->group_size >= POLL_GROUP__MAX_GROUP_SIZE) + poll_group = poll_group__new(port_state); + if (poll_group == NULL) + return NULL; + + if (++poll_group->group_size == POLL_GROUP__MAX_GROUP_SIZE) + queue_move_to_start(poll_group_queue, &poll_group->queue_node); + + return poll_group; +} + +void poll_group_release(poll_group_t* poll_group) { + port_state_t* port_state = poll_group->port_state; + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + + poll_group->group_size--; + assert(poll_group->group_size < POLL_GROUP__MAX_GROUP_SIZE); + + queue_move_to_end(poll_group_queue, &poll_group->queue_node); + + /* Poll groups are currently only freed when the epoll port is closed. */ +} + +WEPOLL_INTERNAL sock_state_t* sock_new(port_state_t* port_state, + SOCKET socket); +WEPOLL_INTERNAL void sock_delete(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL void sock_force_delete(port_state_t* port_state, + sock_state_t* sock_state); + +WEPOLL_INTERNAL int sock_set_event(port_state_t* port_state, + sock_state_t* sock_state, + const struct epoll_event* ev); + +WEPOLL_INTERNAL int sock_update(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL int sock_feed_event(port_state_t* port_state, + IO_STATUS_BLOCK* io_status_block, + struct epoll_event* ev); + +WEPOLL_INTERNAL sock_state_t* sock_state_from_queue_node( + queue_node_t* queue_node); +WEPOLL_INTERNAL queue_node_t* sock_state_to_queue_node( + sock_state_t* sock_state); +WEPOLL_INTERNAL sock_state_t* sock_state_from_tree_node( + tree_node_t* tree_node); +WEPOLL_INTERNAL tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state); + +#define PORT__MAX_ON_STACK_COMPLETIONS 256 + +typedef struct port_state { + HANDLE iocp_handle; + tree_t sock_tree; + queue_t sock_update_queue; + queue_t sock_deleted_queue; + queue_t poll_group_queue; + ts_tree_node_t handle_tree_node; + CRITICAL_SECTION lock; + size_t active_poll_count; +} port_state_t; + +static port_state_t* port__alloc(void) { + port_state_t* port_state = malloc(sizeof *port_state); + if (port_state == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + + return port_state; +} + +static void port__free(port_state_t* port) { + assert(port != NULL); + free(port); +} + +static HANDLE port__create_iocp(void) { + HANDLE iocp_handle = + CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (iocp_handle == NULL) + return_map_error(NULL); + + return iocp_handle; +} + +port_state_t* port_new(HANDLE* iocp_handle_out) { + port_state_t* port_state; + HANDLE iocp_handle; + + port_state = port__alloc(); + if (port_state == NULL) + goto err1; + + iocp_handle = port__create_iocp(); + if (iocp_handle == NULL) + goto err2; + + memset(port_state, 0, sizeof *port_state); + + port_state->iocp_handle = iocp_handle; + tree_init(&port_state->sock_tree); + queue_init(&port_state->sock_update_queue); + queue_init(&port_state->sock_deleted_queue); + queue_init(&port_state->poll_group_queue); + ts_tree_node_init(&port_state->handle_tree_node); + InitializeCriticalSection(&port_state->lock); + + *iocp_handle_out = iocp_handle; + return port_state; + +err2: + port__free(port_state); +err1: + return NULL; +} + +static int port__close_iocp(port_state_t* port_state) { + HANDLE iocp_handle = port_state->iocp_handle; + port_state->iocp_handle = NULL; + + if (!CloseHandle(iocp_handle)) + return_map_error(-1); + + return 0; +} + +int port_close(port_state_t* port_state) { + int result; + + EnterCriticalSection(&port_state->lock); + result = port__close_iocp(port_state); + LeaveCriticalSection(&port_state->lock); + + return result; +} + +int port_delete(port_state_t* port_state) { + tree_node_t* tree_node; + queue_node_t* queue_node; + + /* At this point the IOCP port should have been closed. */ + assert(port_state->iocp_handle == NULL); + + while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) { + sock_state_t* sock_state = sock_state_from_tree_node(tree_node); + sock_force_delete(port_state, sock_state); + } + + while ((queue_node = queue_first(&port_state->sock_deleted_queue)) != NULL) { + sock_state_t* sock_state = sock_state_from_queue_node(queue_node); + sock_force_delete(port_state, sock_state); + } + + while ((queue_node = queue_first(&port_state->poll_group_queue)) != NULL) { + poll_group_t* poll_group = poll_group_from_queue_node(queue_node); + poll_group_delete(poll_group); + } + + assert(queue_is_empty(&port_state->sock_update_queue)); + + DeleteCriticalSection(&port_state->lock); + + port__free(port_state); + + return 0; +} + +static int port__update_events(port_state_t* port_state) { + queue_t* sock_update_queue = &port_state->sock_update_queue; + + /* Walk the queue, submitting new poll requests for every socket that needs + * it. */ + while (!queue_is_empty(sock_update_queue)) { + queue_node_t* queue_node = queue_first(sock_update_queue); + sock_state_t* sock_state = sock_state_from_queue_node(queue_node); + + if (sock_update(port_state, sock_state) < 0) + return -1; + + /* sock_update() removes the socket from the update queue. */ + } + + return 0; +} + +static void port__update_events_if_polling(port_state_t* port_state) { + if (port_state->active_poll_count > 0) + port__update_events(port_state); +} + +static int port__feed_events(port_state_t* port_state, + struct epoll_event* epoll_events, + OVERLAPPED_ENTRY* iocp_events, + DWORD iocp_event_count) { + int epoll_event_count = 0; + DWORD i; + + for (i = 0; i < iocp_event_count; i++) { + IO_STATUS_BLOCK* io_status_block = + (IO_STATUS_BLOCK*) iocp_events[i].lpOverlapped; + struct epoll_event* ev = &epoll_events[epoll_event_count]; + + epoll_event_count += sock_feed_event(port_state, io_status_block, ev); + } + + return epoll_event_count; +} + +static int port__poll(port_state_t* port_state, + struct epoll_event* epoll_events, + OVERLAPPED_ENTRY* iocp_events, + DWORD maxevents, + DWORD timeout) { + DWORD completion_count; + + if (port__update_events(port_state) < 0) + return -1; + + port_state->active_poll_count++; + + LeaveCriticalSection(&port_state->lock); + + BOOL r = GetQueuedCompletionStatusEx(port_state->iocp_handle, + iocp_events, + maxevents, + &completion_count, + timeout, + FALSE); + + EnterCriticalSection(&port_state->lock); + + port_state->active_poll_count--; + + if (!r) + return_map_error(-1); + + return port__feed_events( + port_state, epoll_events, iocp_events, completion_count); +} + +int port_wait(port_state_t* port_state, + struct epoll_event* events, + int maxevents, + int timeout) { + OVERLAPPED_ENTRY stack_iocp_events[PORT__MAX_ON_STACK_COMPLETIONS]; + OVERLAPPED_ENTRY* iocp_events; + uint64_t due = 0; + DWORD gqcs_timeout; + int result; + + /* Check whether `maxevents` is in range. */ + if (maxevents <= 0) + return_set_error(-1, ERROR_INVALID_PARAMETER); + + /* Decide whether the IOCP completion list can live on the stack, or allocate + * memory for it on the heap. */ + if ((size_t) maxevents <= array_count(stack_iocp_events)) { + iocp_events = stack_iocp_events; + } else if ((iocp_events = + malloc((size_t) maxevents * sizeof *iocp_events)) == NULL) { + iocp_events = stack_iocp_events; + maxevents = array_count(stack_iocp_events); + } + + /* Compute the timeout for GetQueuedCompletionStatus, and the wait end + * time, if the user specified a timeout other than zero or infinite. */ + if (timeout > 0) { + due = GetTickCount64() + (uint64_t) timeout; + gqcs_timeout = (DWORD) timeout; + } else if (timeout == 0) { + gqcs_timeout = 0; + } else { + gqcs_timeout = INFINITE; + } + + EnterCriticalSection(&port_state->lock); + + /* Dequeue completion packets until either at least one interesting event + * has been discovered, or the timeout is reached. */ + for (;;) { + uint64_t now; + + result = port__poll( + port_state, events, iocp_events, (DWORD) maxevents, gqcs_timeout); + if (result < 0 || result > 0) + break; /* Result, error, or time-out. */ + + if (timeout < 0) + continue; /* When timeout is negative, never time out. */ + + /* Update time. */ + now = GetTickCount64(); + + /* Do not allow the due time to be in the past. */ + if (now >= due) { + SetLastError(WAIT_TIMEOUT); + break; + } + + /* Recompute time-out argument for GetQueuedCompletionStatus. */ + gqcs_timeout = (DWORD)(due - now); + } + + port__update_events_if_polling(port_state); + + LeaveCriticalSection(&port_state->lock); + + if (iocp_events != stack_iocp_events) + free(iocp_events); + + if (result >= 0) + return result; + else if (GetLastError() == WAIT_TIMEOUT) + return 0; + else + return -1; +} + +static int port__ctl_add(port_state_t* port_state, + SOCKET sock, + struct epoll_event* ev) { + sock_state_t* sock_state = sock_new(port_state, sock); + if (sock_state == NULL) + return -1; + + if (sock_set_event(port_state, sock_state, ev) < 0) { + sock_delete(port_state, sock_state); + return -1; + } + + port__update_events_if_polling(port_state); + + return 0; +} + +static int port__ctl_mod(port_state_t* port_state, + SOCKET sock, + struct epoll_event* ev) { + sock_state_t* sock_state = port_find_socket(port_state, sock); + if (sock_state == NULL) + return -1; + + if (sock_set_event(port_state, sock_state, ev) < 0) + return -1; + + port__update_events_if_polling(port_state); + + return 0; +} + +static int port__ctl_del(port_state_t* port_state, SOCKET sock) { + sock_state_t* sock_state = port_find_socket(port_state, sock); + if (sock_state == NULL) + return -1; + + sock_delete(port_state, sock_state); + + return 0; +} + +static int port__ctl_op(port_state_t* port_state, + int op, + SOCKET sock, + struct epoll_event* ev) { + switch (op) { + case EPOLL_CTL_ADD: + return port__ctl_add(port_state, sock, ev); + case EPOLL_CTL_MOD: + return port__ctl_mod(port_state, sock, ev); + case EPOLL_CTL_DEL: + return port__ctl_del(port_state, sock); + default: + return_set_error(-1, ERROR_INVALID_PARAMETER); + } +} + +int port_ctl(port_state_t* port_state, + int op, + SOCKET sock, + struct epoll_event* ev) { + int result; + + EnterCriticalSection(&port_state->lock); + result = port__ctl_op(port_state, op, sock, ev); + LeaveCriticalSection(&port_state->lock); + + return result; +} + +int port_register_socket(port_state_t* port_state, + sock_state_t* sock_state, + SOCKET socket) { + if (tree_add(&port_state->sock_tree, + sock_state_to_tree_node(sock_state), + socket) < 0) + return_set_error(-1, ERROR_ALREADY_EXISTS); + return 0; +} + +void port_unregister_socket(port_state_t* port_state, + sock_state_t* sock_state) { + tree_del(&port_state->sock_tree, sock_state_to_tree_node(sock_state)); +} + +sock_state_t* port_find_socket(port_state_t* port_state, SOCKET socket) { + tree_node_t* tree_node = tree_find(&port_state->sock_tree, socket); + if (tree_node == NULL) + return_set_error(NULL, ERROR_NOT_FOUND); + return sock_state_from_tree_node(tree_node); +} + +void port_request_socket_update(port_state_t* port_state, + sock_state_t* sock_state) { + if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_append(&port_state->sock_update_queue, + sock_state_to_queue_node(sock_state)); +} + +void port_cancel_socket_update(port_state_t* port_state, + sock_state_t* sock_state) { + unused_var(port_state); + if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_remove(sock_state_to_queue_node(sock_state)); +} + +void port_add_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state) { + if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_append(&port_state->sock_deleted_queue, + sock_state_to_queue_node(sock_state)); +} + +void port_remove_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state) { + unused_var(port_state); + if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_remove(sock_state_to_queue_node(sock_state)); +} + +HANDLE port_get_iocp_handle(port_state_t* port_state) { + assert(port_state->iocp_handle != NULL); + return port_state->iocp_handle; +} + +queue_t* port_get_poll_group_queue(port_state_t* port_state) { + return &port_state->poll_group_queue; +} + +port_state_t* port_state_from_handle_tree_node(ts_tree_node_t* tree_node) { + return container_of(tree_node, port_state_t, handle_tree_node); +} + +ts_tree_node_t* port_state_to_handle_tree_node(port_state_t* port_state) { + return &port_state->handle_tree_node; +} + +void queue_init(queue_t* queue) { + queue_node_init(&queue->head); +} + +void queue_node_init(queue_node_t* node) { + node->prev = node; + node->next = node; +} + +static inline void queue__detach_node(queue_node_t* node) { + node->prev->next = node->next; + node->next->prev = node->prev; +} + +queue_node_t* queue_first(const queue_t* queue) { + return !queue_is_empty(queue) ? queue->head.next : NULL; +} + +queue_node_t* queue_last(const queue_t* queue) { + return !queue_is_empty(queue) ? queue->head.prev : NULL; +} + +void queue_prepend(queue_t* queue, queue_node_t* node) { + node->next = queue->head.next; + node->prev = &queue->head; + node->next->prev = node; + queue->head.next = node; +} + +void queue_append(queue_t* queue, queue_node_t* node) { + node->next = &queue->head; + node->prev = queue->head.prev; + node->prev->next = node; + queue->head.prev = node; +} + +void queue_move_to_start(queue_t* queue, queue_node_t* node) { + queue__detach_node(node); + queue_prepend(queue, node); +} + +void queue_move_to_end(queue_t* queue, queue_node_t* node) { + queue__detach_node(node); + queue_append(queue, node); +} + +void queue_remove(queue_node_t* node) { + queue__detach_node(node); + queue_node_init(node); +} + +bool queue_is_empty(const queue_t* queue) { + return !queue_is_enqueued(&queue->head); +} + +bool queue_is_enqueued(const queue_node_t* node) { + return node->prev != node; +} + +static const long REFLOCK__REF = (long) 0x00000001; +static const long REFLOCK__REF_MASK = (long) 0x0fffffff; +static const long REFLOCK__DESTROY = (long) 0x10000000; +static const long REFLOCK__DESTROY_MASK = (long) 0xf0000000; +static const long REFLOCK__POISON = (long) 0x300dead0; + +static HANDLE reflock__keyed_event = NULL; + +int reflock_global_init(void) { + NTSTATUS status = NtCreateKeyedEvent( + &reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); + if (status != STATUS_SUCCESS) + return_set_error(-1, RtlNtStatusToDosError(status)); + return 0; +} + +void reflock_init(reflock_t* reflock) { + reflock->state = 0; +} + +static void reflock__signal_event(void* address) { + NTSTATUS status = + NtReleaseKeyedEvent(reflock__keyed_event, address, FALSE, NULL); + if (status != STATUS_SUCCESS) + abort(); +} + +static void reflock__await_event(void* address) { + NTSTATUS status = + NtWaitForKeyedEvent(reflock__keyed_event, address, FALSE, NULL); + if (status != STATUS_SUCCESS) + abort(); +} + +void reflock_ref(reflock_t* reflock) { + long state = InterlockedAdd(&reflock->state, REFLOCK__REF); + + /* Verify that the counter didn't overflow and the lock isn't destroyed. */ + assert((state & REFLOCK__DESTROY_MASK) == 0); + unused_var(state); +} + +void reflock_unref(reflock_t* reflock) { + long state = InterlockedAdd(&reflock->state, -REFLOCK__REF); + + /* Verify that the lock was referenced and not already destroyed. */ + assert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0); + + if (state == REFLOCK__DESTROY) + reflock__signal_event(reflock); +} + +void reflock_unref_and_destroy(reflock_t* reflock) { + long state = + InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF); + long ref_count = state & REFLOCK__REF_MASK; + + /* Verify that the lock was referenced and not already destroyed. */ + assert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY); + + if (ref_count != 0) + reflock__await_event(reflock); + + state = InterlockedExchange(&reflock->state, REFLOCK__POISON); + assert(state == REFLOCK__DESTROY); +} + +static const uint32_t SOCK__KNOWN_EPOLL_EVENTS = + EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDNORM | + EPOLLRDBAND | EPOLLWRNORM | EPOLLWRBAND | EPOLLMSG | EPOLLRDHUP; + +typedef enum sock__poll_status { + SOCK__POLL_IDLE = 0, + SOCK__POLL_PENDING, + SOCK__POLL_CANCELLED +} sock__poll_status_t; + +typedef struct sock_state { + IO_STATUS_BLOCK io_status_block; + AFD_POLL_INFO poll_info; + queue_node_t queue_node; + tree_node_t tree_node; + poll_group_t* poll_group; + SOCKET base_socket; + epoll_data_t user_data; + uint32_t user_events; + uint32_t pending_events; + sock__poll_status_t poll_status; + bool delete_pending; +} sock_state_t; + +static inline sock_state_t* sock__alloc(void) { + sock_state_t* sock_state = malloc(sizeof *sock_state); + if (sock_state == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + return sock_state; +} + +static inline void sock__free(sock_state_t* sock_state) { + free(sock_state); +} + +static int sock__cancel_poll(sock_state_t* sock_state) { + assert(sock_state->poll_status == SOCK__POLL_PENDING); + + if (afd_cancel_poll(poll_group_get_afd_helper_handle(sock_state->poll_group), + &sock_state->io_status_block) < 0) + return -1; + + sock_state->poll_status = SOCK__POLL_CANCELLED; + sock_state->pending_events = 0; + return 0; +} + +sock_state_t* sock_new(port_state_t* port_state, SOCKET socket) { + SOCKET base_socket; + poll_group_t* poll_group; + sock_state_t* sock_state; + + if (socket == 0 || socket == INVALID_SOCKET) + return_set_error(NULL, ERROR_INVALID_HANDLE); + + base_socket = ws_get_base_socket(socket); + if (base_socket == INVALID_SOCKET) + return NULL; + + poll_group = poll_group_acquire(port_state); + if (poll_group == NULL) + return NULL; + + sock_state = sock__alloc(); + if (sock_state == NULL) + goto err1; + + memset(sock_state, 0, sizeof *sock_state); + + sock_state->base_socket = base_socket; + sock_state->poll_group = poll_group; + + tree_node_init(&sock_state->tree_node); + queue_node_init(&sock_state->queue_node); + + if (port_register_socket(port_state, sock_state, socket) < 0) + goto err2; + + return sock_state; + +err2: + sock__free(sock_state); +err1: + poll_group_release(poll_group); + + return NULL; +} + +static int sock__delete(port_state_t* port_state, + sock_state_t* sock_state, + bool force) { + if (!sock_state->delete_pending) { + if (sock_state->poll_status == SOCK__POLL_PENDING) + sock__cancel_poll(sock_state); + + port_cancel_socket_update(port_state, sock_state); + port_unregister_socket(port_state, sock_state); + + sock_state->delete_pending = true; + } + + /* If the poll request still needs to complete, the sock_state object can't + * be free()d yet. `sock_feed_event()` or `port_close()` will take care + * of this later. */ + if (force || sock_state->poll_status == SOCK__POLL_IDLE) { + /* Free the sock_state now. */ + port_remove_deleted_socket(port_state, sock_state); + poll_group_release(sock_state->poll_group); + sock__free(sock_state); + } else { + /* Free the socket later. */ + port_add_deleted_socket(port_state, sock_state); + } + + return 0; +} + +void sock_delete(port_state_t* port_state, sock_state_t* sock_state) { + sock__delete(port_state, sock_state, false); +} + +void sock_force_delete(port_state_t* port_state, sock_state_t* sock_state) { + sock__delete(port_state, sock_state, true); +} + +int sock_set_event(port_state_t* port_state, + sock_state_t* sock_state, + const struct epoll_event* ev) { + /* EPOLLERR and EPOLLHUP are always reported, even when not requested by the + * caller. However they are disabled after a event has been reported for a + * socket for which the EPOLLONESHOT flag as set. */ + uint32_t events = ev->events | EPOLLERR | EPOLLHUP; + + sock_state->user_events = events; + sock_state->user_data = ev->data; + + if ((events & SOCK__KNOWN_EPOLL_EVENTS & ~sock_state->pending_events) != 0) + port_request_socket_update(port_state, sock_state); + + return 0; +} + +static inline DWORD sock__epoll_events_to_afd_events(uint32_t epoll_events) { + /* Always monitor for AFD_POLL_LOCAL_CLOSE, which is triggered when the + * socket is closed with closesocket() or CloseHandle(). */ + DWORD afd_events = AFD_POLL_LOCAL_CLOSE; + + if (epoll_events & (EPOLLIN | EPOLLRDNORM)) + afd_events |= AFD_POLL_RECEIVE | AFD_POLL_ACCEPT; + if (epoll_events & (EPOLLPRI | EPOLLRDBAND)) + afd_events |= AFD_POLL_RECEIVE_EXPEDITED; + if (epoll_events & (EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND)) + afd_events |= AFD_POLL_SEND; + if (epoll_events & (EPOLLIN | EPOLLRDNORM | EPOLLRDHUP)) + afd_events |= AFD_POLL_DISCONNECT; + if (epoll_events & EPOLLHUP) + afd_events |= AFD_POLL_ABORT; + if (epoll_events & EPOLLERR) + afd_events |= AFD_POLL_CONNECT_FAIL; + + return afd_events; +} + +static inline uint32_t sock__afd_events_to_epoll_events(DWORD afd_events) { + uint32_t epoll_events = 0; + + if (afd_events & (AFD_POLL_RECEIVE | AFD_POLL_ACCEPT)) + epoll_events |= EPOLLIN | EPOLLRDNORM; + if (afd_events & AFD_POLL_RECEIVE_EXPEDITED) + epoll_events |= EPOLLPRI | EPOLLRDBAND; + if (afd_events & AFD_POLL_SEND) + epoll_events |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND; + if (afd_events & AFD_POLL_DISCONNECT) + epoll_events |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; + if (afd_events & AFD_POLL_ABORT) + epoll_events |= EPOLLHUP; + if (afd_events & AFD_POLL_CONNECT_FAIL) + /* Linux reports all these events after connect() has failed. */ + epoll_events |= + EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLRDNORM | EPOLLWRNORM | EPOLLRDHUP; + + return epoll_events; +} + +int sock_update(port_state_t* port_state, sock_state_t* sock_state) { + assert(!sock_state->delete_pending); + + if ((sock_state->poll_status == SOCK__POLL_PENDING) && + (sock_state->user_events & SOCK__KNOWN_EPOLL_EVENTS & + ~sock_state->pending_events) == 0) { + /* All the events the user is interested in are already being monitored by + * the pending poll operation. It might spuriously complete because of an + * event that we're no longer interested in; when that happens we'll submit + * a new poll operation with the updated event mask. */ + + } else if (sock_state->poll_status == SOCK__POLL_PENDING) { + /* A poll operation is already pending, but it's not monitoring for all the + * events that the user is interested in. Therefore, cancel the pending + * poll operation; when we receive it's completion package, a new poll + * operation will be submitted with the correct event mask. */ + if (sock__cancel_poll(sock_state) < 0) + return -1; + + } else if (sock_state->poll_status == SOCK__POLL_CANCELLED) { + /* The poll operation has already been cancelled, we're still waiting for + * it to return. For now, there's nothing that needs to be done. */ + + } else if (sock_state->poll_status == SOCK__POLL_IDLE) { + /* No poll operation is pending; start one. */ + sock_state->poll_info.Exclusive = FALSE; + sock_state->poll_info.NumberOfHandles = 1; + sock_state->poll_info.Timeout.QuadPart = INT64_MAX; + sock_state->poll_info.Handles[0].Handle = (HANDLE) sock_state->base_socket; + sock_state->poll_info.Handles[0].Status = 0; + sock_state->poll_info.Handles[0].Events = + sock__epoll_events_to_afd_events(sock_state->user_events); + + if (afd_poll(poll_group_get_afd_helper_handle(sock_state->poll_group), + &sock_state->poll_info, + &sock_state->io_status_block) < 0) { + switch (GetLastError()) { + case ERROR_IO_PENDING: + /* Overlapped poll operation in progress; this is expected. */ + break; + case ERROR_INVALID_HANDLE: + /* Socket closed; it'll be dropped from the epoll set. */ + return sock__delete(port_state, sock_state, false); + default: + /* Other errors are propagated to the caller. */ + return_map_error(-1); + } + } + + /* The poll request was successfully submitted. */ + sock_state->poll_status = SOCK__POLL_PENDING; + sock_state->pending_events = sock_state->user_events; + + } else { + /* Unreachable. */ + assert(false); + } + + port_cancel_socket_update(port_state, sock_state); + return 0; +} + +int sock_feed_event(port_state_t* port_state, + IO_STATUS_BLOCK* io_status_block, + struct epoll_event* ev) { + sock_state_t* sock_state = + container_of(io_status_block, sock_state_t, io_status_block); + AFD_POLL_INFO* poll_info = &sock_state->poll_info; + uint32_t epoll_events = 0; + + sock_state->poll_status = SOCK__POLL_IDLE; + sock_state->pending_events = 0; + + if (sock_state->delete_pending) { + /* Socket has been deleted earlier and can now be freed. */ + return sock__delete(port_state, sock_state, false); + + } else if (io_status_block->Status == STATUS_CANCELLED) { + /* The poll request was cancelled by CancelIoEx. */ + + } else if (!NT_SUCCESS(io_status_block->Status)) { + /* The overlapped request itself failed in an unexpected way. */ + epoll_events = EPOLLERR; + + } else if (poll_info->NumberOfHandles < 1) { + /* This poll operation succeeded but didn't report any socket events. */ + + } else if (poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) { + /* The poll operation reported that the socket was closed. */ + return sock__delete(port_state, sock_state, false); + + } else { + /* Events related to our socket were reported. */ + epoll_events = + sock__afd_events_to_epoll_events(poll_info->Handles[0].Events); + } + + /* Requeue the socket so a new poll request will be submitted. */ + port_request_socket_update(port_state, sock_state); + + /* Filter out events that the user didn't ask for. */ + epoll_events &= sock_state->user_events; + + /* Return if there are no epoll events to report. */ + if (epoll_events == 0) + return 0; + + /* If the the socket has the EPOLLONESHOT flag set, unmonitor all events, + * even EPOLLERR and EPOLLHUP. But always keep looking for closed sockets. */ + if (sock_state->user_events & EPOLLONESHOT) + sock_state->user_events = 0; + + ev->data = sock_state->user_data; + ev->events = epoll_events; + return 1; +} + +sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) { + return container_of(queue_node, sock_state_t, queue_node); +} + +queue_node_t* sock_state_to_queue_node(sock_state_t* sock_state) { + return &sock_state->queue_node; +} + +sock_state_t* sock_state_from_tree_node(tree_node_t* tree_node) { + return container_of(tree_node, sock_state_t, tree_node); +} + +tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state) { + return &sock_state->tree_node; +} + +void ts_tree_init(ts_tree_t* ts_tree) { + tree_init(&ts_tree->tree); + InitializeSRWLock(&ts_tree->lock); +} + +void ts_tree_node_init(ts_tree_node_t* node) { + tree_node_init(&node->tree_node); + reflock_init(&node->reflock); +} + +int ts_tree_add(ts_tree_t* ts_tree, ts_tree_node_t* node, uintptr_t key) { + int r; + + AcquireSRWLockExclusive(&ts_tree->lock); + r = tree_add(&ts_tree->tree, &node->tree_node, key); + ReleaseSRWLockExclusive(&ts_tree->lock); + + return r; +} + +static inline ts_tree_node_t* ts_tree__find_node(ts_tree_t* ts_tree, + uintptr_t key) { + tree_node_t* tree_node = tree_find(&ts_tree->tree, key); + if (tree_node == NULL) + return NULL; + + return container_of(tree_node, ts_tree_node_t, tree_node); +} + +ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, uintptr_t key) { + ts_tree_node_t* ts_tree_node; + + AcquireSRWLockExclusive(&ts_tree->lock); + + ts_tree_node = ts_tree__find_node(ts_tree, key); + if (ts_tree_node != NULL) { + tree_del(&ts_tree->tree, &ts_tree_node->tree_node); + reflock_ref(&ts_tree_node->reflock); + } + + ReleaseSRWLockExclusive(&ts_tree->lock); + + return ts_tree_node; +} + +ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, uintptr_t key) { + ts_tree_node_t* ts_tree_node; + + AcquireSRWLockShared(&ts_tree->lock); + + ts_tree_node = ts_tree__find_node(ts_tree, key); + if (ts_tree_node != NULL) + reflock_ref(&ts_tree_node->reflock); + + ReleaseSRWLockShared(&ts_tree->lock); + + return ts_tree_node; +} + +void ts_tree_node_unref(ts_tree_node_t* node) { + reflock_unref(&node->reflock); +} + +void ts_tree_node_unref_and_destroy(ts_tree_node_t* node) { + reflock_unref_and_destroy(&node->reflock); +} + +void tree_init(tree_t* tree) { + memset(tree, 0, sizeof *tree); +} + +void tree_node_init(tree_node_t* node) { + memset(node, 0, sizeof *node); +} + +#define TREE__ROTATE(cis, trans) \ + tree_node_t* p = node; \ + tree_node_t* q = node->trans; \ + tree_node_t* parent = p->parent; \ + \ + if (parent) { \ + if (parent->left == p) \ + parent->left = q; \ + else \ + parent->right = q; \ + } else { \ + tree->root = q; \ + } \ + \ + q->parent = parent; \ + p->parent = q; \ + p->trans = q->cis; \ + if (p->trans) \ + p->trans->parent = p; \ + q->cis = p; + +static inline void tree__rotate_left(tree_t* tree, tree_node_t* node) { + TREE__ROTATE(left, right) +} + +static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) { + TREE__ROTATE(right, left) +} + +#define TREE__INSERT_OR_DESCEND(side) \ + if (parent->side) { \ + parent = parent->side; \ + } else { \ + parent->side = node; \ + break; \ + } + +#define TREE__REBALANCE_AFTER_INSERT(cis, trans) \ + tree_node_t* grandparent = parent->parent; \ + tree_node_t* uncle = grandparent->trans; \ + \ + if (uncle && uncle->red) { \ + parent->red = uncle->red = false; \ + grandparent->red = true; \ + node = grandparent; \ + } else { \ + if (node == parent->trans) { \ + tree__rotate_##cis(tree, parent); \ + node = parent; \ + parent = node->parent; \ + } \ + parent->red = false; \ + grandparent->red = true; \ + tree__rotate_##trans(tree, grandparent); \ + } + +int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { + tree_node_t* parent; + + parent = tree->root; + if (parent) { + for (;;) { + if (key < parent->key) { + TREE__INSERT_OR_DESCEND(left) + } else if (key > parent->key) { + TREE__INSERT_OR_DESCEND(right) + } else { + return -1; + } + } + } else { + tree->root = node; + } + + node->key = key; + node->left = node->right = NULL; + node->parent = parent; + node->red = true; + + for (; parent && parent->red; parent = node->parent) { + if (parent == parent->parent->left) { + TREE__REBALANCE_AFTER_INSERT(left, right) + } else { + TREE__REBALANCE_AFTER_INSERT(right, left) + } + } + tree->root->red = false; + + return 0; +} + +#define TREE__REBALANCE_AFTER_REMOVE(cis, trans) \ + tree_node_t* sibling = parent->trans; \ + \ + if (sibling->red) { \ + sibling->red = false; \ + parent->red = true; \ + tree__rotate_##cis(tree, parent); \ + sibling = parent->trans; \ + } \ + if ((sibling->left && sibling->left->red) || \ + (sibling->right && sibling->right->red)) { \ + if (!sibling->trans || !sibling->trans->red) { \ + sibling->cis->red = false; \ + sibling->red = true; \ + tree__rotate_##trans(tree, sibling); \ + sibling = parent->trans; \ + } \ + sibling->red = parent->red; \ + parent->red = sibling->trans->red = false; \ + tree__rotate_##cis(tree, parent); \ + node = tree->root; \ + break; \ + } \ + sibling->red = true; + +void tree_del(tree_t* tree, tree_node_t* node) { + tree_node_t* parent = node->parent; + tree_node_t* left = node->left; + tree_node_t* right = node->right; + tree_node_t* next; + bool red; + + if (!left) { + next = right; + } else if (!right) { + next = left; + } else { + next = right; + while (next->left) + next = next->left; + } + + if (parent) { + if (parent->left == node) + parent->left = next; + else + parent->right = next; + } else { + tree->root = next; + } + + if (left && right) { + red = next->red; + next->red = node->red; + next->left = left; + left->parent = next; + if (next != right) { + parent = next->parent; + next->parent = node->parent; + node = next->right; + parent->left = node; + next->right = right; + right->parent = next; + } else { + next->parent = parent; + parent = next; + node = next->right; + } + } else { + red = node->red; + node = next; + } + + if (node) + node->parent = parent; + if (red) + return; + if (node && node->red) { + node->red = false; + return; + } + + do { + if (node == tree->root) + break; + if (node == parent->left) { + TREE__REBALANCE_AFTER_REMOVE(left, right) + } else { + TREE__REBALANCE_AFTER_REMOVE(right, left) + } + node = parent; + parent = parent->parent; + } while (!node->red); + + if (node) + node->red = false; +} + +tree_node_t* tree_find(const tree_t* tree, uintptr_t key) { + tree_node_t* node = tree->root; + while (node) { + if (key < node->key) + node = node->left; + else if (key > node->key) + node = node->right; + else + return node; + } + return NULL; +} + +tree_node_t* tree_root(const tree_t* tree) { + return tree->root; +} + +#ifndef SIO_BSP_HANDLE_POLL +#define SIO_BSP_HANDLE_POLL 0x4800001D +#endif + +#ifndef SIO_BASE_HANDLE +#define SIO_BASE_HANDLE 0x48000022 +#endif + +int ws_global_init(void) { + int r; + WSADATA wsa_data; + + r = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (r != 0) + return_set_error(-1, (DWORD) r); + + return 0; +} + +static inline SOCKET ws__ioctl_get_bsp_socket(SOCKET socket, DWORD ioctl) { + SOCKET bsp_socket; + DWORD bytes; + + if (WSAIoctl(socket, + ioctl, + NULL, + 0, + &bsp_socket, + sizeof bsp_socket, + &bytes, + NULL, + NULL) != SOCKET_ERROR) + return bsp_socket; + else + return INVALID_SOCKET; +} + +SOCKET ws_get_base_socket(SOCKET socket) { + SOCKET base_socket; + DWORD error; + + for (;;) { + base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BASE_HANDLE); + if (base_socket != INVALID_SOCKET) + return base_socket; + + error = GetLastError(); + if (error == WSAENOTSOCK) + return_set_error(INVALID_SOCKET, error); + + /* Even though Microsoft documentation clearly states that LSPs should + * never intercept the `SIO_BASE_HANDLE` ioctl [1], Komodia based LSPs do + * so anyway, breaking it, with the apparent intention of preventing LSP + * bypass [2]. Fortunately they don't handle `SIO_BSP_HANDLE_POLL`, which + * we can use to obtain the socket associated with the next protocol chain + * entry. If this succeeds, loop around and call `SIO_BASE_HANDLE` again + * with the retrieved BSP socket to be sure that we actually got all the + * way to the base. + * [1] https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls + * [2] https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6 + */ + + base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BSP_HANDLE_POLL); + if (base_socket != INVALID_SOCKET && base_socket != socket) + socket = base_socket; + else + return_set_error(INVALID_SOCKET, error); + } +} diff --git a/deps/zlib-1.2.11/CMakeLists.txt b/deps/zlib-1.2.11/CMakeLists.txt index 686e6fcff5c2c20815c97d6b976804b3c491527b..5502070819894480a0d7a7320d0f113cc545a0ce 100644 --- a/deps/zlib-1.2.11/CMakeLists.txt +++ b/deps/zlib-1.2.11/CMakeLists.txt @@ -1,8 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_LINUX_64 OR TD_WINDOWS_64) +IF (TD_LINUX) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(z ${SRC}) -ENDIF () +ENDIF () \ No newline at end of file diff --git a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md index 952fd8f3409054396544895d04102aa34191dc99..6c6a3afb6031d095db12fc52297c205a2bafd3c3 100644 --- a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md +++ b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md @@ -157,7 +157,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ```mysql DROP TABLE [IF EXISTS] stb_name; ``` - 删除STable会自动删除通过STable创建的字表。 + 删除STable会自动删除通过STable创建的子表。 - **显示当前数据库下的所有超级表信息** @@ -206,7 +206,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic ``` 修改超级表的标签名,从超级表修改某个标签名后,该超级表下的所有子表也会自动更新该标签名。 -- **修改字表标签值** +- **修改子表标签值** ```mysql ALTER TABLE tb_name SET TAG tag_name=new_tag_value; @@ -281,6 +281,30 @@ SELECT select_expr [, select_expr ...] [LIMIT limit_val [, OFFSET offset_val]] [>> export_file] ``` +说明:针对 insert 类型的 SQL 语句,我们采用的流式解析策略,在发现后面的错误之前,前面正确的部分SQL仍会执行。下面的sql中,insert语句是无效的,但是d1001仍会被创建。 +```mysql +taos> create table meters(ts timestamp, current float, voltage int, phase float) tags(location binary(30), groupId int); +Query OK, 0 row(s) affected (0.008245s) + +taos> show stables; + name | created_time | columns | tags | tables | +============================================================================================ + meters | 2020-08-06 17:50:27.831 | 4 | 2 | 0 | +Query OK, 1 row(s) in set (0.001029s) + +taos> show tables; +Query OK, 0 row(s) in set (0.000946s) + +taos> insert into d1001 using meters tags('Beijing.Chaoyang', 2); + +DB error: invalid SQL: keyword VALUES or FILE required + +taos> show tables; + table_name | created_time | columns | stable_name | +====================================================================================================== + d1001 | 2020-08-06 17:52:02.097 | 4 | meters | +Query OK, 1 row(s) in set (0.001091s) +``` #### SELECT子句 一个选择子句可以是联合查询(UNION)和另一个查询的子查询(SUBQUERY)。 @@ -314,6 +338,7 @@ taos> SELECT * FROM meters; Query OK, 9 row(s) in set (0.002022s) ``` + 通配符支持表名前缀,以下两个SQL语句均为返回全部的列: ```mysql SELECT * FROM d1001; diff --git a/documentation20/webdocs/markdowndocs/advanced features-ch.md b/documentation20/webdocs/markdowndocs/advanced features-ch.md index 688d867affdce7b60d09b0a484107588d3c2fff2..690f2a6268a9fb4d40b2235cb768ec802ef5a118 100644 --- a/documentation20/webdocs/markdowndocs/advanced features-ch.md +++ b/documentation20/webdocs/markdowndocs/advanced features-ch.md @@ -119,7 +119,7 @@ taos_consume taos_unsubscribe ``` -这些API的文档请见 [C/C++ 数据订阅接口](connector/#C/C++-Connector), +这些API的文档请见 [C/C++ Connector](https://www.taosdata.com/cn/documentation20/connector/), 下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”), 完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/tests/examples/c/subscribe.c) 找到。 diff --git a/documentation20/webdocs/markdowndocs/cluster-ch.md b/documentation20/webdocs/markdowndocs/cluster-ch.md index 2df6d2cb0eef9af7037076619efb2080568ff9ef..afe0272387b2baea1fa0f6adb638e3abb17d0525 100644 --- a/documentation20/webdocs/markdowndocs/cluster-ch.md +++ b/documentation20/webdocs/markdowndocs/cluster-ch.md @@ -107,7 +107,7 @@ CREATE DATABASE demo replica 3; ``` 一个DB里的数据会被切片分到多个vnode group,vnode group里的vnode数目就是DB的副本数,同一个vnode group里各vnode的数据是完全一致的。为保证高可用性,vnode group里的vnode一定要分布在不同的dnode里(实际部署时,需要在不同的物理机上),只要一个vgroup里超过半数的vnode处于工作状态,这个vgroup就能正常的对外服务。 -一个dnode里可能有多个DB的数据,因此一个dnode离线时,可能会影响到多个DB。如果一个vnode group里的一半或一半以上的vnode不工作,那么该vnode group就无法对外服务,无法插入或读取数据,这样会影响到它所属的DB的一部分表的d读写操作。 +一个dnode里可能有多个DB的数据,因此一个dnode离线时,可能会影响到多个DB。如果一个vnode group里的一半或一半以上的vnode不工作,那么该vnode group就无法对外服务,无法插入或读取数据,这样会影响到它所属的DB的一部分表的读写操作。 因为vnode的引入,无法简单的给出结论:“集群中过半dnode工作,集群就应该工作”。但是对于简单的情形,很好下结论。比如副本数为3,只有三个dnode,那如果仅有一个节点不工作,整个集群还是可以正常工作的,但如果有两个节点不工作,那整个集群就无法正常工作了。 diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg index 3a03972e68d662603b4d49a7f640f6aa9e05ff92..5d33da5acc8d67092452d88844f5f2ce1cd26ceb 100644 --- a/packaging/cfg/taos.cfg +++ b/packaging/cfg/taos.cfg @@ -5,20 +5,20 @@ # # ######################################################## -# first full-qualified domain name (FQDN) for TDengine system +# first fully qualified domain name (FQDN) for TDengine system # firstEp hostname1:6030 -# second full-qualified domain name (FQDN) for TDengine system, for cluster edition only +# second fully qualified domain name (FQDN) for TDengine system, for cluster only # secondEp cluster_hostname2:6030 -# the full-qualified domain name (FQDN) of dnode +# local fully qualified domain name (FQDN) # fqdn hostname -# port for MNode connect to Client, default udp/tcp [6030-6040] +# first port number for the connection (10 continuous UDP/TCP port number are used) # serverPort 6030 -# http service port, default tcp [6020] -# httpPort 6020 +# http service port, default tcp [6041] +# httpPort 6041 # log file's directory # logDir /var/log/taos @@ -26,76 +26,73 @@ # data file's directory # dataDir /var/lib/taos -# the arbitrator's full-qualified domain name (FQDN) for TDengine system, for cluster edition only +# the arbitrator's fully qualified domain name (FQDN) for TDengine system, for cluster only # arbitrator arbitrator_hostname:6030 # number of threads per CPU core # numOfThreadsPerCore 1.0 -# the ratio of threads responsible for querying in the total thread -# ratioOfQueryThreads 0.5 - # number of management nodes in the system # numOfMnodes 3 -# if backup vnode directory when remove dnode +# enable/disable backuping vnode directory when removing dnode # vnodeBak 1 -# Whether to start load balancing +# enable/disable load balancing # balance 1 -# optional roles for dnode. 0 - any, 1 - mnode, 2 - dnode +# role for dnode. 0 - any, 1 - mnode, 2 - dnode # role 0 -# max timer control block +# max timer control blocks # maxTmrCtrl 512 -# interval of system monitor +# time interval of system monitor, seconds # monitorInterval 30 -# number of seconds allowed for a dnode to be offline, for cluster version only +# number of seconds allowed for a dnode to be offline, for cluster only # offlineThreshold 8640000 # RPC re-try timer, millisecond # rpcTimer 300 -# RPC maximum time for ack, seconds +# RPC maximum time for ack, seconds. # rpcMaxTime 600 -# interval of DNode report status to MNode, unit is Second, for cluster version only +# time interval of dnode status reporting to mnode, seconds, for cluster only # statusInterval 1 -# interval of Shell send HB to MNode, unit is Second +# time interval of heart beat from shell to dnode, seconds # shellActivityTimer 3 -# duration of to keep tableMeta kept in Cache, seconds +# time of keeping table meta data in cache, seconds # tableMetaKeepTimer 7200 -# Minimum sliding window time +# minimum sliding window time, milli-second # minSlidingTime 10 -# Time window minimum +# minimum time window, milli-second # minIntervalTime 10 -# the max allowed delayed time for launching continuous query. 20ms by default +# maximum delay before launching a stream compution, milli-second # maxStreamCompDelay 20000 -# The minimum time to wait before the first stream execution +# maximum delay before launching a stream computation for the first time, milli-second # maxFirstStreamCompDelay 10000 -# Retry wait time benchmark +# retry delay when a stream computation fails, milli-second # retryStreamCompDelay 10 -# the delayed time for launching each continuous query. 10% of the whole computing time window by default. +# the delayed time for launching a stream computation, from 0.1(default, 10% of whole computing time window) to 0.9 # streamCompDelayRatio 0.1 -# max number of vgroups per db +# max number of vgroups per db, 0 means configured automatically # maxVgroupsPerDb 0 # max number of tables per vnode # maxTablesPerVnode 1000000 -# Step size of increasing table number in vnode +# step size of increasing table number in a vnode # tableIncStepPerVnode 1000 # cache block size (Mbyte) @@ -110,22 +107,22 @@ # number of days to keep DB file # keep 3650 -# min row of records in file block +# minimum rows of records in file block # minRows 100 -# max row of records in file block +# maximum rows of records in file block # maxRows 4096 # enable/disable compression # comp 2 -# set write ahead log (WAL) level +# write ahead log (WAL) level, 0: no wal; 1: write wal, but no fysnc; 2: write wal, and call fsync # walLevel 1 -# When walLevel is set to 2, the cycle of fsync is executed +# if walLevel is set to 2, the cycle of fsync being executed, if set to 0, fsync is called right away # fsync 3000 -# number of replications, for cluster version only +# number of replications, for cluster only # replica 1 # mqtt uri @@ -143,7 +140,7 @@ # max length of an SQL # maxSQLLength 65480 -# Support the maximum number of records allowed for super table time sorting +# the maximum number of records allowed for super table time sorting # maxNumOfOrderedRes 100000 # system time zone @@ -155,31 +152,31 @@ # default system charset # charset UTF-8 -# max number of connections from client for dnode +# max number of connections allowed in dnode # maxShellConns 5000 -# max numerber of connections to one database +# max numerber of connections allowed in client # maxConnections 5000 -# Stop writing logs when the disk size of the log folder is less than this value +# stop writing logs when the disk size of the log folder is less than this value # minimalLogDirGB 0.1 -# Stop writing temporary files when the disk size of the log folder is less than this value +# stop writing temporary files when the disk size of the log folder is less than this value # minimalTmpDirGB 0.1 -# Stop writing data when the disk size of the log folder is less than this value +# stop writing data when the disk size of the log folder is less than this value # minimalDataDirGB 0.1 -# start http service +# enbale/disable http service # http 1 -# start muqq service +# enable/disable muqq service # mqtt 0 -# start system monitor module +# enable/disable system monitor # monitor 1 -# Record the SQL through restful interface +# enable/disable recording the SQL statements via restful interface # httpEnableRecordSql 0 # number of threads used to process http requests @@ -255,11 +252,12 @@ # debug flag for http server # tsdbDebugFlag 131 -# Record the SQL in taos client +# enable/disable recording the SQL in taos client # tscEnableRecordSql 0 -# if generate core file when service crash +# generate core file when service crash # enableCoreFile 1 -# The maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden -# maxBinaryDisplayWidth 30 \ No newline at end of file +# maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden +# maxBinaryDisplayWidth 30 + diff --git a/src/balance/CMakeLists.txt b/src/balance/CMakeLists.txt index 45b7c4ed57c678d28bfd5d9e2734b2e5ff724fe3..d5d9ba1d9c6193f406d9b13b0ce9c76d6c08582d 100644 --- a/src/balance/CMakeLists.txt +++ b/src/balance/CMakeLists.txt @@ -1,16 +1,13 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/sdb/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/sdb/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) ADD_LIBRARY(balance ${SRC}) -ENDIF () +ENDIF () \ No newline at end of file diff --git a/src/balance/src/balance.c b/src/balance/src/balance.c index db5dd6a520bec182c132da8132140b7cc9b08b39..53ed860aa16e7733e656c965feb75f88d0d26311 100644 --- a/src/balance/src/balance.c +++ b/src/balance/src/balance.c @@ -415,7 +415,11 @@ static int32_t balanceMonitorVgroups() { } else if (vgReplica < dbReplica) { mInfo("vgId:%d, replica:%d numOfVnodes:%d, try add one vnode", pVgroup->vgId, dbReplica, vgReplica); hasUpdatingVgroup = true; - balanceAddVnode(pVgroup, NULL, NULL); + int32_t code = balanceAddVnode(pVgroup, NULL, NULL); + if (code == TSDB_CODE_SUCCESS) { + mnodeDecVgroupRef(pVgroup); + break; + } } mnodeDecVgroupRef(pVgroup); diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 987c309add49401923899123e613d14b1ebd644c..d5cbf3cab6d408914303e3c06230930bb59f734d 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -3,15 +3,10 @@ PROJECT(TDengine) INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(jni) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) AUX_SOURCE_DIRECTORY(src SRC) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) # set the static lib name @@ -40,19 +35,18 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) 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/pthread) ADD_LIBRARY(taos_static STATIC ${SRC}) - TARGET_LINK_LIBRARIES(taos_static trpc tutil) + TARGET_LINK_LIBRARIES(taos_static trpc tutil query) # generate dynamic library (*.dll) ADD_LIBRARY(taos SHARED ${SRC}) IF (NOT TD_GODLL) SET_TARGET_PROPERTIES(taos PROPERTIES LINK_FLAGS /DEF:${TD_COMMUNITY_DIR}/src/client/src/taos.def) ENDIF () - TARGET_LINK_LIBRARIES(taos trpc tutil) + TARGET_LINK_LIBRARIES(taos trpc tutil query) -ELSEIF (TD_DARWIN_64) +ELSEIF (TD_DARWIN) SET(CMAKE_MACOSX_RPATH 1) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 72ca96891acb2ecbab27aedf47b2e97fc4a487d6..af91ac34f08658da67644d7f72209231b99eaeaf 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -53,12 +53,18 @@ typedef struct SParsedDataColInfo { bool hasVal[TSDB_MAX_COLUMNS]; } SParsedDataColInfo; +#pragma pack(push,1) +// this struct is transfered as binary, padding two bytes to avoid +// an 'uid' whose low bytes is 0xff being recoginized as NULL, +// and set 'pack' to 1 to avoid break existing code. typedef struct STidTags { + int16_t padding; int64_t uid; int32_t tid; int32_t vgId; char tag[]; } STidTags; +#pragma pack(pop) typedef struct SJoinSupporter { SSubqueryState* pState; @@ -224,6 +230,7 @@ int32_t tscAddSubqueryInfo(SSqlCmd *pCmd); void tscInitQueryInfo(SQueryInfo* pQueryInfo); void tscClearSubqueryInfo(SSqlCmd* pCmd); +void tscFreeVgroupTableInfo(SArray* pVgroupTables); int tscGetSTableVgroupInfo(SSqlObj* pSql, int32_t clauseIndex); int tscGetTableMeta(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo); diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index eee255f55ba184652141dc1faf07e8b314ba0a8a..5036983424184c799f42169e2ec1dcf39bfc109f 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -224,7 +224,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn */ tsNumOfThreadsPerCore = 0.0; - ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, jport); + ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); if (ret == 0) { jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, (char *)host, (char *)user, (char *)dbname, jport); diff --git a/src/client/src/taos.def b/src/client/src/taos.def index 39906c7486dc242513f31028c367607fa0197dc9..df84ac657e73fe2a643d8c185e62b02a1a3cf4ad 100644 --- a/src/client/src/taos.def +++ b/src/client/src/taos.def @@ -1,11 +1,19 @@ EXPORTS taos_init +taos_cleanup taos_options taos_connect taos_close +taos_stmt_init +taos_stmt_prepare +taos_stmt_bind_param +taos_stmt_add_batch +taos_stmt_execute +taos_stmt_use_result +taos_stmt_close taos_query -taos_use_result taos_fetch_row +taos_result_precision taos_free_result taos_field_count taos_num_fields @@ -14,6 +22,9 @@ taos_fetch_fields taos_select_db taos_print_row taos_stop_query +taos_fetch_block +taos_validate_sql +taos_fetch_lengths taos_get_server_info taos_get_client_info taos_errstr @@ -27,5 +38,5 @@ taos_unsubscribe taos_open_stream taos_close_stream taos_fetch_block -taos_result_precision +taos_load_table_info diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index 59d906e8fdd5fc4525b2c4b997d24142c8a76398..b05aef76eb387596700d19090406073dcdf6132b 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -54,7 +54,7 @@ void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, void (*fp)(), void* param, const return; } - strntolower(pSql->sqlstr, sqlstr, sqlLen); + strntolower(pSql->sqlstr, sqlstr, (int32_t)sqlLen); tscDebugL("%p SQL: %s", pSql, pSql->sqlstr); pSql->cmd.curSql = pSql->sqlstr; @@ -81,7 +81,7 @@ void taos_query_a(TAOS *taos, const char *sqlstr, __async_cb_func_t fp, void *pa return; } - int32_t sqlLen = strlen(sqlstr); + int32_t sqlLen = (int32_t)strlen(sqlstr); if (sqlLen > tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); terrno = TSDB_CODE_TSC_INVALID_SQL; diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c index b6b1cef08092ad3a8d9225fc1b867840eda0c457..5c708dffeeeb6877467c52cf50eedab68c1f59d3 100644 --- a/src/client/src/tscFunctionImpl.c +++ b/src/client/src/tscFunctionImpl.c @@ -169,7 +169,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI // (uid, tid) + VGID + TAGSIZE + VARSTR_HEADER_SIZE if (functionId == TSDB_FUNC_TID_TAG) { // todo use struct *type = TSDB_DATA_TYPE_BINARY; - *bytes = dataBytes + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE; + *bytes = (int16_t)(dataBytes + sizeof(int16_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE); *interBytes = *bytes; return TSDB_CODE_SUCCESS; } @@ -198,7 +198,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI if (isSuperTable) { if (functionId == TSDB_FUNC_MIN || functionId == TSDB_FUNC_MAX) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = dataBytes + DATA_SET_FLAG_SIZE; + *bytes = (int16_t)(dataBytes + DATA_SET_FLAG_SIZE); *interBytes = *bytes; return TSDB_CODE_SUCCESS; @@ -221,7 +221,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; + *bytes = (int16_t)(sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param); *interBytes = *bytes; return TSDB_CODE_SUCCESS; @@ -239,7 +239,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_LAST_ROW) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = sizeof(SLastrowInfo) + dataBytes; + *bytes = (int16_t)(sizeof(SLastrowInfo) + dataBytes); *interBytes = *bytes; return TSDB_CODE_SUCCESS; @@ -308,7 +308,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *interBytes = *bytes + sizeof(SResultInfo); } else if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = dataBytes + sizeof(SFirstLastInfo); + *bytes = (int16_t)(dataBytes + sizeof(SFirstLastInfo)); *interBytes = *bytes; } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { *type = (int16_t)dataType; @@ -317,7 +317,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI size_t size = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; // the output column may be larger than sizeof(STopBotInfo) - *interBytes = size; + *interBytes = (int32_t)size; } else if (functionId == TSDB_FUNC_LAST_ROW) { *type = (int16_t)dataType; *bytes = (int16_t)dataBytes; @@ -947,11 +947,11 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { int8_t *data = (int8_t *)pOutput; - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, (int8_t)val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { int16_t *data = (int16_t *)pOutput; - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, (int16_t)val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { int32_t *data = (int32_t *)pOutput; #if defined(_DEBUG_VIEW) @@ -959,7 +959,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, #endif if ((*data < val) ^ isMin) { - *data = val; + *data = (int32_t)val; for (int32_t i = 0; i < (pCtx)->tagInfo.numOfTagCols; ++i) { SQLFunctionCtx *__ctx = pCtx->tagInfo.pTagCtxList[i]; if (__ctx->functionId == TSDB_FUNC_TS_DUMMY) { @@ -982,7 +982,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, float *data = (float *)pOutput; double val = GET_DOUBLE_VAL(tval); - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, (float)val, notNullElems, isMin, key); } return; @@ -2041,7 +2041,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { case TSDB_DATA_TYPE_INT: { int32_t *output = (int32_t *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.i64Key; + *output = (int32_t)tvp[i]->v.i64Key; } break; } @@ -2062,21 +2062,21 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { case TSDB_DATA_TYPE_FLOAT: { float *output = (float *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.dKey; + *output = (float)tvp[i]->v.dKey; } break; } case TSDB_DATA_TYPE_SMALLINT: { int16_t *output = (int16_t *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.i64Key; + *output = (int16_t)tvp[i]->v.i64Key; } break; } case TSDB_DATA_TYPE_TINYINT: { int8_t *output = (int8_t *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.i64Key; + *output = (int8_t)tvp[i]->v.i64Key; } break; } @@ -2226,7 +2226,7 @@ static void top_function(SQLFunctionCtx *pCtx) { } notNullElems++; - do_top_function_add(pRes, pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, 0); + do_top_function_add(pRes, (int32_t)pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, 0); } if (!pCtx->hasNull) { @@ -2252,7 +2252,7 @@ static void top_function_f(SQLFunctionCtx *pCtx, int32_t index) { assert(pRes->num >= 0); SET_VAL(pCtx, 1, 1); - do_top_function_add(pRes, pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL, + do_top_function_add(pRes, (int32_t)pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL, 0); SResultInfo *pResInfo = GET_RES_INFO(pCtx); @@ -2276,7 +2276,7 @@ static void top_func_merge(SQLFunctionCtx *pCtx) { STopBotInfo *pOutput = getTopBotOutputInfo(pCtx); for (int32_t i = 0; i < pInput->num; ++i) { - do_top_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, + do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, pCtx->inputType, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } } @@ -2292,7 +2292,7 @@ static void top_func_second_merge(SQLFunctionCtx *pCtx) { // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT)? TSDB_DATA_TYPE_DOUBLE:pCtx->outputType; - do_top_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, + do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } @@ -2316,7 +2316,7 @@ static void bottom_function(SQLFunctionCtx *pCtx) { } notNullElems++; - do_bottom_function_add(pRes, pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, + do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, 0); } @@ -2341,7 +2341,7 @@ static void bottom_function_f(SQLFunctionCtx *pCtx, int32_t index) { STopBotInfo *pRes = getTopBotOutputInfo(pCtx); SET_VAL(pCtx, 1, 1); - do_bottom_function_add(pRes, pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, + do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL, 0); SResultInfo *pResInfo = GET_RES_INFO(pCtx); @@ -2365,7 +2365,7 @@ static void bottom_func_merge(SQLFunctionCtx *pCtx) { STopBotInfo *pOutput = getTopBotOutputInfo(pCtx); for (int32_t i = 0; i < pInput->num; ++i) { - do_bottom_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, + do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, pCtx->inputType, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } } @@ -2380,9 +2380,9 @@ static void bottom_func_second_merge(SQLFunctionCtx *pCtx) { // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { - int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT)? TSDB_DATA_TYPE_DOUBLE:pCtx->outputType; - do_bottom_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, - type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); + int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT) ? TSDB_DATA_TYPE_DOUBLE : pCtx->outputType; + do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, type, + &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } SET_VAL(pCtx, pInput->num, pOutput->num); @@ -2431,7 +2431,7 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx) { } SResultInfo *pResInfo = GET_RES_INFO(pCtx); - SSchema field[1] = {{pCtx->inputType, "dummyCol", 0, pCtx->inputBytes}}; + SSchema field[1] = { { (uint8_t)pCtx->inputType, "dummyCol", 0, pCtx->inputBytes } }; SColumnModel *pModel = createColumnModel(field, 1, 1000); int32_t orderIdx = 0; @@ -2544,7 +2544,7 @@ static void apercentile_function(SQLFunctionCtx *pCtx) { v = GET_INT16_VAL(data); break; case TSDB_DATA_TYPE_BIGINT: - v = GET_INT64_VAL(data); + v = (double)(GET_INT64_VAL(data)); break; case TSDB_DATA_TYPE_FLOAT: v = GET_FLOAT_VAL(data); @@ -2589,7 +2589,7 @@ static void apercentile_function_f(SQLFunctionCtx *pCtx, int32_t index) { v = GET_INT16_VAL(pData); break; case TSDB_DATA_TYPE_BIGINT: - v = GET_INT64_VAL(pData); + v = (double)(GET_INT64_VAL(pData)); break; case TSDB_DATA_TYPE_FLOAT: v = GET_FLOAT_VAL(pData); @@ -2876,7 +2876,7 @@ static void leastsquares_finalizer(SQLFunctionCtx *pCtx) { double(*param)[3] = pInfo->mat; - param[1][1] = pInfo->num; + param[1][1] = (double)pInfo->num; param[1][0] = param[0][1]; param[0][0] -= param[1][0] * (param[0][1] / param[1][1]); @@ -3028,13 +3028,13 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].i64Key = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int32_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].i64Key; // direct previous may be null + *pOutput = (int32_t)(pData[i] - pCtx->param[1].i64Key); // direct previous may be null *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3122,13 +3122,13 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].dKey = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].dKey; + *pOutput = (float)(pData[i] - pCtx->param[1].dKey); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].dKey; + *pOutput = (float)(pData[i] - pCtx->param[1].dKey); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3155,12 +3155,12 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].i64Key = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int16_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int16_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3186,13 +3186,13 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].i64Key = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int8_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int8_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3257,7 +3257,7 @@ static void diff_function_f(SQLFunctionCtx *pCtx, int32_t index) { pCtx->param[1].nType = pCtx->inputType; pCtx->param[1].i64Key = *(int32_t *)pData; } else { - *(int32_t *)pCtx->aOutputBuf = *(int32_t *)pData - pCtx->param[1].i64Key; + *(int32_t *)pCtx->aOutputBuf = *(int32_t *)pData - (int32_t)pCtx->param[1].i64Key; pCtx->param[1].i64Key = *(int32_t *)pData; *(int64_t *)pCtx->ptsOutputBuf = pCtx->ptsList[index]; } @@ -3336,10 +3336,10 @@ static void arithmetic_function_f(SQLFunctionCtx *pCtx, int32_t index) { continue; \ } \ if (inputData[i] < minOutput) { \ - minOutput = inputData[i]; \ + minOutput = (double)inputData[i]; \ } \ if (inputData[i] > maxOutput) { \ - maxOutput = inputData[i]; \ + maxOutput = (double)inputData[i]; \ } \ numOfNotNullElem++; \ } \ @@ -3384,11 +3384,11 @@ static void spread_function(SQLFunctionCtx *pCtx) { if ((pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_BIGINT) || (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP)) { if (pInfo->min > pCtx->preAggVals.statis.min) { - pInfo->min = pCtx->preAggVals.statis.min; + pInfo->min = (double)pCtx->preAggVals.statis.min; } if (pInfo->max < pCtx->preAggVals.statis.max) { - pInfo->max = pCtx->preAggVals.statis.max; + pInfo->max = (double)pCtx->preAggVals.statis.max; } } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { if (pInfo->min > GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.min))) { @@ -3457,7 +3457,7 @@ static void spread_function_f(SQLFunctionCtx *pCtx, int32_t index) { } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { val = GET_INT32_VAL(pData); } else if (pCtx->inputType == TSDB_DATA_TYPE_BIGINT || pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP) { - val = GET_INT64_VAL(pData); + val = (double)(GET_INT64_VAL(pData)); } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE) { val = GET_DOUBLE_VAL(pData); } else if (pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c index de996c478ffc78c121809d68bdcabbd4b8333b04..caaaa5bc180b840a18e5a4c0432ff643c117f45c 100644 --- a/src/client/src/tscLocal.c +++ b/src/client/src/tscLocal.c @@ -223,12 +223,12 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols, rowLen += ((TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE); - f.bytes = typeColLength + VARSTR_HEADER_SIZE; + f.bytes = (int16_t)(typeColLength + VARSTR_HEADER_SIZE); f.type = TSDB_DATA_TYPE_BINARY; tstrncpy(f.name, "Type", sizeof(f.name)); pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f); - pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, typeColLength + VARSTR_HEADER_SIZE, + pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, (int16_t)(typeColLength + VARSTR_HEADER_SIZE), typeColLength, false); rowLen += typeColLength + VARSTR_HEADER_SIZE; @@ -243,12 +243,12 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols, rowLen += sizeof(int32_t); - f.bytes = noteColLength + VARSTR_HEADER_SIZE; + f.bytes = (int16_t)(noteColLength + VARSTR_HEADER_SIZE); f.type = TSDB_DATA_TYPE_BINARY; tstrncpy(f.name, "Note", sizeof(f.name)); pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f); - pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, noteColLength + VARSTR_HEADER_SIZE, + pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, (int16_t)(noteColLength + VARSTR_HEADER_SIZE), noteColLength, false); rowLen += noteColLength + VARSTR_HEADER_SIZE; @@ -305,7 +305,7 @@ static void tscProcessCurrentDB(SSqlObj *pSql) { if (t == 0) { setVardataNull(vx, TSDB_DATA_TYPE_BINARY); } else { - STR_WITH_SIZE_TO_VARSTR(vx, db, t); + STR_WITH_SIZE_TO_VARSTR(vx, db, (VarDataLenT)t); } tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes); @@ -320,10 +320,10 @@ static void tscProcessServerVer(SSqlObj *pSql) { pExpr->resType = TSDB_DATA_TYPE_BINARY; size_t t = strlen(v); - pExpr->resBytes = t + VARSTR_HEADER_SIZE; + pExpr->resBytes = (int16_t)(t + VARSTR_HEADER_SIZE); char* vx = calloc(1, pExpr->resBytes); - STR_WITH_SIZE_TO_VARSTR(vx, v, t); + STR_WITH_SIZE_TO_VARSTR(vx, v, (VarDataLenT)t); tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes); taosTFree(vx); @@ -336,10 +336,10 @@ static void tscProcessClientVer(SSqlObj *pSql) { pExpr->resType = TSDB_DATA_TYPE_BINARY; size_t t = strlen(version); - pExpr->resBytes = t + VARSTR_HEADER_SIZE; + pExpr->resBytes = (int16_t)(t + VARSTR_HEADER_SIZE); char* v = calloc(1, pExpr->resBytes); - STR_WITH_SIZE_TO_VARSTR(v, version, t); + STR_WITH_SIZE_TO_VARSTR(v, version, (VarDataLenT)t); tscSetLocalQueryResult(pSql, v, pExpr->aliasName, pExpr->resType, pExpr->resBytes); taosTFree(v); @@ -379,10 +379,10 @@ void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnNa pQueryInfo->fieldsInfo.pFields = taosArrayInit(1, sizeof(TAOS_FIELD)); pQueryInfo->fieldsInfo.pSupportInfo = taosArrayInit(1, sizeof(SFieldSupInfo)); - TAOS_FIELD f = tscCreateField(type, columnName, valueLength); + TAOS_FIELD f = tscCreateField((int8_t)type, columnName, (int16_t)valueLength); tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f); - tscInitResObjForLocalQuery(pSql, 1, valueLength); + tscInitResObjForLocalQuery(pSql, 1, (int32_t)valueLength); TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0); SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, 0); diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index ff5fbb2699cd177ddcaf49c1da072d9d58627d39..5955515bbd58f2f5a5b1d520c1c1d258615b7997 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -133,7 +133,7 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SLocalReducer *pReducer, tOrderDesc } static SFillColInfo* createFillColInfo(SQueryInfo* pQueryInfo) { - int32_t numOfCols = tscSqlExprNumOfExprs(pQueryInfo); + int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); int32_t offset = 0; SFillColInfo* pFillCol = calloc(numOfCols, sizeof(SFillColInfo)); @@ -141,7 +141,7 @@ static SFillColInfo* createFillColInfo(SQueryInfo* pQueryInfo) { SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i); pFillCol[i].col.bytes = pExpr->resBytes; - pFillCol[i].col.type = pExpr->resType; + pFillCol[i].col.type = (int8_t)pExpr->resType; pFillCol[i].flag = pExpr->colInfo.flag; pFillCol[i].col.offset = offset; pFillCol[i].functionId = pExpr->functionId; @@ -361,7 +361,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd pQueryInfo->limit.offset = pQueryInfo->prjOffset; } - pReducer->offset = pQueryInfo->limit.offset; + pReducer->offset = (int32_t)pQueryInfo->limit.offset; pRes->pLocalReducer = pReducer; pRes->numOfGroups = 0; @@ -376,7 +376,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd if (pQueryInfo->fillType != TSDB_FILL_NONE) { SFillColInfo* pFillCol = createFillColInfo(pQueryInfo); pReducer->pFillInfo = taosInitFillInfo(pQueryInfo->order.order, revisedSTime, pQueryInfo->groupbyExpr.numOfGroupCols, - 4096, numOfCols, pQueryInfo->slidingTime, pQueryInfo->slidingTimeUnit, + 4096, (int32_t)numOfCols, pQueryInfo->slidingTime, pQueryInfo->slidingTimeUnit, tinfo.precision, pQueryInfo->fillType, pFillCol); } @@ -405,7 +405,7 @@ static int32_t tscFlushTmpBufferImpl(tExtMemBuffer *pMemoryBuf, tOrderDescriptor // sort before flush to disk, the data must be consecutively put on tFilePage. if (pDesc->orderInfo.numOfCols > 0) { - tColDataQSort(pDesc, pPage->num, 0, pPage->num - 1, pPage->data, orderType); + tColDataQSort(pDesc, (int32_t)pPage->num, 0, (int32_t)pPage->num - 1, pPage->data, orderType); } #ifdef _DEBUG_VIEW @@ -414,7 +414,7 @@ static int32_t tscFlushTmpBufferImpl(tExtMemBuffer *pMemoryBuf, tOrderDescriptor #endif // write to cache after being sorted - if (tExtMemBufferPut(pMemoryBuf, pPage->data, pPage->num) < 0) { + if (tExtMemBufferPut(pMemoryBuf, pPage->data, (int32_t)pPage->num) < 0) { tscError("failed to save data in temporary buffer"); return -1; } @@ -446,7 +446,7 @@ int32_t saveToBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tFilePa } // current buffer is overflow, flush data to extensive buffer - int32_t numOfRemainEntries = pModel->capacity - pPage->num; + int32_t numOfRemainEntries = pModel->capacity - (int32_t)pPage->num; tColModelAppend(pModel, pPage, data, 0, numOfRemainEntries, numOfRows); // current buffer is full, need to flushed to disk @@ -679,7 +679,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i); pSchema[i].bytes = pExpr->resBytes; - pSchema[i].type = pExpr->resType; + pSchema[i].type = (int8_t)pExpr->resType; rlen += pExpr->resBytes; } @@ -689,7 +689,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr capacity = nBufferSizes / rlen; } - pModel = createColumnModel(pSchema, size, capacity); + pModel = createColumnModel(pSchema, (int32_t)size, capacity); int32_t pg = DEFAULT_PAGE_SIZE; int32_t overhead = sizeof(tFilePage); @@ -740,12 +740,12 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr getResultDataInfo(p1->type, p1->bytes, functionId, 0, &type, &bytes, &inter, 0, false); } - pSchema[i].type = type; + pSchema[i].type = (uint8_t)type; pSchema[i].bytes = bytes; strcpy(pSchema[i].name, pModel->pFields[i].field.name); } - *pFinalModel = createColumnModel(pSchema, size, capacity); + *pFinalModel = createColumnModel(pSchema, (int32_t)size, capacity); taosTFree(pSchema); return TSDB_CODE_SUCCESS; @@ -780,7 +780,7 @@ int32_t loadNewDataFromDiskFor(SLocalReducer *pLocalReducer, SLocalDataSource *p pOneInterDataSrc->rowIdx = 0; pOneInterDataSrc->pageId += 1; - if (pOneInterDataSrc->pageId < + if ((uint32_t)pOneInterDataSrc->pageId < pOneInterDataSrc->pMemBuffer->fileMeta.flushoutData.pFlushoutInfo[pOneInterDataSrc->flushoutIdx].numOfPages) { tExtMemBufferLoadData(pOneInterDataSrc->pMemBuffer, &(pOneInterDataSrc->filePage), pOneInterDataSrc->flushoutIdx, pOneInterDataSrc->pageId); @@ -896,8 +896,8 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO if (pQueryInfo->limit.offset > 0) { if (pQueryInfo->limit.offset < pRes->numOfRows) { - int32_t prevSize = pFinalDataPage->num; - tColModelErase(pLocalReducer->resColModel, pFinalDataPage, prevSize, 0, pQueryInfo->limit.offset - 1); + int32_t prevSize = (int32_t)pFinalDataPage->num; + tColModelErase(pLocalReducer->resColModel, pFinalDataPage, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1); /* remove the hole in column model */ tColModelCompact(pLocalReducer->resColModel, pFinalDataPage, prevSize); @@ -974,7 +974,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO } /* all output for current group are completed */ - int32_t totalRemainRows = getFilledNumOfRes(pFillInfo, actualETime, pLocalReducer->resColModel->capacity); + int32_t totalRemainRows = (int32_t)getFilledNumOfRes(pFillInfo, actualETime, pLocalReducer->resColModel->capacity); if (totalRemainRows <= 0) { break; } @@ -1261,7 +1261,7 @@ bool doGenerateFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool no SFillInfo* pFillInfo = pLocalReducer->pFillInfo; if (pFillInfo != NULL) { - taosFillSetStartInfo(pFillInfo, pResBuf->num, pQueryInfo->window.ekey); + taosFillSetStartInfo(pFillInfo, (int32_t)pResBuf->num, pQueryInfo->window.ekey); taosFillCopyInputDataFromOneFilePage(pFillInfo, pResBuf); } @@ -1320,7 +1320,7 @@ static bool doBuildFilledResultForGroup(SSqlObj *pSql) { int64_t etime = *(int64_t *)(pFinalDataBuf->data + TSDB_KEYSIZE * (pFillInfo->numOfRows - 1)); // the first column must be the timestamp column - int32_t rows = getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); + int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); if (rows > 0) { // do fill gap doFillResult(pSql, pLocalReducer, false); } @@ -1350,7 +1350,7 @@ static bool doHandleLastRemainData(SSqlObj *pSql) { int64_t etime = (pQueryInfo->window.skey < pQueryInfo->window.ekey) ? pQueryInfo->window.ekey : pQueryInfo->window.skey; assert(pFillInfo->numOfRows == 0); - int32_t rows = getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); + int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); if (rows > 0) { // do interpo doFillResult(pSql, pLocalReducer, true); } diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index af875a28c5b631308706b632cfa716ea4b9d39c7..e97d6c32e02c60f16da34ae31697e5386ca2fd6c 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -61,7 +61,7 @@ static int32_t tscToInteger(SSQLToken *pToken, int64_t *value, char **endPtr) { if (v > INT64_MAX || v <= INT64_MIN) { errno = ERANGE; } else { - *value = v; + *value = (int64_t)v; } } @@ -426,7 +426,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[ *str += index; if (sToken.type == TK_QUESTION) { - uint32_t offset = start - pDataBlocks->pData; + uint32_t offset = (uint32_t)(start - pDataBlocks->pData); if (tscAddParamToDataBlock(pDataBlocks, pSchema->type, (uint8_t)timePrec, pSchema->bytes, offset) != NULL) { continue; } @@ -450,7 +450,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[ char delim = sToken.z[0]; int32_t cnt = 0; int32_t j = 0; - for (int32_t k = 1; k < sToken.n - 1; ++k) { + for (uint32_t k = 1; k < sToken.n - 1; ++k) { if (sToken.z[k] == delim || sToken.z[k] == '\\') { if (sToken.z[k + 1] == delim) { cnt++; @@ -504,7 +504,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[ ptr += schema[i].bytes; } - rowSize = ptr - payload; + rowSize = (int32_t)(ptr - payload); } return rowSize; @@ -846,7 +846,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) { if (TK_STRING == sToken.type) { strdequote(sToken.z); - sToken.n = strtrim(sToken.z); + sToken.n = (uint32_t)strtrim(sToken.z); } if (sToken.type == TK_RP) { @@ -972,7 +972,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) { } } - int32_t len = cend - cstart + 1; + int32_t len = (int32_t)(cend - cstart + 1); if (cstart != NULL && createTable == true) { /* move the column list to start position of the next accessed points */ memmove(sql - len, cstart, len); @@ -1188,7 +1188,7 @@ int tsParseInsertSql(SSqlObj *pSql) { if (TK_STRING == sToken.type) { strdequote(sToken.z); - sToken.n = strtrim(sToken.z); + sToken.n = (uint32_t)strtrim(sToken.z); } if (sToken.type == TK_RP) { @@ -1426,7 +1426,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) { char *tokenBuf = calloc(1, 4096); - while ((readLen = getline(&line, &n, fp)) != -1) { + while ((readLen = taosGetline(&line, &n, fp)) != -1) { if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) { line[--readLen] = 0; } @@ -1471,7 +1471,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) { pParentSql->fp = pParentSql->fetchFp; // all data has been sent to vnode, call user function - int32_t v = (pParentSql->res.code != TSDB_CODE_SUCCESS) ? pParentSql->res.code : pParentSql->res.numOfRows; + int32_t v = (pParentSql->res.code != TSDB_CODE_SUCCESS) ? pParentSql->res.code : (int32_t)pParentSql->res.numOfRows; (*pParentSql->fp)(pParentSql->param, pParentSql, v); } } diff --git a/src/client/src/tscProfile.c b/src/client/src/tscProfile.c index 363243b1d7a427fa1d1b4b0dc8a5a0273ba51396..f48e7b7691536cb8f9a5b8561e95b8a5a0f0fefc 100644 --- a/src/client/src/tscProfile.c +++ b/src/client/src/tscProfile.c @@ -96,7 +96,7 @@ void tscSaveSlowQuery(SSqlObj *pSql) { } tscDebug("%p query time:%" PRId64 " sql:%s", pSql, pSql->res.useconds, pSql->sqlstr); - int32_t sqlSize = TSDB_SLOW_QUERY_SQL_LEN + size; + int32_t sqlSize = (int32_t)(TSDB_SLOW_QUERY_SQL_LEN + size); char *sql = malloc(sqlSize); if (sql == NULL) { diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 40be0efab66565213a526114ceee656d91f2773a..1a97a9a997920d7afc3be0e40b0fdd985002c403 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -161,7 +161,7 @@ static int32_t handlePassword(SSqlCmd* pCmd, SSQLToken* pPwd) { } strdequote(pPwd->z); - pPwd->n = strtrim(pPwd->z); // trim space before and after passwords + pPwd->n = (uint32_t)strtrim(pPwd->z); // trim space before and after passwords if (pPwd->n <= 0) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); @@ -1029,12 +1029,12 @@ static char* getAccountId(SSqlObj* pSql) { return pSql->pTscObj->acctId; } static void getCurrentDBName(SSqlObj* pSql, SSQLToken* pDBToken) { pDBToken->z = pSql->pTscObj->db; - pDBToken->n = strlen(pSql->pTscObj->db); + pDBToken->n = (uint32_t)strlen(pSql->pTscObj->db); } /* length limitation, strstr cannot be applied */ static bool hasSpecifyDB(SSQLToken* pTableName) { - for (int32_t i = 0; i < pTableName->n; ++i) { + for (uint32_t i = 0; i < pTableName->n; ++i) { if (pTableName->z[i] == TS_PATH_DELIMITER[0]) { return true; } @@ -1047,7 +1047,7 @@ int32_t setObjFullName(char* fullName, const char* account, SSQLToken* pDB, SSQL int32_t totalLen = 0; if (account != NULL) { - int32_t len = strlen(account); + int32_t len = (int32_t)strlen(account); strcpy(fullName, account); fullName[len] = TS_PATH_DELIMITER[0]; totalLen += (len + 1); @@ -1231,11 +1231,11 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel const char* msg5 = "invalid function name"; SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex); - + if (pQueryInfo->colList == NULL) { pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); } - + for (int32_t i = 0; i < pSelection->nExpr; ++i) { int32_t outputIndex = tscSqlExprNumOfExprs(pQueryInfo); tSQLExprItem* pItem = &pSelection->a[i]; @@ -1362,7 +1362,7 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn ids.num = 0; } - insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, pExpr->resType, pExpr->aliasName, pExpr); + insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, (int8_t)pExpr->resType, pExpr->aliasName, pExpr); } void tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, @@ -1425,7 +1425,7 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t const char* msg0 = "invalid column name"; const char* msg1 = "tag for normal table query is not allowed"; - int32_t startPos = tscSqlExprNumOfExprs(pQueryInfo); + int32_t startPos = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); if (pItem->pNode->nSQLOptr == TK_ALL) { // project on all fields SColumnIndex index = COLUMN_INDEX_INITIALIZER; @@ -1516,7 +1516,7 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS tscColumnListInsert(pQueryInfo->colList, &index); SColumnList ids = getColumnList(1, pColIndex->tableIndex, pColIndex->columnIndex); - insertResultField(pQueryInfo, resColIdx, &ids, bytes, type, columnName, pExpr); + insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, columnName, pExpr); return TSDB_CODE_SUCCESS; } @@ -1714,7 +1714,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col if (finalResult) { int32_t numOfOutput = tscNumOfFields(pQueryInfo); - insertResultField(pQueryInfo, numOfOutput, &ids, pExpr->resBytes, pExpr->resType, pExpr->aliasName, pExpr); + insertResultField(pQueryInfo, numOfOutput, &ids, pExpr->resBytes, (int32_t)pExpr->resType, pExpr->aliasName, pExpr); } else { for (int32_t i = 0; i < ids.num; ++i) { tscColumnListInsert(pQueryInfo->colList, &(ids.ids[i])); @@ -2011,7 +2011,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col int32_t ret = getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0); assert(ret == TSDB_CODE_SUCCESS); - s.type = type; + s.type = (uint8_t)type; s.bytes = bytes; TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY); @@ -2044,7 +2044,7 @@ void getColumnName(tSQLExprItem* pItem, char* resultFieldName, int32_t nameLengt if (pItem->aliasName != NULL) { strncpy(resultFieldName, pItem->aliasName, nameLength); } else { - int32_t len = (pItem->pNode->operand.n < nameLength) ? pItem->pNode->operand.n : nameLength; + int32_t len = ((int32_t)pItem->pNode->operand.n < nameLength) ? (int32_t)pItem->pNode->operand.n : nameLength; strncpy(resultFieldName, pItem->pNode->operand.z, len); } } @@ -2410,7 +2410,7 @@ int32_t tscTansformSQLFuncForSTableQuery(SQueryInfo* pQueryInfo) { if ((functionId >= TSDB_FUNC_SUM && functionId <= TSDB_FUNC_TWA) || (functionId >= TSDB_FUNC_FIRST_DST && functionId <= TSDB_FUNC_LAST_DST) || (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) { - if (getResultDataInfo(pSrcSchema->type, pSrcSchema->bytes, functionId, pExpr->param[0].i64Key, &type, &bytes, + if (getResultDataInfo(pSrcSchema->type, pSrcSchema->bytes, functionId, (int32_t)pExpr->param[0].i64Key, &type, &bytes, &interBytes, 0, true) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -3184,7 +3184,7 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer return TSDB_CODE_TSC_INVALID_SQL; } - int32_t outputIndex = tscSqlExprNumOfExprs(pQueryInfo); + int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); tSQLExprItem item = {.pNode = pExpr, .aliasName = NULL}; @@ -3673,7 +3673,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, num = j; char* name = extractDBName(pTableMetaInfo->name, db); - SSQLToken dbToken = {.type = TK_STRING, .z = name, .n = strlen(name)}; + SSQLToken dbToken = { .type = TK_STRING, .z = name, .n = (uint32_t)strlen(name) }; for (int32_t i = 0; i < num; ++i) { if (i >= 1) { @@ -3681,7 +3681,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, } char idBuf[TSDB_TABLE_FNAME_LEN] = {0}; - int32_t xlen = strlen(segments[i]); + int32_t xlen = (int32_t)strlen(segments[i]); SSQLToken t = {.z = segments[i], .n = xlen, .type = TK_STRING}; int32_t ret = setObjFullName(idBuf, account, &dbToken, &t, &xlen); @@ -4150,10 +4150,10 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery startPos = 0; if (numOfFillVal > size) { - numOfFillVal = size; + numOfFillVal = (int32_t)size; } } else { - numOfFillVal = (pFillToken->nExpr > size) ? size : pFillToken->nExpr; + numOfFillVal = (pFillToken->nExpr > (int32_t)size) ? (int32_t)size : pFillToken->nExpr; } int32_t j = 1; @@ -4817,7 +4817,7 @@ int32_t validateLocalConfig(tDCLSQL* pOptions) { } int32_t validateColumnName(char* name) { - bool ret = isKeyWord(name, strlen(name)); + bool ret = isKeyWord(name, (int32_t)strlen(name)); if (ret) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -4831,7 +4831,7 @@ int32_t validateColumnName(char* name) { if (token.type == TK_STRING) { strdequote(token.z); - token.n = strtrim(token.z); + token.n = (uint32_t)strtrim(token.z); int32_t k = tSQLGetToken(token.z, &token.type); if (k != token.n) { @@ -4976,17 +4976,17 @@ static int32_t setKeepOption(SSqlCmd* pCmd, SCMCreateDbMsg* pMsg, SCreateDBInfo* if (pKeep != NULL) { switch (pKeep->nExpr) { case 1: - pMsg->daysToKeep = htonl(pKeep->a[0].pVar.i64Key); + pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key); break; case 2: { - pMsg->daysToKeep = htonl(pKeep->a[0].pVar.i64Key); - pMsg->daysToKeep1 = htonl(pKeep->a[1].pVar.i64Key); + pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key); + pMsg->daysToKeep1 = htonl((int32_t)pKeep->a[1].pVar.i64Key); break; } case 3: { - pMsg->daysToKeep = htonl(pKeep->a[0].pVar.i64Key); - pMsg->daysToKeep1 = htonl(pKeep->a[1].pVar.i64Key); - pMsg->daysToKeep2 = htonl(pKeep->a[2].pVar.i64Key); + pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key); + pMsg->daysToKeep1 = htonl((int32_t)pKeep->a[1].pVar.i64Key); + pMsg->daysToKeep2 = htonl((int32_t)pKeep->a[2].pVar.i64Key); break; } default: { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg); } @@ -5025,7 +5025,7 @@ static void setCreateDBOption(SCMCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) { pMsg->cacheBlockSize = htonl(pCreateDb->cacheBlockSize); pMsg->totalBlocks = htonl(pCreateDb->numOfBlocks); pMsg->daysPerFile = htonl(pCreateDb->daysPerFile); - pMsg->commitTime = htonl(pCreateDb->commitTime); + pMsg->commitTime = htonl((int32_t)pCreateDb->commitTime); pMsg->minRowsPerFileBlock = htonl(pCreateDb->minRowsPerBlock); pMsg->maxRowsPerFileBlock = htonl(pCreateDb->maxRowsPerBlock); pMsg->fsyncPeriod = htonl(pCreateDb->fsyncPeriod); @@ -5082,7 +5082,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, subClauseIndex); size_t size = taosArrayGetSize(pQueryInfo->exprList); - SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, size - 1); + SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, (int32_t)size - 1); if (pExpr->functionId != TSDB_FUNC_TAG) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex); @@ -5099,7 +5099,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau // NOTE: tag column does not add to source column list SColumnList ids = {0}; - insertResultField(pQueryInfo, size, &ids, bytes, type, name, pExpr); + insertResultField(pQueryInfo, (int32_t)size, &ids, bytes, (int8_t)type, name, pExpr); int32_t relIndex = index.columnIndex; @@ -5129,9 +5129,9 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) { SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, pColIndex->colIndex); SColumnIndex colIndex = {.tableIndex = 0, .columnIndex = pColIndex->colIndex}; - tscAddSpecialColumnForSelect(pQueryInfo, size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL); + tscAddSpecialColumnForSelect(pQueryInfo, (int32_t)size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL); - SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, size); + SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, (int32_t)size); doLimitOutputNormalColOfGroupby(pInfo->pSqlExpr); pInfo->visible = false; } @@ -5159,7 +5159,7 @@ static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) { SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i); if (pExpr->functionId != TSDB_FUNC_TAG_DUMMY && pExpr->functionId != TSDB_FUNC_TS_DUMMY) { SSchema* pColSchema = &pSchema[pExpr->colInfo.colIndex]; - getResultDataInfo(pColSchema->type, pColSchema->bytes, pExpr->functionId, pExpr->param[0].i64Key, &pExpr->resType, + getResultDataInfo(pColSchema->type, pColSchema->bytes, pExpr->functionId, (int32_t)pExpr->param[0].i64Key, &pExpr->resType, &pExpr->resBytes, &pExpr->interBytes, tagLength, true); } } @@ -5384,7 +5384,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo // NOTE: tag column does not add to source column list SColumnList ids = getColumnList(1, 0, pColIndex->colIndex); - insertResultField(pQueryInfo, size, &ids, bytes, type, name, pExpr); + insertResultField(pQueryInfo, (int32_t)size, &ids, bytes, (int8_t)type, name, pExpr); } else { // if this query is "group by" normal column, interval is not allowed if (pQueryInfo->intervalTime > 0) { @@ -5625,7 +5625,7 @@ int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCMCreateDbMsg* pCreate) { void tscPrintSelectClause(SSqlObj* pSql, int32_t subClauseIndex) { SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, subClauseIndex); - int32_t size = tscSqlExprNumOfExprs(pQueryInfo); + int32_t size = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); if (size == 0) { return; } @@ -6080,7 +6080,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { // in case of join query, time range is required. if (QUERY_IS_JOIN_QUERY(pQueryInfo->type)) { - int64_t timeRange = labs(pQueryInfo->window.skey - pQueryInfo->window.ekey); + int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey); if (timeRange == 0 && pQueryInfo->window.skey == 0) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6); @@ -6107,7 +6107,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { } if (pQueryInfo->intervalTime > 0) { - int64_t timeRange = labs(pQueryInfo->window.skey - pQueryInfo->window.ekey); + int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey); // number of result is not greater than 10,000,000 if ((timeRange == 0) || (timeRange / pQueryInfo->intervalTime) > MAX_RETRIEVE_ROWS_IN_INTERVAL_QUERY) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6); @@ -6163,7 +6163,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS SSqlExpr* p1 = taosArrayGetP(pExprInfo, i); if (strcmp((*pExpr)->pSchema->name, p1->aliasName) == 0) { - (*pExpr)->pSchema->type = p1->resType; + (*pExpr)->pSchema->type = (uint8_t)p1->resType; (*pExpr)->pSchema->bytes = p1->resBytes; break; } diff --git a/src/client/src/tscSchemaUtil.c b/src/client/src/tscSchemaUtil.c index 63607b7a86e0cce38c9a2f07f41b7055b538cb96..244bb8116452fac495f2d140b8b3d8b3e8d96eeb 100644 --- a/src/client/src/tscSchemaUtil.c +++ b/src/client/src/tscSchemaUtil.c @@ -208,7 +208,7 @@ char* tsGetTagsValue(STableMeta* pTableMeta) { } // todo refactor -__attribute__ ((unused))static FORCE_INLINE char* skipSegments(char* input, char delim, int32_t num) { +UNUSED_FUNC static FORCE_INLINE char* skipSegments(char* input, char delim, int32_t num) { for (int32_t i = 0; i < num; ++i) { while (*input != 0 && *input++ != delim) { }; @@ -216,7 +216,7 @@ __attribute__ ((unused))static FORCE_INLINE char* skipSegments(char* input, char return input; } -__attribute__ ((unused)) static FORCE_INLINE size_t copy(char* dst, const char* src, char delimiter) { +UNUSED_FUNC static FORCE_INLINE size_t copy(char* dst, const char* src, char delimiter) { size_t len = 0; while (*src != delimiter && *src != 0) { *dst++ = *src++; diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 0cce4195e7b780f8ba2dfe6ad715be36b5155cf7..8d86f046ef5dcb0ae55f75683430a93b2814c683 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -370,7 +370,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) { } if (rpcMsg->code != TSDB_CODE_TSC_ACTION_IN_PROGRESS) { - rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS)? pRes->numOfRows: pRes->code; + rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS) ? (int32_t)pRes->numOfRows : pRes->code; bool shouldFree = tscShouldBeFreed(pSql); (*pSql->fp)(pSql->param, pSql, rpcMsg->code); @@ -558,10 +558,10 @@ static int32_t tscEstimateQueryMsgSize(SSqlCmd *pCmd, int32_t clauseIndex) { const static int32_t MIN_QUERY_MSG_PKT_SIZE = TSDB_MAX_BYTES_PER_ROW * 5; SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex); - int32_t srcColListSize = taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo); + int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo)); size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - int32_t exprSize = sizeof(SSqlFuncMsg) * numOfExprs; + int32_t exprSize = (int32_t)(sizeof(SSqlFuncMsg) * numOfExprs); return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + exprSize + 4096; } @@ -601,7 +601,7 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char pMsg += sizeof(STableIdInfo); } else { // it is a subquery of the super table query, this EP info is acquired from vgroupInfo int32_t index = pTableMetaInfo->vgroupIndex; - int32_t numOfVgroups = taosArrayGetSize(pTableMetaInfo->pVgroupTables); + int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables); assert(index >= 0 && index < numOfVgroups); tscDebug("%p query on stable, vgIndex:%d, numOfVgroups:%d", pSql, index, numOfVgroups); @@ -612,7 +612,7 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char tscSetDnodeEpSet(pSql, &pTableIdList->vgInfo); pQueryMsg->head.vgId = htonl(pTableIdList->vgInfo.vgId); - int32_t numOfTables = taosArrayGetSize(pTableIdList->itemList); + int32_t numOfTables = (int32_t)taosArrayGetSize(pTableIdList->itemList); pQueryMsg->numOfTables = htonl(numOfTables); // set the number of tables // serialize each table id info @@ -664,7 +664,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { SQueryTableMsg *pQueryMsg = (SQueryTableMsg *)pCmd->payload; - int32_t numOfTags = taosArrayGetSize(pTableMetaInfo->tagColList); + int32_t numOfTags = (int32_t)taosArrayGetSize(pTableMetaInfo->tagColList); if (pQueryInfo->order.order == TSDB_ORDER_ASC) { pQueryMsg->window.skey = htobe64(pQueryInfo->window.skey); @@ -679,7 +679,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->fillType = htons(pQueryInfo->fillType); pQueryMsg->limit = htobe64(pQueryInfo->limit.limit); pQueryMsg->offset = htobe64(pQueryInfo->limit.offset); - pQueryMsg->numOfCols = htons(taosArrayGetSize(pQueryInfo->colList)); + pQueryMsg->numOfCols = htons((int16_t)taosArrayGetSize(pQueryInfo->colList)); pQueryMsg->intervalTime = htobe64(pQueryInfo->intervalTime); pQueryMsg->slidingTime = htobe64(pQueryInfo->slidingTime); pQueryMsg->slidingTimeUnit = pQueryInfo->slidingTimeUnit; @@ -689,7 +689,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->queryType = htonl(pQueryInfo->type); size_t numOfOutput = tscSqlExprNumOfExprs(pQueryInfo); - pQueryMsg->numOfOutput = htons(numOfOutput); + pQueryMsg->numOfOutput = htons((int16_t)numOfOutput); // set column list ids size_t numOfCols = taosArrayGetSize(pQueryInfo->colList); @@ -861,7 +861,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { } // compressed ts block - pQueryMsg->tsOffset = htonl(pMsg - pCmd->payload); + pQueryMsg->tsOffset = htonl((int32_t)(pMsg - pCmd->payload)); int32_t tsLen = 0; int32_t numOfBlocks = 0; @@ -894,14 +894,14 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->tsOrder = htonl(pQueryInfo->tsBuf->tsOrder); } - int32_t msgLen = pMsg - pCmd->payload; + int32_t msgLen = (int32_t)(pMsg - pCmd->payload); tscDebug("%p msg built success,len:%d bytes", pSql, msgLen); pCmd->payloadLen = msgLen; pSql->cmd.msgType = TSDB_MSG_TYPE_QUERY; pQueryMsg->head.contLen = htonl(msgLen); - assert(msgLen + minMsgSize() <= size); + assert(msgLen + minMsgSize() <= (int32_t)pCmd->allocSize); return TSDB_CODE_SUCCESS; } @@ -994,7 +994,7 @@ int32_t tscBuildUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) { SUserInfo *pUser = &pInfo->pDCLInfo->user; strncpy(pAlterMsg->user, pUser->user.z, pUser->user.n); - pAlterMsg->flag = pUser->type; + pAlterMsg->flag = (int8_t)pUser->type; if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) { pAlterMsg->privilege = (char)pCmd->count; @@ -1269,7 +1269,7 @@ int tscBuildCreateTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) { tscFieldInfoClear(&pQueryInfo->fieldsInfo); - msgLen = pMsg - (char*)pCreateTableMsg; + msgLen = (int32_t)(pMsg - (char*)pCreateTableMsg); pCreateTableMsg->contLen = htonl(msgLen); pCmd->payloadLen = msgLen; pCmd->msgType = TSDB_MSG_TYPE_CM_CREATE_TABLE; @@ -1322,7 +1322,7 @@ int tscBuildAlterTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) { memcpy(pMsg, pAlterInfo->tagData.data, pAlterInfo->tagData.dataLen); pMsg += pAlterInfo->tagData.dataLen; - msgLen = pMsg - (char*)pAlterTableMsg; + msgLen = (int32_t)(pMsg - (char*)pAlterTableMsg); pCmd->payloadLen = msgLen; pCmd->msgType = TSDB_MSG_TYPE_CM_ALTER_TABLE; @@ -1523,12 +1523,12 @@ int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pMsg += len; } - pCmd->payloadLen = pMsg - (char*)pInfoMsg; + pCmd->payloadLen = (int32_t)(pMsg - (char*)pInfoMsg); pCmd->msgType = TSDB_MSG_TYPE_CM_TABLE_META; taosTFree(tmpData); - assert(msgLen + minMsgSize() <= pCmd->allocSize); + assert(msgLen + minMsgSize() <= (int32_t)pCmd->allocSize); return TSDB_CODE_SUCCESS; } @@ -1620,7 +1620,7 @@ int tscBuildSTableVgroupMsg(SSqlObj *pSql, SSqlInfo *pInfo) { } pCmd->msgType = TSDB_MSG_TYPE_CM_STABLE_VGROUP; - pCmd->payloadLen = (pMsg - pCmd->payload); + pCmd->payloadLen = (int32_t)(pMsg - pCmd->payload); return TSDB_CODE_SUCCESS; } @@ -1987,8 +1987,7 @@ int tscProcessUseDbRsp(SSqlObj *pSql) { return 0; } -int tscProcessDropDbRsp(SSqlObj *pSql) { - pSql->pTscObj->db[0] = 0; +int tscProcessDropDbRsp(SSqlObj *UNUSED_PARAM(pSql)) { taosCacheEmpty(tscCacheHandle); return 0; } diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index f01f1aa384876af2534bb60a7b5c67f3dd62e40a..6c7503ea4c959d6df62c8b338be2c4248d12c6a3 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -85,7 +85,7 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con taosEncryptPass((uint8_t *)pass, strlen(pass), pObj->pass); if (db) { - int32_t len = strlen(db); + int32_t len = (int32_t)strlen(db); /* db name is too long */ if (len >= TSDB_DB_NAME_LEN) { terrno = TSDB_CODE_TSC_INVALID_DB_LENGTH; @@ -240,7 +240,7 @@ TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen) { return NULL; } - if (sqlLen > tsMaxSQLStringLen) { + if (sqlLen > (uint32_t)tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); terrno = TSDB_CODE_TSC_INVALID_SQL; return NULL; @@ -306,7 +306,7 @@ int taos_affected_rows(TAOS_RES *tres) { SSqlObj* pSql = (SSqlObj*) tres; if (pSql == NULL || pSql->signature != pSql) return 0; - return (pSql->res.numOfRows); + return (int)(pSql->res.numOfRows); } TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) { @@ -341,7 +341,7 @@ int taos_retrieve(TAOS_RES *res) { } tscProcessSql(pSql); - return pRes->numOfRows; + return (int)pRes->numOfRows; } int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) { @@ -382,7 +382,7 @@ int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) { *rows = pRes->tsrow; - return (pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows; + return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows); } TAOS_ROW taos_fetch_row(TAOS_RES *res) { @@ -731,7 +731,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) { tscDebug("%p Valid SQL: %s pObj:%p", pSql, sql, pObj); - int32_t sqlLen = strlen(sql); + int32_t sqlLen = (int32_t)strlen(sql); if (sqlLen > tsMaxSQLStringLen) { tscError("%p sql too long", pSql); pRes->code = TSDB_CODE_TSC_INVALID_SQL; @@ -804,11 +804,11 @@ static int tscParseTblNameList(SSqlObj *pSql, const char *tblNameList, int32_t t } memcpy(tblName, str, nextStr - str); - int32_t len = nextStr - str; + int32_t len = (int32_t)(nextStr - str); tblName[len] = '\0'; str = nextStr + 1; - len = strtrim(tblName); + len = (int32_t)strtrim(tblName); SSQLToken sToken = {.n = len, .type = TK_ID, .z = tblName}; tSQLGetToken(tblName, &sToken.type); @@ -874,7 +874,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { assert(pSql->fp == NULL); tscDebug("%p tableNameList: %s pObj:%p", pSql, tableNameList, pObj); - int32_t tblListLen = strlen(tableNameList); + int32_t tblListLen = (int32_t)strlen(tableNameList); if (tblListLen > MAX_TABLE_NAME_LENGTH) { tscError("%p tableNameList too long, length:%d, maximum allowed:%d", pSql, tblListLen, MAX_TABLE_NAME_LENGTH); pRes->code = TSDB_CODE_TSC_INVALID_SQL; diff --git a/src/client/src/tscStream.c b/src/client/src/tscStream.c index 6235e0aeba415627352bc3fd864eb6e35eb6086e..d0591de0114ab6b96be22140edfad5f90bb5b53b 100644 --- a/src/client/src/tscStream.c +++ b/src/client/src/tscStream.c @@ -47,14 +47,14 @@ static bool isProjectStream(SQueryInfo* pQueryInfo) { } static int64_t tscGetRetryDelayTime(int64_t slidingTime, int16_t prec) { - float retryRangeFactor = 0.3; + float retryRangeFactor = 0.3f; // change to ms if (prec == TSDB_TIME_PRECISION_MICRO) { slidingTime = slidingTime / 1000; } - int64_t retryDelta = (int64_t)tsStreamCompRetryDelay * retryRangeFactor; + int64_t retryDelta = (int64_t)(tsStreamCompRetryDelay * retryRangeFactor); retryDelta = ((rand() % retryDelta) + tsStreamCompRetryDelay) * 1000L; if (slidingTime < retryDelta) { @@ -299,7 +299,7 @@ static void tscSetRetryTimer(SSqlStream *pStream, SSqlObj *pSql, int64_t timer) pSql->cmd.command = TSDB_SQL_SELECT; // start timer for next computing - taosTmrReset(tscProcessStreamTimer, timer, pStream, tscTmr, &pStream->pTimer); + taosTmrReset(tscProcessStreamTimer, (int32_t)timer, pStream, tscTmr, &pStream->pTimer); } static int64_t getLaunchTimeDelay(const SSqlStream* pStream) { @@ -314,7 +314,7 @@ static int64_t getLaunchTimeDelay(const SSqlStream* pStream) { int64_t remainTimeWindow = pStream->slidingTime - delayDelta; if (maxDelay > remainTimeWindow) { - maxDelay = (remainTimeWindow / 1.5); + maxDelay = (int64_t)(remainTimeWindow / 1.5f); } int64_t currentDelay = (rand() % maxDelay); // a random number @@ -505,7 +505,7 @@ static void tscCreateStream(void *param, TAOS_RES *res, int code) { int64_t starttime = tscGetLaunchTimestamp(pStream); pCmd->command = TSDB_SQL_SELECT; - taosTmrReset(tscProcessStreamTimer, starttime, pStream, tscTmr, &pStream->pTimer); + taosTmrReset(tscProcessStreamTimer, (int32_t)starttime, pStream, tscTmr, &pStream->pTimer); tscDebug("%p stream:%p is opened, query on:%s, interval:%" PRId64 ", sliding:%" PRId64 ", first launched in:%" PRId64 ", sql:%s", pSql, pStream, pTableMetaInfo->name, pStream->interval, pStream->slidingTime, starttime, pSql->sqlstr); diff --git a/src/client/src/tscSub.c b/src/client/src/tscSub.c index 81d73236a4e9972ac4401ebbb7a5815ebe0feb4b..e9f2c1dc1dfbd975ccdefb759bdf120d805cb335 100644 --- a/src/client/src/tscSub.c +++ b/src/client/src/tscSub.c @@ -230,6 +230,19 @@ static SArray* getTableList( SSqlObj* pSql ) { return result; } +static int32_t compareTidTag(const void* p1, const void* p2) { + const STidTags* t1 = (const STidTags*)p1; + const STidTags* t2 = (const STidTags*)p2; + + if (t1->vgId != t2->vgId) { + return (t1->vgId > t2->vgId) ? 1 : -1; + } + if (t1->tid != t2->tid) { + return (t1->tid > t2->tid) ? 1 : -1; + } + return 0; +} + static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) { SSqlObj* pSql = pSub->pSql; @@ -270,7 +283,8 @@ static int tscUpdateSubscription(STscObj* pObj, SSub* pSub) { pSub->progress = progress; if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { - taosArraySort( tables, tscCompareTidTags ); + taosArraySort( tables, compareTidTag ); + tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables); tscBuildVgroupTableInfo(pSql, pTableMetaInfo, tables); } taosArrayDestroy(tables); @@ -410,6 +424,9 @@ TAOS_RES *taos_consume(TAOS_SUB *tsub) { } } + size_t size = taosArrayGetSize(pSub->progress) * sizeof(STableIdInfo); + size += sizeof(SQueryTableMsg) + 4096; + tscAllocPayload(&pSql->cmd, (int)size); for (int retry = 0; retry < 3; retry++) { tscRemoveFromSqlList(pSql); diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index fd84486d429040d217629b98ad59bc93d6fe9bfc..69a6d5db5b4c9bb467e276bc916844327036c712 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -641,8 +641,8 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow pSupporter->pIdTagList = tmp; memcpy(pSupporter->pIdTagList + pSupporter->totalLen, pRes->data, validLen); - pSupporter->totalLen += validLen; - pSupporter->num += pRes->numOfRows; + pSupporter->totalLen += (int32_t)validLen; + pSupporter->num += (int32_t)pRes->numOfRows; // query not completed, continue to retrieve tid + tag tuples if (!pRes->completed) { @@ -775,7 +775,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow if (!pRes->completed) { taosGetTmpfilePath("ts-join", pSupporter->path); pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = pRes->numOfRows; + pRes->row = (int32_t)pRes->numOfRows; taos_fetch_rows_a(tres, tsCompRetrieveCallback, param); return; @@ -801,7 +801,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow // TODO check for failure pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = pRes->numOfRows; + pRes->row = (int32_t)pRes->numOfRows; // set the callback function pSql->fp = tscJoinQueryCallback; @@ -1220,7 +1220,7 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter getResultDataInfo(s->type, s->bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0); - SSchema s1 = {.colId = s->colId, .type = type, .bytes = bytes}; + SSchema s1 = {.colId = s->colId, .type = (uint8_t)type, .bytes = bytes}; pSupporter->tagSize = s1.bytes; assert(isValidDataType(s1.type) && s1.bytes > 0); @@ -1567,7 +1567,8 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO tscDebug("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pParentSql, pSql, trsupport->subqueryIndex, pState->numOfTotal - remain); - return tscFreeSubSqlObj(trsupport, pSql); + tscFreeSubSqlObj(trsupport, pSql); + return; } // all subqueries are failed @@ -1604,7 +1605,7 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[0]; // data in from current vnode is stored in cache and disk - uint32_t numOfRowsFromSubquery = trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->num; + uint32_t numOfRowsFromSubquery = (uint32_t)(trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->num); tscDebug("%p sub:%p all data retrieved from ep:%s, vgId:%d, numOfRows:%d, orderOfSub:%d", pParentSql, pSql, pTableMetaInfo->vgroupList->vgroups[0].epAddr[0].fqdn, pTableMetaInfo->vgroupList->vgroups[0].vgId, numOfRowsFromSubquery, idx); @@ -1622,14 +1623,16 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p if (tsTotalTmpDirGB != 0 && tsAvailTmpDirectorySpace < tsReservedTmpDirectorySpace) { tscError("%p sub:%p client disk space remain %.3f GB, need at least %.3f GB, stop query", pParentSql, pSql, tsAvailTmpDirectorySpace, tsReservedTmpDirectorySpace); - return tscAbortFurtherRetryRetrieval(trsupport, pSql, TSDB_CODE_TSC_NO_DISKSPACE); + tscAbortFurtherRetryRetrieval(trsupport, pSql, TSDB_CODE_TSC_NO_DISKSPACE); + return; } // each result for a vnode is ordered as an independant list, // then used as an input of loser tree for disk-based merge int32_t code = tscFlushTmpBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pQueryInfo->groupbyExpr.orderType); if (code != 0) { // set no disk space error info, and abort retry - return tscAbortFurtherRetryRetrieval(trsupport, pSql, code); + tscAbortFurtherRetryRetrieval(trsupport, pSql, code); + return; } int32_t remain = -1; @@ -1637,7 +1640,8 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p tscDebug("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pParentSql, pSql, trsupport->subqueryIndex, pState->numOfTotal - remain); - return tscFreeSubSqlObj(trsupport, pSql); + tscFreeSubSqlObj(trsupport, pSql); + return; } // all sub-queries are returned, start to local merge process @@ -1730,7 +1734,8 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) { tscError("%p sub:%p num of OrderedRes is too many, max allowed:%" PRId32 " , current:%" PRId64, pParentSql, pSql, tsMaxNumOfOrderedResults, num); - return tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY); + tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY); + return; } #ifdef _DEBUG_VIEW @@ -1745,11 +1750,12 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR if (tsTotalTmpDirGB != 0 && tsAvailTmpDirectorySpace < tsReservedTmpDirectorySpace) { tscError("%p sub:%p client disk space remain %.3f GB, need at least %.3f GB, stop query", pParentSql, pSql, tsAvailTmpDirectorySpace, tsReservedTmpDirectorySpace); - return tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); + tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); + return; } int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data, - pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); + (int32_t)pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); if (ret != 0) { // set no disk space error info, and abort retry tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); @@ -1877,7 +1883,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows) // todo remove this parameter in async callback function definition. // all data has been sent to vnode, call user function - int32_t v = (pParentObj->res.code != TSDB_CODE_SUCCESS)? pParentObj->res.code:pParentObj->res.numOfRows; + int32_t v = (pParentObj->res.code != TSDB_CODE_SUCCESS) ? pParentObj->res.code : (int32_t)pParentObj->res.numOfRows; (*pParentObj->fp)(pParentObj->param, pParentObj, v); } @@ -1913,7 +1919,7 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) { assert(size > 0); pSql->pSubs = calloc(size, POINTER_BYTES); - pSql->numOfSubs = size; + pSql->numOfSubs = (uint16_t)size; tscDebug("%p submit data to %zu vnode(s)", pSql, size); @@ -2005,7 +2011,7 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { continue; } - numOfRes = MIN(numOfRes, pSql->pSubs[i]->res.numOfRows); + numOfRes = (int32_t)(MIN(numOfRes, pSql->pSubs[i]->res.numOfRows)); } int32_t totalSize = tscGetResRowLength(pQueryInfo->exprList); @@ -2176,7 +2182,7 @@ void **doSetResultRowData(SSqlObj *pSql, bool finalResult) { SArithmeticSupport *sas = (SArithmeticSupport *) calloc(1, sizeof(SArithmeticSupport)); sas->offset = 0; sas->pArithExpr = pSup->pArithExprInfo; - sas->numOfCols = tscSqlExprNumOfExprs(pQueryInfo); + sas->numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); sas->exprList = pQueryInfo->exprList; sas->data = calloc(sas->numOfCols, POINTER_BYTES); diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index 2cc237dd83a684ed76e845f6a813eec80f7b2196..c742db42ab530f23d49db86d8221d9c4b4b4da6f 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -78,7 +78,7 @@ int32_t tscInitRpc(const char *user, const char *secret, void** pDnodeConn) { return 0; } -void taos_init_imp() { +void taos_init_imp(void) { char temp[128]; errno = TSDB_CODE_SUCCESS; @@ -124,9 +124,9 @@ void taos_init_imp() { int queueSize = tsMaxConnections*2; if (tscEmbedded == 0) { - tscNumOfThreads = tsNumOfCores * tsNumOfThreadsPerCore / 2.0; + tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / 2.0); } else { - tscNumOfThreads = tsNumOfCores * tsNumOfThreadsPerCore / 4.0; + tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / 4.0); } if (tscNumOfThreads < 2) tscNumOfThreads = 2; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index fdc019e97b0b90f8848f4b0cbfb0f7ba644b820b..fcc752983c1fc974dcaf893ec3f621d5d5f1c4bc 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -57,7 +57,7 @@ void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) { SCond cond = { .uid = uid, - .len = tbufTell(bw), + .len = (int32_t)(tbufTell(bw)), .cond = NULL, }; @@ -481,7 +481,7 @@ int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock) { */ pCmd->payloadLen = pDataBlock->size; - assert(pCmd->allocSize >= pCmd->payloadLen + 100 && pCmd->payloadLen > 0); + assert(pCmd->allocSize >= (uint32_t)(pCmd->payloadLen + 100) && pCmd->payloadLen > 0); return TSDB_CODE_SUCCESS; } @@ -570,7 +570,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo SSubmitBlk* pBlock = pDataBlock; memcpy(pDataBlock, pTableDataBlock->pData, sizeof(SSubmitBlk)); - pDataBlock += sizeof(SSubmitBlk); + pDataBlock = (char*)pDataBlock + sizeof(SSubmitBlk); int32_t flen = 0; // original total length of row @@ -584,7 +584,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo pCol->bytes = htons(pSchema[j].bytes); pCol->offset = 0; - pDataBlock += sizeof(STColumn); + pDataBlock = (char*)pDataBlock + sizeof(STColumn); flen += TYPE_BYTES[pSchema[j].type]; } @@ -604,7 +604,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo for (int32_t i = 0; i < numOfRows; ++i) { SDataRow trow = (SDataRow) pDataBlock; - dataRowSetLen(trow, TD_DATA_ROW_HEAD_SIZE + flen); + dataRowSetLen(trow, (uint16_t)(TD_DATA_ROW_HEAD_SIZE + flen)); dataRowSetVersion(trow, pTableMeta->sversion); int toffset = 0; @@ -614,7 +614,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo p += pSchema[j].bytes; } - pDataBlock += dataRowLen(trow); + pDataBlock = (char*)pDataBlock + dataRowLen(trow); pBlock->dataLen += dataRowLen(trow); } @@ -667,7 +667,7 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) { if (dataBuf->nAllocSize < destSize) { while (dataBuf->nAllocSize < destSize) { - dataBuf->nAllocSize = dataBuf->nAllocSize * 1.5; + dataBuf->nAllocSize = (uint32_t)(dataBuf->nAllocSize * 1.5); } char* tmp = realloc(dataBuf->pData, dataBuf->nAllocSize); @@ -759,7 +759,7 @@ int tscAllocPayload(SSqlCmd* pCmd, int size) { if (pCmd->payload == NULL) return TSDB_CODE_TSC_OUT_OF_MEMORY; pCmd->allocSize = size; } else { - if (pCmd->allocSize < size) { + if (pCmd->allocSize < (uint32_t)size) { char* b = realloc(pCmd->payload, size); if (b == NULL) return TSDB_CODE_TSC_OUT_OF_MEMORY; pCmd->payload = b; @@ -769,7 +769,7 @@ int tscAllocPayload(SSqlCmd* pCmd, int size) { memset(pCmd->payload, 0, pCmd->allocSize); } - assert(pCmd->allocSize >= size); + assert(pCmd->allocSize >= (uint32_t)size); return TSDB_CODE_SUCCESS; } @@ -964,7 +964,7 @@ static SSqlExpr* doBuildSqlExpr(SQueryInfo* pQueryInfo, int16_t functionId, SCol SSqlExpr* tscSqlExprInsert(SQueryInfo* pQueryInfo, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type, int16_t size, int16_t interSize, bool isTagCol) { - int32_t num = taosArrayGetSize(pQueryInfo->exprList); + int32_t num = (int32_t)taosArrayGetSize(pQueryInfo->exprList); if (index == num) { return tscSqlExprAppend(pQueryInfo, functionId, pColIndex, type, size, interSize, isTagCol); } @@ -1185,7 +1185,7 @@ void tscColumnListDestroy(SArray* pColumnList) { */ static int32_t validateQuoteToken(SSQLToken* pToken) { strdequote(pToken->z); - pToken->n = strtrim(pToken->z); + pToken->n = (uint32_t)strtrim(pToken->z); int32_t k = tSQLGetToken(pToken->z, &pToken->type); @@ -1208,7 +1208,7 @@ int32_t tscValidateName(SSQLToken* pToken) { if (sep == NULL) { // single part if (pToken->type == TK_STRING) { strdequote(pToken->z); - pToken->n = strtrim(pToken->z); + pToken->n = (uint32_t)strtrim(pToken->z); int len = tSQLGetToken(pToken->z, &pToken->type); @@ -1233,7 +1233,7 @@ int32_t tscValidateName(SSQLToken* pToken) { char* pStr = pToken->z; if (pToken->type == TK_SPACE) { - pToken->n = strtrim(pToken->z); + pToken->n = (uint32_t)strtrim(pToken->z); } pToken->n = tSQLGetToken(pToken->z, &pToken->type); @@ -1252,7 +1252,7 @@ int32_t tscValidateName(SSQLToken* pToken) { int32_t firstPartLen = pToken->n; pToken->z = sep + 1; - pToken->n = oldLen - (sep - pStr) - 1; + pToken->n = (uint32_t)(oldLen - (sep - pStr) - 1); int32_t len = tSQLGetToken(pToken->z, &pToken->type); if (len != pToken->n || (pToken->type != TK_STRING && pToken->type != TK_ID)) { return TSDB_CODE_TSC_INVALID_SQL; @@ -1557,12 +1557,22 @@ void tscClearSubqueryInfo(SSqlCmd* pCmd) { } } +void tscFreeVgroupTableInfo(SArray* pVgroupTables) { + if (pVgroupTables != NULL) { + for (size_t i = 0; i < taosArrayGetSize(pVgroupTables); i++) { + SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i); + taosArrayDestroy(pInfo->itemList); + } + taosArrayDestroy(pVgroupTables); + } +} + void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool removeFromCache) { tscDebug("%p deref the table meta in cache, numOfTables:%d", address, pQueryInfo->numOfTables); for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i); - + tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables); tscClearTableMetaInfo(pTableMetaInfo, removeFromCache); free(pTableMetaInfo); } @@ -1961,6 +1971,7 @@ int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid) { return pTagCond->joinInfo.right.tagColId; } else { assert(0); + return -1; } } diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 05114cc3244cab876c7aec5af31ac23cc42b3d8f..0da7bda994db83882e36e9d52a7983635ad85330 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,17 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_WINDOWS) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) -ENDIF () - -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(common ${SRC}) TARGET_LINK_LIBRARIES(common tutil) diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index 0cd3196ad015e28e6444a5763fae6eb2c09b8d35..0d7df38b832b03fdc5e4cdf5ab0bc684e3d1d8e8 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -140,19 +140,19 @@ char tsMqttBrokerAddress[128] = {0}; char tsMqttBrokerClientId[128] = {0}; // monitor -int32_t tsEnableMonitorModule = 0; +int32_t tsEnableMonitorModule = 1; char tsMonitorDbName[TSDB_DB_NAME_LEN] = "log"; char tsInternalPass[] = "secretkey"; int32_t tsMonitorInterval = 30; // seconds // internal int32_t tscEmbedded = 0; -char configDir[TSDB_FILENAME_LEN] = "/etc/taos"; +char configDir[TSDB_FILENAME_LEN] = {0}; char tsVnodeDir[TSDB_FILENAME_LEN] = {0}; char tsDnodeDir[TSDB_FILENAME_LEN] = {0}; char tsMnodeDir[TSDB_FILENAME_LEN] = {0}; -char tsDataDir[TSDB_FILENAME_LEN] = "/var/lib/taos"; -char tsScriptDir[TSDB_FILENAME_LEN] = "/etc/taos"; +char tsDataDir[TSDB_FILENAME_LEN] = {0}; +char tsScriptDir[TSDB_FILENAME_LEN] = {0}; char tsVnodeBakDir[TSDB_FILENAME_LEN] = {0}; /* @@ -295,6 +295,7 @@ bool taosCfgDynamicOptions(char *msg) { } static void doInitGlobalConfig(void) { + osInit(); SGlobalCfg cfg = {0}; // ip address diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/AsyncSubscribeTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/AsyncSubscribeTest.java index 7f2314d295477f15b44a50bfb1031a80fa9c822d..c14624e683c213851e123cc9e1671aa26ceb27be 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/AsyncSubscribeTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/AsyncSubscribeTest.java @@ -42,7 +42,8 @@ public class AsyncSubscribeTest extends BaseTest { long ts = System.currentTimeMillis(); for (int i = 0; i < 2; i++) { ts += i; - statement.executeUpdate("insert into \" + dbName + \".\" + tName + \" values (" + ts + ", " + (100 + i) + ", " + i + ")"); + String sql = "insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")"; + statement.executeUpdate(sql); } } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java index 5d86840ec3608c741ae3fe1f39023f6a54a3d077..a0b9c051c6241a32a60e4b12aa85b1f52ec42672 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/ResultSetTest.java @@ -71,7 +71,7 @@ public class ResultSetTest extends BaseTest { } try { - statement.executeQuery("select * from " + dbName + "." + tName); + statement.executeQuery("select * from " + dbName + "." + tName + " where ts = " + ts); resSet = statement.getResultSet(); System.out.println(((TSDBResultSet) resSet).getRowData()); while (resSet.next()) { @@ -806,9 +806,9 @@ public class ResultSetTest extends BaseTest { @Test public void testBatch() throws SQLException { - String[] sqls = new String[]{"insert into test.t0 values (1496732686001,2147483600,1496732687000,3.1415925,3.1415926\n" + - "535897,\"涛思数据,强~!\",12,12,\"TDengine is powerful\")", "insert into test.t0 values (1496732686002,2147483600,1496732687000,3.1415925,3.1415926\n" + - "535897,\"涛思数据,强~!\",12,12,\"TDengine is powerful\")"}; + String[] sqls = new String[]{"insert into test.t0 values (1496732686001,2147483600,1496732687000,3.1415925,3.1415926535897," + + "'涛思数据,强~',12,0,'TDengine is powerful')", "insert into test.t0 values (1496732686002,2147483600,1496732687000,3.1415925,3.1415926535897," + + "'涛思数据,强~',12,1,'TDengine is powerful')"}; for (String sql : sqls) { statement.addBatch(sql); } @@ -816,7 +816,6 @@ public class ResultSetTest extends BaseTest { assertEquals(res.length, 2); statement.clearBatch(); } - @AfterClass public static void close() throws Exception { statement.executeUpdate("drop database " + dbName); diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java index 58e93fbc7f4d755903f6460af2d2676b3a594422..d7f56ac4683cf0b9d983fa058a9871d2f116cdb2 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java @@ -41,7 +41,8 @@ public class SubscribeTest extends BaseTest { long ts = System.currentTimeMillis(); for (int i = 0; i < 2; i++) { ts += i; - statement.executeUpdate("insert into \" + dbName + \".\" + tName + \" values (" + ts + ", " + (100 + i) + ", " + i + ")"); + String sql = "insert into " + dbName + "." + tName + " values (" + ts + ", " + (100 + i) + ", " + i + ")"; + statement.executeUpdate(sql); } } diff --git a/src/cq/CMakeLists.txt b/src/cq/CMakeLists.txt index 4ccdb765c32926efa35e131322df2c584bd4c2b2..4e63cd4953a9d71fac6070926cf7ecb8d2ccb3cb 100644 --- a/src/cq/CMakeLists.txt +++ b/src/cq/CMakeLists.txt @@ -1,16 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC) -ADD_LIBRARY(tcq ${SRC}) -TARGET_LINK_LIBRARIES(tcq tutil common taos) - -ADD_SUBDIRECTORY(test) - +IF (TD_LINUX) + ADD_LIBRARY(tcq ${SRC}) + TARGET_LINK_LIBRARIES(tcq tutil common taos) + ADD_SUBDIRECTORY(test) +ENDIF () diff --git a/src/cq/test/CMakeLists.txt b/src/cq/test/CMakeLists.txt index 82781f531a30ace6066b1dc65500e06608cc054e..59c0ac79cfffd35a40beb58a2a172a9bf27dca15 100644 --- a/src/cq/test/CMakeLists.txt +++ b/src/cq/test/CMakeLists.txt @@ -1,12 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/cq/inc) - LIST(APPEND CQTEST_SRC ./cqtest.c) ADD_EXECUTABLE(cqtest ${CQTEST_SRC}) TARGET_LINK_LIBRARIES(cqtest tcq) diff --git a/src/dnode/CMakeLists.txt b/src/dnode/CMakeLists.txt index 64d69e9f0103fe1756976a273d16f7ab9bddc729..032e12624fd9a5a44435155aa2d676cf9644bac2 100644 --- a/src/dnode/CMakeLists.txt +++ b/src/dnode/CMakeLists.txt @@ -1,22 +1,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) ADD_EXECUTABLE(taosd ${SRC}) -# TARGET_LINK_LIBRARIES(taosd mnode taos_static monitor http mqtt tsdb twal vnode cJson lz4 balance sync) TARGET_LINK_LIBRARIES(taosd mnode taos monitor http mqtt tsdb twal vnode cJson lz4 balance sync) IF (TD_ACCOUNT) @@ -41,7 +35,4 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) COMMAND ${CMAKE_COMMAND} -E echo charset UTF-8 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg COMMENT "prepare taosd environment") ADD_CUSTOM_TARGET(${PREPARE_ENV_TARGET} ALL WORKING_DIRECTORY ${TD_EXECUTABLE_OUTPUT_PATH} DEPENDS ${PREPARE_ENV_CMD}) - -ENDIF () - - +ENDIF () \ No newline at end of file diff --git a/src/dnode/src/dnodeMain.c b/src/dnode/src/dnodeMain.c index f521fbe02bf611295fae22212080d97840c085a4..96f8f43265e30a75db2477e050eed54d66dc3399 100644 --- a/src/dnode/src/dnodeMain.c +++ b/src/dnode/src/dnodeMain.c @@ -159,7 +159,7 @@ static void dnodeCheckDataDirOpenned(char *dir) { } int32_t ret = flock(fd, LOCK_EX | LOCK_NB); if (ret != 0) { - dError("failed to lock file:%s ret:%d, database may be running, quit", filepath, ret); + dError("failed to lock file:%s ret:%d[%s], database may be running, quit", filepath, ret, strerror(errno)); close(fd); exit(0); } diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index ea445ee54317fb18afef29a80119a34afcf943a1..aa594183478c3c7dc924531525ec5a6ca98ab750 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -292,7 +292,7 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size); #define TSDB_MAX_CACHE_BLOCK_SIZE 128 // 128MB for each vnode #define TSDB_DEFAULT_CACHE_BLOCK_SIZE 16 -#define TSDB_MIN_TOTAL_BLOCKS 2 +#define TSDB_MIN_TOTAL_BLOCKS 3 #define TSDB_MAX_TOTAL_BLOCKS 10000 #define TSDB_DEFAULT_TOTAL_BLOCKS 6 @@ -303,7 +303,7 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size); #define TSDB_MIN_DAYS_PER_FILE 1 #define TSDB_MAX_DAYS_PER_FILE 3650 -#define TSDB_DEFAULT_DAYS_PER_FILE 10 +#define TSDB_DEFAULT_DAYS_PER_FILE 2 #define TSDB_MIN_KEEP 1 // data in db to be reserved. #define TSDB_MAX_KEEP 365000 // data in db to be reserved. diff --git a/src/kit/CMakeLists.txt b/src/kit/CMakeLists.txt index df3ce1000197b1add7f6454de7ed13c652a4d50d..3bacd426f3fc92b18d50e06033f3ad913375540f 100644 --- a/src/kit/CMakeLists.txt +++ b/src/kit/CMakeLists.txt @@ -3,5 +3,5 @@ PROJECT(TDengine) ADD_SUBDIRECTORY(shell) ADD_SUBDIRECTORY(taosdemo) -ADD_SUBDIRECTORY(taosdump) -ADD_SUBDIRECTORY(taosmigrate) \ No newline at end of file +#ADD_SUBDIRECTORY(taosClusterTest) +ADD_SUBDIRECTORY(taosnetwork) diff --git a/src/kit/shell/CMakeLists.txt b/src/kit/shell/CMakeLists.txt index 445d4f6951af4cf97c1a919893838625281c6c44..76af19f4815a8cc9fda812bc1f8d9ccf1356f174 100644 --- a/src/kit/shell/CMakeLists.txt +++ b/src/kit/shell/CMakeLists.txt @@ -1,15 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) AUX_SOURCE_DIRECTORY(./src SRC) LIST(REMOVE_ITEM SRC ./src/shellWindows.c) LIST(REMOVE_ITEM SRC ./src/shellDarwin.c) @@ -23,15 +19,13 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) ELSEIF (TD_WINDOWS) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) LIST(APPEND SRC ./src/shellEngine.c) LIST(APPEND SRC ./src/shellMain.c) LIST(APPEND SRC ./src/shellWindows.c) ADD_EXECUTABLE(shell ${SRC}) TARGET_LINK_LIBRARIES(shell taos_static) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) -ELSEIF (TD_DARWIN_64) +ELSEIF (TD_DARWIN) LIST(APPEND SRC ./src/shellEngine.c) LIST(APPEND SRC ./src/shellMain.c) LIST(APPEND SRC ./src/shellDarwin.c) diff --git a/src/kit/shell/src/shellDarwin.c b/src/kit/shell/src/shellDarwin.c index 3cb324abe93416dc11fbd7ee00d2db3b73d906d3..ce41827462366777d249a2e58c5fd6fec3fbb0e3 100644 --- a/src/kit/shell/src/shellDarwin.c +++ b/src/kit/shell/src/shellDarwin.c @@ -62,7 +62,7 @@ void printHelp() { exit(EXIT_SUCCESS); } -void shellParseArgument(int argc, char *argv[], struct arguments *arguments) { +void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { wordexp_t full_path; for (int i = 1; i < argc; i++) { // for host diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index 5d877ba6f06135bfaee12fe1bbd1bbf6739a1dce..750335a0379f3c1474ca15f823d15f43cd99224e 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -577,7 +577,7 @@ static int verticalPrintResult(TAOS_RES* tres) { int maxColNameLen = 0; for (int col = 0; col < num_fields; col++) { - int len = strlen(fields[col].name); + int len = (int)strlen(fields[col].name); if (len > maxColNameLen) { maxColNameLen = len; } @@ -604,9 +604,8 @@ static int verticalPrintResult(TAOS_RES* tres) { return numOfRows; } - static int calcColWidth(TAOS_FIELD* field, int precision) { - int width = strlen(field->name); + int width = (int)strlen(field->name); switch (field->type) { case TSDB_DATA_TYPE_BOOL: @@ -741,7 +740,7 @@ void read_history() { return; } - while ((read_size = getline(&line, &line_size, f)) != -1) { + while ((read_size = taosGetline(&line, &line_size, f)) != -1) { line[read_size - 1] = '\0'; history.hist[history.hend] = strdup(line); @@ -822,7 +821,7 @@ void source_file(TAOS *con, char *fptr) { return; } - while ((read_len = getline(&line, &line_len, f)) != -1) { + while ((read_len = taosGetline(&line, &line_len, f)) != -1) { if (read_len >= tsMaxSQLStringLen) continue; line[--read_len] = '\0'; diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index 8a7996d6825626e7bd8ed51c429916cba541ac79..7297f2393143fc935109b1e7bac5fac7b6910c80 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -9,12 +9,16 @@ * * ****************************************************************/ -#include "shell.h" #include #include #include +#include "os.h" +#include "shell.h" +#include "taos.h" #include "shellCommand.h" +extern char configDir[]; + void printHelp() { char indent[10] = " "; printf("taos shell is used to test the TDEngine database\n"); @@ -43,7 +47,7 @@ void printHelp() { exit(EXIT_SUCCESS); } -void shellParseArgument(int argc, char *argv[], struct arguments *arguments) { +void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) { for (int i = 1; i < argc; i++) { // for host if (strcmp(argv[i], "-h") == 0) { @@ -81,7 +85,7 @@ void shellParseArgument(int argc, char *argv[], struct arguments *arguments) { fprintf(stderr, "config file path: %s overflow max len %d\n", argv[i], TSDB_FILENAME_LEN - 1); exit(EXIT_FAILURE); } - strcpy(configDir, argv[i]); + strcpy(configDir, argv[++i]); } else { fprintf(stderr, "Option -c requires an argument\n"); exit(EXIT_FAILURE); diff --git a/src/kit/taosdemo/CMakeLists.txt b/src/kit/taosdemo/CMakeLists.txt index 5045e8cd3ffae75436950a2b8a102977d6f8a305..1698c8591541157a8ecb2339a19273a375c03a40 100644 --- a/src/kit/taosdemo/CMakeLists.txt +++ b/src/kit/taosdemo/CMakeLists.txt @@ -1,13 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(taosdemo ${SRC}) @@ -16,5 +13,8 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) # ELSE () # TARGET_LINK_LIBRARIES(taosdemo taos_static) # ENDIF () - +ELSEIF (TD_WINDOWS) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(taosdemo ${SRC}) + TARGET_LINK_LIBRARIES(taosdemo taos_static) ENDIF () diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index bebcf2627799720926bdb064e5a776cf75f5dfbf..9d46ac505551aae46178eabf43f6e4f25a99ec5a 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify @@ -15,24 +15,31 @@ #define _GNU_SOURCE -#include -#include -#include - -#ifndef _ALPINE -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifdef LINUX + #include "os.h" + #include + #include + #include + #ifndef _ALPINE + #include + #endif + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include "os.h" +#endif #include "taos.h" #include "tutil.h" @@ -42,38 +49,12 @@ extern char configDir[]; #define BUFFER_SIZE 65536 #define MAX_DB_NAME_SIZE 64 #define MAX_TB_NAME_SIZE 64 -#define MAX_DATA_SIZE 1024 -#define MAX_NUM_DATATYPE 30 +#define MAX_DATA_SIZE 16000 +#define MAX_NUM_DATATYPE 10 #define OPT_ABORT 1 /* –abort */ -#define STRING_LEN 512 +#define STRING_LEN 60000 #define MAX_PREPARED_RAND 1000000 -/* The options we understand. */ -static struct argp_option options[] = { - {0, 'h', "host", 0, "The host to connect to TDEngine. Default is localhost.", 0}, - {0, 'p', "port", 0, "The TCP/IP port number to use for the connection. Default is 0.", 1}, - {0, 'u', "user", 0, "The TDEngine user name to use when connecting to the server. Default is 'root'.", 2}, - {0, 'P', "password", 0, "The password to use when connecting to the server. Default is 'taosdata'.", 3}, - {0, 'd', "database", 0, "Destination database. Default is 'test'.", 3}, - {0, 'm', "table_prefix", 0, "Table prefix name. Default is 't'.", 3}, - {0, 's', "sql file", 0, "The select sql file.", 3}, - {0, 'M', 0, 0, "Use metric flag.", 13}, - {0, 'o', "outputfile", 0, "Direct output to the named file. Default is './output.txt'.", 14}, - {0, 'q', "query_mode", 0, "Query mode--0: SYNC, 1: ASYNC. Default is SYNC.", 6}, - {0, 'b', "type_of_cols", 0, "The data_type of columns: 'INT', 'TINYINT', 'SMALLINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'BINARY'. Default is 'INT'.", 7}, - {0, 'w', "length_of_binary", 0, "The length of data_type 'BINARY'. Only applicable when type of cols is 'BINARY'. Default is 8", 8}, - {0, 'l', "num_of_cols_per_record", 0, "The number of columns per record. Default is 3.", 8}, - {0, 'T', "num_of_threads", 0, "The number of threads. Default is 10.", 9}, - {0, 'r', "num_of_records_per_req", 0, "The number of records per request. Default is 1000.", 10}, - {0, 't', "num_of_tables", 0, "The number of tables. Default is 10000.", 11}, - {0, 'n', "num_of_records_per_table", 0, "The number of records per table. Default is 100000.", 12}, - {0, 'c', "config_directory", 0, "Configuration directory. Default is '/etc/taos/'.", 14}, - {0, 'x', 0, 0, "Insert only flag.", 13}, - {0, 'O', "order", 0, "Insert mode--0: In order, 1: Out of order. Default is in order.", 14}, - {0, 'R', "rate", 0, "Out of order data's rate--if order=1 Default 10, min: 0, max: 50.", 14}, - {0, 'D', "delete table", 0, "Delete data methods——0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database", 14}, - {0}}; - /* Used by main to communicate with parse_opt. */ typedef struct DemoArguments { char *host; @@ -101,143 +82,337 @@ typedef struct DemoArguments { char **arg_list; } SDemoArguments; -/* Parse a single option. */ -static error_t parse_opt(int key, char *arg, struct argp_state *state) { - /* Get the input argument from argp_parse, which we - know is a pointer to our arguments structure. */ - SDemoArguments *arguments = state->input; - wordexp_t full_path; - char **sptr; - switch (key) { - case 'h': - arguments->host = arg; - break; - case 'p': - arguments->port = atoi(arg); - break; - case 'u': - arguments->user = arg; - break; - case 'P': - arguments->password = arg; - break; - case 'o': - arguments->output_file = arg; - break; - case 's': - arguments->sqlFile = arg; - break; - case 'q': - arguments->mode = atoi(arg); - break; - case 'T': - arguments->num_of_threads = atoi(arg); - break; - case 'r': - arguments->num_of_RPR = atoi(arg); - break; - case 't': - arguments->num_of_tables = atoi(arg); - break; - case 'n': - arguments->num_of_DPT = atoi(arg); - break; - case 'd': - arguments->database = arg; - break; - case 'l': - arguments->num_of_CPR = atoi(arg); - break; - case 'b': - sptr = arguments->datatype; - if (strstr(arg, ",") == NULL) { - if (strcasecmp(arg, "INT") != 0 && strcasecmp(arg, "FLOAT") != 0 && - strcasecmp(arg, "TINYINT") != 0 && strcasecmp(arg, "BOOL") != 0 && - strcasecmp(arg, "SMALLINT") != 0 && - strcasecmp(arg, "BIGINT") != 0 && strcasecmp(arg, "DOUBLE") != 0 && - strcasecmp(arg, "BINARY")) { - argp_error(state, "Invalid data_type!"); - } - sptr[0] = arg; - } else { - int index = 0; - char *dupstr = strdup(arg); - char *running = dupstr; - char *token = strsep(&running, ","); - while (token != NULL) { - if (strcasecmp(token, "INT") != 0 && - strcasecmp(token, "FLOAT") != 0 && - strcasecmp(token, "TINYINT") != 0 && - strcasecmp(token, "BOOL") != 0 && - strcasecmp(token, "SMALLINT") != 0 && - strcasecmp(token, "BIGINT") != 0 && - strcasecmp(token, "DOUBLE") != 0 && strcasecmp(token, "BINARY")) { +#ifdef LINUX + /* The options we understand. */ + static struct argp_option options[] = { + {0, 'h', "host", 0, "The host to connect to TDEngine. Default is localhost.", 0}, + {0, 'p', "port", 0, "The TCP/IP port number to use for the connection. Default is 0.", 1}, + {0, 'u', "user", 0, "The TDEngine user name to use when connecting to the server. Default is 'root'.", 2}, + {0, 'P', "password", 0, "The password to use when connecting to the server. Default is 'taosdata'.", 3}, + {0, 'd', "database", 0, "Destination database. Default is 'test'.", 3}, + {0, 'm', "table_prefix", 0, "Table prefix name. Default is 't'.", 3}, + {0, 's', "sql file", 0, "The select sql file.", 3}, + {0, 'M', 0, 0, "Use metric flag.", 13}, + {0, 'o', "outputfile", 0, "Direct output to the named file. Default is './output.txt'.", 14}, + {0, 'q', "query_mode", 0, "Query mode--0: SYNC, 1: ASYNC. Default is SYNC.", 6}, + {0, 'b', "type_of_cols", 0, "The data_type of columns: 'INT', 'TINYINT', 'SMALLINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'BINARY'. Default is 'INT'.", 7}, + {0, 'w', "length_of_binary", 0, "The length of data_type 'BINARY'. Only applicable when type of cols is 'BINARY'. Default is 8", 8}, + {0, 'l', "num_of_cols_per_record", 0, "The number of columns per record. Default is 3.", 8}, + {0, 'T', "num_of_threads", 0, "The number of threads. Default is 10.", 9}, + {0, 'r', "num_of_records_per_req", 0, "The number of records per request. Default is 1000.", 10}, + {0, 't', "num_of_tables", 0, "The number of tables. Default is 10000.", 11}, + {0, 'n', "num_of_records_per_table", 0, "The number of records per table. Default is 100000.", 12}, + {0, 'c', "config_directory", 0, "Configuration directory. Default is '/etc/taos/'.", 14}, + {0, 'x', 0, 0, "Insert only flag.", 13}, + {0, 'O', "order", 0, "Insert mode--0: In order, 1: Out of order. Default is in order.", 14}, + {0, 'R', "rate", 0, "Out of order data's rate--if order=1 Default 10, min: 0, max: 50.", 14}, + {0, 'D', "delete table", 0, "Delete data methods——0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database", 14}, + {0}}; + + /* Parse a single option. */ + static error_t parse_opt(int key, char *arg, struct argp_state *state) { + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + SDemoArguments *arguments = state->input; + wordexp_t full_path; + char **sptr; + switch (key) { + case 'h': + arguments->host = arg; + break; + case 'p': + arguments->port = atoi(arg); + break; + case 'u': + arguments->user = arg; + break; + case 'P': + arguments->password = arg; + break; + case 'o': + arguments->output_file = arg; + break; + case 's': + arguments->sqlFile = arg; + break; + case 'q': + arguments->mode = atoi(arg); + break; + case 'T': + arguments->num_of_threads = atoi(arg); + break; + case 'r': + arguments->num_of_RPR = atoi(arg); + break; + case 't': + arguments->num_of_tables = atoi(arg); + break; + case 'n': + arguments->num_of_DPT = atoi(arg); + break; + case 'd': + arguments->database = arg; + break; + case 'l': + arguments->num_of_CPR = atoi(arg); + break; + case 'b': + sptr = arguments->datatype; + if (strstr(arg, ",") == NULL) { + if (strcasecmp(arg, "INT") != 0 && strcasecmp(arg, "FLOAT") != 0 && + strcasecmp(arg, "TINYINT") != 0 && strcasecmp(arg, "BOOL") != 0 && + strcasecmp(arg, "SMALLINT") != 0 && + strcasecmp(arg, "BIGINT") != 0 && strcasecmp(arg, "DOUBLE") != 0 && + strcasecmp(arg, "BINARY") && strcasecmp(arg, "NCHAR")) { argp_error(state, "Invalid data_type!"); } - sptr[index++] = token; - token = strsep(&running, ", "); - if (index >= MAX_NUM_DATATYPE) break; + sptr[0] = arg; + } else { + int index = 0; + char *dupstr = strdup(arg); + char *running = dupstr; + char *token = strsep(&running, ","); + while (token != NULL) { + if (strcasecmp(token, "INT") != 0 && + strcasecmp(token, "FLOAT") != 0 && + strcasecmp(token, "TINYINT") != 0 && + strcasecmp(token, "BOOL") != 0 && + strcasecmp(token, "SMALLINT") != 0 && + strcasecmp(token, "BIGINT") != 0 && + strcasecmp(token, "DOUBLE") != 0 && strcasecmp(token, "BINARY") && strcasecmp(token, "NCHAR")) { + argp_error(state, "Invalid data_type!"); + } + sptr[index++] = token; + token = strsep(&running, ","); + if (index >= MAX_NUM_DATATYPE) break; + } } - } - break; - case 'w': - arguments->len_of_binary = atoi(arg); - break; - case 'm': - arguments->tb_prefix = arg; - break; - case 'M': - arguments->use_metric = false; - break; - case 'x': - arguments->insert_only = false; - break; - case 'c': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]); - wordfree(&full_path); - break; - case 'O': - arguments->order = atoi(arg); - if (arguments->order > 1 || arguments->order < 0) - { - arguments->order = 0; - } else if (arguments->order == 1) - { - arguments->rate = 10; - } - break; - case 'R': - arguments->rate = atoi(arg); - if (arguments->order == 1 && (arguments->rate > 50 || arguments->rate <= 0)) - { - arguments->rate = 10; - } - break; - case 'D': - arguments->method_of_delete = atoi(arg); - if (arguments->method_of_delete < 0 || arguments->method_of_delete > 3) - { - arguments->method_of_delete = 0; - } - break; - case OPT_ABORT: - arguments->abort = 1; - break; - case ARGP_KEY_ARG: - /*arguments->arg_list = &state->argv[state->next-1]; - state->next = state->argc;*/ - argp_usage(state); - break; + break; + case 'w': + arguments->len_of_binary = atoi(arg); + break; + case 'm': + arguments->tb_prefix = arg; + break; + case 'M': + arguments->use_metric = false; + break; + case 'x': + arguments->insert_only = false; + break; + case 'c': + if (wordexp(arg, &full_path, 0) != 0) { + fprintf(stderr, "Invalid path %s\n", arg); + return -1; + } + taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]); + wordfree(&full_path); + break; + case 'O': + arguments->order = atoi(arg); + if (arguments->order > 1 || arguments->order < 0) + { + arguments->order = 0; + } else if (arguments->order == 1) + { + arguments->rate = 10; + } + break; + case 'R': + arguments->rate = atoi(arg); + if (arguments->order == 1 && (arguments->rate > 50 || arguments->rate <= 0)) + { + arguments->rate = 10; + } + break; + case 'D': + arguments->method_of_delete = atoi(arg); + if (arguments->method_of_delete < 0 || arguments->method_of_delete > 3) + { + arguments->method_of_delete = 0; + } + break; + case OPT_ABORT: + arguments->abort = 1; + break; + case ARGP_KEY_ARG: + /*arguments->arg_list = &state->argv[state->next-1]; + state->next = state->argc;*/ + argp_usage(state); + break; - default: - return ARGP_ERR_UNKNOWN; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; + } + + static struct argp argp = {options, parse_opt, 0, 0}; + + void parse_args(int argc, char *argv[], SDemoArguments *arguments) { + argp_parse(&argp, argc, argv, 0, 0, &arguments); + if (arguments->abort) { + #ifndef _ALPINE + error(10, 0, "ABORTED"); + #else + abort(); + #endif + } + } + +#else + void printHelp() { + char indent[10] = " "; + printf("%s%s\n", indent, "-h"); + printf("%s%s%s\n", indent, indent, "host, The host to connect to TDEngine. Default is localhost."); + printf("%s%s\n", indent, "-p"); + printf("%s%s%s\n", indent, indent, "port, The TCP/IP port number to use for the connection. Default is 0."); + printf("%s%s\n", indent, "-u"); + printf("%s%s%s\n", indent, indent, "user, The TDEngine user name to use when connecting to the server. Default is 'root'."); + printf("%s%s\n", indent, "-p"); + printf("%s%s%s\n", indent, indent, "password, The password to use when connecting to the server. Default is 'taosdata'."); + printf("%s%s\n", indent, "-d"); + printf("%s%s%s\n", indent, indent, "database, Destination database. Default is 'test'."); + printf("%s%s\n", indent, "-m"); + printf("%s%s%s\n", indent, indent, "table_prefix, Table prefix name. Default is 't'."); + printf("%s%s\n", indent, "-s"); + printf("%s%s%s\n", indent, indent, "sql file, The select sql file."); + printf("%s%s\n", indent, "-M"); + printf("%s%s%s\n", indent, indent, "meteric, Use metric flag."); + printf("%s%s\n", indent, "-o"); + printf("%s%s%s\n", indent, indent, "outputfile, Direct output to the named file. Default is './output.txt'."); + printf("%s%s\n", indent, "-q"); + printf("%s%s%s\n", indent, indent, "query_mode, Query mode--0: SYNC, 1: ASYNC. Default is SYNC."); + printf("%s%s\n", indent, "-b"); + printf("%s%s%s\n", indent, indent, "type_of_cols, data_type of columns: 'INT', 'TINYINT', 'SMALLINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'BINARY'. Default is 'INT'."); + printf("%s%s\n", indent, "-w"); + printf("%s%s%s\n", indent, indent, "length_of_binary, The length of data_type 'BINARY'. Only applicable when type of cols is 'BINARY'. Default is 8"); + printf("%s%s\n", indent, "-l"); + printf("%s%s%s\n", indent, indent, "num_of_cols_per_record, The number of columns per record. Default is 3."); + printf("%s%s\n", indent, "-T"); + printf("%s%s%s\n", indent, indent, "num_of_threads, The number of threads. Default is 10."); + printf("%s%s\n", indent, "-r"); + printf("%s%s%s\n", indent, indent, "num_of_records_per_req, The number of records per request. Default is 1000."); + printf("%s%s\n", indent, "-t"); + printf("%s%s%s\n", indent, indent, "num_of_tables, The number of tables. Default is 10000."); + printf("%s%s\n", indent, "-n"); + printf("%s%s%s\n", indent, indent, "num_of_records_per_table, The number of records per table. Default is 100000."); + printf("%s%s\n", indent, "-c"); + printf("%s%s%s\n", indent, indent, "config_directory, Configuration directory. Default is '/etc/taos/'."); + printf("%s%s\n", indent, "-x"); + printf("%s%s%s\n", indent, indent, "flag, Insert only flag."); + printf("%s%s\n", indent, "-O"); + printf("%s%s%s\n", indent, indent, "order, Insert mode--0: In order, 1: Out of order. Default is in order."); + printf("%s%s\n", indent, "-R"); + printf("%s%s%s\n", indent, indent, "rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50."); + printf("%s%s\n", indent, "-D"); + printf("%s%s%s\n", indent, indent, "Delete data methods——0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database."); } - return 0; -} + + void parse_args(int argc, char *argv[], SDemoArguments *arguments) { + char **sptr; + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0) { + arguments->host = argv[++i]; + } else if (strcmp(argv[i], "-p") == 0) { + arguments->port = atoi(argv[++i]); + } else if (strcmp(argv[i], "-u") == 0) { + arguments->user = argv[++i]; + } else if (strcmp(argv[i], "-P") == 0) { + arguments->password = argv[++i]; + } else if (strcmp(argv[i], "-o") == 0) { + arguments->output_file = argv[++i]; + } else if (strcmp(argv[i], "-s") == 0) { + arguments->sqlFile = argv[++i]; + } else if (strcmp(argv[i], "-q") == 0) { + arguments->mode = atoi(argv[++i]); + } else if (strcmp(argv[i], "-T") == 0) { + arguments->num_of_threads = atoi(argv[++i]); + } else if (strcmp(argv[i], "-r") == 0) { + arguments->num_of_RPR = atoi(argv[++i]); + } else if (strcmp(argv[i], "-t") == 0) { + arguments->num_of_tables = atoi(argv[++i]); + } else if (strcmp(argv[i], "-n") == 0) { + arguments->num_of_DPT = atoi(argv[++i]); + } else if (strcmp(argv[i], "-d") == 0) { + arguments->database = argv[++i]; + } else if (strcmp(argv[i], "-l") == 0) { + arguments->num_of_CPR = atoi(argv[++i]); + } else if (strcmp(argv[i], "-b") == 0) { + sptr = arguments->datatype; + ++i; + if (strstr(argv[i], ",") == NULL) { + if (strcasecmp(argv[i], "INT") != 0 && strcasecmp(argv[i], "FLOAT") != 0 && + strcasecmp(argv[i], "TINYINT") != 0 && strcasecmp(argv[i], "BOOL") != 0 && + strcasecmp(argv[i], "SMALLINT") != 0 && + strcasecmp(argv[i], "BIGINT") != 0 && strcasecmp(argv[i], "DOUBLE") != 0 && + strcasecmp(argv[i], "BINARY") && strcasecmp(argv[i], "NCHAR")) { + fprintf(stderr, "Invalid data_type!\n"); + printHelp(); + exit(EXIT_FAILURE); + } + sptr[0] = argv[i]; + } else { + int index = 0; + char *dupstr = strdup(argv[i]); + char *running = dupstr; + char *token = strsep(&running, ","); + while (token != NULL) { + if (strcasecmp(token, "INT") != 0 && + strcasecmp(token, "FLOAT") != 0 && + strcasecmp(token, "TINYINT") != 0 && + strcasecmp(token, "BOOL") != 0 && + strcasecmp(token, "SMALLINT") != 0 && + strcasecmp(token, "BIGINT") != 0 && + strcasecmp(token, "DOUBLE") != 0 && strcasecmp(token, "BINARY") && strcasecmp(token, "NCHAR")) { + fprintf(stderr, "Invalid data_type!\n"); + printHelp(); + exit(EXIT_FAILURE); + } + sptr[index++] = token; + token = strsep(&running, ","); + if (index >= MAX_NUM_DATATYPE) break; + } + } + } else if (strcmp(argv[i], "-w") == 0) { + arguments->len_of_binary = atoi(argv[++i]); + } else if (strcmp(argv[i], "-m") == 0) { + arguments->tb_prefix = argv[++i]; + } else if (strcmp(argv[i], "-M") == 0) { + arguments->use_metric = false; + } else if (strcmp(argv[i], "-x") == 0) { + arguments->insert_only = false; + } else if (strcmp(argv[i], "-c") == 0) { + strcpy(configDir, argv[++i]); + } else if (strcmp(argv[i], "-O") == 0) { + arguments->order = atoi(argv[++i]); + if (arguments->order > 1 || arguments->order < 0) { + arguments->order = 0; + } else if (arguments->order == 1) { + arguments->rate = 10; + } + } else if (strcmp(argv[i], "-R") == 0) { + arguments->rate = atoi(argv[++i]); + if (arguments->order == 1 && (arguments->rate > 50 || arguments->rate <= 0)) { + arguments->rate = 10; + } + } else if (strcmp(argv[i], "-D") == 0) { + arguments->method_of_delete = atoi(argv[++i]); + if (arguments->method_of_delete < 0 || arguments->method_of_delete > 3) { + arguments->method_of_delete = 0; + } + } else if (strcmp(argv[i], "--help") == 0) { + printHelp(); + exit(EXIT_FAILURE); + } else { + fprintf(stderr, "wrong options\n"); + printHelp(); + exit(EXIT_FAILURE); + } + } + } + +#endif /* ******************************* Structure * definition******************************* */ @@ -293,9 +468,6 @@ typedef struct { * variables******************************* */ char *aggreFunc[] = {"*", "count(*)", "avg(f1)", "sum(f1)", "max(f1)", "min(f1)", "first(f1)", "last(f1)"}; -/* ******************************* Global - * functions******************************* */ -static struct argp argp = {options, parse_opt, 0, 0}; void queryDB(TAOS *taos, char *command); @@ -335,13 +507,13 @@ int main(int argc, char *argv[]) { 0, // mode { "int", // datatype - "", - "", - "", - "", - "", - "", - "" + "int", + "int", + "int", + "int", + "int", + "int", + "float" }, 8, // len_of_binary 1, // num_of_CPR @@ -368,15 +540,7 @@ int main(int argc, char *argv[]) { arguments.insert_only = true; // end change - argp_parse(&argp, argc, argv, 0, 0, &arguments); - - if (arguments.abort) { - #ifndef _ALPINE - error(10, 0, "ABORTED"); - #else - abort(); - #endif - } + parse_args(argc, argv, &arguments); enum MODE query_mode = arguments.mode; char *ip_addr = arguments.host; @@ -412,7 +576,7 @@ int main(int argc, char *argv[]) { memset(dataString, 0, STRING_LEN); int len = 0; - if (strcasecmp(data_type[0], "BINARY") == 0 || strcasecmp(data_type[0], "BOOL") == 0) { + if (strcasecmp(data_type[0], "BINARY") == 0 || strcasecmp(data_type[0], "BOOL") == 0 || strcasecmp(data_type[0], "NCHAR") == 0 ) { do_aggreFunc = false; } for (; count_data_type <= MAX_NUM_DATATYPE; count_data_type++) { @@ -438,7 +602,7 @@ int main(int argc, char *argv[]) { printf("# Use metric: %s\n", use_metric ? "true" : "false"); printf("# Datatype of Columns: %s\n", dataString); printf("# Binary Length(If applicable): %d\n", - (strcasestr(dataString, "BINARY") != NULL) ? len_of_binary : -1); + (strncasecmp(dataString, "BINARY", 6) == 0 || strncasecmp(dataString, "NCHAR", 5) == 0) ? len_of_binary : -1); printf("# Number of Columns per record: %d\n", ncols_per_record); printf("# Number of Threads: %d\n", threads); printf("# Number of Tables: %d\n", ntables); @@ -466,7 +630,7 @@ int main(int argc, char *argv[]) { fprintf(fp, "# Use metric: %s\n", use_metric ? "true" : "false"); fprintf(fp, "# Datatype of Columns: %s\n", dataString); fprintf(fp, "# Binary Length(If applicable): %d\n", - (strcasestr(dataString, "BINARY") != NULL) ? len_of_binary : -1); + (strncasecmp(dataString, "BINARY", 6) == 0 || strncasecmp(dataString, "NCHAR", 5) == 0) ? len_of_binary : -1); fprintf(fp, "# Number of Columns per record: %d\n", ncols_per_record); fprintf(fp, "# Number of Threads: %d\n", threads); fprintf(fp, "# Number of Tables: %d\n", ntables); @@ -506,23 +670,23 @@ int main(int argc, char *argv[]) { len = 0; for (; colIndex < ncols_per_record - 1; colIndex++) { - if (strcasecmp(data_type[colIndex % count_data_type], "BINARY") != 0) { + if (strcasecmp(data_type[colIndex % count_data_type], "BINARY") != 0 && strcasecmp(data_type[colIndex % count_data_type], "NCHAR") != 0) { len += snprintf(cols + len, STRING_LEN - len, ",f%d %s", colIndex + 1, data_type[colIndex % count_data_type]); } else { len += snprintf(cols + len, STRING_LEN - len, ",f%d %s(%d)", colIndex + 1, data_type[colIndex % count_data_type], len_of_binary); } } - if (strcasecmp(data_type[colIndex % count_data_type], "BINARY") != 0) { - len += snprintf(cols + len, STRING_LEN - len, ",f%d %s)", colIndex + 1, data_type[colIndex % count_data_type]); + if (strcasecmp(data_type[colIndex % count_data_type], "BINARY") != 0 && strcasecmp(data_type[colIndex % count_data_type], "NCHAR") != 0){ + len += snprintf(cols + len, STRING_LEN - len, ",f%d %s", colIndex + 1, data_type[colIndex % count_data_type]); } else { - len += snprintf(cols + len, STRING_LEN - len, ",f%d %s(%d))", colIndex + 1, data_type[colIndex % count_data_type], len_of_binary); + len += snprintf(cols + len, STRING_LEN - len, ",f%d %s(%d)", colIndex + 1, data_type[colIndex % count_data_type], len_of_binary); } if (use_metric) { /* Create metric table */ printf("Creating meters super table...\n"); - snprintf(command, BUFFER_SIZE, "create table if not exists %s.meters (ts timestamp%s tags (areaid int, loc binary(10))", db_name, cols); + snprintf(command, BUFFER_SIZE, "create table if not exists %s.meters (ts timestamp%s) tags (areaid int, loc binary(10))", db_name, cols); queryDB(taos, command); printf("meters created!\n"); } @@ -753,7 +917,7 @@ void querySqlFile(TAOS* taos, char* sqlFile) double t = getCurrentTime(); - while ((read_len = getline(&line, &line_len, fp)) != -1) { + while ((read_len = taosGetline(&line, &line_len, fp)) != -1) { if (read_len >= MAX_SQL_SIZE) continue; line[--read_len] = '\0'; @@ -1035,7 +1199,7 @@ void *syncWrite(void *sarg) { char **data_type = winfo->datatype; int len_of_binary = winfo->len_of_binary; int ncols_per_record = winfo->ncols_per_record; - srand(time(NULL)); + srand((uint32_t)time(NULL)); int64_t time_counter = winfo->start_time; for (int i = 0; i < winfo->nrecords_per_table;) { for (int tID = winfo->start_table_id; tID <= winfo->end_table_id; tID++) { @@ -1049,7 +1213,7 @@ void *syncWrite(void *sarg) { int rand_num = rand() % 100; int len = -1; if (winfo->data_of_order ==1 && rand_num < winfo->data_of_rate) { - long d = tmp_time - rand() % 1000000 + rand_num; + int64_t d = tmp_time - rand() % 1000000 + rand_num; len = generateData(data, data_type, ncols_per_record, d, len_of_binary); } else { len = generateData(data, data_type, ncols_per_record, tmp_time += 1000, len_of_binary); @@ -1144,7 +1308,7 @@ void callBack(void *param, TAOS_RES *res, int code) { int rand_num = rand() % 100; if (tb_info->data_of_order ==1 && rand_num < tb_info->data_of_rate) { - long d = tmp_time - rand() % 1000000 + rand_num; + int64_t d = tmp_time - rand() % 1000000 + rand_num; generateData(data, datatype, ncols_per_record, d, len_of_binary); } else { @@ -1269,9 +1433,15 @@ int32_t generateData(char *res, char **data_type, int num_of_cols, int64_t times bool b = rand() & 1; pstr += sprintf(pstr, ", %s", b ? "true" : "false"); } else if (strcasecmp(data_type[i % c], "binary") == 0) { - char s[len_of_binary]; + char *s = malloc(len_of_binary); + rand_string(s, len_of_binary); + pstr += sprintf(pstr, ", \"%s\"", s); + free(s); + }else if (strcasecmp(data_type[i % c], "nchar") == 0) { + char *s = malloc(len_of_binary); rand_string(s, len_of_binary); pstr += sprintf(pstr, ", \"%s\"", s); + free(s); } if (pstr - res > MAX_DATA_SIZE) { @@ -1282,7 +1452,7 @@ int32_t generateData(char *res, char **data_type, int num_of_cols, int64_t times pstr += sprintf(pstr, ")"); - return pstr - res; + return (int32_t)(pstr - res); } static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK1234567890"; diff --git a/src/kit/taosdump/CMakeLists.txt b/src/kit/taosdump/CMakeLists.txt deleted file mode 100644 index 1c5dd3eda235dc56c490cf9027e8c31d3017431a..0000000000000000000000000000000000000000 --- a/src/kit/taosdump/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) -INCLUDE_DIRECTORIES(inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - AUX_SOURCE_DIRECTORY(. SRC) - ADD_EXECUTABLE(taosdump ${SRC}) - -# IF (TD_PAGMODE_LITE) - TARGET_LINK_LIBRARIES(taosdump taos) -# ELSE () -# TARGET_LINK_LIBRARIES(taosdump taos_static) -# ENDIF () - - -ENDIF () diff --git a/src/kit/taosdump/taosdump.c b/src/kit/taosdump/taosdump.c deleted file mode 100644 index 8a05c893e8f406bb37abf002161dcfbd87ac0ab6..0000000000000000000000000000000000000000 --- a/src/kit/taosdump/taosdump.c +++ /dev/null @@ -1,2235 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include -#ifndef _ALPINE - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "os.h" -#include "taos.h" -#include "taosdef.h" -#include "taosmsg.h" -#include "tglobal.h" -#include "tsclient.h" -#include "tsdb.h" -#include "tutil.h" - -#define COMMAND_SIZE 65536 -//#define DEFAULT_DUMP_FILE "taosdump.sql" - -int converStringToReadable(char *str, int size, char *buf, int bufsize); -int convertNCharToReadable(char *str, int size, char *buf, int bufsize); -void taosDumpCharset(FILE *fp); -void taosLoadFileCharset(FILE *fp, char *fcharset); - -typedef struct { - short bytes; - int8_t type; -} SOColInfo; - -// -------------------------- SHOW DATABASE INTERFACE----------------------- -enum _show_db_index { - TSDB_SHOW_DB_NAME_INDEX, - TSDB_SHOW_DB_CREATED_TIME_INDEX, - TSDB_SHOW_DB_VGROUPS_INDEX, - TSDB_SHOW_DB_NTABLES_INDEX, - TSDB_SHOW_DB_REPLICA_INDEX, - TSDB_SHOW_DB_DAYS_INDEX, - TSDB_SHOW_DB_KEEP_INDEX, - TSDB_SHOW_DB_TABLES_INDEX, - TSDB_SHOW_DB_ROWS_INDEX, - TSDB_SHOW_DB_CACHE_INDEX, - TSDB_SHOW_DB_ABLOCKS_INDEX, - TSDB_SHOW_DB_TBLOCKS_INDEX, - TSDB_SHOW_DB_CTIME_INDEX, - TSDB_SHOW_DB_CLOG_INDEX, - TSDB_SHOW_DB_COMP_INDEX, - TSDB_MAX_SHOW_DB -}; - -// -----------------------------------------SHOW TABLES CONFIGURE ------------------------------------- -enum _show_tables_index { - TSDB_SHOW_TABLES_NAME_INDEX, - TSDB_SHOW_TABLES_CREATED_TIME_INDEX, - TSDB_SHOW_TABLES_COLUMNS_INDEX, - TSDB_SHOW_TABLES_METRIC_INDEX, - TSDB_MAX_SHOW_TABLES -}; - -// ---------------------------------- DESCRIBE METRIC CONFIGURE ------------------------------ -enum _describe_table_index { - TSDB_DESCRIBE_METRIC_FIELD_INDEX, - TSDB_DESCRIBE_METRIC_TYPE_INDEX, - TSDB_DESCRIBE_METRIC_LENGTH_INDEX, - TSDB_DESCRIBE_METRIC_NOTE_INDEX, - TSDB_MAX_DESCRIBE_METRIC -}; - -typedef struct { - char field[TSDB_COL_NAME_LEN + 1]; - char type[16]; - int length; - char note[128]; -} SColDes; - -typedef struct { - char name[TSDB_COL_NAME_LEN + 1]; - SColDes cols[]; -} STableDef; - -extern char version[]; - -typedef struct { - char name[TSDB_DB_NAME_LEN + 1]; - int32_t replica; - int32_t days; - int32_t keep; - int32_t tables; - int32_t rows; - int32_t cache; - int32_t ablocks; - int32_t tblocks; - int32_t ctime; - int32_t clog; - int32_t comp; -} SDbInfo; - -typedef struct { - char name[TSDB_TABLE_NAME_LEN + 1]; - char metric[TSDB_TABLE_NAME_LEN + 1]; -} STableRecord; - -typedef struct { - bool isMetric; - STableRecord tableRecord; -} STableRecordInfo; - -typedef struct { - pthread_t threadID; - int32_t threadIndex; - int32_t totalThreads; - char dbName[TSDB_TABLE_NAME_LEN + 1]; - void *taosCon; -} SThreadParaObj; - -static int64_t totalDumpOutRows = 0; - -SDbInfo **dbInfos = NULL; - -const char *argp_program_version = version; -const char *argp_program_bug_address = ""; - -/* Program documentation. */ -static char doc[] = ""; -/* "Argp example #4 -- a program with somewhat more complicated\ */ -/* options\ */ -/* \vThis part of the documentation comes *after* the options;\ */ -/* note that the text is automatically filled, but it's possible\ */ -/* to force a line-break, e.g.\n<-- here."; */ - -/* A description of the arguments we accept. */ -static char args_doc[] = "dbname [tbname ...]\n--databases dbname ...\n--all-databases\n-i inpath\n-o outpath"; - -/* Keys for options without short-options. */ -#define OPT_ABORT 1 /* –abort */ - -/* The options we understand. */ -static struct argp_option options[] = { - // connection option - {"host", 'h', "HOST", 0, "Server host dumping data from. Default is localhost.", 0}, - {"user", 'u', "USER", 0, "User name used to connect to server. Default is root.", 0}, - {"password", 'p', "PASSWORD", 0, "User password to connect to server. Default is taosdata.", 0}, - {"port", 'P', "PORT", 0, "Port to connect", 0}, - {"cversion", 'v', "CVERION", 0, "client version", 0}, - {"mysqlFlag", 'q', "MYSQLFLAG", 0, "mysqlFlag, Default is 0", 0}, - // input/output file - {"outpath", 'o', "OUTPATH", 0, "Output file path.", 1}, - {"inpath", 'i', "INPATH", 0, "Input file path.", 1}, - {"config", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/taos/taos.cfg.", 1}, - {"encode", 'e', "ENCODE", 0, "Input file encoding.", 1}, - // dump unit options - {"all-databases", 'A', 0, 0, "Dump all databases.", 2}, - {"databases", 'B', 0, 0, "Dump assigned databases", 2}, - // dump format options - {"schemaonly", 's', 0, 0, "Only dump schema.", 3}, - {"with-property", 'M', 0, 0, "Dump schema with properties.", 3}, - {"start-time", 'S', "START_TIME", 0, "Start time to dump.", 3}, - {"end-time", 'E', "END_TIME", 0, "End time to dump.", 3}, - {"data-batch", 'N', "DATA_BATCH", 0, "Number of data point per insert statement. Default is 1.", 3}, - {"table-batch", 't', "TABLE_BATCH", 0, "Number of table dumpout into one output file. Default is 1.", 3}, - {"thread_num", 'T', "THREAD_NUM", 0, "Number of thread for dump in file. Default is 5.", 3}, - {"allow-sys", 'a', 0, 0, "Allow to dump sys database", 3}, - {0}}; - -/* Used by main to communicate with parse_opt. */ -struct arguments { - // connection option - char *host; - char *user; - char *password; - uint16_t port; - char cversion[12]; - uint16_t mysqlFlag; - // output file - char outpath[TSDB_FILENAME_LEN+1]; - char inpath[TSDB_FILENAME_LEN+1]; - char *encode; - // dump unit option - bool all_databases; - bool databases; - // dump format option - bool schemaonly; - bool with_property; - int64_t start_time; - int64_t end_time; - int32_t data_batch; - int32_t table_batch; // num of table which will be dump into one output file. - bool allow_sys; - // other options - int32_t thread_num; - int abort; - char **arg_list; - int arg_list_len; - bool isDumpIn; -}; - -/* Parse a single option. */ -static error_t parse_opt(int key, char *arg, struct argp_state *state) { - /* Get the input argument from argp_parse, which we - know is a pointer to our arguments structure. */ - struct arguments *arguments = state->input; - wordexp_t full_path; - - switch (key) { - // connection option - case 'a': - arguments->allow_sys = true; - break; - case 'h': - arguments->host = arg; - break; - case 'u': - arguments->user = arg; - break; - case 'p': - arguments->password = arg; - break; - case 'P': - arguments->port = atoi(arg); - break; - case 'q': - arguments->mysqlFlag = atoi(arg); - break; - case 'v': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid client vesion %s\n", arg); - return -1; - } - tstrncpy(arguments->cversion, full_path.we_wordv[0], 11); - wordfree(&full_path); - break; - // output file path - case 'o': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - tstrncpy(arguments->outpath, full_path.we_wordv[0], TSDB_FILENAME_LEN); - wordfree(&full_path); - break; - case 'i': - arguments->isDumpIn = true; - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - tstrncpy(arguments->inpath, full_path.we_wordv[0], TSDB_FILENAME_LEN); - wordfree(&full_path); - break; - case 'c': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - tstrncpy(configDir, full_path.we_wordv[0], TSDB_FILENAME_LEN); - wordfree(&full_path); - break; - case 'e': - arguments->encode = arg; - break; - // dump unit option - case 'A': - arguments->all_databases = true; - break; - case 'B': - arguments->databases = true; - break; - // dump format option - case 's': - arguments->schemaonly = true; - break; - case 'M': - arguments->with_property = true; - break; - case 'S': - // parse time here. - arguments->start_time = atol(arg); - break; - case 'E': - arguments->end_time = atol(arg); - break; - case 'N': - arguments->data_batch = atoi(arg); - break; - case 't': - arguments->table_batch = atoi(arg); - break; - case 'T': - arguments->thread_num = atoi(arg); - break; - case OPT_ABORT: - arguments->abort = 1; - break; - case ARGP_KEY_ARG: - arguments->arg_list = &state->argv[state->next - 1]; - arguments->arg_list_len = state->argc - state->next + 1; - state->next = state->argc; - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -/* Our argp parser. */ -static struct argp argp = {options, parse_opt, args_doc, doc}; - -int taosDumpOut(struct arguments *arguments); -int taosDumpIn(struct arguments *arguments); -void taosDumpCreateDbClause(SDbInfo *dbInfo, bool isDumpProperty, FILE *fp); -int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *taosCon); -int32_t taosDumpStable(char *table, FILE *fp, TAOS* taosCon); -void taosDumpCreateTableClause(STableDef *tableDes, int numOfCols, FILE *fp); -void taosDumpCreateMTableClause(STableDef *tableDes, char *metric, int numOfCols, FILE *fp); -int32_t taosDumpTable(char *table, char *metric, struct arguments *arguments, FILE *fp, TAOS* taosCon); -int taosDumpTableData(FILE *fp, char *tbname, struct arguments *arguments, TAOS* taosCon); -int taosCheckParam(struct arguments *arguments); -void taosFreeDbInfos(); -static void taosStartDumpOutWorkThreads(struct arguments* args, int32_t numOfThread, char *dbName); - -struct arguments tsArguments = { - // connection option - NULL, - "root", - "taosdata", - 0, - "", - 0, - // outpath and inpath - "", - "", - NULL, - // dump unit option - false, - false, - // dump format option - false, - false, - 0, - INT64_MAX, - 1, - 1, - false, - // other options - 5, - 0, - NULL, - 0, - false -}; - -int queryDB(TAOS *taos, char *command) { - TAOS_RES *pSql = NULL; - int32_t code = -1; - - pSql = taos_query(taos, command); - code = taos_errno(pSql); - if (code) { - fprintf(stderr, "sql error: %s, reason:%s\n", command, taos_errstr(pSql)); - } - taos_free_result(pSql); - return code; -} - -int main(int argc, char *argv[]) { - - /* Parse our arguments; every option seen by parse_opt will be - reflected in arguments. */ - argp_parse(&argp, argc, argv, 0, 0, &tsArguments); - - if (tsArguments.abort) { - #ifndef _ALPINE - error(10, 0, "ABORTED"); - #else - abort(); - #endif - } - - printf("====== arguments config ======\n"); - { - printf("host: %s\n", tsArguments.host); - printf("user: %s\n", tsArguments.user); - printf("password: %s\n", tsArguments.password); - printf("port: %u\n", tsArguments.port); - printf("cversion: %s\n", tsArguments.cversion); - printf("mysqlFlag: %d\n", tsArguments.mysqlFlag); - printf("outpath: %s\n", tsArguments.outpath); - printf("inpath: %s\n", tsArguments.inpath); - printf("encode: %s\n", tsArguments.encode); - printf("all_databases: %d\n", tsArguments.all_databases); - printf("databases: %d\n", tsArguments.databases); - printf("schemaonly: %d\n", tsArguments.schemaonly); - printf("with_property: %d\n", tsArguments.with_property); - printf("start_time: %" PRId64 "\n", tsArguments.start_time); - printf("end_time: %" PRId64 "\n", tsArguments.end_time); - printf("data_batch: %d\n", tsArguments.data_batch); - printf("table_batch: %d\n", tsArguments.table_batch); - printf("allow_sys: %d\n", tsArguments.allow_sys); - printf("abort: %d\n", tsArguments.abort); - printf("isDumpIn: %d\n", tsArguments.isDumpIn); - printf("arg_list_len: %d\n", tsArguments.arg_list_len); - - for (int32_t i = 0; i < tsArguments.arg_list_len; i++) { - printf("arg_list[%d]: %s\n", i, tsArguments.arg_list[i]); - } - } - printf("==============================\n"); - - if (tsArguments.cversion[0] != 0){ - tstrncpy(version, tsArguments.cversion, 11); - } - - if (taosCheckParam(&tsArguments) < 0) { - exit(EXIT_FAILURE); - } - - if (tsArguments.isDumpIn) { - if (taosDumpIn(&tsArguments) < 0) return -1; - } else { - if (taosDumpOut(&tsArguments) < 0) return -1; - } - - return 0; -} - -void taosFreeDbInfos() { - if (dbInfos == NULL) return; - for (int i = 0; i < 128; i++) taosTFree(dbInfos[i]); - taosTFree(dbInfos); -} - -// check table is normal table or super table -int taosGetTableRecordInfo(char *table, STableRecordInfo *pTableRecordInfo, TAOS *taosCon) { - TAOS_ROW row = NULL; - bool isSet = false; - TAOS_RES *result = NULL; - - memset(pTableRecordInfo, 0, sizeof(STableRecordInfo)); - - char* tempCommand = (char *)malloc(COMMAND_SIZE); - if (tempCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - sprintf(tempCommand, "show tables like %s", table); - - result = taos_query(taosCon, tempCommand); - int32_t code = taos_errno(result); - - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - taos_free_result(result); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - - while ((row = taos_fetch_row(result)) != NULL) { - isSet = true; - pTableRecordInfo->isMetric = false; - strncpy(pTableRecordInfo->tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], - fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - strncpy(pTableRecordInfo->tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX], - fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes); - break; - } - - taos_free_result(result); - result = NULL; - - if (isSet) { - free(tempCommand); - return 0; - } - - sprintf(tempCommand, "show stables like %s", table); - - result = taos_query(taosCon, tempCommand); - code = taos_errno(result); - - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - taos_free_result(result); - return -1; - } - - while ((row = taos_fetch_row(result)) != NULL) { - isSet = true; - pTableRecordInfo->isMetric = true; - tstrncpy(pTableRecordInfo->tableRecord.metric, table, TSDB_TABLE_NAME_LEN); - break; - } - - taos_free_result(result); - result = NULL; - - if (isSet) { - free(tempCommand); - return 0; - } - fprintf(stderr, "invalid table/metric %s\n", table); - free(tempCommand); - return -1; -} - - -int32_t taosSaveAllNormalTableToTempFile(TAOS *taosCon, char*meter, char* metric, int* fd) { - STableRecord tableRecord; - - if (-1 == *fd) { - *fd = open(".tables.tmp.0", O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (*fd == -1) { - fprintf(stderr, "failed to open temp file: .tables.tmp.0\n"); - return -1; - } - } - - memset(&tableRecord, 0, sizeof(STableRecord)); - tstrncpy(tableRecord.name, meter, TSDB_TABLE_NAME_LEN); - tstrncpy(tableRecord.metric, metric, TSDB_TABLE_NAME_LEN); - - taosTWrite(*fd, &tableRecord, sizeof(STableRecord)); - return 0; -} - - -int32_t taosSaveTableOfMetricToTempFile(TAOS *taosCon, char* metric, struct arguments *arguments, int32_t* totalNumOfThread) { - TAOS_ROW row; - int fd = -1; - STableRecord tableRecord; - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - sprintf(tmpCommand, "select tbname from %s", metric); - - TAOS_RES *result = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(result); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tmpCommand); - free(tmpCommand); - taos_free_result(result); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - - int32_t numOfTable = 0; - int32_t numOfThread = *totalNumOfThread; - char tmpFileName[TSDB_FILENAME_LEN + 1]; - while ((row = taos_fetch_row(result)) != NULL) { - if (0 == numOfTable) { - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, ".tables.tmp.%d", numOfThread); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "failed to open temp file: %s\n", tmpFileName); - taos_free_result(result); - for (int32_t loopCnt = 0; loopCnt < numOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - (void)remove(tmpFileName); - } - free(tmpCommand); - return -1; - } - - numOfThread++; - } - - memset(&tableRecord, 0, sizeof(STableRecord)); - tstrncpy(tableRecord.name, (char *)row[0], fields[0].bytes); - tstrncpy(tableRecord.metric, metric, TSDB_TABLE_NAME_LEN); - - taosTWrite(fd, &tableRecord, sizeof(STableRecord)); - - numOfTable++; - - if (numOfTable >= arguments->table_batch) { - numOfTable = 0; - close(fd); - fd = -1; - } - } - - if (fd >= 0) { - close(fd); - fd = -1; - } - - taos_free_result(result); - - *totalNumOfThread = numOfThread; - - free(tmpCommand); - - return 0; -} - -int taosDumpOut(struct arguments *arguments) { - TAOS *taos = NULL; - TAOS_RES *result = NULL; - char *command = NULL; - - TAOS_ROW row; - FILE *fp = NULL; - int32_t count = 0; - STableRecordInfo tableRecordInfo; - - char tmpBuf[TSDB_FILENAME_LEN+9] = {0}; - if (arguments->outpath[0] != 0) { - sprintf(tmpBuf, "%s/dbs.sql", arguments->outpath); - } else { - sprintf(tmpBuf, "dbs.sql"); - } - - fp = fopen(tmpBuf, "w"); - if (fp == NULL) { - fprintf(stderr, "failed to open file %s\n", tmpBuf); - return -1; - } - - dbInfos = (SDbInfo **)calloc(128, sizeof(SDbInfo *)); - if (dbInfos == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - goto _exit_failure; - } - - command = (char *)malloc(COMMAND_SIZE); - if (command == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - goto _exit_failure; - } - - /* Connect to server */ - taos = taos_connect(arguments->host, arguments->user, arguments->password, NULL, arguments->port); - if (taos == NULL) { - fprintf(stderr, "failed to connect to TDengine server\n"); - goto _exit_failure; - } - - /* --------------------------------- Main Code -------------------------------- */ - /* if (arguments->databases || arguments->all_databases) { // dump part of databases or all databases */ - /* */ - taosDumpCharset(fp); - - sprintf(command, "show databases"); - result = taos_query(taos, command); - int32_t code = taos_errno(result); - - if (code != 0) { - fprintf(stderr, "failed to run command: %s, reason: %s\n", command, taos_errstr(taos)); - goto _exit_failure; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - - while ((row = taos_fetch_row(result)) != NULL) { - // sys database name : 'monitor', but subsequent version changed to 'log' - if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "monitor", fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0 && - (!arguments->allow_sys)) - continue; - - if (arguments->databases) { // input multi dbs - for (int i = 0; arguments->arg_list[i]; i++) { - if (strncasecmp(arguments->arg_list[i], (char *)row[TSDB_SHOW_DB_NAME_INDEX], - fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) - goto _dump_db_point; - } - continue; - } else if (!arguments->all_databases) { // only input one db - if (strncasecmp(arguments->arg_list[0], (char *)row[TSDB_SHOW_DB_NAME_INDEX], - fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) - goto _dump_db_point; - else - continue; - } - - _dump_db_point: - - dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo)); - if (dbInfos[count] == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - goto _exit_failure; - } - - strncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX], fields[TSDB_SHOW_DB_NAME_INDEX].bytes); - #if 0 - dbInfos[count]->replica = (int)(*((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX])); - dbInfos[count]->days = (int)(*((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX])); - dbInfos[count]->keep = *((int *)row[TSDB_SHOW_DB_KEEP_INDEX]); - dbInfos[count]->tables = *((int *)row[TSDB_SHOW_DB_TABLES_INDEX]); - dbInfos[count]->rows = *((int *)row[TSDB_SHOW_DB_ROWS_INDEX]); - dbInfos[count]->cache = *((int *)row[TSDB_SHOW_DB_CACHE_INDEX]); - dbInfos[count]->ablocks = *((int *)row[TSDB_SHOW_DB_ABLOCKS_INDEX]); - dbInfos[count]->tblocks = (int)(*((int16_t *)row[TSDB_SHOW_DB_TBLOCKS_INDEX])); - dbInfos[count]->ctime = *((int *)row[TSDB_SHOW_DB_CTIME_INDEX]); - dbInfos[count]->clog = (int)(*((int8_t *)row[TSDB_SHOW_DB_CLOG_INDEX])); - dbInfos[count]->comp = (int)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX])); -#endif - - count++; - - if (arguments->databases) { - if (count > arguments->arg_list_len) break; - - } else if (!arguments->all_databases) { - if (count >= 1) break; - } - } - - if (count == 0) { - fprintf(stderr, "No databases valid to dump\n"); - goto _exit_failure; - } - - if (arguments->databases || arguments->all_databases) { // case: taosdump --databases dbx dby ... OR taosdump --all-databases - for (int i = 0; i < count; i++) { - taosDumpDb(dbInfos[i], arguments, fp, taos); - } - } else { - if (arguments->arg_list_len == 1) { // case: taosdump - taosDumpDb(dbInfos[0], arguments, fp, taos); - } else { // case: taosdump tablex tabley ... - taosDumpCreateDbClause(dbInfos[0], arguments->with_property, fp); - - sprintf(command, "use %s", dbInfos[0]->name); - - result = taos_query(taos, command); - int32_t code = taos_errno(result); - if (code != 0) { - fprintf(stderr, "invalid database %s\n", dbInfos[0]->name); - goto _exit_failure; - } - - fprintf(fp, "USE %s;\n\n", dbInfos[0]->name); - - int32_t totalNumOfThread = 1; // 0: all normal talbe into .tables.tmp.0 - int normalTblFd = -1; - int32_t retCode; - for (int i = 1; arguments->arg_list[i]; i++) { - if (taosGetTableRecordInfo(arguments->arg_list[i], &tableRecordInfo, taos) < 0) { - fprintf(stderr, "input the invalide table %s\n", arguments->arg_list[i]); - continue; - } - - if (tableRecordInfo.isMetric) { // dump all table of this metric - (void)taosDumpStable(tableRecordInfo.tableRecord.metric, fp, taos); - retCode = taosSaveTableOfMetricToTempFile(taos, tableRecordInfo.tableRecord.metric, arguments, &totalNumOfThread); - } else { - if (tableRecordInfo.tableRecord.metric[0] != '\0') { // dump this sub table and it's metric - (void)taosDumpStable(tableRecordInfo.tableRecord.metric, fp, taos); - } - retCode = taosSaveAllNormalTableToTempFile(taos, tableRecordInfo.tableRecord.name, tableRecordInfo.tableRecord.metric, &normalTblFd); - } - - if (retCode < 0) { - if (-1 != normalTblFd){ - taosClose(normalTblFd); - } - goto _clean_tmp_file; - } - } - - if (-1 != normalTblFd){ - taosClose(normalTblFd); - } - - // start multi threads to dumpout - taosStartDumpOutWorkThreads(arguments, totalNumOfThread, dbInfos[0]->name); - - char tmpFileName[TSDB_FILENAME_LEN + 1]; - _clean_tmp_file: - for (int loopCnt = 0; loopCnt < totalNumOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - remove(tmpFileName); - } - } - } - - /* Close the handle and return */ - fclose(fp); - taos_close(taos); - taos_free_result(result); - taosTFree(command); - taosFreeDbInfos(); - fprintf(stderr, "dump out rows: %" PRId64 "\n", totalDumpOutRows); - return 0; - -_exit_failure: - fclose(fp); - taos_close(taos); - taos_free_result(result); - taosTFree(command); - taosFreeDbInfos(); - fprintf(stderr, "dump out rows: %" PRId64 "\n", totalDumpOutRows); - return -1; -} - -int taosGetTableDes(char *table, STableDef *tableDes, TAOS* taosCon, bool isSuperTable) { - TAOS_ROW row = NULL; - TAOS_RES *tmpResult = NULL; - int count = 0; - - char* tempCommand = (char *)malloc(COMMAND_SIZE); - if (tempCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - char* tbuf = (char *)malloc(COMMAND_SIZE); - if (tbuf == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - free(tempCommand); - return -1; - } - - sprintf(tempCommand, "describe %s", table); - - tmpResult = taos_query(taosCon, tempCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - free(tbuf); - taos_free_result(tmpResult); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - - tstrncpy(tableDes->name, table, TSDB_COL_NAME_LEN); - - while ((row = taos_fetch_row(tmpResult)) != NULL) { - strncpy(tableDes->cols[count].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX], - fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); - strncpy(tableDes->cols[count].type, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], - fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes); - tableDes->cols[count].length = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); - strncpy(tableDes->cols[count].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], - fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes); - - count++; - } - - taos_free_result(tmpResult); - tmpResult = NULL; - - if (isSuperTable) { - free(tempCommand); - free(tbuf); - return count; - } - - // if chidl-table have tag, using select tagName from table to get tagValue - for (int i = 0 ; i < count; i++) { - if (strcmp(tableDes->cols[i].note, "TAG") != 0) continue; - - - sprintf(tempCommand, "select %s from %s", tableDes->cols[i].field, table); - - tmpResult = taos_query(taosCon, tempCommand); - code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - free(tbuf); - taos_free_result(tmpResult); - return -1; - } - - fields = taos_fetch_fields(tmpResult); - - row = taos_fetch_row(tmpResult); - if (NULL == row) { - fprintf(stderr, " fetch failed to run command %s\n", tempCommand); - free(tempCommand); - free(tbuf); - taos_free_result(tmpResult); - return -1; - } - - switch (fields[0].type) { - case TSDB_DATA_TYPE_BOOL: - sprintf(tableDes->cols[i].note, "%d", ((((int)(*((char *)row[0]))) == 1) ? 1 : 0)); - break; - case TSDB_DATA_TYPE_TINYINT: - sprintf(tableDes->cols[i].note, "%d", (int)(*((char *)row[0]))); - break; - case TSDB_DATA_TYPE_SMALLINT: - sprintf(tableDes->cols[i].note, "%d", (int)(*((short *)row[0]))); - break; - case TSDB_DATA_TYPE_INT: - sprintf(tableDes->cols[i].note, "%d", *((int *)row[0])); - break; - case TSDB_DATA_TYPE_BIGINT: - sprintf(tableDes->cols[i].note, "%" PRId64 "", *((int64_t *)row[0])); - break; - case TSDB_DATA_TYPE_FLOAT: - sprintf(tableDes->cols[i].note, "%f", GET_FLOAT_VAL(row[0])); - break; - case TSDB_DATA_TYPE_DOUBLE: - sprintf(tableDes->cols[i].note, "%f", GET_DOUBLE_VAL(row[0])); - break; - case TSDB_DATA_TYPE_BINARY: - tableDes->cols[i].note[0] = '\''; - converStringToReadable((char *)row[0], fields[0].bytes, tbuf, COMMAND_SIZE); - char* pstr = stpcpy(&(tableDes->cols[i].note[1]), tbuf); - *(pstr++) = '\''; - break; - case TSDB_DATA_TYPE_NCHAR: - convertNCharToReadable((char *)row[0], fields[0].bytes, tbuf, COMMAND_SIZE); - sprintf(tableDes->cols[i].note, "\'%s\'", tbuf); - break; - case TSDB_DATA_TYPE_TIMESTAMP: - sprintf(tableDes->cols[i].note, "%" PRId64 "", *(int64_t *)row[0]); - #if 0 - if (!arguments->mysqlFlag) { - sprintf(tableDes->cols[i].note, "%" PRId64 "", *(int64_t *)row[0]); - } else { - char buf[64] = "\0"; - int64_t ts = *((int64_t *)row[0]); - time_t tt = (time_t)(ts / 1000); - struct tm *ptm = localtime(&tt); - strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); - sprintf(tableDes->cols[i].note, "\'%s.%03d\'", buf, (int)(ts % 1000)); - } - #endif - break; - default: - break; - } - - taos_free_result(tmpResult); - tmpResult = NULL; - } - - free(tempCommand); - free(tbuf); - - return count; -} - -int32_t taosDumpTable(char *table, char *metric, struct arguments *arguments, FILE *fp, TAOS* taosCon) { - int count = 0; - - STableDef *tableDes = (STableDef *)calloc(1, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS); - - if (metric != NULL && metric[0] != '\0') { // dump table schema which is created by using super table - /* - count = taosGetTableDes(metric, tableDes, taosCon); - - if (count < 0) { - free(tableDes); - return -1; - } - - taosDumpCreateTableClause(tableDes, count, fp); - - memset(tableDes, 0, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS); - */ - - count = taosGetTableDes(table, tableDes, taosCon, false); - - if (count < 0) { - free(tableDes); - return -1; - } - - // create child-table using super-table - taosDumpCreateMTableClause(tableDes, metric, count, fp); - - } else { // dump table definition - count = taosGetTableDes(table, tableDes, taosCon, false); - - if (count < 0) { - free(tableDes); - return -1; - } - - // create normal-table or super-table - taosDumpCreateTableClause(tableDes, count, fp); - } - - free(tableDes); - - return taosDumpTableData(fp, table, arguments, taosCon); -} - -void taosDumpCreateDbClause(SDbInfo *dbInfo, bool isDumpProperty, FILE *fp) { - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return; - } - - char *pstr = tmpCommand; - - pstr += sprintf(pstr, "CREATE DATABASE IF NOT EXISTS %s", dbInfo->name); - if (isDumpProperty) { - pstr += sprintf(pstr, - " REPLICA %d DAYS %d KEEP %d TABLES %d ROWS %d CACHE %d ABLOCKS %d TBLOCKS %d CTIME %d CLOG %d COMP %d", - dbInfo->replica, dbInfo->days, dbInfo->keep, dbInfo->tables, dbInfo->rows, dbInfo->cache, - dbInfo->ablocks, dbInfo->tblocks, dbInfo->ctime, dbInfo->clog, dbInfo->comp); - } - - pstr += sprintf(pstr, ";"); - - fprintf(fp, "%s\n\n", tmpCommand); - free(tmpCommand); -} - -void* taosDumpOutWorkThreadFp(void *arg) -{ - SThreadParaObj *pThread = (SThreadParaObj*)arg; - STableRecord tableRecord; - int fd; - - char tmpFileName[TSDB_FILENAME_LEN*4] = {0}; - sprintf(tmpFileName, ".tables.tmp.%d", pThread->threadIndex); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "taosDumpTableFp() failed to open temp file: %s\n", tmpFileName); - return NULL; - } - - FILE *fp = NULL; - memset(tmpFileName, 0, TSDB_FILENAME_LEN + 128); - - if (tsArguments.outpath[0] != 0) { - sprintf(tmpFileName, "%s/%s.tables.%d.sql", tsArguments.outpath, pThread->dbName, pThread->threadIndex); - } else { - sprintf(tmpFileName, "%s.tables.%d.sql", pThread->dbName, pThread->threadIndex); - } - - fp = fopen(tmpFileName, "w"); - if (fp == NULL) { - fprintf(stderr, "failed to open file %s\n", tmpFileName); - close(fd); - return NULL; - } - - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, "use %s", pThread->dbName); - - TAOS_RES* tmpResult = taos_query(pThread->taosCon, tmpFileName); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "invalid database %s\n", pThread->dbName); - taos_free_result(tmpResult); - fclose(fp); - close(fd); - return NULL; - } - - fprintf(fp, "USE %s\n\n", pThread->dbName); - while (1) { - ssize_t readLen = read(fd, &tableRecord, sizeof(STableRecord)); - if (readLen <= 0) break; - taosDumpTable(tableRecord.name, tableRecord.metric, &tsArguments, fp, pThread->taosCon); - } - - taos_free_result(tmpResult); - close(fd); - fclose(fp); - - return NULL; -} - -static void taosStartDumpOutWorkThreads(struct arguments* args, int32_t numOfThread, char *dbName) -{ - pthread_attr_t thattr; - SThreadParaObj *threadObj = (SThreadParaObj *)calloc(numOfThread, sizeof(SThreadParaObj)); - for (int t = 0; t < numOfThread; ++t) { - SThreadParaObj *pThread = threadObj + t; - pThread->threadIndex = t; - pThread->totalThreads = numOfThread; - tstrncpy(pThread->dbName, dbName, TSDB_TABLE_NAME_LEN); - pThread->taosCon = taos_connect(args->host, args->user, args->password, NULL, args->port); - - if (pThread->taosCon == NULL) { - fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taosCon)); - exit(0); - } - - pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); - - if (pthread_create(&(pThread->threadID), &thattr, taosDumpOutWorkThreadFp, (void*)pThread) != 0) { - fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex); - exit(0); - } - } - - for (int32_t t = 0; t < numOfThread; ++t) { - pthread_join(threadObj[t].threadID, NULL); - } - - for (int32_t t = 0; t < numOfThread; ++t) { - taos_close(threadObj[t].taosCon); - } - free(threadObj); -} - - - -int32_t taosDumpStable(char *table, FILE *fp, TAOS* taosCon) { - int count = 0; - - STableDef *tableDes = (STableDef *)calloc(1, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS); - if (NULL == tableDes) { - fprintf(stderr, "failed to allocate memory\n"); - exit(-1); - } - - count = taosGetTableDes(table, tableDes, taosCon, true); - - if (count < 0) { - free(tableDes); - fprintf(stderr, "failed to get stable schema\n"); - exit(-1); - } - - taosDumpCreateTableClause(tableDes, count, fp); - - free(tableDes); - return 0; -} - - -int32_t taosDumpCreateSuperTableClause(TAOS* taosCon, char* dbName, FILE *fp) -{ - TAOS_ROW row; - int fd = -1; - STableRecord tableRecord; - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - exit(-1); - } - - sprintf(tmpCommand, "use %s", dbName); - - TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "invalid database %s, error: %s\n", dbName, taos_errstr(taosCon)); - free(tmpCommand); - taos_free_result(tmpResult); - exit(-1); - } - - taos_free_result(tmpResult); - - sprintf(tmpCommand, "show stables"); - - tmpResult = taos_query(taosCon, tmpCommand); - code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s, error: %s\n", tmpCommand, taos_errstr(taosCon)); - free(tmpCommand); - taos_free_result(tmpResult); - exit(-1); - } - - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - - char tmpFileName[TSDB_FILENAME_LEN + 1]; - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, ".stables.tmp"); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "failed to open temp file: %s\n", tmpFileName); - taos_free_result(tmpResult); - free(tmpCommand); - (void)remove(".stables.tmp"); - exit(-1); - } - - while ((row = taos_fetch_row(tmpResult)) != NULL) { - memset(&tableRecord, 0, sizeof(STableRecord)); - strncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - taosTWrite(fd, &tableRecord, sizeof(STableRecord)); - } - - taos_free_result(tmpResult); - (void)lseek(fd, 0, SEEK_SET); - - while (1) { - ssize_t readLen = read(fd, &tableRecord, sizeof(STableRecord)); - if (readLen <= 0) break; - - (void)taosDumpStable(tableRecord.name, fp, taosCon); - } - - close(fd); - (void)remove(".stables.tmp"); - - free(tmpCommand); - return 0; -} - - -int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *taosCon) { - TAOS_ROW row; - int fd = -1; - STableRecord tableRecord; - - taosDumpCreateDbClause(dbInfo, arguments->with_property, fp); - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - sprintf(tmpCommand, "use %s", dbInfo->name); - - TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "invalid database %s\n", dbInfo->name); - free(tmpCommand); - taos_free_result(tmpResult); - return -1; - } - taos_free_result(tmpResult); - - fprintf(fp, "USE %s\n\n", dbInfo->name); - - (void)taosDumpCreateSuperTableClause(taosCon, dbInfo->name, fp); - - sprintf(tmpCommand, "show tables"); - - tmpResult = taos_query(taosCon, tmpCommand); - code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tmpCommand); - free(tmpCommand); - taos_free_result(tmpResult); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - - int32_t numOfTable = 0; - int32_t numOfThread = 0; - char tmpFileName[TSDB_FILENAME_LEN + 1]; - while ((row = taos_fetch_row(tmpResult)) != NULL) { - if (0 == numOfTable) { - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, ".tables.tmp.%d", numOfThread); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "failed to open temp file: %s\n", tmpFileName); - taos_free_result(tmpResult); - for (int32_t loopCnt = 0; loopCnt < numOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - (void)remove(tmpFileName); - } - free(tmpCommand); - return -1; - } - - numOfThread++; - } - - memset(&tableRecord, 0, sizeof(STableRecord)); - tstrncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - tstrncpy(tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX], fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes); - - taosTWrite(fd, &tableRecord, sizeof(STableRecord)); - - numOfTable++; - - if (numOfTable >= arguments->table_batch) { - numOfTable = 0; - close(fd); - fd = -1; - } - } - - if (fd >= 0) { - close(fd); - fd = -1; - } - - taos_free_result(tmpResult); - - // start multi threads to dumpout - taosStartDumpOutWorkThreads(arguments, numOfThread, dbInfo->name); - for (int loopCnt = 0; loopCnt < numOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - (void)remove(tmpFileName); - } - - free(tmpCommand); - - return 0; -} - -void taosDumpCreateTableClause(STableDef *tableDes, int numOfCols, FILE *fp) { - int counter = 0; - int count_temp = 0; - - char* tmpBuf = (char *)malloc(COMMAND_SIZE); - if (tmpBuf == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return; - } - - char* pstr = tmpBuf; - - pstr += sprintf(tmpBuf, "CREATE TABLE IF NOT EXISTS %s", tableDes->name); - - for (; counter < numOfCols; counter++) { - if (tableDes->cols[counter].note[0] != '\0') break; - - if (counter == 0) { - pstr += sprintf(pstr, " (%s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } else { - pstr += sprintf(pstr, ", %s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } - - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); - } - } - - count_temp = counter; - - for (; counter < numOfCols; counter++) { - if (counter == count_temp) { - pstr += sprintf(pstr, ") TAGS (%s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } else { - pstr += sprintf(pstr, ", %s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } - - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); - } - } - - pstr += sprintf(pstr, ");"); - - fprintf(fp, "%s\n", tmpBuf); - - free(tmpBuf); -} - -void taosDumpCreateMTableClause(STableDef *tableDes, char *metric, int numOfCols, FILE *fp) { - int counter = 0; - int count_temp = 0; - - char* tmpBuf = (char *)malloc(COMMAND_SIZE); - if (tmpBuf == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return; - } - - char *pstr = NULL; - pstr = tmpBuf; - - pstr += sprintf(tmpBuf, "CREATE TABLE IF NOT EXISTS %s USING %s TAGS (", tableDes->name, metric); - - for (; counter < numOfCols; counter++) { - if (tableDes->cols[counter].note[0] != '\0') break; - } - - assert(counter < numOfCols); - count_temp = counter; - - for (; counter < numOfCols; counter++) { - if (counter != count_temp) { - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - //pstr += sprintf(pstr, ", \'%s\'", tableDes->cols[counter].note); - pstr += sprintf(pstr, ", %s", tableDes->cols[counter].note); - } else { - pstr += sprintf(pstr, ", %s", tableDes->cols[counter].note); - } - } else { - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - //pstr += sprintf(pstr, "\'%s\'", tableDes->cols[counter].note); - pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); - } else { - pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); - } - /* pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); */ - } - - /* if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || strcasecmp(tableDes->cols[counter].type, "nchar") - * == 0) { */ - /* pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); */ - /* } */ - } - - pstr += sprintf(pstr, ");"); - - fprintf(fp, "%s\n", tmpBuf); - free(tmpBuf); -} - -int taosDumpTableData(FILE *fp, char *tbname, struct arguments *arguments, TAOS* taosCon) { - /* char temp[MAX_COMMAND_SIZE] = "\0"; */ - int64_t totalRows = 0; - int count = 0; - char *pstr = NULL; - TAOS_ROW row = NULL; - int numFields = 0; - char *tbuf = NULL; - - char* tmpCommand = (char *)calloc(1, COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - char* tmpBuffer = (char *)calloc(1, COMMAND_SIZE); - if (tmpBuffer == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - free(tmpCommand); - return -1; - } - - pstr = tmpBuffer; - - if (arguments->schemaonly) { - free(tmpCommand); - free(tmpBuffer); - return 0; - } - - sprintf(tmpCommand, - "select * from %s where _c0 >= %" PRId64 " and _c0 <= %" PRId64 " order by _c0 asc", - tbname, - arguments->start_time, - arguments->end_time); - - TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s, reason: %s\n", tmpCommand, taos_errstr(taosCon)); - free(tmpCommand); - free(tmpBuffer); - taos_free_result(tmpResult); - return -1; - } - - numFields = taos_field_count(tmpResult); - assert(numFields > 0); - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - tbuf = (char *)malloc(COMMAND_SIZE); - if (tbuf == NULL) { - fprintf(stderr, "No enough memory\n"); - free(tmpCommand); - free(tmpBuffer); - taos_free_result(tmpResult); - return -1; - } - - char sqlStr[8] = "\0"; - if (arguments->mysqlFlag) { - sprintf(sqlStr, "INSERT"); - } else { - sprintf(sqlStr, "IMPORT"); - } - - int rowFlag = 0; - count = 0; - while ((row = taos_fetch_row(tmpResult)) != NULL) { - pstr = tmpBuffer; - - if (count == 0) { - pstr += sprintf(pstr, "%s INTO %s VALUES (", sqlStr, tbname); - } else { - if (arguments->mysqlFlag) { - if (0 == rowFlag) { - pstr += sprintf(pstr, "("); - rowFlag++; - } else { - pstr += sprintf(pstr, ", ("); - } - } else { - pstr += sprintf(pstr, "("); - } - } - - for (int col = 0; col < numFields; col++) { - if (col != 0) pstr += sprintf(pstr, ", "); - - if (row[col] == NULL) { - pstr += sprintf(pstr, "NULL"); - continue; - } - - switch (fields[col].type) { - case TSDB_DATA_TYPE_BOOL: - pstr += sprintf(pstr, "%d", ((((int)(*((char *)row[col]))) == 1) ? 1 : 0)); - break; - case TSDB_DATA_TYPE_TINYINT: - pstr += sprintf(pstr, "%d", (int)(*((char *)row[col]))); - break; - case TSDB_DATA_TYPE_SMALLINT: - pstr += sprintf(pstr, "%d", (int)(*((short *)row[col]))); - break; - case TSDB_DATA_TYPE_INT: - pstr += sprintf(pstr, "%d", *((int *)row[col])); - break; - case TSDB_DATA_TYPE_BIGINT: - pstr += sprintf(pstr, "%" PRId64 "", *((int64_t *)row[col])); - break; - case TSDB_DATA_TYPE_FLOAT: - pstr += sprintf(pstr, "%f", GET_FLOAT_VAL(row[col])); - break; - case TSDB_DATA_TYPE_DOUBLE: - pstr += sprintf(pstr, "%f", GET_DOUBLE_VAL(row[col])); - break; - case TSDB_DATA_TYPE_BINARY: - *(pstr++) = '\''; - converStringToReadable((char *)row[col], fields[col].bytes, tbuf, COMMAND_SIZE); - pstr = stpcpy(pstr, tbuf); - *(pstr++) = '\''; - break; - case TSDB_DATA_TYPE_NCHAR: - convertNCharToReadable((char *)row[col], fields[col].bytes, tbuf, COMMAND_SIZE); - pstr += sprintf(pstr, "\'%s\'", tbuf); - break; - case TSDB_DATA_TYPE_TIMESTAMP: - if (!arguments->mysqlFlag) { - pstr += sprintf(pstr, "%" PRId64 "", *(int64_t *)row[col]); - } else { - char buf[64] = "\0"; - int64_t ts = *((int64_t *)row[col]); - time_t tt = (time_t)(ts / 1000); - struct tm *ptm = localtime(&tt); - strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); - pstr += sprintf(pstr, "\'%s.%03d\'", buf, (int)(ts % 1000)); - } - break; - default: - break; - } - } - - pstr += sprintf(pstr, ") "); - - totalRows++; - count++; - fprintf(fp, "%s", tmpBuffer); - - if (count >= arguments->data_batch) { - fprintf(fp, ";\n"); - count = 0; - } //else { - //fprintf(fp, "\\\n"); - //} - } - - atomic_add_fetch_64(&totalDumpOutRows, totalRows); - - fprintf(fp, "\n"); - - if (tbuf) { - free(tbuf); - } - - taos_free_result(tmpResult); - tmpResult = NULL; - free(tmpCommand); - free(tmpBuffer); - return 0; -} - -int taosCheckParam(struct arguments *arguments) { - if (arguments->all_databases && arguments->databases) { - fprintf(stderr, "conflict option --all-databases and --databases\n"); - return -1; - } - - if (arguments->start_time > arguments->end_time) { - fprintf(stderr, "start time is larger than end time\n"); - return -1; - } - - if (arguments->arg_list_len == 0) { - if ((!arguments->all_databases) && (!arguments->isDumpIn)) { - fprintf(stderr, "taosdump requires parameters\n"); - return -1; - } - } -/* - if (arguments->isDumpIn && (strcmp(arguments->outpath, DEFAULT_DUMP_FILE) != 0)) { - fprintf(stderr, "duplicate parameter input and output file path\n"); - return -1; - } -*/ - if (!arguments->isDumpIn && arguments->encode != NULL) { - fprintf(stderr, "invalid option in dump out\n"); - return -1; - } - - if (arguments->table_batch <= 0) { - fprintf(stderr, "invalid option in dump out\n"); - return -1; - } - - return 0; -} - -bool isEmptyCommand(char *cmd) { - char *pchar = cmd; - - while (*pchar != '\0') { - if (*pchar != ' ') return false; - pchar++; - } - - return true; -} - -void taosReplaceCtrlChar(char *str) { - _Bool ctrlOn = false; - char *pstr = NULL; - - for (pstr = str; *str != '\0'; ++str) { - if (ctrlOn) { - switch (*str) { - case 'n': - *pstr = '\n'; - pstr++; - break; - case 'r': - *pstr = '\r'; - pstr++; - break; - case 't': - *pstr = '\t'; - pstr++; - break; - case '\\': - *pstr = '\\'; - pstr++; - break; - case '\'': - *pstr = '\''; - pstr++; - break; - default: - break; - } - ctrlOn = false; - } else { - if (*str == '\\') { - ctrlOn = true; - } else { - *pstr = *str; - pstr++; - } - } - } - - *pstr = '\0'; -} - -char *ascii_literal_list[] = { - "\\x00", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\x07", "\\x08", "\\t", "\\n", "\\x0b", "\\x0c", - "\\r", "\\x0e", "\\x0f", "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17", "\\x18", "\\x19", - "\\x1a", "\\x1b", "\\x1c", "\\x1d", "\\x1e", "\\x1f", " ", "!", "\\\"", "#", "$", "%", "&", - "\\'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", - "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "[", "\\\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", - "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", - "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\\x7f", "\\x80", "\\x81", - "\\x82", "\\x83", "\\x84", "\\x85", "\\x86", "\\x87", "\\x88", "\\x89", "\\x8a", "\\x8b", "\\x8c", "\\x8d", "\\x8e", - "\\x8f", "\\x90", "\\x91", "\\x92", "\\x93", "\\x94", "\\x95", "\\x96", "\\x97", "\\x98", "\\x99", "\\x9a", "\\x9b", - "\\x9c", "\\x9d", "\\x9e", "\\x9f", "\\xa0", "\\xa1", "\\xa2", "\\xa3", "\\xa4", "\\xa5", "\\xa6", "\\xa7", "\\xa8", - "\\xa9", "\\xaa", "\\xab", "\\xac", "\\xad", "\\xae", "\\xaf", "\\xb0", "\\xb1", "\\xb2", "\\xb3", "\\xb4", "\\xb5", - "\\xb6", "\\xb7", "\\xb8", "\\xb9", "\\xba", "\\xbb", "\\xbc", "\\xbd", "\\xbe", "\\xbf", "\\xc0", "\\xc1", "\\xc2", - "\\xc3", "\\xc4", "\\xc5", "\\xc6", "\\xc7", "\\xc8", "\\xc9", "\\xca", "\\xcb", "\\xcc", "\\xcd", "\\xce", "\\xcf", - "\\xd0", "\\xd1", "\\xd2", "\\xd3", "\\xd4", "\\xd5", "\\xd6", "\\xd7", "\\xd8", "\\xd9", "\\xda", "\\xdb", "\\xdc", - "\\xdd", "\\xde", "\\xdf", "\\xe0", "\\xe1", "\\xe2", "\\xe3", "\\xe4", "\\xe5", "\\xe6", "\\xe7", "\\xe8", "\\xe9", - "\\xea", "\\xeb", "\\xec", "\\xed", "\\xee", "\\xef", "\\xf0", "\\xf1", "\\xf2", "\\xf3", "\\xf4", "\\xf5", "\\xf6", - "\\xf7", "\\xf8", "\\xf9", "\\xfa", "\\xfb", "\\xfc", "\\xfd", "\\xfe", "\\xff"}; - -int converStringToReadable(char *str, int size, char *buf, int bufsize) { - char *pstr = str; - char *pbuf = buf; - while (size > 0) { - if (*pstr == '\0') break; - pbuf = stpcpy(pbuf, ascii_literal_list[((uint8_t)(*pstr))]); - pstr++; - size--; - } - *pbuf = '\0'; - return 0; -} - -int convertNCharToReadable(char *str, int size, char *buf, int bufsize) { - char *pstr = str; - char *pbuf = buf; - // TODO - wchar_t wc; - while (size > 0) { - if (*pstr == '\0') break; - int byte_width = mbtowc(&wc, pstr, MB_CUR_MAX); - if (byte_width < 0) { - fprintf(stderr, "mbtowc() return fail.\n"); - exit(-1); - } - - if ((int)wc < 256) { - pbuf = stpcpy(pbuf, ascii_literal_list[(int)wc]); - } else { - memcpy(pbuf, pstr, byte_width); - pbuf += byte_width; - } - pstr += byte_width; - } - - *pbuf = '\0'; - - return 0; -} - -void taosDumpCharset(FILE *fp) { - char charsetline[256]; - - (void)fseek(fp, 0, SEEK_SET); - sprintf(charsetline, "#!%s\n", tsCharset); - (void)fwrite(charsetline, strlen(charsetline), 1, fp); -} - -void taosLoadFileCharset(FILE *fp, char *fcharset) { - char * line = NULL; - size_t line_size = 0; - - (void)fseek(fp, 0, SEEK_SET); - ssize_t size = getline(&line, &line_size, fp); - if (size <= 2) { - goto _exit_no_charset; - } - - if (strncmp(line, "#!", 2) != 0) { - goto _exit_no_charset; - } - if (line[size - 1] == '\n') { - line[size - 1] = '\0'; - size--; - } - strcpy(fcharset, line + 2); - - taosTFree(line); - return; - -_exit_no_charset: - (void)fseek(fp, 0, SEEK_SET); - *fcharset = '\0'; - taosTFree(line); - return; -} - -// ======== dumpIn support multi threads functions ================================// - -static char **tsDumpInSqlFiles = NULL; -static int32_t tsSqlFileNum = 0; -static char tsDbSqlFile[TSDB_FILENAME_LEN] = {0}; -static char tsfCharset[64] = {0}; -static int taosGetFilesNum(const char *directoryName, const char *prefix) -{ - char cmd[1024] = { 0 }; - sprintf(cmd, "ls %s/*.%s | wc -l ", directoryName, prefix); - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { - fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); - exit(0); - } - - int fileNum = 0; - if (fscanf(fp, "%d", &fileNum) != 1) { - fprintf(stderr, "ERROR: failed to execute:%s, parse result error\n", cmd); - exit(0); - } - - if (fileNum <= 0) { - fprintf(stderr, "ERROR: directory:%s is empry\n", directoryName); - exit(0); - } - - pclose(fp); - return fileNum; -} - -static void taosParseDirectory(const char *directoryName, const char *prefix, char **fileArray, int totalFiles) -{ - char cmd[1024] = { 0 }; - sprintf(cmd, "ls %s/*.%s | sort", directoryName, prefix); - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { - fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); - exit(0); - } - - int fileNum = 0; - while (fscanf(fp, "%128s", fileArray[fileNum++])) { - if (strcmp(fileArray[fileNum-1], tsDbSqlFile) == 0) { - fileNum--; - } - if (fileNum >= totalFiles) { - break; - } - } - - if (fileNum != totalFiles) { - fprintf(stderr, "ERROR: directory:%s changed while read\n", directoryName); - pclose(fp); - exit(0); - } - - pclose(fp); -} - -static void taosCheckTablesSQLFile(const char *directoryName) -{ - char cmd[1024] = { 0 }; - sprintf(cmd, "ls %s/dbs.sql", directoryName); - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { - fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); - exit(0); - } - - while (fscanf(fp, "%128s", tsDbSqlFile)) { - break; - } - - pclose(fp); -} - -static void taosMallocSQLFiles() -{ - tsDumpInSqlFiles = (char**)calloc(tsSqlFileNum, sizeof(char*)); - for (int i = 0; i < tsSqlFileNum; i++) { - tsDumpInSqlFiles[i] = calloc(1, TSDB_FILENAME_LEN); - } -} - -static void taosFreeSQLFiles() -{ - for (int i = 0; i < tsSqlFileNum; i++) { - taosTFree(tsDumpInSqlFiles[i]); - } - taosTFree(tsDumpInSqlFiles); -} - -static void taosGetDirectoryFileList(char *inputDir) -{ - struct stat fileStat; - if (stat(inputDir, &fileStat) < 0) { - fprintf(stderr, "ERROR: %s not exist\n", inputDir); - exit(0); - } - - if (fileStat.st_mode & S_IFDIR) { - taosCheckTablesSQLFile(inputDir); - tsSqlFileNum = taosGetFilesNum(inputDir, "sql"); - int totalSQLFileNum = tsSqlFileNum; - if (tsDbSqlFile[0] != 0) { - tsSqlFileNum--; - } - taosMallocSQLFiles(); - taosParseDirectory(inputDir, "sql", tsDumpInSqlFiles, tsSqlFileNum); - fprintf(stdout, "\nstart to dispose %d files in %s\n", totalSQLFileNum, inputDir); - } - else { - fprintf(stderr, "ERROR: %s is not a directory\n", inputDir); - exit(0); - } -} - -static FILE* taosOpenDumpInFile(char *fptr) { - wordexp_t full_path; - - if (wordexp(fptr, &full_path, 0) != 0) { - fprintf(stderr, "ERROR: illegal file name: %s\n", fptr); - return NULL; - } - - char *fname = full_path.we_wordv[0]; - - FILE *f = fopen(fname, "r"); - if (f == NULL) { - fprintf(stderr, "ERROR: failed to open file %s\n", fname); - wordfree(&full_path); - return NULL; - } - - wordfree(&full_path); - - return f; -} - -int taosDumpInOneFile_old(TAOS * taos, FILE* fp, char* fcharset, char* encode) { - char *command = NULL; - char *lcommand = NULL; - int tsize = 0; - char *line = NULL; - _Bool isRun = true; - size_t line_size = 0; - char *pstr = NULL; - char *lstr = NULL; - size_t inbytesleft = 0; - size_t outbytesleft = COMMAND_SIZE; - char *tcommand = NULL; - char *charsetOfFile = NULL; - iconv_t cd = (iconv_t)(-1); - - command = (char *)malloc(COMMAND_SIZE); - lcommand = (char *)malloc(COMMAND_SIZE); - if (command == NULL || lcommand == NULL) { - fprintf(stderr, "failed to connect to allocate memory\n"); - goto _dumpin_exit_failure; - } - - // Resolve locale - if (*fcharset != '\0') { - charsetOfFile = fcharset; - } else { - charsetOfFile = encode; - } - - if (charsetOfFile != NULL && strcasecmp(tsCharset, charsetOfFile) != 0) { - cd = iconv_open(tsCharset, charsetOfFile); - if (cd == ((iconv_t)(-1))) { - fprintf(stderr, "Failed to open iconv handle\n"); - goto _dumpin_exit_failure; - } - } - - pstr = command; - int64_t linenu = 0; - while (1) { - ssize_t size = getline(&line, &line_size, fp); - linenu++; - if (size <= 0) break; - if (size == 1) { - if (pstr != command) { - inbytesleft = pstr - command; - memset(lcommand, 0, COMMAND_SIZE); - pstr = command; - lstr = lcommand; - outbytesleft = COMMAND_SIZE; - if (cd != ((iconv_t)(-1))) { - iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft); - tcommand = lcommand; - } else { - tcommand = command; - } - - taosReplaceCtrlChar(tcommand); - - if (queryDB(taos, tcommand) != 0) { - fprintf(stderr, "error sql: linenu: %" PRId64 " failed\n", linenu); - exit(0); - } - - pstr = command; - pstr[0] = '\0'; - tsize = 0; - isRun = true; - } - - continue; - } - - /* if (line[0] == '-' && line[1] == '-') continue; */ - - line[size - 1] = 0; - - if (tsize + size - 1 > COMMAND_SIZE) { - fprintf(stderr, "command is too long\n"); - goto _dumpin_exit_failure; - } - - if (line[size - 2] == '\\') { - line[size - 2] = ' '; - isRun = false; - } else { - isRun = true; - } - - memcpy(pstr, line, size - 1); - pstr += (size - 1); - *pstr = '\0'; - - if (!isRun) continue; - - if (command != pstr && !isEmptyCommand(command)) { - inbytesleft = pstr - command; - memset(lcommand, 0, COMMAND_SIZE); - pstr = command; - lstr = lcommand; - outbytesleft = COMMAND_SIZE; - if (cd != ((iconv_t)(-1))) { - iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft); - tcommand = lcommand; - } else { - tcommand = command; - } - taosReplaceCtrlChar(tcommand); - if (queryDB(taos, tcommand) != 0) { - fprintf(stderr, "error sql: linenu:%" PRId64 " failed\n", linenu); - exit(0); - } - } - - pstr = command; - *pstr = '\0'; - tsize = 0; - } - - if (pstr != command) { - inbytesleft = pstr - command; - memset(lcommand, 0, COMMAND_SIZE); - pstr = command; - lstr = lcommand; - outbytesleft = COMMAND_SIZE; - if (cd != ((iconv_t)(-1))) { - iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft); - tcommand = lcommand; - } else { - tcommand = command; - } - taosReplaceCtrlChar(lcommand); - if (queryDB(taos, tcommand) != 0) - fprintf(stderr, "error sql: linenu:%" PRId64 " failed \n", linenu); - } - - if (cd != ((iconv_t)(-1))) iconv_close(cd); - taosTFree(line); - taosTFree(command); - taosTFree(lcommand); - taos_close(taos); - fclose(fp); - return 0; - -_dumpin_exit_failure: - if (cd != ((iconv_t)(-1))) iconv_close(cd); - taosTFree(command); - taosTFree(lcommand); - taos_close(taos); - fclose(fp); - return -1; -} - -int taosDumpInOneFile(TAOS * taos, FILE* fp, char* fcharset, char* encode, char* fileName) { - int read_len = 0; - char * cmd = NULL; - size_t cmd_len = 0; - char * line = NULL; - size_t line_len = 0; - - cmd = (char *)malloc(COMMAND_SIZE); - if (cmd == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - int lineNo = 0; - while ((read_len = getline(&line, &line_len, fp)) != -1) { - ++lineNo; - if (read_len >= COMMAND_SIZE) continue; - line[--read_len] = '\0'; - - //if (read_len == 0 || isCommentLine(line)) { // line starts with # - if (read_len == 0 ) { - continue; - } - - if (line[read_len - 1] == '\\') { - line[read_len - 1] = ' '; - memcpy(cmd + cmd_len, line, read_len); - cmd_len += read_len; - continue; - } - - memcpy(cmd + cmd_len, line, read_len); - cmd[read_len + cmd_len]= '\0'; - if (queryDB(taos, cmd)) { - fprintf(stderr, "error sql: linenu:%d, file:%s\n", lineNo, fileName); - } - - memset(cmd, 0, COMMAND_SIZE); - cmd_len = 0; - } - - taosTFree(cmd); - taosTFree(line); - fclose(fp); - return 0; -} - -void* taosDumpInWorkThreadFp(void *arg) -{ - SThreadParaObj *pThread = (SThreadParaObj*)arg; - for (int32_t f = 0; f < tsSqlFileNum; ++f) { - if (f % pThread->totalThreads == pThread->threadIndex) { - char *SQLFileName = tsDumpInSqlFiles[f]; - FILE* fp = taosOpenDumpInFile(SQLFileName); - if (NULL == fp) { - continue; - } - fprintf(stderr, "Success Open input file: %s\n", SQLFileName); - taosDumpInOneFile(pThread->taosCon, fp, tsfCharset, tsArguments.encode, SQLFileName); - } - } - - return NULL; -} - -static void taosStartDumpInWorkThreads(struct arguments *args) -{ - pthread_attr_t thattr; - SThreadParaObj *pThread; - int32_t totalThreads = args->thread_num; - - if (totalThreads > tsSqlFileNum) { - totalThreads = tsSqlFileNum; - } - - SThreadParaObj *threadObj = (SThreadParaObj *)calloc(totalThreads, sizeof(SThreadParaObj)); - for (int32_t t = 0; t < totalThreads; ++t) { - pThread = threadObj + t; - pThread->threadIndex = t; - pThread->totalThreads = totalThreads; - pThread->taosCon = taos_connect(args->host, args->user, args->password, NULL, args->port); - if (pThread->taosCon == NULL) { - fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taosCon)); - exit(0); - } - - pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); - - if (pthread_create(&(pThread->threadID), &thattr, taosDumpInWorkThreadFp, (void*)pThread) != 0) { - fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex); - exit(0); - } - } - - for (int t = 0; t < totalThreads; ++t) { - pthread_join(threadObj[t].threadID, NULL); - } - - for (int t = 0; t < totalThreads; ++t) { - taos_close(threadObj[t].taosCon); - } - free(threadObj); -} - - -int taosDumpIn(struct arguments *arguments) { - assert(arguments->isDumpIn); - - TAOS *taos = NULL; - FILE *fp = NULL; - - taos = taos_connect(arguments->host, arguments->user, arguments->password, NULL, arguments->port); - if (taos == NULL) { - fprintf(stderr, "failed to connect to TDengine server\n"); - return -1; - } - - taosGetDirectoryFileList(arguments->inpath); - - if (tsDbSqlFile[0] != 0) { - fp = taosOpenDumpInFile(tsDbSqlFile); - if (NULL == fp) { - fprintf(stderr, "failed to open input file %s\n", tsDbSqlFile); - return -1; - } - fprintf(stderr, "Success Open input file: %s\n", tsDbSqlFile); - - taosLoadFileCharset(fp, tsfCharset); - - taosDumpInOneFile(taos, fp, tsfCharset, arguments->encode, tsDbSqlFile); - } - - taosStartDumpInWorkThreads(arguments); - - taos_close(taos); - taosFreeSQLFiles(); - return 0; -} - - diff --git a/src/kit/taosmigrate/CMakeLists.txt b/src/kit/taosmigrate/CMakeLists.txt deleted file mode 100644 index fdd9dd88861c356d63174d9515df3c3a8910a4e4..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/vnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - AUX_SOURCE_DIRECTORY(. SRC) - - ADD_EXECUTABLE(taosmigrate ${SRC}) - TARGET_LINK_LIBRARIES(taosmigrate common cJson osdetail tutil) -ENDIF () - -SET_SOURCE_FILES_PROPERTIES(./taosmigrate.c PROPERTIES COMPILE_FLAGS -w) diff --git a/src/kit/taosmigrate/taosmigrate.c b/src/kit/taosmigrate/taosmigrate.c deleted file mode 100644 index 3ef73ef169a59a8569a520f9c4def32a1de2f644..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrate.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - - -/* The options we understand. */ -static struct argp_option options[] = { - {0, 'r', "data dir", 0, "data dir", 0}, - {0, 'd', "dnodeId", 0, "dnode id", 1}, - {0, 'p', "port", 0, "dnode port", 1}, - {0, 'f', "fqdn", 0, "dnode fqdn", 1}, - {0, 'g', "multi dnodes", 0, "multi dnode info, e.g. \"2 7030 fqdn1, 3 8030 fqdn2\"", 2}, - {0}}; - -/* Used by main to communicate with parse_opt. */ -struct arguments { - char* dataDir; - int32_t dnodeId; - uint16_t port; - char* fqdn; - char* dnodeGroups; - char** arg_list; - int arg_list_len; -}; - -/* Parse a single option. */ -static error_t parse_opt(int key, char *arg, struct argp_state *state) { - struct arguments *arguments = state->input; - switch (key) { - case 'r': - arguments->dataDir = arg; - break; - case 'd': - arguments->dnodeId = atoi(arg); - break; - case 'p': - arguments->port = atoi(arg); - break; - case 'f': - arguments->fqdn = arg; - break; - case 'g': - arguments->dnodeGroups = arg; - break; - case ARGP_KEY_ARG: - arguments->arg_list = &state->argv[state->next - 1]; - arguments->arg_list_len = state->argc - state->next + 1; - state->next = state->argc; - - argp_usage(state); - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static struct argp argp = {options, parse_opt, 0, 0}; -struct arguments arguments = {NULL, 0, 0, NULL, NULL, NULL, 0}; -SdnodeGroup tsDnodeGroup = {0}; - -int tSystemShell(const char * cmd) -{ - FILE * fp; - int res; - char buf[1024]; - if (cmd == NULL) { - printf("tSystem cmd is NULL!\n"); - return -1; - } - - if ((fp = popen(cmd, "r") ) == NULL) { - printf("popen cmd:%s error: %s/n", cmd, strerror(errno)); - return -1; - } else { - while(fgets(buf, sizeof(buf), fp)) { - printf("popen result:%s", buf); - } - - if ((res = pclose(fp)) == -1) { - printf("close popen file pointer fp error!\n"); - } else { - printf("popen res is :%d\n", res); - } - - return res; - } -} - -void taosMvFile(char* destFile, char *srcFile) { - char shellCmd[1024+1] = {0}; - - //(void)snprintf(shellCmd, 1024, "cp -rf %s %s", srcDir, destDir); - (void)snprintf(shellCmd, 1024, "mv -f %s %s", srcFile, destFile); - tSystemShell(shellCmd); -} - -SdnodeIfo* getDnodeInfo(int32_t dnodeId) -{ - for (int32_t i = 0; i < tsDnodeGroup.dnodeNum; i++) { - if (dnodeId == tsDnodeGroup.dnodeArray[i].dnodeId) { - return &(tsDnodeGroup.dnodeArray[i]); - } - } - - return NULL; -} - -void parseOneDnodeInfo(char* buf, SdnodeIfo* pDnodeInfo) -{ - char *ptr; - char *p; - int32_t i = 0; - ptr = strtok_r(buf, " ", &p); - while(ptr != NULL) { - if (0 == i) { - pDnodeInfo->dnodeId = atoi(ptr); - } else if (1 == i) { - pDnodeInfo->port = atoi(ptr); - } else if (2 == i) { - tstrncpy(pDnodeInfo->fqdn, ptr, TSDB_FQDN_LEN); - } else { - printf("input parameter error near:%s\n", buf); - exit(-1); - } - i++; - ptr = strtok_r(NULL, " ", &p); - } - - snprintf(pDnodeInfo->ep, TSDB_EP_LEN, "%s:%d", pDnodeInfo->fqdn, pDnodeInfo->port); -} - -void saveDnodeGroups() -{ - if ((NULL != arguments.fqdn) && (arguments.dnodeId > 0) && (0 != arguments.port)) { - //printf("dnodeId:%d port:%d fqdn:%s ep:%s\n", arguments.dnodeId, arguments.port, arguments.fqdn, arguments.ep); - - tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].dnodeId = arguments.dnodeId; - tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].port = arguments.port; - tstrncpy(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].fqdn, arguments.fqdn, TSDB_FQDN_LEN); - snprintf(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].ep, TSDB_EP_LEN, "%s:%d", tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].fqdn, tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].port); - - tsDnodeGroup.dnodeNum++; - } - - if (NULL == arguments.dnodeGroups) { - return; - } - - //printf("dnodeGroups:%s\n", arguments.dnodeGroups); - - char buf[1024]; - char* str = NULL; - char* start = arguments.dnodeGroups; - while (NULL != (str = strstr(start, ","))) { - memcpy(buf, start, str - start); - // parse one dnode info: dnodeId port fqdn ep - parseOneDnodeInfo(buf, &(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum])); - tsDnodeGroup.dnodeNum++; - // next - start = str + 1; - str = NULL; - } - - if (strlen(start)) { - parseOneDnodeInfo(start, &(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum])); - tsDnodeGroup.dnodeNum++; - } -} - -int32_t main(int32_t argc, char *argv[]) { - memset(&tsDnodeGroup, 0, sizeof(SdnodeGroup)); - - argp_parse(&argp, argc, argv, 0, 0, &arguments); - - if ((NULL == arguments.dataDir) || ((NULL == arguments.dnodeGroups) - && (NULL == arguments.fqdn || arguments.dnodeId < 1 || 0 == arguments.port))) { - printf("input parameter error!\n"); - return -1; - } - - saveDnodeGroups(); - - printf("===================arguments:==================\n"); - printf("oldWal:%s\n", arguments.dataDir); - for (int32_t i = 0; i < tsDnodeGroup.dnodeNum; i++) { - printf("dnodeId:%d port:%d fqdn:%s ep:%s\n", tsDnodeGroup.dnodeArray[i].dnodeId, - tsDnodeGroup.dnodeArray[i].port, - tsDnodeGroup.dnodeArray[i].fqdn, - tsDnodeGroup.dnodeArray[i].ep); - } - printf("===========================\n"); - - // 1. modify wal for mnode - char mnodeWal[TSDB_FILENAME_LEN*2] = {0}; - (void)snprintf(mnodeWal, TSDB_FILENAME_LEN*2, "%s/mnode/wal/wal0", arguments.dataDir); - walModWalFile(mnodeWal); - - // 2. modfiy dnode config: mnodeEpSet.json - char dnodeEpSet[TSDB_FILENAME_LEN*2] = {0}; - (void)snprintf(dnodeEpSet, TSDB_FILENAME_LEN*2, "%s/dnode/mnodeEpSet.json", arguments.dataDir); - modDnodeEpSet(dnodeEpSet); - - // 3. modify vnode config: config.json - char vnodeDir[TSDB_FILENAME_LEN*2] = {0}; - (void)snprintf(vnodeDir, TSDB_FILENAME_LEN*2, "%s/vnode", arguments.dataDir); - modAllVnode(vnodeDir); - - return 0; -} - diff --git a/src/kit/taosmigrate/taosmigrate.h b/src/kit/taosmigrate/taosmigrate.h deleted file mode 100644 index 9fb3c92db284033cdfc2dcaa736e088a9b84f14f..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrate.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef TAOS_MIGRATE_H -#define TAOS_MIGRATE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define _GNU_SOURCE - -#ifndef _ALPINE -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "taosdef.h" -#include "tutil.h" -#include "twal.h" -#include "tchecksum.h" -#include "mnodeDef.h" -#include "mnodeSdb.h" -#include "cJSON.h" -#include "taosmsg.h" -#include "tglobal.h" -#include "tsdb.h" - -//#include "vnode.h" -#include "vnodeInt.h" - -#define MAX_DNODE_NUM 128 - - -typedef struct _SdnodeIfo { - int32_t dnodeId; - uint16_t port; - char fqdn[TSDB_FQDN_LEN+1]; - char ep[TSDB_EP_LEN+1]; -} SdnodeIfo; - -typedef struct _SdnodeGroup { - int32_t dnodeNum; - SdnodeIfo dnodeArray[MAX_DNODE_NUM]; -} SdnodeGroup; - -int tSystemShell(const char * cmd); -void taosMvFile(char* destFile, char *srcFile) ; -void walModWalFile(char* walfile); -SdnodeIfo* getDnodeInfo(int32_t dnodeId); -void modDnodeEpSet(char* dnodeEpSet); -void modAllVnode(char *vnodeDir); - -#endif diff --git a/src/kit/taosmigrate/taosmigrateDnodeCfg.c b/src/kit/taosmigrate/taosmigrateDnodeCfg.c deleted file mode 100644 index 7f6fd03feab28c5e71ac6c390160bde8dabf4b67..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrateDnodeCfg.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - -//#include "dnodeInt.h" -//#include "dnodeMgmt.h" -//#include "dnodeVRead.h" -//#include "dnodeVWrite.h" -//#include "dnodeModule.h" - -static SDMMnodeInfos tsDnodeIpInfos = {0}; - -static bool dnodeReadMnodeInfos(char* dnodeEpSet) { - FILE *fp = fopen(dnodeEpSet, "r"); - if (!fp) { - printf("failed to read mnodeEpSet.json, file not exist\n"); - return false; - } - - bool ret = false; - int maxLen = 2000; - char *content = calloc(1, maxLen + 1); - int len = fread(content, 1, maxLen, fp); - if (len <= 0) { - free(content); - fclose(fp); - printf("failed to read mnodeEpSet.json, content is null\n"); - return false; - } - - content[len] = 0; - cJSON* root = cJSON_Parse(content); - if (root == NULL) { - printf("failed to read mnodeEpSet.json, invalid json format\n"); - goto PARSE_OVER; - } - - cJSON* inUse = cJSON_GetObjectItem(root, "inUse"); - if (!inUse || inUse->type != cJSON_Number) { - printf("failed to read mnodeEpSet.json, inUse not found\n"); - goto PARSE_OVER; - } - tsDnodeIpInfos.inUse = inUse->valueint; - - cJSON* nodeNum = cJSON_GetObjectItem(root, "nodeNum"); - if (!nodeNum || nodeNum->type != cJSON_Number) { - printf("failed to read mnodeEpSet.json, nodeNum not found\n"); - goto PARSE_OVER; - } - tsDnodeIpInfos.nodeNum = nodeNum->valueint; - - cJSON* nodeInfos = cJSON_GetObjectItem(root, "nodeInfos"); - if (!nodeInfos || nodeInfos->type != cJSON_Array) { - printf("failed to read mnodeEpSet.json, nodeInfos not found\n"); - goto PARSE_OVER; - } - - int size = cJSON_GetArraySize(nodeInfos); - if (size != tsDnodeIpInfos.nodeNum) { - printf("failed to read mnodeEpSet.json, nodeInfos size not matched\n"); - goto PARSE_OVER; - } - - for (int i = 0; i < size; ++i) { - cJSON* nodeInfo = cJSON_GetArrayItem(nodeInfos, i); - if (nodeInfo == NULL) continue; - - cJSON *nodeId = cJSON_GetObjectItem(nodeInfo, "nodeId"); - if (!nodeId || nodeId->type != cJSON_Number) { - printf("failed to read mnodeEpSet.json, nodeId not found\n"); - goto PARSE_OVER; - } - tsDnodeIpInfos.nodeInfos[i].nodeId = nodeId->valueint; - - cJSON *nodeEp = cJSON_GetObjectItem(nodeInfo, "nodeEp"); - if (!nodeEp || nodeEp->type != cJSON_String || nodeEp->valuestring == NULL) { - printf("failed to read mnodeEpSet.json, nodeName not found\n"); - goto PARSE_OVER; - } - strncpy(tsDnodeIpInfos.nodeInfos[i].nodeEp, nodeEp->valuestring, TSDB_EP_LEN); - - SdnodeIfo* pDnodeInfo = getDnodeInfo(tsDnodeIpInfos.nodeInfos[i].nodeId); - if (NULL == pDnodeInfo) { - continue; - } - - tstrncpy(tsDnodeIpInfos.nodeInfos[i].nodeEp, pDnodeInfo->ep, TSDB_EP_LEN); - } - - ret = true; - - //printf("read mnode epSet successed, numOfEps:%d inUse:%d\n", tsDnodeIpInfos.nodeNum, tsDnodeIpInfos.inUse); - //for (int32_t i = 0; i < tsDnodeIpInfos.nodeNum; i++) { - // printf("mnode:%d, %s\n", tsDnodeIpInfos.nodeInfos[i].nodeId, tsDnodeIpInfos.nodeInfos[i].nodeEp); - //} - -PARSE_OVER: - free(content); - cJSON_Delete(root); - fclose(fp); - return ret; -} - - -static void dnodeSaveMnodeInfos(char* dnodeEpSet) { - FILE *fp = fopen(dnodeEpSet, "w"); - if (!fp) return; - - int32_t len = 0; - int32_t maxLen = 2000; - char * content = calloc(1, maxLen + 1); - - len += snprintf(content + len, maxLen - len, "{\n"); - len += snprintf(content + len, maxLen - len, " \"inUse\": %d,\n", tsDnodeIpInfos.inUse); - len += snprintf(content + len, maxLen - len, " \"nodeNum\": %d,\n", tsDnodeIpInfos.nodeNum); - len += snprintf(content + len, maxLen - len, " \"nodeInfos\": [{\n"); - for (int32_t i = 0; i < tsDnodeIpInfos.nodeNum; i++) { - len += snprintf(content + len, maxLen - len, " \"nodeId\": %d,\n", tsDnodeIpInfos.nodeInfos[i].nodeId); - len += snprintf(content + len, maxLen - len, " \"nodeEp\": \"%s\"\n", tsDnodeIpInfos.nodeInfos[i].nodeEp); - if (i < tsDnodeIpInfos.nodeNum -1) { - len += snprintf(content + len, maxLen - len, " },{\n"); - } else { - len += snprintf(content + len, maxLen - len, " }]\n"); - } - } - len += snprintf(content + len, maxLen - len, "}\n"); - - fwrite(content, 1, len, fp); - fflush(fp); - fclose(fp); - free(content); - - printf("mod mnode epSet successed\n"); -} - -void modDnodeEpSet(char* dnodeEpSet) -{ - (void)dnodeReadMnodeInfos(dnodeEpSet); - dnodeSaveMnodeInfos(dnodeEpSet); - return; -} - - diff --git a/src/kit/taosmigrate/taosmigrateMnodeWal.c b/src/kit/taosmigrate/taosmigrateMnodeWal.c deleted file mode 100644 index 28e2b7772b29641c5cb2f736606c6cb03169402e..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrateMnodeWal.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - -static void recordWrite(int fd, SWalHead *pHead) { - - taosCalcChecksumAppend(0, (uint8_t *)pHead, sizeof(SWalHead)); - - int contLen = pHead->len + sizeof(SWalHead); - - if(write(fd, pHead, contLen) != contLen) { - printf("failed to write(%s)", strerror(errno)); - exit(-1); - } -} - -static void recordMod(SWalHead* pHead) -{ - SDnodeObj *pDnode; - - ESdbTable tableId = (ESdbTable)(pHead->msgType / 10); - - switch (tableId) { - case SDB_TABLE_DNODE: - case SDB_TABLE_MNODE: - pDnode = (SDnodeObj *)pHead->cont; - - printf("dnodeId:%d port:%d fqdn:%s ep:%s\n", pDnode->dnodeId, pDnode->dnodePort, pDnode->dnodeFqdn, pDnode->dnodeEp); - - SdnodeIfo* pDnodeInfo = getDnodeInfo(pDnode->dnodeId); - if (NULL == pDnodeInfo) { - break; - } - - pDnode->dnodePort = pDnodeInfo->port; - tstrncpy(pDnode->dnodeFqdn, pDnodeInfo->fqdn, sizeof(pDnode->dnodeFqdn)); - tstrncpy(pDnode->dnodeEp, pDnodeInfo->ep, sizeof(pDnode->dnodeEp)); - break; - #if 0 - case SDB_TABLE_ACCOUNT: - SAcctObj *pAcct = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_USER: - SUserObj *pUser = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_DB: - SDbObj *pDb = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_VGROUP: - SVgObj *pVgroup = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_STABLE: - SSuperTableObj *pStable = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_CTABLE: - SChildTableObj *pCTable = (SDnodeObj *)pHead->cont; - break; - #endif - default: - break; - } -} - -void walModWalFile(char* walfile) { - char *buffer = malloc(1024000); // size for one record - if (buffer == NULL) { - printf("failed to malloc:%s\n", strerror(errno)); - return ; - } - - SWalHead *pHead = (SWalHead *)buffer; - - int rfd = open(walfile, O_RDONLY); - if (rfd < 0) { - printf("failed to open %s failed:%s\n", walfile, strerror(errno)); - free(buffer); - return ; - } - - char newWalFile[32] = "wal0"; - int wfd = open(newWalFile, O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); - - if (wfd < 0) { - printf("wal:%s, failed to open(%s)\n", newWalFile, strerror(errno)); - free(buffer); - close(rfd); - return ; - } - - printf("start to mod %s into %s\n", walfile, newWalFile); - - while (1) { - memset(buffer, 0, 1024000); - int ret = read(rfd, pHead, sizeof(SWalHead)); - if ( ret == 0) break; - - if (ret != sizeof(SWalHead)) { - printf("wal:%s, failed to read head, skip, ret:%d(%s)\n", walfile, ret, strerror(errno)); - break; - } - - if (!taosCheckChecksumWhole((uint8_t *)pHead, sizeof(SWalHead))) { - printf("wal:%s, cksum is messed up, skip the rest of file\n", walfile); - break; - } - - if (pHead->len >= 1024000 - sizeof(SWalHead)) { - printf("wal:%s, SWalHead.len(%d) overflow, skip the rest of file\n", walfile, pHead->len); - break; - } - - ret = read(rfd, pHead->cont, pHead->len); - if ( ret != pHead->len) { - printf("wal:%s, failed to read body, skip, len:%d ret:%d\n", walfile, pHead->len, ret); - break; - } - - recordMod(pHead); - recordWrite(wfd, pHead); - } - - close(rfd); - close(wfd); - free(buffer); - - taosMvFile(walfile, newWalFile); - - return ; -} - - - diff --git a/src/kit/taosmigrate/taosmigrateVnodeCfg.c b/src/kit/taosmigrate/taosmigrateVnodeCfg.c deleted file mode 100644 index 472671c22c4dc0d578d03452a4ceef3ff16395c2..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrateVnodeCfg.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - - -static int32_t saveVnodeCfg(SVnodeObj *pVnode, char* cfgFile) -{ - FILE *fp = fopen(cfgFile, "w"); - if (!fp) { - printf("failed to open vnode cfg file for write, file:%s error:%s\n", cfgFile, strerror(errno)); - return errno; - } - - int32_t len = 0; - int32_t maxLen = 1000; - char * content = calloc(1, maxLen + 1); - if (content == NULL) { - fclose(fp); - return -1; - } - - len += snprintf(content + len, maxLen - len, "{\n"); - len += snprintf(content + len, maxLen - len, " \"db\": \"%s\",\n", pVnode->db); - len += snprintf(content + len, maxLen - len, " \"cfgVersion\": %d,\n", pVnode->cfgVersion); - len += snprintf(content + len, maxLen - len, " \"cacheBlockSize\": %d,\n", pVnode->tsdbCfg.cacheBlockSize); - len += snprintf(content + len, maxLen - len, " \"totalBlocks\": %d,\n", pVnode->tsdbCfg.totalBlocks); - len += snprintf(content + len, maxLen - len, " \"daysPerFile\": %d,\n", pVnode->tsdbCfg.daysPerFile); - len += snprintf(content + len, maxLen - len, " \"daysToKeep\": %d,\n", pVnode->tsdbCfg.keep); - len += snprintf(content + len, maxLen - len, " \"daysToKeep1\": %d,\n", pVnode->tsdbCfg.keep1); - len += snprintf(content + len, maxLen - len, " \"daysToKeep2\": %d,\n", pVnode->tsdbCfg.keep2); - len += snprintf(content + len, maxLen - len, " \"minRowsPerFileBlock\": %d,\n", pVnode->tsdbCfg.minRowsPerFileBlock); - len += snprintf(content + len, maxLen - len, " \"maxRowsPerFileBlock\": %d,\n", pVnode->tsdbCfg.maxRowsPerFileBlock); - len += snprintf(content + len, maxLen - len, " \"precision\": %d,\n", pVnode->tsdbCfg.precision); - len += snprintf(content + len, maxLen - len, " \"compression\": %d,\n", pVnode->tsdbCfg.compression); - len += snprintf(content + len, maxLen - len, " \"walLevel\": %d,\n", pVnode->walCfg.walLevel); - len += snprintf(content + len, maxLen - len, " \"fsync\": %d,\n", pVnode->walCfg.fsyncPeriod); - len += snprintf(content + len, maxLen - len, " \"replica\": %d,\n", pVnode->syncCfg.replica); - len += snprintf(content + len, maxLen - len, " \"wals\": %d,\n", pVnode->walCfg.wals); - len += snprintf(content + len, maxLen - len, " \"quorum\": %d,\n", pVnode->syncCfg.quorum); - - len += snprintf(content + len, maxLen - len, " \"nodeInfos\": [{\n"); - for (int32_t i = 0; i < pVnode->syncCfg.replica; i++) { - len += snprintf(content + len, maxLen - len, " \"nodeId\": %d,\n", pVnode->syncCfg.nodeInfo[i].nodeId); - len += snprintf(content + len, maxLen - len, " \"nodeEp\": \"%s:%d\"\n", pVnode->syncCfg.nodeInfo[i].nodeFqdn, pVnode->syncCfg.nodeInfo[i].nodePort); - - if (i < pVnode->syncCfg.replica - 1) { - len += snprintf(content + len, maxLen - len, " },{\n"); - } else { - len += snprintf(content + len, maxLen - len, " }]\n"); - } - } - len += snprintf(content + len, maxLen - len, "}\n"); - - fwrite(content, 1, len, fp); - fflush(fp); - fclose(fp); - free(content); - - printf("mod vnode cfg %s successed\n", cfgFile); - - return 0; -} - -static int32_t readVnodeCfg(SVnodeObj *pVnode, char* cfgFile) -{ - cJSON *root = NULL; - char *content = NULL; - int maxLen = 1000; - int32_t ret = -1; - - FILE *fp = fopen(cfgFile, "r"); - if (!fp) { - printf("failed to open vnode cfg file:%s to read, error:%s\n", cfgFile, strerror(errno)); - goto PARSE_OVER; - } - - content = calloc(1, maxLen + 1); - if (content == NULL) { - goto PARSE_OVER; - } - - int len = fread(content, 1, maxLen, fp); - if (len <= 0) { - printf("failed to read vnode cfg, content is null, error:%s\n", strerror(errno)); - goto PARSE_OVER; - } - - content[maxLen] = (char)0; - - root = cJSON_Parse(content); - if (root == NULL) { - printf("failed to json parse %s, invalid json format\n", cfgFile); - goto PARSE_OVER; - } - - cJSON *db = cJSON_GetObjectItem(root, "db"); - if (!db || db->type != cJSON_String || db->valuestring == NULL) { - printf("vgId:%d, failed to read vnode cfg, db not found\n", pVnode->vgId); - goto PARSE_OVER; - } - strcpy(pVnode->db, db->valuestring); - - cJSON *cfgVersion = cJSON_GetObjectItem(root, "cfgVersion"); - if (!cfgVersion || cfgVersion->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, cfgVersion not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->cfgVersion = cfgVersion->valueint; - - cJSON *cacheBlockSize = cJSON_GetObjectItem(root, "cacheBlockSize"); - if (!cacheBlockSize || cacheBlockSize->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, cacheBlockSize not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.cacheBlockSize = cacheBlockSize->valueint; - - cJSON *totalBlocks = cJSON_GetObjectItem(root, "totalBlocks"); - if (!totalBlocks || totalBlocks->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, totalBlocks not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.totalBlocks = totalBlocks->valueint; - - // cJSON *maxTables = cJSON_GetObjectItem(root, "maxTables"); - // if (!maxTables || maxTables->type != cJSON_Number) { - // printf("vgId:%d, failed to read vnode cfg, maxTables not found\n", pVnode->vgId); - // goto PARSE_OVER; - // } - // pVnode->tsdbCfg.maxTables = maxTables->valueint; - - cJSON *daysPerFile = cJSON_GetObjectItem(root, "daysPerFile"); - if (!daysPerFile || daysPerFile->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysPerFile not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.daysPerFile = daysPerFile->valueint; - - cJSON *daysToKeep = cJSON_GetObjectItem(root, "daysToKeep"); - if (!daysToKeep || daysToKeep->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysToKeep not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.keep = daysToKeep->valueint; - - cJSON *daysToKeep1 = cJSON_GetObjectItem(root, "daysToKeep1"); - if (!daysToKeep1 || daysToKeep1->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysToKeep1 not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.keep1 = daysToKeep1->valueint; - - cJSON *daysToKeep2 = cJSON_GetObjectItem(root, "daysToKeep2"); - if (!daysToKeep2 || daysToKeep2->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysToKeep2 not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.keep2 = daysToKeep2->valueint; - - cJSON *minRowsPerFileBlock = cJSON_GetObjectItem(root, "minRowsPerFileBlock"); - if (!minRowsPerFileBlock || minRowsPerFileBlock->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, minRowsPerFileBlock not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.minRowsPerFileBlock = minRowsPerFileBlock->valueint; - - cJSON *maxRowsPerFileBlock = cJSON_GetObjectItem(root, "maxRowsPerFileBlock"); - if (!maxRowsPerFileBlock || maxRowsPerFileBlock->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, maxRowsPerFileBlock not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.maxRowsPerFileBlock = maxRowsPerFileBlock->valueint; - - // cJSON *commitTime = cJSON_GetObjectItem(root, "commitTime"); - // if (!commitTime || commitTime->type != cJSON_Number) { - // printf("vgId:%d, failed to read vnode cfg, commitTime not found\n", pVnode->vgId); - // goto PARSE_OVER; - // } - // pVnode->tsdbCfg.commitTime = (int8_t)commitTime->valueint; - - cJSON *precision = cJSON_GetObjectItem(root, "precision"); - if (!precision || precision->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, precision not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.precision = (int8_t)precision->valueint; - - cJSON *compression = cJSON_GetObjectItem(root, "compression"); - if (!compression || compression->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, compression not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.compression = (int8_t)compression->valueint; - - cJSON *walLevel = cJSON_GetObjectItem(root, "walLevel"); - if (!walLevel || walLevel->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, walLevel not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->walCfg.walLevel = (int8_t) walLevel->valueint; - - cJSON *fsyncPeriod = cJSON_GetObjectItem(root, "fsync"); - if (!fsyncPeriod || fsyncPeriod->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, fsyncPeriod not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->walCfg.fsyncPeriod = fsyncPeriod->valueint; - - cJSON *wals = cJSON_GetObjectItem(root, "wals"); - if (!wals || wals->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, wals not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->walCfg.wals = (int8_t)wals->valueint; - pVnode->walCfg.keep = 0; - - cJSON *replica = cJSON_GetObjectItem(root, "replica"); - if (!replica || replica->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, replica not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->syncCfg.replica = (int8_t)replica->valueint; - - cJSON *quorum = cJSON_GetObjectItem(root, "quorum"); - if (!quorum || quorum->type != cJSON_Number) { - printf("vgId: %d, failed to read vnode cfg, quorum not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->syncCfg.quorum = (int8_t)quorum->valueint; - - cJSON *nodeInfos = cJSON_GetObjectItem(root, "nodeInfos"); - if (!nodeInfos || nodeInfos->type != cJSON_Array) { - printf("vgId:%d, failed to read vnode cfg, nodeInfos not found\n", pVnode->vgId); - goto PARSE_OVER; - } - - int size = cJSON_GetArraySize(nodeInfos); - if (size != pVnode->syncCfg.replica) { - printf("vgId:%d, failed to read vnode cfg, nodeInfos size not matched\n", pVnode->vgId); - goto PARSE_OVER; - } - - for (int i = 0; i < size; ++i) { - cJSON *nodeInfo = cJSON_GetArrayItem(nodeInfos, i); - if (nodeInfo == NULL) continue; - - cJSON *nodeId = cJSON_GetObjectItem(nodeInfo, "nodeId"); - if (!nodeId || nodeId->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, nodeId not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->syncCfg.nodeInfo[i].nodeId = nodeId->valueint; - - cJSON *nodeEp = cJSON_GetObjectItem(nodeInfo, "nodeEp"); - if (!nodeEp || nodeEp->type != cJSON_String || nodeEp->valuestring == NULL) { - printf("vgId:%d, failed to read vnode cfg, nodeFqdn not found\n", pVnode->vgId); - goto PARSE_OVER; - } - - taosGetFqdnPortFromEp(nodeEp->valuestring, pVnode->syncCfg.nodeInfo[i].nodeFqdn, &pVnode->syncCfg.nodeInfo[i].nodePort); - //pVnode->syncCfg.nodeInfo[i].nodePort += TSDB_PORT_SYNC; - - - SdnodeIfo* pDnodeInfo = getDnodeInfo(pVnode->syncCfg.nodeInfo[i].nodeId); - if (NULL == pDnodeInfo) { - continue; - } - - pVnode->syncCfg.nodeInfo[i].nodePort = pDnodeInfo->port; - tstrncpy(pVnode->syncCfg.nodeInfo[i].nodeFqdn, pDnodeInfo->fqdn, TSDB_FQDN_LEN); - } - - ret = 0; - //printf("read vnode cfg successfully, replcia:%d\n", pVnode->syncCfg.replica); - //for (int32_t i = 0; i < pVnode->syncCfg.replica; i++) { - // printf("dnode:%d, %s:%d\n", pVnode->syncCfg.nodeInfo[i].nodeId, pVnode->syncCfg.nodeInfo[i].nodeFqdn, pVnode->syncCfg.nodeInfo[i].nodePort); - //} - -PARSE_OVER: - taosTFree(content); - cJSON_Delete(root); - if (fp) fclose(fp); - return ret; -} - -static void modVnodeCfg(char* vnodeCfg) -{ - int32_t ret; - SVnodeObj vnodeObj = {0}; - ret = readVnodeCfg(&vnodeObj, vnodeCfg); - if (0 != ret) { - printf("read vnode cfg %s fail!\n", vnodeCfg); - return ; - } - - (void)saveVnodeCfg(&vnodeObj, vnodeCfg); - - return ; -} - -void modAllVnode(char *vnodeDir) -{ - DIR *dir = opendir(vnodeDir); - if (dir == NULL) return; - - char filename[1024]; - struct dirent *de = NULL; - while ((de = readdir(dir)) != NULL) { - if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; - - if ((de->d_type & DT_DIR) && (strncmp(de->d_name, "vnode", 5) == 0)) { - memset(filename, 0, 1024); - snprintf(filename, 1023, "%s/%s/config.json", vnodeDir, de->d_name); - modVnodeCfg(filename); - } - } - - closedir(dir); -} - diff --git a/src/kit/taosnetwork/CMakeLists.txt b/src/kit/taosnetwork/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9d2a5ba3f8622e9623083ee0c9788fe8716b3058 --- /dev/null +++ b/src/kit/taosnetwork/CMakeLists.txt @@ -0,0 +1,10 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_LINUX) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(taosClient client.c) + ADD_EXECUTABLE(taosServer server.c) + TARGET_LINK_LIBRARIES( taosServer -lpthread -lm -lrt ) + TARGET_LINK_LIBRARIES( taosClient -lpthread -lm -lrt ) +ENDIF () diff --git a/src/kit/taosnetwork/client.c b/src/kit/taosnetwork/client.c index 706359ec20e5b014630164a110b8997d2e1d76fc..102f9b9d89b3e39218d53105fe620b0726e41d45 100644 --- a/src/kit/taosnetwork/client.c +++ b/src/kit/taosnetwork/client.c @@ -28,23 +28,27 @@ #include #include -#define BUFFER_SIZE 200 +#define MAX_PKG_LEN (64*1000) +#define BUFFER_SIZE (MAX_PKG_LEN + 1024) typedef struct { int port; - char *host[15]; -} info; + char *host; + uint16_t pktLen; +} info_s; typedef struct Arguments { char * host; uint16_t port; uint16_t max_port; + uint16_t pktLen; } SArguments; static struct argp_option options[] = { {0, 'h', "host", 0, "The host to connect to TDEngine. Default is localhost.", 0}, - {0, 'p', "port", 0, "The TCP or UDP port number to use for the connection. Default is 6041.", 1}, - {0, 'm', "max port", 0, "The max TCP or UDP port number to use for the connection. Default is 6050.", 2}}; + {0, 'p', "port", 0, "The TCP or UDP port number to use for the connection. Default is 6030.", 1}, + {0, 'm', "max port", 0, "The max TCP or UDP port number to use for the connection. Default is 6060.", 2}, + {0, 'l', "test pkg len", 0, "The len of pkg for test. Default is 1000 Bytes, max not greater than 64k Bytes.\nNotes: This parameter must be consistent between the client and the server.", 3}}; static error_t parse_opt(int key, char *arg, struct argp_state *state) { @@ -59,114 +63,165 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case 'm': arguments->max_port = atoi(arg); break; + case 'l': + arguments->pktLen = atoi(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; } return 0; } static struct argp argp = {options, parse_opt, 0, 0}; -void *checkPort(void *sarg) { - info *pinfo = (info *)sarg; - int port = pinfo->port; - char *host = *pinfo->host; +int checkTcpPort(info_s *info) { + int port = info->port; + char *host = info->host; int clientSocket; struct sockaddr_in serverAddr; char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; - int iDataNum; + int iDataNum = 0; if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket"); - return NULL; + printf("socket() fail: %s\n", strerror(errno)); + return -1; } serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = inet_addr(host); - printf("=================================\n"); + //printf("=================================\n"); if (connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { - perror("connect"); - return NULL; + printf("connect() fail: %s\n", strerror(errno)); + return -1; + } + //printf("Connect to: %s:%d...success\n", host, port); + memset(sendbuf, 0, BUFFER_SIZE); + memset(recvbuf, 0, BUFFER_SIZE); + + sprintf(sendbuf, "client send tcp pkg to %s:%d, content: 1122334455", host, port); + sprintf(sendbuf + info->pktLen - 16, "1122334455667788"); + + send(clientSocket, sendbuf, info->pktLen, 0); + + memset(recvbuf, 0, BUFFER_SIZE); + int nleft, nread; + char *ptr = recvbuf; + nleft = info->pktLen; + while (nleft > 0) { + nread = recv(clientSocket, ptr, BUFFER_SIZE, 0);; + + if (nread == 0) { + break; + } else if (nread < 0) { + if (errno == EINTR) { + continue; + } else { + printf("recv ack pkg from TCP port: %d fail:%s.\n", port, strerror(errno)); + close(clientSocket); + return -1; + } + } else { + nleft -= nread; + ptr += nread; + iDataNum += nread; + } } - printf("Connect to: %s:%d...success\n", host, port); - - sprintf(sendbuf, "send port_%d", port); - send(clientSocket, sendbuf, strlen(sendbuf), 0); - printf("Send msg_%d: %s\n", port, sendbuf); - recvbuf[0] = '\0'; - iDataNum = recv(clientSocket, recvbuf, BUFFER_SIZE, 0); - recvbuf[iDataNum] = '\0'; - printf("Read ack msg_%d: %s\n", port, recvbuf); + if (iDataNum < info->pktLen) { + printf("recv ack pkg len: %d, less than req pkg len: %d from tcp port: %d\n", iDataNum, info->pktLen, port); + return -1; + } + //printf("Read ack pkg len:%d from tcp port: %d, buffer: %s %s\n", info->pktLen, port, recvbuf, recvbuf+iDataNum-8); - printf("=================================\n"); close(clientSocket); - return NULL; + return 0; } -void *checkUPort(void *sarg) { - info *pinfo = (info *)sarg; - int port = pinfo->port; - char *host = *pinfo->host; +int checkUdpPort(info_s *info) { + int port = info->port; + char *host = info->host; int clientSocket; struct sockaddr_in serverAddr; char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; - int iDataNum; + int iDataNum = 0; if ((clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); - return NULL; + return -1; } + serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); - serverAddr.sin_addr.s_addr = inet_addr(host); + + memset(sendbuf, 0, BUFFER_SIZE); + memset(recvbuf, 0, BUFFER_SIZE); - printf("=================================\n"); - - sprintf(sendbuf, "send msg port_%d by udp", port); + sprintf(sendbuf, "client send udp pkg to %s:%d, content: 1122334455", host, port); + sprintf(sendbuf + info->pktLen - 16, "1122334455667788"); socklen_t sin_size = sizeof(*(struct sockaddr *)&serverAddr); - sendto(clientSocket, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&serverAddr, (int)sin_size); - - printf("Send msg_%d by udp: %s\n", port, sendbuf); + int code = sendto(clientSocket, sendbuf, info->pktLen, 0, (struct sockaddr *)&serverAddr, (int)sin_size); + if (code < 0) { + perror("sendto"); + return -1; + } - recvbuf[0] = '\0'; iDataNum = recvfrom(clientSocket, recvbuf, BUFFER_SIZE, 0, (struct sockaddr *)&serverAddr, &sin_size); - recvbuf[iDataNum] = '\0'; - printf("Read ack msg_%d from udp: %s\n", port, recvbuf); - printf("=================================\n"); + if (iDataNum < info->pktLen) { + printf("Read ack pkg len: %d, less than req pkg len: %d from udp port: %d\n", iDataNum, info->pktLen, port); + return -1; + } + + //printf("Read ack pkg len:%d from udp port: %d, buffer: %s %s\n", info->pktLen, port, recvbuf, recvbuf+iDataNum-8); close(clientSocket); - return NULL; + return 0; } int main(int argc, char *argv[]) { - SArguments arguments = {"127.0.0.1", 6041, 6050}; - + SArguments arguments = {"127.0.0.1", 6030, 6060, 1000}; + info_s info; + int ret; + argp_parse(&argp, argc, argv, 0, 0, &arguments); + if (arguments.pktLen > MAX_PKG_LEN) { + printf("test pkg len overflow: %d, max len not greater than %d bytes\n", arguments.pktLen, MAX_PKG_LEN); + exit(0); + } - printf("host: %s\tport: %d\tmax_port: %d\n", arguments.host, arguments.port, arguments.max_port); + printf("host: %s\tport: %d\tmax_port: %d\tpkgLen: %d\n", arguments.host, arguments.port, arguments.max_port, arguments.pktLen); int port = arguments.port; - char *host = arguments.host; - info *tinfo = malloc(sizeof(info)); - info *uinfo = malloc(sizeof(info)); - - for (; port < arguments.max_port; port++) { - printf("For test: %s:%d\n", host, port); - - *tinfo->host = host; - tinfo->port = port; - checkPort(tinfo); - *uinfo->host = host; - uinfo->port = port; - checkUPort(uinfo); + info.host = arguments.host; + info.pktLen = arguments.pktLen; + + for (; port <= arguments.max_port; port++) { + //printf("test: %s:%d\n", info.host, port); + printf("\n"); + + info.port = port; + ret = checkTcpPort(&info); + if (ret != 0) { + printf("tcp port:%d test fail.\t\t", port); + } else { + printf("tcp port:%d test ok.\t\t", port); + } + + ret = checkUdpPort(&info); + if (ret != 0) { + printf("udp port:%d test fail.\t\t", port); + } else { + printf("udp port:%d test ok.\t\t", port); + } } - free(tinfo); - free(uinfo); -} \ No newline at end of file + printf("\n"); + return 0; +} diff --git a/src/kit/taosnetwork/server.c b/src/kit/taosnetwork/server.c index c967828f0b28ea8bd55c91c3473a7762ac815356..1c3bc6fa098d793c2c7d1c355c524c755301b57b 100644 --- a/src/kit/taosnetwork/server.c +++ b/src/kit/taosnetwork/server.c @@ -27,24 +27,28 @@ #include #include #include +#include -#define BUFFER_SIZE 200 +#define MAX_PKG_LEN (64*1000) +#define BUFFER_SIZE (MAX_PKG_LEN + 1024) typedef struct { int port; - int type; // 0: tcp, 1: udo, default: 0 -} info; + uint16_t pktLen; +} info_s; typedef struct Arguments { char * host; uint16_t port; uint16_t max_port; + uint16_t pktLen; } SArguments; static struct argp_option options[] = { {0, 'h', "host", 0, "The host to connect to TDEngine. Default is localhost.", 0}, - {0, 'p', "port", 0, "The TCP or UDP port number to use for the connection. Default is 6020.", 1}, - {0, 'm', "max port", 0, "The max TCP or UDP port number to use for the connection. Default is 6050.", 2}}; + {0, 'p', "port", 0, "The TCP or UDP port number to use for the connection. Default is 6041.", 1}, + {0, 'm', "max port", 0, "The max TCP or UDP port number to use for the connection. Default is 6060.", 2}, + {0, 'l', "test pkg len", 0, "The len of pkg for test. Default is 1000 Bytes, max not greater than 64k Bytes.\nNotes: This parameter must be consistent between the client and the server.", 3}}; static error_t parse_opt(int key, char *arg, struct argp_state *state) { @@ -59,16 +63,21 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case 'm': arguments->max_port = atoi(arg); break; + case 'l': + arguments->pktLen = atoi(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; } return 0; } static struct argp argp = {options, parse_opt, 0, 0}; -static void *bindPort(void *sarg) { - info *pinfo = (info *)sarg; +static void *bindTcpPort(void *sarg) { + info_s *pinfo = (info_s *)sarg; int port = pinfo->port; - int type = pinfo->type; int serverSocket; struct sockaddr_in server_addr; @@ -76,10 +85,10 @@ static void *bindPort(void *sarg) { int addr_len = sizeof(clientAddr); int client; char buffer[BUFFER_SIZE]; - int iDataNum; + int iDataNum = 0; if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - perror("socket"); + printf("socket() fail: %s", strerror(errno)); return NULL; } @@ -89,65 +98,67 @@ static void *bindPort(void *sarg) { server_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(serverSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { - perror("connect"); + printf("port:%d bind() fail: %s", port, strerror(errno)); return NULL; } if (listen(serverSocket, 5) < 0) { - perror("listen"); + printf("listen() fail: %s", strerror(errno)); return NULL; } - printf("Bind port: %d success\n", port); + //printf("Bind port: %d success\n", port); while (1) { client = accept(serverSocket, (struct sockaddr *)&clientAddr, (socklen_t *)&addr_len); if (client < 0) { - perror("accept"); + printf("accept() fail: %s", strerror(errno)); continue; } - printf("=================================\n"); - - printf("Client ip is %s, Server port is %d\n", inet_ntoa(clientAddr.sin_addr), port); - while (1) { - buffer[0] = '\0'; - iDataNum = recv(client, buffer, BUFFER_SIZE, 0); - - if (iDataNum < 0) { - perror("recv null"); - continue; - } - if (iDataNum > 0) { - buffer[iDataNum] = '\0'; - printf("read msg:%s\n", buffer); - if (strcmp(buffer, "quit") == 0) break; - buffer[0] = '\0'; - - sprintf(buffer, "ack port_%d", port); - printf("send ack msg:%s\n", buffer); - - send(client, buffer, strlen(buffer), 0); + + memset(buffer, 0, BUFFER_SIZE); + int nleft, nread; + char *ptr = buffer; + nleft = pinfo->pktLen; + while (nleft > 0) { + nread = recv(client, ptr, BUFFER_SIZE, 0); + + if (nread == 0) { break; - } + } else if (nread < 0) { + if (errno == EINTR) { + continue; + } else { + printf("recv Client: %s pkg from TCP port: %d fail:%s.\n", inet_ntoa(clientAddr.sin_addr), port, strerror(errno)); + close(serverSocket); + return NULL; + } + } else { + nleft -= nread; + ptr += nread; + iDataNum += nread; + } + } + + printf("recv Client: %s pkg from TCP port: %d, pkg len: %d\n", inet_ntoa(clientAddr.sin_addr), port, iDataNum); + if (iDataNum > 0) { + send(client, buffer, iDataNum, 0); + break; } - printf("=================================\n"); } close(serverSocket); return NULL; } -static void *bindUPort(void *sarg) { - info *pinfo = (info *)sarg; +static void *bindUdpPort(void *sarg) { + info_s *pinfo = (info_s *)sarg; int port = pinfo->port; - int type = pinfo->type; int serverSocket; struct sockaddr_in server_addr; struct sockaddr_in clientAddr; - int addr_len = sizeof(clientAddr); - int client; char buffer[BUFFER_SIZE]; int iDataNum; - + if ((serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); return NULL; @@ -164,10 +175,9 @@ static void *bindUPort(void *sarg) { } socklen_t sin_size; - printf("Bind port: %d success\n", port); while (1) { - buffer[0] = '\0'; + memset(buffer, 0, BUFFER_SIZE); sin_size = sizeof(*(struct sockaddr *)&server_addr); @@ -178,21 +188,10 @@ static void *bindUPort(void *sarg) { continue; } if (iDataNum > 0) { - printf("=================================\n"); - - printf("Client ip is %s, Server port is %d\n", inet_ntoa(clientAddr.sin_addr), port); - buffer[iDataNum] = '\0'; - printf("Read msg from udp:%s\n", buffer); - if (strcmp(buffer, "quit") == 0) break; - buffer[0] = '\0'; + printf("recv Client: %s pkg from UDP port: %d, pkg len: %d\n", inet_ntoa(clientAddr.sin_addr), port, iDataNum); + //printf("Read msg from udp:%s ... %s\n", buffer, buffer+iDataNum-16); - sprintf(buffer, "ack port_%d by udp", port); - printf("Send ack msg by udp:%s\n", buffer); - - sendto(serverSocket, buffer, strlen(buffer), 0, (struct sockaddr *)&clientAddr, (int)sin_size); - - send(client, buffer, strlen(buffer), 0); - printf("=================================\n"); + sendto(serverSocket, buffer, iDataNum, 0, (struct sockaddr *)&clientAddr, (int)sin_size); } } @@ -202,39 +201,44 @@ static void *bindUPort(void *sarg) { int main(int argc, char *argv[]) { - SArguments arguments = {"127.0.0.1", 6020, 6050}; + SArguments arguments = {"127.0.0.1", 6030, 6060, 1000}; argp_parse(&argp, argc, argv, 0, 0, &arguments); + if (arguments.pktLen > MAX_PKG_LEN) { + printf("test pkg len overflow: %d, max len not greater than %d bytes\n", arguments.pktLen, MAX_PKG_LEN); + exit(0); + } + int port = arguments.port; - int num = arguments.max_port - arguments.port; + int num = arguments.max_port - arguments.port + 1; if (num < 0) { num = 1; } pthread_t *pids = malloc(2 * num * sizeof(pthread_t)); - info * infos = malloc(num * sizeof(info)); - info * uinfos = malloc(num * sizeof(info)); + info_s * tinfos = malloc(num * sizeof(info_s)); + info_s * uinfos = malloc(num * sizeof(info_s)); for (size_t i = 0; i < num; i++) { - info *pinfo = infos++; - pinfo->port = port; - - if (pthread_create(pids + i, NULL, bindPort, pinfo) != 0) //创建线程 - { //创建线程失败 - printf("创建线程失败: %d.\n", port); - exit(0); + info_s *tcpInfo = tinfos + i; + tcpInfo->port = port + i; + tcpInfo->pktLen = arguments.pktLen; + + if (pthread_create(pids + i, NULL, bindTcpPort, tcpInfo) != 0) + { + printf("create thread fail, port:%d.\n", port); + exit(-1); } - info *uinfo = uinfos++; - uinfo->port = port; - uinfo->type = 1; - port++; - if (pthread_create(pids + num + i, NULL, bindUPort, uinfo) != 0) //创建线程 - { //创建线程失败 - printf("创建线程失败: %d.\n", port); - exit(0); + info_s *udpInfo = uinfos + i; + udpInfo->port = port + i; + if (pthread_create(pids + num + i, NULL, bindUdpPort, udpInfo) != 0) + { + printf("create thread fail, port:%d.\n", port); + exit(-1); } } + for (int i = 0; i < num; i++) { pthread_join(pids[i], NULL); pthread_join(pids[(num + i)], NULL); diff --git a/src/mnode/CMakeLists.txt b/src/mnode/CMakeLists.txt index f5b9fbf74763bc331c809e0f5d5d6b9eca6593d8..ff5c9335b654edbdb7bbf6c081b38b265923d645 100644 --- a/src/mnode/CMakeLists.txt +++ b/src/mnode/CMakeLists.txt @@ -1,11 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) @@ -13,5 +9,4 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(mnode ${SRC}) - #TARGET_LINK_LIBRARIES(mnode trpc tutil pthread) ENDIF () \ No newline at end of file diff --git a/src/mnode/src/mnodePeer.c b/src/mnode/src/mnodePeer.c index 71b8b1ea843dc799e18d38ac5fe5b464ab1170d7..7b4b4e4343c8fd7f4f2655162b25363da5c71394 100644 --- a/src/mnode/src/mnodePeer.c +++ b/src/mnode/src/mnodePeer.c @@ -75,6 +75,11 @@ int32_t mnodeProcessPeerReq(SMnodeMsg *pMsg) { } void mnodeProcessPeerRsp(SRpcMsg *pMsg) { + if (!sdbIsMaster()) { + mError("%p, msg:%s is not processed for it is not master", pMsg->ahandle, taosMsg[pMsg->msgType]); + return; + } + if (tsMnodeProcessPeerRspFp[pMsg->msgType]) { (*tsMnodeProcessPeerRspFp[pMsg->msgType])(pMsg); } else { diff --git a/src/mnode/src/mnodeVgroup.c b/src/mnode/src/mnodeVgroup.c index e1c81db0ac83c03bf6f310c7191e0342c6a4e3db..ff253c1935376e337125ab8ae5e5ef702651c208 100644 --- a/src/mnode/src/mnodeVgroup.c +++ b/src/mnode/src/mnodeVgroup.c @@ -164,9 +164,9 @@ static int32_t mnodeVgroupActionUpdate(SSdbOper *pOper) { // reset vgid status on vgroup changed - mDebug("vgId:%d, reset sync status to unsynced", pVgroup->vgId); + mDebug("vgId:%d, reset sync status to offline", pVgroup->vgId); for (int32_t v = 0; v < pVgroup->numOfVnodes; ++v) { - pVgroup->vnodeGid[v].role = TAOS_SYNC_ROLE_UNSYNCED; + pVgroup->vnodeGid[v].role = TAOS_SYNC_ROLE_OFFLINE; } mnodeDecVgroupRef(pVgroup); diff --git a/src/os/inc/osFile.h b/src/os/inc/osFile.h index e99c64c2e04165bb42006935385c7f06395a8ac1..dc19c8177c62307ca110486c130f6a6b56047ef4 100644 --- a/src/os/inc/osFile.h +++ b/src/os/inc/osFile.h @@ -56,18 +56,6 @@ int32_t taosFileRename(char *fullPath, char *suffix, char delimiter, char **dstP // TAOS_OS_FUNC_FILE_GETTMPFILEPATH void taosGetTmpfilePath(const char *fileNamePrefix, char *dstPath); -#ifdef TAOS_OS_FUNC_FILE_ISDIR - #define S_ISDIR(m) (((m) & 0170000) == (0040000)) -#endif - -#ifdef TAOS_OS_FUNC_FILE_ISREG - #define S_ISREG(m) !(S_ISDIR(m)) -#endif - -#ifdef TAOS_OS_FUNC_FILE_ISLNK - #define S_ISLNK(m) 0 -#endif - #ifndef TAOS_OS_FUNC_FILE_FTRUNCATE #define taosFtruncate ftruncate #endif diff --git a/src/os/inc/osMath.h b/src/os/inc/osMath.h index 168f6607f05c2b013762e30e7eb07bf5e87ab389..9935f94d39ef0431b7c9b1a524b956e6fafe9f4f 100644 --- a/src/os/inc/osMath.h +++ b/src/os/inc/osMath.h @@ -21,6 +21,7 @@ extern "C" { #endif #define POW2(x) ((x) * (x)) +#define ABS(x) ((x) > 0 ? (x) : -(x)) #ifndef TAOS_OS_FUNC_MATH #define SWAP(a, b, c) \ diff --git a/src/os/inc/osSocket.h b/src/os/inc/osSocket.h index 10fed022bb9cafbb7c613473fab6b9c4b9e5d277..58f95c3c2da4394321f63db9171005f6f1547b1c 100644 --- a/src/os/inc/osSocket.h +++ b/src/os/inc/osSocket.h @@ -32,7 +32,12 @@ extern "C" { x = FD_INITIALIZER; \ } \ } -#endif + typedef int SOCKET; +#endif + +#ifndef TAOS_OS_DEF_EPOLL + #define TAOS_EPOLL_WAIT_TIME -1 +#endif #define taosClose(x) taosCloseSocket(x) @@ -54,11 +59,11 @@ extern "C" { #endif // TAOS_OS_FUNC_SOCKET -int taosSetNonblocking(int sock, int on); +int taosSetNonblocking(SOCKET sock, int on); void taosBlockSIGPIPE(); // TAOS_OS_FUNC_SOCKET_SETSOCKETOPT -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen); #ifdef __cplusplus } diff --git a/src/os/inc/osWindows.h b/src/os/inc/osWindows.h index 1118b3c64b7bd1296a2b083143e444a665c2264e..caab61536e0aeca6fd0acca0fa5cc52362043b8b 100644 --- a/src/os/inc/osWindows.h +++ b/src/os/inc/osWindows.h @@ -18,9 +18,7 @@ #include #include -#include #include -#include #include #include #include @@ -35,15 +33,18 @@ #include #include #include -#include -#include -#include -#include #include "winsock2.h" #include #include #include -#include +#include +#include +#include "msvcProcess.h" +#include "msvcDirect.h" +#include "msvcFcntl.h" +#include "msvcStdio.h" +#include "sys/msvcStat.h" +#include "sys/msvcTypes.h" #ifdef __cplusplus extern "C" { @@ -85,11 +86,16 @@ extern "C" { #define TAOS_OS_FUNC_SOCKET #define TAOS_OS_FUNC_SOCKET_SETSOCKETOPT #define TAOS_OS_FUNC_SOCKET_OP - #define taosSend(sockfd, buf, len, flags) send(sockfd, buf, len, flags) - #define taosSendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto(sockfd, buf, len, flags, dest_addr, addrlen) - #define taosWriteSocket(fd, buf, len) send(fd, buf, len, 0) - #define taosReadSocket(fd, buf, len) recv(fd, buf, len, 0) - #define taosCloseSocket(fd) closesocket(fd) + #define taosSend(sockfd, buf, len, flags) send((SOCKET)sockfd, buf, len, flags) + #define taosSendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto((SOCKET)sockfd, buf, len, flags, dest_addr, addrlen) + #define taosWriteSocket(fd, buf, len) send((SOCKET)fd, buf, len, 0) + #define taosReadSocket(fd, buf, len) recv((SOCKET)fd, buf, len, 0) + #define taosCloseSocket(fd) closesocket((SOCKET)fd) +typedef SOCKET eventfd_t; +#define eventfd(a, b) -1 + +#define TAOS_OS_DEF_EPOLL + #define TAOS_EPOLL_WAIT_TIME 100 #define TAOS_OS_FUNC_STRING_WCHAR int twcslen(const wchar_t *wcs); @@ -105,6 +111,9 @@ extern "C" { #define taosStrdupImp(str) _strdup(str) #define taosStrndupImp(str, size) _strndup(str, size) +char *stpcpy (char *dest, const char *src); +char *stpncpy (char *dest, const char *src, size_t n); + #define TAOS_OS_FUNC_SYSINFO #define TAOS_OS_FUNC_TIME_DEF @@ -121,7 +130,6 @@ extern "C" { typedef int (*__compar_fn_t)(const void *, const void *); #define ssize_t int #define bzero(ptr, size) memset((ptr), 0, (size)) -#define mkdir(pathname, mode) _mkdir(pathname) #define strcasecmp _stricmp #define strncasecmp _strnicmp #define wcsncasecmp _wcsnicmp @@ -133,7 +141,6 @@ typedef int (*__compar_fn_t)(const void *, const void *); #define twrite write #define getpid _getpid -int gettimeofday(struct timeval *tv, struct timezone *tz); struct tm *localtime_r(const time_t *timep, struct tm *result); char * strptime(const char *buf, const char *fmt, struct tm *tm); char * strsep(char **stringp, const char *delim); @@ -141,11 +148,8 @@ char * getpass(const char *prefix); int flock(int fd, int option); int fsync(int filedes); char * strndup(const char *s, size_t n); - -// for function open in stat.h -#define S_IRWXU _S_IREAD -#define S_IRWXG _S_IWRITE -#define S_IRWXO _S_IWRITE +char * dirname(char *pszPathname); +int gettimeofday(struct timeval *ptv, void *pTimeZone); // for access function in io.h #define F_OK 00 //Existence only diff --git a/src/os/src/alpine/CMakeLists.txt b/src/os/src/alpine/CMakeLists.txt index 79cbf917e2cf4cfa41492379452c7210da0d5e5e..b5e739c24ce7ec3ef3ffc537ca8769706f7b56de 100644 --- a/src/os/src/alpine/CMakeLists.txt +++ b/src/os/src/alpine/CMakeLists.txt @@ -1,12 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) AUX_SOURCE_DIRECTORY(. SRC) - ADD_LIBRARY(os ${SRC}) TARGET_LINK_LIBRARIES(os m rt) diff --git a/src/os/src/alpine/alpineEnv.c b/src/os/src/alpine/alpineEnv.c index 4f84412075766dae66e9e55831b4bf290af987e2..811d98ad7f8c34851e70ccbd190a13b74d865703 100644 --- a/src/os/src/alpine/alpineEnv.c +++ b/src/os/src/alpine/alpineEnv.c @@ -18,7 +18,10 @@ #include "tglobal.h" void osInit() { - strcpy(configDir, "/etc/taos"); + if (configDir[0] == 0) { + strcpy(configDir, "/etc/taos"); + } + strcpy(tsVnodeDir, ""); strcpy(tsDnodeDir, ""); strcpy(tsMnodeDir, ""); diff --git a/src/os/src/darwin/CMakeLists.txt b/src/os/src/darwin/CMakeLists.txt index 1568d16164629ddaadc34ffe52c7ab460767fdc2..c4cb28aa05e4716ca98c2687ce41d436b1300bb2 100644 --- a/src/os/src/darwin/CMakeLists.txt +++ b/src/os/src/darwin/CMakeLists.txt @@ -1,10 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) AUX_SOURCE_DIRECTORY(. SRC) - ADD_LIBRARY(os ${SRC}) diff --git a/src/os/src/darwin/darwinEnv.c b/src/os/src/darwin/darwinEnv.c index 7e1031a5af6e2ed59fae7fa607d1ce7fc3790043..6adebabec01ae378a4c5f3d82389508334210972 100644 --- a/src/os/src/darwin/darwinEnv.c +++ b/src/os/src/darwin/darwinEnv.c @@ -18,7 +18,10 @@ #include "tglobal.h" void osInit() { - strcpy(configDir, "~/TDengine/cfg"); + if (configDir[0] == 0) { + strcpy(configDir, "~/TDengine/cfg"); + } + strcpy(tsVnodeDir, ""); strcpy(tsDnodeDir, ""); strcpy(tsMnodeDir, ""); diff --git a/src/os/src/darwin/darwinSocket.c b/src/os/src/darwin/darwinSocket.c index e51f2c4fba4f91474189709b9b410bb886a2e9b3..69a4666d34394ef71da1d18559f8ba2f8f9cb290 100644 --- a/src/os/src/darwin/darwinSocket.c +++ b/src/os/src/darwin/darwinSocket.c @@ -16,7 +16,7 @@ #define _DEFAULT_SOURCE #include "os.h" -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { if (level == SOL_SOCKET && optname == SO_SNDBUF) { return 0; } diff --git a/src/os/src/detail/CMakeLists.txt b/src/os/src/detail/CMakeLists.txt index 3ea7f97985f52ac96f625ba5f366441f486684a9..9f710e3ddffbe9342857cc3e92348f70c586f86e 100644 --- a/src/os/src/detail/CMakeLists.txt +++ b/src/os/src/detail/CMakeLists.txt @@ -1,16 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_WINDOWS) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) -ENDIF () - -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(.) AUX_SOURCE_DIRECTORY(. SRC) SET_SOURCE_FILES_PROPERTIES(osSysinfo.c PROPERTIES COMPILE_FLAGS -w) diff --git a/src/os/src/detail/osSocket.c b/src/os/src/detail/osSocket.c index 7e4031eff930ff143ae1ba7f61390bd6621ec6fe..c8ad6a5acccc81fc08ebf1b9e542817914949452 100644 --- a/src/os/src/detail/osSocket.c +++ b/src/os/src/detail/osSocket.c @@ -19,7 +19,7 @@ #ifndef TAOS_OS_FUNC_SOCKET -int taosSetNonblocking(int sock, int on) { +int taosSetNonblocking(SOCKET sock, int on) { int flags = 0; if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); @@ -53,7 +53,7 @@ void taosBlockSIGPIPE() { #ifndef TAOS_OS_FUNC_SOCKET_SETSOCKETOPT -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); } diff --git a/src/os/src/linux64/CMakeLists.txt b/src/os/src/linux64/CMakeLists.txt index 0c577374ed855ad79efc4bd7c591587dea5e9f37..752326cc1de74550afac386ad5ac84f6d2f48990 100644 --- a/src/os/src/linux64/CMakeLists.txt +++ b/src/os/src/linux64/CMakeLists.txt @@ -1,10 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) AUX_SOURCE_DIRECTORY(. SRC) ADD_LIBRARY(os ${SRC}) diff --git a/src/os/src/linux64/linuxEnv.c b/src/os/src/linux64/linuxEnv.c index 4f84412075766dae66e9e55831b4bf290af987e2..811d98ad7f8c34851e70ccbd190a13b74d865703 100644 --- a/src/os/src/linux64/linuxEnv.c +++ b/src/os/src/linux64/linuxEnv.c @@ -18,7 +18,10 @@ #include "tglobal.h" void osInit() { - strcpy(configDir, "/etc/taos"); + if (configDir[0] == 0) { + strcpy(configDir, "/etc/taos"); + } + strcpy(tsVnodeDir, ""); strcpy(tsDnodeDir, ""); strcpy(tsMnodeDir, ""); diff --git a/src/os/src/windows/CMakeLists.txt b/src/os/src/windows/CMakeLists.txt index 60fab63cd12a3f2c976c458c6be686009350ee96..588d3b7f68ea6f54051d4723a0730b9316f53157 100644 --- a/src/os/src/windows/CMakeLists.txt +++ b/src/os/src/windows/CMakeLists.txt @@ -1,15 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) AUX_SOURCE_DIRECTORY(. SRC) - ADD_LIBRARY(os ${SRC}) -TARGET_LINK_LIBRARIES(os winmm IPHLPAPI ws2_32) +TARGET_LINK_LIBRARIES(os winmm IPHLPAPI ws2_32 MsvcLibXw64) diff --git a/src/os/src/windows/w64Dir.c b/src/os/src/windows/w64Dir.c new file mode 100644 index 0000000000000000000000000000000000000000..7816dac0d61c22155a8cdbcf55e6d87d932762c2 --- /dev/null +++ b/src/os/src/windows/w64Dir.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "tulog.h" + +void taosRemoveDir(char *rootDir) { + uError("%s not implemented yet", __FUNCTION__); +} + +int taosMkDir(const char *path, mode_t mode) { + uError("%s not implemented yet", __FUNCTION__); + return -1; +} + +void taosMvDir(char* destDir, char *srcDir) { + uError("%s not implemented yet", __FUNCTION__); +} diff --git a/src/os/src/windows/w64Env.c b/src/os/src/windows/w64Env.c index 840a8d9f7a80c382e2eda40806093b2ff2d36f2b..c6046ecae7e369c7ae3c9198ee0727b2d3c4c653 100644 --- a/src/os/src/windows/w64Env.c +++ b/src/os/src/windows/w64Env.c @@ -18,8 +18,13 @@ #include "tglobal.h" #include "tulog.h" +extern void taosWinSocketInit(); + void osInit() { - strcpy(configDir, "C:/TDengine/cfg"); + if (configDir[0] == 0) { + strcpy(configDir, "~/TDengine/cfg"); + } + strcpy(tsVnodeDir, "C:/TDengine/data"); strcpy(tsDnodeDir, ""); strcpy(tsMnodeDir, ""); @@ -27,4 +32,5 @@ void osInit() { strcpy(tsLogDir, "C:/TDengine/log"); strcpy(tsScriptDir, "C:/TDengine/script"); strcpy(tsOsName, "Windows"); + taosWinSocketInit(); } \ No newline at end of file diff --git a/src/os/src/windows/w64Socket.c b/src/os/src/windows/w64Socket.c index dbe501b6454000adf8e250e0acfbed980ac55785..dd8961da4048f499bf339147506c767f7ead60e2 100644 --- a/src/os/src/windows/w64Socket.c +++ b/src/os/src/windows/w64Socket.c @@ -34,7 +34,7 @@ void taosWinSocketInit() { } } -int taosSetNonblocking(int sock, int on) { +int taosSetNonblocking(SOCKET sock, int on) { u_long mode; if (on) { mode = 1; @@ -48,7 +48,7 @@ int taosSetNonblocking(int sock, int on) { void taosBlockSIGPIPE() {} -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { if (level == SOL_SOCKET && optname == TCP_KEEPCNT) { return 0; } diff --git a/src/os/src/windows/w64String.c b/src/os/src/windows/w64String.c index e3ac7d88322b9b1722460c7c0415d7a6c932c620..0d9a28e288d9ea5885769b4fa3537dd9ba689f6e 100644 --- a/src/os/src/windows/w64String.c +++ b/src/os/src/windows/w64String.c @@ -129,3 +129,28 @@ int tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int bytes) { return ret; #endif } + + +/* Copy memory to memory until the specified number of bytes +has been copied, return pointer to following byte. +Overlap is NOT handled correctly. */ +void *mempcpy(void *dest, const void *src, size_t len) { + return (char*)memcpy(dest, src, len) + len; +} + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +char *stpcpy (char *dest, const char *src) { + size_t len = strlen (src); + return (char*)memcpy(dest, src, len + 1) + len; +} + +/* Copy no more than N characters of SRC to DEST, returning the address of + the terminating '\0' in DEST, if any, or else DEST + N. */ +char *stpncpy (char *dest, const char *src, size_t n) { + size_t size = strnlen (src, n); + memcpy (dest, src, size); + dest += size; + if (size == n) + return dest; + return memset (dest, '\0', n - size); +} \ No newline at end of file diff --git a/src/plugins/http/CMakeLists.txt b/src/plugins/http/CMakeLists.txt index 4dbfde8ce69960bffebb3558ab476601415ce40b..94f5305f289ecb01e445effc3a159d9c56db3631 100644 --- a/src/plugins/http/CMakeLists.txt +++ b/src/plugins/http/CMakeLists.txt @@ -1,20 +1,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) ADD_LIBRARY(http ${SRC}) -# TARGET_LINK_LIBRARIES(http taos_static z) TARGET_LINK_LIBRARIES(http taos z) IF (TD_ADMIN) diff --git a/src/plugins/http/src/httpServer.c b/src/plugins/http/src/httpServer.c index 5c910a331124813e15bb35dffc983f0ca9a3aae6..8ee92be31c004843a9c03342bf20d99dd02118ff 100644 --- a/src/plugins/http/src/httpServer.c +++ b/src/plugins/http/src/httpServer.c @@ -38,6 +38,7 @@ static void httpStopThread(HttpThread* pThread) { eventfd_t fd = eventfd(1, 0); if (fd == -1) { httpError("%s, failed to create eventfd, will call pthread_cancel instead, which may result in data corruption: %s", pThread->label, strerror(errno)); + pThread->stop = true; pthread_cancel(pThread->thread); } else if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) { httpError("%s, failed to call epoll_ctl, will call pthread_cancel instead, which may result in data corruption: %s", pThread->label, strerror(errno)); diff --git a/src/plugins/monitor/CMakeLists.txt b/src/plugins/monitor/CMakeLists.txt index 9b6cbfeef3dc6b8fdc4271888c7615912a247a42..ba30edd0e48590a124fadda7723b7c22a7e92061 100644 --- a/src/plugins/monitor/CMakeLists.txt +++ b/src/plugins/monitor/CMakeLists.txt @@ -1,16 +1,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(./src SRC) + +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(./src SRC) ADD_LIBRARY(monitor ${SRC}) -# TARGET_LINK_LIBRARIES(monitor taos_static) TARGET_LINK_LIBRARIES(monitor taos) ENDIF () diff --git a/src/plugins/monitor/src/monitorMain.c b/src/plugins/monitor/src/monitorMain.c index 644835abc0591ad9da66600b06dd7c0f996b5e33..32f5966e2d7818edffcfa379967bad7b35270278 100644 --- a/src/plugins/monitor/src/monitorMain.c +++ b/src/plugins/monitor/src/monitorMain.c @@ -152,9 +152,9 @@ static void dnodeBuildMonitorSql(char *sql, int32_t cmd) { if (cmd == MONITOR_CMD_CREATE_DB) { snprintf(sql, SQL_LENGTH, - "create database if not exists %s replica 1 days 10 keep 30 cache 1 " - "blocks 2 maxtables 16 precision 'us'", - tsMonitorDbName); + "create database if not exists %s replica 1 days 10 keep 30 cache %d " + "blocks %d maxtables 16 precision 'us'", + tsMonitorDbName, TSDB_MIN_CACHE_BLOCK_SIZE, TSDB_MIN_TOTAL_BLOCKS); } else if (cmd == MONITOR_CMD_CREATE_MT_DN) { snprintf(sql, SQL_LENGTH, "create table if not exists %s.dn(ts timestamp" diff --git a/src/plugins/mqtt/CMakeLists.txt b/src/plugins/mqtt/CMakeLists.txt index 929232cfe1b6564b2fd0586d11b629279a7a8365..72312ffcec5899fc997b55f81d7262cb67b6c309 100644 --- a/src/plugins/mqtt/CMakeLists.txt +++ b/src/plugins/mqtt/CMakeLists.txt @@ -1,20 +1,15 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MQTT-C/include) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MQTT-C/examples/templates) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(mqtt ${SRC}) -# TARGET_LINK_LIBRARIES(mqtt taos_static cJson mqttc) TARGET_LINK_LIBRARIES(mqtt taos cJson mqttc) IF (TD_ADMIN) diff --git a/src/query/CMakeLists.txt b/src/query/CMakeLists.txt index 625b85d908537c361b446bee1bb6b94d5e2140e5..e2bee4285fd94fc71899247f7d2ed94849f30a93 100644 --- a/src/query/CMakeLists.txt +++ b/src/query/CMakeLists.txt @@ -1,20 +1,17 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(query ${SRC}) - TARGET_LINK_LIBRARIES(query tsdb tutil m rt) -ENDIF () - -ADD_SUBDIRECTORY(tests) +AUX_SOURCE_DIRECTORY(src SRC) +ADD_LIBRARY(query ${SRC}) SET_SOURCE_FILES_PROPERTIES(src/sql.c PROPERTIES COMPILE_FLAGS -w) +IF (TD_LINUX) + TARGET_LINK_LIBRARIES(query tsdb tutil m rt) + ADD_SUBDIRECTORY(tests) +ELSEIF (TD_WINDOWS) + TARGET_LINK_LIBRARIES(query tsdb tutil) +ENDIF () diff --git a/src/query/inc/qUtil.h b/src/query/inc/qUtil.h index ed7c7e8845317ac754758b8553e3f65ba8da4544..b7f57bf1b5a622a8d1f72632b18ced7fb4985872 100644 --- a/src/query/inc/qUtil.h +++ b/src/query/inc/qUtil.h @@ -52,7 +52,7 @@ static FORCE_INLINE char *getPosInResultPage(SQueryRuntimeEnv *pRuntimeEnv, int3 SQuery *pQuery = pRuntimeEnv->pQuery; // tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pos.pageId); - int32_t realRowId = pResult->pos.rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery); + int32_t realRowId = (int32_t)(pResult->pos.rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery)); return ((char *)page->data) + pRuntimeEnv->offset[columnIndex] * pRuntimeEnv->numOfRowsPerPage + pQuery->pSelectExpr[columnIndex].bytes * realRowId; } diff --git a/src/query/src/qAst.c b/src/query/src/qAst.c index 6d9e5856e227cab259d863c588300b64092ccb8e..afa3618a96df6fd315a5fca7e5652497a13ea464 100644 --- a/src/query/src/qAst.c +++ b/src/query/src/qAst.c @@ -1051,7 +1051,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { } else if (*e == ',') { size_t len = e - cond; char* p = exception_malloc(len + VARSTR_HEADER_SIZE); - STR_WITH_SIZE_TO_VARSTR(p, cond, len); + STR_WITH_SIZE_TO_VARSTR(p, cond, (VarDataLenT)len); cond += len; taosArrayPush(pVal->arr, &p); } @@ -1061,7 +1061,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { size_t len = strlen(cond) + VARSTR_HEADER_SIZE; char* p = exception_malloc(len); - STR_WITH_SIZE_TO_VARSTR(p, cond, len - VARSTR_HEADER_SIZE); + STR_WITH_SIZE_TO_VARSTR(p, cond, (VarDataLenT)(len - VARSTR_HEADER_SIZE)); taosArrayPush(pVal->arr, &p); } diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index c64f9d5c48785dd0b3269588578383cf10e77cf5..7f6fac3631495fd9b2d3448c17af069b9bae3f7a 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -49,6 +49,11 @@ #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} +#define TIME_WINDOW_COPY(_dst, _src) do {\ + _dst.skey = _src.skey;\ + _dst.ekey = _src.ekey;\ +} while (0); + enum { // when query starts to execute, this status will set QUERY_NOT_COMPLETED = 0x1u, @@ -152,7 +157,7 @@ bool doFilterData(SQuery *pQuery, int32_t elemPos) { for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) { SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k]; - char *pElem = pFilterInfo->pData + pFilterInfo->info.bytes * elemPos; + char *pElem = (char*)pFilterInfo->pData + pFilterInfo->info.bytes * elemPos; if (isNull(pElem, pFilterInfo->info.type)) { return false; } @@ -414,7 +419,7 @@ static SWindowResult *doSetTimeWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SWin pWindowResInfo->pResult = (SWindowResult *)t; - int32_t inc = newCap - pWindowResInfo->capacity; + int32_t inc = (int32_t)newCap - pWindowResInfo->capacity; memset(&pWindowResInfo->pResult[pWindowResInfo->capacity], 0, sizeof(SWindowResult) * inc); pRuntimeEnv->summary.internalSupSize += (pQuery->numOfOutput * sizeof(SResultInfo) + pRuntimeEnv->interBufSize) * inc; @@ -423,7 +428,7 @@ static SWindowResult *doSetTimeWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SWin createQueryResultInfo(pQuery, &pWindowResInfo->pResult[i], pRuntimeEnv->stableQuery, pRuntimeEnv->interBufSize); } - pWindowResInfo->capacity = newCap; + pWindowResInfo->capacity = (int32_t)newCap; } // add a new result set for a new group @@ -512,7 +517,7 @@ static int32_t addNewWindowResultBuf(SWindowResult *pWindowRes, SDiskbasedResult // set the number of rows in current disk page if (pWindowRes->pos.pageId == -1) { // not allocated yet, allocate new buffer pWindowRes->pos.pageId = pageId; - pWindowRes->pos.rowId = pData->num++; + pWindowRes->pos.rowId = (int32_t)(pData->num++); assert(pWindowRes->pos.pageId >= 0); } @@ -816,7 +821,7 @@ static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) //todo binary search static void* getDataBlockImpl(SArray* pDataBlock, int32_t colId) { - int32_t numOfCols = taosArrayGetSize(pDataBlock); + int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData *p = taosArrayGet(pDataBlock, i); @@ -860,7 +865,7 @@ static char *getDataBlock(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas } // here the pQuery->colList and sas->colList are identical - int32_t numOfCols = taosArrayGetSize(pDataBlock); + int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); for (int32_t i = 0; i < pQuery->numOfCols; ++i) { SColumnInfo *pColMsg = &pQuery->colList[i]; @@ -1078,7 +1083,7 @@ static char *getGroupbyColumnData(SQuery *pQuery, int16_t *type, int16_t *bytes, * stage, the remain tables may not have the required column in cache actually. So, the validation of required * column in cache with the corresponding schema is reinforced. */ - int32_t numOfCols = taosArrayGetSize(pDataBlock); + int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData *p = taosArrayGet(pDataBlock, i); @@ -1102,7 +1107,7 @@ static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, int32_t offset) { return TS_JOIN_TAG_NOT_EQUALS; } - TSKEY key = *(TSKEY *)(pCtx[0].aInputElemBuf + TSDB_KEYSIZE * offset); + TSKEY key = *(TSKEY *)((char*)pCtx[0].aInputElemBuf + TSDB_KEYSIZE * offset); #if defined(_DEBUG_VIEW) printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n", @@ -1341,7 +1346,7 @@ static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBl if (QUERY_IS_INTERVAL_QUERY(pQuery)) { numOfRes = doCheckQueryCompleted(pRuntimeEnv, lastKey, pWindowResInfo); } else { - numOfRes = getNumOfResult(pRuntimeEnv); + numOfRes = (int32_t)getNumOfResult(pRuntimeEnv); // update the number of output result if (numOfRes > 0 && pQuery->checkBuffer == 1) { @@ -1355,6 +1360,11 @@ static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBl if ((pQuery->limit.limit >= 0) && (pQuery->limit.limit + pQuery->limit.offset) <= numOfRes) { setQueryStatus(pQuery, QUERY_COMPLETED); } + + if (((pTableQInfo->lastKey > pTableQInfo->win.ekey) && QUERY_IS_ASC_QUERY(pQuery)) || + ((pTableQInfo->lastKey < pTableQInfo->win.ekey) && (!QUERY_IS_ASC_QUERY(pQuery)))) { + setQueryStatus(pQuery, QUERY_COMPLETED); + } } } @@ -1419,7 +1429,7 @@ void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void* inputData, TSKEY } } else if (functionId == TSDB_FUNC_INTERP) { SInterpInfoDetail *pInterpInfo = GET_RES_INFO(pCtx)->interResultBuf; - pInterpInfo->type = pQuery->fillType; + pInterpInfo->type = (int8_t)pQuery->fillType; pInterpInfo->ts = pQuery->window.skey; pInterpInfo->primaryCol = (colId == PRIMARYKEY_TIMESTAMP_COL_INDEX); @@ -1718,7 +1728,7 @@ static bool needReverseScan(SQuery *pQuery) { } if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) { - int32_t order = pQuery->pSelectExpr[i].base.arg->argValue.i64; + int32_t order = (int32_t)pQuery->pSelectExpr[i].base.arg->argValue.i64; return order != pQuery->order.order; } } @@ -1931,7 +1941,7 @@ static int32_t getInitialPageNum(SQInfo *pQInfo) { num = 128; } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) { // time window query, allocate one page for each table size_t s = pQInfo->tableqinfoGroupInfo.numOfTables; - num = MAX(s, INITIAL_RESULT_ROWS_VALUE); + num = (int32_t)(MAX(s, INITIAL_RESULT_ROWS_VALUE)); } else { // for super table query, one page for each subset num = 1; // pQInfo->pSidSet->numOfSubSet; } @@ -1943,7 +1953,7 @@ static int32_t getInitialPageNum(SQInfo *pQInfo) { static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) { SQuery* pQuery = pRuntimeEnv->pQuery; - *rowsize = pQuery->rowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery); + *rowsize = (int32_t)(pQuery->rowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery)); int32_t overhead = sizeof(tFilePage); // one page contains at least two rows @@ -1994,8 +2004,8 @@ static bool needToLoadDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDat SDataStatis* pDataBlockst = &pDataStatis[index]; if (pFilterInfo->info.type == TSDB_DATA_TYPE_FLOAT) { - float minval = *(double *)(&pDataBlockst->min); - float maxval = *(double *)(&pDataBlockst->max); + float minval = (float)(*(double *)(&pDataBlockst->min)); + float maxval = (float)(*(double *)(&pDataBlockst->max)); for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) { if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval)) { @@ -2236,8 +2246,8 @@ static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pB SResultRec *pRec = &pQuery->rec; if (pQuery->rec.capacity - pQuery->rec.rows < pBlockInfo->rows) { - int32_t remain = pRec->capacity - pRec->rows; - int32_t newSize = pRec->capacity + (pBlockInfo->rows - remain); + int32_t remain = (int32_t)(pRec->capacity - pRec->rows); + int32_t newSize = (int32_t)(pRec->capacity + (pBlockInfo->rows - remain)); for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t bytes = pQuery->pSelectExpr[i].bytes; @@ -2416,7 +2426,7 @@ void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable, void *tsdb) { if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP) { assert(pExprInfo->base.numOfParams == 1); - int16_t tagColId = pExprInfo->base.arg->argValue.i64; + int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); doSetTagValueInParam(tsdb, pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes); @@ -2441,7 +2451,7 @@ void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable, void *tsdb) { pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { assert(pFuncMsg->numOfParams == 1); - int16_t tagColId = pExprInfo->base.arg->argValue.i64; + int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); doSetTagValueInParam(tsdb, pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes); @@ -2649,7 +2659,7 @@ int32_t mergeIntoGroupResult(SQInfo *pQInfo) { int64_t st = taosGetTimestampMs(); int32_t ret = TSDB_CODE_SUCCESS; - int32_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); while (pQInfo->groupIndex < numOfGroups) { SArray *group = GET_TABLEGROUP(pQInfo, pQInfo->groupIndex); @@ -2689,7 +2699,7 @@ void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { } // check if all results has been sent to client - int32_t numOfGroup = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroup = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); if (pQInfo->numOfGroupResultPages == 0 && pQInfo->groupIndex == numOfGroup) { SET_STABLE_QUERY_OVER(pQInfo); return; @@ -2702,7 +2712,7 @@ void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { int32_t id = getGroupResultId(pQInfo->groupIndex - 1); SIDList list = getDataBufPagesIdList(pResultBuf, pQInfo->offset + id); - int32_t size = taosArrayGetSize(list); + int32_t size = (int32_t)(taosArrayGetSize(list)); int32_t offset = 0; for (int32_t j = 0; j < size; ++j) { @@ -2915,7 +2925,7 @@ int32_t flushFromResultBuf(SQInfo *pQInfo) { int32_t pageId = -1; int32_t capacity = pResultBuf->numOfRowsPerPage; - int32_t remain = pQuery->sdata[0]->num; + int32_t remain = (int32_t)pQuery->sdata[0]->num; int32_t offset = 0; while (remain > 0) { @@ -3133,7 +3143,7 @@ void forwardCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, int64_t output) { * * diff function is handled in multi-output function */ - pRuntimeEnv->pCtx[j].ptsOutputBuf += TSDB_KEYSIZE * output; + pRuntimeEnv->pCtx[j].ptsOutputBuf = (char*)pRuntimeEnv->pCtx[j].ptsOutputBuf + TSDB_KEYSIZE * output; } RESET_RESULT_INFO(pRuntimeEnv->pCtx[j].resultInfo); @@ -3193,7 +3203,7 @@ void skipResults(SQueryRuntimeEnv *pRuntimeEnv) { } } - updateNumOfResult(pRuntimeEnv, pQuery->rec.rows); + updateNumOfResult(pRuntimeEnv, (int32_t)pQuery->rec.rows); } } @@ -3263,10 +3273,13 @@ static SQueryStatusInfo getQueryStatusInfo(SQueryRuntimeEnv *pRuntimeEnv, TSKEY .status = pQuery->status, .windowIndex = pRuntimeEnv->windowResInfo.curIndex, .lastKey = start, - .w = pQuery->window, - .curWindow = {.skey = start, .ekey = pTableQueryInfo->win.ekey}, }; + TIME_WINDOW_COPY(info.w, pQuery->window); + TIME_WINDOW_COPY(info.curWindow, pTableQueryInfo->win); + + info.curWindow.skey = start; + return info; } @@ -3295,12 +3308,13 @@ static void setEnvBeforeReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusI SET_REVERSE_SCAN_FLAG(pRuntimeEnv); STsdbQueryCond cond = { - .twindow = pQuery->window, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + setQueryStatus(pQuery, QUERY_NOT_COMPLETED); switchCtxOrder(pRuntimeEnv); disableFuncInReverseScan(pQInfo); @@ -3383,12 +3397,13 @@ void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) { } STsdbQueryCond cond = { - .twindow = qstatus.curWindow, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, qstatus.curWindow); + if (pRuntimeEnv->pSecQueryHandle != NULL) { tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); } @@ -3452,7 +3467,7 @@ void finalizeQueryResult(SQueryRuntimeEnv *pRuntimeEnv) { * set the number of output results for group by normal columns, the number of output rows usually is 1 except * the top and bottom query */ - buf->numOfRows = getNumOfResult(pRuntimeEnv); + buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv); } } else { @@ -3754,7 +3769,7 @@ static int32_t doCopyToSData(SQInfo *pQInfo, SWindowResInfo *pResultInfo, int32_ * to SQuery object's result buffer */ if (numOfRowsToCopy > pQuery->rec.capacity - numOfResult) { - numOfRowsToCopy = pQuery->rec.capacity - numOfResult; + numOfRowsToCopy = (int32_t)pQuery->rec.capacity - numOfResult; pQInfo->offset += numOfRowsToCopy; } else { pQInfo->offset = 0; @@ -3867,7 +3882,7 @@ bool queryHasRemainResForTableQuery(SQueryRuntimeEnv* pRuntimeEnv) { * first result row in the actual result set will fill nothing. */ if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - int32_t numOfTotal = getFilledNumOfRes(pFillInfo, pQuery->window.ekey, pQuery->rec.capacity); + int32_t numOfTotal = (int32_t)getFilledNumOfRes(pFillInfo, pQuery->window.ekey, (int32_t)pQuery->rec.capacity); return numOfTotal > 0; } @@ -3925,7 +3940,7 @@ int32_t doFillGapsInResults(SQueryRuntimeEnv* pRuntimeEnv, tFilePage **pDst, int SFillInfo* pFillInfo = pRuntimeEnv->pFillInfo; while (1) { - int32_t ret = taosGenerateDataBlock(pFillInfo, (tFilePage**) pQuery->sdata, pQuery->rec.capacity); + int32_t ret = (int32_t)taosGenerateDataBlock(pFillInfo, (tFilePage**)pQuery->sdata, (int32_t)pQuery->rec.capacity); // todo apply limit output function /* reached the start position of according to offset value, return immediately */ @@ -3938,7 +3953,7 @@ int32_t doFillGapsInResults(SQueryRuntimeEnv* pRuntimeEnv, tFilePage **pDst, int qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows, offset:%" PRId64 ". Discard due to offset, remain:%" PRId64 ", new offset:%d", pQInfo, pFillInfo->numOfRows, ret, pQuery->limit.offset, ret - pQuery->limit.offset, 0); - ret -= pQuery->limit.offset; + ret -= (int32_t)pQuery->limit.offset; // todo !!!!there exactly number of interpo is not valid. // todo refactor move to the beginning of buffer for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { @@ -3989,9 +4004,9 @@ static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBloc } if (QUERY_IS_ASC_QUERY(pQuery)) { - pQuery->pos = pQuery->limit.offset; + pQuery->pos = (int32_t)pQuery->limit.offset; } else { - pQuery->pos = pBlockInfo->rows - pQuery->limit.offset - 1; + pQuery->pos = pBlockInfo->rows - (int32_t)pQuery->limit.offset - 1; } assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->rows - 1); @@ -4196,12 +4211,13 @@ static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) } STsdbQueryCond cond = { - .twindow = pQuery->window, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + if (!isSTableQuery && (pQInfo->tableqinfoGroupInfo.numOfTables == 1) && (cond.order == TSDB_ORDER_ASC) @@ -4235,7 +4251,7 @@ static SFillColInfo* taosCreateFillColInfo(SQuery* pQuery) { SExprInfo* pExprInfo = &pQuery->pSelectExpr[i]; pFillCol[i].col.bytes = pExprInfo->bytes; - pFillCol[i].col.type = pExprInfo->type; + pFillCol[i].col.type = (int8_t)pExprInfo->type; pFillCol[i].col.offset = offset; pFillCol[i].flag = TSDB_COL_NORMAL; // always be ta normal column for table query pFillCol[i].functionId = pExprInfo->base.functionId; @@ -4306,7 +4322,7 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo threshold = 4000; } else { type = TSDB_DATA_TYPE_INT; // group id - threshold = GET_NUM_OF_TABLEGROUP(pQInfo); + threshold = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); if (threshold < 8) { threshold = 8; } @@ -4346,8 +4362,8 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo TSKEY ek = MAX(pQuery->window.skey, pQuery->window.ekey); getAlignQueryTimeWindow(pQuery, pQuery->window.skey, sk, ek, &w); - pRuntimeEnv->pFillInfo = taosInitFillInfo(pQuery->order.order, w.skey, 0, pQuery->rec.capacity, pQuery->numOfOutput, - pQuery->slidingTime, pQuery->slidingTimeUnit, pQuery->precision, + pRuntimeEnv->pFillInfo = taosInitFillInfo(pQuery->order.order, w.skey, 0, (int32_t)pQuery->rec.capacity, pQuery->numOfOutput, + pQuery->slidingTime, pQuery->slidingTimeUnit, (int8_t)pQuery->precision, pQuery->fillType, pColInfo); } @@ -4531,12 +4547,13 @@ static void sequentialTableProcess(SQInfo *pQInfo) { numOfGroups, group); STsdbQueryCond cond = { - .twindow = pQuery->window, .colList = pQuery->colList, .order = pQuery->order.order, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + SArray *g1 = taosArrayInit(1, POINTER_BYTES); SArray *tx = taosArrayClone(group); taosArrayPush(g1, &tx); @@ -4603,12 +4620,13 @@ static void sequentialTableProcess(SQInfo *pQInfo) { qDebug("QInfo:%p group by normal columns group:%d, total group:%zu", pQInfo, pQInfo->groupIndex, numOfGroups); STsdbQueryCond cond = { - .twindow = pQuery->window, .colList = pQuery->colList, .order = pQuery->order.order, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + SArray *g1 = taosArrayInit(1, POINTER_BYTES); SArray *tx = taosArrayClone(group); taosArrayPush(g1, &tx); @@ -4809,12 +4827,13 @@ static void doSaveContext(SQInfo *pQInfo) { } STsdbQueryCond cond = { - .twindow = pQuery->window, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + // clean unused handle if (pRuntimeEnv->pSecQueryHandle != NULL) { tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); @@ -5047,7 +5066,7 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) // maxOutput <= 0, means current query does not generate any results int32_t numOfClosed = numOfClosedTimeWindow(&pRuntimeEnv->windowResInfo); - int32_t c = MIN(numOfClosed, pQuery->limit.offset); + int32_t c = (int32_t)(MIN(numOfClosed, pQuery->limit.offset)); clearFirstNTimeWindow(pRuntimeEnv, c); pQuery->limit.offset -= c; } @@ -5091,7 +5110,7 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { limitResults(pRuntimeEnv); break; } else { - taosFillSetStartInfo(pRuntimeEnv->pFillInfo, pQuery->rec.rows, pQuery->window.ekey); + taosFillSetStartInfo(pRuntimeEnv->pFillInfo, (int32_t)pQuery->rec.rows, pQuery->window.ekey); taosFillCopyInputDataFromFilePage(pRuntimeEnv->pFillInfo, (tFilePage**) pQuery->sdata); numOfFilled = 0; @@ -5596,7 +5615,7 @@ static int32_t createQFunctionExprFromMsg(SQueryTableMsg *pQueryMsg, SExprInfo * } } - int32_t param = pExprs[i].base.arg[0].argValue.i64; + int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64; if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) { taosTFree(pExprs); @@ -5621,7 +5640,7 @@ static int32_t createQFunctionExprFromMsg(SQueryTableMsg *pQueryMsg, SExprInfo * SColumnInfo *pCol = &pQueryMsg->colList[j]; int32_t ret = - getResultDataInfo(pCol->type, pCol->bytes, functId, pExprs[i].base.arg[0].argValue.i64, + getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.arg[0].argValue.i64, &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, tagLen, isSuperTable); assert(ret == TSDB_CODE_SUCCESS); } @@ -5790,7 +5809,7 @@ static void freeQInfo(SQInfo *pQInfo); static void calResultBufSize(SQuery* pQuery) { const int32_t RESULT_MSG_MIN_SIZE = 1024 * (1024 + 512); // bytes const int32_t RESULT_MSG_MIN_ROWS = 8192; - const float RESULT_THRESHOLD_RATIO = 0.85; + const float RESULT_THRESHOLD_RATIO = 0.85f; if (isProjQuery(pQuery)) { int32_t numOfRes = RESULT_MSG_MIN_SIZE / pQuery->rowSize; @@ -5799,10 +5818,10 @@ static void calResultBufSize(SQuery* pQuery) { } pQuery->rec.capacity = numOfRes; - pQuery->rec.threshold = numOfRes * RESULT_THRESHOLD_RATIO; + pQuery->rec.threshold = (int32_t)(numOfRes * RESULT_THRESHOLD_RATIO); } else { // in case of non-prj query, a smaller output buffer will be used. pQuery->rec.capacity = 4096; - pQuery->rec.threshold = pQuery->rec.capacity * RESULT_THRESHOLD_RATIO; + pQuery->rec.threshold = (int32_t)(pQuery->rec.capacity * RESULT_THRESHOLD_RATIO); } } @@ -5931,7 +5950,7 @@ static SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SArray* pTableIdList, window.skey = pQueryMsg->window.skey; } - void* buf = pQInfo->pBuf + index * sizeof(STableQueryInfo); + void* buf = (char*)pQInfo->pBuf + index * sizeof(STableQueryInfo); STableQueryInfo* item = createTableQueryInfo(&pQInfo->runtimeEnv, info->pTable, window, buf); if (item == NULL) { goto _cleanup; @@ -6087,7 +6106,7 @@ static void freeQInfo(SQInfo *pQInfo) { // todo refactor, extract method to destroytableDataInfo if (pQInfo->tableqinfoGroupInfo.pGroupList != NULL) { - int32_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); for (int32_t i = 0; i < numOfGroups; ++i) { SArray *p = GET_TABLEGROUP(pQInfo, i); @@ -6190,7 +6209,7 @@ static int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) { setQueryStatus(pQuery, QUERY_OVER); } } else { - doCopyQueryResultToMsg(pQInfo, pQuery->rec.rows, data); + doCopyQueryResultToMsg(pQInfo, (int32_t)pQuery->rec.rows, data); } pQuery->rec.total += pQuery->rec.rows; @@ -6466,7 +6485,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co size += sizeof(int32_t); size += sizeof(STableIdInfo) * taosArrayGetSize(pQInfo->arrTableIdInfo); - *contLen = size + sizeof(SRetrieveTableRsp); + *contLen = (int32_t)(size + sizeof(SRetrieveTableRsp)); // todo proper handle failed to allocate memory, // current solution only avoid crash, but cannot return error code to client @@ -6475,7 +6494,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co return TSDB_CODE_QRY_OUT_OF_MEMORY; } - (*pRsp)->numOfRows = htonl(pQuery->rec.rows); + (*pRsp)->numOfRows = htonl((int32_t)pQuery->rec.rows); int32_t code = pQInfo->code; if (code == TSDB_CODE_SUCCESS) { @@ -6593,12 +6612,15 @@ static void buildTagQueryResult(SQInfo* pQInfo) { int32_t i = pQInfo->tableIndex++; STableQueryInfo *item = taosArrayGetP(pa, i); - char *output = pQuery->sdata[0]->data + i * rsize; + char *output = pQuery->sdata[0]->data + count * rsize; varDataSetLen(output, rsize - VARSTR_HEADER_SIZE); output = varDataVal(output); STableId* id = TSDB_TABLEID(item->pTable); + *(int16_t *)output = 0; + output += sizeof(int16_t); + *(int64_t *)output = id->uid; // memory align problem, todo serialize output += sizeof(id->uid); @@ -6631,9 +6653,9 @@ static void buildTagQueryResult(SQInfo* pQInfo) { count = 0; SSchema tbnameSchema = tGetTableNameColumnSchema(); - int32_t maxNumOfTables = pQuery->rec.capacity; + int32_t maxNumOfTables = (int32_t)pQuery->rec.capacity; if (pQuery->limit.limit >= 0 && pQuery->limit.limit < pQuery->rec.capacity) { - maxNumOfTables = pQuery->limit.limit; + maxNumOfTables = (int32_t)pQuery->limit.limit; } while(pQInfo->tableIndex < num && count < maxNumOfTables) { diff --git a/src/query/src/qExtbuffer.c b/src/query/src/qExtbuffer.c index f11a16810c56603700e2edc3ce71e8dae874e442..a147780144312192886a9ba39f609a4f6b01ec76 100644 --- a/src/query/src/qExtbuffer.c +++ b/src/query/src/qExtbuffer.c @@ -171,7 +171,7 @@ int16_t tExtMemBufferPut(tExtMemBuffer *pMemBuffer, void *data, int32_t numOfRow pMemBuffer->numOfElemsInBuffer += numOfRows; pMemBuffer->numOfTotalElems += numOfRows; } else { - int32_t numOfRemainEntries = pMemBuffer->numOfElemsPerPage - pLast->item.num; + int32_t numOfRemainEntries = pMemBuffer->numOfElemsPerPage - (int32_t)pLast->item.num; tColModelAppend(pMemBuffer->pColumnModel, &pLast->item, data, 0, numOfRemainEntries, numOfRows); pMemBuffer->numOfElemsInBuffer += numOfRemainEntries; @@ -269,7 +269,7 @@ int32_t tExtMemBufferFlush(tExtMemBuffer *pMemBuffer) { return ret; } - pMemBuffer->fileMeta.numOfElemsInFile += first->item.num; + pMemBuffer->fileMeta.numOfElemsInFile += (uint32_t)first->item.num; pMemBuffer->fileMeta.nFileSize += 1; tFilePagesItem *ptmp = first; @@ -321,7 +321,7 @@ void tExtMemBufferClear(tExtMemBuffer *pMemBuffer) { } bool tExtMemBufferLoadData(tExtMemBuffer *pMemBuffer, tFilePage *pFilePage, int32_t flushoutId, int32_t pageIdx) { - if (flushoutId < 0 || flushoutId > pMemBuffer->fileMeta.flushoutData.nLength) { + if (flushoutId < 0 || flushoutId > (int32_t)pMemBuffer->fileMeta.flushoutData.nLength) { return false; } @@ -1010,8 +1010,8 @@ void tColModelErase(SColumnModel *pModel, tFilePage *inputBuffer, int32_t blockC } int32_t removed = e - s + 1; - int32_t remain = inputBuffer->num - removed; - int32_t secPart = inputBuffer->num - e - 1; + int32_t remain = (int32_t)inputBuffer->num - removed; + int32_t secPart = (int32_t)inputBuffer->num - e - 1; /* start from the second column */ for (int32_t i = 0; i < pModel->numOfCols; ++i) { diff --git a/src/query/src/qFill.c b/src/query/src/qFill.c index e65d793dc9b6cb3a59e25ad78106895378d70f25..ac44feb5760c1b1dae5bd501b73a7a40e0fcf5e8 100644 --- a/src/query/src/qFill.c +++ b/src/query/src/qFill.c @@ -155,14 +155,14 @@ int64_t getFilledNumOfRes(SFillInfo* pFillInfo, TSKEY ekey, int32_t maxNumOfRows if (numOfRows > 0) { // still fill gap within current data block, not generating data after the result set. TSKEY lastKey = tsList[pFillInfo->numOfRows - 1]; - numOfRes = (int64_t)(labs(lastKey - pFillInfo->start) / pFillInfo->slidingTime) + 1; + numOfRes = (int64_t)(ABS(lastKey - pFillInfo->start) / pFillInfo->slidingTime) + 1; assert(numOfRes >= numOfRows); } else { // reach the end of data if ((ekey1 < pFillInfo->start && FILL_IS_ASC_FILL(pFillInfo)) || (ekey1 > pFillInfo->start && !FILL_IS_ASC_FILL(pFillInfo))) { return 0; } else { // the numOfRes rows are all filled with specified policy - numOfRes = (labs(ekey1 - pFillInfo->start) / pFillInfo->slidingTime) + 1; + numOfRes = (ABS(ekey1 - pFillInfo->start) / pFillInfo->slidingTime) + 1; } } @@ -185,34 +185,34 @@ static double linearInterpolationImpl(double v1, double v2, double k1, double k2 int taosDoLinearInterpolation(int32_t type, SPoint* point1, SPoint* point2, SPoint* point) { switch (type) { case TSDB_DATA_TYPE_INT: { - *(int32_t*)point->val = (int32_t) linearInterpolationImpl(*(int32_t*)point1->val, *(int32_t*)point2->val, point1->key, - point2->key, point->key); + *(int32_t*)point->val = (int32_t)linearInterpolationImpl(*(int32_t*)point1->val, *(int32_t*)point2->val, (double)point1->key, + (double)point2->key, (double)point->key); break; } case TSDB_DATA_TYPE_FLOAT: { - *(float*)point->val = - linearInterpolationImpl(*(float*)point1->val, *(float*)point2->val, point1->key, point2->key, point->key); + *(float*)point->val = (float) + linearInterpolationImpl(*(float*)point1->val, *(float*)point2->val, (double)point1->key, (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_DOUBLE: { *(double*)point->val = - linearInterpolationImpl(*(double*)point1->val, *(double*)point2->val, point1->key, point2->key, point->key); + linearInterpolationImpl(*(double*)point1->val, *(double*)point2->val, (double)point1->key, (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_BIGINT: { - *(int64_t*)point->val = (int64_t) linearInterpolationImpl(*(int64_t*)point1->val, *(int64_t*)point2->val, point1->key, - point2->key, point->key); + *(int64_t*)point->val = (int64_t)linearInterpolationImpl((double)(*(int64_t*)point1->val), (double)(*(int64_t*)point2->val), (double)point1->key, + (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_SMALLINT: { - *(int16_t*)point->val = (int16_t) linearInterpolationImpl(*(int16_t*)point1->val, *(int16_t*)point2->val, point1->key, - point2->key, point->key); + *(int16_t*)point->val = (int16_t)linearInterpolationImpl(*(int16_t*)point1->val, *(int16_t*)point2->val, (double)point1->key, + (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_TINYINT: { *(int8_t*) point->val = (int8_t) - linearInterpolationImpl(*(int8_t*)point1->val, *(int8_t*)point2->val, point1->key, point2->key, point->key); + linearInterpolationImpl(*(int8_t*)point1->val, *(int8_t*)point2->val, (double)point1->key, (double)point2->key, (double)point->key); break; }; default: { @@ -467,7 +467,7 @@ int32_t generateDataBlockImpl(SFillInfo* pFillInfo, tFilePage** data, int32_t nu int64_t taosGenerateDataBlock(SFillInfo* pFillInfo, tFilePage** output, int32_t capacity) { int32_t remain = taosNumOfRemainRows(pFillInfo); // todo use iterator? - int32_t rows = getFilledNumOfRes(pFillInfo, pFillInfo->endKey, capacity); + int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, pFillInfo->endKey, capacity); int32_t numOfRes = generateDataBlockImpl(pFillInfo, output, remain, rows, pFillInfo->pData); assert(numOfRes == rows); diff --git a/src/query/src/qHistogram.c b/src/query/src/qHistogram.c index 7835d824699c46b2daa4a805ae163b5240f2c4e0..703ee2c52129a067d1070cfbe567087ec48a7a6e 100644 --- a/src/query/src/qHistogram.c +++ b/src/query/src/qHistogram.c @@ -482,10 +482,10 @@ int64_t tHistogramSum(SHistogramInfo* pHisto, double v) { } } - double m1 = pHisto->elems[slotIdx].num; + double m1 = (double)pHisto->elems[slotIdx].num; double v1 = pHisto->elems[slotIdx].val; - double m2 = pHisto->elems[slotIdx + 1].num; + double m2 = (double)pHisto->elems[slotIdx + 1].num; double v2 = pHisto->elems[slotIdx + 1].val; double estNum = m1 + (m2 - m1) * (v - v1) / (v2 - v1); @@ -538,7 +538,7 @@ double* tHistogramUniform(SHistogramInfo* pHisto, double* ratio, int32_t num) { pVal[i] = pHisto->elems[j].val; } - double start = pHisto->elems[j].num; + double start = (double)pHisto->elems[j].num; double range = pHisto->elems[j + 1].num - start; if (range == 0) { diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index f556e2dd53b69a4293939fe97224371733dcdda2..d8f12da642851babe493cc85dec4dc1b3dcfe888 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -158,7 +158,7 @@ tSQLExpr *tSQLExprCreateFunction(tSQLExprList *pList, SSQLToken *pFuncToken, SSQ pExpr->nSQLOptr = optType; pExpr->pParam = pList; - int32_t len = (endToken->z + endToken->n) - pFuncToken->z; + int32_t len = (int32_t)((endToken->z + endToken->n) - pFuncToken->z); pExpr->operand.z = pFuncToken->z; pExpr->operand.n = len; // raw field name @@ -468,7 +468,7 @@ void tSQLSetColumnInfo(TAOS_FIELD *pField, SSQLToken *pName, TAOS_FIELD *pType) int32_t maxLen = sizeof(pField->name) / sizeof(pField->name[0]); // truncate the column name - if (pName->n >= maxLen) { + if ((int32_t)pName->n >= maxLen) { pName->n = maxLen - 1; } @@ -524,7 +524,7 @@ SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection, SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL)); pQuery->selectToken = *pSelectToken; - pQuery->selectToken.n = strlen(pQuery->selectToken.z); // all later sql string are belonged to the stream sql + pQuery->selectToken.n = (uint32_t)strlen(pQuery->selectToken.z); // all later sql string are belonged to the stream sql pQuery->pSelection = pSelection; pQuery->from = pFrom; diff --git a/src/query/src/qPercentile.c b/src/query/src/qPercentile.c index 7f5fa08cf1bffa423a24650d4f5e2b66b089625f..19775075fc34249bc5d772fb34b3dc6408f2ed44 100644 --- a/src/query/src/qPercentile.c +++ b/src/query/src/qPercentile.c @@ -55,18 +55,18 @@ static tFilePage *loadIntoBucketFromDisk(tMemBucket *pMemBucket, int32_t segIdx, // load data in disk to memory tFilePage *pPage = (tFilePage *)calloc(1, pMemBuffer->pageSize); - for (int32_t i = 0; i < pMemBuffer->fileMeta.flushoutData.nLength; ++i) { + for (uint32_t i = 0; i < pMemBuffer->fileMeta.flushoutData.nLength; ++i) { tFlushoutInfo *pFlushInfo = &pMemBuffer->fileMeta.flushoutData.pFlushoutInfo[i]; int32_t ret = fseek(pMemBuffer->file, pFlushInfo->startPageId * pMemBuffer->pageSize, SEEK_SET); UNUSED(ret); for (uint32_t j = 0; j < pFlushInfo->numOfPages; ++j) { - ret = fread(pPage, pMemBuffer->pageSize, 1, pMemBuffer->file); + ret = (int32_t)fread(pPage, pMemBuffer->pageSize, 1, pMemBuffer->file); UNUSED(ret); assert(pPage->num > 0); - tColModelAppend(pDesc->pColumnModel, buffer, pPage->data, 0, pPage->num, pPage->num); + tColModelAppend(pDesc->pColumnModel, buffer, pPage->data, 0, (int32_t)pPage->num, (int32_t)pPage->num); printf("id: %d count: %" PRIu64 "\n", j, buffer->num); } } @@ -78,12 +78,12 @@ static tFilePage *loadIntoBucketFromDisk(tMemBucket *pMemBucket, int32_t segIdx, // load data in pMemBuffer to buffer tFilePagesItem *pListItem = pMemBuffer->pHead; while (pListItem != NULL) { - tColModelAppend(pDesc->pColumnModel, buffer, pListItem->item.data, 0, pListItem->item.num, - pListItem->item.num); + tColModelAppend(pDesc->pColumnModel, buffer, pListItem->item.data, 0, (int32_t)pListItem->item.num, + (int32_t)pListItem->item.num); pListItem = pListItem->pNext; } - tColDataQSort(pDesc, buffer->num, 0, buffer->num - 1, buffer->data, TSDB_ORDER_ASC); + tColDataQSort(pDesc, (int32_t)buffer->num, 0, (int32_t)buffer->num - 1, buffer->data, TSDB_ORDER_ASC); pDesc->pColumnModel->capacity = oldCapacity; // restore value return buffer; @@ -883,7 +883,7 @@ double getPercentileImpl(tMemBucket *pMemBucket, int32_t count, double fraction) if (sz != pMemBuffer->pageSize) { uError("MemBucket:%p, read tmp file %s failed", pMemBucket, pMemBuffer->path); } else { - tMemBucketPut(pMemBucket, pPage->data, pPage->num); + tMemBucketPut(pMemBucket, pPage->data, (int32_t)pPage->num); } } diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index 777210bd110939c3a930b1893e8bebd4401d8fcf..7c40c33933651727e71d7636446e9df8a360bbfa 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -96,8 +96,8 @@ static int32_t allocatePositionInFile(SDiskbasedResultBuf* pResultBuf, size_t si SFreeListItem* pi = taosArrayGet(pResultBuf->pFree, i); if (pi->len >= size) { offset = pi->offset; - pi->offset += size; - pi->len -= size; + pi->offset += (int32_t)size; + pi->len -= (int32_t)size; return offset; } @@ -173,7 +173,7 @@ static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { // load file block data in disk static char* loadPageFromDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t ret = fseek(pResultBuf->file, pg->info.offset, SEEK_SET); - ret = fread(GET_DATA_PAYLOAD(pg), 1, pg->info.length, pResultBuf->file); + ret = (int32_t)fread(GET_DATA_PAYLOAD(pg), 1, pg->info.length, pResultBuf->file); if (ret != pg->info.length) { terrno = errno; return NULL; @@ -184,7 +184,7 @@ static char* loadPageFromDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t fullSize = 0; doDecompressData(GET_DATA_PAYLOAD(pg), pg->info.length, &fullSize, pResultBuf); - return GET_DATA_PAYLOAD(pg); + return (char*)GET_DATA_PAYLOAD(pg); } static SIDList addNewGroup(SDiskbasedResultBuf* pResultBuf, int32_t groupId) { @@ -248,7 +248,7 @@ static char* evicOneDataPage(SDiskbasedResultBuf* pResultBuf) { int32_t prev = pResultBuf->inMemPages; // increase by 50% of previous mem pages - pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; + pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5f; qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, pResultBuf->inMemPages, pResultBuf->pageSize); diff --git a/src/query/src/qTokenizer.c b/src/query/src/qTokenizer.c index 1fa565ca903479dbfe75ecf4477a907c58fc0dd3..227aded5f1c41b8ffd1c04d10dc914ae8c4f933f 100644 --- a/src/query/src/qTokenizer.c +++ b/src/query/src/qTokenizer.c @@ -254,12 +254,12 @@ static const char isIdChar[] = { static void* KeywordHashTable = NULL; -static void doInitKeywordsTable() { +static void doInitKeywordsTable(void) { int numOfEntries = tListLen(keywordTable); KeywordHashTable = taosHashInit(numOfEntries, MurmurHash3_32, true, false); for (int32_t i = 0; i < numOfEntries; i++) { - keywordTable[i].len = strlen(keywordTable[i].name); + keywordTable[i].len = (uint8_t)strlen(keywordTable[i].name); void* ptr = &keywordTable[i]; taosHashPut(KeywordHashTable, keywordTable[i].name, keywordTable[i].len, (void*)&ptr, POINTER_BYTES); } @@ -662,4 +662,4 @@ bool isKeyWord(const char* z, int32_t len) { return (tSQLKeywordCode((char*)z, l void taosCleanupKeywordsTable() { taosHashCleanup(KeywordHashTable); -} +} \ No newline at end of file diff --git a/src/query/src/qTsbuf.c b/src/query/src/qTsbuf.c index 95581e1869de786fd41e1a9c718d9ad11628f042..25eb33ff7d3557f4911c736bdeaf0da82aae0587 100644 --- a/src/query/src/qTsbuf.c +++ b/src/query/src/qTsbuf.c @@ -76,7 +76,7 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) { return NULL; } - if (header.numOfVnode > pTSBuf->numOfAlloc) { + if ((int32_t)header.numOfVnode > pTSBuf->numOfAlloc) { pTSBuf->numOfAlloc = header.numOfVnode; STSVnodeBlockInfoEx* tmp = realloc(pTSBuf->pData, sizeof(STSVnodeBlockInfoEx) * pTSBuf->numOfAlloc); if (tmp == NULL) { @@ -172,7 +172,7 @@ static STSVnodeBlockInfoEx* tsBufGetLastVnodeInfo(STSBuf* pTSBuf) { static STSVnodeBlockInfoEx* addOneVnodeInfo(STSBuf* pTSBuf, int32_t vnodeId) { if (pTSBuf->numOfAlloc <= pTSBuf->numOfVnodes) { uint32_t newSize = (uint32_t)(pTSBuf->numOfAlloc * 1.5); - assert(newSize > pTSBuf->numOfAlloc); + assert((int32_t)newSize > pTSBuf->numOfAlloc); STSVnodeBlockInfoEx* tmp = (STSVnodeBlockInfoEx*)realloc(pTSBuf->pData, sizeof(STSVnodeBlockInfoEx) * newSize); if (tmp == NULL) { @@ -289,7 +289,7 @@ STSBlock* readDataFromDisk(STSBuf* pTSBuf, int32_t order, bool decomp) { * set the right position for the reversed traverse, the reversed traverse is started from * the end of each comp data block */ - int32_t ret = fseek(pTSBuf->f, -sizeof(pBlock->padding), SEEK_CUR); + int32_t ret = fseek(pTSBuf->f, -(int32_t)(sizeof(pBlock->padding)), SEEK_CUR); size_t sz = fread(&pBlock->padding, sizeof(pBlock->padding), 1, pTSBuf->f); UNUSED(sz); @@ -475,7 +475,7 @@ static int32_t tsBufFindBlockByTag(STSBuf* pTSBuf, STSVnodeBlockInfo* pBlockInfo offset = pBlockInfo->offset + pBlockInfo->compLen; } - if (fseek(pTSBuf->f, offset, SEEK_SET) != 0) { + if (fseek(pTSBuf->f, (int32_t)offset, SEEK_SET) != 0) { return -1; } @@ -525,7 +525,7 @@ static void tsBufGetBlock(STSBuf* pTSBuf, int32_t vnodeIndex, int32_t blockIndex * may exceed the maximum allowed size during *tsBufAppend* function by invoking expandBuffer function */ if (s > pTSBuf->tsData.allocSize) { - expandBuffer(&pTSBuf->tsData, s); + expandBuffer(&pTSBuf->tsData, (int32_t)s); } pTSBuf->tsData.len = @@ -738,7 +738,7 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf, int32_t vnodeId) { assert(r == 0); int64_t offset = getDataStartOffset(); - int32_t size = pSrcBuf->fileSize - offset; + int32_t size = (int32_t)pSrcBuf->fileSize - (int32_t)offset; ssize_t rc = taosFSendFile(pDestBuf->f, pSrcBuf->f, &offset, size); @@ -897,7 +897,7 @@ static int32_t doUpdateVnodeInfo(STSBuf* pTSBuf, int64_t offset, STSVnodeBlockIn return -1; } - if (fseek(pTSBuf->f, offset, SEEK_SET) != 0) { + if (fseek(pTSBuf->f, (int32_t)offset, SEEK_SET) != 0) { return -1; } diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 15a8923d2126df480165f082b33f5919e8aac351..f94b4aeb6d21277b6b845587cd35a2c98e0bc0b0 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -1,25 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) INCLUDE_DIRECTORIES(inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - AUX_SOURCE_DIRECTORY(src SRC) -ELSEIF (TD_DARWIN_64) - AUX_SOURCE_DIRECTORY(src SRC) -ELSEIF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - AUX_SOURCE_DIRECTORY(src SRC) -ENDIF () +AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(trpc ${SRC}) TARGET_LINK_LIBRARIES(trpc tutil lz4 common) ADD_SUBDIRECTORY(test) - diff --git a/src/rpc/src/rpcMain.c b/src/rpc/src/rpcMain.c index c8cf3ee6cf421041ad5fcde02b72740a71f288dd..13f44f20b751036629a15024c0aec997060db85c 100644 --- a/src/rpc/src/rpcMain.c +++ b/src/rpc/src/rpcMain.c @@ -322,6 +322,8 @@ void *rpcMallocCont(int contLen) { if (start == NULL) { tError("failed to malloc msg, size:%d", size); return NULL; + } else { + tDebug("malloc mem: %p", start); } return start + sizeof(SRpcReqContext) + sizeof(SRpcHead); @@ -331,7 +333,7 @@ void rpcFreeCont(void *cont) { if ( cont ) { char *temp = ((char *)cont) - sizeof(SRpcHead) - sizeof(SRpcReqContext); free(temp); - // tTrace("free mem: %p", temp); + tDebug("free mem: %p", temp); } } @@ -551,7 +553,7 @@ static void rpcFreeMsg(void *msg) { if ( msg ) { char *temp = (char *)msg - sizeof(SRpcReqContext); free(temp); - // tTrace("free mem: %p", temp); + tDebug("free mem: %p", temp); } } @@ -1007,9 +1009,15 @@ static void *rpcProcessMsgFromPeer(SRecvInfo *pRecv) { terrno = 0; pConn = rpcProcessMsgHead(pRpc, pRecv); - tDebug("%s %p %p, %s received from 0x%x:%hu, parse code:0x%x len:%d sig:0x%08x:0x%08x:%d code:0x%x", - pRpc->label, pConn, (void *)pHead->ahandle, taosMsg[pHead->msgType], pRecv->ip, pRecv->port, terrno, - pRecv->msgLen, pHead->sourceId, pHead->destId, pHead->tranId, pHead->code); + if (pHead->msgType >= 1 && pHead->msgType < TSDB_MSG_TYPE_MAX) { + tDebug("%s %p %p, %s received from 0x%x:%hu, parse code:0x%x len:%d sig:0x%08x:0x%08x:%d code:0x%x", pRpc->label, + pConn, (void *)pHead->ahandle, taosMsg[pHead->msgType], pRecv->ip, pRecv->port, terrno, pRecv->msgLen, + pHead->sourceId, pHead->destId, pHead->tranId, pHead->code); + } else { + tDebug("%s %p %p, %d received from 0x%x:%hu, parse code:0x%x len:%d sig:0x%08x:0x%08x:%d code:0x%x", pRpc->label, + pConn, (void *)pHead->ahandle, pHead->msgType, pRecv->ip, pRecv->port, terrno, pRecv->msgLen, + pHead->sourceId, pHead->destId, pHead->tranId, pHead->code); + } int32_t code = terrno; if (code != TSDB_CODE_RPC_ALREADY_PROCESSED) { @@ -1092,10 +1100,15 @@ static void rpcProcessIncomingMsg(SRpcConn *pConn, SRpcHead *pHead) { } if (pHead->code == TSDB_CODE_RPC_REDIRECT) { - pContext->redirect++; - if (pContext->redirect > TSDB_MAX_REPLICA) { - pHead->code = TSDB_CODE_RPC_NETWORK_UNAVAIL; - tWarn("%s, too many redirects, quit", pConn->info); + if (rpcMsg.contLen < sizeof(SRpcEpSet)) { + // if EpSet is not included in the msg, treat it as NOT_READY + pHead->code = TSDB_CODE_RPC_NOT_READY; + } else { + pContext->redirect++; + if (pContext->redirect > TSDB_MAX_REPLICA) { + pHead->code = TSDB_CODE_RPC_NETWORK_UNAVAIL; + tWarn("%s, too many redirects, quit", pConn->info); + } } } diff --git a/src/rpc/src/rpcTcp.c b/src/rpc/src/rpcTcp.c index c69456b8e282dcad61d3c30fca89efabdc8ecbda..9da11831e56b4098d7a7856e3eb9744cf77ad23b 100644 --- a/src/rpc/src/rpcTcp.c +++ b/src/rpc/src/rpcTcp.c @@ -21,6 +21,9 @@ #include "rpcLog.h" #include "rpcHead.h" #include "rpcTcp.h" +#ifdef WINDOWS +#include "wepoll.h" +#endif #ifndef EPOLLWAKEUP #define EPOLLWAKEUP (1u << 29) @@ -28,7 +31,7 @@ typedef struct SFdObj { void *signature; - int fd; // TCP socket FD + SOCKET fd; // TCP socket FD int closedByApp; // 1: already closed by App void *thandle; // handle from upper layer, like TAOS uint32_t ip; @@ -44,7 +47,7 @@ typedef struct SThreadObj { pthread_mutex_t mutex; uint32_t ip; bool stop; - int pollFd; + SOCKET pollFd; int numOfFds; int threadId; char label[TSDB_LABEL_LEN]; @@ -53,7 +56,7 @@ typedef struct SThreadObj { } SThreadObj; typedef struct { - int fd; + SOCKET fd; uint32_t ip; uint16_t port; char label[TSDB_LABEL_LEN]; @@ -64,7 +67,7 @@ typedef struct { } SServerObj; static void *taosProcessTcpData(void *param); -static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, int fd); +static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd); static void taosFreeFdObj(SFdObj *pFdObj); static void taosReportBrokenLink(SFdObj *pFdObj); static void *taosAcceptTcpConnection(void *arg); @@ -120,7 +123,7 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread break; } - pThreadObj->pollFd = epoll_create(10); // size does not matter + pThreadObj->pollFd = (int64_t)epoll_create(10); // size does not matter if (pThreadObj->pollFd < 0) { tError("%s failed to create TCP epoll", label); code = -1; @@ -163,7 +166,7 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) { pThreadObj->stop = true; eventfd_t fd = -1; - if (pThreadObj->thread && pThreadObj->pollFd >=0) { + if (taosCheckPthreadValid(pThreadObj->thread) && pThreadObj->pollFd >= 0) { // signal the thread to stop, try graceful method first, // and use pthread_cancel when failed struct epoll_event event = { .events = EPOLLIN }; @@ -171,6 +174,7 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) { if (fd == -1) { // failed to create eventfd, call pthread_cancel instead, which may result in data corruption: tError("%s, failed to create eventfd(%s)", pThreadObj->label, strerror(errno)); + pThreadObj->stop = true; pthread_cancel(pThreadObj->thread); } else if (epoll_ctl(pThreadObj->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) { // failed to call epoll_ctl, call pthread_cancel instead, which may result in data corruption: @@ -179,9 +183,9 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) { } } - if (pThreadObj->thread) pthread_join(pThreadObj->thread, NULL); - if (pThreadObj->pollFd >=0) close(pThreadObj->pollFd); - if (fd != -1) close(fd); + if (taosCheckPthreadValid(pThreadObj->thread)) pthread_join(pThreadObj->thread, NULL); + if (pThreadObj->pollFd >=0) taosCloseSocket(pThreadObj->pollFd); + if (fd != -1) taosCloseSocket(fd); while (pThreadObj->pHead) { SFdObj *pFdObj = pThreadObj->pHead; @@ -195,7 +199,7 @@ void taosStopTcpServer(void *handle) { if (pServerObj == NULL) return; if(pServerObj->fd >=0) shutdown(pServerObj->fd, SHUT_RD); - if(pServerObj->thread) pthread_join(pServerObj->thread, NULL); + if (taosCheckPthreadValid(pServerObj->thread)) pthread_join(pServerObj->thread, NULL); tDebug("%s TCP server is stopped", pServerObj->label); } @@ -218,7 +222,7 @@ void taosCleanUpTcpServer(void *handle) { } static void *taosAcceptTcpConnection(void *arg) { - int connFd = -1; + SOCKET connFd = -1; struct sockaddr_in caddr; int threadId = 0; SThreadObj *pThreadObj; @@ -252,7 +256,7 @@ static void *taosAcceptTcpConnection(void *arg) { tDebug("%s new TCP connection from %s:%hu, fd:%d FD:%p numOfFds:%d", pServerObj->label, inet_ntoa(caddr.sin_addr), pFdObj->port, connFd, pFdObj, pThreadObj->numOfFds); } else { - close(connFd); + taosCloseSocket(connFd); tError("%s failed to malloc FdObj(%s) for connection from:%s:%hu", pServerObj->label, strerror(errno), inet_ntoa(caddr.sin_addr), htons(caddr.sin_port)); } @@ -262,7 +266,7 @@ static void *taosAcceptTcpConnection(void *arg) { threadId = threadId % pServerObj->numOfThreads; } - close(pServerObj->fd); + taosCloseSocket(pServerObj->fd); return NULL; } @@ -283,7 +287,7 @@ void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int num, void * return NULL; } - pThreadObj->pollFd = epoll_create(10); // size does not matter + pThreadObj->pollFd = (SOCKET)epoll_create(10); // size does not matter if (pThreadObj->pollFd < 0) { tError("%s failed to create TCP client epoll", label); free(pThreadObj); @@ -298,7 +302,7 @@ void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int num, void * int code = pthread_create(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj)); pthread_attr_destroy(&thattr); if (code != 0) { - close(pThreadObj->pollFd); + taosCloseSocket(pThreadObj->pollFd); free(pThreadObj); terrno = TAOS_SYSTEM_ERROR(errno); tError("%s failed to create TCP read data thread(%s)", label, strerror(errno)); @@ -330,7 +334,7 @@ void taosCleanUpTcpClient(void *chandle) { void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port) { SThreadObj * pThreadObj = shandle; - int fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip); + SOCKET fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip); if (fd < 0) return NULL; struct sockaddr_in sin; @@ -350,7 +354,7 @@ void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uin tDebug("%s %p TCP connection to 0x%x:%hu is created, localPort:%hu FD:%p numOfFds:%d", pThreadObj->label, thandle, ip, port, localPort, pFdObj, pThreadObj->numOfFds); } else { - close(fd); + taosCloseSocket(fd); tError("%s failed to malloc client FdObj(%s)", pThreadObj->label, strerror(errno)); } @@ -461,7 +465,7 @@ static void *taosProcessTcpData(void *param) { SRecvInfo recvInfo; while (1) { - int fdNum = epoll_wait(pThreadObj->pollFd, events, maxEvents, -1); + int fdNum = epoll_wait(pThreadObj->pollFd, events, maxEvents, TAOS_EPOLL_WAIT_TIME); if (pThreadObj->stop) { tDebug("%s TCP thread get stop event, exiting...", pThreadObj->label); break; @@ -502,7 +506,7 @@ static void *taosProcessTcpData(void *param) { return NULL; } -static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, int fd) { +static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd) { struct epoll_event event; SFdObj *pFdObj = (SFdObj *)calloc(sizeof(SFdObj), 1); diff --git a/src/rpc/src/rpcUdp.c b/src/rpc/src/rpcUdp.c index 7e59210caee47c533ed44fcc94eed11b5aa1b29d..8e24aed8f789f03ef324c05922c38ecefe747256 100644 --- a/src/rpc/src/rpcUdp.c +++ b/src/rpc/src/rpcUdp.c @@ -31,7 +31,7 @@ typedef struct { int index; - int fd; + SOCKET fd; uint16_t port; // peer port uint16_t localPort; // local port char label[TSDB_LABEL_LEN]; // copy from udpConnSet; diff --git a/src/rpc/test/CMakeLists.txt b/src/rpc/test/CMakeLists.txt index ac7ea8e4c119fd82ea6b1fc7b45a7c7dcab0c792..286c8e168067f5691030eb1e58e16b5c751ab672 100644 --- a/src/rpc/test/CMakeLists.txt +++ b/src/rpc/test/CMakeLists.txt @@ -1,13 +1,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/rpc/inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX_64) LIST(APPEND CLIENT_SRC ./rclient.c) ADD_EXECUTABLE(rclient ${CLIENT_SRC}) TARGET_LINK_LIBRARIES(rclient trpc) @@ -20,5 +16,3 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) ADD_EXECUTABLE(rserver ${SERVER_SRC}) TARGET_LINK_LIBRARIES(rserver trpc) ENDIF () - - diff --git a/src/rpc/test/rclient.c b/src/rpc/test/rclient.c index e2d9d388f9af91f12fa0fba0e892ba256555552e..6ec2d8244512eb0ccce24bd45ce5c7aafa2b1399 100644 --- a/src/rpc/test/rclient.c +++ b/src/rpc/test/rclient.c @@ -183,7 +183,7 @@ int main(int argc, char *argv[]) { gettimeofday(&systemTime, NULL); endTime = systemTime.tv_sec*1000000 + systemTime.tv_usec; - float usedTime = (endTime - startTime)/1000.0; // mseconds + float usedTime = (endTime - startTime)/1000.0f; // mseconds tInfo("it takes %.3f mseconds to send %d requests to server", usedTime, numOfReqs*appThreads); tInfo("Performance: %.3f requests per second, msgSize:%d bytes", 1000.0*numOfReqs*appThreads/usedTime, msgSize); diff --git a/src/sync/CMakeLists.txt b/src/sync/CMakeLists.txt index 9b7def6a68956b8a889a5d5cb81980e30a747321..efdf2bd185cb5db46d7f0918725ebe8886d5bd98 100644 --- a/src/sync/CMakeLists.txt +++ b/src/sync/CMakeLists.txt @@ -1,16 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) LIST(REMOVE_ITEM SRC ./src/tarbitrator.c) - ADD_LIBRARY(sync ${SRC}) TARGET_LINK_LIBRARIES(sync tutil pthread common) diff --git a/src/sync/src/syncMain.c b/src/sync/src/syncMain.c index 60d889a84f7be14dbaab02ff2ea29be940e5304e..f2abded3b67d59f70598551a16aadf8fc545fa9a 100644 --- a/src/sync/src/syncMain.c +++ b/src/sync/src/syncMain.c @@ -30,7 +30,7 @@ #include "syncInt.h" // global configurable -int tsMaxSyncNum = 4; +int tsMaxSyncNum = 2; int tsSyncTcpThreads = 2; int tsMaxWatchFiles = 100; int tsMaxFwdInfo = 200; diff --git a/src/sync/src/taosTcpPool.c b/src/sync/src/taosTcpPool.c index 88c2c53be4de906cc8d9ac71922e3213ffeee2a1..b523728bf9357e17602c75e3822284c2871e8511 100644 --- a/src/sync/src/taosTcpPool.c +++ b/src/sync/src/taosTcpPool.c @@ -184,7 +184,7 @@ static void *taosProcessTcpData(void *param) { while (1) { if (pThread->stop) break; - int fdNum = epoll_wait(pThread->pollFd, events, maxEvents, -1); + int fdNum = epoll_wait(pThread->pollFd, events, maxEvents, TAOS_EPOLL_WAIT_TIME); if (pThread->stop) { uDebug("%p TCP epoll thread is exiting...", pThread); break; @@ -313,6 +313,7 @@ static void taosStopPoolThread(SThreadObj* pThread) { // failed to create eventfd, call pthread_cancel instead, which may result in data corruption uError("failed to create eventfd(%s)", strerror(errno)); pthread_cancel(pThread->thread); + pThread->stop = true; } else if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, fd, &event) < 0) { // failed to call epoll_ctl, call pthread_cancel instead, which may result in data corruption uError("failed to call epoll_ctl(%s)", strerror(errno)); diff --git a/src/sync/test/CMakeLists.txt b/src/sync/test/CMakeLists.txt index 89d739080f0bf327deca784350f58b8cc53b7933..a309539024c32a25f64fb4c092e8197f8ecbe123 100644 --- a/src/sync/test/CMakeLists.txt +++ b/src/sync/test/CMakeLists.txt @@ -1,11 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +IF (TD_LINUX_64) INCLUDE_DIRECTORIES(../inc) LIST(APPEND CLIENT_SRC ./syncClient.c) diff --git a/src/tsdb/CMakeLists.txt b/src/tsdb/CMakeLists.txt index 450afe337bb287f204567e743d1aee5b37f86ba3..cef1d0bba7ada660ef5f8059c264b2bdfd0056d2 100644 --- a/src/tsdb/CMakeLists.txt +++ b/src/tsdb/CMakeLists.txt @@ -1,19 +1,15 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - # INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/vnode/common/inc) - - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) +IF (TD_LINUX) ADD_LIBRARY(tsdb ${SRC}) TARGET_LINK_LIBRARIES(tsdb common tutil) - # Someone has no gtest directory, so comment it # ADD_SUBDIRECTORY(tests) +ELSEIF (TD_WINDOWS) + ADD_LIBRARY(tsdb ${SRC}) + TARGET_LINK_LIBRARIES(tsdb common tutil) ENDIF () diff --git a/src/tsdb/inc/tsdbMain.h b/src/tsdb/inc/tsdbMain.h index 5a06dfa65a19e925251d984277f1ed5078129a5f..f42c00f1711a276c2a4d6682f93d0b92864aabb9 100644 --- a/src/tsdb/inc/tsdbMain.h +++ b/src/tsdb/inc/tsdbMain.h @@ -15,6 +15,7 @@ #ifndef _TD_TSDB_MAIN_H_ #define _TD_TSDB_MAIN_H_ +#include "os.h" #include "hash.h" #include "tcoding.h" #include "tglobal.h" @@ -67,7 +68,7 @@ typedef struct STable { char* sql; void* cqhandle; SRWLatch latch; // TODO: implementa latch functions - T_REF_DECLARE(); + T_REF_DECLARE() } STable; typedef struct { @@ -115,7 +116,7 @@ typedef struct { } STableData; typedef struct { - T_REF_DECLARE(); + T_REF_DECLARE() SRWLatch latch; TSKEY keyFirst; TSKEY keyLast; @@ -123,14 +124,24 @@ typedef struct { int32_t maxTables; STableData** tData; SList* actList; + SList* extraBuffList; SList* bufBlockList; } SMemTable; enum { TSDB_UPDATE_META, TSDB_DROP_META }; + +#ifdef WINDOWS +#pragma pack(push ,1) +typedef struct { +#else typedef struct __attribute__((packed)){ +#endif char act; uint64_t uid; } SActObj; +#ifdef WINDOWS +#pragma pack(pop) +#endif typedef struct { int len; @@ -140,22 +151,22 @@ typedef struct { // ------------------ tsdbFile.c extern const char* tsdbFileSuffix[]; typedef enum { -#ifdef TSDB_IDX - TSDB_FILE_TYPE_IDX = 0, - TSDB_FILE_TYPE_HEAD, -#else TSDB_FILE_TYPE_HEAD = 0, -#endif TSDB_FILE_TYPE_DATA, TSDB_FILE_TYPE_LAST, - TSDB_FILE_TYPE_MAX, -#ifdef TSDB_IDX - TSDB_FILE_TYPE_NIDX, -#endif + TSDB_FILE_TYPE_STAT, TSDB_FILE_TYPE_NHEAD, - TSDB_FILE_TYPE_NLAST + TSDB_FILE_TYPE_NDATA, + TSDB_FILE_TYPE_NLAST, + TSDB_FILE_TYPE_NSTAT } TSDB_FILE_TYPE; +#ifndef TDINTERNAL +#define TSDB_FILE_TYPE_MAX (TSDB_FILE_TYPE_LAST+1) +#else +#define TSDB_FILE_TYPE_MAX (TSDB_FILE_TYPE_STAT+1) +#endif + typedef struct { uint32_t magic; uint32_t len; @@ -270,9 +281,6 @@ typedef struct { TSKEY minKey; TSKEY maxKey; SFileGroup fGroup; -#ifdef TSDB_IDX - SFile nIdxF; -#endif SFile nHeadF; SFile nLastF; } SHelperFile; @@ -392,6 +400,8 @@ static FORCE_INLINE STSchema *tsdbGetTableTagSchema(STable *pTable) { } // ------------------ tsdbBuffer.c +#define TSDB_BUFFER_RESERVE 1024 // Reseve 1K as commit threshold + STsdbBufPool* tsdbNewBufPool(); void tsdbFreeBufPool(STsdbBufPool* pBufPool); int tsdbOpenBufPool(STsdbRepo* pRepo); @@ -415,7 +425,7 @@ static FORCE_INLINE SDataRow tsdbNextIterRow(SSkipListIterator* pIter) { SSkipListNode* node = tSkipListIterGet(pIter); if (node == NULL) return NULL; - return SL_GET_NODE_DATA(node); + return *(SDataRow *)SL_GET_NODE_DATA(node); } static FORCE_INLINE TSKEY tsdbNextIterKey(SSkipListIterator* pIter) { @@ -425,6 +435,19 @@ static FORCE_INLINE TSKEY tsdbNextIterKey(SSkipListIterator* pIter) { return dataRowKey(row); } +static FORCE_INLINE STsdbBufBlock* tsdbGetCurrBufBlock(STsdbRepo* pRepo) { + ASSERT(pRepo != NULL); + if (pRepo->mem == NULL) return NULL; + + SListNode* pNode = listTail(pRepo->mem->bufBlockList); + if (pNode == NULL) return NULL; + + STsdbBufBlock* pBufBlock = NULL; + tdListNodeGetData(pRepo->mem->bufBlockList, pNode, (void*)(&pBufBlock)); + + return pBufBlock; +} + // ------------------ tsdbFile.c #define TSDB_KEY_FILEID(key, daysPerFile, precision) ((key) / tsMsPerDay[(precision)] / (daysPerFile)) #define TSDB_MAX_FILE(keep, daysPerFile) ((keep) / (daysPerFile) + 3) @@ -471,10 +494,6 @@ void tsdbGetFidKeyRange(int daysPerFile, int8_t precision, int fileId, TS #define helperState(h) (h)->state #define TSDB_NLAST_FILE_OPENED(h) ((h)->files.nLastF.fd > 0) #define helperFileId(h) ((h)->files.fGroup.fileId) -#ifdef TSDB_IDX -#define helperIdxF(h) (&((h)->files.fGroup.files[TSDB_FILE_TYPE_IDX])) -#define helperNewIdxF(h) (&((h)->files.nIdxF)) -#endif #define helperHeadF(h) (&((h)->files.fGroup.files[TSDB_FILE_TYPE_HEAD])) #define helperDataF(h) (&((h)->files.fGroup.files[TSDB_FILE_TYPE_DATA])) #define helperLastF(h) (&((h)->files.fGroup.files[TSDB_FILE_TYPE_LAST])) @@ -486,7 +505,7 @@ int tsdbInitWriteHelper(SRWHelper* pHelper, STsdbRepo* pRepo); void tsdbDestroyHelper(SRWHelper* pHelper); void tsdbResetHelper(SRWHelper* pHelper); int tsdbSetAndOpenHelperFile(SRWHelper* pHelper, SFileGroup* pGroup); -int tsdbCloseHelperFile(SRWHelper* pHelper, bool hasError); +int tsdbCloseHelperFile(SRWHelper* pHelper, bool hasError, SFileGroup* pGroup); int tsdbSetHelperTable(SRWHelper* pHelper, STable* pTable, STsdbRepo* pRepo); int tsdbCommitTableData(SRWHelper* pHelper, SCommitIter* pCommitIter, SDataCols* pDataCols, TSKEY maxKey); int tsdbMoveLastBlockIfNeccessary(SRWHelper* pHelper); @@ -523,6 +542,7 @@ char* tsdbGetDataDirName(char* rootDir); int tsdbGetNextMaxTables(int tid); STsdbMeta* tsdbGetMeta(TSDB_REPO_T* pRepo); STsdbFileH* tsdbGetFile(TSDB_REPO_T* pRepo); +int tsdbCheckCommit(STsdbRepo* pRepo); #ifdef __cplusplus } diff --git a/src/tsdb/src/tsdbFile.c b/src/tsdb/src/tsdbFile.c index 8cec7c08e1048b1668ac9297cdfd07829ee95d35..b8173d41b398747c4742a7c6e3cdd06b71030f67 100644 --- a/src/tsdb/src/tsdbFile.c +++ b/src/tsdb/src/tsdbFile.c @@ -18,13 +18,10 @@ #include "tchecksum.h" #include "tsdbMain.h" #include "tutil.h" + #define TAOS_RANDOM_FILE_FAIL_TEST -#ifdef TSDB_IDX -const char *tsdbFileSuffix[] = {".idx", ".head", ".data", ".last", "", ".i", ".h", ".l"}; -#else -const char *tsdbFileSuffix[] = {".head", ".data", ".last", "", ".h", ".l"}; -#endif +const char *tsdbFileSuffix[] = {".head", ".data", ".last", ".stat", ".h", ".d", ".l", ".s"}; static int tsdbInitFile(SFile *pFile, STsdbRepo *pRepo, int fid, int type); static void tsdbDestroyFile(SFile *pFile); @@ -201,7 +198,7 @@ void tsdbSeekFileGroupIter(SFileGroupIter *pIter, int fid) { pIter->index = -1; pIter->fileId = -1; } else { - pIter->index = POINTER_DISTANCE(ptr, pFileH->pFGroup) / sizeof(SFileGroup); + pIter->index = (int)(POINTER_DISTANCE(ptr, pFileH->pFGroup) / sizeof(SFileGroup)); pIter->fileId = ((SFileGroup *)ptr)->fileId; } } @@ -304,8 +301,8 @@ void tsdbFitRetention(STsdbRepo *pRepo) { STsdbFileH *pFileH = pRepo->tsdbFileH; SFileGroup *pGroup = pFileH->pFGroup; - int mfid = TSDB_KEY_FILEID(taosGetTimestamp(pCfg->precision), pCfg->daysPerFile, pCfg->precision) - - TSDB_MAX_FILE(pCfg->keep, pCfg->daysPerFile); + int mfid = (int)(TSDB_KEY_FILEID(taosGetTimestamp(pCfg->precision), pCfg->daysPerFile, pCfg->precision) - + TSDB_MAX_FILE(pCfg->keep, pCfg->daysPerFile)); pthread_rwlock_wrlock(&(pFileH->fhlock)); @@ -370,7 +367,7 @@ void tsdbRemoveFileGroup(STsdbRepo *pRepo, SFileGroup *pFGroup) { SFileGroup fileGroup = *pFGroup; - int nFilesLeft = pFileH->nFGroups - (POINTER_DISTANCE(pFGroup, pFileH->pFGroup) / sizeof(SFileGroup) + 1); + int nFilesLeft = pFileH->nFGroups - (int)(POINTER_DISTANCE(pFGroup, pFileH->pFGroup) / sizeof(SFileGroup) + 1); if (nFilesLeft > 0) { memmove((void *)pFGroup, POINTER_SHIFT(pFGroup, sizeof(SFileGroup)), sizeof(SFileGroup) * nFilesLeft); } @@ -412,6 +409,10 @@ static int tsdbInitFile(SFile *pFile, STsdbRepo *pRepo, int fid, int type) { pBuf = taosDecodeFixedU32(pBuf, &version); pBuf = tsdbDecodeSFileInfo(pBuf, &(pFile->info)); + if (pFile->info.size == TSDB_FILE_HEAD_SIZE) { + pFile->info.size = lseek(pFile->fd, 0, SEEK_END); + } + if (version != TSDB_FILE_VERSION) { tsdbError("vgId:%d file %s version %u is not the same as program version %u which may cause problem", REPO_ID(pRepo), pFile->fname, version, TSDB_FILE_VERSION); diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 1486adb65b984202fba3759a3383a6c6d0517e95..3acad055042a2479cf3293baa16ce2fabf1c7a71 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -192,6 +192,8 @@ int32_t tsdbInsertData(TSDB_REPO_T *repo, SSubmitMsg *pMsg, SShellSubmitRspMsg * } if (pRsp != NULL) pRsp->affectedRows = htonl(affectedrows); + + if (tsdbCheckCommit(pRepo) < 0) return -1; return 0; } @@ -209,7 +211,7 @@ uint32_t tsdbGetFileInfo(TSDB_REPO_T *repo, char *name, uint32_t *index, uint32_ char *sdup = strdup(pRepo->rootDir); char *prefix = dirname(sdup); - int prefixLen = strlen(prefix); + int prefixLen = (int)strlen(prefix); taosTFree(sdup); if (name[0] == 0) { // get the file from index or after, but not larger than eindex @@ -230,7 +232,7 @@ uint32_t tsdbGetFileInfo(TSDB_REPO_T *repo, char *name, uint32_t *index, uint32_ fname = strdup(pFGroup->files[(*index) % TSDB_FILE_TYPE_MAX].fname); magic = pFGroup->files[(*index) % TSDB_FILE_TYPE_MAX].info.magic; } else { - if ((pFGroup->fileId + 1) * TSDB_FILE_TYPE_MAX - 1 < eindex) { + if ((pFGroup->fileId + 1) * TSDB_FILE_TYPE_MAX - 1 < (int)eindex) { fname = strdup(pFGroup->files[0].fname); *index = pFGroup->fileId * TSDB_FILE_TYPE_MAX; magic = pFGroup->files[0].info.magic; @@ -325,7 +327,7 @@ void tsdbReportStat(void *repo, int64_t *totalPoints, int64_t *totalStorage, int // ----------------- INTERNAL FUNCTIONS ----------------- char *tsdbGetMetaFileName(char *rootDir) { - int tlen = strlen(rootDir) + strlen(TSDB_META_FILE_NAME) + 2; + int tlen = (int)(strlen(rootDir) + strlen(TSDB_META_FILE_NAME) + 2); char *fname = calloc(1, tlen); if (fname == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; @@ -364,7 +366,7 @@ int tsdbUnlockRepo(STsdbRepo *pRepo) { } char *tsdbGetDataDirName(char *rootDir) { - int tlen = strlen(rootDir) + strlen(TSDB_DATA_DIR_NAME) + 2; + int tlen = (int)(strlen(rootDir) + strlen(TSDB_DATA_DIR_NAME) + 2); char *fname = calloc(1, tlen); if (fname == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; @@ -387,6 +389,21 @@ int tsdbGetNextMaxTables(int tid) { return maxTables + 1; } +int tsdbCheckCommit(STsdbRepo *pRepo) { + ASSERT(pRepo->mem != NULL); + STsdbCfg *pCfg = &(pRepo->config); + + STsdbBufBlock *pBufBlock = tsdbGetCurrBufBlock(pRepo); + ASSERT(pBufBlock != NULL); + if ((pRepo->mem->extraBuffList != NULL) || + ((listNEles(pRepo->mem->bufBlockList) >= pCfg->totalBlocks / 3) && (pBufBlock->remain < TSDB_BUFFER_RESERVE))) { + // trigger commit + if (tsdbAsyncCommit(pRepo) < 0) return -1; + } + + return 0; +} + STsdbMeta * tsdbGetMeta(TSDB_REPO_T *pRepo) { return ((STsdbRepo *)pRepo)->tsdbMeta; } STsdbFileH * tsdbGetFile(TSDB_REPO_T *pRepo) { return ((STsdbRepo *)pRepo)->tsdbFileH; } STsdbRepoInfo *tsdbGetStatus(TSDB_REPO_T *pRepo) { return NULL; } @@ -610,7 +627,7 @@ _err: } static char *tsdbGetCfgFname(char *rootDir) { - int tlen = strlen(rootDir) + strlen(TSDB_CFG_FILE_NAME) + 2; + int tlen = (int)(strlen(rootDir) + strlen(TSDB_CFG_FILE_NAME) + 2); char *fname = calloc(1, tlen); if (fname == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; @@ -836,8 +853,8 @@ static int tsdbAlterKeep(STsdbRepo *pRepo, int32_t keep) { return -1; } - int mfid = TSDB_KEY_FILEID(taosGetTimestamp(pCfg->precision), pCfg->daysPerFile, pCfg->precision) - - TSDB_MAX_FILE(keep, pCfg->daysPerFile); + int mfid = (int)(TSDB_KEY_FILEID(taosGetTimestamp(pCfg->precision), pCfg->daysPerFile, pCfg->precision) - + TSDB_MAX_FILE(keep, pCfg->daysPerFile)); int i = 0; for (; i < pFileH->nFGroups; i++) { diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 44f787a8c0d01192cc77e88b7859b9ce6902858f..cd5f223f3da5c7595e3c267590b0be3047181daf 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -18,8 +18,6 @@ #define TSDB_DATA_SKIPLIST_LEVEL 5 -static FORCE_INLINE STsdbBufBlock *tsdbGetCurrBufBlock(STsdbRepo *pRepo); - static void tsdbFreeBytes(STsdbRepo *pRepo, void *ptr, int bytes); static SMemTable * tsdbNewMemTable(STsdbRepo *pRepo); static void tsdbFreeMemTable(SMemTable *pMemTable); @@ -45,7 +43,6 @@ int tsdbInsertRowToMem(STsdbRepo *pRepo, SDataRow row, STable *pTable) { SMemTable * pMemTable = pRepo->mem; STableData *pTableData = NULL; SSkipList * pSList = NULL; - int bytes = 0; if (pMemTable != NULL && TABLE_TID(pTable) < pMemTable->maxTables && pMemTable->tData[TABLE_TID(pTable)] != NULL && pMemTable->tData[TABLE_TID(pTable)]->uid == TABLE_UID(pTable)) { @@ -55,27 +52,39 @@ int tsdbInsertRowToMem(STsdbRepo *pRepo, SDataRow row, STable *pTable) { tSkipListNewNodeInfo(pSList, &level, &headSize); - bytes = headSize + dataRowLen(row); - SSkipListNode *pNode = tsdbAllocBytes(pRepo, bytes); + SSkipListNode *pNode = (SSkipListNode *)malloc(headSize + sizeof(SDataRow *)); if (pNode == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + return -1; + } + + void *pRow = tsdbAllocBytes(pRepo, dataRowLen(row)); + if (pRow == NULL) { tsdbError("vgId:%d failed to insert row with key %" PRId64 " to table %s while allocate %d bytes since %s", - REPO_ID(pRepo), key, TABLE_CHAR_NAME(pTable), bytes, tstrerror(terrno)); + REPO_ID(pRepo), key, TABLE_CHAR_NAME(pTable), dataRowLen(row), tstrerror(terrno)); + free(pNode); return -1; } + pNode->level = level; - dataRowCpy(SL_GET_NODE_DATA(pNode), row); + dataRowCpy(pRow, row); + *(SDataRow *)SL_GET_NODE_DATA(pNode) = pRow; // Operations above may change pRepo->mem, retake those values ASSERT(pRepo->mem != NULL); pMemTable = pRepo->mem; if (TABLE_TID(pTable) >= pMemTable->maxTables) { - if (tsdbAdjustMemMaxTables(pMemTable, pMeta->maxTables) < 0) return -1;; + if (tsdbAdjustMemMaxTables(pMemTable, pMeta->maxTables) < 0) { + tsdbFreeBytes(pRepo, pRow, dataRowLen(row)); + free(pNode); + return -1; + } } pTableData = pMemTable->tData[TABLE_TID(pTable)]; if (pTableData == NULL || pTableData->uid != TABLE_UID(pTable)) { - if (pTableData != NULL) { // destroy the table skiplist (may have race condition problem) + if (pTableData != NULL) { taosWLockLatch(&(pMemTable->latch)); pMemTable->tData[TABLE_TID(pTable)] = NULL; tsdbFreeTableData(pTableData); @@ -87,7 +96,8 @@ int tsdbInsertRowToMem(STsdbRepo *pRepo, SDataRow row, STable *pTable) { tsdbError("vgId:%d failed to insert row with key %" PRId64 " to table %s while create new table data object since %s", REPO_ID(pRepo), key, TABLE_CHAR_NAME(pTable), tstrerror(terrno)); - tsdbFreeBytes(pRepo, (void *)pNode, bytes); + tsdbFreeBytes(pRepo, (void *)pRow, dataRowLen(row)); + free(pNode); return -1; } @@ -97,7 +107,8 @@ int tsdbInsertRowToMem(STsdbRepo *pRepo, SDataRow row, STable *pTable) { ASSERT((pTableData != NULL) && pTableData->uid == TABLE_UID(pTable)); if (tSkipListPut(pTableData->pData, pNode) == NULL) { - tsdbFreeBytes(pRepo, (void *)pNode, bytes); + tsdbFreeBytes(pRepo, (void *)pRow, dataRowLen(row)); + free(pNode); } else { if (TABLE_LASTKEY(pTable) < key) TABLE_LASTKEY(pTable) = key; if (pMemTable->keyFirst > key) pMemTable->keyFirst = key; @@ -189,44 +200,59 @@ void tsdbUnTakeMemSnapShot(STsdbRepo *pRepo, SMemTable *pMem, SMemTable *pIMem) void *tsdbAllocBytes(STsdbRepo *pRepo, int bytes) { STsdbCfg * pCfg = &pRepo->config; - STsdbBufBlock *pBufBlock = tsdbGetCurrBufBlock(pRepo); - - if (pBufBlock != NULL && pBufBlock->remain < bytes) { - if (listNEles(pRepo->mem->bufBlockList) >= pCfg->totalBlocks / 3) { // need to commit mem - if (tsdbAsyncCommit(pRepo) < 0) return NULL; - } else { - if (tsdbLockRepo(pRepo) < 0) return NULL; - SListNode *pNode = tsdbAllocBufBlockFromPool(pRepo); - tdListAppendNode(pRepo->mem->bufBlockList, pNode); - if (tsdbUnlockRepo(pRepo) < 0) return NULL; - } - } + STsdbBufBlock *pBufBlock = NULL; + void * ptr = NULL; + // Either allocate from buffer blocks or from SYSTEM memory pool if (pRepo->mem == NULL) { SMemTable *pMemTable = tsdbNewMemTable(pRepo); if (pMemTable == NULL) return NULL; + pRepo->mem = pMemTable; + } - if (tsdbLockRepo(pRepo) < 0) { - tsdbFreeMemTable(pMemTable); + ASSERT(pRepo->mem != NULL); + + pBufBlock = tsdbGetCurrBufBlock(pRepo); + if ((pRepo->mem->extraBuffList != NULL) || + ((listNEles(pRepo->mem->bufBlockList) >= pCfg->totalBlocks / 3) && (pBufBlock->remain < bytes))) { + // allocate from SYSTEM buffer pool + if (pRepo->mem->extraBuffList == NULL) { + pRepo->mem->extraBuffList = tdListNew(0); + if (pRepo->mem->extraBuffList == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + return NULL; + } + } + + ASSERT(pRepo->mem->extraBuffList != NULL); + SListNode *pNode = (SListNode *)malloc(sizeof(SListNode) + bytes); + if (pNode == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; return NULL; } - SListNode *pNode = tsdbAllocBufBlockFromPool(pRepo); - tdListAppendNode(pMemTable->bufBlockList, pNode); - pRepo->mem = pMemTable; + pNode->next = pNode->prev = NULL; + tdListAppend(pRepo->mem->extraBuffList, pNode); + ptr = (void *)(pNode->data); + tsdbTrace("vgId:%d allocate %d bytes from SYSTEM buffer block", REPO_ID(pRepo), bytes); + } else { // allocate from TSDB buffer pool + if (pBufBlock == NULL || pBufBlock->remain < bytes) { + ASSERT(listNEles(pRepo->mem->bufBlockList) < pCfg->totalBlocks / 3); + if (tsdbLockRepo(pRepo) < 0) return NULL; + SListNode *pNode = tsdbAllocBufBlockFromPool(pRepo); + tdListAppendNode(pRepo->mem->bufBlockList, pNode); + if (tsdbUnlockRepo(pRepo) < 0) return NULL; + pBufBlock = tsdbGetCurrBufBlock(pRepo); + } - if (tsdbUnlockRepo(pRepo) < 0) return NULL; + ASSERT(pBufBlock->remain >= bytes); + ptr = POINTER_SHIFT(pBufBlock->data, pBufBlock->offset); + pBufBlock->offset += bytes; + pBufBlock->remain -= bytes; + tsdbTrace("vgId:%d allocate %d bytes from TSDB buffer block, nBlocks %d offset %d remain %d", REPO_ID(pRepo), bytes, + listNEles(pRepo->mem->bufBlockList), pBufBlock->offset, pBufBlock->remain); } - pBufBlock = tsdbGetCurrBufBlock(pRepo); - ASSERT(pBufBlock->remain >= bytes); - void *ptr = POINTER_SHIFT(pBufBlock->data, pBufBlock->offset); - pBufBlock->offset += bytes; - pBufBlock->remain -= bytes; - - tsdbTrace("vgId:%d allocate %d bytes from buffer block, nBlocks %d offset %d remain %d", REPO_ID(pRepo), bytes, - listNEles(pRepo->mem->bufBlockList), pBufBlock->offset, pBufBlock->remain); - return ptr; } @@ -281,7 +307,7 @@ int tsdbLoadDataFromCache(STable *pTable, SSkipListIterator *pIter, TSKEY maxKey keyNext = tsdbNextIterKey(pIter); if (keyNext < 0 || keyNext > maxKey) return numOfRows; void *ptr = taosbsearch((void *)(&keyNext), (void *)filterKeys, nFilterKeys, sizeof(TSKEY), compTSKEY, TD_GE); - filterIter = (ptr == NULL) ? nFilterKeys : (POINTER_DISTANCE(ptr, filterKeys) / sizeof(TSKEY)); + filterIter = (ptr == NULL) ? nFilterKeys : (int)((POINTER_DISTANCE(ptr, filterKeys) / sizeof(TSKEY))); } do { @@ -327,27 +353,23 @@ int tsdbLoadDataFromCache(STable *pTable, SSkipListIterator *pIter, TSKEY maxKey } // ---------------- LOCAL FUNCTIONS ---------------- -static FORCE_INLINE STsdbBufBlock *tsdbGetCurrBufBlock(STsdbRepo *pRepo) { - ASSERT(pRepo != NULL); - if (pRepo->mem == NULL) return NULL; - - SListNode *pNode = listTail(pRepo->mem->bufBlockList); - if (pNode == NULL) return NULL; - - STsdbBufBlock *pBufBlock = NULL; - tdListNodeGetData(pRepo->mem->bufBlockList, pNode, (void *)(&pBufBlock)); - - return pBufBlock; -} - static void tsdbFreeBytes(STsdbRepo *pRepo, void *ptr, int bytes) { - STsdbBufBlock *pBufBlock = tsdbGetCurrBufBlock(pRepo); - ASSERT(pBufBlock != NULL); - pBufBlock->offset -= bytes; - pBufBlock->remain += bytes; - ASSERT(ptr == POINTER_SHIFT(pBufBlock->data, pBufBlock->offset)); - tsdbTrace("vgId:%d return %d bytes to buffer block, nBlocks %d offset %d remain %d", REPO_ID(pRepo), bytes, - listNEles(pRepo->mem->bufBlockList), pBufBlock->offset, pBufBlock->remain); + ASSERT(pRepo->mem != NULL); + if (pRepo->mem->extraBuffList == NULL) { + STsdbBufBlock *pBufBlock = tsdbGetCurrBufBlock(pRepo); + ASSERT(pBufBlock != NULL); + pBufBlock->offset -= bytes; + pBufBlock->remain += bytes; + ASSERT(ptr == POINTER_SHIFT(pBufBlock->data, pBufBlock->offset)); + tsdbTrace("vgId:%d free %d bytes to TSDB buffer pool, nBlocks %d offset %d remain %d", REPO_ID(pRepo), bytes, + listNEles(pRepo->mem->bufBlockList), pBufBlock->offset, pBufBlock->remain); + } else { + SListNode *pNode = (SListNode *)POINTER_SHIFT(ptr, -(int)(sizeof(SListNode))); + ASSERT(listTail(pRepo->mem->extraBuffList) == pNode); + tdListPopNode(pRepo->mem->extraBuffList, pNode); + free(pNode); + tsdbTrace("vgId:%d free %d bytes to SYSTEM buffer pool", REPO_ID(pRepo), bytes); + } } static SMemTable* tsdbNewMemTable(STsdbRepo *pRepo) { @@ -396,6 +418,7 @@ static void tsdbFreeMemTable(SMemTable* pMemTable) { ASSERT((pMemTable->bufBlockList == NULL) ? true : (listNEles(pMemTable->bufBlockList) == 0)); ASSERT((pMemTable->actList == NULL) ? true : (listNEles(pMemTable->actList) == 0)); + tdListFree(pMemTable->extraBuffList); tdListFree(pMemTable->bufBlockList); tdListFree(pMemTable->actList); taosTFree(pMemTable->tData); @@ -416,7 +439,7 @@ static STableData *tsdbNewTableData(STsdbCfg *pCfg, STable *pTable) { pTableData->numOfRows = 0; pTableData->pData = tSkipListCreate(TSDB_DATA_SKIPLIST_LEVEL, TSDB_DATA_TYPE_TIMESTAMP, - TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], 0, 0, 0, tsdbGetTsTupleKey); + TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], 0, 0, 1, tsdbGetTsTupleKey); if (pTableData->pData == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; goto _err; @@ -436,7 +459,7 @@ static void tsdbFreeTableData(STableData *pTableData) { } } -static char *tsdbGetTsTupleKey(const void *data) { return dataRowTuple(data); } +static char *tsdbGetTsTupleKey(const void *data) { return dataRowTuple(*(SDataRow *)data); } static void *tsdbCommitData(void *arg) { STsdbRepo * pRepo = (STsdbRepo *)arg; @@ -472,8 +495,8 @@ static void *tsdbCommitData(void *arg) { goto _exit; } - int sfid = TSDB_KEY_FILEID(pMem->keyFirst, pCfg->daysPerFile, pCfg->precision); - int efid = TSDB_KEY_FILEID(pMem->keyLast, pCfg->daysPerFile, pCfg->precision); + int sfid = (int)(TSDB_KEY_FILEID(pMem->keyFirst, pCfg->daysPerFile, pCfg->precision)); + int efid = (int)(TSDB_KEY_FILEID(pMem->keyLast, pCfg->daysPerFile, pCfg->precision)); // Loop to commit to each file for (int fid = sfid; fid <= efid; fid++) { @@ -656,15 +679,10 @@ static int tsdbCommitToFile(STsdbRepo *pRepo, int fid, SCommitIter *iters, SRWHe } taosTFree(dataDir); - tsdbCloseHelperFile(pHelper, 0); + tsdbCloseHelperFile(pHelper, 0, pGroup); pthread_rwlock_wrlock(&(pFileH->fhlock)); -#ifdef TSDB_IDX - rename(helperNewIdxF(pHelper)->fname, helperIdxF(pHelper)->fname); - pGroup->files[TSDB_FILE_TYPE_IDX].info = helperNewIdxF(pHelper)->info; -#endif - rename(helperNewHeadF(pHelper)->fname, helperHeadF(pHelper)->fname); pGroup->files[TSDB_FILE_TYPE_HEAD].info = helperNewHeadF(pHelper)->info; @@ -683,7 +701,7 @@ static int tsdbCommitToFile(STsdbRepo *pRepo, int fid, SCommitIter *iters, SRWHe _err: taosTFree(dataDir); - tsdbCloseHelperFile(pHelper, 1); + tsdbCloseHelperFile(pHelper, 1, NULL); return -1; } diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 52dca61519edd5080b389fe96f6dcc4b0bb51162..a84bb69777f512a6c5d947dd48f8f2865b867200 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -120,20 +120,23 @@ int tsdbCreateTable(TSDB_REPO_T *repo, STableCfg *pCfg) { tsdbUnlockRepoMeta(pRepo); // Write to memtable action - int tlen1 = (newSuper) ? tsdbGetTableEncodeSize(TSDB_UPDATE_META, super) : 0; - int tlen2 = tsdbGetTableEncodeSize(TSDB_UPDATE_META, table); - int tlen = tlen1 + tlen2; - void *buf = tsdbAllocBytes(pRepo, tlen); - if (buf == NULL) { - goto _err; - } - + // TODO: refactor duplicate codes + int tlen = 0; + void *pBuf = NULL; if (newSuper) { - void *pBuf = tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, buf, super); - ASSERT(POINTER_DISTANCE(pBuf, buf) == tlen1); - buf = pBuf; + tlen = tsdbGetTableEncodeSize(TSDB_UPDATE_META, super); + pBuf = tsdbAllocBytes(pRepo, tlen); + if (pBuf == NULL) goto _err; + void *tBuf = tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, pBuf, super); + ASSERT(POINTER_DISTANCE(tBuf, pBuf) == tlen); } - tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, buf, table); + tlen = tsdbGetTableEncodeSize(TSDB_UPDATE_META, table); + pBuf = tsdbAllocBytes(pRepo, tlen); + if (pBuf == NULL) goto _err; + void *tBuf = tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, pBuf, table); + ASSERT(POINTER_DISTANCE(tBuf, pBuf) == tlen); + + if (tsdbCheckCommit(pRepo) < 0) return -1; return 0; @@ -182,6 +185,8 @@ int tsdbDropTable(TSDB_REPO_T *repo, STableId tableId) { tsdbDebug("vgId:%d, table %s is dropped! tid:%d, uid:%" PRId64, pRepo->config.tsdbId, tbname, tid, uid); free(tbname); + if (tsdbCheckCommit(pRepo) < 0) goto _err; + return 0; _err: @@ -405,6 +410,8 @@ int tsdbUpdateTableTagValue(TSDB_REPO_T *repo, SUpdateTableTagValMsg *pMsg) { } tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, buf, pTable); + if (tsdbCheckCommit(pRepo) < 0) return -1; + return 0; } @@ -436,7 +443,7 @@ STsdbMeta *tsdbNewMeta(STsdbCfg *pCfg) { goto _err; } - pMeta->uidMap = taosHashInit(TSDB_INIT_NTABLES * 1.1, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); + pMeta->uidMap = taosHashInit((size_t)(TSDB_INIT_NTABLES * 1.1), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); if (pMeta->uidMap == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; goto _err; @@ -665,7 +672,7 @@ static STable *tsdbNewTable(STableCfg *pCfg, bool isSuper) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; goto _err; } - STR_WITH_SIZE_TO_VARSTR(pTable->name, pCfg->sname, tsize); + STR_WITH_SIZE_TO_VARSTR(pTable->name, pCfg->sname, (VarDataLenT)tsize); TABLE_UID(pTable) = pCfg->superUid; TABLE_TID(pTable) = -1; TABLE_SUID(pTable) = -1; @@ -683,7 +690,7 @@ static STable *tsdbNewTable(STableCfg *pCfg, bool isSuper) { } pTable->tagVal = NULL; STColumn *pCol = schemaColAt(pTable->tagSchema, DEFAULT_TAG_INDEX_COLUMN); - pTable->pIndex = tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), colBytes(pCol), 1, 0, 1, getTagIndexKey); + pTable->pIndex = tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), (uint8_t)(colBytes(pCol)), 1, 0, 1, getTagIndexKey); if (pTable->pIndex == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; goto _err; @@ -696,7 +703,7 @@ static STable *tsdbNewTable(STableCfg *pCfg, bool isSuper) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; goto _err; } - STR_WITH_SIZE_TO_VARSTR(pTable->name, pCfg->name, tsize); + STR_WITH_SIZE_TO_VARSTR(pTable->name, pCfg->name, (VarDataLenT)tsize); TABLE_UID(pTable) = pCfg->tableId.uid; TABLE_TID(pTable) = pCfg->tableId.tid; @@ -1158,7 +1165,7 @@ static void *tsdbDecodeTable(void *buf, STable **pRTable) { buf = tdDecodeSchema(buf, &(pTable->tagSchema)); STColumn *pCol = schemaColAt(pTable->tagSchema, DEFAULT_TAG_INDEX_COLUMN); pTable->pIndex = - tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), colBytes(pCol), 1, 0, 1, getTagIndexKey); + tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), (uint8_t)(colBytes(pCol)), 1, 0, 1, getTagIndexKey); if (pTable->pIndex == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; tsdbFreeTable(pTable); @@ -1184,7 +1191,7 @@ static int tsdbGetTableEncodeSize(int8_t act, STable *pTable) { tlen = sizeof(SListNode) + sizeof(SActObj) + sizeof(SActCont) + tsdbEncodeTable(NULL, pTable) + sizeof(TSCKSUM); } else { if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) { - tlen = (sizeof(SListNode) + sizeof(SActObj)) * (tSkipListGetSize(pTable->pIndex) + 1); + tlen = (int)((sizeof(SListNode) + sizeof(SActObj)) * (tSkipListGetSize(pTable->pIndex) + 1)); } else { tlen = sizeof(SListNode) + sizeof(SActObj); } diff --git a/src/tsdb/src/tsdbRWHelper.c b/src/tsdb/src/tsdbRWHelper.c index fb79747d303295fbfa39703ec90000de45957e6c..1e082e39bed065d6ae81a8aef53342a2f0535938 100644 --- a/src/tsdb/src/tsdbRWHelper.c +++ b/src/tsdb/src/tsdbRWHelper.c @@ -91,7 +91,7 @@ void tsdbResetHelper(SRWHelper *pHelper) { tsdbResetHelperTableImpl(pHelper); // Reset the file part - tsdbCloseHelperFile(pHelper, false); + tsdbCloseHelperFile(pHelper, false, NULL); tsdbResetHelperFileImpl(pHelper); pHelper->state = TSDB_HELPER_CLEAR_STATE; @@ -110,31 +110,16 @@ int tsdbSetAndOpenHelperFile(SRWHelper *pHelper, SFileGroup *pGroup) { // Set the files pHelper->files.fGroup = *pGroup; if (helperType(pHelper) == TSDB_WRITE_HELPER) { -#ifdef TSDB_IDX - tsdbGetDataFileName(pHelper->pRepo, pGroup->fileId, TSDB_FILE_TYPE_NIDX, helperNewIdxF(pHelper)->fname); -#endif tsdbGetDataFileName(pHelper->pRepo, pGroup->fileId, TSDB_FILE_TYPE_NHEAD, helperNewHeadF(pHelper)->fname); tsdbGetDataFileName(pHelper->pRepo, pGroup->fileId, TSDB_FILE_TYPE_NLAST, helperNewLastF(pHelper)->fname); } // Open the files -#ifdef TSDB_IDX - if (tsdbOpenFile(helperIdxF(pHelper), O_RDONLY) < 0) return -1; -#endif if (tsdbOpenFile(helperHeadF(pHelper), O_RDONLY) < 0) return -1; if (helperType(pHelper) == TSDB_WRITE_HELPER) { if (tsdbOpenFile(helperDataF(pHelper), O_RDWR) < 0) return -1; if (tsdbOpenFile(helperLastF(pHelper), O_RDWR) < 0) return -1; -#ifdef TSDB_IDX - // Create and open .i file - pFile = helperNewIdxF(pHelper); - if (tsdbOpenFile(pFile, O_WRONLY | O_CREAT) < 0) return -1; - pFile->info.size = TSDB_FILE_HEAD_SIZE; - pFile->info.magic = TSDB_FILE_INIT_MAGIC; - if (tsdbUpdateFileHeader(pFile) < 0) return -1; -#endif - // Create and open .h pFile = helperNewHeadF(pHelper); if (tsdbOpenFile(pFile, O_WRONLY | O_CREAT) < 0) return -1; @@ -161,14 +146,9 @@ int tsdbSetAndOpenHelperFile(SRWHelper *pHelper, SFileGroup *pGroup) { return 0; } -int tsdbCloseHelperFile(SRWHelper *pHelper, bool hasError) { +int tsdbCloseHelperFile(SRWHelper *pHelper, bool hasError, SFileGroup *pGroup) { SFile *pFile = NULL; -#ifdef TSDB_IDX - pFile = helperIdxF(pHelper); - tsdbCloseFile(pFile); -#endif - pFile = helperHeadF(pHelper); tsdbCloseFile(pFile); @@ -177,10 +157,11 @@ int tsdbCloseHelperFile(SRWHelper *pHelper, bool hasError) { if (helperType(pHelper) == TSDB_WRITE_HELPER) { if (!hasError) { tsdbUpdateFileHeader(pFile); - fsync(pFile->fd); } else { - // TODO: shrink back to origin + ASSERT(pGroup != NULL); + taosFtruncate(pFile->fd, pGroup->files[TSDB_FILE_TYPE_DATA].info.size); } + fsync(pFile->fd); } tsdbCloseFile(pFile); } @@ -190,27 +171,16 @@ int tsdbCloseHelperFile(SRWHelper *pHelper, bool hasError) { if (helperType(pHelper) == TSDB_WRITE_HELPER && !TSDB_NLAST_FILE_OPENED(pHelper)) { if (!hasError) { tsdbUpdateFileHeader(pFile); - fsync(pFile->fd); } else { - // TODO: shrink back to origin + ASSERT(pGroup != NULL); + taosFtruncate(pFile->fd, pGroup->files[TSDB_FILE_TYPE_LAST].info.size); } + fsync(pFile->fd); } tsdbCloseFile(pFile); } if (helperType(pHelper) == TSDB_WRITE_HELPER) { -#ifdef TSDB_IDX - pFile = helperNewIdxF(pHelper); - if (pFile->fd > 0) { - if (!hasError) { - tsdbUpdateFileHeader(pFile); - fsync(pFile->fd); - } - tsdbCloseFile(pFile); - if (hasError) (void)remove(pFile->fname); - } -#endif - pFile = helperNewHeadF(pHelper); if (pFile->fd > 0) { if (!hasError) { @@ -302,7 +272,7 @@ int tsdbCommitTableData(SRWHelper *pHelper, SCommitIter *pCommitIter, SDataCols if (tsdbLoadCompInfo(pHelper, NULL) < 0) return -1; while (true) { - ASSERT(blkIdx <= pIdx->numOfBlocks); + ASSERT(blkIdx <= (int)pIdx->numOfBlocks); TSKEY keyFirst = tsdbNextIterKey(pCommitIter->pIter); if (keyFirst < 0 || keyFirst > maxKey) break; // iter over @@ -405,17 +375,13 @@ int tsdbWriteCompInfo(SRWHelper *pHelper) { pIdx->tid = pHelper->tableInfo.tid; ASSERT(pIdx->offset >= TSDB_FILE_HEAD_SIZE); - if (taosTWrite(pFile->fd, (void *)(pHelper->pCompInfo), pIdx->len) < pIdx->len) { + if (taosTWrite(pFile->fd, (void *)(pHelper->pCompInfo), pIdx->len) < (int)pIdx->len) { tsdbError("vgId:%d failed to write %d bytes to file %s since %s", REPO_ID(pHelper->pRepo), pIdx->len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; } -#ifdef TSDB_IDX - pFile = helperNewIdxF(pHelper); -#endif - if (taosTSizeof(pHelper->pWIdx) < pFile->info.len + sizeof(SCompIdx) + 12) { pHelper->pWIdx = taosTRealloc(pHelper->pWIdx, taosTSizeof(pHelper->pWIdx) == 0 ? 1024 : taosTSizeof(pHelper->pWIdx) * 2); if (pHelper->pWIdx == NULL) { @@ -426,6 +392,9 @@ int tsdbWriteCompInfo(SRWHelper *pHelper) { void *pBuf = POINTER_SHIFT(pHelper->pWIdx, pFile->info.len); pFile->info.len += tsdbEncodeSCompIdx(&pBuf, &(pHelper->curCompIdx)); + + pFile->info.size += pIdx->len; + // ASSERT(pFile->info.size == lseek(pFile->fd, 0, SEEK_CUR)); } return 0; @@ -435,11 +404,7 @@ int tsdbWriteCompIdx(SRWHelper *pHelper) { ASSERT(helperType(pHelper) == TSDB_WRITE_HELPER); off_t offset = 0; -#ifdef TSDB_IDX - SFile *pFile = helperNewIdxF(pHelper); -#else SFile *pFile = helperNewHeadF(pHelper); -#endif pFile->info.len += sizeof(TSCKSUM); if (taosTSizeof(pHelper->pWIdx) < pFile->info.len) { @@ -460,25 +425,25 @@ int tsdbWriteCompIdx(SRWHelper *pHelper) { return -1; } - pFile->info.offset = offset; + ASSERT(offset == pFile->info.size); - if (taosTWrite(pFile->fd, (void *)pHelper->pWIdx, pFile->info.len) < pFile->info.len) { + if (taosTWrite(pFile->fd, (void *)pHelper->pWIdx, pFile->info.len) < (int)pFile->info.len) { tsdbError("vgId:%d failed to write %d bytes to file %s since %s", REPO_ID(pHelper->pRepo), pFile->info.len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; } + pFile->info.offset = offset; + pFile->info.size += pFile->info.len; + // ASSERT(pFile->info.size == lseek(pFile->fd, 0, SEEK_CUR)); + return 0; } int tsdbLoadCompIdx(SRWHelper *pHelper, void *target) { ASSERT(pHelper->state == TSDB_HELPER_FILE_SET_AND_OPEN); -#ifdef TSDB_IDX - SFile *pFile = helperIdxF(pHelper); -#else SFile *pFile = helperHeadF(pHelper); -#endif int fd = pFile->fd; if (!helperHasState(pHelper, TSDB_HELPER_IDX_LOAD)) { @@ -495,7 +460,7 @@ int tsdbLoadCompIdx(SRWHelper *pHelper, void *target) { return -1; } - if (taosTRead(fd, (void *)(pHelper->pBuffer), pFile->info.len) < pFile->info.len) { + if (taosTRead(fd, (void *)(pHelper->pBuffer), pFile->info.len) < (int)pFile->info.len) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pHelper->pRepo), pFile->info.len, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -512,7 +477,7 @@ int tsdbLoadCompIdx(SRWHelper *pHelper, void *target) { // Decode it pHelper->idxH.numOfIdx = 0; void *ptr = pHelper->pBuffer; - while (POINTER_DISTANCE(ptr, pHelper->pBuffer) < (pFile->info.len - sizeof(TSCKSUM))) { + while (POINTER_DISTANCE(ptr, pHelper->pBuffer) < (int)(pFile->info.len - sizeof(TSCKSUM))) { size_t tlen = taosTSizeof(pHelper->idxH.pIdxArray); pHelper->idxH.numOfIdx++; @@ -535,7 +500,7 @@ int tsdbLoadCompIdx(SRWHelper *pHelper, void *target) { ASSERT(pHelper->idxH.numOfIdx == 1 || pHelper->idxH.pIdxArray[pHelper->idxH.numOfIdx - 1].tid > pHelper->idxH.pIdxArray[pHelper->idxH.numOfIdx - 2].tid); - ASSERT(POINTER_DISTANCE(ptr, pHelper->pBuffer) <= pFile->info.len - sizeof(TSCKSUM)); + ASSERT(POINTER_DISTANCE(ptr, pHelper->pBuffer) <= (int)(pFile->info.len - sizeof(TSCKSUM))); } } } @@ -566,7 +531,7 @@ int tsdbLoadCompInfo(SRWHelper *pHelper, void *target) { } pHelper->pCompInfo = taosTRealloc((void *)pHelper->pCompInfo, pIdx->len); - if (taosTRead(fd, (void *)(pHelper->pCompInfo), pIdx->len) < pIdx->len) { + if (taosTRead(fd, (void *)(pHelper->pCompInfo), pIdx->len) < (int)pIdx->len) { tsdbError("vgId:%d failed to read %d bytes from file %s since %s", REPO_ID(pHelper->pRepo), pIdx->len, helperHeadF(pHelper)->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -594,7 +559,7 @@ int tsdbLoadCompData(SRWHelper *pHelper, SCompBlock *pCompBlock, void *target) { ASSERT(pCompBlock->numOfSubBlocks <= 1); SFile *pFile = (pCompBlock->last) ? helperLastF(pHelper) : helperDataF(pHelper); - if (lseek(pFile->fd, pCompBlock->offset, SEEK_SET) < 0) { + if (lseek(pFile->fd, (off_t)pCompBlock->offset, SEEK_SET) < 0) { tsdbError("vgId:%d failed to lseek file %s since %s", REPO_ID(pHelper->pRepo), pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; @@ -614,7 +579,7 @@ int tsdbLoadCompData(SRWHelper *pHelper, SCompBlock *pCompBlock, void *target) { return -1; } - if (!taosCheckChecksumWhole((uint8_t *)pHelper->pCompData, tsize)) { + if (!taosCheckChecksumWhole((uint8_t *)pHelper->pCompData, (uint32_t)tsize)) { tsdbError("vgId:%d file %s is broken, offset %" PRId64 " size %zu", REPO_ID(pHelper->pRepo), pFile->fname, (int64_t)pCompBlock->offset, tsize); terrno = TSDB_CODE_TDB_FILE_CORRUPTED; @@ -787,8 +752,8 @@ static int tsdbWriteBlockToFile(SRWHelper *pHelper, SFile *pFile, SDataCols *pDa } flen = (*(tDataTypeDesc[pDataCol->type].compFunc))((char *)pDataCol->pData, tlen, rowsToWrite, tptr, - taosTSizeof(pHelper->pBuffer) - lsize, pCfg->compression, - pHelper->compBuffer, taosTSizeof(pHelper->compBuffer)); + (int32_t)taosTSizeof(pHelper->pBuffer) - lsize, pCfg->compression, + pHelper->compBuffer, (int32_t)taosTSizeof(pHelper->compBuffer)); } else { flen = tlen; memcpy(tptr, pDataCol->pData, flen); @@ -847,6 +812,9 @@ static int tsdbWriteBlockToFile(SRWHelper *pHelper, SFile *pFile, SDataCols *pDa (int)(pCompBlock->numOfRows), pCompBlock->len, pCompBlock->numOfCols, pCompBlock->keyFirst, pCompBlock->keyLast); + pFile->info.size += pCompBlock->len; + // ASSERT(pFile->info.size == lseek(pFile->fd, 0, SEEK_CUR)); + return 0; _err: @@ -879,7 +847,7 @@ static int tsdbAdjustInfoSizeIfNeeded(SRWHelper *pHelper, size_t esize) { static int tsdbInsertSuperBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int blkIdx) { SCompIdx *pIdx = &(pHelper->curCompIdx); - ASSERT(blkIdx >= 0 && blkIdx <= pIdx->numOfBlocks); + ASSERT(blkIdx >= 0 && blkIdx <= (int)pIdx->numOfBlocks); ASSERT(pCompBlock->numOfSubBlocks == 1); // Adjust memory if no more room @@ -887,7 +855,7 @@ static int tsdbInsertSuperBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int if (tsdbAdjustInfoSizeIfNeeded(pHelper, pIdx->len + sizeof(SCompInfo)) < 0) goto _err; // Change the offset - for (int i = 0; i < pIdx->numOfBlocks; i++) { + for (uint32_t i = 0; i < pIdx->numOfBlocks; i++) { SCompBlock *pTCompBlock = &pHelper->pCompInfo->blocks[i]; if (pTCompBlock->numOfSubBlocks > 1) pTCompBlock->offset += sizeof(SCompBlock); } @@ -906,7 +874,7 @@ static int tsdbInsertSuperBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int pIdx->len += sizeof(SCompBlock); ASSERT(pIdx->len <= taosTSizeof(pHelper->pCompInfo)); pIdx->maxKey = blockAtIdx(pHelper, pIdx->numOfBlocks - 1)->keyLast; - pIdx->hasLast = blockAtIdx(pHelper, pIdx->numOfBlocks - 1)->last; + pIdx->hasLast = (uint32_t)blockAtIdx(pHelper, pIdx->numOfBlocks - 1)->last; if (pIdx->numOfBlocks > 1) { ASSERT(pHelper->pCompInfo->blocks[0].keyLast < pHelper->pCompInfo->blocks[1].keyFirst); @@ -925,7 +893,7 @@ static int tsdbAddSubBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int blkId ASSERT(pCompBlock->numOfSubBlocks == 0); SCompIdx *pIdx = &(pHelper->curCompIdx); - ASSERT(blkIdx >= 0 && blkIdx < pIdx->numOfBlocks); + ASSERT(blkIdx >= 0 && blkIdx < (int)pIdx->numOfBlocks); SCompBlock *pSCompBlock = pHelper->pCompInfo->blocks + blkIdx; ASSERT(pSCompBlock->numOfSubBlocks >= 1 && pSCompBlock->numOfSubBlocks < TSDB_MAX_SUBBLOCKS); @@ -943,7 +911,7 @@ static int tsdbAddSubBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int blkId memmove((void *)((char *)(pHelper->pCompInfo) + pSCompBlock->offset + pSCompBlock->len + sizeof(SCompBlock)), (void *)((char *)(pHelper->pCompInfo) + pSCompBlock->offset + pSCompBlock->len), tsize); - for (int i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { + for (uint32_t i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { SCompBlock *pTCompBlock = &pHelper->pCompInfo->blocks[i]; if (pTCompBlock->numOfSubBlocks > 1) pTCompBlock->offset += sizeof(SCompBlock); } @@ -960,7 +928,7 @@ static int tsdbAddSubBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int blkId pIdx->len += sizeof(SCompBlock); } else { // Need to create two sub-blocks void *ptr = NULL; - for (int i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { + for (uint32_t i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { SCompBlock *pTCompBlock = pHelper->pCompInfo->blocks + i; if (pTCompBlock->numOfSubBlocks > 1) { ptr = POINTER_SHIFT(pHelper->pCompInfo, pTCompBlock->offset); @@ -973,7 +941,7 @@ static int tsdbAddSubBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int blkId size_t tsize = pIdx->len - ((char *)ptr - (char *)(pHelper->pCompInfo)); if (tsize > 0) { memmove(POINTER_SHIFT(ptr, sizeof(SCompBlock) * 2), ptr, tsize); - for (int i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { + for (uint32_t i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { SCompBlock *pTCompBlock = pHelper->pCompInfo->blocks + i; if (pTCompBlock->numOfSubBlocks > 1) pTCompBlock->offset += (sizeof(SCompBlock) * 2); } @@ -995,7 +963,7 @@ static int tsdbAddSubBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int blkId } pIdx->maxKey = pHelper->pCompInfo->blocks[pIdx->numOfBlocks - 1].keyLast; - pIdx->hasLast = pHelper->pCompInfo->blocks[pIdx->numOfBlocks - 1].last; + pIdx->hasLast = (uint32_t)pHelper->pCompInfo->blocks[pIdx->numOfBlocks - 1].last; tsdbDebug("vgId:%d tid:%d a subblock is added at index %d", REPO_ID(pHelper->pRepo), pHelper->tableInfo.tid, blkIdx); @@ -1010,7 +978,7 @@ static int tsdbUpdateSuperBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int SCompIdx *pIdx = &(pHelper->curCompIdx); - ASSERT(blkIdx >= 0 && blkIdx < pIdx->numOfBlocks); + ASSERT(blkIdx >= 0 && blkIdx < (int)pIdx->numOfBlocks); SCompBlock *pSCompBlock = pHelper->pCompInfo->blocks + blkIdx; @@ -1024,7 +992,7 @@ static int tsdbUpdateSuperBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int POINTER_SHIFT(pHelper->pCompInfo, pSCompBlock->offset + pSCompBlock->len), tsize); } - for (int i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { + for (uint32_t i = blkIdx + 1; i < pIdx->numOfBlocks; i++) { SCompBlock *pTCompBlock = &pHelper->pCompInfo->blocks[i]; if (pTCompBlock->numOfSubBlocks > 1) pTCompBlock->offset -= (sizeof(SCompBlock) * pSCompBlock->numOfSubBlocks); } @@ -1035,7 +1003,7 @@ static int tsdbUpdateSuperBlock(SRWHelper *pHelper, SCompBlock *pCompBlock, int *pSCompBlock = *pCompBlock; pIdx->maxKey = blockAtIdx(pHelper, pIdx->numOfBlocks - 1)->keyLast; - pIdx->hasLast = blockAtIdx(pHelper, pIdx->numOfBlocks - 1)->last; + pIdx->hasLast = (uint32_t)blockAtIdx(pHelper, pIdx->numOfBlocks - 1)->last; tsdbDebug("vgId:%d tid:%d a super block is updated at index %d", REPO_ID(pHelper->pRepo), pHelper->tableInfo.tid, blkIdx); @@ -1052,10 +1020,6 @@ static void tsdbResetHelperFileImpl(SRWHelper *pHelper) { helperLastF(pHelper)->fd = -1; helperNewHeadF(pHelper)->fd = -1; helperNewLastF(pHelper)->fd = -1; -#ifdef TSDB_IDX - helperIdxF(pHelper)->fd = -1; - helperNewIdxF(pHelper)->fd = -1; -#endif } static int tsdbInitHelperFile(SRWHelper *pHelper) { @@ -1064,7 +1028,7 @@ static int tsdbInitHelperFile(SRWHelper *pHelper) { } static void tsdbDestroyHelperFile(SRWHelper *pHelper) { - tsdbCloseHelperFile(pHelper, false); + tsdbCloseHelperFile(pHelper, false, NULL); tsdbResetHelperFileImpl(pHelper); taosTZfree(pHelper->idxH.pIdxArray); taosTZfree(pHelper->pWIdx); @@ -1197,7 +1161,7 @@ static int tsdbLoadColData(SRWHelper *pHelper, SFile *pFile, SCompBlock *pCompBl } int64_t offset = pCompBlock->offset + TSDB_GET_COMPCOL_LEN(pCompBlock->numOfCols) + pCompCol->offset; - if (lseek(pFile->fd, offset, SEEK_SET) < 0) { + if (lseek(pFile->fd, (off_t)offset, SEEK_SET) < 0) { tsdbError("vgId:%d failed to lseek file %s since %s", REPO_ID(pHelper->pRepo), pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); return -1; @@ -1212,7 +1176,7 @@ static int tsdbLoadColData(SRWHelper *pHelper, SFile *pFile, SCompBlock *pCompBl if (tsdbCheckAndDecodeColumnData(pDataCol, pHelper->pBuffer, pCompCol->len, pCompBlock->algorithm, pCompBlock->numOfRows, pHelper->pRepo->config.maxRowsPerFileBlock, - pHelper->compBuffer, taosTSizeof(pHelper->compBuffer)) < 0) { + pHelper->compBuffer, (int32_t)taosTSizeof(pHelper->compBuffer)) < 0) { tsdbError("vgId:%d file %s is broken at column %d offset %" PRId64, REPO_ID(pHelper->pRepo), pFile->fname, pCompCol->colId, offset); return -1; @@ -1312,7 +1276,7 @@ static int tsdbLoadBlockDataImpl(SRWHelper *pHelper, SCompBlock *pCompBlock, SDa SCompData *pCompData = (SCompData *)pHelper->pBuffer; int fd = pFile->fd; - if (lseek(fd, pCompBlock->offset, SEEK_SET) < 0) { + if (lseek(fd, (off_t)pCompBlock->offset, SEEK_SET) < 0) { tsdbError("vgId:%d tid:%d failed to lseek file %s since %s", REPO_ID(pHelper->pRepo), pHelper->tableInfo.tid, pFile->fname, strerror(errno)); terrno = TAOS_SYSTEM_ERROR(errno); @@ -1375,7 +1339,7 @@ static int tsdbLoadBlockDataImpl(SRWHelper *pHelper, SCompBlock *pCompBlock, SDa } if (tsdbCheckAndDecodeColumnData(pDataCol, (char *)pCompData + tsize + toffset, tlen, pCompBlock->algorithm, pCompBlock->numOfRows, pDataCols->maxPoints, pHelper->compBuffer, - taosTSizeof(pHelper->compBuffer)) < 0) { + (int32_t)taosTSizeof(pHelper->compBuffer)) < 0) { tsdbError("vgId:%d file %s is broken at column %d block offset %" PRId64 " column offset %d", REPO_ID(pHelper->pRepo), pFile->fname, tcolId, (int64_t)pCompBlock->offset, toffset); goto _err; @@ -1499,7 +1463,7 @@ static int tsdbProcessMergeCommit(SRWHelper *pHelper, SCommitIter *pCommitIter, SCompBlock *pCompBlock = taosbsearch((void *)(&keyFirst), (void *)blockAtIdx(pHelper, *blkIdx), pIdx->numOfBlocks - *blkIdx, sizeof(SCompBlock), compareKeyBlock, TD_GE); ASSERT(pCompBlock != NULL); - int tblkIdx = TSDB_GET_COMPBLOCK_IDX(pHelper, pCompBlock); + int tblkIdx = (int32_t)(TSDB_GET_COMPBLOCK_IDX(pHelper, pCompBlock)); if (pCompBlock->last) { ASSERT(pCompBlock->numOfRows < pCfg->minRowsPerFileBlock && tblkIdx == pIdx->numOfBlocks - 1); diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 17cee360f37f2b62917e267b20acb5c0cce0fe7b..0aae3b2ad95d626b1a65e8b1267520ea581552d7 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -184,6 +184,7 @@ TsdbQueryHandleT* tsdbQueryTables(TSDB_REPO_T* tsdb, STsdbQueryCond* pCond, STab pQueryHandle->qinfo = qinfo; pQueryHandle->outputCapacity = ((STsdbRepo*)tsdb)->config.maxRowsPerFileBlock; pQueryHandle->allocSize = 0; + pQueryHandle->locateStart = false; if (tsdbInitReadHelper(&pQueryHandle->rhelper, (STsdbRepo*) tsdb) != 0) { goto out_of_memory; @@ -191,6 +192,15 @@ TsdbQueryHandleT* tsdbQueryTables(TSDB_REPO_T* tsdb, STsdbQueryCond* pCond, STab tsdbTakeMemSnapshot(pQueryHandle->pTsdb, &pQueryHandle->mem, &pQueryHandle->imem); + size_t sizeOfGroup = taosArrayGetSize(groupList->pGroupList); + assert(sizeOfGroup >= 1 && pCond != NULL && pCond->numOfCols > 0); + + if (ASCENDING_TRAVERSE(pCond->order)) { + assert(pQueryHandle->window.skey <= pQueryHandle->window.ekey); + } else { + assert(pQueryHandle->window.skey >= pQueryHandle->window.ekey); + } + // allocate buffer in order to load data blocks from file int32_t numOfCols = pCond->numOfCols; @@ -241,6 +251,7 @@ TsdbQueryHandleT* tsdbQueryTables(TSDB_REPO_T* tsdb, STsdbQueryCond* pCond, STab .tableId = ((STable*)(pKeyInfo->pTable))->tableId, .pTableObj = pKeyInfo->pTable, }; + info.tableId = pTable->tableId; assert(info.pTableObj != NULL && (info.pTableObj->type == TSDB_NORMAL_TABLE || info.pTableObj->type == TSDB_CHILD_TABLE || info.pTableObj->type == TSDB_STREAM_TABLE)); @@ -252,6 +263,8 @@ TsdbQueryHandleT* tsdbQueryTables(TSDB_REPO_T* tsdb, STsdbQueryCond* pCond, STab } taosArrayPush(pQueryHandle->pTableCheckInfo, &info); + tsdbDebug("%p check table uid:%"PRId64", tid:%d from lastKey:%"PRId64" %p", pQueryHandle, info.tableId.uid, + info.tableId.tid, info.lastKey, qinfo); } } @@ -326,7 +339,7 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh STableData* pMem = NULL; STableData* pIMem = NULL; - + if (pHandle->mem && pCheckInfo->tableId.tid < pHandle->mem->maxTables) { pMem = pHandle->mem->tData[pCheckInfo->tableId.tid]; if (pMem != NULL && pMem->uid == pCheckInfo->tableId.uid) { // check uid @@ -358,7 +371,7 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter); assert(node != NULL); - SDataRow row = SL_GET_NODE_DATA(node); + SDataRow row = *(SDataRow *)SL_GET_NODE_DATA(node); TSKEY key = dataRowKey(row); // first timestamp in buffer tsdbDebug("%p uid:%" PRId64 ", tid:%d check data in mem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64 "-%" PRId64 ", lastKey:%" PRId64 ", %p", @@ -380,7 +393,7 @@ static bool initTableMemIterator(STsdbQueryHandle* pHandle, STableCheckInfo* pCh SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter); assert(node != NULL); - SDataRow row = SL_GET_NODE_DATA(node); + SDataRow row = *(SDataRow *)SL_GET_NODE_DATA(node); TSKEY key = dataRowKey(row); // first timestamp in buffer tsdbDebug("%p uid:%" PRId64 ", tid:%d check data in mem from skey:%" PRId64 ", order:%d, ts range in buf:%" PRId64 "-%" PRId64 ", lastKey:%" PRId64 ", %p", @@ -410,14 +423,14 @@ SDataRow getSDataRowInTableMem(STableCheckInfo* pCheckInfo, int32_t order) { if (pCheckInfo->iter) { SSkipListNode* node = tSkipListIterGet(pCheckInfo->iter); if (node != NULL) { - rmem = SL_GET_NODE_DATA(node); + rmem = *(SDataRow *)SL_GET_NODE_DATA(node); } } if (pCheckInfo->iiter) { SSkipListNode* node = tSkipListIterGet(pCheckInfo->iiter); if (node != NULL) { - rimem = SL_GET_NODE_DATA(node); + rimem = *(SDataRow *)SL_GET_NODE_DATA(node); } } @@ -555,7 +568,7 @@ static int32_t getFileIdFromKey(TSKEY key, int32_t daysPerFile, int32_t precisio fid = INT32_MAX; } - return fid; + return (int32_t)fid; } static int32_t binarySearchForBlock(SCompBlock* pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) { @@ -603,7 +616,7 @@ static int32_t getFileCompInfo(STsdbQueryHandle* pQueryHandle, int32_t* numOfBlo continue; // no data blocks in the file belongs to pCheckInfo->pTable } - if (pCheckInfo->compSize < compIndex->len) { + if (pCheckInfo->compSize < (int32_t)compIndex->len) { assert(compIndex->len > 0); char* t = realloc(pCheckInfo->pCompInfo, compIndex->len); @@ -636,7 +649,7 @@ static int32_t getFileCompInfo(STsdbQueryHandle* pQueryHandle, int32_t* numOfBlo } // todo speedup the procedure of located end block - while (end < compIndex->numOfBlocks && (pCompInfo->blocks[end].keyFirst <= e)) { + while (end < (int32_t)compIndex->numOfBlocks && (pCompInfo->blocks[end].keyFirst <= e)) { end += 1; } @@ -676,7 +689,7 @@ static bool doLoadFileDataBlock(STsdbQueryHandle* pQueryHandle, SCompBlock* pBlo tdInitDataCols(pQueryHandle->rhelper.pDataCols[1], pSchema); int16_t* colIds = pQueryHandle->defaultLoadColumn->pData; - int32_t ret = tsdbLoadBlockDataCols(&(pQueryHandle->rhelper), pBlock, pCheckInfo->pCompInfo, colIds, QH_GET_NUM_OF_COLS(pQueryHandle)); + int32_t ret = tsdbLoadBlockDataCols(&(pQueryHandle->rhelper), pBlock, pCheckInfo->pCompInfo, colIds, (int)(QH_GET_NUM_OF_COLS(pQueryHandle))); if (ret == TSDB_CODE_SUCCESS) { SDataBlockLoadInfo* pBlockLoadInfo = &pQueryHandle->dataBlockLoadInfo; @@ -878,7 +891,7 @@ static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t cap return numOfRows; } - int32_t requiredNumOfCols = taosArrayGetSize(pQueryHandle->pColumns); + int32_t requiredNumOfCols = (int32_t)taosArrayGetSize(pQueryHandle->pColumns); //data in buffer has greater timestamp, copy data in file block int32_t i = 0, j = 0; @@ -894,15 +907,15 @@ static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t cap int32_t bytes = pColInfo->info.bytes; if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = pColInfo->pData + numOfRows * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; } else { - pData = pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes; } if (pColInfo->info.colId == src->colId) { if (pColInfo->info.type != TSDB_DATA_TYPE_BINARY && pColInfo->info.type != TSDB_DATA_TYPE_NCHAR) { - memmove(pData, src->pData + bytes * start, bytes * num); + memmove(pData, (char*)src->pData + bytes * start, bytes * num); } else { // handle the var-string char* dst = pData; @@ -934,9 +947,9 @@ static int32_t copyDataFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t cap while (i < requiredNumOfCols) { // the remain columns are all null data SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = pColInfo->pData + numOfRows * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; } else { - pData = pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes; } if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { @@ -976,13 +989,13 @@ static void copyOneRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, } if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = pColInfo->pData + numOfRows * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; } else { - pData = pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; } if (pSchema->columns[j].colId == pColInfo->info.colId) { - void* value = tdGetRowDataOfCol(row, pColInfo->info.type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); + void* value = tdGetRowDataOfCol(row, (int8_t)pColInfo->info.type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { memcpy(pData, value, varDataTLen(value)); } else { @@ -1004,9 +1017,9 @@ static void copyOneRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, while (i < numOfCols) { // the remain columns are all null data SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = pColInfo->pData + numOfRows * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; } else { - pData = pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; } if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { @@ -1029,7 +1042,7 @@ static void moveDataToFront(STsdbQueryHandle* pQueryHandle, int32_t numOfRows, i int32_t emptySize = pQueryHandle->outputCapacity - numOfRows; for(int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); - memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); + memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); } } } @@ -1103,11 +1116,19 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* TSKEY* tsArray = pCols->cols[0].pData; + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + TSKEY s = tsArray[cur->pos]; + assert(s >= pQueryHandle->window.skey && s <= pQueryHandle->window.ekey); + } else { + TSKEY s = tsArray[cur->pos]; + assert(s <= pQueryHandle->window.skey && s >= pQueryHandle->window.ekey); + } + // for search the endPos, so the order needs to reverse int32_t order = (pQueryHandle->order == TSDB_ORDER_ASC)? TSDB_ORDER_DESC:TSDB_ORDER_ASC; int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; - int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); + int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); STable* pTable = pCheckInfo->pTableObj; int32_t endPos = cur->pos; @@ -1216,8 +1237,8 @@ static void doMergeTwoLevelData(STsdbQueryHandle* pQueryHandle, STableCheckInfo* * copy them all to result buffer, since it may be overlapped with file data block. */ if (node == NULL || - ((dataRowKey(SL_GET_NODE_DATA(node)) > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || - ((dataRowKey(SL_GET_NODE_DATA(node)) < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))) { + ((dataRowKey(*(SDataRow *)SL_GET_NODE_DATA(node)) > pQueryHandle->window.ekey) && ASCENDING_TRAVERSE(pQueryHandle->order)) || + ((dataRowKey(*(SDataRow *)SL_GET_NODE_DATA(node)) < pQueryHandle->window.ekey) && !ASCENDING_TRAVERSE(pQueryHandle->order))) { // no data in cache or data in cache is greater than the ekey of time window, load data from file block if (cur->win.skey == TSKEY_INITIAL_VAL) { cur->win.skey = tsArray[pos]; @@ -1358,7 +1379,7 @@ static int32_t createDataBlocksInfo(STsdbQueryHandle* pQueryHandle, int32_t numO size_t size = sizeof(STableBlockInfo) * numOfBlocks; if (pQueryHandle->allocSize < size) { - pQueryHandle->allocSize = size; + pQueryHandle->allocSize = (int32_t)size; char* tmp = realloc(pQueryHandle->pDataBlockInfo, pQueryHandle->allocSize); if (tmp == NULL) { return TSDB_CODE_TDB_OUT_OF_MEMORY; @@ -1370,7 +1391,7 @@ static int32_t createDataBlocksInfo(STsdbQueryHandle* pQueryHandle, int32_t numO memset(pQueryHandle->pDataBlockInfo, 0, size); *numOfAllocBlocks = numOfBlocks; - int32_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + int32_t numOfTables = (int32_t)taosArrayGetSize(pQueryHandle->pTableCheckInfo); SBlockOrderSupporter sup = {0}; sup.numOfTables = numOfTables; @@ -1477,7 +1498,7 @@ static int32_t getDataBlocksInFilesImpl(STsdbQueryHandle* pQueryHandle, bool* ex int32_t code = TSDB_CODE_SUCCESS; int32_t numOfBlocks = 0; - int32_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + int32_t numOfTables = (int32_t)taosArrayGetSize(pQueryHandle->pTableCheckInfo); STsdbCfg* pCfg = &pQueryHandle->pTsdb->config; STimeWindow win = TSWINDOW_INITIALIZER; @@ -1582,7 +1603,7 @@ static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists STableCheckInfo* pCheckInfo = pBlockInfo->pTableCheckInfo; // current block is done, try next - if (!cur->mixBlock || cur->blockCompleted) { + if ((!cur->mixBlock) || cur->blockCompleted) { if ((cur->slot == pQueryHandle->numOfBlocks - 1 && ASCENDING_TRAVERSE(pQueryHandle->order)) || (cur->slot == 0 && !ASCENDING_TRAVERSE(pQueryHandle->order))) { // all data blocks in current file has been checked already, try next file if exists @@ -1601,6 +1622,7 @@ static int32_t getDataBlocksInFiles(STsdbQueryHandle* pQueryHandle, bool* exists return TSDB_CODE_SUCCESS; } } else { + tsdbDebug("%p continue in current data block, index:%d, %p", pQueryHandle, cur->slot, pQueryHandle->qinfo); handleDataMergeIfNeeded(pQueryHandle, pBlockInfo->compBlock, pCheckInfo); *exists = pQueryHandle->realNumOfRows > 0; @@ -1647,10 +1669,10 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { if (pQueryHandle->cur.win.ekey == pQueryHandle->window.skey) { // data already retrieve, discard other data rows and return - int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); + int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData* pCol = taosArrayGet(pQueryHandle->pColumns, i); - memcpy(pCol->pData, pCol->pData + pCol->info.bytes * (pQueryHandle->cur.rows-1), pCol->info.bytes); + memcpy((char*)pCol->pData, (char*)pCol->pData + pCol->info.bytes * (pQueryHandle->cur.rows - 1), pCol->info.bytes); } pQueryHandle->cur.win = (STimeWindow){pQueryHandle->window.skey, pQueryHandle->window.skey}; @@ -1678,7 +1700,7 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { tsdbTakeMemSnapshot(pSecQueryHandle->pTsdb, &pSecQueryHandle->mem, &pSecQueryHandle->imem); // allocate buffer in order to load data blocks from file - int32_t numOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); + int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); pSecQueryHandle->statis = calloc(numOfCols, sizeof(SDataStatis)); pSecQueryHandle->pColumns = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); @@ -1701,9 +1723,10 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { STableCheckInfo* pCheckInfo = (STableCheckInfo*) taosArrayGet(pQueryHandle->pTableCheckInfo, j); STableCheckInfo info = { .lastKey = pSecQueryHandle->window.skey, - .tableId = pCheckInfo->tableId, + //.tableId = pCheckInfo->tableId, .pTableObj = pCheckInfo->pTableObj, }; + info.tableId = pCheckInfo->tableId; taosArrayPush(pSecQueryHandle->pTableCheckInfo, &info); } @@ -1720,12 +1743,12 @@ bool tsdbNextDataBlock(TsdbQueryHandleT* pHandle) { for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData* pCol = taosArrayGet(pQueryHandle->pColumns, i); - memcpy(pCol->pData, pCol->pData + pCol->info.bytes * (pQueryHandle->cur.rows-1), pCol->info.bytes); + memcpy((char*)pCol->pData, (char*)pCol->pData + pCol->info.bytes * (pQueryHandle->cur.rows - 1), pCol->info.bytes); SColumnInfoData* pCol1 = taosArrayGet(pSecQueryHandle->pColumns, i); assert(pCol->info.colId == pCol1->info.colId); - memcpy(pCol->pData + pCol->info.bytes, pCol1->pData, pCol1->info.bytes); + memcpy((char*)pCol->pData + pCol->info.bytes, pCol1->pData, pCol1->info.bytes); } SColumnInfoData* pTSCol = taosArrayGet(pQueryHandle->pColumns, 0); @@ -1871,7 +1894,7 @@ static void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle) { static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int maxRowsToRead, STimeWindow* win, STsdbQueryHandle* pQueryHandle) { int numOfRows = 0; - int32_t numOfCols = taosArrayGetSize(pQueryHandle->pColumns); + int32_t numOfCols = (int32_t)taosArrayGetSize(pQueryHandle->pColumns); win->skey = TSKEY_INITIAL_VAL; int64_t st = taosGetTimestampUs(); @@ -1913,7 +1936,7 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int for(int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); - memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); + memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); } } @@ -1942,7 +1965,7 @@ void tsdbRetrieveDataBlockInfo(TsdbQueryHandleT* pQueryHandle, SDataBlockInfo* p pDataBlockInfo->tid = pTable->tableId.tid; pDataBlockInfo->rows = cur->rows; pDataBlockInfo->window = cur->win; - pDataBlockInfo->numOfCols = QH_GET_NUM_OF_COLS(pHandle); + pDataBlockInfo->numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pHandle)); } /* @@ -1977,7 +2000,7 @@ int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT* pQueryHandle, SDataSta pHandle->statis[i].colId = colIds[i]; } - tsdbGetDataStatis(&pHandle->rhelper, pHandle->statis, numOfCols); + tsdbGetDataStatis(&pHandle->rhelper, pHandle->statis, (int)numOfCols); // always load the first primary timestamp column data SDataStatis* pPrimaryColStatis = &pHandle->statis[0]; @@ -2042,11 +2065,11 @@ SArray* tsdbRetrieveDataBlock(TsdbQueryHandleT* pQueryHandle, SArray* pIdList) { // if the buffer is not full in case of descending order query, move the data in the front of the buffer if (!ASCENDING_TRAVERSE(pHandle->order) && numOfRows < pHandle->outputCapacity) { int32_t emptySize = pHandle->outputCapacity - numOfRows; - int32_t reqNumOfCols = taosArrayGetSize(pHandle->pColumns); + int32_t reqNumOfCols = (int32_t)taosArrayGetSize(pHandle->pColumns); for(int32_t i = 0; i < reqNumOfCols; ++i) { SColumnInfoData* pColInfo = taosArrayGet(pHandle->pColumns, i); - memmove(pColInfo->pData, pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); + memmove((char*)pColInfo->pData, (char*)pColInfo->pData + emptySize * pColInfo->info.bytes, numOfRows * pColInfo->info.bytes); } } @@ -2374,7 +2397,7 @@ int32_t tsdbQuerySTableByTagCond(TSDB_REPO_T* tsdb, uint64_t uid, TSKEY skey, co THROW( TSDB_CODE_TDB_OUT_OF_MEMORY ); } expr->nodeType = TSQL_NODE_EXPR; - expr->_node.optr = tagNameRelType; + expr->_node.optr = (uint8_t)tagNameRelType; expr->_node.pLeft = tagExpr; expr->_node.pRight = tbnameExpr; } @@ -2489,6 +2512,7 @@ void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle) { destroyTableMemIterator(pTableCheckInfo); tdFreeDataCols(pTableCheckInfo->pDataCols); + pTableCheckInfo->pDataCols = NULL; taosTFree(pTableCheckInfo->pCompInfo); } taosArrayDestroy(pQueryHandle->pTableCheckInfo); diff --git a/src/tsdb/tests/tsdbTests.cpp b/src/tsdb/tests/tsdbTests.cpp index e504109cec882ca8c5698a2d9e429790557a5abb..605586515b7b1626751c01a550925c6e9ac4e183 100644 --- a/src/tsdb/tests/tsdbTests.cpp +++ b/src/tsdb/tests/tsdbTests.cpp @@ -35,7 +35,7 @@ static int insertData(SInsertInfo *pInfo) { for (int k = 0; k < pInfo->totalRows/pInfo->rowsPerSubmit; k++) { memset((void *)pMsg, 0, sizeof(SSubmitMsg)); - SSubmitBlk *pBlock = pMsg->blocks; + SSubmitBlk *pBlock = (SSubmitBlk *)pMsg->blocks; pBlock->uid = pInfo->uid; pBlock->tid = pInfo->tid; pBlock->sversion = pInfo->sversion; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index d91ef075ef980215a03389c3e9d4c826fd41bf35..b2778b69d93be9c86bb948223967d755fed9bbbe 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,16 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(tutil ${SRC}) +AUX_SOURCE_DIRECTORY(src SRC) +ADD_LIBRARY(tutil ${SRC}) + +IF (TD_LINUX) TARGET_LINK_LIBRARIES(tutil pthread osdetail m rt lz4) ADD_SUBDIRECTORY(tests) @@ -29,18 +23,8 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) MESSAGE(STATUS "Failed to find iconv, use default encoding method") ENDIF () -ELSEIF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(tutil ${SRC}) - TARGET_LINK_LIBRARIES(tutil iconv regex pthread osdetail winmm IPHLPAPI ws2_32 lz4) -ELSEIF(TD_DARWIN_64) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(tutil ${SRC}) +ELSEIF (TD_WINDOWS) + TARGET_LINK_LIBRARIES(tutil iconv regex pthread osdetail winmm IPHLPAPI ws2_32 lz4 wepoll) +ELSEIF(TD_DARWIN) TARGET_LINK_LIBRARIES(tutil iconv pthread osdetail lz4) ENDIF() - -# TARGET_LINK_LIBRARIES(tutil mstorage) diff --git a/src/util/inc/tscompression.h b/src/util/inc/tscompression.h index 9398ff82439445692b2e1c90041fd0595bbc27c7..bd1ccf3ca5fd52cb8e6f596ff955579389cd249f 100644 --- a/src/util/inc/tscompression.h +++ b/src/util/inc/tscompression.h @@ -56,6 +56,7 @@ static FORCE_INLINE int tsCompressTinyint(const char *const input, int inputSize return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -68,6 +69,7 @@ static FORCE_INLINE int tsDecompressTinyint(const char *const input, int compres return tsDecompressINTImp(buffer, nelements, output, TSDB_DATA_TYPE_TINYINT); } else { assert(0); + return -1; } } @@ -80,6 +82,7 @@ static FORCE_INLINE int tsCompressSmallint(const char *const input, int inputSiz return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -92,6 +95,7 @@ static FORCE_INLINE int tsDecompressSmallint(const char *const input, int compre return tsDecompressINTImp(buffer, nelements, output, TSDB_DATA_TYPE_SMALLINT); } else { assert(0); + return -1; } } @@ -104,6 +108,7 @@ static FORCE_INLINE int tsCompressInt(const char *const input, int inputSize, co return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -116,6 +121,7 @@ static FORCE_INLINE int tsDecompressInt(const char *const input, int compressedS return tsDecompressINTImp(buffer, nelements, output, TSDB_DATA_TYPE_INT); } else { assert(0); + return -1; } } @@ -128,6 +134,7 @@ static FORCE_INLINE int tsCompressBigint(const char *const input, int inputSize, return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -140,6 +147,7 @@ static FORCE_INLINE int tsDecompressBigint(const char *const input, int compress return tsDecompressINTImp(buffer, nelements, output, TSDB_DATA_TYPE_BIGINT); } else { assert(0); + return -1; } } @@ -152,6 +160,7 @@ static FORCE_INLINE int tsCompressBool(const char *const input, int inputSize, c return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -164,6 +173,7 @@ static FORCE_INLINE int tsDecompressBool(const char *const input, int compressed return tsDecompressBoolImp(buffer, nelements, output); } else { assert(0); + return -1; } } @@ -186,6 +196,7 @@ static FORCE_INLINE int tsCompressFloat(const char *const input, int inputSize, return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -198,6 +209,7 @@ static FORCE_INLINE int tsDecompressFloat(const char *const input, int compresse return tsDecompressFloatImp(buffer, nelements, output); } else { assert(0); + return -1; } } @@ -210,6 +222,7 @@ static FORCE_INLINE int tsCompressDouble(const char *const input, int inputSize, return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -222,6 +235,7 @@ static FORCE_INLINE int tsDecompressDouble(const char *const input, int compress return tsDecompressDoubleImp(buffer, nelements, output); } else { assert(0); + return -1; } } @@ -234,6 +248,7 @@ static FORCE_INLINE int tsCompressTimestamp(const char *const input, int inputSi return tsCompressStringImp(buffer, len, output, outputSize); } else { assert(0); + return -1; } } @@ -246,6 +261,7 @@ static FORCE_INLINE int tsDecompressTimestamp(const char *const input, int compr return tsDecompressTimestampImp(buffer, nelements, output); } else { assert(0); + return -1; } } diff --git a/src/util/inc/tsocket.h b/src/util/inc/tsocket.h index 97abc16333ae08cec2387045d8ae458de43b3a06..f14e8dbb356e131bbd580f8c5310bea944e71033 100644 --- a/src/util/inc/tsocket.h +++ b/src/util/inc/tsocket.h @@ -20,17 +20,17 @@ extern "C" { #endif -int taosReadn(int sock, char *buffer, int len); -int taosWriteMsg(int fd, void *ptr, int nbytes); -int taosReadMsg(int fd, void *ptr, int nbytes); -int taosNonblockwrite(int fd, char *ptr, int nbytes); -int taosCopyFds(int sfd, int dfd, int64_t len); -int taosSetNonblocking(int sock, int on); +int taosReadn(SOCKET sock, char *buffer, int len); +int taosWriteMsg(SOCKET fd, void *ptr, int nbytes); +int taosReadMsg(SOCKET fd, void *ptr, int nbytes); +int taosNonblockwrite(SOCKET fd, char *ptr, int nbytes); +int taosCopyFds(SOCKET sfd, SOCKET dfd, int64_t len); +int taosSetNonblocking(SOCKET sock, int on); -int taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); -int taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp); -int taosOpenTcpServerSocket(uint32_t ip, uint16_t port); -int taosKeepTcpAlive(int sockFd); +SOCKET taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); +SOCKET taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp); +SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port); +int taosKeepTcpAlive(SOCKET sockFd); int taosGetFqdn(char *); uint32_t taosGetIpFromFqdn(const char *); diff --git a/src/util/inc/tutil.h b/src/util/inc/tutil.h index e312513ff3f1f2294360ab2fce25310bcd9bf6d7..fe5c038c5169d88814c7807d550ebadaba8ebacd 100644 --- a/src/util/inc/tutil.h +++ b/src/util/inc/tutil.h @@ -44,10 +44,10 @@ int taosCheckVersion(char *input_client_version, char *input_server_version, in char * taosIpStr(uint32_t ipInt); uint32_t ip2uint(const char *const ip_addr); -static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, unsigned int inLen, char *target) { +static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, size_t inLen, char *target) { MD5_CTX context; MD5Init(&context); - MD5Update(&context, inBuf, inLen); + MD5Update(&context, inBuf, (unsigned int)inLen); MD5Final(&context); memcpy(target, context.digest, TSDB_KEY_LEN); } diff --git a/src/util/src/tcompression.c b/src/util/src/tcompression.c index c20ba59ac9b351445cf9f97134ae08fd1e45f0f7..8c5828d32d2323cbdc7a05687c3e64e4e61a29af 100644 --- a/src/util/src/tcompression.c +++ b/src/util/src/tcompression.c @@ -591,6 +591,7 @@ int tsDecompressTimestampImp(const char *const input, const int nelements, char } else { assert(0); + return -1; } } /* --------------------------------------------Double Compression diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index 6f4d2b8afd81f3bb85405f2d6a1f0f71144878f3..9abda0e1961ebea1112e7e6226cfa552155273a2 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -90,7 +90,7 @@ uint32_t ip2uint(const char *const ip_addr) { return *((unsigned int *)ip); } -int taosWriteMsg(int fd, void *buf, int nbytes) { +int taosWriteMsg(SOCKET fd, void *buf, int nbytes) { int nleft, nwritten; char *ptr = (char *)buf; @@ -112,7 +112,7 @@ int taosWriteMsg(int fd, void *buf, int nbytes) { return (nbytes - nleft); } -int taosReadMsg(int fd, void *buf, int nbytes) { +int taosReadMsg(SOCKET fd, void *buf, int nbytes) { int nleft, nread; char *ptr = (char *)buf; @@ -139,7 +139,7 @@ int taosReadMsg(int fd, void *buf, int nbytes) { return (nbytes - nleft); } -int taosNonblockwrite(int fd, char *ptr, int nbytes) { +int taosNonblockwrite(SOCKET fd, char *ptr, int nbytes) { taosSetNonblocking(fd, 1); int nleft, nwritten, nready; @@ -152,7 +152,7 @@ int taosNonblockwrite(int fd, char *ptr, int nbytes) { tv.tv_usec = 0; FD_ZERO(&fset); FD_SET(fd, &fset); - if ((nready = select(fd + 1, NULL, &fset, NULL, &tv)) == 0) { + if ((nready = select((int)(fd + 1), NULL, &fset, NULL, &tv)) == 0) { errno = ETIMEDOUT; uError("fd %d timeout, no enough space to write", fd); break; @@ -181,7 +181,7 @@ int taosNonblockwrite(int fd, char *ptr, int nbytes) { return (nbytes - nleft); } -int taosReadn(int fd, char *ptr, int nbytes) { +int taosReadn(SOCKET fd, char *ptr, int nbytes) { int nread, nready, nleft = nbytes; fd_set fset; @@ -192,7 +192,7 @@ int taosReadn(int fd, char *ptr, int nbytes) { tv.tv_usec = 0; FD_ZERO(&fset); FD_SET(fd, &fset); - if ((nready = select(fd + 1, NULL, &fset, NULL, &tv)) == 0) { + if ((nready = select((int)(fd + 1), NULL, &fset, NULL, &tv)) == 0) { errno = ETIMEDOUT; uError("fd %d timeout\n", fd); break; @@ -219,9 +219,9 @@ int taosReadn(int fd, char *ptr, int nbytes) { return (nbytes - nleft); } -int taosOpenUdpSocket(uint32_t ip, uint16_t port) { +SOCKET taosOpenUdpSocket(uint32_t ip, uint16_t port) { struct sockaddr_in localAddr; - int sockFd; + SOCKET sockFd; int bufSize = 1024000; uDebug("open udp socket:0x%x:%hu", ip, port); @@ -238,32 +238,32 @@ int taosOpenUdpSocket(uint32_t ip, uint16_t port) { if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { uError("failed to set the send buffer size for UDP socket\n"); - close(sockFd); + taosCloseSocket(sockFd); return -1; } if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { uError("failed to set the receive buffer size for UDP socket\n"); - close(sockFd); + taosCloseSocket(sockFd); return -1; } /* bind socket to local address */ if (bind(sockFd, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) { uError("failed to bind udp socket: %d (%s), 0x%x:%hu", errno, strerror(errno), ip, port); - close(sockFd); + taosCloseSocket(sockFd); return -1; } return sockFd; } -int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) { - int sockFd = 0; +SOCKET taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) { + SOCKET sockFd = 0; struct sockaddr_in serverAddr, clientAddr; int ret; - sockFd = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + sockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockFd < 0) { uError("failed to open the socket: %d (%s)", errno, strerror(errno)); @@ -274,11 +274,11 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI int reuse = 1; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { uError("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; }; - if ( clientIp != 0) { + if (clientIp != 0) { memset((char *)&clientAddr, 0, sizeof(clientAddr)); clientAddr.sin_family = AF_INET; clientAddr.sin_addr.s_addr = clientIp; @@ -288,7 +288,7 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI if (bind(sockFd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) { uError("bind tcp client socket failed, client(0x%x:0), dest(0x%x:%d), reason:(%s)", clientIp, destIp, destPort, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } } @@ -302,7 +302,7 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI if (ret != 0) { //uError("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); sockFd = -1; } else { taosKeepTcpAlive(sockFd); @@ -311,39 +311,39 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI return sockFd; } -int taosKeepTcpAlive(int sockFd) { +int taosKeepTcpAlive(SOCKET sockFd) { int alive = 1; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&alive, sizeof(alive)) < 0) { uError("fd:%d setsockopt SO_KEEPALIVE failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int probes = 3; if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPCNT, (void *)&probes, sizeof(probes)) < 0) { uError("fd:%d setsockopt SO_KEEPCNT failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int alivetime = 10; if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPIDLE, (void *)&alivetime, sizeof(alivetime)) < 0) { uError("fd:%d setsockopt SO_KEEPIDLE failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int interval = 3; if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&interval, sizeof(interval)) < 0) { uError("fd:%d setsockopt SO_KEEPINTVL failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int nodelay = 1; if (taosSetSockOpt(sockFd, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(nodelay)) < 0) { uError("fd:%d setsockopt TCP_NODELAY failed %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } @@ -352,16 +352,16 @@ int taosKeepTcpAlive(int sockFd) { linger.l_linger = 3; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) { uError("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } return 0; } -int taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { +SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { struct sockaddr_in serverAdd; - int sockFd; + SOCKET sockFd; int reuse; uDebug("open tcp server socket:0x%x:%hu", ip, port); @@ -380,26 +380,26 @@ int taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { reuse = 1; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { uError("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; }; /* bind socket to server address */ if (bind(sockFd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) { uError("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } if (taosKeepTcpAlive(sockFd) < 0) { uError("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } if (listen(sockFd, 10) < 0) { uError("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } @@ -413,7 +413,7 @@ void tinet_ntoa(char *ipstr, unsigned int ip) { #define COPY_SIZE 32768 // sendfile shall be used -int taosCopyFds(int sfd, int dfd, int64_t len) { +int taosCopyFds(SOCKET sfd, SOCKET dfd, int64_t len) { int64_t leftLen; int readLen, writeLen; char temp[COPY_SIZE]; diff --git a/src/vnode/CMakeLists.txt b/src/vnode/CMakeLists.txt index 9b6b03209e6fc9abce2ee4871de649c9cc688dbe..09cfa632fbfaaa77b32c09b49f051c0714b33564 100644 --- a/src/vnode/CMakeLists.txt +++ b/src/vnode/CMakeLists.txt @@ -1,19 +1,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) +IF (TD_LINUX) ADD_LIBRARY(vnode ${SRC}) TARGET_LINK_LIBRARIES(vnode tsdb tcq) ENDIF () diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index bf55c5d0126ebb7be084a0a3d84979cd16337768..a576d43cda5ece6c8c2655055098a4b6447f9378 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -251,10 +251,17 @@ int32_t vnodeOpen(int32_t vnode, char *rootDir) { appH.cqCreateFunc = cqCreate; appH.cqDropFunc = cqDrop; sprintf(temp, "%s/tsdb", rootDir); + + terrno = 0; pVnode->tsdb = tsdbOpenRepo(temp, &appH); if (pVnode->tsdb == NULL) { vnodeCleanUp(pVnode); return terrno; + } else if (terrno != 0 && pVnode->syncCfg.replica <= 1) { + vError("vgId:%d, failed to open tsdb, replica:%d reason:%s", pVnode->vgId, pVnode->syncCfg.replica, + tstrerror(terrno)); + vnodeCleanUp(pVnode); + return terrno; } sprintf(temp, "%s/wal", rootDir); diff --git a/src/wal/CMakeLists.txt b/src/wal/CMakeLists.txt index a9c20f643a18eefad94dfb245fcd9692048ee3bf..e7d5ae15108175a20aa2deaae797cb6777d1984f 100644 --- a/src/wal/CMakeLists.txt +++ b/src/wal/CMakeLists.txt @@ -1,15 +1,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC) -ADD_LIBRARY(twal ${SRC}) -TARGET_LINK_LIBRARIES(twal tutil common) - -ADD_SUBDIRECTORY(test) +IF (TD_LINUX) + ADD_LIBRARY(twal ${SRC}) + TARGET_LINK_LIBRARIES(twal tutil common) + ADD_SUBDIRECTORY(test) +ENDIF () diff --git a/src/wal/test/CMakeLists.txt b/src/wal/test/CMakeLists.txt index bfa6aa15401ef4aa0550ebc154a41969446f2e99..6fdb03710e65aedfb6220ca2f9fc43ce9dbfad0d 100644 --- a/src/wal/test/CMakeLists.txt +++ b/src/wal/test/CMakeLists.txt @@ -1,11 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) +IF (TD_LINUX_64) INCLUDE_DIRECTORIES(../inc) LIST(APPEND WALTEST_SRC ./waltest.c) diff --git a/tests/comparisonTest/opentsdb/opentsdbtest/src/main/java/com/opentsdb/test/OpentsdbTest.java b/tests/comparisonTest/opentsdb/opentsdbtest/src/main/java/com/opentsdb/test/OpentsdbTest.java index 4d02922766d6a3424a21b127ebe888b4b582dbab..0e82c480ece8063bd78090d4bb67d87ffa698cc3 100644 --- a/tests/comparisonTest/opentsdb/opentsdbtest/src/main/java/com/opentsdb/test/OpentsdbTest.java +++ b/tests/comparisonTest/opentsdb/opentsdbtest/src/main/java/com/opentsdb/test/OpentsdbTest.java @@ -198,7 +198,7 @@ public class OpentsdbTest{ case "q2": //count startTime = System.currentTimeMillis(); - get_url = "http://192.168.1.114:4242/api/query?"; + get_url = "http://127.0.0.1:4242/api/query?"; httpPost = new HttpPost(get_url); qjson = " {\n" + " \"start\": 1563249700,\n" + @@ -351,7 +351,7 @@ public class OpentsdbTest{ break; case "q3": startTime = System.currentTimeMillis(); - get_url = "http://192.168.1.114:4242/api/query?"; + get_url = "http://127.0.0.1:4242/api/query?"; httpPost = new HttpPost(get_url); qjson = " {\n" + " \"start\": 1563249700,\n" + @@ -411,7 +411,7 @@ public class OpentsdbTest{ break; case "q4": startTime = System.currentTimeMillis(); - get_url = "http://192.168.1.114:4242/api/query?"; + get_url = "http://127.0.0.1:4242/api/query?"; httpPost = new HttpPost(get_url); qjson = " {\n" + " \"start\": 1563249700,\n" + diff --git a/tests/comparisonTest/tdengine/CMakeLists.txt b/tests/comparisonTest/tdengine/CMakeLists.txt index ccdeefcdaf5a111b62f3d3bae09bf52da2c6b726..2555bdce913d81eab5bd3728b3a35199bef2b7ca 100644 --- a/tests/comparisonTest/tdengine/CMakeLists.txt +++ b/tests/comparisonTest/tdengine/CMakeLists.txt @@ -1,12 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX_64) add_executable(tdengineTest tdengineTest.c) target_link_libraries(tdengineTest taos_static tutil common pthread) ENDIF() diff --git a/tests/examples/c/CMakeLists.txt b/tests/examples/c/CMakeLists.txt index 81d912fc00d9d543cbee9835ef6c791b1b67542f..59bcb6eaff349e8b20fa13995d1a7297f9185a50 100644 --- a/tests/examples/c/CMakeLists.txt +++ b/tests/examples/c/CMakeLists.txt @@ -1,16 +1,8 @@ PROJECT(TDengine) -IF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) +IF (TD_LINUX) + INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(demo demo.c) + TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ) ENDIF () - -INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc) -AUX_SOURCE_DIRECTORY(. SRC) -ADD_EXECUTABLE(demo demo.c) -TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ) - - - - - - diff --git a/tests/examples/c/subscribe.c b/tests/examples/c/subscribe.c index f9acf2bb10d36740dc5b82704e18256c4421ba5e..db5ad34ee7064978a888fc0e1cedc62aabc5a6a3 100644 --- a/tests/examples/c/subscribe.c +++ b/tests/examples/c/subscribe.c @@ -7,28 +7,31 @@ #include // include TDengine header file #include +int nTotalRows; + void print_result(TAOS_RES* res, int blockFetch) { TAOS_ROW row = NULL; int num_fields = taos_num_fields(res); TAOS_FIELD* fields = taos_fetch_fields(res); int nRows = 0; + char buf[4096]; + if (blockFetch) { nRows = taos_fetch_block(res, &row); for (int i = 0; i < nRows; i++) { - char temp[256]; - taos_print_row(temp, row + i, fields, num_fields); - puts(temp); + taos_print_row(buf, row + i, fields, num_fields); + puts(buf); } } else { while ((row = taos_fetch_row(res))) { - char temp[256]; - taos_print_row(temp, row, fields, num_fields); - puts(temp); + taos_print_row(buf, row, fields, num_fields); + puts(buf); nRows++; } } + nTotalRows += nRows; printf("%d rows consumed.\n", nRows); } @@ -52,47 +55,52 @@ void check_row_count(int line, TAOS_RES* res, int expected) { } +void do_query(TAOS* taos, const char* sql) { + TAOS_RES* res = taos_query(taos, "drop database if exists test;"); + taos_free_result(res); +} + + void run_test(TAOS* taos) { - taos_query(taos, "drop database if exists test;"); + do_query(taos, "drop database if exists test;"); usleep(100000); - //taos_query(taos, "create database test tables 5;"); - taos_query(taos, "create database test;"); + do_query(taos, "create database test;"); usleep(100000); - taos_query(taos, "use test;"); + do_query(taos, "use test;"); usleep(100000); - taos_query(taos, "create table meters(ts timestamp, a int) tags(area int);"); - - taos_query(taos, "create table t0 using meters tags(0);"); - taos_query(taos, "create table t1 using meters tags(1);"); - taos_query(taos, "create table t2 using meters tags(2);"); - taos_query(taos, "create table t3 using meters tags(3);"); - taos_query(taos, "create table t4 using meters tags(4);"); - taos_query(taos, "create table t5 using meters tags(5);"); - taos_query(taos, "create table t6 using meters tags(6);"); - taos_query(taos, "create table t7 using meters tags(7);"); - taos_query(taos, "create table t8 using meters tags(8);"); - taos_query(taos, "create table t9 using meters tags(9);"); - - taos_query(taos, "insert into t0 values('2020-01-01 00:00:00.000', 0);"); - taos_query(taos, "insert into t0 values('2020-01-01 00:01:00.000', 0);"); - taos_query(taos, "insert into t0 values('2020-01-01 00:02:00.000', 0);"); - taos_query(taos, "insert into t1 values('2020-01-01 00:00:00.000', 0);"); - taos_query(taos, "insert into t1 values('2020-01-01 00:01:00.000', 0);"); - taos_query(taos, "insert into t1 values('2020-01-01 00:02:00.000', 0);"); - taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.000', 0);"); - taos_query(taos, "insert into t2 values('2020-01-01 00:00:00.000', 0);"); - taos_query(taos, "insert into t2 values('2020-01-01 00:01:00.000', 0);"); - taos_query(taos, "insert into t2 values('2020-01-01 00:01:01.000', 0);"); - taos_query(taos, "insert into t2 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t3 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t4 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t5 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t6 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t7 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t8 values('2020-01-01 00:01:02.000', 0);"); - taos_query(taos, "insert into t9 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "create table meters(ts timestamp, a int) tags(area int);"); + + do_query(taos, "create table t0 using meters tags(0);"); + do_query(taos, "create table t1 using meters tags(1);"); + do_query(taos, "create table t2 using meters tags(2);"); + do_query(taos, "create table t3 using meters tags(3);"); + do_query(taos, "create table t4 using meters tags(4);"); + do_query(taos, "create table t5 using meters tags(5);"); + do_query(taos, "create table t6 using meters tags(6);"); + do_query(taos, "create table t7 using meters tags(7);"); + do_query(taos, "create table t8 using meters tags(8);"); + do_query(taos, "create table t9 using meters tags(9);"); + + do_query(taos, "insert into t0 values('2020-01-01 00:00:00.000', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:01:00.000', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:02:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:00:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:01:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:02:00.000', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:03:00.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:00:00.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:00.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:01.000', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t3 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t4 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t5 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t6 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t7 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t8 values('2020-01-01 00:01:02.000', 0);"); + do_query(taos, "insert into t9 values('2020-01-01 00:01:02.000', 0);"); // super tables subscription usleep(1000000); @@ -104,23 +112,23 @@ void run_test(TAOS* taos) { res = taos_consume(tsub); check_row_count(__LINE__, res, 0); - taos_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);"); - taos_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:02:00.001', 0);"); + do_query(taos, "insert into t8 values('2020-01-01 00:01:03.000', 0);"); res = taos_consume(tsub); check_row_count(__LINE__, res, 2); - taos_query(taos, "insert into t2 values('2020-01-01 00:01:02.001', 0);"); - taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.001', 0);"); + do_query(taos, "insert into t2 values('2020-01-01 00:01:02.001', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:03:00.001', 0);"); res = taos_consume(tsub); check_row_count(__LINE__, res, 2); - taos_query(taos, "insert into t1 values('2020-01-01 00:03:00.002', 0);"); + do_query(taos, "insert into t1 values('2020-01-01 00:03:00.002', 0);"); res = taos_consume(tsub); check_row_count(__LINE__, res, 1); // keep progress information and restart subscription taos_unsubscribe(tsub, 1); - taos_query(taos, "insert into t0 values('2020-01-01 00:04:00.000', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:04:00.000', 0);"); tsub = taos_subscribe(taos, 1, "test", "select * from meters;", NULL, NULL, 0); res = taos_consume(tsub); check_row_count(__LINE__, res, 24); @@ -147,7 +155,7 @@ void run_test(TAOS* taos) { res = taos_consume(tsub); check_row_count(__LINE__, res, 0); - taos_query(taos, "insert into t0 values('2020-01-01 00:04:00.001', 0);"); + do_query(taos, "insert into t0 values('2020-01-01 00:04:00.001', 0);"); res = taos_consume(tsub); check_row_count(__LINE__, res, 1); @@ -223,7 +231,7 @@ int main(int argc, char *argv[]) { exit(0); } - taos_query(taos, "use test;"); + taos_select_db(taos, "test"); TAOS_SUB* tsub = NULL; if (async) { // create an asynchronized subscription, the callback function will be called every 1s @@ -251,6 +259,7 @@ int main(int argc, char *argv[]) { } } + printf("total rows consumed: %d\n", nTotalRows); taos_unsubscribe(tsub, keep); taos_close(taos); diff --git a/tests/perftest-scripts/influxdbTestWriteLoop.sh b/tests/perftest-scripts/influxdbTestWriteLoop.sh new file mode 100755 index 0000000000000000000000000000000000000000..a9b10ac45d7f56514ae0141ae4cf9f1c668de351 --- /dev/null +++ b/tests/perftest-scripts/influxdbTestWriteLoop.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +DATA_DIR=/mnt/root/testdata +NUM_LOOP=1 +NUM_OF_FILES=100 + +rowsPerRequest=(1 100 500 1000 2000) + +function printTo { + if $verbose ; then + echo $1 + fi +} + +function runTest { + printf "R/R, " + for c in `seq 1 $clients`; do + if [ "$c" == "1" ]; then + printf "$c client, " + else + printf "$c clients, " + fi + done + printf "\n" + + for r in ${rowsPerRequest[@]}; do + printf "$r, " + for c in `seq 1 $clients`; do + totalRPR=0 + OUTPUT_FILE=influxdbTestWrite-RPR$r-clients$c.out + for i in `seq 1 $NUM_LOOP`; do + printTo "loop i:$i, $INF_TEST_DIR/influxdbTest \ + -dataDir $DATA_DIR \ + -numOfFiles $NUM_OF_FILES \ + -writeClients $c \ + -rowsPerRequest $r" + $INF_TEST_DIR/influxdbTest \ + -dataDir $DATA_DIR \ + -numOfFiles $NUM_OF_FILES \ + -writeClients $c \ + -rowsPerRequest $r 2>&1 \ + | tee $OUTPUT_FILE + RPR=`cat $OUTPUT_FILE | grep speed | awk '{print $(NF-1)}'` + totalRPR=`echo "scale=4; $totalRPR + $RPR" | bc` + printTo "rows:$r, clients:$c, i:$i RPR:$RPR" + done + avgRPR=`echo "scale=4; $totalRPR / $NUM_LOOP" | bc` + printf "$avgRPR, " + done + printf "\n" + done +} + +################ Main ################ + +verbose=false +clients=1 + +while : ; do + case $1 in + -v) + verbose=true + shift ;; + + -n) + NUM_LOOP=$2 + shift 2;; + + -c) + clients=$2 + shift 2;; + + *) + break ;; + esac +done + +WORK_DIR=/mnt/root/TDengine + +INF_TEST_DIR=$WORK_DIR/tests/comparisonTest/influxdb + +runTest + +echo "Test done!" diff --git a/tests/perftest-scripts/opentsdbTestQ1Loop.sh b/tests/perftest-scripts/opentsdbTestQ1Loop.sh new file mode 100755 index 0000000000000000000000000000000000000000..2f9ca0dfdb7b851739e97c0d056017255292e288 --- /dev/null +++ b/tests/perftest-scripts/opentsdbTestQ1Loop.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +NUM_LOOP=5 + +function printTo { + if $verbose ; then + echo $1 + fi +} + +TSDBTESTQ1OUT=opentsdbTestQ1.out + +function runTest { + totalG0=0 + totalG10=0 + totalG20=0 + totalG30=0 + totalG40=0 + totalG50=0 + totalG60=0 + totalG70=0 + totalG80=0 + totalG90=0 + for i in `seq 1 $NUM_LOOP`; do + printTo "loop i:$i, java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q1" + java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q1 2>&1 \ + | tee $TSDBTESTQ1OUT + G0=`grep "devgroup = 0" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG0=`echo "scale=4; $totalG0 + $G0" | bc` + G10=`grep "devgroup = 10" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG10=`echo "scale=4; $totalG10 + $G10" | bc` + G20=`grep "devgroup = 20" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG20=`echo "scale=4; $totalG20 + $G20" | bc` + G30=`grep "devgroup = 30" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG30=`echo "scale=4; $totalG30 + $G30" | bc` + G40=`grep "devgroup = 40" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG40=`echo "scale=4; $totalG40 + $G40" | bc` + G50=`grep "devgroup = 50" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG50=`echo "scale=4; $totalG50 + $G50" | bc` + G60=`grep "devgroup = 60" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG60=`echo "scale=4; $totalG60 + $G60" | bc` + G70=`grep "devgroup = 70" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG70=`echo "scale=4; $totalG70 + $G70" | bc` + G80=`grep "devgroup = 80" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG80=`echo "scale=4; $totalG80 + $G80" | bc` + G90=`grep "devgroup = 90" $TSDBTESTQ1OUT| awk '{print $2}'` + totalG90=`echo "scale=4; $totalG90 + $G90" | bc` + done + avgG0=`echo "scale=4; x = $totalG0 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG10=`echo "scale=4; x = $totalG10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG20=`echo "scale=4; x = $totalG20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG30=`echo "scale=4; x = $totalG30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG40=`echo "scale=4; x = $totalG40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG50=`echo "scale=4; x = $totalG50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG60=`echo "scale=4; x = $totalG60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG70=`echo "scale=4; x = $totalG70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG80=`echo "scale=4; x = $totalG80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG90=`echo "scale=4; x = $totalG90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + echo "Latency, G-0, G-10, G-20, G-30, G-40, G-50, G-60, G-70, G-80, G-90" + echo "OpenTSDB, $avgG0, $avgG10, $avgG20, $avgG30, $avgG40, $avgG50, $avgG60, $avgG70, $avgG80, $avgG90" +} + +################ Main ################ + +master=false +develop=true +verbose=false + +clients=1 + +while : ; do + case $1 in + -v) + verbose=true + shift ;; + + -c) + clients=$2 + shift 2;; + + -n) + NUM_LOOP=$2 + shift 2;; + + *) + break ;; + esac +done + +WORK_DIR=/mnt/root/TDengine +TSDBTEST_DIR=$WORK_DIR/tests/comparisonTest/opentsdb + +runTest + +printTo "Test done!" diff --git a/tests/perftest-scripts/opentsdbTestQ2Loop.sh b/tests/perftest-scripts/opentsdbTestQ2Loop.sh new file mode 100755 index 0000000000000000000000000000000000000000..db2d0435a3322e10a27f3cbe4a52ea8d623e6690 --- /dev/null +++ b/tests/perftest-scripts/opentsdbTestQ2Loop.sh @@ -0,0 +1,276 @@ +#!/bin/bash + +NUM_LOOP=5 + +function printTo { + if $verbose ; then + echo $1 + fi +} + +TSDBTESTQ2OUT=opentsdbTestQ2.out + +function runTest { + totalCount10=0 + totalCount20=0 + totalCount30=0 + totalCount40=0 + totalCount50=0 + totalCount60=0 + totalCount70=0 + totalCount80=0 + totalCount90=0 + totalCount100=0 + + totalAvg10=0 + totalAvg20=0 + totalAvg30=0 + totalAvg40=0 + totalAvg50=0 + totalAvg60=0 + totalAvg70=0 + totalAvg80=0 + totalAvg90=0 + totalAvg100=0 + + totalSum10=0 + totalSum20=0 + totalSum30=0 + totalSum40=0 + totalSum50=0 + totalSum60=0 + totalSum70=0 + totalSum80=0 + totalSum90=0 + totalSum100=0 + + totalMax10=0 + totalMax20=0 + totalMax30=0 + totalMax40=0 + totalMax50=0 + totalMax60=0 + totalMax70=0 + totalMax80=0 + totalMax90=0 + totalMax100=0 + + totalMin10=0 + totalMin20=0 + totalMin30=0 + totalMin40=0 + totalMin50=0 + totalMin60=0 + totalMin70=0 + totalMin80=0 + totalMin90=0 + totalMin100=0 + + for i in `seq 1 $NUM_LOOP`; do + printTo "loop i:$i, java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q2" + java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q2 2>&1 \ + | tee $TSDBTESTQ2OUT + + Count10=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 10" | awk '{print $2}'` + totalCount10=`echo "scale=4; $totalCount10 + $Count10" | bc` + Count20=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 20" | awk '{print $2}'` + totalCount20=`echo "scale=4; $totalCount20 + $Count20" | bc` + Count30=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 30" | awk '{print $2}'` + totalCount30=`echo "scale=4; $totalCount30 + $Count30" | bc` + Count40=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 40" | awk '{print $2}'` + totalCount40=`echo "scale=4; $totalCount40 + $Count40" | bc` + Count50=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 50" | awk '{print $2}'` + totalCount50=`echo "scale=4; $totalCount50 + $Count50" | bc` + Count60=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 60" | awk '{print $2}'` + totalCount60=`echo "scale=4; $totalCount60 + $Count60" | bc` + Count70=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 70" | awk '{print $2}'` + totalCount70=`echo "scale=4; $totalCount70 + $Count70" | bc` + Count80=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 80" | awk '{print $2}'` + totalCount80=`echo "scale=4; $totalCount80 + $Count80" | bc` + Count90=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 90" | awk '{print $2}'` + totalCount90=`echo "scale=4; $totalCount90 + $Count90" | bc` + Count100=`cat $TSDBTESTQ2OUT | grep count | grep "devgroup < 100" | awk '{print $2}'` + totalCount100=`echo "scale=4; $totalCount100 + $Count100" | bc` + + Avg10=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 10" | awk '{print $2}'` + totalAvg10=`echo "scale=4; $totalAvg10 + $Avg10" | bc` + Avg20=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 20" | awk '{print $2}'` + totalAvg20=`echo "scale=4; $totalAvg20 + $Avg20" | bc` + Avg30=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 30" | awk '{print $2}'` + totalAvg30=`echo "scale=4; $totalAvg30 + $Avg30" | bc` + Avg40=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 40" | awk '{print $2}'` + totalAvg40=`echo "scale=4; $totalAvg40 + $Avg40" | bc` + Avg50=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 50" | awk '{print $2}'` + totalAvg50=`echo "scale=4; $totalAvg50 + $Avg50" | bc` + Avg60=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 60" | awk '{print $2}'` + totalAvg60=`echo "scale=4; $totalAvg60 + $Avg60" | bc` + Avg70=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 70" | awk '{print $2}'` + totalAvg70=`echo "scale=4; $totalAvg70 + $Avg70" | bc` + Avg80=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 80" | awk '{print $2}'` + totalAvg80=`echo "scale=4; $totalAvg80 + $Avg80" | bc` + Avg90=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 90" | awk '{print $2}'` + totalAvg90=`echo "scale=4; $totalAvg90 + $Avg90" | bc` + Avg100=`cat $TSDBTESTQ2OUT | grep avg | grep "devgroup < 100" | awk '{print $2}'` + totalAvg100=`echo "scale=4; $totalAvg100 + $Avg100" | bc` + + Sum10=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 10" | awk '{print $2}'` + totalSum10=`echo "scale=4; $totalSum10 + $Sum10" | bc` + Sum20=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 20" | awk '{print $2}'` + totalSum20=`echo "scale=4; $totalSum20 + $Sum20" | bc` + Sum30=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 30" | awk '{print $2}'` + totalSum30=`echo "scale=4; $totalSum30 + $Sum30" | bc` + Sum40=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 40" | awk '{print $2}'` + totalSum40=`echo "scale=4; $totalSum40 + $Sum40" | bc` + Sum50=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 50" | awk '{print $2}'` + totalSum50=`echo "scale=4; $totalSum50 + $Sum50" | bc` + Sum60=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 60" | awk '{print $2}'` + totalSum60=`echo "scale=4; $totalSum60 + $Sum60" | bc` + Sum70=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 70" | awk '{print $2}'` + totalSum70=`echo "scale=4; $totalSum70 + $Sum70" | bc` + Sum80=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 80" | awk '{print $2}'` + totalSum80=`echo "scale=4; $totalSum80 + $Sum80" | bc` + Sum90=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 90" | awk '{print $2}'` + totalSum90=`echo "scale=4; $totalSum90 + $Sum90" | bc` + Sum100=`cat $TSDBTESTQ2OUT | grep sum | grep "devgroup < 100" | awk '{print $2}'` + totalSum100=`echo "scale=4; $totalSum100 + $Sum100" | bc` + + Max10=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 10" | awk '{print $2}'` + totalMax10=`echo "scale=4; $totalMax10 + $Max10" | bc` + Max20=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 20" | awk '{print $2}'` + totalMax20=`echo "scale=4; $totalMax20 + $Max20" | bc` + Max30=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 30" | awk '{print $2}'` + totalMax30=`echo "scale=4; $totalMax30 + $Max30" | bc` + Max40=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 40" | awk '{print $2}'` + totalMax40=`echo "scale=4; $totalMax40 + $Max40" | bc` + Max50=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 50" | awk '{print $2}'` + totalMax50=`echo "scale=4; $totalMax50 + $Max50" | bc` + Max60=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 60" | awk '{print $2}'` + totalMax60=`echo "scale=4; $totalMax60 + $Max60" | bc` + Max70=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 70" | awk '{print $2}'` + totalMax70=`echo "scale=4; $totalMax70 + $Max70" | bc` + Max80=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 80" | awk '{print $2}'` + totalMax80=`echo "scale=4; $totalMax80 + $Max80" | bc` + Max90=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 90" | awk '{print $2}'` + totalMax90=`echo "scale=4; $totalMax90 + $Max90" | bc` + Max100=`cat $TSDBTESTQ2OUT | grep max | grep "devgroup < 100" | awk '{print $2}'` + totalMax100=`echo "scale=4; $totalMax100 + $Max100" | bc` + + Min10=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 10" | awk '{print $2}'` + totalMin10=`echo "scale=4; $totalMin10 + $Min10" | bc` + Min20=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 20" | awk '{print $2}'` + totalMin20=`echo "scale=4; $totalMin20 + $Min20" | bc` + Min30=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 30" | awk '{print $2}'` + totalMin30=`echo "scale=4; $totalMin30 + $Min30" | bc` + Min40=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 40" | awk '{print $2}'` + totalMin40=`echo "scale=4; $totalMin40 + $Min40" | bc` + Min50=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 50" | awk '{print $2}'` + totalMin50=`echo "scale=4; $totalMin50 + $Min50" | bc` + Min60=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 60" | awk '{print $2}'` + totalMin60=`echo "scale=4; $totalMin60 + $Min60" | bc` + Min70=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 70" | awk '{print $2}'` + totalMin70=`echo "scale=4; $totalMin70 + $Min70" | bc` + Min80=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 80" | awk '{print $2}'` + totalMin80=`echo "scale=4; $totalMin80 + $Min80" | bc` + Min90=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 90" | awk '{print $2}'` + totalMin90=`echo "scale=4; $totalMin90 + $Min90" | bc` + Min100=`cat $TSDBTESTQ2OUT | grep min | grep "devgroup < 100" | awk '{print $2}'` + totalMin100=`echo "scale=4; $totalMin100 + $Min100" | bc` + + done + avgCount10=`echo "scale=4; x = $totalCount10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount20=`echo "scale=4; x = $totalCount20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount30=`echo "scale=4; x = $totalCount30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount40=`echo "scale=4; x = $totalCount40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount50=`echo "scale=4; x = $totalCount50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount60=`echo "scale=4; x = $totalCount60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount70=`echo "scale=4; x = $totalCount70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount80=`echo "scale=4; x = $totalCount80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount90=`echo "scale=4; x = $totalCount90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgCount100=`echo "scale=4; x = $totalCount100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + + avgAvg10=`echo "scale=4; x = $totalAvg10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg20=`echo "scale=4; x = $totalAvg20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg30=`echo "scale=4; x = $totalAvg30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg40=`echo "scale=4; x = $totalAvg40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg50=`echo "scale=4; x = $totalAvg50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg60=`echo "scale=4; x = $totalAvg60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg70=`echo "scale=4; x = $totalAvg70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg80=`echo "scale=4; x = $totalAvg80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg90=`echo "scale=4; x = $totalAvg90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgAvg100=`echo "scale=4; x = $totalAvg100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + + avgSum10=`echo "scale=4; x = $totalSum10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum20=`echo "scale=4; x = $totalSum20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum30=`echo "scale=4; x = $totalSum30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum40=`echo "scale=4; x = $totalSum40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum50=`echo "scale=4; x = $totalSum50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum60=`echo "scale=4; x = $totalSum60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum70=`echo "scale=4; x = $totalSum70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum80=`echo "scale=4; x = $totalSum80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum90=`echo "scale=4; x = $totalSum90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgSum100=`echo "scale=4; x = $totalSum100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + + avgMax10=`echo "scale=4; x = $totalMax10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax20=`echo "scale=4; x = $totalMax20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax30=`echo "scale=4; x = $totalMax30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax40=`echo "scale=4; x = $totalMax40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax50=`echo "scale=4; x = $totalMax50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax60=`echo "scale=4; x = $totalMax60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax70=`echo "scale=4; x = $totalMax70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax80=`echo "scale=4; x = $totalMax80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax90=`echo "scale=4; x = $totalMax90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMax100=`echo "scale=4; x = $totalMax100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + + avgMin10=`echo "scale=4; x = $totalMin10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin20=`echo "scale=4; x = $totalMin20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin30=`echo "scale=4; x = $totalMin30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin40=`echo "scale=4; x = $totalMin40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin50=`echo "scale=4; x = $totalMin50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin60=`echo "scale=4; x = $totalMin60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin70=`echo "scale=4; x = $totalMin70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin80=`echo "scale=4; x = $totalMin80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin90=`echo "scale=4; x = $totalMin90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgMin100=`echo "scale=4; x = $totalMin100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + + echo "Latency, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%, 100%" + echo "Count, $avgCount10, $avgCount20, $avgCount30, $avgCount40, $avgCount50, $avgCount60, $avgCount70, $avgCount80, $avgCount90, $avgCount100" + echo "Avg, $avgAvg10, $avgAvg20, $avgAvg30, $avgAvg40, $avgAvg50, $avgAvg60, $avgAvg70, $avgAvg80, $avgAvg90, $avgAvg100" + echo "Sum, $avgSum10, $avgSum20, $avgSum30, $avgSum40, $avgSum50, $avgSum60, $avgSum70, $avgSum80, $avgSum90, $avgSum100" + echo "Max, $avgMax10, $avgMax20, $avgMax30, $avgMax40, $avgMax50, $avgMax60, $avgMax70, $avgMax80, $avgMax90, $avgMax100" + echo "Min, $avgMin10, $avgMin20, $avgMin30, $avgMin40, $avgMin50, $avgMin60, $avgMin70, $avgMin80, $avgMin90, $avgMin100" +} + +################ Main ################ + +verbose=false + +for arg in "$@" +do + case $arg in + -v) + verbose=true + shift ;; + + -c) + clients=$2 + shift 2;; + + -n) + NUM_LOOP=$2 + shift 2;; + + *) + ;; + esac +done + +WORK_DIR=/mnt/root/TDengine +TSDBTEST_DIR=$WORK_DIR/tests/comparisonTest/opentsdb + +runTest + +printTo "Test done!" diff --git a/tests/perftest-scripts/opentsdbTestQ3Loop.sh b/tests/perftest-scripts/opentsdbTestQ3Loop.sh new file mode 100755 index 0000000000000000000000000000000000000000..6f69cf85a0d9d3a196991b40655d9c90e6865253 --- /dev/null +++ b/tests/perftest-scripts/opentsdbTestQ3Loop.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +NUM_LOOP=5 + +function printTo { + if $verbose ; then + echo $1 + fi +} + +TSDBTESTQ3OUT=opentsdbTestQ3.out + +function runTest { + totalG10=0 + totalG20=0 + totalG30=0 + totalG40=0 + totalG50=0 + totalG60=0 + totalG70=0 + totalG80=0 + totalG90=0 + totalG100=0 + for i in `seq 1 $NUM_LOOP`; do + printTo "loop i:$i, java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q3" + java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q3 2>&1 \ + | tee $TSDBTESTQ3OUT + G10=`grep -w "devgroup < 10" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG10=`echo "scale=4; $totalG10 + $G10" | bc` + G20=`grep -w "devgroup < 20" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG20=`echo "scale=4; $totalG20 + $G20" | bc` + G30=`grep -w "devgroup < 30" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG30=`echo "scale=4; $totalG30 + $G30" | bc` + G40=`grep -w "devgroup < 40" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG40=`echo "scale=4; $totalG40 + $G40" | bc` + G50=`grep -w "devgroup < 50" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG50=`echo "scale=4; $totalG50 + $G50" | bc` + G60=`grep -w "devgroup < 60" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG60=`echo "scale=4; $totalG60 + $G60" | bc` + G70=`grep -w "devgroup < 70" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG70=`echo "scale=4; $totalG70 + $G70" | bc` + G80=`grep -w "devgroup < 80" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG80=`echo "scale=4; $totalG80 + $G80" | bc` + G90=`grep -w "devgroup < 90" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG90=`echo "scale=4; $totalG90 + $G90" | bc` + G100=`grep -w "devgroup < 100" $TSDBTESTQ3OUT| awk '{print $2}'` + totalG100=`echo "scale=4; $totalG100 + $G100" | bc` + done + avgG10=`echo "scale=4; x = $totalG10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG20=`echo "scale=4; x = $totalG20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG30=`echo "scale=4; x = $totalG30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG40=`echo "scale=4; x = $totalG40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG50=`echo "scale=4; x = $totalG50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG60=`echo "scale=4; x = $totalG60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG70=`echo "scale=4; x = $totalG70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG80=`echo "scale=4; x = $totalG80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG90=`echo "scale=4; x = $totalG90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG100=`echo "scale=4; x = $totalG100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + echo "Latency, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%, 100%" + echo "OpenTSDB, $avgG10, $avgG20, $avgG30, $avgG40, $avgG50, $avgG60, $avgG70, $avgG80, $avgG90, $avgG100" +} + +################ Main ################ + +verbose=false + +for arg in "$@" +do + case $arg in + -v) + verbose=true + shift ;; + + -c) + clients=$2 + shift 2;; + + -n) + NUM_LOOP=$2 + shift 2;; + + *) + ;; + esac +done + +WORK_DIR=/mnt/root/TDengine +TSDBTEST_DIR=$WORK_DIR/tests/comparisonTest/opentsdb + +runTest + +printTo "Test done!" diff --git a/tests/perftest-scripts/opentsdbTestQ4Loop.sh b/tests/perftest-scripts/opentsdbTestQ4Loop.sh new file mode 100755 index 0000000000000000000000000000000000000000..4341f2165ce05da20d268b991f596d6636f3bdb2 --- /dev/null +++ b/tests/perftest-scripts/opentsdbTestQ4Loop.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +DATA_DIR=/mnt/root/testdata +NUM_LOOP=5 + +function printTo { + if $verbose ; then + echo $1 + fi +} + +TSDBTESTQ4OUT=opentsdbTestQ4.out + +function runTest { + totalG10=0 + totalG20=0 + totalG30=0 + totalG40=0 + totalG50=0 + totalG60=0 + totalG70=0 + totalG80=0 + totalG90=0 + totalG100=0 + for i in `seq 1 $NUM_LOOP`; do + printTo "loop i:$i, java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q4" + + java -jar \ + $TSDBTEST_DIR/opentsdbtest/target/opentsdbtest-1.0-SNAPSHOT-jar-with-dependencies.jar \ + -sql q4 2>&1 | + tee $TSDBTESTQ4OUT + G10=`grep -w "devgroup < 10" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG10=`echo "scale=4; $totalG10 + $G10" | bc` + G20=`grep -w "devgroup < 20" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG20=`echo "scale=4; $totalG20 + $G20" | bc` + G30=`grep -w "devgroup < 30" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG30=`echo "scale=4; $totalG30 + $G30" | bc` + G40=`grep -w "devgroup < 40" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG40=`echo "scale=4; $totalG40 + $G40" | bc` + G50=`grep -w "devgroup < 50" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG50=`echo "scale=4; $totalG50 + $G50" | bc` + G60=`grep -w "devgroup < 60" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG60=`echo "scale=4; $totalG60 + $G60" | bc` + G70=`grep -w "devgroup < 70" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG70=`echo "scale=4; $totalG70 + $G70" | bc` + G80=`grep -w "devgroup < 80" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG80=`echo "scale=4; $totalG80 + $G80" | bc` + G90=`grep -w "devgroup < 90" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG90=`echo "scale=4; $totalG90 + $G90" | bc` + G100=`grep -w "devgroup < 100" $TSDBTESTQ4OUT| awk '{print $2}'` + totalG100=`echo "scale=4; $totalG100 + $G100" | bc` + done + avgG10=`echo "scale=4; x = $totalG10 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG20=`echo "scale=4; x = $totalG20 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG30=`echo "scale=4; x = $totalG30 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG40=`echo "scale=4; x = $totalG40 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG50=`echo "scale=4; x = $totalG50 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG60=`echo "scale=4; x = $totalG60 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG70=`echo "scale=4; x = $totalG70 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG80=`echo "scale=4; x = $totalG80 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG90=`echo "scale=4; x = $totalG90 / $NUM_LOOP; if(x<1) print 0; x" | bc` + avgG100=`echo "scale=4; x = $totalG100 / $NUM_LOOP; if(x<1) print 0; x" | bc` + echo "Latency, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90%, 100%" + echo "OpenTSDB, $avgG10, $avgG20, $avgG30, $avgG40, $avgG50, $avgG60, $avgG70, $avgG80, $avgG90, $avgG100" +} + +################ Main ################ + +verbose=false +regeneratedata=false + +for arg in "$@" +do + case $arg in + -v) + verbose=true + shift ;; + + -c) + clients=$2 + shift 2;; + + -r) + regeneratedata=true + ;; + + -n) + NUM_LOOP=$2 + shift 2;; + + *) + ;; + esac +done + +WORK_DIR=/mnt/root/TDengine +TSDBTEST_DIR=$WORK_DIR/tests/comparisonTest/opentsdb + +runTest + +printTo "Test done!" diff --git a/tests/pytest/crash_gen.py b/tests/pytest/crash_gen.py index 7cdc2b27c39fa453a30361cf00f45c513ef7365a..8edba3903d794477cf82af95387bd8d9f10bbe93 100755 --- a/tests/pytest/crash_gen.py +++ b/tests/pytest/crash_gen.py @@ -643,7 +643,7 @@ class DbConn: self.execute("use {}".format(dbName)) def hasDatabases(self): - return self.query("show databases") > 0 + return self.query("show databases") > 1 # We now have a "log" database by default def hasTables(self): return self.query("show tables") > 0 @@ -850,6 +850,7 @@ class DbConnNative(DbConn): raise RuntimeError( "Cannot execute database commands until connection is open") logger.debug("[SQL] Executing SQL: {}".format(sql)) + self._lastSql = sql nRows = self._tdSql.execute(sql) logger.debug( "[SQL] Execution Result, nRows = {}, SQL = {}".format( @@ -861,6 +862,7 @@ class DbConnNative(DbConn): raise RuntimeError( "Cannot query database until connection is open") logger.debug("[SQL] Executing SQL: {}".format(sql)) + self._lastSql = sql nRows = self._tdSql.query(sql) logger.debug( "[SQL] Query Result, nRows = {}, SQL = {}".format( @@ -1771,6 +1773,9 @@ class TdSuperTable: def __init__(self, stName): self._stName = stName + def getName(self): + return self._stName + def create(self, dbc, cols: dict, tags: dict): sql = "CREATE TABLE db.{} ({}) TAGS ({})".format( self._stName, @@ -1864,16 +1869,29 @@ class TaskReadData(StateTransitionTask): wt.getDbConn().close() wt.getDbConn().open() - for rTbName in sTable.getRegTables(wt.getDbConn()): # regular tables - aggExpr = Dice.choice(['*', 'count(*)', 'avg(speed)', + dbc = wt.getDbConn() + for rTbName in sTable.getRegTables(dbc): # regular tables + aggExpr = Dice.choice([ + '*', + 'count(*)', + 'avg(speed)', # 'twa(speed)', # TODO: this one REQUIRES a where statement, not reasonable - 'sum(speed)', 'stddev(speed)', - 'min(speed)', 'max(speed)', 'first(speed)', 'last(speed)']) # TODO: add more from 'top' + 'sum(speed)', + 'stddev(speed)', + 'min(speed)', + 'max(speed)', + 'first(speed)', + 'last(speed)']) # TODO: add more from 'top' + filterExpr = Dice.choice([ # TODO: add various kind of WHERE conditions + None + ]) try: - self.execWtSql(wt, "select {} from db.{}".format(aggExpr, rTbName)) + dbc.execute("select {} from db.{}".format(aggExpr, rTbName)) + if aggExpr not in ['stddev(speed)']: #TODO: STDDEV not valid for super tables?! + dbc.execute("select {} from db.{}".format(aggExpr, sTable.getName())) except taos.error.ProgrammingError as err: errno2 = err.errno if (err.errno > 0) else 0x80000000 + err.errno - logger.debug("[=] Read Failure: errno=0x{:X}, msg: {}, SQL: {}".format(errno2, err, wt.getDbConn().getLastSql())) + logger.debug("[=] Read Failure: errno=0x{:X}, msg: {}, SQL: {}".format(errno2, err, dbc.getLastSql())) raise class TaskDropSuperTable(StateTransitionTask): @@ -2204,8 +2222,8 @@ class SvcManager: # print("Process: {}".format(proc.name())) self.svcMgrThread = ServiceManagerThread() # create the object - self.svcMgrThread.start() print("Attempting to start TAOS service started, printing out output...") + self.svcMgrThread.start() self.svcMgrThread.procIpcBatch( trimToTarget=10, forceOutput=True) # for printing 10 lines @@ -2222,8 +2240,8 @@ class SvcManager: if self.svcMgrThread.isStopped(): self.svcMgrThread.procIpcBatch(outputLines) # one last time self.svcMgrThread = None - print("----- End of TDengine Service Output -----\n") - print("SMT execution terminated") + print("End of TDengine Service Output") + print("----- TDengine Service (managed by SMT) is now terminated -----\n") else: print("WARNING: SMT did not terminate as expected") @@ -2330,6 +2348,8 @@ class ServiceManagerThread: self._status = MainExec.STATUS_STOPPING retCode = self._tdeSubProcess.stop() print("Attempted to stop sub process, got return code: {}".format(retCode)) + if (retCode==-11): # SGV + logger.error("[[--ERROR--]]: TDengine service SEGV fault (check core file!)") if self._tdeSubProcess.isRunning(): # still running print("FAILED to stop sub process, it is still running... pid = {}".format( @@ -2624,12 +2644,12 @@ class ClientManager: def _printLastNumbers(self): # to verify data durability dbManager = DbManager(resetDb=False) dbc = dbManager.getDbConn() - if dbc.query("show databases") == 0: # no databae + if dbc.query("show databases") <= 1: # no database (we have a default called "log") return + dbc.execute("use db") if dbc.query("show tables") == 0: # no tables return - dbc.execute("use db") sTbName = dbManager.getFixedSuperTableName() # get all regular tables diff --git a/tests/pytest/subscribe/stability.py b/tests/pytest/subscribe/stability.py new file mode 100644 index 0000000000000000000000000000000000000000..ddd8b3282a01843f912ce8e19b4baa790aa32bfa --- /dev/null +++ b/tests/pytest/subscribe/stability.py @@ -0,0 +1,93 @@ +################################################################### + # Copyright (c) 2020 by TAOS Technologies, Inc. + # All rights reserved. + # + # This file is proprietary and confidential to TAOS Technologies. + # No part of this file may be reproduced, stored, transmitted, + # disclosed or used in any form or by any means other than as + # expressly provided by the written permission from Jianhui Tao + # +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +import time +import random +import string +from util.log import * +from util.cases import * +from util.sql import * +from util.sub import * + +class TDTestCase: + maxTables = 10000 + maxCols = 50 + rowsPerSecond = 1000 + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdLog.notice("NOTE: this case does not stop automatically, Ctrl+C to stop") + tdSql.init(conn.cursor(), logSql) + self.conn = conn + + + def generateString(self, length): + chars = string.ascii_uppercase + string.ascii_lowercase + v = "" + for i in range(length): + v += random.choice(chars) + return v + + + def insert(self): + id = random.randint(0, self.maxTables - 1) + cola = self.generateString(40) + sql = "insert into car%d values(now, '%s', %f, %d" % (id, cola, random.random()*100, random.randint(0, 2)) + for i in range(self.maxCols): + sql += ", %d" % random.randint(0, self.maxTables) + sql += ")" + tdSql.execute(sql) + + + def prepare(self): + tdLog.info("prepare database: test") + tdSql.execute('reset query cache') + tdSql.execute('drop database if exists test') + tdSql.execute('create database test') + tdSql.execute('use test') + + def run(self): + self.prepare() + + sql = "create table cars (ts timestamp, a binary(50), b float, c bool" + for i in range(self.maxCols): + sql += ", c%d int" % i + sql += ") tags(id int, category binary(30), brand binary(30));" + tdSql.execute(sql) + + for i in range(self.maxTables): + tdSql.execute("create table car%d using cars tags(%d, 'category%d', 'brand%d')" % (i, i, i % 30, i // 30)) + + time.sleep(0.1) + + total = 0 + while True: + start = time.time() + for i in range(self.rowsPerSecond): + self.insert() + total = total + 1 + d = time.time() - start + tdLog.info("%d rows inserted in %f seconds, total %d" % (self.rowsPerSecond, d, total)) + if d < 1: + time.sleep(1 - d) + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/subscribe/supertable.py b/tests/pytest/subscribe/supertable.py index c6cc2969aa57848bf2c43163a26608117e82ad90..ee3aa225bd79a6709a06672df76d7e7163f7a831 100644 --- a/tests/pytest/subscribe/supertable.py +++ b/tests/pytest/subscribe/supertable.py @@ -31,16 +31,19 @@ class TDTestCase: now = int(time.time() * 1000) tdSql.prepare() - tdLog.info("create a super table and 10 sub-tables, then insert 5 rows into each sub-table.") + numTables = 2000 + rowsPerTable = 5 + totalRows = numTables * rowsPerTable + tdLog.info("create a super table and %d sub-tables, then insert %d rows into each sub-table." % (numTables, rowsPerTable)) tdSql.execute("create table meters(ts timestamp, a int, b int) tags(area int, loc binary(20));") - for i in range(0, 10): - for j in range(0, 5): + for i in range(0, numTables): + for j in range(0, rowsPerTable): tdSql.execute("insert into t%d using meters tags(%d, 'area%d') values (%d, %d, %d);" % (i, i, i, now + j, j, j)) tdLog.info("consumption 01.") tdSub.init(self.conn.subscribe(True, topic, sqlstr, 0)) tdSub.consume() - tdSub.checkRows(50) + tdSub.checkRows(totalRows) tdLog.info("consumption 02: no new rows inserted") tdSub.consume() @@ -61,17 +64,17 @@ class TDTestCase: tdSub.close(False) tdSub.init(self.conn.subscribe(False, topic, sqlstr, 0)) tdSub.consume() - tdSub.checkRows(51) + tdSub.checkRows(totalRows + 1) tdLog.info("consumption 06: keep progress and restart the subscription") tdSub.close(True) tdSub.init(self.conn.subscribe(True, topic, sqlstr, 0)) tdSub.consume() - tdSub.checkRows(51) + tdSub.checkRows(totalRows + 1) tdLog.info("consumption 07: insert one row to two table then remove one table") tdSql.execute("insert into t0 values (%d, 11, 11);" % (now + 11)) - tdSql.execute("insert into t1 values (%d, 11, 11);" % (now + 11)) + tdSql.execute("insert into t%d values (%d, 11, 11);" % ((numTables-1), (now + 11))) tdSql.execute("drop table t0") tdSub.consume() tdSub.checkRows(1) @@ -80,7 +83,7 @@ class TDTestCase: tdSub.close(False) tdSub.init(self.conn.subscribe(True, topic, sqlstr + " where ts > %d" % now, 0)) tdSub.consume() - tdSub.checkRows(37) + tdSub.checkRows((numTables-1) * (rowsPerTable-1) + 1) tdLog.info("consumption 09: insert large timestamp to t2 then insert smaller timestamp to t1") tdSql.execute("insert into t2 values (%d, 100, 100);" % (now + 100)) @@ -101,10 +104,15 @@ class TDTestCase: tdLog.info("consumption 11: two vnodes") tdSql.execute("insert into t2 values (%d, 102, 100);" % (now + 104)) - tdSql.execute("insert into t9 values (%d, 102, 100);" % (now + 104)) + tdSql.execute("insert into t1299 values (%d, 102, 100);" % (now + 104)) tdSub.consume() tdSub.checkRows(2) + tdLog.info("consumption 12: create a new table") + tdSql.execute("insert into t%d using meters tags(%d, 'area%d') values (%d, 102, 100);" % (numTables, numTables, numTables, now + 105)) + tdSub.consume() + tdSub.checkRows(1) + def stop(self): tdSub.close(False) tdSql.close() diff --git a/tests/script/general/db/delete.sim b/tests/script/general/db/delete.sim index 059ab2e353830252cea71c5048a89d7164772fbb..e4d40bf5da267985066f61383c6614dee78aaff1 100644 --- a/tests/script/general/db/delete.sim +++ b/tests/script/general/db/delete.sim @@ -10,7 +10,7 @@ sleep 3000 sql connect print ======== step1 -sql create database db blocks 2 +sql create database db blocks 3 sql create table db.mt (ts timestamp, tbcol int) TAGS(tgcol int) $tbPrefix = db.t diff --git a/tests/script/general/db/vnodes.sim b/tests/script/general/db/vnodes.sim index ef505b25c16e4ccdc37f016116f01fd715f82d14..b01e94206fa33978b359b6c40576284f69b74d87 100644 --- a/tests/script/general/db/vnodes.sim +++ b/tests/script/general/db/vnodes.sim @@ -17,7 +17,7 @@ print ========== prepare data system sh/exec.sh -n dnode1 -s start sleep 3000 sql connect -sql create database db blocks 2 cache 1 +sql create database db blocks 3 cache 1 sql use db print ========== step1 diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index 1e73893793a9f011f6753e5745226e664ca253f2..dd4faee95966a209709cade09368e1241e5548f7 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -1,27 +1,27 @@ -sleep 2000 -run general/parser/alter.sim -sleep 2000 -run general/parser/alter1.sim -sleep 2000 -run general/parser/alter_stable.sim -sleep 2000 -run general/parser/auto_create_tb.sim -sleep 2000 -run general/parser/auto_create_tb_drop_tb.sim -sleep 2000 -run general/parser/col_arithmetic_operation.sim -sleep 2000 -run general/parser/columnValue.sim -sleep 2000 -run general/parser/commit.sim -sleep 2000 -run general/parser/create_db.sim -sleep 2000 -run general/parser/create_mt.sim -sleep 2000 -run general/parser/create_tb.sim -sleep 2000 -run general/parser/dbtbnameValidate.sim +#sleep 2000 +#run general/parser/alter.sim +#sleep 2000 +#run general/parser/alter1.sim +#sleep 2000 +#run general/parser/alter_stable.sim +#sleep 2000 +#run general/parser/auto_create_tb.sim +#sleep 2000 +#run general/parser/auto_create_tb_drop_tb.sim +#sleep 2000 +#run general/parser/col_arithmetic_operation.sim +#sleep 2000 +#run general/parser/columnValue.sim +#sleep 2000 +#run general/parser/commit.sim +#sleep 2000 +#run general/parser/create_db.sim +#sleep 2000 +#run general/parser/create_mt.sim +#sleep 2000 +#run general/parser/create_tb.sim +#sleep 2000 +#run general/parser/dbtbnameValidate.sim sleep 2000 run general/parser/fill.sim sleep 2000 diff --git a/tests/script/sh/deploy.sh b/tests/script/sh/deploy.sh index 841dfcce95bb8aa4dc16201cbcc9f5ffd9040eb7..498f5367261c395be3ef1c508a8dc14700a7f8d1 100755 --- a/tests/script/sh/deploy.sh +++ b/tests/script/sh/deploy.sh @@ -137,7 +137,7 @@ echo "numOfLogLines 20000000" >> $TAOS_CFG echo "mnodeEqualVnodeNum 0" >> $TAOS_CFG echo "clog 2" >> $TAOS_CFG #echo "cache 1" >> $TAOS_CFG -#echo "block 2" >> $TAOS_CFG +echo "days 10" >> $TAOS_CFG echo "statusInterval 1" >> $TAOS_CFG echo "maxVgroupsPerDb 4" >> $TAOS_CFG echo "minTablesPerVnode 4" >> $TAOS_CFG diff --git a/tests/script/unique/big/maxvnodes.sim b/tests/script/unique/big/maxvnodes.sim index a4959aab3f61b916913b488449f7cea23f48053c..eb6e0b3b53c4bfee7b8f11c0f431812fc27c93e8 100644 --- a/tests/script/unique/big/maxvnodes.sim +++ b/tests/script/unique/big/maxvnodes.sim @@ -18,7 +18,7 @@ print ========== prepare data system sh/exec.sh -n dnode1 -s start sleep 3000 sql connect -sql create database db blocks 2 cache 1 maxTables $maxTables +sql create database db blocks 3 cache 1 maxTables $maxTables sql use db print ========== step1 diff --git a/tests/script/unique/big/restartSpeed.sim b/tests/script/unique/big/restartSpeed.sim index ef32cec585cb0fca443dd319dc3461e1b2c15a1c..9d490fcb8b15b8eb2b4af1fd48fcd6fa908a2ce6 100644 --- a/tests/script/unique/big/restartSpeed.sim +++ b/tests/script/unique/big/restartSpeed.sim @@ -16,7 +16,7 @@ print ========== prepare data system sh/exec.sh -n dnode1 -s start sleep 3000 sql connect -sql create database db blocks 2 cache 1 maxTables $maxTables +sql create database db blocks 3 cache 1 maxTables $maxTables sql use db print ========== step1 diff --git a/tests/script/unique/db/delete.sim b/tests/script/unique/db/delete.sim index 49732cdf912d051d6f2eb9522ad3627be89a2b6e..f89588a8ac72a7584e04d6d0d3537d2ff97c56c7 100644 --- a/tests/script/unique/db/delete.sim +++ b/tests/script/unique/db/delete.sim @@ -26,7 +26,7 @@ sql create dnode $hostname3 system sh/exec.sh -n dnode3 -s start print ======== step1 -sql create database db replica 3 blocks 2 +sql create database db replica 3 blocks 3 sql create table db.mt (ts timestamp, tbcol int) TAGS(tgcol int) $tbPrefix = db.t diff --git a/tests/script/windows/account/authority.sim b/tests/script/windows/account/authority.sim deleted file mode 100644 index a352faf23bc9ea2979abcb337c8bae6794b91890..0000000000000000000000000000000000000000 --- a/tests/script/windows/account/authority.sim +++ /dev/null @@ -1,317 +0,0 @@ -sql connect -sleep 3000 - -print ============= step1 - -sql create user read pass 'taosdata' -sql create user write pass 'taosdata' -sql create user manage pass 'taosdata' - -sql create user a PASS 'ade' privilege -x step11 - return -1 -step11: - -sql create user a PASS 'ade' privilege a -x step12 - return -1 -step12: - -sql create user a PASS 'ade' privilege read -x step13 - return -1 -step13: - -sql show users -if $rows != 6 then - return -1 -endi - -sql alter user read privilege read -sql alter user write privilege write -sql alter user manage privilege super - -print ============= step2 -sql close -sql connect write -sleep 2000 - -sql create database d1 -sql create database d2 -sql create table d1.t1 (ts timestamp, i int) -sql create table d2.t2 (ts timestamp, i int) -sql insert into d1.t1 values(now, 1) -sql insert into d2.t2 values(now, 1) -sql insert into d2.t2 values(now+1s, 2) - -sql show users -if $rows != 6 then - return -1 -endi -sql show databases -if $rows != 2 then - return -1 -endi -sql select * from d1.t1 -if $rows != 1 then - return -1 -endi -sql select * from d2.t2 -if $rows != 2 then - return -1 -endi - -sql create account t1 pass 'taosdata' -x step21 - return -1 -step21: - -sql create user t1 pass 'taosdata' -x step22 - return -1 -step22: - -sql alter user read pass 'taosdata' -x step23 - return -1 -step23: - -sql create dnode $hostname2 -x step24 - return -1 -step24: - -sql drop dnode $hostname2 -x step25 - return -1 -step25: - -sql create mnode 192.168.0.2 -x step26 - return -1 -step26: - -sql drop mnode 192.168.0.2 -x step27 - return -1 -step27: - -sql drop account root -x step28 - return -1 -step28: - -sql alter user write pass 'taosdata' - -print ============= step3 -sql close -sql connect read -sleep 2000 - -sql create database d3 -x step31 - return -1 -step31: - -sql create table d1.t3 (ts timestamp, i int) -x step32 - return -1 -step32: - -#sql insert into d1.t1 values(now, 2) -x step33 -# return -1 -#step33: - -sql show accounts -if $rows != 1 then - return -1 -endi -sql show users -if $rows != 6 then - return -1 -endi -sql show databases -if $rows != 2 then - return -1 -endi -sql select * from d1.t1 -if $rows != 1 then - return -1 -endi - -sql select * from d2.t2 -if $rows != 2 then - return -1 -endi - -sql sql create account t1 pass 'taosdata' -x step34 - return -1 -step34: - -sql sql create user t1 pass 'taosdata' -x step35 - return -1 -step35: - -print ============= step4 -sql close -sql connect manage -sleep 2000 - -sql create database d3 -sql create database d4 -sql create table d3.t3 (ts timestamp, i int) -sql create table d4.t4 (ts timestamp, i int) - -sql show accounts -if $rows != 1 then - return -1 -endi -sql show users -if $rows != 6 then - return -1 -endi -sql show databases -if $rows != 4 then - return -1 -endi -sql select * from d1.t1 -if $rows != 1 then - return -1 -endi -sql select * from d2.t2 -if $rows != 2 then - return -1 -endi - -sql create account other pass 'taosdata' -x step41 - return -1 -step41: - -sql close -sql connect -sleep 2000 -sql create account other pass 'taosdata' - -print ============= step5 -sql close -sql connect other -sleep 2000 -sql create user read pass 'taosdata' -x step51 - return -1 -step51: -sql create other write pass 'taosdata' -x step52 - return -1 -step52: - -sql create user oread pass 'taosdata' -sql create user owrite pass 'taosdata' -sql create user omanage pass 'taosdata' - -sql show users -print show users $rows -if $rows != 5 then - return -1 -endi - -sql alter user oread privilege read -sql alter user owrite privilege write -sql alter user oroot privilege super -x step53 - return -1 -step53: -sql alter user read privilege read -x step54 - return -1 -step54: - -print ============= step6 -sql close -sql connect owrite -sleep 2000 - -sql create database d1 -sql create database d3 -sql create table d1.t1 (ts timestamp, i int) -sql create table d3.t3 (ts timestamp, i int) -sql insert into d1.t1 values(now, 11) -sql insert into d3.t3 values(now, 11) -sql insert into d3.t3 values(now+1s, 12) - -sql show databases -if $rows != 2 then - return -1 -endi -sql select * from d1.t1 -if $rows != 1 then - return -1 -endi -sql select * from d2.t2 -x step6 - return -1 -step6: -sql select * from d3.t3 -if $rows != 2 then - return -1 -endi - -sql sql create user t1 pass 'taosdata' -x step62 - return -1 -step62: - -print ============= step7 -sql close -sql connect oread -sleep 2000 - -sql create database d7 -x step71 - return -1 -step71: - -sql show databases -if $rows != 2 then - return -1 -endi -sql select * from d1.t1 -if $rows != 1 then - return -1 -endi -sql select * from d2.t2 -x step72 - return -1 -step72: -sql select * from d3.t3 -if $rows != 2 then - return -1 -endi - -sql sql create user t1 pass 'taosdata' -x step74 - return -1 -step74: - -print ============= step8 -sql close -sql connect omanage -sleep 2000 - -sql create database d4 -sql create table d4.t4 (ts timestamp, i int) - -sql show databases -if $rows != 3 then - return -1 -endi -sql select * from d1.t1 -if $rows != 1 then - return -1 -endi -sql select * from d2.t2 -x step82 - return -1 -step82: -sql select * from d3.t3 -if $rows != 2 then - return -1 -endi - -print ============= step9 -sql close -sql connect -sleep 2000 -sql show databases -if $rows != 4 then - return -1 -endi - -sql drop user read -sql drop user manage -sql drop user write - -sql close -sql connect -sleep 2000 -sql drop database d1 -sql drop database d2 -sql drop database d3 -sql drop database d4 diff --git a/tests/script/windows/account/user_create.sim b/tests/script/windows/account/user_create.sim deleted file mode 100644 index 6dc9ab05b3baf7ffa01540b51918cb18715f5eb1..0000000000000000000000000000000000000000 --- a/tests/script/windows/account/user_create.sim +++ /dev/null @@ -1,80 +0,0 @@ -sql connect -sleep 3000 - -print =============== step1 -sql show users -if $rows != 3 then - return -1 -endi - -sql create user read PASS 'pass123' -sql create user read PASS 'pass123' -x step1 - return -1 -step1: - -sql show users -if $rows != 4 then - return -1 -endi - -sql alter user read PASS 'taosdata' - -print =============== step2 -sql close -sql connect read -sleep 2000 - -sql alter user read PASS 'taosdata' - -print =============== step3 -sql drop user read -x step31 - return -1 -step31: -sql drop user _root -x step32 - return -1 -step32: -sql drop user monitor -x step33 - return -1 -step33: - -print =============== step4 -sql close -sql connect -sleep 2000 - -sql alter user read privilege read -sql show users -if $data1_read != read then - return -1 -endi - -sql alter user read privilege super -sql show users -if $data1_read != super then - return -1 -endi - -sql alter user read privilege write -sql show users -if $data1_read != write then - return -1 -endi - -sql alter user read privilege 1 -x step43 - return -1 -step43: - -sql drop user _root -x step41 - return -1 -step41: - -sql drop user monitor -x step42 - return -1 -step42: - -sql drop user read - - - - - diff --git a/tests/script/windows/account/user_len.sim b/tests/script/windows/account/user_len.sim deleted file mode 100644 index b4a344fe8d9bedf54f307d13fba07976b95d9110..0000000000000000000000000000000000000000 --- a/tests/script/windows/account/user_len.sim +++ /dev/null @@ -1,81 +0,0 @@ -sql connect -sleep 3000 - -$i = 0 -$dbPrefix = lm_us_db -$tbPrefix = lm_us_tb -$db = $dbPrefix . $i -$tb = $tbPrefix . $i - -print =============== step1 -sql drop user ac -x step0 - return -1 -step0: - -sql create user PASS '123' -x step1 - return -1 -step1: - -sql show users -if $rows != 3 then - return -1 -endi - -print =============== step2 -sql drop user a -x step2 -step2: -sql create user a PASS '123' -sql show users -if $rows != 4 then - return -1 -endi - -sql drop user a -sql show users -if $rows != 3 then - return -1 -endi - -print =============== step3 -sql drop user abc01234567890123456789 -x step3 -step3: - -sql create user abc01234567890123456789 PASS '123' -sql show users -if $rows != 4 then - return -1 -endi - -sql drop user abc01234567890123456789 -sql show users -if $rows != 3 then - return -1 -endi - -print =============== step4 -sql create user abcd0123456789012345678901234567890111 PASS '123' -x step4 - return -1 -step4: -sql show users -if $rows != 3 then - return -1 -endi - -print =============== step5 -sql drop user 123 -x step5 -step5: -sql create user 123 PASS '123' -x step61 - return -1 -step61: - -sql create user a123 PASS '123' -sql show users -if $rows != 4 then - return -1 -endi - -sql drop user a123 -sql show users -if $rows != 3 then - return -1 -endi diff --git a/tests/script/windows/alter/metrics.sim b/tests/script/windows/alter/metrics.sim index 323e150d41410c780680bf41b7e8c7f2c5aaee66..3717d8c1ed766a0a80d22cbb1965af934b570746 100644 --- a/tests/script/windows/alter/metrics.sim +++ b/tests/script/windows/alter/metrics.sim @@ -35,7 +35,6 @@ endi print ======== step2 sql alter table mt add column b smallint -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -64,7 +63,6 @@ endi print ======== step3 sql alter table mt add column c tinyint -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -99,7 +97,6 @@ endi print ======== step4 sql alter table mt add column d int -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -140,7 +137,6 @@ endi print ======== step5 sql alter table mt add column e bigint -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -187,7 +183,6 @@ endi print ======== step6 sql alter table mt add column f float -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -240,7 +235,6 @@ endi print ======== step7 sql alter table mt add column g double -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -299,7 +293,6 @@ endi print ======== step8 sql alter table mt add column h binary(10) -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -461,7 +454,6 @@ print ======== step11 print ======== step12 sql alter table mt drop column b -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -523,7 +515,6 @@ endi print ======== step13 sql alter table mt drop column c -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -579,7 +570,6 @@ endi print ======== step14 sql alter table mt drop column d -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -629,7 +619,6 @@ endi print ======== step15 sql alter table mt drop column e -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -673,7 +662,6 @@ endi print ======== step16 sql alter table mt drop column f -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -711,7 +699,6 @@ endi print ======== step17 sql alter table mt drop column g -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -743,7 +730,6 @@ endi print ============= step18 sql alter table mt drop column h -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -763,7 +749,7 @@ endi if $data21 != INT then return -1 endi -if $data30 != NULL then +if $data30 != null then return -1 endi diff --git a/tests/script/windows/alter/table.sim b/tests/script/windows/alter/table.sim index e6b5d695510cf66ee4accc0a329fe44597f1cdce..3b811a065ee28bbc9cf8e1a72bd9e9b656139c83 100644 --- a/tests/script/windows/alter/table.sim +++ b/tests/script/windows/alter/table.sim @@ -28,7 +28,6 @@ endi print ======== step2 sql alter table tb add column b smallint -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -51,7 +50,6 @@ endi print ======== step3 sql alter table tb add column c tinyint -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -80,7 +78,6 @@ endi print ======== step4 sql alter table tb add column d int -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -115,7 +112,6 @@ endi print ======== step5 sql alter table tb add column e bigint -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -156,7 +152,6 @@ endi print ======== step6 sql alter table tb add column f float -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -203,7 +198,6 @@ endi print ======== step7 sql alter table tb add column g double -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -256,7 +250,6 @@ endi print ======== step8 sql alter table tb add column h binary(10) -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -406,7 +399,6 @@ step115: print ======== step12 sql alter table tb drop column b -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -462,7 +454,6 @@ endi print ======== step13 sql alter table tb drop column c -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -512,7 +503,6 @@ endi print ======== step14 sql alter table tb drop column d -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -556,7 +546,6 @@ endi print ======== step15 sql alter table tb drop column e -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -594,7 +583,6 @@ endi print ======== step16 sql alter table tb drop column f -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -626,7 +614,6 @@ endi print ======== step17 sql alter table tb drop column g -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -652,7 +639,6 @@ endi print ============= step18 sql alter table tb drop column h -sleep 2500 sql describe tb if $data00 != ts then return -1 @@ -666,7 +652,7 @@ endi if $data11 != INT then return -1 endi -if $data20 != NULL then +if $data20 != null then return -1 endi diff --git a/tests/script/windows/compute/diff.sim b/tests/script/windows/compute/diff.sim index e9d76f8c78128f38a9248dcb832628d99a0e0408..6c2829872a02fa1de829df7b5089c6d06bbb581e 100644 --- a/tests/script/windows/compute/diff.sim +++ b/tests/script/windows/compute/diff.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_di_db $tbPrefix = m_di_tb diff --git a/tests/script/windows/compute/first.sim b/tests/script/windows/compute/first.sim index 7b6a8310045afbcf2c2fda9f6f3e11e1a337581e..9a0c02fe4b972383d9a9247291635a814410cded 100644 --- a/tests/script/windows/compute/first.sim +++ b/tests/script/windows/compute/first.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_fi_db $tbPrefix = m_fi_tb diff --git a/tests/script/windows/compute/interval.sim b/tests/script/windows/compute/interval.sim index d40c6ad0c9ce98f401e2e144e279e2b48b2b96ea..365c6d9d312ae25539664747ca2410e55cf9e067 100644 --- a/tests/script/windows/compute/interval.sim +++ b/tests/script/windows/compute/interval.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_in_db $tbPrefix = m_in_tb diff --git a/tests/script/windows/compute/last.sim b/tests/script/windows/compute/last.sim index 4b686766ae547b4b6d7dc99c2a2c714a5aa4934a..aa9699778f4526783a3c425bea2dddf096ba01eb 100644 --- a/tests/script/windows/compute/last.sim +++ b/tests/script/windows/compute/last.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_la_db $tbPrefix = m_la_tb diff --git a/tests/script/windows/compute/leastsquare.sim b/tests/script/windows/compute/leastsquare.sim index 81f37c32287fdc1a10e15a1856c659564e666056..bb7404edd0eefb06851c24aaf7de6f97e2e9f60f 100644 --- a/tests/script/windows/compute/leastsquare.sim +++ b/tests/script/windows/compute/leastsquare.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_le_db $tbPrefix = m_le_tb @@ -15,7 +15,7 @@ $mt = $mtPrefix . $i sql drop database $db -x step1 step1: -sql create database $db +sql create database $db keep 36500 sql use $db sql create table $mt (ts timestamp, tbcol int) TAGS(tgcol int) @@ -43,41 +43,41 @@ $tb = $tbPrefix . $i sql select leastsquares(tbcol, 1, 1) from $tb print ===> $data00 -if $data00 != @(1.000000, 1.000000)@ then +if $data00 != @{slop:1.000000, intercept:1.000000}@ then return -1 endi print =============== step3 sql select leastsquares(tbcol, 1, 1) from $tb where ts < now + 4m print ===> $data00 -if $data00 != @(1.000000, 1.000000)@ then +if $data00 != @{slop:1.000000, intercept:1.000000}@ then return -1 endi print =============== step4 sql select leastsquares(tbcol, 1, 1) as b from $tb print ===> $data00 -if $data00 != @(1.000000, 1.000000)@ then +if $data00 != @{slop:1.000000, intercept:1.000000}@ then return -1 endi print =============== step5 sql select leastsquares(tbcol, 1, 1) as b from $tb interval(1m) print ===> $data01 -if $data01 != @(1.000000, 1.000000)@ then +if $data01 != @{slop:1.000000, intercept:1.000000}@ then return -1 endi sql select leastsquares(tbcol, 1, 1) as b from $tb interval(1d) print ===> $data01 -if $data01 != @(1.000000, 1.000000)@ then +if $data01 != @{slop:1.000000, intercept:1.000000}@ then return -1 endi print =============== step6 sql select leastsquares(tbcol, 1, 1) as b from $tb where ts < now + 4m interval(1m) print ===> $data01 -if $data01 != @(1.000000, 1.000000)@ then +if $data01 != @{slop:1.000000, intercept:1.000000}@ then return -1 endi print ===> $rows @@ -90,4 +90,4 @@ sql drop database $db sql show databases if $rows != 0 then return -1 -endi \ No newline at end of file +endi diff --git a/tests/script/windows/compute/max.sim b/tests/script/windows/compute/max.sim index 60147358b362dd5f39a99002cdaebb71036cc6a3..a19d122ecdbc1344cd62d558b83c0879d88b2d3b 100644 --- a/tests/script/windows/compute/max.sim +++ b/tests/script/windows/compute/max.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_ma_db $tbPrefix = m_ma_tb diff --git a/tests/script/windows/compute/min.sim b/tests/script/windows/compute/min.sim index 928404babc39201267fc5579b0611be01e1be4b1..216f2061d757ea6388b5c053251c0a0ec29a2721 100644 --- a/tests/script/windows/compute/min.sim +++ b/tests/script/windows/compute/min.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_mi_db $tbPrefix = m_mi_tb diff --git a/tests/script/windows/compute/percentile.sim b/tests/script/windows/compute/percentile.sim index 6068722b549cb213399aae8bc7c48d100e167993..20b2740d6e19c7b2584a0081d321a0a4baa7e0d8 100644 --- a/tests/script/windows/compute/percentile.sim +++ b/tests/script/windows/compute/percentile.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_pe_db $tbPrefix = m_pe_tb diff --git a/tests/script/windows/compute/stddev.sim b/tests/script/windows/compute/stddev.sim index b5ba704bef35a4a9f1b4d00f7b6170e4228cac2b..c02b3e4ab36522de224e630f94b27c73ff329f43 100644 --- a/tests/script/windows/compute/stddev.sim +++ b/tests/script/windows/compute/stddev.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_st_db $tbPrefix = m_st_tb diff --git a/tests/script/windows/compute/sum.sim b/tests/script/windows/compute/sum.sim index 39eb771f34226b3cb54754735aa6381133f5ff3f..04af1d457a4121307618fd6f5950ca04d1f49e83 100644 --- a/tests/script/windows/compute/sum.sim +++ b/tests/script/windows/compute/sum.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_su_db $tbPrefix = m_su_tb diff --git a/tests/script/windows/compute/top.sim b/tests/script/windows/compute/top.sim index b64c24b03f594e11b73a821c275aecbe1cd3aee1..b3c698c0648e8e6267e340b3930cca0193369569 100644 --- a/tests/script/windows/compute/top.sim +++ b/tests/script/windows/compute/top.sim @@ -1,5 +1,5 @@ -sql connect sleep 3000 +sql connect $dbPrefix = m_to_db $tbPrefix = m_to_tb diff --git a/tests/script/windows/db/basic.sim b/tests/script/windows/db/basic.sim index 4222cfe3b2cda0943e6cdd19ab2f7190d2ffad7e..f1e18d15a54df35dd172bc35413912d95f9e9c24 100644 --- a/tests/script/windows/db/basic.sim +++ b/tests/script/windows/db/basic.sim @@ -1,5 +1,6 @@ -sql connect sleep 3000 +sql connect + print ============================ dnode1 start $i = 0 @@ -9,7 +10,7 @@ $db = $dbPrefix . $i $tb = $tbPrefix . $i print =============== step1 -sql create database $db replica 1 days 20 keep 2000 +sql create database $db replica 1 days 20 keep 2000 cache 16 sql show databases print $data00 $data01 $data02 $data03 $data04 $data05 $data06 $data07 if $data00 != $db then @@ -24,10 +25,10 @@ endi if $data04 != 1 then return -1 endi -if $data05 != 20 then +if $data06 != 20 then return -1 endi -if $data07 != 1000 then +if $data08 != 16 then return -1 endi @@ -46,7 +47,7 @@ if $rows != 0 then endi print =============== step4 -sql drop database $db +sql_error drop database $db print =============== step5 sql create database $db replica 1 days 15 keep 1500 @@ -64,14 +65,10 @@ endi if $data04 != 1 then return -1 endi -if $data05 != 15 then +if $data06 != 15 then return -1 endi -if $data07 != 1000 then - return -1 -endi - print =============== step6 sql use $db sql create table $tb (ts timestamp, speed int) @@ -95,9 +92,7 @@ $db = $dbPrefix . $i $tb = $tbPrefix . $i sql create database $db sql use $db -sql create table $tb (ts timestamp, speed int) -x step6 - return -1 -step6: +sql create table $tb (ts timestamp, speed int) print =============== step7 $i = 0 diff --git a/tests/script/windows/db/len.sim b/tests/script/windows/db/len.sim index 32f647617792f3f72cdb6ed630f2db7c9b38f296..f922e7e05a6060890448467f5dbb123b81eb5cb2 100644 --- a/tests/script/windows/db/len.sim +++ b/tests/script/windows/db/len.sim @@ -1,8 +1,8 @@ -sql connect sleep 3000 +sql connect print =============== step1 -sql drop database dd +sql_error drop database dd sql create database -x step1 return -1 @@ -40,7 +40,7 @@ if $rows != 0 then endi print =============== step4 -sql create database a012345678901201234567890120123456789012 -x step4 +sql create database a012345678901201234567890120123456789012a012345678901201234567890120123456789012 -x step4 return -1 step4: sql show databases diff --git a/tests/script/windows/field/binary.sim b/tests/script/windows/field/binary.sim index cd75b6381441402f4997400a1803b4a28fd1bd30..8b86c4dbeaaa02a1a8d31b22bf3d112ca87435e2 100644 --- a/tests/script/windows/field/binary.sim +++ b/tests/script/windows/field/binary.sim @@ -55,17 +55,10 @@ if $rows != 75 then return -1 endi -sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = '1' group by tgcol -x step13 - return -1 -step13: - -sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where ts < now + 4m and tbcol = '1' group by tgcol -x step14 - return -1 -step14: - -sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = '1' interval(1d) group by tgcol -x step15 - return -1 -step15: +print select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = '1' +sql_error select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = '1' group by tgcol +sql_error select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where ts < now + 4m and tbcol = '1' group by tgcol +sql_error select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt where tbcol = '1' interval(1d) group by tgcol #can't filter binary fields diff --git a/tests/script/windows/import/basic.sim b/tests/script/windows/import/basic.sim index 0621721a6b88f3badb46532d1417f185b33cd595..c20378ee88c69c6ded52198339a8fe0bcfc74a9c 100644 --- a/tests/script/windows/import/basic.sim +++ b/tests/script/windows/import/basic.sim @@ -6,111 +6,112 @@ sql use ibadb sql create table tb(ts timestamp, i int) print ================= step1 -sql import into tb values(10000, 10000) + +sql import into tb values(1564641710000, 10000) sql select * from tb; if $rows != 1 then return -1 endi print ================= step2 -sql insert into tb values(8000, 8000) +sql insert into tb values(1564641708000, 8000) sql select * from tb; -if $rows != 1 then +if $rows != 2 then return -1 endi print ================= step3 -sql insert into tb values(20000, 20000) +sql insert into tb values(1564641720000, 20000) sql select * from tb; -if $rows != 2 then +if $rows != 3 then return -1 endi print ================= step4 -sql import into tb values(8000, 8000) -sql import into tb values(15000, 15000) -sql import into tb values(30000, 30000) +sql import into tb values(1564641708000, 8000) +sql import into tb values(1564641715000, 15000) +sql import into tb values(1564641730000, 30000) sql select * from tb; if $rows != 5 then return -1 endi print ================= step5 -sql insert into tb values(8000, 8000) -sql insert into tb values(14000, 14000) -sql insert into tb values(25000, 25000) -sql insert into tb values(40000, 40000) +sql insert into tb values(1564641708000, 8000) +sql insert into tb values(1564641714000, 14000) +sql insert into tb values(1564641725000, 25000) +sql insert into tb values(1564641740000, 40000) sql select * from tb; -if $rows != 6 then +if $rows != 8 then return -1 endi print ================= step6 -sql import into tb values(7000, 7000) -sql import into tb values(12000, 12000) -sql import into tb values(23000, 23000) -sql import into tb values(34000, 34000) -sql import into tb values(50000, 50000) +sql import into tb values(1564641707000, 7000) +sql import into tb values(1564641712000, 12000) +sql import into tb values(1564641723000, 23000) +sql import into tb values(1564641734000, 34000) +sql import into tb values(1564641750000, 50000) sql select * from tb; -if $rows != 11 then +if $rows != 13 then return -1 endi print ================= step7 -sql import into tb values(7001, 7001) -sql import into tb values(12001, 12001) -sql import into tb values(23001, 23001) -sql import into tb values(34001, 34001) -sql import into tb values(50001, 50001) +sql import into tb values(1564641707001, 7001) +sql import into tb values(1564641712001, 12001) +sql import into tb values(1564641723001, 23001) +sql import into tb values(1564641734001, 34001) +sql import into tb values(1564641750001, 50001) sql select * from tb; -if $rows != 16 then +if $rows != 18 then return -1 endi print ================= step8 -sql insert into tb values(8002, 8002) -sql insert into tb values(14002, 14002) -sql insert into tb values(25002, 25002) -sql insert into tb values(200000, 60000) +sql insert into tb values(1564641708002, 8002) +sql insert into tb values(1564641714002, 14002) +sql insert into tb values(1564641725002, 25002) +sql insert into tb values(1564641900000, 200000) sql select * from tb; -if $rows != 17 then +if $rows != 22 then return -1 endi print ================= step9 only insert last one -sql import into tb values(5000, 5000)(18000, 18000)(700000, 700000) +sql import into tb values(1564641705000, 5000)(1564641718000, 18000)(1564642400000, 700000) sql select * from tb; -if $rows != 18 then +if $rows != 25 then return -1 endi print ================= step10 -sql import into tb values(5000, 5000)(18000, 18000)(700000, 70000) +sql import into tb values(1564641705000, 5000)(1564641718000, 18000)(1564642400000, 70000) sql select * from tb; -if $rows != 19 then +if $rows != 25 then return -1 endi print ================= step11 -sql import into tb values(700000, 700000) +sql import into tb values(1564642400000, 700000) sql select * from tb; -if $rows != 19 then +if $rows != 25 then return -1 endi print ================= step12 -sql import into tb values(9527, 9527)(9527, 9528) +sql import into tb values(1564641709527, 9527)(1564641709527, 9528) sql select * from tb; print rows=> $rows -if $rows != 21 then +if $rows != 26 then return -1 endi print ================= step13 -sql import into tb values(9898, 9898)(9897, 9897) +sql import into tb values(1564641709898, 9898)(1564641709897, 9897) sql select * from tb; print rows=> $rows -if $rows != 23 then +if $rows != 28 then return -1 endi diff --git a/tests/script/windows/insert/basic.sim b/tests/script/windows/insert/basic.sim index 42fdf87098f626cd7cbe215c60b064d0ac53ccad..be0980a2d4a60d8c94152f9fd57e6187cb788198 100644 --- a/tests/script/windows/insert/basic.sim +++ b/tests/script/windows/insert/basic.sim @@ -22,20 +22,20 @@ while $x < 10 endw print =============== step 2 -sql insert into $tb values (now - 5m , 10) -x error_insert -sql insert into $tb values (now - 6m , 10) -x error_insert -sql insert into $tb values (now - 7m , 10) -x error_insert -sql insert into $tb values (now - 8m , 10) -x error_insert -error_insert: +sql insert into $tb values (now - 5m , 10) +sql insert into $tb values (now - 6m , 10) +sql insert into $tb values (now - 7m , 10) +sql insert into $tb values (now - 8m , 10) sql select * from $tb print $rows points data are retrieved -if $rows != 10 then +if $rows != 14 then return -1 endi sql drop database $db +sleep 1000 sql show databases if $rows != 0 then return -1 diff --git a/tests/script/windows/insert/query_multi_file.sim b/tests/script/windows/insert/query_multi_file.sim index 3170b435824113bb82f150d8dbba9dc8c3486a91..84c091fb213bfe61184de3e765fba04f5b7dadac 100644 --- a/tests/script/windows/insert/query_multi_file.sim +++ b/tests/script/windows/insert/query_multi_file.sim @@ -27,7 +27,7 @@ $N = 20000 $x = 0 while $x < $N - $ms = $x . m + $ms = $x . s #print insert into $tb values (now + $ms , $x ) sql insert into $tb values (now + $ms , $x ) -x error_insert $x = $x + 1 diff --git a/tests/script/windows/table/binary.sim b/tests/script/windows/table/binary.sim index 1f3df987bb9c33ad1cada10f929f16efe819c449..69354ed5c8ec5f4f938f755c29ce22a7e01bdfbd 100644 --- a/tests/script/windows/table/binary.sim +++ b/tests/script/windows/table/binary.sim @@ -38,7 +38,8 @@ if $data00 != 23456 then endi print =============== step4 -sql insert into $tb values (now+3a, '345678') +sql_error insert into $tb values (now+3a, '345678') +sql insert into $tb values (now+3a, '34567') sql select speed from $tb order by ts desc if $rows != 3 then return -1 diff --git a/tests/script/windows/table/bool.sim b/tests/script/windows/table/bool.sim index afaaf46f518dba54e35510212f8df7d41db9b64d..9e434d801a21fe58d05b83b5e52b5d24581bc29f 100644 --- a/tests/script/windows/table/bool.sim +++ b/tests/script/windows/table/bool.sim @@ -19,7 +19,7 @@ if $rows != 1 then return -1 endi -if $data01 != true then +if $data01 != 1 then return -1 endi @@ -30,7 +30,7 @@ if $rows != 2 then return -1 endi -if $data01 != true then +if $data01 != 1 then return -1 endi @@ -41,7 +41,7 @@ if $rows != 3 then return -1 endi -if $data01 != true then +if $data01 != 1 then return -1 endi @@ -52,7 +52,7 @@ if $rows != 4 then return -1 endi -if $data01 != false then +if $data01 != 0 then return -1 endi @@ -63,7 +63,7 @@ if $rows != 5 then return -1 endi -if $data01 != true then +if $data01 != 1 then return -1 endi @@ -74,7 +74,7 @@ if $rows != 6 then return -1 endi -if $data01 != false then +if $data01 != 0 then return -1 endi diff --git a/tests/script/windows/table/column_value.sim b/tests/script/windows/table/column_value.sim index d3b120d08e8d35a95fbec81875afdc1da6b72b47..9dbaf7ceabef3bfa2d02be8f3cfb004f944d65bd 100644 --- a/tests/script/windows/table/column_value.sim +++ b/tests/script/windows/table/column_value.sim @@ -29,13 +29,12 @@ if $rows != 0 then endi print =============== step2 -sql create table $tb (ts timestamp, speed bigint, v1 binary(1500), v2 binary(1500), v3 binary(1500), v4 binary(500), v5 binary(500)) -x step2 - return -1 -step2: +sql create table $tb (ts timestamp, speed bigint, v1 binary(1500), v2 binary(1500), v3 binary(1500), v4 binary(500), v5 binary(500)) sql show tables -if $rows != 0 then +if $rows != 1 then return -1 endi +sql drop table $tb print =============== step3 sql create table $tb (ts timestamp, speed float, v1 binary(100), v2 binary(100), v3 binary(100), v4 binary(100), v5 binary(100)) @@ -56,11 +55,9 @@ if $rows != 0 then endi print =============== step4 -sql create table $tb (ts timestamp, speed double, v1 binary(1500), v2 binary(1500), v3 binary(1500), v4 binary(500), v5 binary(500)) -x step4 - return -1 -step4: +sql create table $tb (ts timestamp, speed double, v1 binary(1500), v2 binary(1500), v3 binary(1500), v4 binary(500), v5 binary(500)) sql show tables -if $rows != 0 then +if $rows != 1 then return -1 endi diff --git a/tests/script/windows/table/float.sim b/tests/script/windows/table/float.sim index 4188f62166a4899c18cb963c82cb14079047eb4b..57b626f8659aace50f459f8fd185d2c64be2c0df 100644 --- a/tests/script/windows/table/float.sim +++ b/tests/script/windows/table/float.sim @@ -31,7 +31,7 @@ sql select * from $tb order by ts desc if $rows != 1 then return -1 endi -if $data01 != 2.8500 then +if $data01 != 2.85000 then return -1 endi @@ -41,7 +41,7 @@ sql select * from $tb order by ts desc if $rows != 2 then return -1 endi -if $data01 != 3.4000 then +if $data01 != 3.40000 then return -1 endi @@ -54,7 +54,7 @@ sql select * from $tb order by ts desc if $rows != 3 then return -1 endi -if $data01 != 0.0000 then +if $data01 != 0.00000 then return -1 endi @@ -67,7 +67,7 @@ sql select * from $tb order by ts desc if $rows != 4 then return -1 endi -if $data01 != 2.0000 then +if $data01 != 2.00000 then return -1 endi @@ -80,7 +80,7 @@ sql select * from $tb order by ts desc if $rows != 5 then return -1 endi -if $data01 != 2.0000 then +if $data01 != 2.00000 then return -1 endi diff --git a/tests/script/windows/table/table.sim b/tests/script/windows/table/table.sim index fe93fec6cd82f9eff014dd51b269ef170b889393..55be8af85145cd88f84d2d5194bb41d2a9c6afb1 100644 --- a/tests/script/windows/table/table.sim +++ b/tests/script/windows/table/table.sim @@ -58,7 +58,7 @@ sql create table $tb (ts timestamp, val float, val2 float) sql insert into $tb values(now, 5, 5) sql select * from $tb print ==> $data01 $data02 -if $data01 != 5.0000 then +if $data01 != 5.00000 then return -1 endi @@ -162,7 +162,7 @@ endi sql insert into $tb values(now, 5, 5) sql select * from $tb print ==> $data01 $data02 -if $data01 != 5.0000 then +if $data01 != 5.00000 then return -1 endi diff --git a/tests/script/windows/table/table_len.sim b/tests/script/windows/table/table_len.sim index b792044b40c1603a1ede5cf72dc20f6dfe2c198b..cdd1f3173137ad881034feb1267bd08883dd4723 100644 --- a/tests/script/windows/table/table_len.sim +++ b/tests/script/windows/table/table_len.sim @@ -51,7 +51,7 @@ if $rows != 0 then endi print =============== step4 -sql create table ab01234567890123456789a0123456789a0123456789ab01234567890123456789a0123456789a0123456789 (ts timestamp, speed int) -x step4 +sql create table ab01234567890123456789a0123456789a0123456789ab01234567890123456789a0123456789a0123456789ab01234567890123456789a0123456789a0123456789ab01234567890123456789a0123456789a0123456789ab01234567890123456789a0123456789a0123456789ab01234567890123456789a0123456789a0123456789 (ts timestamp, speed int) -x step4 return -1 step4: sql show tables diff --git a/tests/script/windows/tag/add.sim b/tests/script/windows/tag/add.sim index adcff4f62d8551f287d34e626396a7173f112665..2c72d019551d78e4b3eba710621d36d57bf75b76 100644 --- a/tests/script/windows/tag/add.sim +++ b/tests/script/windows/tag/add.sim @@ -30,7 +30,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -40,7 +40,7 @@ endi sql alter table $mt drop tag tgcol2 sql alter table $mt add tag tgcol4 int sql reset query cache -sql alter table $tb set tgcol4 =4 +sql alter table $tb set tag tgcol4 =4 sql reset query cache sql select * from $mt where tgcol4 = 4 @@ -51,7 +51,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 4 then @@ -86,7 +86,7 @@ endi sql alter table $mt drop tag tgcol2 sql alter table $mt add tag tgcol4 tinyint sql reset query cache -sql alter table $tb set tgcol4=4 +sql alter table $tb set tag tgcol4=4 sql reset query cache sql select * from $mt where tgcol4 = 4 @@ -125,28 +125,29 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi sql describe $tb +print sql describe $tb if $data21 != BIGINT then return -1 endi if $data31 != FLOAT then return -1 endi -if $data23 != 1 then +if $data23 != TAG then return -1 endi -if $data33 != 2.000000 then +if $data33 != TAG then return -1 endi sql alter table $mt drop tag tgcol2 sql alter table $mt add tag tgcol4 float sql reset query cache -sql alter table $tb set tgcol4=4 +sql alter table $tb set tag tgcol4=4 sql reset query cache sql select * from $mt where tgcol4 = 4 @@ -160,7 +161,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 4.0000 then +if $data03 != 4.00000 then return -1 endi @@ -192,7 +193,7 @@ endi sql alter table $mt drop tag tgcol2 sql alter table $mt add tag tgcol4 smallint sql reset query cache -sql alter table $tb set tgcol4=4 +sql alter table $tb set tag tgcol4=4 sql reset query cache sql select * from $mt where tgcol4 = 4 @@ -228,7 +229,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -245,9 +246,9 @@ sql alter table $mt add tag tgcol5 binary(10) sql alter table $mt add tag tgcol6 binary(10) sql reset query cache -sql alter table $tb set tgcol4=false -sql alter table $tb set tgcol5=5 -sql alter table $tb set tgcol6=6 +sql alter table $tb set tag tgcol4=false +sql alter table $tb set tag tgcol5=5 +sql alter table $tb set tag tgcol6=6 sql reset query cache sql select * from $mt where tgcol5 = '5' @@ -258,7 +259,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != false then +if $data02 != 0 then return -1 endi if $data03 != 5 then @@ -276,7 +277,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != false then +if $data02 != 0 then return -1 endi if $data03 != 5 then @@ -325,9 +326,9 @@ sql alter table $mt add tag tgcol5 bigint sql alter table $mt add tag tgcol6 tinyint sql reset query cache -sql alter table $tb set tgcol4=4 -sql alter table $tb set tgcol5=5 -sql alter table $tb set tgcol6=6 +sql alter table $tb set tag tgcol4=4 +sql alter table $tb set tag tgcol5=5 +sql alter table $tb set tag tgcol6=6 sql reset query cache sql select * from $mt where tgcol6 = 6 @@ -372,7 +373,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi if $data04 != 3 then @@ -385,9 +386,9 @@ sql alter table $mt drop tag tgcol3 sql alter table $mt add tag tgcol5 binary(17) sql alter table $mt add tag tgcol6 bool sql reset query cache -sql alter table $tb set tgcol4=4 -sql alter table $tb set tgcol5=5 -sql alter table $tb set tgcol6=true +sql alter table $tb set tag tgcol4=4 +sql alter table $tb set tag tgcol5=5 +sql alter table $tb set tag tgcol6=1 sql reset query cache sql select * from $mt where tgcol5 = '5' @@ -405,7 +406,7 @@ endi if $data03 != 5 then return -1 endi -if $data04 != true then +if $data04 != 1 then return -1 endi @@ -447,12 +448,12 @@ sql alter table $mt add tag tgcol5 bool sql alter table $mt add tag tgcol6 float sql reset query cache -sql alter table $tb set tgcol4=4 -sql alter table $tb set tgcol5=true -sql alter table $tb set tgcol6=6 +sql alter table $tb set tag tgcol4=4 +sql alter table $tb set tag tgcol5=1 +sql alter table $tb set tag tgcol6=6 sql reset query cache -sql select * from $mt where tgcol5 = true +sql select * from $mt where tgcol5 = 1 print $data01 $data02 $data03 if $rows != 1 then return -1 @@ -463,10 +464,10 @@ endi if $data02 != 4.000000000 then return -1 endi -if $data03 != true then +if $data03 != 1 then return -1 endi -if $data04 != 6.0000 then +if $data04 != 6.00000 then return -1 endi @@ -516,8 +517,8 @@ sql alter table $mt add tag tgcol4 binary(10) sql alter table $mt add tag tgcol5 bool sql reset query cache -sql alter table $tb set tgcol4=4 -sql alter table $tb set tgcol5=false +sql alter table $tb set tag tgcol4=4 +sql alter table $tb set tag tgcol5=false sql reset query cache sql select * from $mt where tgcol4 = '4' @@ -534,10 +535,10 @@ endi if $data03 != 4 then return -1 endi -if $data04 != false then +if $data04 != 0 then return -1 endi -if $data05 != NULL then +if $data05 != null then return -1 endi @@ -562,7 +563,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -571,7 +572,7 @@ endi if $data04 != 3 then return -1 endi -if $data05 != 4.0000 then +if $data05 != 4.00000 then return -1 endi if $data06 != 5 then @@ -594,11 +595,11 @@ sql alter table $mt add tag tgcol7 bigint sql alter table $mt add tag tgcol8 smallint sql reset query cache -sql alter table $tb set tgcol4=4 -sql alter table $tb set tgcol5=5 -sql alter table $tb set tgcol6=6 -sql alter table $tb set tgcol7=7 -sql alter table $tb set tgcol8=8 +sql alter table $tb set tag tgcol4=4 +sql alter table $tb set tag tgcol5=5 +sql alter table $tb set tag tgcol6=6 +sql alter table $tb set tag tgcol7=7 +sql alter table $tb set tag tgcol8=8 sql reset query cache sql select * from $mt where tgcol5 =5 @@ -609,7 +610,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 4 then @@ -652,13 +653,13 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then return -1 endi -if $data04 != 3.0000 then +if $data04 != 3.00000 then return -1 endi if $data05 != 4.000000000 then @@ -682,12 +683,12 @@ sql alter table $mt add tag tgcol4 binary(10) sql alter table $mt add tag tgcol5 bigint sql reset query cache -sql alter table $tb set tgcol1=false -sql alter table $tb set tgcol2=5 -sql alter table $tb set tgcol3=4 -sql alter table $tb set tgcol4=3 -sql alter table $tb set tgcol5=2 -sql alter table $tb set tgcol6=1 +sql alter table $tb set tag tgcol1=false +sql alter table $tb set tag tgcol2=5 +sql alter table $tb set tag tgcol3=4 +sql alter table $tb set tag tgcol4=3 +sql alter table $tb set tag tgcol5=2 +sql alter table $tb set tag tgcol6=1 sql reset query cache sql select * from $mt where tgcol4 = '3' @@ -698,7 +699,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != false then +if $data02 != 0 then return -1 endi if $data03 != 1 then @@ -779,12 +780,12 @@ sql alter table $mt add tag tgcol4 int sql alter table $mt add tag tgcol6 bigint sql reset query cache -sql alter table $tb set tgcol1=7 -sql alter table $tb set tgcol2=8 -sql alter table $tb set tgcol3=9 -sql alter table $tb set tgcol4=10 -sql alter table $tb set tgcol5=11 -sql alter table $tb set tgcol6=12 +sql alter table $tb set tag tgcol1=7 +sql alter table $tb set tag tgcol2=8 +sql alter table $tb set tag tgcol3=9 +sql alter table $tb set tag tgcol4=10 +sql alter table $tb set tag tgcol5=11 +sql alter table $tb set tag tgcol6=12 sql reset query cache sql select * from $mt where tgcol2 = '8' @@ -826,6 +827,8 @@ sql alter table $mt add tag tgcol3 binary(10) sql alter table $mt add tag tgcol4 int sql alter table $mt add tag tgcol5 bigint sql alter table $mt add tag tgcol6 bigint + +return sql alter table $mt add tag tgcol7 bigint -x step141 return -1 step141: diff --git a/tests/script/windows/tag/change.sim b/tests/script/windows/tag/change.sim index 95a767da496b336d65e140203b51850235ec8433..2901842190ba5acfe3dc85ea50cdb89a589263ea 100644 --- a/tests/script/windows/tag/change.sim +++ b/tests/script/windows/tag/change.sim @@ -30,7 +30,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -43,9 +43,9 @@ step21: sql alter table $mt change tag tgcol1 tgcol2 -x step22 return -1 step22: -sql alter table $mt change tag tgcol1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -x step20 - return -1 -step20: +#sql alter table $mt change tag tgcol1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -x step20 +# return -1 +#step20: sql alter table $mt change tag tgcol1 tgcol3 sql alter table $mt change tag tgcol2 tgcol4 @@ -94,7 +94,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi @@ -191,7 +191,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -206,7 +206,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -278,22 +278,22 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi sql select * from $mt where tgcol4 = 2 print $data01 $data02 $data03 -if $rows != 1 then +if $rows != 1 then return -1 endi -if $data01 != 1 then +if $data01 != 1 then return -1 endi -if $data02 != 1 then +if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi @@ -386,7 +386,7 @@ endi if $data06 != 6 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -413,7 +413,7 @@ endi if $data06 != 6 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -440,7 +440,7 @@ endi if $data06 != 6 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -467,7 +467,7 @@ endi if $data06 != 6 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -494,7 +494,7 @@ endi if $data06 != 6 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -503,4 +503,4 @@ sql drop database $db sql show databases if $rows != 0 then return -1 -endi \ No newline at end of file +endi diff --git a/tests/script/windows/tag/create.sim b/tests/script/windows/tag/create.sim index e7f716316019efc7796ade5dbc3f7d66178b75a5..5beba21727ebf842269aca8b9b760e68bb2470b4 100644 --- a/tests/script/windows/tag/create.sim +++ b/tests/script/windows/tag/create.sim @@ -126,7 +126,8 @@ if $data01 != 1 then return -1 endi sql select * from $mt where tgcol = 0 -if $rows != 0 then +if $rows != 0 then + print expect 0, actual: $rows return -1 endi @@ -176,7 +177,8 @@ sql create table $mt (ts timestamp, tbcol int) TAGS(tgcol bool, tgcol2 bool) sql create table $tb using $mt tags( 1, 2 ) sql insert into $tb values(now, 1) sql select * from $mt where tgcol2 = 2 -if $rows != 1 then +if $rows != 1 then + print expect 1, actual: $rows return -1 endi if $data01 != 1 then @@ -569,7 +571,7 @@ $i = 30 $mt = $mtPrefix . $i $tb = $tbPrefix . $i sql create table $mt (ts timestamp, tbcol int) TAGS(tgcol binary(250), tgcol2 binary(250), tgcol3 binary(30)) -x step30 - return -1 +# return -1 step30: print =============== step31 @@ -577,7 +579,8 @@ $i = 31 $mt = $mtPrefix . $i $tb = $tbPrefix . $i sql create table $mt (ts timestamp, tbcol int) TAGS(tgcol binary(5)) -sql create table $tb using $mt tags('1234567') +sql_error create table $tb using $mt tags('1234567') +sql create table $tb using $mt tags('12345') sql insert into $tb values(now, 1) sql select * from $mt print sql select * from $mt diff --git a/tests/script/windows/tag/delete.sim b/tests/script/windows/tag/delete.sim index 75702fe9eee4eb22a0dc90b17805f01ae182fd8e..e2395c8f976aca6309bf32a273d20f44eb4951b0 100644 --- a/tests/script/windows/tag/delete.sim +++ b/tests/script/windows/tag/delete.sim @@ -30,7 +30,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -79,7 +79,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi @@ -90,7 +90,7 @@ endi if $data31 != FLOAT then return -1 endi -if $data23 != 1 then +if $data23 != TAG then return -1 endi @@ -139,7 +139,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -195,13 +195,13 @@ endi if $data42 != 10 then return -1 endi -if $data23 != 1 then +if $data23 != TAG then return -1 endi -if $data33 != 2 then +if $data33 != TAG then return -1 endi -if $data43 != 3 then +if $data43 != TAG then return -1 endi @@ -225,7 +225,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi if $data04 != 3 then @@ -307,7 +307,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -316,7 +316,7 @@ endi if $data04 != 3 then return -1 endi -if $data05 != 4.0000 then +if $data05 != 4.00000 then return -1 endi if $data06 != 5 then @@ -341,13 +341,13 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then return -1 endi -if $data04 != 3.0000 then +if $data04 != 3.00000 then return -1 endi if $data05 != 4.000000000 then @@ -417,10 +417,10 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi @@ -444,7 +444,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi @@ -468,7 +468,7 @@ endi if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi @@ -492,7 +492,7 @@ endi if $data02 != 1.000000000 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi @@ -513,13 +513,13 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi @@ -546,10 +546,10 @@ endi if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi @@ -576,10 +576,10 @@ endi if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi @@ -606,10 +606,10 @@ endi if $data02 != 1.000000000 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi @@ -636,13 +636,13 @@ endi if $data02 != 1 then return -1 endi -if $data03 != NULL then +if $data03 != null then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi -if $data05 != NULL then +if $data05 != null then return -1 endi @@ -669,19 +669,19 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi -if $data03 != 4.0000 then +if $data03 != 4.00000 then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi -if $data05 != NULL then +if $data05 != null then return -1 endi -if $data06 != NULL then +if $data06 != null then return -1 endi @@ -708,22 +708,22 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 4.000000000 then return -1 endi -if $data04 != NULL then +if $data04 != null then return -1 endi -if $data05 != NULL then +if $data05 != null then return -1 endi -if $data06 != NULL then +if $data06 != null then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -763,13 +763,13 @@ endi if $data04 != 5.000000000 then return -1 endi -if $data05 != NULL then +if $data05 != null then return -1 endi -if $data06 != NULL then +if $data06 != null then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi diff --git a/tests/script/windows/tag/filter.sim b/tests/script/windows/tag/filter.sim index 72a8e39dc8e91e8cb095a600ba8fe4a87d130188..b70e56fdb6cd45b7c1e4e0c20acdf337ba1d320a 100644 --- a/tests/script/windows/tag/filter.sim +++ b/tests/script/windows/tag/filter.sim @@ -85,9 +85,7 @@ sql select count(tgcol), avg(tgcol), sum(tgcol), min(tgcol), max(tgcol), first(t step7: print =============== step8 -sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt group by tbcol -x step8 - return -1 -step8: +sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt group by tbcol print =============== step9 sql select count(tbcol), avg(tbcol), sum(tbcol), min(tbcol), max(tbcol), first(tbcol), last(tbcol) from $mt group by noexist -x step9 @@ -102,9 +100,7 @@ if $data00 != 100 then endi print =============== step11 -sql select count(tbcol) as c from $mt group by tbcol -x step11 - return -1 -step11: +sql select count(tbcol) as c from $mt group by tbcol print =============== step12 sql select count(tbcol) as c from $mt group by noexist -x step12 @@ -121,7 +117,8 @@ endi print =============== step14 sql select count(tbcol) as c from $mt where ts > 1000 group by tgcol print $data00 $data01 $data02 $data03 $data04 $data05 $data06 -if $data00 != 100 then +if $data00 != 100 then + print expect 100, actual $data00 return -1 endi diff --git a/tests/script/windows/tag/set.sim b/tests/script/windows/tag/set.sim index b264164604cf09f37938c51d3186b5f79e9a49f4..580f91cb4945df5952f205e50520345b277d5a86 100644 --- a/tests/script/windows/tag/set.sim +++ b/tests/script/windows/tag/set.sim @@ -30,7 +30,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != true then +if $data02 != 1 then return -1 endi if $data03 != 2 then @@ -40,8 +40,8 @@ endi sql alter table $tb set tag tagcx 1 -x step21 return -1 step21: -sql alter table $tb set tgcol1=false -sql alter table $tb set tgcol2=4 +sql alter table $tb set tag tgcol1=false +sql alter table $tb set tag tgcol2=4 sql reset query cache @@ -53,7 +53,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != false then +if $data02 != 0 then return -1 endi if $data03 != 4 then @@ -68,7 +68,7 @@ endi if $data01 != 1 then return -1 endi -if $data02 != false then +if $data02 != 0 then return -1 endi if $data03 != 4 then @@ -83,10 +83,10 @@ endi if $data31 != INT then return -1 endi -if $data23 != false then +if $data23 != TAG then return -1 endi -if $data33 != 4 then +if $data33 != TAG then return -1 endi @@ -111,8 +111,8 @@ if $data03 != 2 then return -1 endi -sql alter table $tb set tgcol1=3 -sql alter table $tb set tgcol2=4 +sql alter table $tb set tag tgcol1=3 +sql alter table $tb set tag tgcol2=4 sql reset query cache @@ -169,12 +169,12 @@ endi if $data02 != 1 then return -1 endi -if $data03 != 2.0000 then +if $data03 != 2.00000 then return -1 endi -sql alter table $tb set tgcol1=3 -sql alter table $tb set tgcol2=4 +sql alter table $tb set tag tgcol1=3 +sql alter table $tb set tag tgcol2=4 sql reset query cache @@ -189,7 +189,7 @@ endi if $data02 != 3 then return -1 endi -if $data03 != 4.0000 then +if $data03 != 4.00000 then return -1 endi @@ -204,7 +204,7 @@ endi if $data02 != 3 then return -1 endi -if $data03 != 4.0000 then +if $data03 != 4.00000 then return -1 endi @@ -230,8 +230,8 @@ if $data03 != 2 then return -1 endi -sql alter table $tb set tgcol1=3 -sql alter table $tb set tgcol2='4' +sql alter table $tb set tag tgcol1=3 +sql alter table $tb set tag tgcol2='4' sql reset query cache @@ -299,11 +299,11 @@ if $data07 != 6 then endi sql alter table $mt drop tag tgcol3 -sql alter table $tb set tgcol1='7' -sql alter table $tb set tgcol2=8 -sql alter table $tb set tgcol4='9' -sql alter table $tb set tgcol5=10 -sql alter table $tb set tgcol6='11' +sql alter table $tb set tag tgcol1='7' +sql alter table $tb set tag tgcol2=8 +sql alter table $tb set tag tgcol4='9' +sql alter table $tb set tag tgcol5=10 +sql alter table $tb set tag tgcol6='11' sql reset query cache @@ -330,7 +330,7 @@ endi if $data06 != 11 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -357,7 +357,7 @@ endi if $data06 != 11 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -384,7 +384,7 @@ endi if $data06 != 11 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -411,7 +411,7 @@ endi if $data06 != 11 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi @@ -438,7 +438,7 @@ endi if $data06 != 11 then return -1 endi -if $data07 != NULL then +if $data07 != null then return -1 endi diff --git a/tests/script/windows/testSuite.sim b/tests/script/windows/testSuite.sim index 9aa7147ef698d79bbf9fb0af26ddb0bc44b914c4..e372217b620fcf0735e3645fa96872ca11450225 100644 --- a/tests/script/windows/testSuite.sim +++ b/tests/script/windows/testSuite.sim @@ -1,97 +1,93 @@ -run windows/account/user_create.sim -run windows/account/user_len.sim - -run windows/db/len.sim - -run windows/table/table.sim -run windows/table/table_len.sim -run windows/table/column_num.sim -run windows/table/column_name.sim -run windows/table/column_value.sim -run windows/table/binary.sim -run windows/table/bool.sim -run windows/table/double.sim -run windows/table/float.sim -run windows/table/db.table.sim - -run windows/import/basic.sim - run windows/alter/table.sim run windows/alter/metrics.sim -run windows/compute/count.sim run windows/compute/avg.sim -run windows/compute/sum.sim -run windows/compute/min.sim -run windows/compute/max.sim +run windows/compute/bottom.sim +run windows/compute/count.sim +run windows/compute/diff.sim run windows/compute/first.sim +run windows/compute/interval.sim run windows/compute/last.sim +run windows/compute/leastsquare.sim +run windows/compute/max.sim +run windows/compute/min.sim +run windows/compute/percentile.sim run windows/compute/stddev.sim -#run windows/compute/leastsquare.sim +run windows/compute/sum.sim run windows/compute/top.sim -run windows/compute/bottom.sim -run windows/compute/percentile.sim -run windows/compute/diff.sim -run windows/compute/interval.sim - -run windows/field/single.sim -run windows/field/bool.sim -run windows/field/smallint.sim -run windows/field/tinyint.sim -run windows/field/int.sim -run windows/field/bigint.sim -run windows/field/float.sim -run windows/field/double.sim -run windows/field/binary.sim + +run windows/db/basic.sim +run windows/db/len.sim + run windows/field/2.sim run windows/field/3.sim run windows/field/4.sim run windows/field/5.sim run windows/field/6.sim +run windows/field/bigint.sim +run windows/field/binary.sim +run windows/field/bool.sim +run windows/field/double.sim +run windows/field/float.sim +run windows/field/int.sim +run windows/field/single.sim +run windows/field/smallint.sim +run windows/field/tinyint.sim + +run windows/import/basic.sim + +run windows/insert/basic.sim +run windows/insert/query_block1_file.sim +run windows/insert/query_block1_memory.sim +run windows/insert/query_block2_file.sim +run windows/insert/query_block2_memory.sim +run windows/insert/query_file_memory.sim +run windows/insert/query_multi_file.sim + +run windows/table/binary.sim +run windows/table/bool.sim +run windows/table/column_num.sim +run windows/table/column_name.sim +run windows/table/column_value.sim +run windows/table/db.table.sim +run windows/table/double.sim +run windows/table/float.sim +run windows/table/table_len.sim +run windows/table/table.sim -run windows/tag/filter.sim -run windows/tag/column.sim -run windows/tag/bool.sim -run windows/tag/smallint.sim -run windows/tag/tinyint.sim -run windows/tag/int.sim -run windows/tag/bigint.sim -run windows/tag/float.sim -run windows/tag/double.sim -run windows/tag/binary.sim -run windows/tag/bool_int.sim -run windows/tag/bool_binary.sim -run windows/tag/int_float.sim -run windows/tag/int_binary.sim -run windows/tag/binary_binary.sim run windows/tag/3.sim run windows/tag/4.sim run windows/tag/5.sim run windows/tag/6.sim +run windows/tag/add.sim +run windows/tag/bigint.sim +run windows/tag/binary_binary.sim +run windows/tag/binary.sim +run windows/tag/bool_binary.sim +run windows/tag/bool_int.sim +run windows/tag/bool.sim +run windows/tag/change.sim +run windows/tag/column.sim run windows/tag/create.sim -#run windows/tag/delete.sim - -#run windows/tag/set.sim -#run windows/tag/add.sim +run windows/tag/delete.sim +run windows/tag/double.sim +run windows/tag/filter.sim +run windows/tag/float.sim +run windows/tag/int_binary.sim +run windows/tag/int_float.sim +run windows/tag/int.sim +run windows/tag/set.sim +run windows/tag/smallint.sim +run windows/tag/tinyint.sim -run windows/vector/single.sim -run windows/vector/multi.sim -run windows/vector/table_query.sim -run windows/vector/table_time.sim -run windows/vector/table_field.sim -run windows/vector/table_mix.sim +run windows/vector/metrics_field.sim +run windows/vector/metrics_mix.sim run windows/vector/metrics_query.sim run windows/vector/metrics_tag.sim run windows/vector/metrics_time.sim -run windows/vector/metrics_field.sim -run windows/vector/metrics_mix.sim - -run windows/insert/basic.sim -run windows/insert/query_block1_memory.sim -run windows/insert/query_block2_memory.sim -run windows/insert/query_block1_file.sim -#run windows/insert/query_block2_file.sim -#run windows/insert/query_file_memory.sim -#run windows/insert/query_multi_file.sim - -run windows/tag/change.sim +run windows/vector/multi.sim +run windows/vector/single.sim +run windows/vector/table_field.sim +run windows/vector/table_mix.sim +run windows/vector/table_query.sim +run windows/vector/table_time.sim diff --git a/tests/script/windows/vector/multi.sim b/tests/script/windows/vector/multi.sim index 969ba5aa19cdf9e3fbc4ce125efc652310eb9266..adcc94db3be4976580e6a7c607d8ebcb613db88c 100644 --- a/tests/script/windows/vector/multi.sim +++ b/tests/script/windows/vector/multi.sim @@ -200,7 +200,6 @@ sql select a + f from $tb where g = 2 and ts > now + 4m order by ts asc -x step return -1 step74: - print =============== clear sql drop database $db sql show databases diff --git a/tests/test/c/CMakeLists.txt b/tests/test/c/CMakeLists.txt index 4736c1ebed80d899b4b31d4dce395b7cc278761a..cc8bc78e33ac47a49b34e3914484e2feb0644616 100644 --- a/tests/test/c/CMakeLists.txt +++ b/tests/test/c/CMakeLists.txt @@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) #add_executable(insertPerTable insertPerTable.c) #target_link_libraries(insertPerTable taos_static pthread) diff --git a/tests/tsim/CMakeLists.txt b/tests/tsim/CMakeLists.txt index 0a11a8f14ed0a8855471a5875b2ba8668c5410cc..50b42941aff12ec6762b2da904675e6fa0183cad 100644 --- a/tests/tsim/CMakeLists.txt +++ b/tests/tsim/CMakeLists.txt @@ -1,17 +1,9 @@ PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(inc) -IF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) -ENDIF () - AUX_SOURCE_DIRECTORY(src SRC) ADD_EXECUTABLE(tsim ${SRC}) TARGET_LINK_LIBRARIES(tsim taos_static trpc tutil pthread cJson) diff --git a/tests/tsim/src/simExe.c b/tests/tsim/src/simExe.c index 1078b329810f902e4884810a2572f8b760b0263f..8bc9a76545d749b698d9dcac5bc8d2a48aa9b103 100644 --- a/tests/tsim/src/simExe.c +++ b/tests/tsim/src/simExe.c @@ -313,7 +313,9 @@ bool simExecuteSystemCmd(SScript *script, char *option) { simError("script:%s, failed to execute %s , code %d, errno:%d %s, repeatTimes:%d", script->fileName, buf, code, errno, strerror(errno), repeatTimes); taosMsleep(1000); +#ifdef LINUX signal(SIGCHLD, SIG_DFL); +#endif if (repeatTimes++ >= 10) { exit(0); } @@ -418,14 +420,14 @@ void simVisuallizeOption(SScript *script, char *src, char *dst) { var = strchr(src, '$'); if (var == NULL) break; if (var && ((var - src - 1) > 0) && *(var - 1) == '\\') { - srcLen = var - src - 1; + srcLen = (int)(var - src - 1); memcpy(dst + dstLen, src, srcLen); dstLen += srcLen; src = var; break; } - srcLen = var - src; + srcLen = (int)(var - src); memcpy(dst + dstLen, src, srcLen); dstLen += srcLen; @@ -433,7 +435,7 @@ void simVisuallizeOption(SScript *script, char *src, char *dst) { value = simGetVariable(script, token, tokenLen); strcpy(dst + dstLen, value); - dstLen += strlen(value); + dstLen += (int)strlen(value); } strcpy(dst + dstLen, src); @@ -455,9 +457,9 @@ void simCloseNativeConnect(SScript *script) { void simCloseTaosdConnect(SScript *script) { if (simAsyncQuery) { - return simCloseRestFulConnect(script); + simCloseRestFulConnect(script); } else { - return simCloseNativeConnect(script); + simCloseNativeConnect(script); } } // {"status":"succ","code":0,"desc":"/KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04"} @@ -575,7 +577,7 @@ int simExecuteRestFulCommand(SScript *script, char *command) { while (!feof(fp)) { int availSize = mallocSize - alreadyReadSize; - int len = fread(content + alreadyReadSize, 1, availSize, fp); + int len = (int)fread(content + alreadyReadSize, 1, availSize, fp); if (len >= availSize) { alreadyReadSize += len; mallocSize *= 2; diff --git a/tests/tsim/src/simParse.c b/tests/tsim/src/simParse.c index 2528fde9f5cfdd7cbbd390a8bf46b33baa9bad1e..f201f149a14381cb1f068bc3132ab14feafd637c 100644 --- a/tests/tsim/src/simParse.c +++ b/tests/tsim/src/simParse.c @@ -105,7 +105,7 @@ void simAddCmdIntoHash(SCommand *pCmd) { int hash; SCommand *node; - hash = simHashCmd(pCmd->name, strlen(pCmd->name)); + hash = simHashCmd(pCmd->name, (int)strlen(pCmd->name)); node = cmdHashList[hash]; pCmd->next = node; cmdHashList[hash] = pCmd; @@ -199,7 +199,7 @@ SScript *simParseScript(char *fileName) { if (fgets(buffer, sizeof(buffer), fd) == NULL) continue; lineNum++; - int cmdlen = strlen(buffer); + int cmdlen = (int)strlen(buffer); if (buffer[cmdlen - 1] == '\r' || buffer[cmdlen - 1] == '\n') buffer[cmdlen - 1] = 0; rest = buffer; @@ -294,10 +294,10 @@ int simCheckExpression(char *exp) { rest = paGetToken(rest, &op, &opLen); - if (opLen == 0) return rest - exp; + if (opLen == 0) return (int)(rest - exp); /* if it is key word "then" */ - if (strncmp(op, "then", 4) == 0) return op - exp; + if (strncmp(op, "then", 4) == 0) return (int)(op - exp); rest = paGetToken(rest, &op2, &op2Len); if (op2Len == 0) { @@ -312,7 +312,7 @@ int simCheckExpression(char *exp) { if (op[0] == '+' || op[0] == '-' || op[0] == '*' || op[0] == '/' || op[0] == '.') { - return rest - exp; + return (int)(rest - exp); } return -1; @@ -655,7 +655,7 @@ bool simParsePrintCmd(char *rest, SCommand *pCmd, int lineNum) { cmdLine[numOfLines].cmdno = SIM_CMD_PRINT; cmdLine[numOfLines].lineNum = lineNum; cmdLine[numOfLines].optionOffset = optionOffset; - expLen = strlen(rest); + expLen = (int)strlen(rest); memcpy(optionBuffer + optionOffset, rest, expLen); optionOffset += expLen + 1; *(optionBuffer + optionOffset - 1) = 0; @@ -690,7 +690,7 @@ bool simParseSqlCmd(char *rest, SCommand *pCmd, int lineNum) { cmdLine[numOfLines].cmdno = SIM_CMD_SQL; cmdLine[numOfLines].lineNum = lineNum; cmdLine[numOfLines].optionOffset = optionOffset; - expLen = strlen(rest); + expLen = (int)strlen(rest); memcpy(optionBuffer + optionOffset, rest, expLen); optionOffset += expLen + 1; *(optionBuffer + optionOffset - 1) = 0; @@ -706,7 +706,7 @@ bool simParseSqlErrorCmd(char *rest, SCommand *pCmd, int lineNum) { cmdLine[numOfLines].cmdno = SIM_CMD_SQL_ERROR; cmdLine[numOfLines].lineNum = lineNum; cmdLine[numOfLines].optionOffset = optionOffset; - expLen = strlen(rest); + expLen = (int)strlen(rest); memcpy(optionBuffer + optionOffset, rest, expLen); optionOffset += expLen + 1; *(optionBuffer + optionOffset - 1) = 0; @@ -728,7 +728,7 @@ bool simParseSystemCmd(char *rest, SCommand *pCmd, int lineNum) { cmdLine[numOfLines].cmdno = SIM_CMD_SYSTEM; cmdLine[numOfLines].lineNum = lineNum; cmdLine[numOfLines].optionOffset = optionOffset; - expLen = strlen(rest); + expLen = (int)strlen(rest); memcpy(optionBuffer + optionOffset, rest, expLen); optionOffset += expLen + 1; *(optionBuffer + optionOffset - 1) = 0; @@ -840,14 +840,14 @@ void simInitsimCmdList() { cmdno = SIM_CMD_EXP; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "exp"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = NULL; simCmdList[cmdno].executeCmd = simExecuteExpCmd; cmdno = SIM_CMD_IF; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "if"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseIfCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -855,7 +855,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_ELIF; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "elif"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseElifCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -863,7 +863,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_ELSE; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "else"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseElseCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -871,7 +871,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_ENDI; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "endi"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseEndiCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -879,7 +879,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_WHILE; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "while"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseWhileCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -887,7 +887,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_ENDW; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "endw"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseEndwCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -895,7 +895,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SWITCH; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "switch"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSwitchCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -903,7 +903,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_CASE; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "case"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseCaseCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -911,7 +911,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_DEFAULT; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "default"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseDefaultCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -919,7 +919,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_BREAK; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "break"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseBreakCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -927,7 +927,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_CONTINUE; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "continue"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseContinueCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -935,7 +935,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_ENDS; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "ends"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseEndsCmd; simCmdList[cmdno].executeCmd = NULL; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -943,7 +943,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SLEEP; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "sleep"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSleepCmd; simCmdList[cmdno].executeCmd = simExecuteSleepCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -951,7 +951,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_GOTO; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "goto"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseGotoCmd; simCmdList[cmdno].executeCmd = simExecuteGotoCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -959,7 +959,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_RUN; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "run"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseRunCmd; simCmdList[cmdno].executeCmd = simExecuteRunCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -967,7 +967,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_RUN_BACK; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "run_back"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseRunBackCmd; simCmdList[cmdno].executeCmd = simExecuteRunBackCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -975,7 +975,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SYSTEM; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "system"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSystemCmd; simCmdList[cmdno].executeCmd = simExecuteSystemCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -983,7 +983,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SYSTEM_CONTENT; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "system_content"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSystemContentCmd; simCmdList[cmdno].executeCmd = simExecuteSystemContentCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -991,7 +991,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_PRINT; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "print"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParsePrintCmd; simCmdList[cmdno].executeCmd = simExecutePrintCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -999,7 +999,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SQL; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "sql"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSqlCmd; simCmdList[cmdno].executeCmd = simExecuteSqlCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -1007,7 +1007,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SQL_ERROR; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "sql_error"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSqlErrorCmd; simCmdList[cmdno].executeCmd = simExecuteSqlErrorCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -1015,7 +1015,7 @@ void simInitsimCmdList() { cmdno = SIM_CMD_SQL_SLOW; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "sql_slow"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseSqlSlowCmd; simCmdList[cmdno].executeCmd = simExecuteSqlSlowCmd; simAddCmdIntoHash(&(simCmdList[cmdno])); @@ -1024,14 +1024,14 @@ void simInitsimCmdList() { cmdno = SIM_CMD_TEST; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "test"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = NULL; simCmdList[cmdno].executeCmd = simExecuteTestCmd; cmdno = SIM_CMD_RETURN; simCmdList[cmdno].cmdno = cmdno; strcpy(simCmdList[cmdno].name, "return"); - simCmdList[cmdno].nlen = strlen(simCmdList[cmdno].name); + simCmdList[cmdno].nlen = (int)strlen(simCmdList[cmdno].name); simCmdList[cmdno].parseCmd = simParseReturnCmd; simCmdList[cmdno].executeCmd = simExecuteReturnCmd; simAddCmdIntoHash(&(simCmdList[cmdno]));