提交 c0a171b1 编写于 作者: S Shengliang Guan

[TD-10430] adjust os module

上级 e8890087
......@@ -42,6 +42,8 @@ execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/deps/deps-download")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -gdwarf-2 -msse4.2 -mfma")
# deps
add_subdirectory(deps)
......
......@@ -31,21 +31,23 @@ typedef void TAOS_SUB;
typedef void **TAOS_ROW;
// Data type definition
#define TSDB_DATA_TYPE_NULL 0 // 1 bytes
#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes
#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte
#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes
#define TSDB_DATA_TYPE_INT 4 // 4 bytes
#define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes
#define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes
#define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes
#define TSDB_DATA_TYPE_BINARY 8 // string
#define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes
#define TSDB_DATA_TYPE_NCHAR 10 // unicode string
#define TSDB_DATA_TYPE_UTINYINT 11 // 1 byte
#define TSDB_DATA_TYPE_USMALLINT 12 // 2 bytes
#define TSDB_DATA_TYPE_UINT 13 // 4 bytes
#define TSDB_DATA_TYPE_UBIGINT 14 // 8 bytes
#ifndef TSDB_DATA_TYPE_NULL
#define TSDB_DATA_TYPE_NULL 0 // 1 bytes
#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes
#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte
#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes
#define TSDB_DATA_TYPE_INT 4 // 4 bytes
#define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes
#define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes
#define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes
#define TSDB_DATA_TYPE_BINARY 8 // string
#define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes
#define TSDB_DATA_TYPE_NCHAR 10 // unicode string
#define TSDB_DATA_TYPE_UTINYINT 11 // 1 byte
#define TSDB_DATA_TYPE_USMALLINT 12 // 2 bytes
#define TSDB_DATA_TYPE_UINT 13 // 4 bytes
#define TSDB_DATA_TYPE_UBIGINT 14 // 8 bytes
#endif
typedef enum {
TSDB_OPTION_LOCALE,
......
......@@ -13,389 +13,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TAOS_DEF_H
#define TDENGINE_TAOS_DEF_H
#ifndef _TD_COMMON_TAOS_DEF_H
#define _TD_COMMON_TAOS_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include "tdef.h"
#include "taos.h"
#define TSDB__packed
#ifdef TSKEY32
#define TSKEY int32_t;
#else
#define TSKEY int64_t
#endif
#define TSWINDOW_INITIALIZER ((STimeWindow) {INT64_MIN, INT64_MAX})
#define TSWINDOW_DESC_INITIALIZER ((STimeWindow) {INT64_MAX, INT64_MIN})
#define IS_TSWINDOW_SPECIFIED(win) (((win).skey != INT64_MIN) || ((win).ekey != INT64_MAX))
#define TSKEY_INITIAL_VAL INT64_MIN
// Bytes for each type.
extern const int32_t TYPE_BYTES[15];
#define TSDB_KEYSIZE sizeof(TSKEY)
#if LINUX
#define TSDB_NCHAR_SIZE sizeof(wchar_t)
#else
#define TSDB_NCHAR_SIZE sizeof(int32_t)
#endif
// NULL definition
#define TSDB_DATA_BOOL_NULL 0x02
#define TSDB_DATA_TINYINT_NULL 0x80
#define TSDB_DATA_SMALLINT_NULL 0x8000
#define TSDB_DATA_INT_NULL 0x80000000L
#define TSDB_DATA_BIGINT_NULL 0x8000000000000000L
#define TSDB_DATA_TIMESTAMP_NULL TSDB_DATA_BIGINT_NULL
#define TSDB_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000L // an NAN
#define TSDB_DATA_NCHAR_NULL 0xFFFFFFFF
#define TSDB_DATA_BINARY_NULL 0xFF
#define TSDB_DATA_UTINYINT_NULL 0xFF
#define TSDB_DATA_USMALLINT_NULL 0xFFFF
#define TSDB_DATA_UINT_NULL 0xFFFFFFFF
#define TSDB_DATA_UBIGINT_NULL 0xFFFFFFFFFFFFFFFFL
#define TSDB_DATA_NULL_STR "NULL"
#define TSDB_DATA_NULL_STR_L "null"
#define TSDB_DEFAULT_USER "root"
#ifdef _TD_POWER_
#define TSDB_DEFAULT_PASS "powerdb"
#elif (_TD_TQ_ == true)
#define TSDB_DEFAULT_PASS "tqueue"
#elif (_TD_PRO_ == true)
#define TSDB_DEFAULT_PASS "prodb"
#else
#define TSDB_DEFAULT_PASS "taosdata"
#endif
#define SHELL_MAX_PASSWORD_LEN 20
#define TSDB_TRUE 1
#define TSDB_FALSE 0
#define TSDB_OK 0
#define TSDB_ERR -1
#define TS_PATH_DELIMITER "."
#define TSDB_TIME_PRECISION_MILLI 0
#define TSDB_TIME_PRECISION_MICRO 1
#define TSDB_TIME_PRECISION_NANO 2
#define TSDB_TIME_PRECISION_MILLI_STR "ms"
#define TSDB_TIME_PRECISION_MICRO_STR "us"
#define TSDB_TIME_PRECISION_NANO_STR "ns"
#define TSDB_TICK_PER_SECOND(precision) ((int64_t)((precision)==TSDB_TIME_PRECISION_MILLI ? 1e3L : ((precision)==TSDB_TIME_PRECISION_MICRO ? 1e6L : 1e9L)))
#define T_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#define T_APPEND_MEMBER(dst, ptr, type, member) \
do {\
memcpy((void *)(dst), (void *)(&((ptr)->member)), T_MEMBER_SIZE(type, member));\
dst = (void *)((char *)(dst) + T_MEMBER_SIZE(type, member));\
} while(0)
#define T_READ_MEMBER(src, type, target) \
do { \
(target) = *(type *)(src); \
(src) = (void *)((char *)src + sizeof(type));\
} while(0)
#define GET_INT8_VAL(x) (*(int8_t *)(x))
#define GET_INT16_VAL(x) (*(int16_t *)(x))
#define GET_INT32_VAL(x) (*(int32_t *)(x))
#define GET_INT64_VAL(x) (*(int64_t *)(x))
#define GET_UINT8_VAL(x) (*(uint8_t*) (x))
#define GET_UINT16_VAL(x) (*(uint16_t *)(x))
#define GET_UINT32_VAL(x) (*(uint32_t *)(x))
#define GET_UINT64_VAL(x) (*(uint64_t *)(x))
#ifdef _TD_ARM_32
float taos_align_get_float(const char* pBuf);
double taos_align_get_double(const char* pBuf);
#define GET_FLOAT_VAL(x) taos_align_get_float(x)
#define GET_DOUBLE_VAL(x) taos_align_get_double(x)
#define SET_FLOAT_VAL(x, y) { float z = (float)(y); (*(int32_t*) x = *(int32_t*)(&z)); }
#define SET_DOUBLE_VAL(x, y) { double z = (double)(y); (*(int64_t*) x = *(int64_t*)(&z)); }
#define SET_FLOAT_PTR(x, y) { (*(int32_t*) x = *(int32_t*)y); }
#define SET_DOUBLE_PTR(x, y) { (*(int64_t*) x = *(int64_t*)y); }
#else
#define GET_FLOAT_VAL(x) (*(float *)(x))
#define GET_DOUBLE_VAL(x) (*(double *)(x))
#define SET_FLOAT_VAL(x, y) { (*(float *)(x)) = (float)(y); }
#define SET_DOUBLE_VAL(x, y) { (*(double *)(x)) = (double)(y); }
#define SET_FLOAT_PTR(x, y) { (*(float *)(x)) = (*(float *)(y)); }
#define SET_DOUBLE_PTR(x, y) { (*(double *)(x)) = (*(double *)(y)); }
#endif
// TODO: check if below is necessary
#define TSDB_RELATION_INVALID 0
#define TSDB_RELATION_LESS 1
#define TSDB_RELATION_GREATER 2
#define TSDB_RELATION_EQUAL 3
#define TSDB_RELATION_LESS_EQUAL 4
#define TSDB_RELATION_GREATER_EQUAL 5
#define TSDB_RELATION_NOT_EQUAL 6
#define TSDB_RELATION_LIKE 7
#define TSDB_RELATION_ISNULL 8
#define TSDB_RELATION_NOTNULL 9
#define TSDB_RELATION_IN 10
#define TSDB_RELATION_AND 11
#define TSDB_RELATION_OR 12
#define TSDB_RELATION_NOT 13
#define TSDB_RELATION_MATCH 14
#define TSDB_RELATION_NMATCH 15
#define TSDB_BINARY_OP_ADD 30
#define TSDB_BINARY_OP_SUBTRACT 31
#define TSDB_BINARY_OP_MULTIPLY 32
#define TSDB_BINARY_OP_DIVIDE 33
#define TSDB_BINARY_OP_REMAINDER 34
#define IS_RELATION_OPTR(op) (((op) >= TSDB_RELATION_LESS) && ((op) < TSDB_RELATION_IN))
#define IS_ARITHMETIC_OPTR(op) (((op) >= TSDB_BINARY_OP_ADD) && ((op) <= TSDB_BINARY_OP_REMAINDER))
#define TS_PATH_DELIMITER_LEN 1
#define TSDB_UNI_LEN 24
#define TSDB_USER_LEN TSDB_UNI_LEN
// ACCOUNT is a 32 bit positive integer
// this is the length of its string representation, including the terminator zero
#define TSDB_ACCT_ID_LEN 11
#define TSDB_MAX_COLUMNS 4096
#define TSDB_MIN_COLUMNS 2 //PRIMARY COLUMN(timestamp) + other columns
#define TSDB_NODE_NAME_LEN 64
#define TSDB_TABLE_NAME_LEN 193 // it is a null-terminated string
#define TSDB_DB_NAME_LEN 33
#define TSDB_FUNC_NAME_LEN 65
#define TSDB_FUNC_CODE_LEN (65535 - 512)
#define TSDB_FUNC_BUF_SIZE 512
#define TSDB_TYPE_STR_MAX_LEN 32
#define TSDB_TABLE_FNAME_LEN (TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN + TSDB_TABLE_NAME_LEN)
#define TSDB_COL_NAME_LEN 65
#define TSDB_MAX_SAVED_SQL_LEN TSDB_MAX_COLUMNS * 64
#define TSDB_MAX_SQL_LEN TSDB_PAYLOAD_SIZE
#define TSDB_MAX_SQL_SHOW_LEN 512
#define TSDB_MAX_ALLOWED_SQL_LEN (1*1024*1024u) // sql length should be less than 1mb
#define TSDB_APPNAME_LEN TSDB_UNI_LEN
/**
* In some scenarios uint16_t (0~65535) is used to store the row len.
* - Firstly, we use 65531(65535 - 4), as the SDataRow/SKVRow contains 4 bits header.
* - Secondly, if all cols are VarDataT type except primary key, we need 4 bits to store the offset, thus
* the final value is 65531-(4096-1)*4 = 49151.
*/
#define TSDB_MAX_BYTES_PER_ROW 49151
#define TSDB_MAX_TAGS_LEN 16384
#define TSDB_MAX_TAGS 128
#define TSDB_MAX_TAG_CONDITIONS 1024
#define TSDB_AUTH_LEN 16
#define TSDB_KEY_LEN 16
#define TSDB_VERSION_LEN 12
#define TSDB_LOCALE_LEN 64
#define TSDB_TIMEZONE_LEN 96
#define TSDB_LABEL_LEN 8
#define TSDB_CLUSTER_ID_LEN 40
#define TSDB_FQDN_LEN 128
#define TSDB_EP_LEN (TSDB_FQDN_LEN+6)
#define TSDB_IPv4ADDR_LEN 16
#define TSDB_FILENAME_LEN 128
#define TSDB_SHOW_SQL_LEN 512
#define TSDB_SHOW_SUBQUERY_LEN 1000
#define TSDB_SLOW_QUERY_SQL_LEN 512
#define TSDB_STEP_NAME_LEN 32
#define TSDB_STEP_DESC_LEN 128
#define TSDB_MQTT_HOSTNAME_LEN 64
#define TSDB_MQTT_PORT_LEN 8
#define TSDB_MQTT_USER_LEN 24
#define TSDB_MQTT_PASS_LEN 24
#define TSDB_MQTT_TOPIC_LEN 64
#define TSDB_MQTT_CLIENT_ID_LEN 32
#define TSDB_DB_TYPE_DEFAULT 0
#define TSDB_DB_TYPE_TOPIC 1
#define TSDB_DEFAULT_PKT_SIZE 65480 //same as RPC_MAX_UDP_SIZE
#define TSDB_PAYLOAD_SIZE TSDB_DEFAULT_PKT_SIZE
#define TSDB_DEFAULT_PAYLOAD_SIZE 5120 // default payload size, greater than PATH_MAX value
#define TSDB_EXTRA_PAYLOAD_SIZE 128 // extra bytes for auth
#define TSDB_CQ_SQL_SIZE 1024
#define TSDB_MIN_VNODES 64
#define TSDB_MAX_VNODES 2048
#define TSDB_MIN_VNODES_PER_DB 2
#define TSDB_MAX_VNODES_PER_DB 64
#define TSDB_DNODE_ROLE_ANY 0
#define TSDB_DNODE_ROLE_MGMT 1
#define TSDB_DNODE_ROLE_VNODE 2
#define TSDB_MAX_REPLICA 5
#define TSDB_TBNAME_COLUMN_INDEX (-1)
#define TSDB_UD_COLUMN_INDEX (-1000)
#define TSDB_RES_COL_ID (-5000)
#define TSDB_MULTI_TABLEMETA_MAX_NUM 100000 // maximum batch size allowed to load table meta
#define TSDB_MIN_CACHE_BLOCK_SIZE 1
#define TSDB_MAX_CACHE_BLOCK_SIZE 128 // 128MB for each vnode
#define TSDB_DEFAULT_CACHE_BLOCK_SIZE 16
#define TSDB_MIN_TOTAL_BLOCKS 3
#define TSDB_MAX_TOTAL_BLOCKS 10000
#define TSDB_DEFAULT_TOTAL_BLOCKS 6
#define TSDB_MIN_TABLES 4
#define TSDB_MAX_TABLES 10000000
#define TSDB_DEFAULT_TABLES 1000000
#define TSDB_TABLES_STEP 1000
#define TSDB_META_COMPACT_RATIO 0 // disable tsdb meta compact by default
#define TSDB_MIN_DAYS_PER_FILE 1
#define TSDB_MAX_DAYS_PER_FILE 3650
#define TSDB_DEFAULT_DAYS_PER_FILE 10
#define TSDB_MIN_KEEP 1 // data in db to be reserved.
#define TSDB_MAX_KEEP 365000 // data in db to be reserved.
#define TSDB_DEFAULT_KEEP 3650 // ten years
#define TSDB_DEFAULT_MIN_ROW_FBLOCK 100
#define TSDB_MIN_MIN_ROW_FBLOCK 10
#define TSDB_MAX_MIN_ROW_FBLOCK 1000
#define TSDB_DEFAULT_MAX_ROW_FBLOCK 4096
#define TSDB_MIN_MAX_ROW_FBLOCK 200
#define TSDB_MAX_MAX_ROW_FBLOCK 10000
#define TSDB_MIN_COMMIT_TIME 30
#define TSDB_MAX_COMMIT_TIME 40960
#define TSDB_DEFAULT_COMMIT_TIME 3600
#define TSDB_MIN_PRECISION TSDB_TIME_PRECISION_MILLI
#define TSDB_MAX_PRECISION TSDB_TIME_PRECISION_NANO
#define TSDB_DEFAULT_PRECISION TSDB_TIME_PRECISION_MILLI
#define TSDB_MIN_COMP_LEVEL 0
#define TSDB_MAX_COMP_LEVEL 2
#define TSDB_DEFAULT_COMP_LEVEL 2
#define TSDB_MIN_WAL_LEVEL 0
#define TSDB_MAX_WAL_LEVEL 2
#define TSDB_DEFAULT_WAL_LEVEL 1
#define TSDB_MIN_DB_UPDATE 0
#define TSDB_MAX_DB_UPDATE 2
#define TSDB_DEFAULT_DB_UPDATE_OPTION 0
#define TSDB_MIN_DB_CACHE_LAST_ROW 0
#define TSDB_MAX_DB_CACHE_LAST_ROW 3
#define TSDB_DEFAULT_CACHE_LAST_ROW 0
#define TSDB_MIN_FSYNC_PERIOD 0
#define TSDB_MAX_FSYNC_PERIOD 180000 // millisecond
#define TSDB_DEFAULT_FSYNC_PERIOD 3000 // three second
#define TSDB_MIN_DB_REPLICA_OPTION 1
#define TSDB_MAX_DB_REPLICA_OPTION 3
#define TSDB_DEFAULT_DB_REPLICA_OPTION 1
#define TSDB_MIN_DB_PARTITON_OPTION 0
#define TSDB_MAX_DB_PARTITON_OPTION 1000
#define TSDB_DEFAULT_DB_PARTITON_OPTION 4
#define TSDB_MIN_DB_QUORUM_OPTION 1
#define TSDB_MAX_DB_QUORUM_OPTION 2
#define TSDB_DEFAULT_DB_QUORUM_OPTION 1
#define TSDB_MAX_JOIN_TABLE_NUM 10
#define TSDB_MAX_UNION_CLAUSE 5
#define TSDB_MAX_FIELD_LEN 16384
#define TSDB_MAX_BINARY_LEN (TSDB_MAX_FIELD_LEN-TSDB_KEYSIZE) // keep 16384
#define TSDB_MAX_NCHAR_LEN (TSDB_MAX_FIELD_LEN-TSDB_KEYSIZE) // keep 16384
#define PRIMARYKEY_TIMESTAMP_COL_INDEX 0
#define TSDB_MAX_RPC_THREADS 5
#define TSDB_QUERY_TYPE_NON_TYPE 0x00u // none type
#define TSDB_QUERY_TYPE_FREE_RESOURCE 0x01u // free qhandle at vnode
#define TSDB_UDF_TYPE_SCALAR 1
#define TSDB_UDF_TYPE_AGGREGATE 2
/*
* 1. ordinary sub query for select * from super_table
* 2. all sqlobj generated by createSubqueryObj with this flag
*/
#define TSDB_QUERY_TYPE_SUBQUERY 0x02u
#define TSDB_QUERY_TYPE_STABLE_SUBQUERY 0x04u // two-stage subquery for super table
#define TSDB_QUERY_TYPE_TABLE_QUERY 0x08u // query ordinary table; below only apply to client side
#define TSDB_QUERY_TYPE_STABLE_QUERY 0x10u // query on super table
#define TSDB_QUERY_TYPE_JOIN_QUERY 0x20u // join query
#define TSDB_QUERY_TYPE_PROJECTION_QUERY 0x40u // select *,columns... query
#define TSDB_QUERY_TYPE_JOIN_SEC_STAGE 0x80u // join sub query at the second stage
#define TSDB_QUERY_TYPE_TAG_FILTER_QUERY 0x400u
#define TSDB_QUERY_TYPE_INSERT 0x100u // insert type
#define TSDB_QUERY_TYPE_MULTITABLE_QUERY 0x200u
#define TSDB_QUERY_TYPE_FILE_INSERT 0x400u // insert data from file
#define TSDB_QUERY_TYPE_STMT_INSERT 0x800u // stmt insert type
#define TSDB_QUERY_TYPE_NEST_SUBQUERY 0x1000u // nested sub query
#define TSDB_QUERY_HAS_TYPE(x, _type) (((x) & (_type)) != 0)
#define TSDB_QUERY_SET_TYPE(x, _type) ((x) |= (_type))
#define TSDB_QUERY_CLEAR_TYPE(x, _type) ((x) &= (~_type))
#define TSDB_QUERY_RESET_TYPE(x) ((x) = TSDB_QUERY_TYPE_NON_TYPE)
#define TSDB_ORDER_ASC 1
#define TSDB_ORDER_DESC 2
#define TSDB_DEFAULT_CLUSTER_HASH_SIZE 1
#define TSDB_DEFAULT_MNODES_HASH_SIZE 5
#define TSDB_DEFAULT_DNODES_HASH_SIZE 10
#define TSDB_DEFAULT_ACCOUNTS_HASH_SIZE 10
#define TSDB_DEFAULT_USERS_HASH_SIZE 20
#define TSDB_DEFAULT_DBS_HASH_SIZE 100
#define TSDB_DEFAULT_VGROUPS_HASH_SIZE 100
#define TSDB_DEFAULT_STABLES_HASH_SIZE 100
#define TSDB_DEFAULT_CTABLES_HASH_SIZE 20000
#define TSDB_PORT_DNODESHELL 0
#define TSDB_PORT_DNODEDNODE 5
#define TSDB_PORT_SYNC 10
#define TSDB_PORT_HTTP 11
#define TSDB_PORT_ARBITRATOR 12
#define TSDB_MAX_WAL_SIZE (1024*1024*3)
#define TSDB_ARB_DUMMY_TIME 4765104000000 // 2121-01-01 00:00:00.000, :P
typedef enum {
TAOS_QTYPE_RPC = 0,
TAOS_QTYPE_FWD = 1,
......@@ -404,10 +35,6 @@ typedef enum {
TAOS_QTYPE_QUERY = 4
} EQType;
#define TSDB_MAX_TIERS 3
#define TSDB_MAX_DISKS_PER_TIER 16
#define TSDB_MAX_DISKS (TSDB_MAX_TIERS * TSDB_MAX_DISKS_PER_TIER)
typedef enum {
TSDB_SUPER_TABLE = 0, // super table
TSDB_CHILD_TABLE = 1, // table created from super table
......@@ -449,4 +76,4 @@ extern char *qtypeStr[];
}
#endif
#endif
#endif /*_TD_COMMON_TAOS_DEF_H*/
......@@ -13,10 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_COMMON_GLOBAL_H
#define TDENGINE_COMMON_GLOBAL_H
#include "taosdef.h"
#ifndef _TD_COMMON_GLOBAL_H
#define _TD_COMMON_GLOBAL_H
#ifdef __cplusplus
extern "C" {
......@@ -52,9 +50,6 @@ extern float tsNumOfThreadsPerCore;
extern int32_t tsNumOfCommitThreads;
extern float tsRatioOfQueryCores;
extern int8_t tsDaylight;
extern char tsTimezone[];
extern char tsLocale[];
extern char tsCharset[]; // default encode string
extern int8_t tsEnableCoreFile;
extern int32_t tsCompressMsgSize;
extern int32_t tsCompressColData;
......@@ -151,24 +146,14 @@ extern int8_t tsEnableStream;
// internal
extern int8_t tsPrintAuth;
extern int8_t tscEmbedded;
extern char configDir[];
extern char tsVnodeDir[];
extern char tsDnodeDir[];
extern char tsMnodeDir[];
extern char tsMnodeBakDir[];
extern char tsMnodeTmpDir[];
extern char tsDataDir[];
extern char tsLogDir[];
extern char tsScriptDir[];
extern int64_t tsTickPerDay[3];
extern int32_t tsTopicBianryLen;
// system info
extern char tsOsName[];
extern int64_t tsPageSize;
extern int64_t tsOpenMax;
extern int64_t tsStreamMax;
extern int32_t tsNumOfCores;
extern float tsTotalLogDirGB;
extern float tsTotalTmpDirGB;
extern float tsTotalDataDirGB;
......@@ -179,7 +164,6 @@ extern float tsUsedDataDirGB;
extern float tsMinimalLogDirGB;
extern float tsReservedTmpDirectorySpace;
extern float tsMinimalDataDirGB;
extern int32_t tsTotalMemoryMB;
extern uint32_t tsVersion;
// build info
......@@ -189,28 +173,6 @@ extern char gitinfo[];
extern char gitinfoOfInternal[];
extern char buildinfo[];
// log
extern int8_t tsAsyncLog;
extern int32_t tsNumOfLogLines;
extern int32_t tsLogKeepDays;
extern int32_t dDebugFlag;
extern int32_t vDebugFlag;
extern int32_t mDebugFlag;
extern uint32_t cDebugFlag;
extern int32_t jniDebugFlag;
extern int32_t tmrDebugFlag;
extern int32_t sdbDebugFlag;
extern int32_t httpDebugFlag;
extern int32_t mqttDebugFlag;
extern int32_t monDebugFlag;
extern int32_t uDebugFlag;
extern int32_t rpcDebugFlag;
extern int32_t odbcDebugFlag;
extern uint32_t qDebugFlag;
extern int32_t wDebugFlag;
extern int32_t cqDebugFlag;
extern int32_t debugFlag;
#ifdef TD_TSZ
// lossy
extern char lossyColumns[];
......@@ -224,7 +186,7 @@ extern char Compressor[];
extern int8_t tsDeadLockKillQuery;
typedef struct {
char dir[TSDB_FILENAME_LEN];
char dir[128];
int level;
int primary;
} SDiskCfg;
......@@ -235,7 +197,6 @@ extern SDiskCfg tsDiskCfg[];
void taosInitGlobalCfg();
int32_t taosCheckGlobalCfg();
void taosSetAllDebugFlag();
bool taosCfgDynamicOptions(char *msg);
int taosGetFqdnPortFromEp(const char *ep, char *fqdn, uint16_t *port);
bool taosCheckBalanceCfgOptions(const char *option, int32_t *vnodeId, int32_t *dnodeId);
......
......@@ -13,30 +13,46 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_COMMON_ULOG_H
#define TDENGINE_COMMON_ULOG_H
#ifndef _TD_COMMON_TIME_H_
#define _TD_COMMON_TIME_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "tlog.h"
#include "taosdef.h"
#include "taosmsg.h"
extern int32_t uDebugFlag;
extern int8_t tscEmbedded;
/*
* @return timestamp decided by global conf variable, tsTimePrecision
* if precision == TSDB_TIME_PRECISION_MICRO, it returns timestamp in microsecond.
* precision == TSDB_TIME_PRECISION_MILLI, it returns timestamp in millisecond.
*/
static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) {
if (precision == TSDB_TIME_PRECISION_MICRO) {
return taosGetTimestampUs();
} else if (precision == TSDB_TIME_PRECISION_NANO) {
return taosGetTimestampNs();
}else {
return taosGetTimestampMs();
}
}
int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision);
int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precision);
int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char unit, int32_t precision);
#define uFatal(...) { if (uDebugFlag & DEBUG_FATAL) { taosPrintLog("UTL FATAL", tscEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }}
#define uError(...) { if (uDebugFlag & DEBUG_ERROR) { taosPrintLog("UTL ERROR ", tscEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }}
#define uWarn(...) { if (uDebugFlag & DEBUG_WARN) { taosPrintLog("UTL WARN ", tscEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }}
#define uInfo(...) { if (uDebugFlag & DEBUG_INFO) { taosPrintLog("UTL ", tscEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }}
#define uDebug(...) { if (uDebugFlag & DEBUG_DEBUG) { taosPrintLog("UTL ", uDebugFlag, __VA_ARGS__); }}
#define uTrace(...) { if (uDebugFlag & DEBUG_TRACE) { taosPrintLog("UTL ", uDebugFlag, __VA_ARGS__); }}
int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* ts, char* unit, int32_t timePrecision);
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit, int32_t timePrecision);
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth);
void deltaToUtcInitOnce();
int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision);
#define pError(...) { taosPrintLog("APP ERROR ", 255, __VA_ARGS__); }
#define pPrint(...) { taosPrintLog("APP ", 255, __VA_ARGS__); }
#ifdef __cplusplus
}
#endif
#endif
#endif /*_TD_COMMON_TIME_H_*/
......@@ -9,43 +9,6 @@ extern "C" {
#include <stdint.h>
#include "taosdef.h"
// ----------------- For variable data types such as TSDB_DATA_TYPE_BINARY and TSDB_DATA_TYPE_NCHAR
typedef int32_t VarDataOffsetT;
typedef int16_t VarDataLenT; // maxVarDataLen: 32767
typedef uint16_t TDRowLenT; // not including overhead: 0 ~ 65535
typedef uint32_t TDRowTLenT; // total length, including overhead
typedef struct tstr {
VarDataLenT len;
char data[];
} tstr;
#pragma pack(push, 1)
typedef struct {
VarDataLenT len;
uint8_t data;
} SBinaryNullT;
typedef struct {
VarDataLenT len;
uint32_t data;
} SNCharNullT;
#pragma pack(pop)
#define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
#define varDataLen(v) ((VarDataLenT *)(v))[0]
#define varDataTLen(v) (sizeof(VarDataLenT) + varDataLen(v))
#define varDataVal(v) ((void *)((char *)v + VARSTR_HEADER_SIZE))
#define varDataCopy(dst, v) memcpy((dst), (void*) (v), varDataTLen(v))
#define varDataLenByData(v) (*(VarDataLenT *)(((char*)(v)) - VARSTR_HEADER_SIZE))
#define varDataSetLen(v, _len) (((VarDataLenT *)(v))[0] = (VarDataLenT) (_len))
#define IS_VAR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_BINARY) || ((t) == TSDB_DATA_TYPE_NCHAR))
#define varDataNetLen(v) (htons(((VarDataLenT *)(v))[0]))
#define varDataNetTLen(v) (sizeof(VarDataLenT) + varDataNetLen(v))
// this data type is internally used only in 'in' query to hold the values
#define TSDB_DATA_TYPE_POINTER_ARRAY (1000)
#define TSDB_DATA_TYPE_VALUE_ARRAY (1001)
......
......@@ -27,20 +27,26 @@ extern "C" {
#include <inttypes.h>
#include <locale.h>
#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wctype.h>
#include <wchar.h>
#include "osAtomic.h"
#include "osDef.h"
#include "osDir.h"
#include "osEndian.h"
#include "osEnv.h"
#include "osFile.h"
#include "osLz4.h"
#include "osMath.h"
#include "osMemory.h"
#include "osRand.h"
......@@ -49,10 +55,14 @@ extern "C" {
#include "osSleep.h"
#include "osSocket.h"
#include "osString.h"
#include "osSysinfo.h"
#include "osSystem.h"
#include "osThread.h"
#include "osTime.h"
#include "osTimer.h"
void osInit();
#ifdef __cplusplus
}
#endif
......
......@@ -20,14 +20,154 @@
extern "C" {
#endif
#if defined(_TD_DARWIN_64)
// specific
typedef int(*__compar_fn_t)(const void *, const void *);
// for send function in tsocket.c
#if defined(MSG_NOSIGNAL)
#undef MSG_NOSIGNAL
#endif
#define MSG_NOSIGNAL 0
#define SO_NO_CHECK 0x1234
#define SOL_TCP 0x1234
#define TCP_KEEPIDLE 0x1234
#ifndef PTHREAD_MUTEX_RECURSIVE_NP
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
#endif
#endif
#if defined(_ALPINE)
typedef int(*__compar_fn_t)(const void *, const void *);
void error (int, int, const char *);
#ifndef PTHREAD_MUTEX_RECURSIVE_NP
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
#endif
#endif
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
char *stpcpy (char *dest, const char *src);
char *stpncpy (char *dest, const char *src, size_t n);
// specific
typedef int (*__compar_fn_t)(const void *, const void *);
#define ssize_t int
#define bzero(ptr, size) memset((ptr), 0, (size))
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define wcsncasecmp _wcsnicmp
#define strtok_r strtok_s
#define snprintf _snprintf
#define in_addr_t unsigned long
#define socklen_t int
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);
char * getpass(const char *prefix);
char * strndup(const char *s, size_t n);
#endif
#define POINTER_SHIFT(p, b) ((void *)((char *)(p) + (b)))
#define POINTER_DISTANCE(p1, p2) ((char *)(p1) - (char *)(p2))
#ifndef NDEBUG
#define ASSERT(x) assert(x)
#else
#define ASSERT(x)
#endif
#ifndef UNUSED
#define UNUSED(x) ((void)(x))
#endif
#ifdef UNUSED_FUNC
#undefine UNUSED_FUNC
#endif
#ifdef UNUSED_PARAM
#undef UNUSED_PARAM
#endif
#if defined(__GNUC__)
#define UNUSED_PARAM(x) _UNUSED##x __attribute__((unused))
#define UNUSED_FUNC __attribute__((unused))
#else
#define UNUSED_PARAM(x) x
#define UNUSED_FUNC
#endif
// TODO: replace and remove code below
#define CHAR_BYTES sizeof(char)
#define SHORT_BYTES sizeof(int16_t)
#define INT_BYTES sizeof(int32_t)
#define LONG_BYTES sizeof(int64_t)
#define FLOAT_BYTES sizeof(float)
#define DOUBLE_BYTES sizeof(double)
#define POINTER_BYTES sizeof(void *) // 8 by default assert(sizeof(ptrdiff_t) == sizseof(void*)
#ifdef tListLen
#undefine tListLen
#endif
#define tListLen(x) (sizeof(x) / sizeof((x)[0]))
#if defined(__GNUC__)
#define FORCE_INLINE inline __attribute__((always_inline))
#else
#define FORCE_INLINE
#endif
#define POINTER_SHIFT(p, b) ((void *)((char *)(p) + (b)))
#define POINTER_DISTANCE(p1, p2) ((char *)(p1) - (char *)(p2))
#define DEFAULT_UNICODE_ENCODEC "UCS-4LE"
#define DEFAULT_COMP(x, y) \
do { \
if ((x) == (y)) { \
return 0; \
} else { \
return (x) < (y) ? -1 : 1; \
} \
} while (0)
#define DEFAULT_DOUBLE_COMP(x, y) \
do { \
if (isnan(x) && isnan(y)) { return 0; } \
if (isnan(x)) { return -1; } \
if (isnan(y)) { return 1; } \
if ((x) == (y)) { \
return 0; \
} else { \
return (x) < (y) ? -1 : 1; \
} \
} while (0)
#define DEFAULT_FLOAT_COMP(x, y) DEFAULT_DOUBLE_COMP(x, y)
#define ALIGN_NUM(n, align) (((n) + ((align)-1)) & (~((align)-1)))
// align to 8bytes
#define ALIGN8(n) ALIGN_NUM(n, 8)
#undef threadlocal
#ifdef _ISOC11_SOURCE
#define threadlocal _Thread_local
#elif defined(__APPLE__)
#define threadlocal __thread
#elif defined(__GNUC__) && !defined(threadlocal)
#define threadlocal __thread
#else
#define threadlocal __declspec( thread )
#endif
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#define PRIzu "ld"
#else
#define PRIzu "zu"
#endif
#if defined(_TD_LINUX_64) || defined(_TD_LINUX_32) || defined(_TD_MIPS_64) || defined(_TD_ARM_32) || defined(_TD_ARM_64) || defined(_TD_DARWIN_64)
#if defined(_TD_DARWIN_64)
......@@ -47,17 +187,6 @@ extern "C" {
#define setThreadName(name)
#endif
// TODO: replace and remove code below
#define CHAR_BYTES sizeof(char)
#define SHORT_BYTES sizeof(int16_t)
#define INT_BYTES sizeof(int32_t)
#define LONG_BYTES sizeof(int64_t)
#define FLOAT_BYTES sizeof(float)
#define DOUBLE_BYTES sizeof(double)
#define POINTER_BYTES sizeof(void *) // 8 by default assert(sizeof(ptrdiff_t) == sizseof(void*)
#ifdef __cplusplus
}
#endif
......
......@@ -20,12 +20,12 @@
extern "C" {
#endif
void taosRemoveDir(char *rootDir);
bool taosDirExist(const char* dirname);
int32_t taosMkDir(const char *pathname, mode_t mode);
void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays);
int32_t taosRename(char *oldName, char *newName);
int32_t taosCompressFile(char *srcFileName, char *destFileName);
void taosRemoveDir(char *dirname);
bool taosDirExist(char *dirname);
bool taosMkDir(char *dirname, mode_t mode);
void taosRemoveOldFiles(char *dirname, int32_t keepDays);
bool taosExpandDir(char *dirname, char *outname, int32_t maxlen);
bool taosRealPath(char *dirname, int32_t maxlen);
#ifdef __cplusplus
}
......
......@@ -13,19 +13,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_RAND_H
#define TDENGINE_OS_RAND_H
#ifndef _TD_OS_ENV_H_
#define _TD_OS_ENV_H_
#ifdef __cplusplus
extern "C" {
#endif
uint32_t taosRand(void);
void taosRandStr(char* str, int32_t size);
uint32_t taosSafeRand(void);
extern char tsOsName[];
extern char tsDnodeDir[];
extern char tsDataDir[];
extern char tsLogDir[];
extern char tsScriptDir[];
extern char configDir[];
#ifdef __cplusplus
}
#endif
#endif
#endif /*_TD_OS_ENV_H_*/
\ No newline at end of file
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_LZ4_H
#define TDENGINE_OS_LZ4_H
#ifndef _TD_OS_LZ4_H_
#define _TD_OS_LZ4_H_
#ifdef __cplusplus
extern "C" {
......@@ -46,4 +46,4 @@ extern "C" {
}
#endif
#endif
#endif /*_TD_OS_LZ4_H_*/
......@@ -20,8 +20,34 @@
extern "C" {
#endif
int32_t taosInitTimer(void (*callback)(int32_t), int32_t ms);
void taosUninitTimer();
#ifndef SIGALRM
#define SIGALRM 1234
#endif
#ifndef SIGHUP
#define SIGHUP 1230
#endif
#ifndef SIGCHLD
#define SIGCHLD 1234
#endif
#ifndef SIGUSR1
#define SIGUSR1 1234
#endif
#ifndef SIGUSR2
#define SIGUSR2 1234
#endif
#ifndef SIGBREAK
#define SIGBREAK 1234
#endif
typedef void (*FSignalHandler)(int32_t signum, void *sigInfo, void *context);
void taosSetSignal(int32_t signum, FSignalHandler sigfp);
void taosIgnSignal(int32_t signum);
void taosDflSignal(int32_t signum);
#ifdef __cplusplus
}
......
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_SLEEP_H
#define TDENGINE_OS_SLEEP_H
#ifndef _TD_OS_SLEEP_H_
#define _TD_OS_SLEEP_H_
#ifdef __cplusplus
extern "C" {
......@@ -26,4 +26,4 @@ void taosMsleep(int32_t ms);
}
#endif
#endif
\ No newline at end of file
#endif /*_TD_OS_SLEEP_H_*/
\ No newline at end of file
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_SOCKET_H
#define TDENGINE_OS_SOCKET_H
#ifndef _TD_OS_SOCKET_H_
#define _TD_OS_SOCKET_H_
#ifdef __cplusplus
extern "C" {
......@@ -89,4 +89,4 @@ const char *taosInetNtoa(struct in_addr ipInt);
}
#endif
#endif
#endif /*_TD_OS_SOCKET_H_*/
......@@ -43,7 +43,7 @@ int64_t taosStr2int64(char *str);
// USE_LIBICONV
int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs);
bool taosMbsToUcs4(char *mbs, size_t mbs_len, char *ucs4, int32_t ucs4_max_len, int32_t *len);
int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes);
int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes, int8_t ncharSize);
bool taosValidateEncodec(const char *encodec);
char * taosCharsetReplace(char *charsetstr);
......
......@@ -13,13 +13,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_SYSINFO_H
#define TDENGINE_OS_SYSINFO_H
#ifndef _TD_OS_SYSINFO_H_
#define _TD_OS_SYSINFO_H_
#ifdef __cplusplus
extern "C" {
#endif
#define TSDB_LOCALE_LEN 64
#define TSDB_TIMEZONE_LEN 96
extern int64_t tsPageSize;
extern int64_t tsOpenMax;
extern int64_t tsStreamMax;
extern int32_t tsNumOfCores;
extern int32_t tsTotalMemoryMB;
extern char tsTimezone[];
extern char tsLocale[];
extern char tsCharset[]; // default encode string
typedef struct {
int64_t tsize;
int64_t used;
......@@ -27,25 +39,32 @@ typedef struct {
} SysDiskSize;
int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize);
int32_t taosGetCpuCores();
void taosGetSystemInfo();
bool taosReadProcIO(int64_t* rchars, int64_t* wchars);
bool taosReadProcIO(int64_t *rchars, int64_t *wchars);
bool taosGetProcIO(float *readKB, float *writeKB);
bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes);
bool taosGetBandSpeed(float *bandSpeedKb);
void taosGetDisk();
bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) ;
bool taosGetProcMemory(float *memoryUsedMB) ;
bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage);
bool taosGetProcMemory(float *memoryUsedMB);
bool taosGetSysMemory(float *memoryUsedMB);
void taosPrintOsInfo();
void taosPrintDiskInfo();
int taosSystem(const char * cmd) ;
int taosSystem(const char *cmd);
void taosKillSystem();
bool taosGetSystemUid(char *uid);
char *taosGetCmdlineByPID(int pid);
bool taosGetSystemUid(char *uid, int32_t uidlen);
char * taosGetCmdlineByPID(int pid);
void taosSetCoreDump(bool enable);
typedef struct {
const char *sysname;
const char *nodename;
const char *release;
const char *version;
const char *machine;
} SysNameInfo;
void taosSetCoreDump();
SysNameInfo taosGetSysNameInfo();
#ifdef __cplusplus
}
......
......@@ -13,21 +13,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_SYSTEM_H
#define TDENGINE_OS_SYSTEM_H
#ifndef _TD_OS_SYSTEM_H_
#define _TD_OS_SYSTEM_H_
#ifdef __cplusplus
extern "C" {
#endif
void* taosLoadDll(const char *filename);
void* taosLoadDll(const char* filename);
void* taosLoadSym(void* handle, char* name);
void taosCloseDll(void *handle);
void taosCloseDll(void* handle);
int taosSetConsoleEcho(bool on);
int32_t taosSetConsoleEcho(bool on);
#ifdef __cplusplus
}
#endif
#endif
#endif /*_TD_OS_SYSTEM_H_*/
......@@ -20,6 +20,21 @@
extern "C" {
#endif
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#ifdef _TD_GO_DLL_
#define MILLISECOND_PER_SECOND (1000LL)
#else
#define MILLISECOND_PER_SECOND (1000i64)
#endif
#else
#define MILLISECOND_PER_SECOND ((int64_t)1000L)
#endif
#define MILLISECOND_PER_MINUTE (MILLISECOND_PER_SECOND * 60)
#define MILLISECOND_PER_HOUR (MILLISECOND_PER_MINUTE * 60)
#define MILLISECOND_PER_DAY (MILLISECOND_PER_HOUR * 24)
#define MILLISECOND_PER_WEEK (MILLISECOND_PER_DAY * 7)
int32_t taosGetTimeOfDay(struct timeval *tv);
//@return timestamp in second
......@@ -46,11 +61,6 @@ static FORCE_INLINE int64_t taosGetTimestampNs() {
return (int64_t)systemTime.tv_sec * 1000000000L + (int64_t)systemTime.tv_nsec;
}
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth);
void deltaToUtcInitOnce();
int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision);
#ifdef __cplusplus
}
#endif
......
......@@ -20,6 +20,8 @@
extern "C" {
#endif
#define MSECONDS_PER_TICK 5
int32_t taosInitTimer(void (*callback)(int32_t), int32_t ms);
void taosUninitTimer();
......
......@@ -13,13 +13,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_EXCEPTION_H
#define TDENGINE_EXCEPTION_H
#ifndef _TD_UTIL_EXCEPTION_H
#define _TD_UTIL_EXCEPTION_H
#include <setjmp.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "os.h"
#ifdef __cplusplus
extern "C" {
......@@ -125,4 +122,4 @@ void exceptionThrow( int32_t code );
}
#endif
#endif
#endif /*_TD_UTIL_EXCEPTION_H*/
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_HASH_H
#define TDENGINE_HASH_H
#ifndef _TD_UTIL_HASH_H
#define _TD_UTIL_HASH_H
#ifdef __cplusplus
extern "C" {
......@@ -178,4 +178,4 @@ uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data);
}
#endif
#endif // TDENGINE_HASH_H
#endif /*_TD_UTIL_HASH_H*/
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_HASHUTIL_H
#define TDENGINE_HASHUTIL_H
#ifndef _TD_UTIL_HASH_FUNC_H
#define _TD_UTIL_HASH_FUNC_H
#include "os.h"
......@@ -48,4 +48,4 @@ _hash_fn_t taosGetDefaultHashFunction(int32_t type);
_equal_fn_t taosGetDefaultEqualFunction(int32_t type);
#endif //TDENGINE_HASHUTIL_H
#endif /*_TD_UTIL_HASH_FUNC_H*/
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TALGO_H
#define TDENGINE_TALGO_H
#ifndef _TD_UTIL_TALGO_H
#define _TD_UTIL_TALGO_H
#ifdef __cplusplus
extern "C" {
......@@ -95,4 +95,4 @@ void taosheapsort(void *base, int32_t size, int32_t len, const void *parcompar,
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_TALGO_H
#endif /*_TD_UTIL_TALGO_H*/
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TAOSARRAY_H
#define TDENGINE_TAOSARRAY_H
#ifndef _TD_UTIL_ARRAY_H
#define _TD_UTIL_ARRAY_H
#ifdef __cplusplus
extern "C" {
......@@ -228,6 +228,4 @@ void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void *par
}
#endif
#endif // TDENGINE_TAOSARRAY_H
#endif /*_TD_UTIL_ARRAY_H*/
......@@ -13,11 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TBUFFER_H
#define TDENGINE_TBUFFER_H
#include <stdint.h>
#include <stdbool.h>
#ifndef _TD_UTIL_BUFFER_H
#define _TD_UTIL_BUFFER_H
#ifdef __cplusplus
extern "C" {
......@@ -175,4 +172,4 @@ void tbufWriteDoubleAt( SBufferWriter* buf, size_t pos, double data );
}
#endif
#endif
#endif /*_TD_UTIL_BUFFER_H*/
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TCACHE_H
#define TDENGINE_TCACHE_H
#ifndef _TD_UTIL_CACHE_H
#define _TD_UTIL_CACHE_H
#ifdef __cplusplus
extern "C" {
......@@ -188,4 +188,4 @@ void taosStopCacheRefreshWorker();
}
#endif
#endif // TDENGINE_TCACHE_H
#endif /*_TD_UTIL_CACHE_H*/
......@@ -12,8 +12,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TD_CODING_H_
#define _TD_CODING_H_
#ifndef _TD_UTIL_CODING_H
#define _TD_UTIL_CODING_H
#ifdef __cplusplus
extern "C" {
......@@ -361,4 +361,4 @@ static FORCE_INLINE void *taosDecodeString(void *buf, char **value) {
}
#endif
#endif
\ No newline at end of file
#endif /*_TD_UTIL_CODING_H*/
\ No newline at end of file
......@@ -13,8 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_CFG_H
#define TDENGINE_CFG_H
#ifndef _TD_UTIL_CONFIG_H
#define _TD_UTIL_CONFIG_H
#ifdef __cplusplus
extern "C" {
......@@ -89,10 +89,9 @@ void taosDumpGlobalCfg();
void taosInitConfigOption(SGlobalCfg cfg);
SGlobalCfg * taosGetConfigOption(const char *option);
bool taosReadConfigOption(const char *option, char *value, char *value2, char *value3, int8_t cfgStatus, int8_t sourceType);
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_TGLOBALCFG_H
#endif /*_TD_UTIL_CONFIG_H*/
......@@ -18,10 +18,8 @@
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TDENGINE_TCRC32C_H
#define TDENGINE_TCRC32C_H
#include <stdint.h>
#ifndef _TD_UTIL_CRC32_H
#define _TD_UTIL_CRC32_H
#ifdef __cplusplus
extern "C" {
......@@ -41,4 +39,4 @@ void taosResolveCRC();
}
#endif
#endif // TDENGINE_TCRC32C_H
#endif /*_TD_UTIL_CRC32_H*/
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TD_UTIL_DEF_H
#define _TD_UTIL_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
#define TSDB__packed
#ifdef TSKEY32
#define TSKEY int32_t;
#else
#define TSKEY int64_t
#endif
#define TSKEY_INITIAL_VAL INT64_MIN
// Bytes for each type.
extern const int32_t TYPE_BYTES[15];
#define TSDB_KEYSIZE sizeof(TSKEY)
#if LINUX
#define TSDB_NCHAR_SIZE sizeof(wchar_t)
#else
#define TSDB_NCHAR_SIZE sizeof(int32_t)
#endif
// NULL definition
#define TSDB_DATA_BOOL_NULL 0x02
#define TSDB_DATA_TINYINT_NULL 0x80
#define TSDB_DATA_SMALLINT_NULL 0x8000
#define TSDB_DATA_INT_NULL 0x80000000L
#define TSDB_DATA_BIGINT_NULL 0x8000000000000000L
#define TSDB_DATA_TIMESTAMP_NULL TSDB_DATA_BIGINT_NULL
#define TSDB_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000L // an NAN
#define TSDB_DATA_NCHAR_NULL 0xFFFFFFFF
#define TSDB_DATA_BINARY_NULL 0xFF
#define TSDB_DATA_UTINYINT_NULL 0xFF
#define TSDB_DATA_USMALLINT_NULL 0xFFFF
#define TSDB_DATA_UINT_NULL 0xFFFFFFFF
#define TSDB_DATA_UBIGINT_NULL 0xFFFFFFFFFFFFFFFFL
#define TSDB_DATA_NULL_STR "NULL"
#define TSDB_DATA_NULL_STR_L "null"
#define TSDB_DEFAULT_USER "root"
#ifdef _TD_POWER_
#define TSDB_DEFAULT_PASS "powerdb"
#elif (_TD_TQ_ == true)
#define TSDB_DEFAULT_PASS "tqueue"
#elif (_TD_PRO_ == true)
#define TSDB_DEFAULT_PASS "prodb"
#else
#define TSDB_DEFAULT_PASS "taosdata"
#endif
#define SHELL_MAX_PASSWORD_LEN 20
#define TSDB_TRUE 1
#define TSDB_FALSE 0
#define TSDB_OK 0
#define TSDB_ERR -1
#define TS_PATH_DELIMITER "."
#define TSDB_TIME_PRECISION_MILLI 0
#define TSDB_TIME_PRECISION_MICRO 1
#define TSDB_TIME_PRECISION_NANO 2
#define TSDB_TIME_PRECISION_MILLI_STR "ms"
#define TSDB_TIME_PRECISION_MICRO_STR "us"
#define TSDB_TIME_PRECISION_NANO_STR "ns"
#define TSDB_TICK_PER_SECOND(precision) ((int64_t)((precision)==TSDB_TIME_PRECISION_MILLI ? 1e3L : ((precision)==TSDB_TIME_PRECISION_MICRO ? 1e6L : 1e9L)))
#define T_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
#define T_APPEND_MEMBER(dst, ptr, type, member) \
do {\
memcpy((void *)(dst), (void *)(&((ptr)->member)), T_MEMBER_SIZE(type, member));\
dst = (void *)((char *)(dst) + T_MEMBER_SIZE(type, member));\
} while(0)
#define T_READ_MEMBER(src, type, target) \
do { \
(target) = *(type *)(src); \
(src) = (void *)((char *)src + sizeof(type));\
} while(0)
#define GET_INT8_VAL(x) (*(int8_t *)(x))
#define GET_INT16_VAL(x) (*(int16_t *)(x))
#define GET_INT32_VAL(x) (*(int32_t *)(x))
#define GET_INT64_VAL(x) (*(int64_t *)(x))
#define GET_UINT8_VAL(x) (*(uint8_t*) (x))
#define GET_UINT16_VAL(x) (*(uint16_t *)(x))
#define GET_UINT32_VAL(x) (*(uint32_t *)(x))
#define GET_UINT64_VAL(x) (*(uint64_t *)(x))
#ifdef _TD_ARM_32
float taos_align_get_float(const char* pBuf);
double taos_align_get_double(const char* pBuf);
#define GET_FLOAT_VAL(x) taos_align_get_float(x)
#define GET_DOUBLE_VAL(x) taos_align_get_double(x)
#define SET_FLOAT_VAL(x, y) { float z = (float)(y); (*(int32_t*) x = *(int32_t*)(&z)); }
#define SET_DOUBLE_VAL(x, y) { double z = (double)(y); (*(int64_t*) x = *(int64_t*)(&z)); }
#define SET_FLOAT_PTR(x, y) { (*(int32_t*) x = *(int32_t*)y); }
#define SET_DOUBLE_PTR(x, y) { (*(int64_t*) x = *(int64_t*)y); }
#else
#define GET_FLOAT_VAL(x) (*(float *)(x))
#define GET_DOUBLE_VAL(x) (*(double *)(x))
#define SET_FLOAT_VAL(x, y) { (*(float *)(x)) = (float)(y); }
#define SET_DOUBLE_VAL(x, y) { (*(double *)(x)) = (double)(y); }
#define SET_FLOAT_PTR(x, y) { (*(float *)(x)) = (*(float *)(y)); }
#define SET_DOUBLE_PTR(x, y) { (*(double *)(x)) = (*(double *)(y)); }
#endif
// TODO: check if below is necessary
#define TSDB_RELATION_INVALID 0
#define TSDB_RELATION_LESS 1
#define TSDB_RELATION_GREATER 2
#define TSDB_RELATION_EQUAL 3
#define TSDB_RELATION_LESS_EQUAL 4
#define TSDB_RELATION_GREATER_EQUAL 5
#define TSDB_RELATION_NOT_EQUAL 6
#define TSDB_RELATION_LIKE 7
#define TSDB_RELATION_ISNULL 8
#define TSDB_RELATION_NOTNULL 9
#define TSDB_RELATION_IN 10
#define TSDB_RELATION_AND 11
#define TSDB_RELATION_OR 12
#define TSDB_RELATION_NOT 13
#define TSDB_RELATION_MATCH 14
#define TSDB_RELATION_NMATCH 15
#define TSDB_BINARY_OP_ADD 30
#define TSDB_BINARY_OP_SUBTRACT 31
#define TSDB_BINARY_OP_MULTIPLY 32
#define TSDB_BINARY_OP_DIVIDE 33
#define TSDB_BINARY_OP_REMAINDER 34
#define IS_RELATION_OPTR(op) (((op) >= TSDB_RELATION_LESS) && ((op) < TSDB_RELATION_IN))
#define IS_ARITHMETIC_OPTR(op) (((op) >= TSDB_BINARY_OP_ADD) && ((op) <= TSDB_BINARY_OP_REMAINDER))
#define TS_PATH_DELIMITER_LEN 1
#define TSDB_UNI_LEN 24
#define TSDB_USER_LEN TSDB_UNI_LEN
// ACCOUNT is a 32 bit positive integer
// this is the length of its string representation, including the terminator zero
#define TSDB_ACCT_ID_LEN 11
#define TSDB_MAX_COLUMNS 4096
#define TSDB_MIN_COLUMNS 2 //PRIMARY COLUMN(timestamp) + other columns
#define TSDB_NODE_NAME_LEN 64
#define TSDB_TABLE_NAME_LEN 193 // it is a null-terminated string
#define TSDB_DB_NAME_LEN 33
#define TSDB_FUNC_NAME_LEN 65
#define TSDB_FUNC_CODE_LEN (65535 - 512)
#define TSDB_FUNC_BUF_SIZE 512
#define TSDB_TYPE_STR_MAX_LEN 32
#define TSDB_TABLE_FNAME_LEN (TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN + TSDB_TABLE_NAME_LEN)
#define TSDB_COL_NAME_LEN 65
#define TSDB_MAX_SAVED_SQL_LEN TSDB_MAX_COLUMNS * 64
#define TSDB_MAX_SQL_LEN TSDB_PAYLOAD_SIZE
#define TSDB_MAX_SQL_SHOW_LEN 512
#define TSDB_MAX_ALLOWED_SQL_LEN (1*1024*1024u) // sql length should be less than 1mb
#define TSDB_APPNAME_LEN TSDB_UNI_LEN
/**
* In some scenarios uint16_t (0~65535) is used to store the row len.
* - Firstly, we use 65531(65535 - 4), as the SDataRow/SKVRow contains 4 bits header.
* - Secondly, if all cols are VarDataT type except primary key, we need 4 bits to store the offset, thus
* the final value is 65531-(4096-1)*4 = 49151.
*/
#define TSDB_MAX_BYTES_PER_ROW 49151
#define TSDB_MAX_TAGS_LEN 16384
#define TSDB_MAX_TAGS 128
#define TSDB_MAX_TAG_CONDITIONS 1024
#define TSDB_AUTH_LEN 16
#define TSDB_KEY_LEN 16
#define TSDB_VERSION_LEN 12
#define TSDB_LABEL_LEN 8
#define TSDB_CLUSTER_ID_LEN 40
#define TSDB_FQDN_LEN 128
#define TSDB_EP_LEN (TSDB_FQDN_LEN+6)
#define TSDB_IPv4ADDR_LEN 16
#define TSDB_FILENAME_LEN 128
#define TSDB_SHOW_SQL_LEN 512
#define TSDB_SHOW_SUBQUERY_LEN 1000
#define TSDB_SLOW_QUERY_SQL_LEN 512
#define TSDB_STEP_NAME_LEN 32
#define TSDB_STEP_DESC_LEN 128
#define TSDB_MQTT_HOSTNAME_LEN 64
#define TSDB_MQTT_PORT_LEN 8
#define TSDB_MQTT_USER_LEN 24
#define TSDB_MQTT_PASS_LEN 24
#define TSDB_MQTT_TOPIC_LEN 64
#define TSDB_MQTT_CLIENT_ID_LEN 32
#define TSDB_DB_TYPE_DEFAULT 0
#define TSDB_DB_TYPE_TOPIC 1
#define TSDB_DEFAULT_PKT_SIZE 65480 //same as RPC_MAX_UDP_SIZE
#define TSDB_PAYLOAD_SIZE TSDB_DEFAULT_PKT_SIZE
#define TSDB_DEFAULT_PAYLOAD_SIZE 5120 // default payload size, greater than PATH_MAX value
#define TSDB_EXTRA_PAYLOAD_SIZE 128 // extra bytes for auth
#define TSDB_CQ_SQL_SIZE 1024
#define TSDB_MIN_VNODES 64
#define TSDB_MAX_VNODES 2048
#define TSDB_MIN_VNODES_PER_DB 2
#define TSDB_MAX_VNODES_PER_DB 64
#define TSDB_DNODE_ROLE_ANY 0
#define TSDB_DNODE_ROLE_MGMT 1
#define TSDB_DNODE_ROLE_VNODE 2
#define TSDB_MAX_REPLICA 5
#define TSDB_TBNAME_COLUMN_INDEX (-1)
#define TSDB_UD_COLUMN_INDEX (-1000)
#define TSDB_RES_COL_ID (-5000)
#define TSDB_MULTI_TABLEMETA_MAX_NUM 100000 // maximum batch size allowed to load table meta
#define TSDB_MIN_CACHE_BLOCK_SIZE 1
#define TSDB_MAX_CACHE_BLOCK_SIZE 128 // 128MB for each vnode
#define TSDB_DEFAULT_CACHE_BLOCK_SIZE 16
#define TSDB_MIN_TOTAL_BLOCKS 3
#define TSDB_MAX_TOTAL_BLOCKS 10000
#define TSDB_DEFAULT_TOTAL_BLOCKS 6
#define TSDB_MIN_TABLES 4
#define TSDB_MAX_TABLES 10000000
#define TSDB_DEFAULT_TABLES 1000000
#define TSDB_TABLES_STEP 1000
#define TSDB_META_COMPACT_RATIO 0 // disable tsdb meta compact by default
#define TSDB_MIN_DAYS_PER_FILE 1
#define TSDB_MAX_DAYS_PER_FILE 3650
#define TSDB_DEFAULT_DAYS_PER_FILE 10
#define TSDB_MIN_KEEP 1 // data in db to be reserved.
#define TSDB_MAX_KEEP 365000 // data in db to be reserved.
#define TSDB_DEFAULT_KEEP 3650 // ten years
#define TSDB_DEFAULT_MIN_ROW_FBLOCK 100
#define TSDB_MIN_MIN_ROW_FBLOCK 10
#define TSDB_MAX_MIN_ROW_FBLOCK 1000
#define TSDB_DEFAULT_MAX_ROW_FBLOCK 4096
#define TSDB_MIN_MAX_ROW_FBLOCK 200
#define TSDB_MAX_MAX_ROW_FBLOCK 10000
#define TSDB_MIN_COMMIT_TIME 30
#define TSDB_MAX_COMMIT_TIME 40960
#define TSDB_DEFAULT_COMMIT_TIME 3600
#define TSDB_MIN_PRECISION TSDB_TIME_PRECISION_MILLI
#define TSDB_MAX_PRECISION TSDB_TIME_PRECISION_NANO
#define TSDB_DEFAULT_PRECISION TSDB_TIME_PRECISION_MILLI
#define TSDB_MIN_COMP_LEVEL 0
#define TSDB_MAX_COMP_LEVEL 2
#define TSDB_DEFAULT_COMP_LEVEL 2
#define TSDB_MIN_WAL_LEVEL 0
#define TSDB_MAX_WAL_LEVEL 2
#define TSDB_DEFAULT_WAL_LEVEL 1
#define TSDB_MIN_DB_UPDATE 0
#define TSDB_MAX_DB_UPDATE 2
#define TSDB_DEFAULT_DB_UPDATE_OPTION 0
#define TSDB_MIN_DB_CACHE_LAST_ROW 0
#define TSDB_MAX_DB_CACHE_LAST_ROW 3
#define TSDB_DEFAULT_CACHE_LAST_ROW 0
#define TSDB_MIN_FSYNC_PERIOD 0
#define TSDB_MAX_FSYNC_PERIOD 180000 // millisecond
#define TSDB_DEFAULT_FSYNC_PERIOD 3000 // three second
#define TSDB_MIN_DB_REPLICA_OPTION 1
#define TSDB_MAX_DB_REPLICA_OPTION 3
#define TSDB_DEFAULT_DB_REPLICA_OPTION 1
#define TSDB_MIN_DB_PARTITON_OPTION 0
#define TSDB_MAX_DB_PARTITON_OPTION 1000
#define TSDB_DEFAULT_DB_PARTITON_OPTION 4
#define TSDB_MIN_DB_QUORUM_OPTION 1
#define TSDB_MAX_DB_QUORUM_OPTION 2
#define TSDB_DEFAULT_DB_QUORUM_OPTION 1
#define TSDB_MAX_JOIN_TABLE_NUM 10
#define TSDB_MAX_UNION_CLAUSE 5
#define TSDB_MAX_FIELD_LEN 16384
#define TSDB_MAX_BINARY_LEN (TSDB_MAX_FIELD_LEN-TSDB_KEYSIZE) // keep 16384
#define TSDB_MAX_NCHAR_LEN (TSDB_MAX_FIELD_LEN-TSDB_KEYSIZE) // keep 16384
#define PRIMARYKEY_TIMESTAMP_COL_INDEX 0
#define TSDB_MAX_RPC_THREADS 5
#define TSDB_QUERY_TYPE_NON_TYPE 0x00u // none type
#define TSDB_QUERY_TYPE_FREE_RESOURCE 0x01u // free qhandle at vnode
#define TSDB_UDF_TYPE_SCALAR 1
#define TSDB_UDF_TYPE_AGGREGATE 2
/*
* 1. ordinary sub query for select * from super_table
* 2. all sqlobj generated by createSubqueryObj with this flag
*/
#define TSDB_QUERY_TYPE_SUBQUERY 0x02u
#define TSDB_QUERY_TYPE_STABLE_SUBQUERY 0x04u // two-stage subquery for super table
#define TSDB_QUERY_TYPE_TABLE_QUERY 0x08u // query ordinary table; below only apply to client side
#define TSDB_QUERY_TYPE_STABLE_QUERY 0x10u // query on super table
#define TSDB_QUERY_TYPE_JOIN_QUERY 0x20u // join query
#define TSDB_QUERY_TYPE_PROJECTION_QUERY 0x40u // select *,columns... query
#define TSDB_QUERY_TYPE_JOIN_SEC_STAGE 0x80u // join sub query at the second stage
#define TSDB_QUERY_TYPE_TAG_FILTER_QUERY 0x400u
#define TSDB_QUERY_TYPE_INSERT 0x100u // insert type
#define TSDB_QUERY_TYPE_MULTITABLE_QUERY 0x200u
#define TSDB_QUERY_TYPE_FILE_INSERT 0x400u // insert data from file
#define TSDB_QUERY_TYPE_STMT_INSERT 0x800u // stmt insert type
#define TSDB_QUERY_TYPE_NEST_SUBQUERY 0x1000u // nested sub query
#define TSDB_QUERY_HAS_TYPE(x, _type) (((x) & (_type)) != 0)
#define TSDB_QUERY_SET_TYPE(x, _type) ((x) |= (_type))
#define TSDB_QUERY_CLEAR_TYPE(x, _type) ((x) &= (~_type))
#define TSDB_QUERY_RESET_TYPE(x) ((x) = TSDB_QUERY_TYPE_NON_TYPE)
#define TSDB_ORDER_ASC 1
#define TSDB_ORDER_DESC 2
#define TSDB_DEFAULT_CLUSTER_HASH_SIZE 1
#define TSDB_DEFAULT_MNODES_HASH_SIZE 5
#define TSDB_DEFAULT_DNODES_HASH_SIZE 10
#define TSDB_DEFAULT_ACCOUNTS_HASH_SIZE 10
#define TSDB_DEFAULT_USERS_HASH_SIZE 20
#define TSDB_DEFAULT_DBS_HASH_SIZE 100
#define TSDB_DEFAULT_VGROUPS_HASH_SIZE 100
#define TSDB_DEFAULT_STABLES_HASH_SIZE 100
#define TSDB_DEFAULT_CTABLES_HASH_SIZE 20000
#define TSDB_PORT_DNODESHELL 0
#define TSDB_PORT_DNODEDNODE 5
#define TSDB_PORT_SYNC 10
#define TSDB_PORT_HTTP 11
#define TSDB_PORT_ARBITRATOR 12
#define TSDB_MAX_WAL_SIZE (1024*1024*3)
#define TSDB_ARB_DUMMY_TIME 4765104000000 // 2121-01-01 00:00:00.000, :P
#define TSDB_MAX_TIERS 3
#define TSDB_MAX_DISKS_PER_TIER 16
#define TSDB_MAX_DISKS (TSDB_MAX_TIERS * TSDB_MAX_DISKS_PER_TIER)
#define TSDB_DATA_TYPE_NULL 0 // 1 bytes
#define TSDB_DATA_TYPE_BOOL 1 // 1 bytes
#define TSDB_DATA_TYPE_TINYINT 2 // 1 byte
#define TSDB_DATA_TYPE_SMALLINT 3 // 2 bytes
#define TSDB_DATA_TYPE_INT 4 // 4 bytes
#define TSDB_DATA_TYPE_BIGINT 5 // 8 bytes
#define TSDB_DATA_TYPE_FLOAT 6 // 4 bytes
#define TSDB_DATA_TYPE_DOUBLE 7 // 8 bytes
#define TSDB_DATA_TYPE_BINARY 8 // string
#define TSDB_DATA_TYPE_TIMESTAMP 9 // 8 bytes
#define TSDB_DATA_TYPE_NCHAR 10 // unicode string
#define TSDB_DATA_TYPE_UTINYINT 11 // 1 byte
#define TSDB_DATA_TYPE_USMALLINT 12 // 2 bytes
#define TSDB_DATA_TYPE_UINT 13 // 4 bytes
#define TSDB_DATA_TYPE_UBIGINT 14 // 8 bytes
// ----------------- For variable data types such as TSDB_DATA_TYPE_BINARY and TSDB_DATA_TYPE_NCHAR
typedef int32_t VarDataOffsetT;
typedef int16_t VarDataLenT; // maxVarDataLen: 32767
typedef uint16_t TDRowLenT; // not including overhead: 0 ~ 65535
typedef uint32_t TDRowTLenT; // total length, including overhead
typedef struct tstr {
VarDataLenT len;
char data[];
} tstr;
#pragma pack(push, 1)
typedef struct {
VarDataLenT len;
uint8_t data;
} SBinaryNullT;
typedef struct {
VarDataLenT len;
uint32_t data;
} SNCharNullT;
#pragma pack(pop)
#define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
#define varDataLen(v) ((VarDataLenT *)(v))[0]
#define varDataTLen(v) (sizeof(VarDataLenT) + varDataLen(v))
#define varDataVal(v) ((void *)((char *)v + VARSTR_HEADER_SIZE))
#define varDataCopy(dst, v) memcpy((dst), (void*) (v), varDataTLen(v))
#define varDataLenByData(v) (*(VarDataLenT *)(((char*)(v)) - VARSTR_HEADER_SIZE))
#define varDataSetLen(v, _len) (((VarDataLenT *)(v))[0] = (VarDataLenT) (_len))
#define IS_VAR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_BINARY) || ((t) == TSDB_DATA_TYPE_NCHAR))
#define varDataNetLen(v) (htons(((VarDataLenT *)(v))[0]))
#define varDataNetTLen(v) (sizeof(VarDataLenT) + varDataNetLen(v))
#ifdef __cplusplus
}
#endif
#endif
......@@ -12,8 +12,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TD_LIST_
#define _TD_LIST_
#ifndef _TD_UTIL_LIST_H
#define _TD_UTIL_LIST_H
#ifdef __cplusplus
extern "C" {
......@@ -69,4 +69,4 @@ SListNode *tdListNext(SListIter *pIter);
}
#endif
#endif
\ No newline at end of file
#endif /*_TD_UTIL_LIST_H*/
\ No newline at end of file
......@@ -12,8 +12,8 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TD_LOCK_FREE_H__
#define __TD_LOCK_FREE_H__
#ifndef _TD_UTIL_LOCK_FREE_H
#define _TD_UTIL_LOCK_FREE_H
#include "os.h"
......@@ -21,7 +21,6 @@
extern "C" {
#endif
// reference counting
typedef void (*_ref_fn_t)(const void* pObj);
......@@ -106,9 +105,8 @@ void taosRUnLockLatch(SRWLatch *pLatch);
break; \
}
#ifdef __cplusplus
}
#endif
#endif
#endif /*_TD_UTIL_LOCK_FREE_H*/
......@@ -13,13 +13,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TLOG_H
#define TDENGINE_TLOG_H
#ifndef _TD_UTIL_LOG_H
#define _TD_UTIL_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
// log
extern int8_t tsAsyncLog;
extern int32_t tsNumOfLogLines;
extern int32_t tsLogKeepDays;
extern int32_t dDebugFlag;
extern int32_t vDebugFlag;
extern int32_t mDebugFlag;
extern int32_t cDebugFlag;
extern int32_t jniDebugFlag;
extern int32_t tmrDebugFlag;
extern int32_t sdbDebugFlag;
extern int32_t httpDebugFlag;
extern int32_t mqttDebugFlag;
extern int32_t monDebugFlag;
extern int32_t uDebugFlag;
extern int32_t rpcDebugFlag;
extern int32_t odbcDebugFlag;
extern int32_t qDebugFlag;
extern int32_t wDebugFlag;
extern int32_t sDebugFlag;
extern int32_t tsdbDebugFlag;
extern int32_t cqDebugFlag;
extern int32_t debugFlag;
#define DEBUG_FATAL 1U
#define DEBUG_ERROR DEBUG_FATAL
#define DEBUG_WARN 2U
......@@ -53,4 +78,4 @@ void taosDumpData(unsigned char *msg, int32_t len);
}
#endif
#endif
#endif /*_TD_UTIL_LOG_H*/
......@@ -20,7 +20,7 @@
extern "C" {
#endif
#include "taosdef.h"
#include "tdef.h"
#include "tutil.h"
#define COMP_OVERFLOW_BYTES 2
......
......@@ -53,11 +53,6 @@ static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, size_t inLen, char *tar
memcpy(target, context.digest, keylen);
}
#ifdef tListLen
#undefine tListLen
#endif
#define tListLen(x) (sizeof(x) / sizeof((x)[0]))
#ifdef __cplusplus
}
#endif
......
......@@ -5,3 +5,8 @@ target_include_directories(
PUBLIC "${CMAKE_SOURCE_DIR}/include/common"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc"
)
target_link_libraries(
common
PUBLIC os
PUBLIC util
)
\ No newline at end of file
......@@ -18,14 +18,14 @@
#include "taosdef.h"
#include "taoserror.h"
#include "tulog.h"
#include "tlog.h"
#include "tconfig.h"
#include "tglobal.h"
#include "monitor.h"
#include "tsocket.h"
#include "tcompare.h"
#include "tutil.h"
#include "tlocale.h"
#include "ttimezone.h"
#include "tcompare.h"
#include "tlocale.h"
// cluster
char tsFirst[TSDB_EP_LEN] = {0};
......@@ -59,9 +59,6 @@ float tsNumOfThreadsPerCore = 1.0f;
int32_t tsNumOfCommitThreads = 4;
float tsRatioOfQueryCores = 1.0f;
int8_t tsDaylight = 0;
char tsTimezone[TSDB_TIMEZONE_LEN] = {0};
char tsLocale[TSDB_LOCALE_LEN] = {0};
char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string
int8_t tsEnableCoreFile = 0;
int32_t tsMaxBinaryDisplayWidth = 30;
......@@ -201,15 +198,11 @@ int8_t tsEnableStream = 1;
int8_t tsCompactMnodeWal = 0;
int8_t tsPrintAuth = 0;
int8_t tscEmbedded = 0;
char configDir[PATH_MAX] = {0};
char tsVnodeDir[PATH_MAX] = {0};
char tsDnodeDir[PATH_MAX] = {0};
char tsMnodeDir[PATH_MAX] = {0};
char tsMnodeTmpDir[PATH_MAX] = {0};
char tsMnodeBakDir[PATH_MAX] = {0};
char tsDataDir[PATH_MAX] = {0};
char tsScriptDir[PATH_MAX] = {0};
char tsTempDir[PATH_MAX] = "/tmp/";
int32_t tsDiskCfgNum = 0;
int32_t tsTopicBianryLen = 16000;
......@@ -229,11 +222,6 @@ SDiskCfg tsDiskCfg[TSDB_MAX_DISKS];
int64_t tsTickPerDay[] = {86400000L, 86400000000L, 86400000000000L};
// system info
char tsOsName[10] = "Linux";
int64_t tsPageSize;
int64_t tsOpenMax;
int64_t tsStreamMax;
int32_t tsNumOfCores = 1;
float tsTotalTmpDirGB = 0;
float tsTotalDataDirGB = 0;
float tsAvailTmpDirectorySpace = 0;
......@@ -244,28 +232,6 @@ float tsMinimalDataDirGB = 2.0f;
int32_t tsTotalMemoryMB = 0;
uint32_t tsVersion = 0;
// log
int32_t tsNumOfLogLines = 10000000;
int32_t mDebugFlag = 131;
int32_t sdbDebugFlag = 131;
int32_t dDebugFlag = 135;
int32_t vDebugFlag = 135;
uint32_t cDebugFlag = 131;
int32_t jniDebugFlag = 131;
int32_t odbcDebugFlag = 131;
int32_t httpDebugFlag = 131;
int32_t mqttDebugFlag = 131;
int32_t monDebugFlag = 131;
uint32_t qDebugFlag = 131;
int32_t rpcDebugFlag = 131;
int32_t uDebugFlag = 131;
int32_t debugFlag = 0;
int32_t sDebugFlag = 135;
int32_t wDebugFlag = 135;
int32_t tsdbDebugFlag = 131;
int32_t cqDebugFlag = 131;
int32_t fsDebugFlag = 135;
#ifdef TD_TSZ
//
// lossy compress 6
......@@ -420,6 +386,7 @@ static void taosCheckDataDirCfg() {
}
static int32_t taosCheckTmpDir(void) {
#if 0
if (strlen(tsTempDir) <= 0){
uError("tempDir is not set");
return -1;
......@@ -432,10 +399,11 @@ static int32_t taosCheckTmpDir(void) {
}
closedir(dir);
#endif
return 0;
}
static void doInitGlobalConfig(void) {
osInit();
srand(taosSafeRand());
......@@ -1096,7 +1064,7 @@ static void doInitGlobalConfig(void) {
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW | TSDB_CFG_CTYPE_B_CLIENT;
cfg.minValue = 0;
cfg.maxValue = 0;
cfg.ptrLength = tListLen(tsTimezone);
cfg.ptrLength = TSDB_TIMEZONE_LEN;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
......@@ -1106,7 +1074,7 @@ static void doInitGlobalConfig(void) {
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW | TSDB_CFG_CTYPE_B_CLIENT;
cfg.minValue = 0;
cfg.maxValue = 0;
cfg.ptrLength = tListLen(tsLocale);
cfg.ptrLength = TSDB_LOCALE_LEN;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
......@@ -1116,7 +1084,7 @@ static void doInitGlobalConfig(void) {
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW | TSDB_CFG_CTYPE_B_CLIENT;
cfg.minValue = 0;
cfg.maxValue = 0;
cfg.ptrLength = tListLen(tsCharset);
cfg.ptrLength = TSDB_LOCALE_LEN;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
......@@ -1612,7 +1580,7 @@ static void doInitGlobalConfig(void) {
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT;
cfg.minValue = 0;
cfg.maxValue = 0;
cfg.ptrLength = tListLen(tsTempDir);
cfg.ptrLength = PATH_MAX;
cfg.unitType = TAOS_CFG_UTYPE_NONE;
taosInitConfigOption(cfg);
......
......@@ -25,6 +25,7 @@
#include "os.h"
#include "taosdef.h"
#include "ttime.h"
#include "tutil.h"
/*
......
......@@ -14,6 +14,7 @@
*/
#include "os.h"
#include "taosdef.h"
#include "tglobal.h"
#include "tmempool.h"
#include "ttimer.h"
......
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
\ No newline at end of file
......@@ -13,13 +13,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tglobal.h"
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
// add
char interlocked_add_fetch_8(char volatile* ptr, char val) {
......@@ -162,3 +158,42 @@ __int64 interlocked_fetch_xor_64(__int64 volatile* ptr, __int64 val) {
#endif
}
#endif
#ifdef _TD_NINGSI_60
void* atomic_exchange_ptr_impl(void** ptr, void* val ) {
void *old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int8_t atomic_exchange_8_impl(int8_t* ptr, int8_t val ) {
int8_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int16_t atomic_exchange_16_impl(int16_t* ptr, int16_t val ) {
int16_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int32_t atomic_exchange_32_impl(int32_t* ptr, int32_t val ) {
int32_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int64_t atomic_exchange_64_impl(int64_t* ptr, int64_t val ) {
int64_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
#endif
......@@ -13,16 +13,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
#include "tulog.h"
#include "zlib.h"
#include "osString.h"
#define COMPRESS_STEP_SIZE 163840
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
// todo
#else
/*
* linux implementation
*/
void taosRemoveDir(char *rootDir) {
DIR *dir = opendir(rootDir);
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wordexp.h>
void taosRemoveDir(char *dirname) {
DIR *dir = opendir(dirname);
if (dir == NULL) return;
struct dirent *de = NULL;
......@@ -30,33 +43,34 @@ void taosRemoveDir(char *rootDir) {
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
char filename[1024];
snprintf(filename, 1023, "%s/%s", rootDir, de->d_name);
snprintf(filename, sizeof(filename), "%s/%s", dirname, de->d_name);
if (de->d_type & DT_DIR) {
taosRemoveDir(filename);
} else {
(void)remove(filename);
uInfo("file:%s is removed", filename);
printf("file:%s is removed", filename);
}
}
closedir(dir);
rmdir(rootDir);
rmdir(dirname);
uInfo("dir:%s is removed", rootDir);
printf("dir:%s is removed", dirname);
}
bool taosDirExist(const char* dirname) {
return access(dirname, F_OK) == 0;
}
bool taosDirExist(char *dirname) { return access(dirname, F_OK) == 0; }
int taosMkDir(const char *path, mode_t mode) {
int code = mkdir(path, 0755);
if (code < 0 && errno == EEXIST) code = 0;
return code;
bool taosMkDir(char *dirname, mode_t mode) {
int32_t code = mkdir(dirname, 0755);
if (code < 0 && errno == EEXIST) {
return true;
}
return code == 0;
}
void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays) {
DIR *dir = opendir(rootDir);
void taosRemoveOldFiles(char *dirname, int32_t keepDays) {
DIR *dir = opendir(dirname);
if (dir == NULL) return;
int64_t sec = taosGetTimestampSec();
......@@ -66,7 +80,7 @@ void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays) {
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
char filename[1024];
snprintf(filename, 1023, "%s/%s", rootDir, de->d_name);
snprintf(filename, sizeof(filename), "%s/%s", dirname, de->d_name);
if (de->d_type & DT_DIR) {
continue;
} else {
......@@ -76,7 +90,7 @@ void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays) {
}
int64_t fileSec = 0;
for (int i = len - 1; i >= 0; i--) {
for (int32_t i = len - 1; i >= 0; i--) {
if (filename[i] == '.') {
fileSec = atoll(filename + i + 1);
break;
......@@ -87,56 +101,41 @@ void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays) {
int32_t days = (int32_t)(ABS(sec - fileSec) / 86400 + 1);
if (days > keepDays) {
(void)remove(filename);
uInfo("file:%s is removed, days:%d keepDays:%d", filename, days, keepDays);
printf("file:%s is removed, days:%d keepDays:%d", filename, days, keepDays);
} else {
uTrace("file:%s won't be removed, days:%d keepDays:%d", filename, days, keepDays);
printf("file:%s won't be removed, days:%d keepDays:%d", filename, days, keepDays);
}
}
}
closedir(dir);
rmdir(rootDir);
rmdir(dirname);
}
int32_t taosCompressFile(char *srcFileName, char *destFileName) {
int32_t ret = 0;
int32_t len = 0;
char * data = malloc(COMPRESS_STEP_SIZE);
FILE * srcFp = NULL;
gzFile dstFp = NULL;
srcFp = fopen(srcFileName, "r");
if (srcFp == NULL) {
ret = -1;
goto cmp_end;
bool taosExpandDir(char *dirname, char *outname, int32_t maxlen) {
wordexp_t full_path;
if (0 != wordexp(dirname, &full_path, 0)) {
printf("failed to expand path:%s since %s", dirname, strerror(errno));
wordfree(&full_path);
return false;
}
int32_t fd = open(destFileName, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU | S_IRWXG | S_IRWXO);
if (fd < 0) {
ret = -2;
goto cmp_end;
if (full_path.we_wordv != NULL && full_path.we_wordv[0] != NULL) {
strncpy(outname, full_path.we_wordv[0], maxlen);
}
dstFp = gzdopen(fd, "wb6f");
if (dstFp == NULL) {
ret = -3;
close(fd);
goto cmp_end;
}
wordfree(&full_path);
while (!feof(srcFp)) {
len = (int32_t)fread(data, 1, COMPRESS_STEP_SIZE, srcFp);
(void)gzwrite(dstFp, data, len);
}
return true;
}
cmp_end:
if (srcFp) {
fclose(srcFp);
}
if (dstFp) {
gzclose(dstFp);
bool taosRealPath(char *dirname, int32_t maxlen) {
char tmp[PATH_MAX] = {0};
if (realpath(dirname, tmp) != NULL) {
strncpy(dirname, tmp, maxlen);
}
free(data);
return ret;
return true;
}
#endif
\ No newline at end of file
......@@ -13,46 +13,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
#include "tulog.h"
extern void taosWinSocketInit();
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
void osInit() {
taosSetCoreDump();
#ifdef _TD_POWER_
if (configDir[0] == 0) {
strcpy(configDir, "C:/PowerDB/cfg");
}
char tsOsName[10] = "Windows";
char configDir[PATH_MAX] = "C:/TDengine/cfg";
char tsDataDir[PATH_MAX] = "C:/TDengine/data";
char tsLogDir[PATH_MAX] = "C:/TDengine/log";
char tsScriptDir[PATH_MAX] = "C:/TDengine/script";
char tsTempDir[PATH_MAX] = "C:\\Windows\\Temp";
strcpy(tsVnodeDir, "C:/PowerDB/data");
strcpy(tsDataDir, "C:/PowerDB/data");
strcpy(tsLogDir, "C:/PowerDB/log");
strcpy(tsScriptDir, "C:/PowerDB/script");
#elif (_TD_TQ_ == true)
if (configDir[0] == 0) {
strcpy(configDir, "C:/TQ/cfg");
}
strcpy(tsVnodeDir, "C:/TQ/data");
strcpy(tsDataDir, "C:/TQ/data");
strcpy(tsLogDir, "C:/TQ/log");
strcpy(tsScriptDir, "C:/TQ/script");
#else
if (configDir[0] == 0) {
strcpy(configDir, "C:/TDengine/cfg");
}
extern taosWinSocketInit();
strcpy(tsVnodeDir, "C:/TDengine/data");
strcpy(tsDataDir, "C:/TDengine/data");
strcpy(tsLogDir, "C:/TDengine/log");
strcpy(tsScriptDir, "C:/TDengine/script");
#endif
strcpy(tsDnodeDir, "");
strcpy(tsMnodeDir, "");
strcpy(tsOsName, "Windows");
void osInit() {
taosWinSocketInit();
const char *tmpDir = getenv("tmp");
if (tmpDir == NULL) {
......@@ -61,9 +38,29 @@ void osInit() {
if (tmpDir != NULL) {
strcpy(tsTempDir, tmpDir);
} else {
strcpy(tsTempDir, "C:\\Windows\\Temp");
}
taosWinSocketInit();
}
#elif defined(_TD_DARWIN_64)
char tsOsName[10] = "Darwin";
char configDir[PATH_MAX] = "/usr/local/etc/taos";
char tsDataDir[PATH_MAX] = "/usr/local/var/lib/taos";
char tsLogDir[PATH_MAX] = "/usr/local/var/log/taos";
char tsScriptDir[PATH_MAX] = "/usr/local/etc/taos";
char tsTempDir[PATH_MAX] = "/tmp/taosd";
void osInit() {}
#else
char tsOsName[10] = "Linux";
char configDir[PATH_MAX] = "/etc/taos";
char tsDataDir[PATH_MAX] = "/var/lib/taos";
char tsLogDir[PATH_MAX] = "/var/log/taos";
char tsScriptDir[PATH_MAX] = "/etc/taos";
char tsTempDir[PATH_MAX] = "/tmp/";
void osInit() {}
#endif
......@@ -402,7 +402,6 @@ int32_t taosRenameFile(char *oldName, char *newName) {
#endif
}
int32_t taosLockFile(int32_t fd) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
return 0;
......
......@@ -15,11 +15,12 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tglobal.h"
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
unsigned char _MyBitScanForward64(unsigned long *ret, uint64_t x) {
unsigned long x0 = (unsigned long)x, top, bottom;
......@@ -68,3 +69,5 @@ int32_t BUILDIN_CTZ(uint32_t val) {
_BitScanForward(&r, val);
return (int)(r >> 3);
}
#endif
......@@ -15,6 +15,10 @@
#define _DEFAULT_SOURCE
#include "os.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
#include <sys/file.h>
#endif
uint32_t taosRand(void) { return rand(); }
......
......@@ -13,13 +13,66 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// fail-fast or let-it-crash philosophy
// https://en.wikipedia.org/wiki/Fail-fast
// https://stackoverflow.com/questions/4393197/erlangs-let-it-crash-philosophy-applicable-elsewhere
// experimentally, we follow log-and-crash here
#define _DEFAULT_SOURCE
#include "os.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#include <windows.h>
bool taosCheckPthreadValid(pthread_t thread) { return thread.p != NULL; }
void taosResetPthread(pthread_t* thread) { thread->p = 0; }
int64_t taosGetPthreadId(pthread_t thread) {
#ifdef PTW32_VERSION
return pthread_getw32threadid_np(thread);
#else
return (int64_t)thread;
#endif
}
int64_t taosGetSelfPthreadId() { return GetCurrentThreadId(); }
bool taosComparePthread(pthread_t first, pthread_t second) { return first.p == second.p; }
int32_t taosGetPId() { return GetCurrentProcessId(); }
int32_t taosGetCurrentAPPName(char* name, int32_t* len) {
char filepath[1024] = {0};
GetModuleFileName(NULL, filepath, MAX_PATH);
char* sub = strrchr(filepath, '.');
if (sub != NULL) {
*sub = '\0';
}
strcpy(name, filepath);
if (len != NULL) {
*len = (int32_t)strlen(filepath);
}
return 0;
}
int32_t tsem_wait(tsem_t* sem) {
int ret = 0;
do {
ret = sem_wait(sem);
} while (ret != 0 && errno == EINTR);
return ret;
}
#elif defined(_TD_DARWIN_64)
/*
* darwin implementation
*/
#include <libproc.h>
// #define SEM_USE_PTHREAD
......@@ -27,8 +80,8 @@
#define SEM_USE_SEM
#ifdef SEM_USE_SEM
#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach_init.h>
#include <mach/semaphore.h>
#include <mach/task.h>
#include <pthread.h>
......@@ -39,7 +92,7 @@ static task_t sem_port;
static volatile int sem_inited = 0;
static semaphore_t sem_exit;
static void* sem_thread_routine(void *arg) {
static void *sem_thread_routine(void *arg) {
(void)arg;
setThreadName("sem_thrd");
......@@ -62,7 +115,7 @@ static void once_init(void) {
fprintf(stderr, "==%s[%d]%s()==failed to create thread\n", basename(__FILE__), __LINE__, __func__);
return;
}
while (sem_inited==0) {
while (sem_inited == 0) {
;
}
}
......@@ -75,14 +128,14 @@ struct tsem_s {
volatile int64_t val;
#elif defined(SEM_USE_POSIX)
size_t id;
sem_t *sem;
sem_t * sem;
#elif defined(SEM_USE_SEM)
semaphore_t sem;
#else // SEM_USE_PTHREAD
dispatch_semaphore_t sem;
#endif // SEM_USE_PTHREAD
volatile unsigned int valid:1;
volatile unsigned int valid : 1;
};
int tsem_init(tsem_t *sem, int pshared, unsigned int value) {
......@@ -91,7 +144,7 @@ int tsem_init(tsem_t *sem, int pshared, unsigned int value) {
fprintf(stderr, "==%s[%d]%s():[%p]==already initialized\n", basename(__FILE__), __LINE__, __func__, sem);
abort();
}
struct tsem_s *p = (struct tsem_s*)calloc(1, sizeof(*p));
struct tsem_s *p = (struct tsem_s *)calloc(1, sizeof(*p));
if (!p) {
fprintf(stderr, "==%s[%d]%s():[%p]==out of memory\n", basename(__FILE__), __LINE__, __func__, sem);
abort();
......@@ -116,24 +169,25 @@ int tsem_init(tsem_t *sem, int pshared, unsigned int value) {
static size_t tick = 0;
do {
size_t id = atomic_add_fetch_64(&tick, 1);
if (id==SEM_VALUE_MAX) {
if (id == SEM_VALUE_MAX) {
atomic_store_64(&tick, 0);
id = 0;
}
char name[NAME_MAX-4];
char name[NAME_MAX - 4];
snprintf(name, sizeof(name), "/t%ld", id);
p->sem = sem_open(name, O_CREAT|O_EXCL, pshared, value);
p->sem = sem_open(name, O_CREAT | O_EXCL, pshared, value);
p->id = id;
if (p->sem!=SEM_FAILED) break;
if (p->sem != SEM_FAILED) break;
int e = errno;
if (e==EEXIST) continue;
if (e==EINTR) continue;
fprintf(stderr, "==%s[%d]%s():[%p]==not created[%d]%s\n", basename(__FILE__), __LINE__, __func__, sem, e, strerror(e));
if (e == EEXIST) continue;
if (e == EINTR) continue;
fprintf(stderr, "==%s[%d]%s():[%p]==not created[%d]%s\n", basename(__FILE__), __LINE__, __func__, sem, e,
strerror(e));
abort();
} while (p->sem==SEM_FAILED);
} while (p->sem == SEM_FAILED);
#elif defined(SEM_USE_SEM)
pthread_once(&sem_once, once_init);
if (sem_inited!=1) {
if (sem_inited != 1) {
fprintf(stderr, "==%s[%d]%s():[%p]==internal resource init failed\n", basename(__FILE__), __LINE__, __func__, sem);
errno = ENOMEM;
return -1;
......@@ -263,12 +317,13 @@ int tsem_destroy(tsem_t *sem) {
abort();
}
#elif defined(SEM_USE_POSIX)
char name[NAME_MAX-4];
char name[NAME_MAX - 4];
snprintf(name, sizeof(name), "/t%ld", p->id);
int r = sem_unlink(name);
if (r) {
int e = errno;
fprintf(stderr, "==%s[%d]%s():[%p]==unlink failed[%d]%s\n", basename(__FILE__), __LINE__, __func__, sem, e, strerror(e));
fprintf(stderr, "==%s[%d]%s():[%p]==unlink failed[%d]%s\n", basename(__FILE__), __LINE__, __func__, sem, e,
strerror(e));
abort();
}
#elif defined(SEM_USE_SEM)
......@@ -292,29 +347,21 @@ bool taosCheckPthreadValid(pthread_t thread) {
int64_t taosGetSelfPthreadId() {
uint64_t id;
pthread_threadid_np(0, &id);
return (int64_t) id;
return (int64_t)id;
}
int64_t taosGetPthreadId(pthread_t thread) {
return (int64_t)thread;
}
int64_t taosGetPthreadId(pthread_t thread) { return (int64_t)thread; }
void taosResetPthread(pthread_t* thread) {
*thread = NULL;
}
void taosResetPthread(pthread_t *thread) { *thread = NULL; }
bool taosComparePthread(pthread_t first, pthread_t second) {
return pthread_equal(first, second) ? true : false;
}
bool taosComparePthread(pthread_t first, pthread_t second) { return pthread_equal(first, second) ? true : false; }
int32_t taosGetPId() {
return (int32_t)getpid();
}
int32_t taosGetPId() { return (int32_t)getpid(); }
int32_t taosGetCurrentAPPName(char* name, int32_t* len) {
char buf[PATH_MAX+1];
int32_t taosGetCurrentAPPName(char *name, int32_t *len) {
char buf[PATH_MAX + 1];
buf[0] = '\0';
proc_name(getpid(), buf, sizeof(buf)-1);
proc_name(getpid(), buf, sizeof(buf) - 1);
buf[PATH_MAX] = '\0';
size_t n = strlen(buf);
if (len) *len = n;
......@@ -322,4 +369,59 @@ int32_t taosGetCurrentAPPName(char* name, int32_t* len) {
return 0;
}
#else
/*
* linux implementation
*/
#include <sys/syscall.h>
bool taosCheckPthreadValid(pthread_t thread) { return thread != 0; }
int64_t taosGetSelfPthreadId() {
static __thread int id = 0;
if (id != 0) return id;
id = syscall(SYS_gettid);
return id;
}
int64_t taosGetPthreadId(pthread_t thread) { return (int64_t)thread; }
void taosResetPthread(pthread_t* thread) { *thread = 0; }
bool taosComparePthread(pthread_t first, pthread_t second) { return first == second; }
int32_t taosGetPId() { return getpid(); }
int32_t taosGetCurrentAPPName(char* name, int32_t* len) {
const char* self = "/proc/self/exe";
char path[PATH_MAX] = {0};
if (readlink(self, path, PATH_MAX) <= 0) {
return -1;
}
path[PATH_MAX - 1] = 0;
char* end = strrchr(path, '/');
if (end == NULL) {
return -1;
}
++end;
strcpy(name, end);
if (len != NULL) {
*len = strlen(name);
}
return 0;
}
int32_t tsem_wait(tsem_t* sem) {
int ret = 0;
do {
ret = sem_wait(sem);
} while (ret != 0 && errno == EINTR);
return ret;
}
#endif
......@@ -15,7 +15,13 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include <signal.h>
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#include <windows.h>
typedef void (*FWinSignalHandler)(int32_t signum);
......@@ -40,3 +46,29 @@ void taosDflSignal(int32_t signum) {
if (signum == SIGUSR1 || signum == SIGHUP) return;
signal(signum, SIG_DFL);
}
#else
/*
* linux and darwin implementation
*/
typedef void (*FLinuxSignalHandler)(int32_t signum, siginfo_t *sigInfo, void *context);
void taosSetSignal(int32_t signum, FSignalHandler sigfp) {
struct sigaction act;
memset(&act, 0, sizeof(act));
#if 1
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = (FLinuxSignalHandler)sigfp;
#else
act.sa_handler = sigfp;
#endif
sigaction(signum, &act, NULL);
}
void taosIgnSignal(int32_t signum) { signal(signum, SIG_IGN); }
void taosDflSignal(int32_t signum) { signal(signum, SIG_DFL); }
#endif
......@@ -16,6 +16,19 @@
#define _DEFAULT_SOURCE
#include "os.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
void taosShutDownSocketRD(SOCKET fd) {
#ifdef WINDOWS
closesocket(fd);
......@@ -41,7 +54,7 @@ void taosShutDownSocketWR(SOCKET fd) {
int32_t taosSetNonblocking(SOCKET sock, int32_t on) {
int32_t flags = 0;
if ((flags = fcntl(sock, F_GETFL, 0)) < 0) {
uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno));
printf("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno));
return 1;
}
......@@ -51,16 +64,14 @@ int32_t taosSetNonblocking(SOCKET sock, int32_t on) {
flags &= ~O_NONBLOCK;
if ((flags = fcntl(sock, F_SETFL, flags)) < 0) {
uError("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno));
printf("fcntl(F_SETFL) error: %d (%s)\n", errno, strerror(errno));
return 1;
}
return 0;
}
void taosIgnSIGPIPE() {
signal(SIGPIPE, SIG_IGN);
}
void taosIgnSIGPIPE() { signal(SIGPIPE, SIG_IGN); }
void taosBlockSIGPIPE() {
sigset_t signal_mask;
......@@ -68,7 +79,7 @@ void taosBlockSIGPIPE() {
sigaddset(&signal_mask, SIGPIPE);
int32_t rc = pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
if (rc != 0) {
uError("failed to block SIGPIPE");
printf("failed to block SIGPIPE");
}
}
......@@ -78,7 +89,7 @@ void taosSetMaskSIGPIPE() {
sigaddset(&signal_mask, SIGPIPE);
int32_t rc = pthread_sigmask(SIG_SETMASK, &signal_mask, NULL);
if (rc != 0) {
uError("failed to setmask SIGPIPE");
printf("failed to setmask SIGPIPE");
}
}
......@@ -90,23 +101,113 @@ int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *op
return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen);
}
int32_t taosGetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t* optlen) {
int32_t taosGetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t *optlen) {
return getsockopt(socketfd, level, optname, optval, (socklen_t *)optlen);
}
#endif
#if !( (defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) && defined(_MSC_VER) )
#if !((defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)) && defined(_MSC_VER))
uint32_t taosInetAddr(char *ipAddr) {
return inet_addr(ipAddr);
uint32_t taosInetAddr(char *ipAddr) { return inet_addr(ipAddr); }
const char *taosInetNtoa(struct in_addr ipInt) { return inet_ntoa(ipInt); }
#endif
#if defined(_TD_DARWIN_64)
/*
* darwin implementation
*/
int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) {
if (level == SOL_SOCKET && optname == SO_SNDBUF) {
return 0;
}
if (level == SOL_SOCKET && optname == SO_RCVBUF) {
return 0;
}
return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen);
}
#endif
const char *taosInetNtoa(struct in_addr ipInt) {
return inet_ntoa(ipInt);
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#include <IPHlpApi.h>
#include <WS2tcpip.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <winsock2.h>
#include <ws2def.h>
void taosWinSocketInit() {
static char flag = 0;
if (flag == 0) {
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested, &wsaData) == 0) {
flag = 1;
}
}
}
#else
int32_t taosSetNonblocking(SOCKET sock, int32_t on) {
u_long mode;
if (on) {
mode = 1;
ioctlsocket(sock, FIONBIO, &mode);
} else {
mode = 0;
ioctlsocket(sock, FIONBIO, &mode);
}
return 0;
}
void taosIgnSIGPIPE() {}
void taosBlockSIGPIPE() {}
void taosSetMaskSIGPIPE() {}
int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t optlen) {
if (level == SOL_SOCKET && optname == TCP_KEEPCNT) {
return 0;
}
if (level == SOL_TCP && optname == TCP_KEEPIDLE) {
return 0;
}
if (level == SOL_TCP && optname == TCP_KEEPINTVL) {
return 0;
}
if (level == SOL_TCP && optname == TCP_KEEPCNT) {
return 0;
}
return setsockopt(socketfd, level, optname, optval, optlen);
}
#ifdef _MSC_VER
//#if _MSC_VER >= 1900
uint32_t taosInetAddr(char *ipAddr) {
uint32_t value;
int32_t ret = inet_pton(AF_INET, ipAddr, &value);
if (ret <= 0) {
return INADDR_NONE;
} else {
return value;
}
}
const char *taosInetNtoa(struct in_addr ipInt) {
// not thread safe, only for debug usage while print log
......@@ -114,11 +215,13 @@ const char *taosInetNtoa(struct in_addr ipInt) {
return inet_ntop(AF_INET, &ipInt, tmpDstStr, INET6_ADDRSTRLEN);
}
//#endif
#endif
#if defined(_TD_GO_DLL_)
uint64_t htonll(uint64_t val) { return (((uint64_t)htonl(val)) << 32) + htonl(val >> 32); }
#endif
#endif
\ No newline at end of file
......@@ -15,11 +15,229 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tglobal.h"
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
#include <wchar.h>
#include <wctype.h>
typedef struct CharsetPair {
char *oldCharset;
char *newCharset;
} CharsetPair;
char *taosCharsetReplace(char *charsetstr) {
CharsetPair charsetRep[] = {
{ "utf8", "UTF-8" }, { "936", "CP936" },
};
for (int32_t i = 0; i < tListLen(charsetRep); ++i) {
if (strcasecmp(charsetRep[i].oldCharset, charsetstr) == 0) {
return strdup(charsetRep[i].newCharset);
}
}
return strdup(charsetstr);
}
int64_t taosStr2int64(char *str) {
char *endptr = NULL;
return strtoll(str, &endptr, 10);
}
#ifdef USE_LIBICONV
#include "iconv.h"
int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) {
iconv_t cd = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
size_t ucs4_input_len = ucs4_max_len;
size_t outLen = ucs4_max_len;
if (iconv(cd, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
iconv_close(cd);
return -1;
}
iconv_close(cd);
return (int32_t)(ucs4_max_len - outLen);
}
bool taosMbsToUcs4(char *mbs, size_t mbsLength, char *ucs4, int32_t ucs4_max_len, int32_t *len) {
memset(ucs4, 0, ucs4_max_len);
iconv_t cd = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
size_t ucs4_input_len = mbsLength;
size_t outLeft = ucs4_max_len;
if (iconv(cd, &mbs, &ucs4_input_len, &ucs4, &outLeft) == -1) {
iconv_close(cd);
return false;
}
iconv_close(cd);
if (len != NULL) {
*len = (int32_t)(ucs4_max_len - outLeft);
if (*len < 0) {
return false;
}
}
return true;
}
bool taosValidateEncodec(const char *encodec) {
iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
if (cd == (iconv_t)(-1)) {
return false;
}
iconv_close(cd);
return true;
}
#else
int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) {
mbstate_t state = {0};
int32_t len = (int32_t)wcsnrtombs(NULL, (const wchar_t **)&ucs4, ucs4_max_len / 4, 0, &state);
if (len < 0) {
return -1;
}
memset(&state, 0, sizeof(state));
len = wcsnrtombs(mbs, (const wchar_t **)&ucs4, ucs4_max_len / 4, (size_t)len, &state);
if (len < 0) {
return -1;
}
return len;
}
bool taosMbsToUcs4(char *mbs, size_t mbsLength, char *ucs4, int32_t ucs4_max_len, int32_t *len) {
memset(ucs4, 0, ucs4_max_len);
mbstate_t state = {0};
int32_t retlen = mbsnrtowcs((wchar_t *)ucs4, (const char **)&mbs, mbsLength, ucs4_max_len / 4, &state);
*len = retlen;
return retlen >= 0;
}
bool taosValidateEncodec(const char *encodec) {
return true;
}
#endif
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <stdint.h>
#if STDC_HEADERS
#include <stdlib.h>
#else
char *malloc(), *realloc();
#endif
/* Always add at least this many bytes when extending the buffer. */
#define MIN_CHUNK 64
/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
+ OFFSET (and null-terminate it). *LINEPTR is a pointer returned from
malloc (or NULL), pointing to *N characters of space. It is realloc'd
as necessary. Return the number of characters read (not including the
null terminator), or -1 on error or EOF. On a -1 return, the caller
should check feof(), if not then errno has been set to indicate
the error. */
int32_t getstr(char **lineptr, size_t *n, FILE *stream, char terminator, int32_t offset) {
int32_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */
char * read_pos; /* Where we're reading into *LINEPTR. */
int32_t ret;
if (!lineptr || !n || !stream) {
errno = EINVAL;
return -1;
}
if (!*lineptr) {
*n = MIN_CHUNK;
*lineptr = malloc(*n);
if (!*lineptr) {
errno = ENOMEM;
return -1;
}
}
nchars_avail = (int32_t)(*n - offset);
read_pos = *lineptr + offset;
for (;;) {
int32_t save_errno;
register int32_t c = getc(stream);
save_errno = errno;
/* We always want at least one char left in the buffer, since we
always (unless we get an error while reading the first char)
NUL-terminate the line buffer. */
assert((*lineptr + *n) == (read_pos + nchars_avail));
if (nchars_avail < 2) {
if (*n > MIN_CHUNK)
*n *= 2;
else
*n += MIN_CHUNK;
nchars_avail = (int32_t)(*n + *lineptr - read_pos);
char* lineptr1 = realloc(*lineptr, *n);
if (!lineptr1) {
errno = ENOMEM;
return -1;
}
*lineptr = lineptr1;
read_pos = *n - nchars_avail + *lineptr;
assert((*lineptr + *n) == (read_pos + nchars_avail));
}
if (ferror(stream)) {
/* Might like to return partial line, but there is no
place for us to store errno. And we don't want to just
lose errno. */
errno = save_errno;
return -1;
}
if (c == EOF) {
/* Return partial line, if any. */
if (read_pos == *lineptr)
return -1;
else
break;
}
*read_pos++ = c;
nchars_avail--;
if (c == terminator) /* Return the line. */
break;
}
/* Done - NUL terminate and return the number of chars read. */
*read_pos = '\0';
ret = (int32_t)(read_pos - (*lineptr + offset));
return ret;
}
int32_t tgetline(char **lineptr, size_t *n, FILE *stream) { return getstr(lineptr, n, stream, '\n', 0); }
/*
* Get next token from string *stringp, where tokens are possibly-empty
......@@ -150,3 +368,15 @@ char *stpncpy (char *dest, const char *src, size_t n) {
return dest;
return memset (dest, '\0', n - size);
}
#else
/*
* linux and darwin implementation
*/
int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes, int8_t ncharSize) {
return wcsncmp((wchar_t *)f1_ucs4, (wchar_t *)f2_ucs4, bytes / ncharSize);
}
#endif
\ No newline at end of file
......@@ -37,6 +37,9 @@
*/
//
//#include "lukemftp.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#include <time.h>
#include <stdlib.h>
#include <string.h>
......@@ -396,3 +399,5 @@ conv_num(const char **buf, int *dest, int llim, int ulim)
*dest = result;
return (1);
}
#endif
\ No newline at end of file
......@@ -15,12 +15,476 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "taoserror.h"
#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) || defined (_TD_DARWIN_64))
int32_t tsTotalMemoryMB = 0;
int64_t tsPageSize = 0;
int64_t tsOpenMax = 0;
int64_t tsStreamMax = 0;
int32_t tsNumOfCores = 1;
char tsTimezone[TSDB_TIMEZONE_LEN] = {0};
char tsLocale[TSDB_LOCALE_LEN] = {0};
char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#if (_WIN64)
#include <iphlpapi.h>
#include <mswsock.h>
#include <psapi.h>
#include <stdio.h>
#include <windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Mswsock.lib ")
#endif
#include <objbase.h>
#pragma warning(push)
#pragma warning(disable : 4091)
#include <DbgHelp.h>
#pragma warning(pop)
static int32_t taosGetTotalMemory() {
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) {
return 0;
}
float nMemTotal = memsStat.ullTotalPhys / (1024.0f * 1024.0f);
return (int32_t)nMemTotal;
}
bool taosGetSysMemory(float *memoryUsedMB) {
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) {
return false;
}
float nMemFree = memsStat.ullAvailPhys / (1024.0f * 1024.0f);
float nMemTotal = memsStat.ullTotalPhys / (1024.0f * 1024.0f);
*memoryUsedMB = nMemTotal - nMemFree;
return true;
}
bool taosGetProcMemory(float *memoryUsedMB) {
unsigned bytes_used = 0;
#if defined(_WIN64) && defined(_MSC_VER)
PROCESS_MEMORY_COUNTERS pmc;
HANDLE cur_proc = GetCurrentProcess();
if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) {
bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage);
}
#endif
*memoryUsedMB = (float)bytes_used / 1024 / 1024;
return true;
}
static void taosGetSystemTimezone() {
// get and set default timezone
char *tz = getenv("TZ");
if (tz == NULL || strlen(tz) == 0) {
strcpy(tsTimezone, "not configured");
} else {
strcpy(tsTimezone, tz);
}
}
static void taosGetSystemLocale() {
// get and set default locale
char *locale = setlocale(LC_CTYPE, "chs");
if (locale != NULL) {
tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN);
}
strcpy(tsCharset, "cp936");
}
int32_t taosGetCpuCores() {
SYSTEM_INFO info;
GetSystemInfo(&info);
return (int32_t)info.dwNumberOfProcessors;
}
bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) {
*sysCpuUsage = 0;
*procCpuUsage = 0;
return true;
}
int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) {
unsigned _int64 i64FreeBytesToCaller;
unsigned _int64 i64TotalBytes;
unsigned _int64 i64FreeBytes;
BOOL fResult = GetDiskFreeSpaceExA(dataDir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
if (fResult) {
diskSize->tsize = (int64_t)(i64TotalBytes);
diskSize->avail = (int64_t)(i64FreeBytesToCaller);
diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes);
return 0;
} else {
printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
}
}
bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes) {
if (bytes) *bytes = 0;
if (rbytes) *rbytes = 0;
if (tbytes) *tbytes = 0;
return true;
}
bool taosGetBandSpeed(float *bandSpeedKb) {
*bandSpeedKb = 0;
return true;
}
bool taosReadProcIO(int64_t *readbyte, int64_t *writebyte) {
IO_COUNTERS io_counter;
if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) {
if (readbyte) *readbyte = io_counter.ReadTransferCount;
if (writebyte) *writebyte = io_counter.WriteTransferCount;
return true;
}
return false;
}
bool taosGetProcIO(float *readKB, float *writeKB) {
static int64_t lastReadbyte = -1;
static int64_t lastWritebyte = -1;
int64_t curReadbyte = 0;
int64_t curWritebyte = 0;
if (!taosReadProcIO(&curReadbyte, &curWritebyte)) {
return false;
}
if (lastReadbyte == -1 || lastWritebyte == -1) {
lastReadbyte = curReadbyte;
lastWritebyte = curWritebyte;
return false;
}
*readKB = (float)((double)(curReadbyte - lastReadbyte) / 1024);
*writeKB = (float)((double)(curWritebyte - lastWritebyte) / 1024);
if (*readKB < 0) *readKB = 0;
if (*writeKB < 0) *writeKB = 0;
lastReadbyte = curReadbyte;
lastWritebyte = curWritebyte;
return true;
}
void taosGetSystemInfo() {
tsNumOfCores = taosGetCpuCores();
tsTotalMemoryMB = taosGetTotalMemory();
float tmp1, tmp2;
// taosGetDisk();
taosGetBandSpeed(&tmp1);
taosGetCpuUsage(&tmp1, &tmp2);
taosGetProcIO(&tmp1, &tmp2);
taosGetSystemTimezone();
taosGetSystemLocale();
}
void taosKillSystem() {
printf("function taosKillSystem, exit!");
exit(0);
}
int taosSystem(const char *cmd) {
printf("taosSystem not support");
return -1;
}
LONG WINAPI FlCrashDump(PEXCEPTION_POINTERS ep) {
typedef BOOL(WINAPI * FxMiniDumpWriteDump)(IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile,
IN MINIDUMP_TYPE DumpType,
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
HMODULE dll = LoadLibrary("dbghelp.dll");
if (dll == NULL) return EXCEPTION_CONTINUE_SEARCH;
FxMiniDumpWriteDump mdwd = (FxMiniDumpWriteDump)(GetProcAddress(dll, "MiniDumpWriteDump"));
if (mdwd == NULL) {
FreeLibrary(dll);
return EXCEPTION_CONTINUE_SEARCH;
}
TCHAR path[MAX_PATH];
DWORD len = GetModuleFileName(NULL, path, _countof(path));
path[len - 3] = 'd';
path[len - 2] = 'm';
path[len - 1] = 'p';
HANDLE file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = ep;
mei.ClientPointers = FALSE;
(*mdwd)(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpWithHandleData, &mei, NULL, NULL);
CloseHandle(file);
FreeLibrary(dll);
return EXCEPTION_CONTINUE_SEARCH;
}
void taosSetCoreDump() { SetUnhandledExceptionFilter(&FlCrashDump); }
bool taosGetSystemUid(char *uid) {
GUID guid;
CoCreateGuid(&guid);
sprintf(uid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0],
guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
return true;
}
char *taosGetCmdlineByPID(int pid) { return ""; }
#elif defined(_TD_DARWIN_64)
/*
* darwin implementation
*/
#include <errno.h>
#include <libproc.h>
static void taosGetSystemTimezone() {
/* load time zone string from /etc/localtime */
char buf[4096];
char *tz = NULL;
{
int n = readlink("/etc/localtime", buf, sizeof(buf));
if (n < 0) {
printf("read /etc/localtime error, reason:%s", strerror(errno));
return;
}
buf[n] = '\0';
for (int i = n - 1; i >= 0; --i) {
if (buf[i] == '/') {
if (tz) {
tz = buf + i + 1;
break;
}
tz = buf + i + 1;
}
}
if (!tz || 0 == strchr(tz, '/')) {
printf("parsing /etc/localtime failed");
return;
}
setenv("TZ", tz, 1);
tzset();
}
/*
* NOTE: do not remove it.
* Enforce set the correct daylight saving time(DST) flag according
* to current time
*/
time_t tx1 = time(NULL);
struct tm tm1;
localtime_r(&tx1, &tm1);
/*
* format example:
*
* Asia/Shanghai (CST, +0800)
* Europe/London (BST, +0100)
*/
snprintf(tsTimezone, TSDB_TIMEZONE_LEN, "%s (%s, %+03ld00)", tz, tm1.tm_isdst ? tzname[daylight] : tzname[0],
-timezone / 3600);
// cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
printf("timezone not configured, set to system default:%s", tsTimezone);
}
/*
* originally from src/os/src/detail/osSysinfo.c
* POSIX format locale string:
* (Language Strings)_(Country/Region Strings).(code_page)
*
* example: en_US.UTF-8, zh_CN.GB18030, zh_CN.UTF-8,
*
* if user does not specify the locale in taos.cfg the program use default LC_CTYPE as system locale.
*
* In case of some CentOS systems, their default locale is "en_US.utf8", which is not valid code_page
* for libiconv that is employed to convert string in this system. This program will automatically use
* UTF-8 instead as the charset.
*
* In case of windows client, the locale string is not valid POSIX format, user needs to set the
* correct code_page for libiconv. Usually, the code_page of windows system with simple chinese is
* CP936, CP437 for English charset.
*
*/
static void taosGetSystemLocale() { // get and set default locale
char sep = '.';
char *locale = NULL;
locale = setlocale(LC_CTYPE, "");
if (locale == NULL) {
printf("can't get locale from system, set it to en_US.UTF-8 since error:%d:%s", errno, strerror(errno));
strcpy(tsLocale, "en_US.UTF-8");
} else {
tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN);
printf("locale not configured, set to system default:%s", tsLocale);
}
/* if user does not specify the charset, extract it from locale */
char *str = strrchr(tsLocale, sep);
if (str != NULL) {
str++;
char *revisedCharset = taosCharsetReplace(str);
tstrncpy(tsCharset, revisedCharset, TSDB_LOCALE_LEN);
free(revisedCharset);
printf("charset not configured, set to system default:%s", tsCharset);
} else {
strcpy(tsCharset, "UTF-8");
printf("can't get locale and charset from system, set it to UTF-8");
}
}
void taosKillSystem() {
printf("function taosKillSystem, exit!");
exit(0);
}
int32_t taosGetCpuCores() { return sysconf(_SC_NPROCESSORS_ONLN); }
void taosGetSystemInfo() {
// taosGetProcInfos();
tsNumOfCores = sysconf(_SC_NPROCESSORS_ONLN);
long physical_pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGESIZE);
tsTotalMemoryMB = physical_pages * page_size / (1024 * 1024);
tsPageSize = page_size;
taosGetSystemTimezone();
taosGetSystemLocale();
}
bool taosReadProcIO(int64_t *rchars, int64_t *wchars) {
if (rchars) *rchars = 0;
if (wchars) *wchars = 0;
return true;
}
bool taosGetProcIO(float *readKB, float *writeKB) {
*readKB = 0;
*writeKB = 0;
return true;
}
bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes) {
if (bytes) *bytes = 0;
if (rbytes) *rbytes = 0;
if (tbytes) *tbytes = 0;
return true;
}
bool taosGetBandSpeed(float *bandSpeedKb) {
*bandSpeedKb = 0;
return true;
}
bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) {
*sysCpuUsage = 0;
*procCpuUsage = 0;
return true;
}
bool taosGetProcMemory(float *memoryUsedMB) {
*memoryUsedMB = 0;
return true;
}
bool taosGetSysMemory(float *memoryUsedMB) {
*memoryUsedMB = 0;
return true;
}
int taosSystem(const char *cmd) {
printf("un support funtion");
return -1;
}
void taosSetCoreDump() {}
int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) {
struct statvfs info;
if (statvfs(dataDir, &info)) {
printf("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
} else {
diskSize->tsize = info.f_blocks * info.f_frsize;
diskSize->avail = info.f_bavail * info.f_frsize;
diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize;
return 0;
}
}
bool taosGetSystemUid(char *uid) {
uuid_t uuid = {0};
uuid_generate(uuid);
// it's caller's responsibility to make enough space for `uid`, that's 36-char + 1-null
uuid_unparse_lower(uuid, uid);
return true;
}
char *taosGetCmdlineByPID(int pid) {
static char cmdline[1024];
errno = 0;
if (proc_pidpath(pid, cmdline, sizeof(cmdline)) <= 0) {
fprintf(stderr, "PID is %d, %s", pid, strerror(errno));
return strerror(errno);
}
return cmdline;
}
#else
/*
* linux implementation
*/
#include <argp.h>
#include <linux/sysctl.h>
#include <sys/file.h>
#include <sys/resource.h>
#include <sys/statvfs.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#define PROCESS_ITEM 12
......@@ -70,7 +534,7 @@ bool taosGetSysMemory(float *memoryUsedMB) {
bool taosGetProcMemory(float *memoryUsedMB) {
FILE *fp = fopen(tsProcMemFile, "r");
if (fp == NULL) {
uError("open file:%s failed", tsProcMemFile);
printf("open file:%s failed", tsProcMemFile);
return false;
}
......@@ -90,7 +554,7 @@ bool taosGetProcMemory(float *memoryUsedMB) {
}
if (line == NULL) {
uError("read file:%s failed", tsProcMemFile);
printf("read file:%s failed", tsProcMemFile);
fclose(fp);
return false;
}
......@@ -108,7 +572,7 @@ bool taosGetProcMemory(float *memoryUsedMB) {
static bool taosGetSysCpuInfo(SysCpuInfo *cpuInfo) {
FILE *fp = fopen(tsSysCpuFile, "r");
if (fp == NULL) {
uError("open file:%s failed", tsSysCpuFile);
printf("open file:%s failed", tsSysCpuFile);
return false;
}
......@@ -116,7 +580,7 @@ static bool taosGetSysCpuInfo(SysCpuInfo *cpuInfo) {
char * line = NULL;
ssize_t _bytes = getline(&line, &len, fp);
if ((_bytes < 0) || (line == NULL)) {
uError("read file:%s failed", tsSysCpuFile);
printf("read file:%s failed", tsSysCpuFile);
fclose(fp);
return false;
}
......@@ -133,7 +597,7 @@ static bool taosGetSysCpuInfo(SysCpuInfo *cpuInfo) {
static bool taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) {
FILE *fp = fopen(tsProcCpuFile, "r");
if (fp == NULL) {
uError("open file:%s failed", tsProcCpuFile);
printf("open file:%s failed", tsProcCpuFile);
return false;
}
......@@ -141,7 +605,7 @@ static bool taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) {
char * line = NULL;
ssize_t _bytes = getline(&line, &len, fp);
if ((_bytes < 0) || (line == NULL)) {
uError("read file:%s failed", tsProcCpuFile);
printf("read file:%s failed", tsProcCpuFile);
fclose(fp);
return false;
}
......@@ -161,12 +625,6 @@ static bool taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) {
}
static void taosGetSystemTimezone() {
SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone");
if (cfg_timezone == NULL) return;
if (cfg_timezone->cfgStatus >= TAOS_CFG_CSTATUS_DEFAULT) {
return;
}
/*
* NOTE: do not remove it.
* Enforce set the correct daylight saving time(DST) flag according
......@@ -183,7 +641,7 @@ static void taosGetSystemTimezone() {
int len = fread(buf, 64, 1, f);
if (len < 64 && ferror(f)) {
fclose(f);
uError("read /etc/timezone error, reason:%s", strerror(errno));
printf("read /etc/timezone error, reason:%s", strerror(errno));
return;
}
......@@ -222,7 +680,7 @@ static void taosGetSystemTimezone() {
snprintf(tsTimezone, TSDB_TIMEZONE_LEN, "%s (%s, %s%02d00)", buf, tzname[daylight], tz >= 0 ? "+" : "-", abs(tz));
// cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uWarn("timezone not configured, set to system default:%s", tsTimezone);
printf("timezone not configured, set to system default:%s", tsTimezone);
}
/*
......@@ -246,21 +704,16 @@ static void taosGetSystemLocale() { // get and set default locale
char sep = '.';
char *locale = NULL;
SGlobalCfg *cfg_locale = taosGetConfigOption("locale");
if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
locale = setlocale(LC_CTYPE, "");
if (locale == NULL) {
uError("can't get locale from system, set it to en_US.UTF-8 since error:%d:%s", errno, strerror(errno));
printf("can't get locale from system, set it to en_US.UTF-8 since error:%d:%s", errno, strerror(errno));
strcpy(tsLocale, "en_US.UTF-8");
} else {
tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN);
uWarn("locale not configured, set to system default:%s", tsLocale);
}
printf("locale not configured, set to system default:%s", tsLocale);
}
/* if user does not specify the charset, extract it from locale */
SGlobalCfg *cfg_charset = taosGetConfigOption("charset");
if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
char *str = strrchr(tsLocale, sep);
if (str != NULL) {
str++;
......@@ -269,11 +722,10 @@ static void taosGetSystemLocale() { // get and set default locale
tstrncpy(tsCharset, revisedCharset, TSDB_LOCALE_LEN);
free(revisedCharset);
uWarn("charset not configured, set to system default:%s", tsCharset);
printf("charset not configured, set to system default:%s", tsCharset);
} else {
strcpy(tsCharset, "UTF-8");
uWarn("can't get locale and charset from system, set it to UTF-8");
}
printf("can't get locale and charset from system, set it to UTF-8");
}
}
......@@ -321,8 +773,7 @@ bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) {
int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) {
struct statvfs info;
if (statvfs(dataDir, &info)) {
uError("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
terrno = TAOS_SYSTEM_ERROR(errno);
printf("failed to get disk size, dataDir:%s errno:%s", dataDir, strerror(errno));
return -1;
} else {
diskSize->tsize = info.f_blocks * info.f_frsize;
......@@ -336,7 +787,7 @@ bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes) {
*bytes = 0;
FILE *fp = fopen(tsSysNetFile, "r");
if (fp == NULL) {
uError("open file:%s failed", tsSysNetFile);
printf("open file:%s failed", tsSysNetFile);
return false;
}
......@@ -360,8 +811,7 @@ bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes) {
char nouse0[200] = {0};
_bytes = getline(&line, &len, fp);
if (_bytes < 0)
{
if (_bytes < 0) {
break;
}
......@@ -413,7 +863,7 @@ bool taosGetBandSpeed(float *bandSpeedKb) {
double totalBytes = (double)(curBytes - lastBytes) / 1024 * 8; // Kb
*bandSpeedKb = (float)(totalBytes / (double)(curTime - lastTime));
// uInfo("bandwidth lastBytes:%ld, lastTime:%ld, curBytes:%ld, curTime:%ld,
// printf("bandwidth lastBytes:%ld, lastTime:%ld, curBytes:%ld, curTime:%ld,
// speed:%f", lastBytes, lastTime, curBytes, curTime, *bandSpeed);
lastTime = curTime;
......@@ -425,7 +875,7 @@ bool taosGetBandSpeed(float *bandSpeedKb) {
bool taosReadProcIO(int64_t *rchars, int64_t *wchars) {
FILE *fp = fopen(tsProcIOFile, "r");
if (fp == NULL) {
uError("open file:%s failed", tsProcIOFile);
printf("open file:%s failed", tsProcIOFile);
return false;
}
......@@ -458,7 +908,7 @@ bool taosReadProcIO(int64_t *rchars, int64_t *wchars) {
fclose(fp);
if (readIndex < 2) {
uError("read file:%s failed", tsProcIOFile);
printf("read file:%s failed", tsProcIOFile);
return false;
}
......@@ -511,36 +961,9 @@ void taosGetSystemInfo() {
taosGetSystemLocale();
}
void taosPrintOsInfo() {
uInfo(" os pageSize: %" PRId64 "(KB)", tsPageSize);
uInfo(" os openMax: %" PRId64, tsOpenMax);
uInfo(" os streamMax: %" PRId64, tsStreamMax);
uInfo(" os numOfCores: %d", tsNumOfCores);
uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB);
struct utsname buf;
if (uname(&buf)) {
uInfo(" can't fetch os info");
return;
}
uInfo(" os sysname: %s", buf.sysname);
uInfo(" os nodename: %s", buf.nodename);
uInfo(" os release: %s", buf.release);
uInfo(" os version: %s", buf.version);
uInfo(" os machine: %s", buf.machine);
}
void taosPrintDiskInfo() {
uInfo("==================================");
uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB);
uInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB);
uInfo(" os availDisk: %f(GB)", tsAvailDataDirGB);
uInfo("==================================");
}
void taosKillSystem() {
// SIGINT
uInfo("taosd will shut down soon");
printf("taosd will shut down soon");
kill(tsProcId, 2);
}
......@@ -549,46 +972,44 @@ int taosSystem(const char *cmd) {
int res;
char buf[1024];
if (cmd == NULL) {
uError("taosSystem cmd is NULL!");
printf("taosSystem cmd is NULL!");
return -1;
}
if ((fp = popen(cmd, "r")) == NULL) {
uError("popen cmd:%s error: %s", cmd, strerror(errno));
printf("popen cmd:%s error: %s", cmd, strerror(errno));
return -1;
} else {
while (fgets(buf, sizeof(buf), fp)) {
uDebug("popen result:%s", buf);
printf("popen result:%s", buf);
}
if ((res = pclose(fp)) == -1) {
uError("close popen file pointer fp error!");
printf("close popen file pointer fp error!");
} else {
uDebug("popen res is :%d", res);
printf("popen res is :%d", res);
}
return res;
}
}
void taosSetCoreDump() {
if (0 == tsEnableCoreFile) {
return;
}
void taosSetCoreDump(bool enable) {
if (!enable) return;
// 1. set ulimit -c unlimited
struct rlimit rlim;
struct rlimit rlim_new;
if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
#ifndef _ALPINE
uInfo("the old unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
printf("the old unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
#else
uInfo("the old unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
printf("the old unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
#endif
rlim_new.rlim_cur = RLIM_INFINITY;
rlim_new.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim_new) != 0) {
uInfo("set unlimited fail, error: %s", strerror(errno));
printf("set unlimited fail, error: %s", strerror(errno));
rlim_new.rlim_cur = rlim.rlim_max;
rlim_new.rlim_max = rlim.rlim_max;
(void)setrlimit(RLIMIT_CORE, &rlim_new);
......@@ -597,9 +1018,9 @@ void taosSetCoreDump() {
if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
#ifndef _ALPINE
uInfo("the new unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
printf("the new unlimited para: rlim_cur=%" PRIu64 ", rlim_max=%" PRIu64, rlim.rlim_cur, rlim.rlim_max);
#else
uInfo("the new unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
printf("the new unlimited para: rlim_cur=%llu, rlim_max=%llu", rlim.rlim_cur, rlim.rlim_max);
#endif
}
......@@ -625,10 +1046,10 @@ void taosSetCoreDump() {
old_len = sizeof(old_usespid);
if (syscall(SYS__sysctl, &args) == -1) {
uInfo("_sysctl(kern_core_uses_pid) set fail: %s", strerror(errno));
printf("_sysctl(kern_core_uses_pid) set fail: %s", strerror(errno));
}
uInfo("The old core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
printf("The old core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
old_usespid = 0;
old_len = 0;
......@@ -641,14 +1062,14 @@ void taosSetCoreDump() {
old_len = sizeof(old_usespid);
if (syscall(SYS__sysctl, &args) == -1) {
uInfo("_sysctl(kern_core_uses_pid) get fail: %s", strerror(errno));
printf("_sysctl(kern_core_uses_pid) get fail: %s", strerror(errno));
}
uInfo("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
printf("The new core_uses_pid[%" PRIu64 "]: %d", old_len, old_usespid);
#endif
}
bool taosGetSystemUid(char *uid) {
bool taosGetSystemUid(char *uid, int32_t uidlen) {
int fd;
int len = 0;
......@@ -656,7 +1077,7 @@ bool taosGetSystemUid(char *uid) {
if (fd < 0) {
return false;
} else {
len = read(fd, uid, TSDB_CLUSTER_ID_LEN);
len = read(fd, uid, uidlen);
close(fd);
}
......@@ -667,4 +1088,43 @@ bool taosGetSystemUid(char *uid) {
return false;
}
char *taosGetCmdlineByPID(int pid) {
static char cmdline[1024];
sprintf(cmdline, "/proc/%d/cmdline", pid);
int fd = open(cmdline, O_RDONLY);
if (fd >= 0) {
int n = read(fd, cmdline, sizeof(cmdline) - 1);
if (n < 0) n = 0;
if (n > 0 && cmdline[n - 1] == '\n') --n;
cmdline[n] = 0;
close(fd);
} else {
cmdline[0] = 0;
}
return cmdline;
}
#endif
#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32))
SysNameInfo taosGetSysNameInfo() {
SysNameInfo info = {0};
struct utsname buf;
if (!uname(&buf)) {
info.sysname = buf.sysname;
info.sysname == buf.nodename;
info.sysname = buf.release;
info.sysname = buf.version;
info.sysname = buf.machine;
}
return info;
}
#endif
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
void* taosLoadDll(const char* filename) { return NULL; }
void* taosLoadSym(void* handle, char* name) { return NULL; }
void taosCloseDll(void* handle) {}
int taosSetConsoleEcho(bool on) {
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0;
GetConsoleMode(hStdin, &mode);
if (on) {
mode |= ENABLE_ECHO_INPUT;
} else {
mode &= ~ENABLE_ECHO_INPUT;
}
SetConsoleMode(hStdin, mode);
return 0;
}
#elif defined(_TD_DARWIN_64)
/*
* darwin implementation
*/
void* taosLoadDll(const char* filename) { return NULL; }
void* taosLoadSym(void* handle, char* name) { return NULL; }
void taosCloseDll(void* handle) {}
int taosSetConsoleEcho(bool on) {
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
int err;
struct termios term;
if (tcgetattr(STDIN_FILENO, &term) == -1) {
perror("Cannot get the attribution of the terminal");
return -1;
}
if (on)
term.c_lflag |= ECHOFLAGS;
else
term.c_lflag &= ~ECHOFLAGS;
err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
if (err == -1 && err == EINTR) {
perror("Cannot set the attribution of the terminal");
return -1;
}
return 0;
}
#else
/*
* linux implementation
*/
#include <dlfcn.h>
#include <termios.h>
#include <unistd.h>
void* taosLoadDll(const char* filename) {
void* handle = dlopen(filename, RTLD_LAZY);
if (!handle) {
printf("load dll:%s failed, error:%s", filename, dlerror());
return NULL;
}
printf("dll %s loaded", filename);
return handle;
}
void* taosLoadSym(void* handle, char* name) {
void* sym = dlsym(handle, name);
char* error = NULL;
if ((error = dlerror()) != NULL) {
printf("load sym:%s failed, error:%s", name, dlerror());
return NULL;
}
printf("sym %s loaded", name);
return sym;
}
void taosCloseDll(void* handle) {
if (handle) {
dlclose(handle);
}
}
int taosSetConsoleEcho(bool on) {
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
int err;
struct termios term;
if (tcgetattr(STDIN_FILENO, &term) == -1) {
perror("Cannot get the attribution of the terminal");
return -1;
}
if (on)
term.c_lflag |= ECHOFLAGS;
else
term.c_lflag &= ~ECHOFLAGS;
err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
if (err == -1 || err == EINTR) {
printf("Cannot set the attribution of the terminal");
return -1;
}
return 0;
}
#endif
......@@ -13,15 +13,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os.h"
#define _BSD_SOURCE
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#include <winsock2.h>
#ifdef DARWIN
#define _XOPEN_SOURCE
#else
#define _XOPEN_SOURCE 500
#endif
FORCE_INLINE int32_t taosGetTimeOfDay(struct timeval *tv) {
#define _DEFAULT_SOURCE
#include "os.h"
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#include <time.h>
#include <winsock2.h>
int taosGetTimeOfDay(struct timeval *tv, struct timezone *tz) {
time_t t;
t = time(NULL);
SYSTEMTIME st;
......@@ -31,7 +43,23 @@ FORCE_INLINE int32_t taosGetTimeOfDay(struct timeval *tv) {
tv->tv_usec = st.wMilliseconds * 1000;
return 0;
}
struct tm *localtime_r(const time_t *timep, struct tm *result) {
localtime_s(result, timep);
return result;
}
#else
/*
* linux and darwin implementation
*/
#include <sys/time.h>
FORCE_INLINE int32_t taosGetTimeOfDay(struct timeval *tv) {
return gettimeofday(tv, NULL);
#endif
}
#endif
......@@ -13,15 +13,54 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// fail-fast or let-it-crash philosophy
// https://en.wikipedia.org/wiki/Fail-fast
// https://stackoverflow.com/questions/4393197/erlangs-let-it-crash-philosophy-applicable-elsewhere
// experimentally, we follow log-and-crash here
#define _DEFAULT_SOURCE
#include "os.h"
#if 1
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
/*
* windows implementation
*/
#include <Windows.h>
#include <Mmsystem.h>
#include <stdio.h>
#include <stdint.h>
#pragma warning( disable : 4244 )
typedef void (*win_timer_f)(int signo);
void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwl, DWORD_PTR dw2) {
win_timer_f callback = *((win_timer_f *)&dwUser);
if (callback != NULL) {
callback(0);
}
}
static MMRESULT timerId;
int taosInitTimer(win_timer_f callback, int ms) {
DWORD_PTR param = *((int64_t *) & callback);
timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC);
if (timerId == 0) {
return -1;
}
return 0;
}
void taosUninitTimer() {
timeKillEvent(timerId);
}
#elif defined(_TD_DARWIN_64)
/*
* darwin implementation
*/
#include <sys/syscall.h>
#include <sys/event.h>
static void (*timer_callback)(int);
......@@ -89,36 +128,98 @@ void taos_block_sigalrm(void) {
// we don't know if there's any specific API for SIGALRM to deliver to specific thread
// this implementation relies on kqueue rather than SIGALRM
}
#else
int taosInitTimer(void (*callback)(int), int ms) {
signal(SIGALRM, callback);
struct itimerval tv;
tv.it_interval.tv_sec = 0; /* my timer resolution */
tv.it_interval.tv_usec = 1000 * ms; // resolution is in msecond
tv.it_value = tv.it_interval;
/*
* linux implementation
*/
setitimer(ITIMER_REAL, &tv, NULL);
#include <sys/syscall.h>
return 0;
static void taosDeleteTimer(void *tharg) {
timer_t *pTimer = tharg;
timer_delete(*pTimer);
}
void taosUninitTimer() {
struct itimerval tv = { 0 };
setitimer(ITIMER_REAL, &tv, NULL);
static pthread_t timerThread;
static timer_t timerId;
static volatile bool stopTimer = false;
static void *taosProcessAlarmSignal(void *tharg) {
// Block the signal
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
sigprocmask(SIG_BLOCK, &sigset, NULL);
void (*callback)(int) = tharg;
struct sigevent sevent = {{0}};
setThreadName("tmr");
#ifdef _ALPINE
sevent.sigev_notify = SIGEV_THREAD;
sevent.sigev_value.sival_int = syscall(__NR_gettid);
#else
sevent.sigev_notify = SIGEV_THREAD_ID;
sevent._sigev_un._tid = syscall(__NR_gettid);
#endif
sevent.sigev_signo = SIGALRM;
if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) {
printf("Failed to create timer");
}
pthread_cleanup_push(taosDeleteTimer, &timerId);
struct itimerspec ts;
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK;
if (timer_settime(timerId, 0, &ts, NULL)) {
printf("Failed to init timer");
return NULL;
}
int signo;
while (!stopTimer) {
if (sigwait(&sigset, &signo)) {
printf("Failed to wait signal: number %d", signo);
continue;
}
/* printf("Signal handling: number %d ......\n", signo); */
callback(0);
}
pthread_cleanup_pop(1);
return NULL;
}
void taos_block_sigalrm(void) {
// since SIGALRM has been used
// consideration: any better solution?
static __thread int already_set = 0;
if (!already_set) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_BLOCK, &set, NULL);
already_set = 1;
int taosInitTimer(void (*callback)(int), int ms) {
pthread_attr_t tattr;
pthread_attr_init(&tattr);
int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback);
pthread_attr_destroy(&tattr);
if (code != 0) {
printf("failed to create timer thread");
return -1;
} else {
printf("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
}
return 0;
}
#endif
void taosUninitTimer() {
stopTimer = true;
printf("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
pthread_join(timerThread, NULL);
}
#endif
......@@ -28,7 +28,7 @@
#include "mnode.h"
static int32_t dnodeCreateDir(const char *dir) {
if (taosMkDir(dir, 0755) != 0 && errno != EEXIST) {
if (!taosMkDir(dir, 0755) && errno != EEXIST) {
return -1;
}
......@@ -55,6 +55,14 @@ static void dnodeCheckDataDirOpenned(char *dir) {
#endif
}
void dnodePrintDiskInfo() {
dInfo("==================================");
dInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB);
dInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB);
dInfo(" os availDisk: %f(GB)", tsAvailDataDirGB);
dInfo("==================================");
}
int32_t dnodeInitMain(Dnode *dnode, DnMain **out) {
DnMain* main = calloc(1, sizeof(DnMain));
if (main == NULL) return -1;
......@@ -76,7 +84,7 @@ int32_t dnodeInitMain(Dnode *dnode, DnMain **out) {
taosInitGlobalCfg();
taosReadGlobalLogCfg();
#if 0
taosSetCoreDump();
taosSetCoreDump(tsEnableCoreFile);
#endif
if (dnodeCreateDir(tsLogDir) < 0) {
......@@ -182,7 +190,7 @@ int32_t dnodeInitStorage(Dnode *dnode, void **m) {
dnodeCheckDataDirOpenned(tsDnodeDir);
taosGetDisk();
taosPrintDiskInfo();
dnodePrintDiskInfo();
#endif
dInfo("dnode storage is initialized at %s", tsDnodeDir);
......
......@@ -15,6 +15,7 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "ttime.h"
#include "ttimer.h"
#include "tglobal.h"
#include "dnodeCfg.h"
......
......@@ -8,4 +8,6 @@ target_include_directories(
target_link_libraries(
util
PRIVATE os
PUBLIC zlib
PUBLIC lz4_static
)
......@@ -16,7 +16,6 @@
#include "os.h"
#include "hash.h"
#include "tulog.h"
// #include "taosdef.h"
#define EXT_SIZE 1024
......
......@@ -14,7 +14,6 @@
*/
#include "os.h"
#include "talgo.h"
#define doswap(__left, __right, __size, __buf) do {\
......
......@@ -22,7 +22,7 @@
#include "hash.h"
#include "regex.h"
#include "os.h"
#include "ttype.h"
#include "tdef.h"
int32_t setCompareBytes1(const void *pLeft, const void *pRight) {
return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0;
......
......@@ -52,11 +52,8 @@
#ifdef TD_TSZ
#include "td_sz.h"
#endif
#include "taosdef.h"
#include "tscompression.h"
#include "tulog.h"
#include "tglobal.h"
static const int TEST_NUMBER = 1;
#define is_bigendian() ((*(char *)&TEST_NUMBER) == 0)
......
......@@ -15,10 +15,7 @@
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "taoserror.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "tsocket.h"
#include "tutil.h"
......@@ -78,7 +75,6 @@ static void taosReadDoubleConfig(SGlobalCfg *cfg, char *input_value) {
}
}
static void taosReadInt32Config(SGlobalCfg *cfg, char *input_value) {
int32_t value = atoi(input_value);
int32_t *option = (int32_t *)cfg->ptr;
......@@ -156,27 +152,10 @@ static bool taosReadDirectoryConfig(SGlobalCfg *cfg, char *input_value) {
return false;
} else {
if (cfg->cfgStatus <= TAOS_CFG_CSTATUS_FILE) {
wordexp_t full_path;
if (0 != wordexp(input_value, &full_path, 0)) {
printf("\nconfig dir: %s wordexp fail! reason:%s\n", input_value, strerror(errno));
wordfree(&full_path);
return false;
}
if (full_path.we_wordv != NULL && full_path.we_wordv[0] != NULL) {
strcpy(option, full_path.we_wordv[0]);
}
taosExpandDir(input_value, option, cfg->ptrLength);
taosRealPath(option, cfg->ptrLength);
wordfree(&full_path);
char tmp[PATH_MAX] = {0};
if (realpath(option, tmp) != NULL) {
strcpy(option, tmp);
}
int code = taosMkDir(option, 0755);
if (code != 0) {
terrno = TAOS_SYSTEM_ERROR(errno);
if (!taosMkDir(option, 0755)) {
uError("config option:%s, input value:%s, directory not exist, create fail:%s", cfg->option, input_value,
strerror(errno));
return false;
......@@ -234,9 +213,9 @@ static void taosReadLogOption(char *option, char *value) {
switch (cfg->valType) {
case TAOS_CFG_VTYPE_INT32:
taosReadInt32Config(cfg, value);
if (strcasecmp(cfg->option, "debugFlag") == 0) {
taosSetAllDebugFlag();
}
// if (strcasecmp(cfg->option, "debugFlag") == 0) {
// taosSetAllDebugFlag();
// }
break;
case TAOS_CFG_VTYPE_DIRECTORY:
taosReadDirectoryConfig(cfg, value);
......@@ -249,7 +228,6 @@ static void taosReadLogOption(char *option, char *value) {
}
SGlobalCfg *taosGetConfigOption(const char *option) {
taosInitGlobalCfg();
for (int i = 0; i < tsGlobalConfigNum; ++i) {
SGlobalCfg *cfg = tsGlobalConfig + i;
if (strcasecmp(cfg->option, option) != 0) continue;
......@@ -294,7 +272,7 @@ static void taosReadConfigOption(const char *option, char *value, char *value2,
break;
case TAOS_CFG_VTYPE_DATA_DIRCTORY:
if (taosReadDirectoryConfig(cfg, value)) {
taosReadDataDirCfg(value, value2, value3);
// taosReadDataDirCfg(value, value2, value3);
}
break;
default:
......@@ -315,34 +293,7 @@ void taosReadGlobalLogCfg() {
int olen, vlen;
char fileName[PATH_MAX] = {0};
wordexp_t full_path;
if ( 0 != wordexp(configDir, &full_path, 0)) {
printf("\nconfig file: %s wordexp fail! reason:%s\n", configDir, strerror(errno));
wordfree(&full_path);
return;
}
if (full_path.we_wordv != NULL && full_path.we_wordv[0] != NULL) {
if (strlen(full_path.we_wordv[0]) >= TSDB_FILENAME_LEN) {
printf("\nconfig file: %s path overflow max len %d, all variables are set to default\n", full_path.we_wordv[0], TSDB_FILENAME_LEN - 1);
wordfree(&full_path);
return;
}
strcpy(configDir, full_path.we_wordv[0]);
} else {
#ifdef _TD_POWER_
printf("configDir:%s not there, use default value: /etc/power", configDir);
strcpy(configDir, "/etc/power");
#elif (_TD_TQ_ == true)
printf("configDir:%s not there, use default value: /etc/tq", configDir);
strcpy(configDir, "/etc/tq");
#else
printf("configDir:%s not there, use default value: /etc/taos", configDir);
strcpy(configDir, "/etc/taos");
#endif
}
wordfree(&full_path);
taosExpandDir(configDir, configDir, PATH_MAX);
taosReadLogOption("logDir", tsLogDir);
sprintf(fileName, "%s/taos.cfg", configDir);
......@@ -391,13 +342,8 @@ bool taosReadGlobalCfg() {
char fileName[PATH_MAX] = {0};
sprintf(fileName, "%s/taos.cfg", configDir);
FILE* fp = fopen(fileName, "r");
FILE *fp = fopen(fileName, "r");
if (fp == NULL) {
struct stat s;
if (stat(configDir, &s) != 0 || (!S_ISREG(s.st_mode) && !S_ISLNK(s.st_mode))) {
//return true to follow behavior before file support
return true;
}
fp = fopen(configDir, "r");
if (fp == NULL) {
return false;
......@@ -444,9 +390,9 @@ bool taosReadGlobalCfg() {
tfree(line);
if (debugFlag & DEBUG_TRACE || debugFlag & DEBUG_DEBUG || debugFlag & DEBUG_DUMP) {
taosSetAllDebugFlag();
}
// if (debugFlag & DEBUG_TRACE || debugFlag & DEBUG_DEBUG || debugFlag & DEBUG_DUMP) {
// taosSetAllDebugFlag();
// }
return true;
}
......@@ -498,7 +444,7 @@ void taosPrintGlobalCfg() {
}
taosPrintOsInfo();
taosPrintDataDirCfg();
// taosPrintDataDirCfg();
uInfo("==================================");
}
......
......@@ -18,14 +18,15 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "os.h"
#include "tcrc32c.h"
#include "tdef.h"
#if !defined(_TD_ARM_) && !defined(_TD_MIPS_)
#include <nmmintrin.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "tcrc32c.h"
#define POLY 0x82f63b78
#define LONG_SHIFT 8192
......
......@@ -19,6 +19,7 @@
#include "tlog.h"
#include "tnote.h"
#include "tutil.h"
#include "zlib.h"
#define MAX_LOGLINE_SIZE (1000)
#define MAX_LOGLINE_BUFFER_SIZE (MAX_LOGLINE_SIZE + 10)
......@@ -75,22 +76,34 @@ float tsMinimalLogDirGB = 1.0f;
int64_t asyncLogLostLines = 0;
int32_t writeInterval = DEFAULT_LOG_INTERVAL;
// log
int32_t tsNumOfLogLines = 10000000;
int32_t mDebugFlag = 131;
int32_t sdbDebugFlag = 131;
int32_t dDebugFlag = 135;
int32_t vDebugFlag = 135;
int32_t cDebugFlag = 131;
int32_t jniDebugFlag = 131;
int32_t odbcDebugFlag = 131;
int32_t httpDebugFlag = 131;
int32_t mqttDebugFlag = 131;
int32_t monDebugFlag = 131;
int32_t qDebugFlag = 131;
int32_t rpcDebugFlag = 131;
int32_t uDebugFlag = 131;
int32_t debugFlag = 0;
int32_t sDebugFlag = 135;
int32_t wDebugFlag = 135;
int32_t tsdbDebugFlag = 131;
int32_t cqDebugFlag = 131;
int32_t fsDebugFlag = 135;
int64_t dbgEmptyW = 0;
int64_t dbgWN = 0;
int64_t dbgSmallWN = 0;
int64_t dbgBigWN = 0;
int64_t dbgWSize = 0;
#ifdef _TD_POWER_
char tsLogDir[TSDB_FILENAME_LEN] = "/var/log/power";
#elif (_TD_TQ_ == true)
char tsLogDir[TSDB_FILENAME_LEN] = "/var/log/tq";
#elif (_TD_PRO_ == true)
char tsLogDir[TSDB_FILENAME_LEN] = "/var/log/ProDB";
#else
char tsLogDir[PATH_MAX] = "/var/log/taos";
#endif
static SLogObj tsLogObj = { .fileNum = 1 };
static void * taosAsyncOutputLog(void *param);
static int32_t taosPushLogBuffer(SLogBuff *tLogBuff, char *msg, int32_t msgLen);
......@@ -98,6 +111,7 @@ static SLogBuff *taosLogBuffNew(int32_t bufSize);
static void taosCloseLogByFd(int32_t oldFd);
static int32_t taosOpenLogFile(char *fn, int32_t maxLines, int32_t maxFileNum);
extern void taosPrintGlobalCfg();
static int32_t taosCompressFile(char *srcFileName, char *destFileName);
static int32_t taosStartLog() {
pthread_attr_t threadAttr;
......@@ -164,7 +178,7 @@ static void taosKeepOldLog(char *oldName) {
char fileName[LOG_FILE_NAME_LEN + 20];
snprintf(fileName, LOG_FILE_NAME_LEN + 20, "%s.%" PRId64, tsLogObj.logName, fileSec);
taosRename(oldName, fileName);
taosRenameFile(oldName, fileName);
if (tsLogKeepDays < 0) {
char compressFileName[LOG_FILE_NAME_LEN + 20];
snprintf(compressFileName, LOG_FILE_NAME_LEN + 20, "%s.%" PRId64 ".gz", tsLogObj.logName, fileSec);
......@@ -173,7 +187,7 @@ static void taosKeepOldLog(char *oldName) {
}
}
taosRemoveOldLogFiles(tsLogDir, ABS(tsLogKeepDays));
taosRemoveOldFiles(tsLogDir, ABS(tsLogKeepDays));
}
static void *taosThreadToOpenNewFile(void *param) {
......@@ -702,3 +716,62 @@ static void *taosAsyncOutputLog(void *param) {
return NULL;
}
int32_t taosCompressFile(char *srcFileName, char *destFileName) {
int32_t compressSize = 163840;
int32_t ret = 0;
int32_t len = 0;
char * data = malloc(compressSize);
FILE * srcFp = NULL;
gzFile dstFp = NULL;
srcFp = fopen(srcFileName, "r");
if (srcFp == NULL) {
ret = -1;
goto cmp_end;
}
int32_t fd = taosOpenFileTruncCreateWrite(destFileName);
if (fd < 0) {
ret = -2;
goto cmp_end;
}
dstFp = gzdopen(fd, "wb6f");
if (dstFp == NULL) {
ret = -3;
close(fd);
goto cmp_end;
}
while (!feof(srcFp)) {
len = (int32_t)fread(data, 1, compressSize, srcFp);
(void)gzwrite(dstFp, data, len);
}
cmp_end:
if (srcFp) {
fclose(srcFp);
}
if (dstFp) {
gzclose(dstFp);
}
free(data);
return ret;
}
void taosPrintOsInfo() {
SysNameInfo info = taosGetSysNameInfo();
uInfo(" os pageSize: %" PRId64 "(KB)", tsPageSize);
uInfo(" os openMax: %" PRId64, tsOpenMax);
uInfo(" os streamMax: %" PRId64, tsStreamMax);
uInfo(" os numOfCores: %d", tsNumOfCores);
uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB);
uInfo(" os sysname: %s", info.sysname);
uInfo(" os nodename: %s", info.nodename);
uInfo(" os release: %s", info.release);
uInfo(" os version: %s", info.version);
uInfo(" os machine: %s", info.machine);
}
......@@ -371,7 +371,7 @@ void tscSaveSubscriptionProgress(void* sub) {
char path[256];
sprintf(path, "%s/subscribe", tsDataDir);
if (taosMkDir(path, 0777) != 0) {
if (!taosMkDir(path, 0777)) {
tscError("failed to create subscribe dir: %s", path);
}
......
aux_source_directory(source COMMON_SRC)
add_library(common ${COMMON_SRC})
target_include_directories(
common
PUBLIC "${CMAKE_SOURCE_DIR}/include/common"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include"
)
target_include_directories(
common
PRIVATE util
)
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
\ No newline at end of file
aux_source_directory(source OS_SRC)
add_library(os ${OS_SRC})
target_include_directories(
os
PUBLIC "${CMAKE_SOURCE_DIR}/include/os"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include"
)
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_EOK_H
#define TDENGINE_OS_EOK_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __APPLE__
enum EPOLL_EVENTS
{
EPOLLIN = 0x001,
#define EPOLLIN EPOLLIN
EPOLLPRI = 0x002,
#define EPOLLPRI EPOLLPRI
EPOLLOUT = 0x004,
#define EPOLLOUT EPOLLOUT
EPOLLRDNORM = 0x040,
#define EPOLLRDNORM EPOLLRDNORM
EPOLLRDBAND = 0x080,
#define EPOLLRDBAND EPOLLRDBAND
EPOLLWRNORM = 0x100,
#define EPOLLWRNORM EPOLLWRNORM
EPOLLWRBAND = 0x200,
#define EPOLLWRBAND EPOLLWRBAND
EPOLLMSG = 0x400,
#define EPOLLMSG EPOLLMSG
EPOLLERR = 0x008,
#define EPOLLERR EPOLLERR
EPOLLHUP = 0x010,
#define EPOLLHUP EPOLLHUP
EPOLLRDHUP = 0x2000,
#define EPOLLRDHUP EPOLLRDHUP
EPOLLEXCLUSIVE = 1u << 28,
#define EPOLLEXCLUSIVE EPOLLEXCLUSIVE
EPOLLWAKEUP = 1u << 29,
#define EPOLLWAKEUP EPOLLWAKEUP
EPOLLONESHOT = 1u << 30,
#define EPOLLONESHOT EPOLLONESHOT
EPOLLET = 1u << 31
#define EPOLLET EPOLLET
};
/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */
#define EPOLL_CTL_ADD 1 /* Add a file descriptor to the interface. */
#define EPOLL_CTL_DEL 2 /* Remove a file descriptor from the interface. */
#define EPOLL_CTL_MOD 3 /* Change file descriptor epoll_event structure. */
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event
{
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
int epoll_close(int epfd);
#endif // __APPLE__
#ifdef __cplusplus
}
#endif
#endif // _eok_h_fd274616_996c_400e_9023_ae70be881fa3_
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_INC_H
#define TDENGINE_OS_INC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
#include <locale.h>
#include <math.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(_TD_LINUX_64) || defined(_TD_LINUX_32) || defined(_TD_MIPS_64) || defined(_TD_ARM_32) || defined(_TD_ARM_64) || defined(_TD_DARWIN_64)
#include <arpa/inet.h>
#include <dirent.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <limits.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <pwd.h>
#include <regex.h>
#include <stddef.h>
#include <strings.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <syslog.h>
#include <termios.h>
#include <unistd.h>
#include <wchar.h>
#include <wordexp.h>
#include <wctype.h>
#if defined(_TD_DARWIN_64)
#include <dispatch/dispatch.h>
#include "osEok.h"
#else
#include <argp.h>
#include <dlfcn.h>
#include <endian.h>
#include <linux/sysctl.h>
#include <poll.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/resource.h>
#include <sys/sendfile.h>
#include <sys/prctl.h>
#if !(defined(_ALPINE))
#include <error.h>
#endif
#endif
#endif
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
#include <intrin.h>
#include <io.h>
#include "winsock2.h"
#include <WS2tcpip.h>
#include <winbase.h>
#include <Winsock2.h>
#include <time.h>
#include <conio.h>
#include "msvcProcess.h"
#include "msvcDirect.h"
#include "msvcFcntl.h"
#include "msvcLibgen.h"
#include "msvcStdio.h"
#include "msvcUnistd.h"
#include "msvcLibgen.h"
#include "sys/msvcStat.h"
#include "sys/msvcTypes.h"
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_MEMORY_H
#define TDENGINE_OS_MEMORY_H
#include "osString.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef TD_JEMALLOC_ENABLED
#include <jemalloc/jemalloc.h>
#endif
typedef enum {
TAOS_ALLOC_MODE_DEFAULT = 0,
TAOS_ALLOC_MODE_RANDOM_FAIL = 1,
TAOS_ALLOC_MODE_DETECT_LEAK = 2
} ETaosMemoryAllocMode;
void taosSetAllocMode(int mode, const char *path, bool autoDump);
void taosDumpMemoryLeak();
// used in tsdb module
void * taosTMalloc(size_t size);
void * taosTCalloc(size_t nmemb, size_t size);
void * taosTRealloc(void *ptr, size_t size);
void * taosTZfree(void *ptr);
size_t taosTSizeof(void *ptr);
void taosTMemset(void *ptr, int c);
// used in other module
#define tmalloc(size) malloc(size)
#define tcalloc(num, size) calloc(num, size)
#define trealloc(ptr, size) realloc(ptr, size)
#define tfree(x) \
do { \
if (x) { \
free((void *)(x)); \
x = 0; \
} \
} while (0)
#ifdef TAOS_MEM_CHECK
#ifdef TAOS_MEM_CHECK_TEST
void * taosMallocMem(size_t size, const char *file, uint32_t line);
void * taosCallocMem(size_t num, size_t size, const char *file, uint32_t line);
void * taosReallocMem(void *ptr, size_t size, const char *file, uint32_t line);
void taosFreeMem(void *ptr, const char *file, uint32_t line);
char * taosStrdupMem(const char *str, const char *file, uint32_t line);
char * taosStrndupMem(const char *str, size_t size, const char *file, uint32_t line);
ssize_t taosGetlineMem(char **lineptr, size_t *n, FILE *stream, const char *file, uint32_t line);
#undef tmalloc
#undef tcalloc
#undef trealloc
#undef tfree
#define tmalloc(size) taosMallocMem(size, __FILE__, __LINE__)
#define tcalloc(num, size) taosCallocMem(num, size, __FILE__, __LINE__)
#define trealloc(ptr, size) taosReallocMem(ptr, size, __FILE__, __LINE__)
#define tfree(ptr) taosFreeMem(ptr, __FILE__, __LINE__)
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_MIPS64_H
#define TDENGINE_OS_MIPS64_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <argp.h>
#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <float.h>
#include <ifaddrs.h>
#include <libgen.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <pthread.h>
#include <pwd.h>
#include <regex.h>
#include <semaphore.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <strings.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <syslog.h>
#include <termios.h>
#include <unistd.h>
#include <wchar.h>
#include <wordexp.h>
#include <wctype.h>
#include <inttypes.h>
#include <fcntl.h>
#include <sys/utsname.h>
#include <sys/resource.h>
#include <error.h>
#include <linux/sysctl.h>
#include <math.h>
#include <poll.h>
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_SIGNAL_H
#define TDENGINE_OS_SIGNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <signal.h>
#ifndef SIGALRM
#define SIGALRM 1234
#endif
#ifndef SIGHUP
#define SIGHUP 1230
#endif
#ifndef SIGCHLD
#define SIGCHLD 1234
#endif
#ifndef SIGUSR1
#define SIGUSR1 1234
#endif
#ifndef SIGUSR2
#define SIGUSR2 1234
#endif
#ifndef SIGBREAK
#define SIGBREAK 1234
#endif
typedef void (*FSignalHandler)(int32_t signum, void *sigInfo, void *context);
void taosSetSignal(int32_t signum, FSignalHandler sigfp);
void taosIgnSignal(int32_t signum);
void taosDflSignal(int32_t signum);
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_OS_SIGNAL_H
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_SLEEP_H
#define TDENGINE_OS_SLEEP_H
#ifdef __cplusplus
extern "C" {
#endif
void taosMsleep(int32_t ms);
#ifdef __cplusplus
}
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_OS_TIMER_H
#define TDENGINE_OS_TIMER_H
#ifdef __cplusplus
extern "C" {
#endif
int taosInitTimer(void (*callback)(int), int ms);
void taosUninitTimer();
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
\ No newline at end of file
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
AUX_SOURCE_DIRECTORY(. SRC)
ADD_LIBRARY(osdarwin ${SRC})
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
#include "tulog.h"
void* taosLoadDll(const char *filename) {
return NULL;
}
void* taosLoadSym(void* handle, char* name) {
return NULL;
}
void taosCloseDll(void *handle) {
}
int taosSetConsoleEcho(bool on)
{
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
int err;
struct termios term;
if (tcgetattr(STDIN_FILENO, &term) == -1) {
perror("Cannot get the attribution of the terminal");
return -1;
}
if (on)
term.c_lflag|=ECHOFLAGS;
else
term.c_lflag &=~ECHOFLAGS;
err = tcsetattr(STDIN_FILENO,TCSAFLUSH,&term);
if (err == -1 && err == EINTR) {
perror("Cannot set the attribution of the terminal");
return -1;
}
return 0;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
static const char* expand_like_shell(const char *path) {
static __thread char buf[TSDB_FILENAME_LEN];
buf[0] = '\0';
wordexp_t we;
if (wordexp(path, &we, 0)) return "/tmp/taosd";
if (sizeof(buf)<=snprintf(buf, sizeof(buf), "%s", we.we_wordv[0])) return "/tmp/taosd";
wordfree(&we);
return buf;
}
void osInit() {
if (configDir[0] == 0) {
strcpy(configDir, expand_like_shell("/usr/local/etc/taos"));
}
strcpy(tsDataDir, expand_like_shell("/usr/local/var/lib/taos"));
strcpy(tsLogDir, expand_like_shell("/usr/local/var/log/taos"));
strcpy(tsScriptDir, expand_like_shell("/usr/local/etc/taos"));
strcpy(tsVnodeDir, "");
strcpy(tsDnodeDir, "");
strcpy(tsMnodeDir, "");
strcpy(tsOsName, "Darwin");
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// fail-fast or let-it-crash philosophy
// https://en.wikipedia.org/wiki/Fail-fast
// https://stackoverflow.com/questions/4393197/erlangs-let-it-crash-philosophy-applicable-elsewhere
// experimentally, we follow log-and-crash here
#define _DEFAULT_SOURCE
#include "os.h"
#include "osEok.h"
#include <sys/event.h>
// #define BALANCE_CHECK_WHEN_CLOSE
#ifdef ENABLE_LOG
#define D(fmt, ...) fprintf(stderr, "%s[%d]%s(): " fmt "\n", basename(__FILE__), __LINE__, __func__, ##__VA_ARGS__)
#define E(fmt, ...) do { \
fprintf(stderr, "%s[%d]%s(): %d[%s]: " fmt "\n", \
basename(__FILE__), __LINE__, __func__, \
errno, strerror(errno), \
##__VA_ARGS__); \
} while (0)
#else // !ENABLE_LOG
#define D(fmt, ...) (void)fmt
#define E(fmt, ...) (void)fmt
#endif // ENABLE_LOG
#define A(statement, fmt, ...) do { \
if (statement) break; \
fprintf(stderr, "%s[%d]%s(): assert [%s] failed: %d[%s]: " fmt "\n", \
basename(__FILE__), __LINE__, __func__, \
#statement, errno, strerror(errno), \
##__VA_ARGS__); \
abort(); \
} while (0)
static int eok_dummy = 0;
typedef struct ep_over_kq_s ep_over_kq_t;
typedef struct eok_event_s eok_event_t;
struct ep_over_kq_s {
int kq;
// !!!
// idx in the eoks list
// used as pseudo-file-desciptor
// must be 'closed' with epoll_close
int idx;
ep_over_kq_t *next;
int sv[2]; // 0 for read, 1 for write
// all registered 'epoll events, key by fd'
int evs_count;
eok_event_t *evs_head;
eok_event_t *evs_tail;
eok_event_t *evs_free;
// all kev changes list pending to be processed by kevent64
// key by tuple (ident,filter), ident === fd in this case
struct kevent64_s *kchanges;
int nchanges;
int ichanges;
// kev eventslist for kevent64 to store active events
// they remain alive among kevent64 calls
struct kevent64_s *kevslist;
int nevslist;
pthread_mutex_t lock;
volatile unsigned int lock_valid:1;
volatile unsigned int waiting:1;
volatile unsigned int changed:1;
volatile unsigned int wakenup:1;
volatile unsigned int stopping:1;
};
struct eok_event_s {
int fd;
struct epoll_event epev;
volatile unsigned int changed; // 0:registered;1:add;2:mod;3:del
eok_event_t *next;
eok_event_t *prev;
};
typedef struct eoks_s eoks_t;
struct eoks_s {
pthread_mutex_t lock;
ep_over_kq_t **eoks; // note: this memory leaks when process terminates
int neoks; // we can add an extra api to let user clean
ep_over_kq_t *eoks_free_list; // currently, we just keep it simple stupid
};
static eoks_t eoks = {
.lock = PTHREAD_MUTEX_INITIALIZER,
.eoks = NULL,
.neoks = 0,
.eoks_free_list = NULL,
};
#ifdef ENABLE_LOG
static const char* op_str(int op) {
switch (op) {
case EPOLL_CTL_ADD: return "EPOLL_CTL_ADD";
case EPOLL_CTL_MOD: return "EPOLL_CTL_MOD";
case EPOLL_CTL_DEL: return "EPOLL_CTL_DEL";
default: return "UNKNOWN";
}
}
static __thread char buf_slots[10][1024] = {0};
static __thread int buf_slots_linelen = sizeof(buf_slots[0])/sizeof(buf_slots[0][0]);
static __thread int buf_slots_count = sizeof(buf_slots)/(sizeof(buf_slots[0])/sizeof(buf_slots[0][0]));
static const char* events_str(uint32_t events, int slots) {
A(slots>=0 && slots<buf_slots_count, "internal logic error");
char *buf = buf_slots[slots];
char *p = buf;
size_t len = buf_slots_linelen;
int n = 0;
buf[0] = '\0';
// copied from <sys/epoll.h> on linux
// EPOLLIN = 0x001,
// #define EPOLLIN EPOLLIN
// EPOLLPRI = 0x002,
// #define EPOLLPRI EPOLLPRI
// EPOLLOUT = 0x004,
// #define EPOLLOUT EPOLLOUT
// EPOLLRDNORM = 0x040,
// #define EPOLLRDNORM EPOLLRDNORM
// EPOLLRDBAND = 0x080,
// #define EPOLLRDBAND EPOLLRDBAND
// EPOLLWRNORM = 0x100,
// #define EPOLLWRNORM EPOLLWRNORM
// EPOLLWRBAND = 0x200,
// #define EPOLLWRBAND EPOLLWRBAND
// EPOLLMSG = 0x400,
// #define EPOLLMSG EPOLLMSG
// EPOLLERR = 0x008,
// #define EPOLLERR EPOLLERR
// EPOLLHUP = 0x010,
// #define EPOLLHUP EPOLLHUP
// EPOLLRDHUP = 0x2000,
// #define EPOLLRDHUP EPOLLRDHUP
// EPOLLEXCLUSIVE = 1u << 28,
// #define EPOLLEXCLUSIVE EPOLLEXCLUSIVE
// EPOLLWAKEUP = 1u << 29,
// #define EPOLLWAKEUP EPOLLWAKEUP
// EPOLLONESHOT = 1u << 30,
// #define EPOLLONESHOT EPOLLONESHOT
// EPOLLET = 1u << 31
// #define EPOLLET EPOLLET
#define CHK_EV(ev) \
if (len>0 && (events & (ev))==(ev)) { \
n = snprintf(p, len, "%s%s", p!=buf ? "|" : "", #ev); \
p += n; \
len -= n; \
}
CHK_EV(EPOLLIN);
CHK_EV(EPOLLPRI);
CHK_EV(EPOLLOUT);
CHK_EV(EPOLLRDNORM);
CHK_EV(EPOLLRDBAND);
CHK_EV(EPOLLWRNORM);
CHK_EV(EPOLLWRBAND);
CHK_EV(EPOLLMSG);
CHK_EV(EPOLLERR);
CHK_EV(EPOLLHUP);
CHK_EV(EPOLLRDHUP);
CHK_EV(EPOLLEXCLUSIVE);
CHK_EV(EPOLLWAKEUP);
CHK_EV(EPOLLONESHOT);
CHK_EV(EPOLLET);
#undef CHK_EV
return buf;
}
static const char* kev_flags_str(uint16_t flags, int slots) {
A(slots>=0 && slots<buf_slots_count, "internal logic error");
char *buf = buf_slots[slots];
char *p = buf;
size_t len = buf_slots_linelen;
int n = 0;
buf[0] = '\0';
// copied to <sys/event.h>
// #define EV_ADD 0x0001 /* add event to kq (implies enable) */
// #define EV_DELETE 0x0002 /* delete event from kq */
// #define EV_ENABLE 0x0004 /* enable event */
// #define EV_DISABLE 0x0008 /* disable event (not reported) */
// /* flags */
// #define EV_ONESHOT 0x0010 /* only report one occurrence */
// #define EV_CLEAR 0x0020 /* clear event state after reporting */
// #define EV_RECEIPT 0x0040 /* force immediate event output */
// /* ... with or without EV_ERROR */
// /* ... use KEVENT_FLAG_ERROR_EVENTS */
// /* on syscalls supporting flags */
// #define EV_DISPATCH 0x0080 /* disable event after reporting */
// #define EV_UDATA_SPECIFIC 0x0100 /* unique kevent per udata value */
// #define EV_DISPATCH2 (EV_DISPATCH | EV_UDATA_SPECIFIC)
// /* ... in combination with EV_DELETE */
// /* will defer delete until udata-specific */
// /* event enabled. EINPROGRESS will be */
// /* returned to indicate the deferral */
// #define EV_VANISHED 0x0200 /* report that source has vanished */
// /* ... only valid with EV_DISPATCH2 */
// #define EV_SYSFLAGS 0xF000 /* reserved by system */
// #define EV_FLAG0 0x1000 /* filter-specific flag */
// #define EV_FLAG1 0x2000 /* filter-specific flag */
// /* returned values */
// #define EV_EOF 0x8000 /* EOF detected */
// #define EV_ERROR 0x4000 /* error, data contains errno */
#define CHK_EV(ev) \
if (len>0 && (flags & (ev))==(ev)) { \
n = snprintf(p, len, "%s%s", p!=buf ? "|" : "", #ev); \
p += n; \
len -= n; \
}
CHK_EV(EV_ADD);
CHK_EV(EV_DELETE);
CHK_EV(EV_ENABLE);
CHK_EV(EV_DISABLE);
CHK_EV(EV_ONESHOT);
CHK_EV(EV_CLEAR);
CHK_EV(EV_RECEIPT);
CHK_EV(EV_DISPATCH);
CHK_EV(EV_UDATA_SPECIFIC);
CHK_EV(EV_DISPATCH2);
CHK_EV(EV_VANISHED);
CHK_EV(EV_SYSFLAGS);
CHK_EV(EV_FLAG0);
CHK_EV(EV_FLAG1);
CHK_EV(EV_EOF);
CHK_EV(EV_ERROR);
#undef CHK_EV
return buf;
}
#endif // ENABLE_LOG
static ep_over_kq_t* eoks_alloc(void);
static void eoks_free(ep_over_kq_t *eok);
static ep_over_kq_t* eoks_find(int epfd);
static eok_event_t* eok_find_ev(ep_over_kq_t *eok, int fd);
static eok_event_t* eok_calloc_ev(ep_over_kq_t *eok);
static void eok_free_ev(ep_over_kq_t *eok, eok_event_t *ev);
static void eok_wakeup(ep_over_kq_t *eok);
static int eok_chgs_refresh(ep_over_kq_t *eok, eok_event_t *oev, eok_event_t *ev, struct kevent64_s *krev, struct kevent64_s *kwev);
static struct kevent64_s* eok_alloc_eventslist(ep_over_kq_t *eok, int maxevents);
int epoll_create(int size) {
(void)size;
int e = 0;
ep_over_kq_t *eok = eoks_alloc();
if (!eok) return -1;
A(eok->kq==-1, "internal logic error");
A(eok->lock_valid, "internal logic error");
A(eok->idx>=0 && eok->idx<eoks.neoks, "internal logic error");
A(eok->next==NULL, "internal logic error");
A(eok->sv[0]==-1, "internal logic error");
A(eok->sv[1]==-1, "internal logic error");
eok->kq = kqueue();
if (eok->kq==-1) {
e = errno;
eoks_free(eok);
errno = e;
return -1;
}
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, eok->sv)) {
e = errno;
eoks_free(eok);
errno = e;
return -1;
}
struct epoll_event ev = {0};
ev.events = EPOLLIN;
ev.data.ptr = &eok_dummy;
D("epoll_create epfd:[%d] and sv0[%d]", eok->idx, eok->sv[0]);
if (epoll_ctl(eok->idx, EPOLL_CTL_ADD, eok->sv[0], &ev)) {
e = errno;
epoll_close(eok->idx);
errno = e;
return -1;
}
return eok->idx;
}
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) {
D("epoll_ctling epfd:[%d], op:[%s], fd:[%d], events:[%04x:%s]",
epfd, op_str(op), fd,
event ? event->events : 0,
event ? events_str(event->events, 0) : "NULL");
int e = 0;
if (epfd<0 || epfd>=eoks.neoks) {
errno = EBADF;
return -1;
}
if (fd==-1) {
errno = EBADF;
return -1;
}
if (event && !(event->events & (EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP | EPOLLOUT))) {
e = ENOTSUP;
return -1;
}
ep_over_kq_t *eok = eoks_find(epfd);
if (!eok) {
errno = EBADF;
return -1;
}
A(0==pthread_mutex_lock(&eok->lock), "");
do {
eok_event_t* oev = eok_find_ev(eok, fd);
if (op==EPOLL_CTL_ADD && oev) {
e = EEXIST;
break;
}
if (op!=EPOLL_CTL_ADD && !oev) {
e = ENOENT;
break;
}
if (op!=EPOLL_CTL_DEL && !event) {
e = EINVAL;
break;
}
// prepare krev/kwev
struct kevent64_s krev = {0};
struct kevent64_s kwev = {0};
krev.ident = -1;
kwev.ident = -1;
uint16_t flags = 0;
// prepare internal eok event
eok_event_t ev = {0};
ev.fd = fd;
if (event) ev.epev = *event;
struct epoll_event *pev = event;
switch (op) {
case EPOLL_CTL_ADD: {
flags = EV_ADD;
ev.changed = 1;
} break;
case EPOLL_CTL_MOD: {
flags = EV_ADD;
ev.changed = 2;
} break;
case EPOLL_CTL_DEL: {
// event is ignored
// pev points to registered epoll_event
pev = &oev->epev;
flags = EV_DELETE;
ev.changed = 3;
} break;
default: {
e = ENOTSUP;
} break;
}
if (e) break;
// udata will be delayed to be set
if (pev->events & (EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
flags |= EV_EOF;
EV_SET64(&krev, ev.fd, EVFILT_READ, flags, 0, 0, -1, 0, 0);
}
if (pev->events & EPOLLOUT) {
EV_SET64(&kwev, ev.fd, EVFILT_WRITE, flags, 0, 0, -1, 0, 0);
}
// refresh registered evlist and changelist in a transaction way
if (eok_chgs_refresh(eok, oev, &ev, &krev, &kwev)) {
e = errno;
A(e, "internal logic error");
break;
}
eok->changed = 1;
eok_wakeup(eok);
} while (0);
A(0==pthread_mutex_unlock(&eok->lock), "");
if (e) {
errno = e;
return -1;
}
return 0;
}
static struct timespec do_timespec_diff(struct timespec *from, struct timespec *to);
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) {
int e = 0;
if (!events) {
errno = EINVAL;
E("epoll_waiting epfd:[%d], maxevents:[%d], timeout:[%d] failed", epfd, maxevents, timeout);
return -1;
}
if (maxevents<=0) {
errno = EINVAL;
E("epoll_waiting epfd:[%d], maxevents:[%d], timeout:[%d] failed", epfd, maxevents, timeout);
return -1;
}
struct timespec abstime = {0};
A(TIME_UTC==timespec_get(&abstime, TIME_UTC), "internal logic error");
if (timeout!=-1) {
if (timeout<0) timeout = 0;
int64_t t = abstime.tv_nsec + timeout * 1000000;
abstime.tv_sec += t / 1000000000;
abstime.tv_nsec = t % 1000000000;
}
int r = 0;
ep_over_kq_t *eok = eoks_find(epfd);
if (!eok) {
errno = EBADF;
E("epoll_waiting epfd:[%d], maxevents:[%d], timeout:[%d] failed", epfd, maxevents, timeout);
errno = EBADF;
return -1;
}
int cnts = 0;
A(0==pthread_mutex_lock(&eok->lock), "");
do {
cnts = 0;
A(eok->waiting==0, "internal logic error");
struct kevent64_s *eventslist = eok_alloc_eventslist(eok, maxevents);
if (!eventslist) {
e = ENOMEM;
E("epoll_waiting epfd:[%d], maxevents:[%d], timeout:[%d] failed", epfd, maxevents, timeout);
break;
}
memset(eventslist, 0, maxevents * sizeof(*eventslist));
struct timespec now = {0};
A(TIME_UTC==timespec_get(&now, TIME_UTC), "internal logic error");
struct timespec to = do_timespec_diff(&now, &abstime);
struct timespec *pto = &to;
if (timeout==-1) {
pto = NULL;
}
// taking the changelist
struct kevent64_s *kchanges = eok->kchanges;
int nchanges = eok->nchanges;
int ichanges = eok->ichanges;
// let outside world to add changes
eok->kchanges = NULL;
eok->nchanges = 0;
eok->ichanges = 0;
eok->changed = 0;
eok->wakenup = 0;
eok->waiting = 1;
A(0==pthread_mutex_unlock(&eok->lock), "");
if (ichanges>0) {
D("kevent64 epfd[%d] changing [%d] changes and waiting...", eok->idx, ichanges);
}
errno = 0;
r = kevent64(eok->kq, kchanges, ichanges, eventslist, maxevents, 0, pto);
e = errno;
if (e) {
E("kevent64 epfd[%d] waiting done, with r[%d]", eok->idx, r);
}
A(0==pthread_mutex_lock(&eok->lock), "");
eok->waiting = 0;
if (kchanges) {
if (eok->kchanges==NULL) {
// reuse
A(eok->nchanges==0 && eok->ichanges==0, "internal logic error");
eok->kchanges = kchanges;
eok->nchanges = nchanges;
} else {
free(kchanges);
kchanges = NULL;
}
nchanges = 0;
ichanges = 0;
}
if (r==0) {
A(timeout!=-1, "internal logic error");
}
for (int i=0; i<r; ++i) {
struct kevent64_s *kev = eventslist + i;
A(kev->udata && eok->evs_head && eok->evs_tail, "internal logic error");
eok_event_t *ev = (eok_event_t*)kev->udata;
A(kev->ident == ev->fd, "internal logic error");
if (kev->flags & EV_ERROR) {
D("epfd[%d] error when processing change list for fd[%d], error[%s], kev_flags:[%04x:%s]",
epfd, ev->fd, strerror(kev->data), kev->flags, kev_flags_str(kev->flags, 0));
}
switch (kev->filter) {
case EVFILT_READ: {
A((ev->epev.events & EPOLLIN), "internal logic errro");
if (ev->epev.data.ptr==&eok_dummy) {
// it's coming from wakeup socket pair
char c = '\0';
A(1==recv(kev->ident, &c, 1, 0), "internal logic error");
A(0==memcmp(&c, "1", 1), "internal logic error");
D("epfd[%d] wokenup", epfd);
continue;
} else {
if (ev->changed==3) {
D("epfd[%d] already requested to delete for fd[%d]", epfd, ev->fd);
// TODO: write a unit test for this case
// EV_DELETE?
continue;
}
// converting to epoll_event
// we shall collect all kevents for the uniq fd into one epoll_evnt
// but currently, taos never use EPOLLOUT
// just let it this way for the moment
struct epoll_event pev = {0};
pev.data.ptr = ev->epev.data.ptr;
pev.events = EPOLLIN;
if (kev->flags & EV_EOF) {
// take all these as EOF for the moment
pev.events |= (EPOLLHUP | EPOLLERR | EPOLLRDHUP);
}
// rounded to what user care
pev.events = pev.events & ev->epev.events;
D("epfd[%d] events found for fd[%d]: [%04x:%s], which was registered: [%04x:%s], kev_flags: [%04x:%s]",
epfd,
ev->fd, pev.events, events_str(pev.events, 0),
ev->epev.events, events_str(ev->epev.events, 1),
kev->flags, kev_flags_str(kev->flags, 2));
// now we get ev and store it
events[cnts++] = pev;
}
} break;
case EVFILT_WRITE: {
A(0, "not implemented yet");
} break;
default: {
A(0, "internal logic error");
} break;
}
}
if (r>=0) {
// we can safely rule out delete-requested-events from the regitered evlists
// if only changelist are correctly registered
eok_event_t *p = eok->evs_head;
while (p) {
eok_event_t *next = p->next;
if (p->changed==3) {
D("epfd[%d] removing registered event for fd[%d]: [%04x:%s]", epfd, p->fd, p->epev.events, events_str(p->epev.events, 0));
eok_free_ev(eok, p);
}
p = next;
}
}
if (cnts==0) {
// if no user-cared-events is up
// we check to see if time is up
if (timeout!=-1) {
A(TIME_UTC==timespec_get(&now, TIME_UTC), "internal logic error");
to = do_timespec_diff(&now, &abstime);
if (to.tv_sec==0 && to.tv_nsec==0) break;
}
// time is not up yet, continue loop
}
} while (cnts==0);
if (cnts>0) {
D("kevent64 epfd[%d] waiting done with [%d] events", epfd, cnts);
}
A(0==pthread_mutex_unlock(&eok->lock), "");
if (e) {
errno = e;
E("epfd[%d] epoll_wait failed", epfd);
return -1;
}
// tell user how many events are valid
return cnts;
}
static struct timespec do_timespec_diff(struct timespec *from, struct timespec *to) {
struct timespec delta;
delta.tv_sec = to->tv_sec - from->tv_sec;
delta.tv_nsec = to->tv_nsec - from->tv_nsec;
// norm and round up
while (delta.tv_nsec<0) {
delta.tv_sec -= 1;
delta.tv_nsec += 1000000000;
}
if (delta.tv_sec < 0) {
delta.tv_sec = 0;
delta.tv_nsec = 0;
}
return delta;
}
int epoll_close(int epfd) {
D("epoll_closing epfd: [%d]", epfd);
ep_over_kq_t *eok = eoks_find(epfd);
if (!eok) {
errno = EBADF;
return -1;
}
A(0==pthread_mutex_lock(&eok->lock), "");
do {
// panic if it would be double-closed
A(eok->stopping==0, "internal logic error");
eok->stopping = 1;
// panic if epoll_wait is pending
A(eok->waiting==0, "internal logic error");
if (eok->kq!=-1) {
close(eok->kq);
eok->kq = -1;
}
} while (0);
A(0==pthread_mutex_unlock(&eok->lock), "");
eoks_free(eok);
return 0;
}
static struct kevent64_s* eok_alloc_eventslist(ep_over_kq_t *eok, int maxevents) {
if (maxevents<=eok->nevslist) return eok->kevslist;
struct kevent64_s *p = (struct kevent64_s*)realloc(eok->kevslist, sizeof(*p)*maxevents);
if (!p) return NULL;
eok->kevslist = p;
eok->nevslist = maxevents;
return p;
}
static eok_event_t* eok_find_ev(ep_over_kq_t *eok, int fd) {
eok_event_t *p = eok->evs_head;
while (p) {
if (p->fd == fd) return p;
p = p->next;
}
errno = ENOENT;
return NULL;
}
static eok_event_t* eok_calloc_ev(ep_over_kq_t *eok) {
eok_event_t *p = NULL;
if (eok->evs_free) {
p = eok->evs_free;
eok->evs_free = p->next;
p->next = NULL;
A(p->prev==NULL, "internal logic error");
} else {
p = (eok_event_t*)calloc(1, sizeof(*p));
if (!p) return NULL;
A(p->next==NULL, "internal logic error");
A(p->prev==NULL, "internal logic error");
}
// dirty link
p->prev = eok->evs_tail;
if (eok->evs_tail) eok->evs_tail->next = p;
else eok->evs_head = p;
eok->evs_tail = p;
eok->evs_count += 1;
return p;
}
static void eok_free_ev(ep_over_kq_t *eok, eok_event_t *ev) {
if (ev->prev) ev->prev->next = ev->next;
else eok->evs_head = ev->next;
if (ev->next) ev->next->prev = ev->prev;
else eok->evs_tail = ev->prev;
ev->prev = NULL;
ev->next = eok->evs_free;
eok->evs_free = ev;
eok->evs_count -= 1;
}
static void eok_wakeup(ep_over_kq_t *eok) {
if (!eok->waiting) return;
if (eok->wakenup) return;
eok->wakenup = 1;
A(1==send(eok->sv[1], "1", 1, 0), "");
}
static int eok_chgs_refresh(ep_over_kq_t *eok, eok_event_t *oev, eok_event_t *ev, struct kevent64_s *krev, struct kevent64_s *kwev) {
if (!oev) oev = eok_calloc_ev(eok);
if (!oev) return -1;
int n = 0;
if (krev->ident==ev->fd) ++n;
if (kwev->ident==ev->fd) ++n;
A(n, "internal logic error");
if (eok->ichanges+n>eok->nchanges) {
struct kevent64_s *p = (struct kevent64_s*)realloc(eok->kchanges, sizeof(*p) * (eok->nchanges + 10));
if (!p) {
if (ev->changed==1) {
// roll back
A(oev, "internal logic error");
eok_free_ev(eok, oev);
}
errno = ENOMEM;
return -1;
}
eok->kchanges = p;
eok->nchanges += 10;
}
// copy to registered event slot
oev->fd = ev->fd;
if (ev->changed!=3) {
// if add/mod, copy epoll_event
oev->epev = ev->epev;
}
oev->changed = ev->changed;
// copy to changes list
n = 0;
if (krev->ident==ev->fd) {
krev->udata = (uint64_t)oev;
eok->kchanges[eok->ichanges++] = *krev;
++n;
}
if (kwev->ident==ev->fd) {
kwev->udata = (uint64_t)oev;
eok->kchanges[eok->ichanges++] = *kwev;
++n;
}
D("epfd[%d]: add #changes[%d] for fd[%d], and now #changes/registers [%d/%d]", eok->idx, n, ev->fd, eok->ichanges, eok->evs_count);
return 0;
}
static ep_over_kq_t* eoks_alloc(void) {
ep_over_kq_t *eok = NULL;
A(0==pthread_mutex_lock(&eoks.lock), "");
do {
if (eoks.eoks_free_list) {
eok = eoks.eoks_free_list;
eoks.eoks_free_list = eok->next;
A(eoks.eoks, "internal logic error");
A(eok->idx>=0 && eok->idx<eoks.neoks, "internal logic error");
A(*(eoks.eoks + eok->idx)==NULL, "internal logic error");
*(eoks.eoks + eok->idx) = eok;
eok->next = NULL;
eok->stopping = 0;
break;
}
eok = (ep_over_kq_t*)calloc(1, sizeof(*eok));
if (!eok) break;
eok->idx = -1;
ep_over_kq_t **ar = (ep_over_kq_t**)realloc(eoks.eoks, sizeof(**ar) * (eoks.neoks+1));
if (!ar) break;
eoks.eoks = ar;
*(eoks.eoks + eoks.neoks) = eok;
eok->idx = eoks.neoks;
eok->kq = -1;
eok->sv[0] = -1;
eok->sv[1] = -1;
eoks.neoks += 1;
} while (0);
A(0==pthread_mutex_unlock(&eoks.lock), "");
if (!eok) {
errno = ENOMEM;
return NULL;
}
if (eok->idx==-1) {
free(eok);
errno = ENOMEM;
return NULL;
}
if (eok->lock_valid) {
return eok;
}
if (0==pthread_mutex_init(&eok->lock, NULL)) {
eok->lock_valid = 1;
return eok;
}
eoks_free(eok);
errno = ENOMEM;
return NULL;
}
static void eoks_free(ep_over_kq_t *eok) {
A(0==pthread_mutex_lock(&eoks.lock), "");
do {
A(eok->idx>=0 && eok->idx<eoks.neoks, "internal logic error");
A(eok->next==NULL, "internal logic error");
// leave eok->kchanges as is
A(eok->ichanges==0, "internal logic error");
A(eok->waiting==0, "internal logic error");
eok_event_t *ev = eok->evs_head;
int sv_closed = 0;
while (ev) {
eok_event_t *next = ev->next;
if (ev->fd==eok->sv[0]) {
// fd is critical system resource
A(sv_closed==0, "internal logic error");
close(eok->sv[0]);
eok->sv[0] = -1;
close(eok->sv[1]);
eok->sv[1] = -1;
eok_free_ev(eok, ev);
} else {
// user forget calling epoll_ctl(EPOLL_CTL_DEL) before calling epoll_close/close?
// calling close(ev->fd) here smells really bad
#ifndef BALANCE_CHECK_WHEN_CLOSE
// we just let it be and reclaim ev
eok_free_ev(eok, ev);
#else
// panic otherwise, if BALANCE_CHECK_WHEN_CLOSE is defined
A(eok->evs_head==NULL && eok->evs_tail==NULL && eok->evs_count==0,
"epfd[%d] fd[%d]: internal logic error: have you epoll_ctl(EPOLL_CTL_DEL) everything before calling epoll_close?",
eok->idx, ev->fd);
#endif
}
ev = next;
}
// if (eok->evs_count==1) {
// A(eok->evs_head && eok->evs_tail && eok->evs_head==eok->evs_tail, "internal logic error");
// A(eok->evs_head->fd==eok->sv[0] && eok->sv[0]!=-1 && eok->sv[1]!=-1, "internal logic error");
// // fd is critical system resource
// close(eok->sv[0]);
// eok->sv[0] = -1;
// close(eok->sv[1]);
// eok->sv[1] = -1;
// eok_free_ev(eok, eok->evs_head);
// }
A(eok->evs_head==NULL && eok->evs_tail==NULL && eok->evs_count==0,
"internal logic error: have you epoll_ctl(EPOLL_CTL_DEL) everything before calling epoll_close?");
A(eok->sv[0]==-1 && eok->sv[1]==-1, "internal logic error");
if (eok->kq!=-1) {
close(eok->kq);
eok->kq = -1;
}
eok->next = eoks.eoks_free_list;
eoks.eoks_free_list = eok;
*(eoks.eoks + eok->idx) = NULL;
} while (0);
A(0==pthread_mutex_unlock(&eoks.lock), "");
}
static ep_over_kq_t* eoks_find(int epfd) {
ep_over_kq_t *eok = NULL;
A(0==pthread_mutex_lock(&eoks.lock), "");
do {
if (epfd<0 || epfd>=eoks.neoks) {
break;
}
A(eoks.eoks, "internal logic error");
eok = *(eoks.eoks + epfd);
A(eok->next==NULL, "internal logic error");
A(eok->lock_valid, "internal logic error");
} while (0);
A(0==pthread_mutex_unlock(&eoks.lock), "");
return eok;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) {
if (level == SOL_SOCKET && optname == SO_SNDBUF) {
return 0;
}
if (level == SOL_SOCKET && optname == SO_RCVBUF) {
return 0;
}
return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen);
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#include "taoserror.h"
#include <errno.h>
#include <libproc.h>
static void taosGetSystemTimezone() {
SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone");
if (cfg_timezone == NULL) return;
if (cfg_timezone->cfgStatus >= TAOS_CFG_CSTATUS_DEFAULT) {
return;
}
/* load time zone string from /etc/localtime */
char buf[4096];
char *tz = NULL; {
int n = readlink("/etc/localtime", buf, sizeof(buf));
if (n<0) {
uError("read /etc/localtime error, reason:%s", strerror(errno));
return;
}
buf[n] = '\0';
for(int i=n-1; i>=0; --i) {
if (buf[i]=='/') {
if (tz) {
tz = buf + i + 1;
break;
}
tz = buf + i + 1;
}
}
if (!tz || 0==strchr(tz, '/')) {
uError("parsing /etc/localtime failed");
return;
}
setenv("TZ", tz, 1);
tzset();
}
/*
* NOTE: do not remove it.
* Enforce set the correct daylight saving time(DST) flag according
* to current time
*/
time_t tx1 = time(NULL);
struct tm tm1;
localtime_r(&tx1, &tm1);
/*
* format example:
*
* Asia/Shanghai (CST, +0800)
* Europe/London (BST, +0100)
*/
snprintf(tsTimezone, TSDB_TIMEZONE_LEN, "%s (%s, %+03ld00)",
tz, tm1.tm_isdst ? tzname[daylight] : tzname[0], -timezone/3600);
// cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uWarn("timezone not configured, set to system default:%s", tsTimezone);
}
/*
* originally from src/os/src/detail/osSysinfo.c
* POSIX format locale string:
* (Language Strings)_(Country/Region Strings).(code_page)
*
* example: en_US.UTF-8, zh_CN.GB18030, zh_CN.UTF-8,
*
* if user does not specify the locale in taos.cfg the program use default LC_CTYPE as system locale.
*
* In case of some CentOS systems, their default locale is "en_US.utf8", which is not valid code_page
* for libiconv that is employed to convert string in this system. This program will automatically use
* UTF-8 instead as the charset.
*
* In case of windows client, the locale string is not valid POSIX format, user needs to set the
* correct code_page for libiconv. Usually, the code_page of windows system with simple chinese is
* CP936, CP437 for English charset.
*
*/
static void taosGetSystemLocale() { // get and set default locale
char sep = '.';
char *locale = NULL;
SGlobalCfg *cfg_locale = taosGetConfigOption("locale");
if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
locale = setlocale(LC_CTYPE, "");
if (locale == NULL) {
uError("can't get locale from system, set it to en_US.UTF-8 since error:%d:%s", errno, strerror(errno));
strcpy(tsLocale, "en_US.UTF-8");
} else {
tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN);
uWarn("locale not configured, set to system default:%s", tsLocale);
}
}
/* if user does not specify the charset, extract it from locale */
SGlobalCfg *cfg_charset = taosGetConfigOption("charset");
if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
char *str = strrchr(tsLocale, sep);
if (str != NULL) {
str++;
char *revisedCharset = taosCharsetReplace(str);
tstrncpy(tsCharset, revisedCharset, TSDB_LOCALE_LEN);
free(revisedCharset);
uWarn("charset not configured, set to system default:%s", tsCharset);
} else {
strcpy(tsCharset, "UTF-8");
uWarn("can't get locale and charset from system, set it to UTF-8");
}
}
}
void taosPrintOsInfo() {
uInfo(" os pageSize: %" PRId64 "(KB)", tsPageSize / 1024);
// uInfo(" os openMax: %" PRId64, tsOpenMax);
// uInfo(" os streamMax: %" PRId64, tsStreamMax);
uInfo(" os numOfCores: %d", tsNumOfCores);
uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB);
struct utsname buf;
if (uname(&buf)) {
uInfo(" can't fetch os info");
return;
}
uInfo(" os sysname: %s", buf.sysname);
uInfo(" os nodename: %s", buf.nodename);
uInfo(" os release: %s", buf.release);
uInfo(" os version: %s", buf.version);
uInfo(" os machine: %s", buf.machine);
uInfo("==================================");
}
void taosPrintDiskInfo() {
uInfo("==================================");
uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB);
uInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB);
uInfo(" os availDisk: %f(GB)", tsAvailDataDirGB);
uInfo("==================================");
}
void taosKillSystem() {
uError("function taosKillSystem, exit!");
exit(0);
}
int32_t taosGetCpuCores() {
return sysconf(_SC_NPROCESSORS_ONLN);
}
void taosGetSystemInfo() {
// taosGetProcInfos();
tsNumOfCores = sysconf(_SC_NPROCESSORS_ONLN);
long physical_pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGESIZE);
tsTotalMemoryMB = physical_pages * page_size / (1024 * 1024);
tsPageSize = page_size;
// float tmp1, tmp2;
// taosGetSysMemory(&tmp1);
// taosGetProcMemory(&tmp2);
// taosGetDisk();
// taosGetBandSpeed(&tmp1);
// taosGetCpuUsage(&tmp1, &tmp2);
// taosGetProcIO(&tmp1, &tmp2);
taosGetSystemTimezone();
taosGetSystemLocale();
}
bool taosReadProcIO(int64_t *rchars, int64_t *wchars) {
if (rchars) *rchars = 0;
if (wchars) *wchars = 0;
return true;
}
bool taosGetProcIO(float *readKB, float *writeKB) {
*readKB = 0;
*writeKB = 0;
return true;
}
bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes) {
if (bytes) *bytes = 0;
if (rbytes) *rbytes = 0;
if (tbytes) *tbytes = 0;
return true;
}
bool taosGetBandSpeed(float *bandSpeedKb) {
*bandSpeedKb = 0;
return true;
}
bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) {
*sysCpuUsage = 0;
*procCpuUsage = 0;
return true;
}
bool taosGetProcMemory(float *memoryUsedMB) {
*memoryUsedMB = 0;
return true;
}
bool taosGetSysMemory(float *memoryUsedMB) {
*memoryUsedMB = 0;
return true;
}
int taosSystem(const char *cmd) {
uError("un support funtion");
return -1;
}
void taosSetCoreDump() {}
int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) {
struct statvfs info;
if (statvfs(dataDir, &info)) {
uError("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
} else {
diskSize->tsize = info.f_blocks * info.f_frsize;
diskSize->avail = info.f_bavail * info.f_frsize;
diskSize->used = (info.f_blocks - info.f_bfree) * info.f_frsize;
return 0;
}
}
char cmdline[1024];
char *taosGetCmdlineByPID(int pid) {
errno = 0;
if (proc_pidpath(pid, cmdline, sizeof(cmdline)) <= 0) {
fprintf(stderr, "PID is %d, %s", pid, strerror(errno));
return strerror(errno);
}
return cmdline;
}
bool taosGetSystemUid(char *uid) {
uuid_t uuid = {0};
uuid_generate(uuid);
// it's caller's responsibility to make enough space for `uid`, that's 36-char + 1-null
uuid_unparse_lower(uuid, uid);
return true;
}
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
INCLUDE_DIRECTORIES(.)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc)
AUX_SOURCE_DIRECTORY(. SRC)
SET_SOURCE_FILES_PROPERTIES(osSysinfo.c PROPERTIES COMPILE_FLAGS -w)
SET_SOURCE_FILES_PROPERTIES(osCoredump.c PROPERTIES COMPILE_FLAGS -w)
ADD_LIBRARY(os ${SRC})
IF (TD_LINUX)
TARGET_LINK_LIBRARIES(os oslinux)
IF (TD_ARM_32 OR TD_LINUX_32)
TARGET_LINK_LIBRARIES(os atomic)
ENDIF ()
ELSEIF (TD_DARWIN)
TARGET_LINK_LIBRARIES(os osdarwin)
ELSEIF (TD_WINDOWS)
TARGET_LINK_LIBRARIES(os oswindows)
ENDIF ()
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#ifdef _TD_NINGSI_60
void* atomic_exchange_ptr_impl(void** ptr, void* val ) {
void *old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int8_t atomic_exchange_8_impl(int8_t* ptr, int8_t val ) {
int8_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int16_t atomic_exchange_16_impl(int16_t* ptr, int16_t val ) {
int16_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int32_t atomic_exchange_32_impl(int32_t* ptr, int32_t val ) {
int32_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
int64_t atomic_exchange_64_impl(int64_t* ptr, int64_t val ) {
int64_t old;
do {
old = *ptr;
} while( !__sync_bool_compare_and_swap(ptr, old, val) );
return old;
}
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#define RANDOM_NETWORK_FAIL_FACTOR 20
#ifdef TAOS_RANDOM_NETWORK_FAIL
int64_t taosSendRandomFail(int32_t sockfd, const void *buf, size_t len, int32_t flags) {
if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) {
errno = ECONNRESET;
return -1;
}
return send(sockfd, buf, len, flags);
}
int64_t taosSendToRandomFail(int32_t sockfd, const void *buf, size_t len, int32_t flags,
const struct sockaddr *dest_addr, socklen_t addrlen) {
if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) {
errno = ECONNRESET;
return -1;
}
return sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
int64_t taosReadSocketRandomFail(int32_t fd, void *buf, size_t count) {
if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) {
errno = ECONNRESET;
return -1;
}
return read(fd, buf, count);
}
int64_t taosWriteSocketRandomFail(int32_t fd, const void *buf, size_t count) {
if (rand() % RANDOM_NETWORK_FAIL_FACTOR == 0) {
errno = EINTR;
return -1;
}
return write(fd, buf, count);
}
#endif //TAOS_RANDOM_NETWORK_FAIL
#ifdef TAOS_RANDOM_FILE_FAIL
static int32_t random_file_fail_factor = 20;
static FILE *fpRandomFileFailOutput = NULL;
void taosSetRandomFileFailFactor(int32_t factor) {
random_file_fail_factor = factor;
}
static void close_random_file_fail_output() {
if (fpRandomFileFailOutput != NULL) {
if (fpRandomFileFailOutput != stdout) {
fclose(fpRandomFileFailOutput);
}
fpRandomFileFailOutput = NULL;
}
}
static void random_file_fail_output_sig(int32_t sig) {
fprintf(fpRandomFileFailOutput, "signal %d received.\n", sig);
struct sigaction act = {0};
act.sa_handler = SIG_DFL;
sigaction(sig, &act, NULL);
close_random_file_fail_output();
exit(EXIT_FAILURE);
}
void taosSetRandomFileFailOutput(const char *path) {
if (path == NULL) {
fpRandomFileFailOutput = stdout;
} else if ((fpRandomFileFailOutput = fopen(path, "w")) != NULL) {
atexit(close_random_file_fail_output);
} else {
printf("failed to open random file fail log file '%s', errno=%d\n", path, errno);
return;
}
struct sigaction act = {0};
act.sa_handler = random_file_fail_output_sig;
sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGILL, &act, NULL);
}
int64_t taosReadFileRandomFail(int32_t fd, void *buf, int32_t count, const char *file, uint32_t line) {
if (random_file_fail_factor > 0) {
if (rand() % random_file_fail_factor == 0) {
errno = EIO;
return -1;
}
}
return taosRead(fd, buf, count);
}
int64_t taosWriteFileRandomFail(int32_t fd, void *buf, int32_t count, const char *file, uint32_t line) {
if (random_file_fail_factor > 0) {
if (rand() % random_file_fail_factor == 0) {
errno = EIO;
return -1;
}
}
return taosWrite(fd, buf, count);
}
int64_t taosLSeekRandomFail(int32_t fd, int64_t offset, int32_t whence, const char *file, uint32_t line) {
if (random_file_fail_factor > 0) {
if (rand() % random_file_fail_factor == 0) {
errno = EIO;
return -1;
}
}
return taosLSeek(fd, offset, whence);
}
#endif //TAOS_RANDOM_FILE_FAIL
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tulog.h"
#ifdef TAOS_MEM_CHECK
static ETaosMemoryAllocMode allocMode = TAOS_ALLOC_MODE_DEFAULT;
static FILE* fpAllocLog = NULL;
////////////////////////////////////////////////////////////////////////////////
// memory allocator which fails randomly
extern int32_t taosGetTimestampSec();
static int32_t startTime = INT32_MAX;
static bool taosRandomAllocFail(size_t size, const char* file, uint32_t line) {
if (taosGetTimestampSec() < startTime) {
return false;
}
if (size < 100 * (size_t)1024) {
return false;
}
if (rand() % 20 != 0) {
return false;
}
if (fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: memory allocation of %" PRIzu " bytes will fail.\n", file, line, size);
}
return true;
}
static void* taosRandmoMalloc(size_t size, const char* file, uint32_t line) {
return taosRandomAllocFail(size, file, line) ? NULL : malloc(size);
}
static void* taosRandomCalloc(size_t num, size_t size, const char* file, uint32_t line) {
return taosRandomAllocFail(num * size, file, line) ? NULL : calloc(num, size);
}
static void* taosRandomRealloc(void* ptr, size_t size, const char* file, uint32_t line) {
return taosRandomAllocFail(size, file, line) ? NULL : realloc(ptr, size);
}
static char* taosRandomStrdup(const char* str, const char* file, uint32_t line) {
size_t len = strlen(str);
return taosRandomAllocFail(len + 1, file, line) ? NULL : tstrdup(str);
}
static char* taosRandomStrndup(const char* str, size_t size, const char* file, uint32_t line) {
size_t len = strlen(str);
if (len > size) {
len = size;
}
return taosRandomAllocFail(len + 1, file, line) ? NULL : tstrndup(str, len);
}
static ssize_t taosRandomGetline(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) {
return taosRandomAllocFail(*n, file, line) ? -1 : tgetline(lineptr, n, stream);
}
////////////////////////////////////////////////////////////////////////////////
// memory allocator with leak detection
#define MEMBLK_MAGIC 0x55AA
typedef struct SMemBlock {
const char* file;
uint16_t line;
uint16_t magic;
uint32_t size;
struct SMemBlock* prev;
struct SMemBlock* next;
// TODO: need pading in 32bit platform
char data[0];
} SMemBlock;
static SMemBlock *blocks = NULL;
static uintptr_t lock = 0;
static void taosAddMemBlock(SMemBlock* blk) {
blk->prev = NULL;
while (atomic_val_compare_exchange_ptr(&lock, 0, 1) != 0);
blk->next = blocks;
if (blocks != NULL) {
blocks->prev = blk;
}
blocks = blk;
atomic_store_ptr(&lock, 0);
}
static void taosRemoveMemBlock(SMemBlock* blk) {
while (atomic_val_compare_exchange_ptr(&lock, 0, 1) != 0);
if (blocks == blk) {
blocks = blk->next;
}
if (blk->prev != NULL) {
blk->prev->next = blk->next;
}
if (blk->next != NULL) {
blk->next->prev = blk->prev;
}
atomic_store_ptr(&lock, 0);
blk->prev = NULL;
blk->next = NULL;
}
static void taosFreeDetectLeak(void* ptr, const char* file, uint32_t line) {
if (ptr == NULL) {
return;
}
SMemBlock* blk = (SMemBlock*)(((char*)ptr) - sizeof(SMemBlock));
if (blk->magic != MEMBLK_MAGIC) {
if (fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: memory is allocated by default allocator.\n", file, line);
}
free(ptr);
return;
}
taosRemoveMemBlock(blk);
free(blk);
}
static void* taosMallocDetectLeak(size_t size, const char* file, uint32_t line) {
if (size == 0) {
return NULL;
}
SMemBlock *blk = (SMemBlock*)malloc(size + sizeof(SMemBlock));
if (blk == NULL) {
return NULL;
}
if (line > UINT16_MAX && fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: line number too large.\n", file, line);
}
if (size > UINT32_MAX && fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: size too large: %" PRIzu ".\n", file, line, size);
}
blk->file = file;
blk->line = (uint16_t)line;
blk->magic = MEMBLK_MAGIC;
blk->size = size;
taosAddMemBlock(blk);
return blk->data;
}
static void* taosCallocDetectLeak(size_t num, size_t size, const char* file, uint32_t line) {
size *= num;
void* p = taosMallocDetectLeak(size, file, line);
if (p != NULL) {
memset(p, 0, size);
}
return p;
}
static void* taosReallocDetectLeak(void* ptr, size_t size, const char* file, uint32_t line) {
if (size == 0) {
taosFreeDetectLeak(ptr, file, line);
return NULL;
}
if (ptr == NULL) {
return taosMallocDetectLeak(size, file, line);
}
SMemBlock* blk = (SMemBlock *)((char*)ptr) - sizeof(SMemBlock);
if (blk->magic != MEMBLK_MAGIC) {
if (fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: memory is allocated by default allocator.\n", file, line);
}
return realloc(ptr, size);
}
taosRemoveMemBlock(blk);
void* p = realloc(blk, size + sizeof(SMemBlock));
if (p == NULL) {
taosAddMemBlock(blk);
return NULL;
}
if (size > UINT32_MAX && fpAllocLog != NULL) {
fprintf(fpAllocLog, "%s:%d: size too large: %" PRIzu ".\n", file, line, size);
}
blk = (SMemBlock*)p;
blk->size = size;
taosAddMemBlock(blk);
return blk->data;
}
static char* taosStrdupDetectLeak(const char* str, const char* file, uint32_t line) {
size_t len = strlen(str);
char *p = taosMallocDetectLeak(len + 1, file, line);
if (p != NULL) {
memcpy(p, str, len);
p[len] = 0;
}
return p;
}
static char* taosStrndupDetectLeak(const char* str, size_t size, const char* file, uint32_t line) {
size_t len = strlen(str);
if (len > size) {
len = size;
}
char *p = taosMallocDetectLeak(len + 1, file, line);
if (p != NULL) {
memcpy(p, str, len);
p[len] = 0;
}
return p;
}
static ssize_t taosGetlineDetectLeak(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) {
char* buf = NULL;
size_t bufSize = 0;
ssize_t size = tgetline(&buf, &bufSize, stream);
if (size != -1) {
if (*n < size + 1) {
void* p = taosReallocDetectLeak(*lineptr, size + 1, file, line);
if (p == NULL) {
free(buf);
return -1;
}
*lineptr = (char*)p;
*n = size + 1;
}
memcpy(*lineptr, buf, size + 1);
}
free(buf);
return size;
}
static void taosDumpMemoryLeakImp() {
const char* hex = "0123456789ABCDEF";
const char* fmt = ":%d: addr=%p, size=%d, content(first 16 bytes)=";
size_t numOfBlk = 0, totalSize = 0;
if (fpAllocLog == NULL) {
return;
}
fputs("memory blocks allocated but not freed before exit:\n", fpAllocLog);
while (atomic_val_compare_exchange_ptr(&lock, 0, 1) != 0);
for (SMemBlock* blk = blocks; blk != NULL; blk = blk->next) {
++numOfBlk;
totalSize += blk->size;
fputs(blk->file, fpAllocLog);
fprintf(fpAllocLog, fmt, blk->line, blk->data, blk->size);
char sep = '\'';
size_t size = blk->size > 16 ? 16 : blk->size;
for (size_t i = 0; i < size; ++i) {
uint8_t c = (uint8_t)(blk->data[i]);
fputc(sep, fpAllocLog);
sep = ' ';
fputc(hex[c >> 4], fpAllocLog);
fputc(hex[c & 0x0f], fpAllocLog);
}
fputs("'\n", fpAllocLog);
}
atomic_store_ptr(&lock, 0);
fprintf(fpAllocLog, "\nnumber of blocks: %" PRIzu ", total bytes: %" PRIzu "\n", numOfBlk, totalSize);
fflush(fpAllocLog);
}
static void taosDumpMemoryLeakOnSig(int sig) {
fprintf(fpAllocLog, "signal %d received.\n", sig);
// restore default signal handler
struct sigaction act = {0};
act.sa_handler = SIG_DFL;
sigaction(sig, &act, NULL);
taosDumpMemoryLeakImp();
}
////////////////////////////////////////////////////////////////////////////////
// interface functions
void* taosMallocMem(size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return malloc(size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return taosRandmoMalloc(size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosMallocDetectLeak(size, file, line);
}
return malloc(size);
}
void* taosCallocMem(size_t num, size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return calloc(num, size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return taosRandomCalloc(num, size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosCallocDetectLeak(num, size, file, line);
}
return calloc(num, size);
}
void* taosReallocMem(void* ptr, size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return realloc(ptr, size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return taosRandomRealloc(ptr, size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosReallocDetectLeak(ptr, size, file, line);
}
return realloc(ptr, size);
}
void taosFreeMem(void* ptr, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return free(ptr);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return free(ptr);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosFreeDetectLeak(ptr, file, line);
}
return free(ptr);
}
char* taosStrdupMem(const char* str, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return tstrdup(str);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return taosRandomStrdup(str, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosStrdupDetectLeak(str, file, line);
}
return tstrdup(str);
}
char* taosStrndupMem(const char* str, size_t size, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return tstrndup(str, size);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return taosRandomStrndup(str, size, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosStrndupDetectLeak(str, size, file, line);
}
return tstrndup(str, size);
}
ssize_t taosGetlineMem(char **lineptr, size_t *n, FILE *stream, const char* file, uint32_t line) {
switch (allocMode) {
case TAOS_ALLOC_MODE_DEFAULT:
return tgetline(lineptr, n, stream);
case TAOS_ALLOC_MODE_RANDOM_FAIL:
return taosRandomGetline(lineptr, n, stream, file, line);
case TAOS_ALLOC_MODE_DETECT_LEAK:
return taosGetlineDetectLeak(lineptr, n, stream, file, line);
}
return tgetline(lineptr, n, stream);
}
static void taosCloseAllocLog() {
if (fpAllocLog != NULL) {
if (fpAllocLog != stdout) {
fclose(fpAllocLog);
}
fpAllocLog = NULL;
}
}
void taosSetAllocMode(int mode, const char* path, bool autoDump) {
assert(mode >= TAOS_ALLOC_MODE_DEFAULT);
assert(mode <= TAOS_ALLOC_MODE_DETECT_LEAK);
if (fpAllocLog != NULL || allocMode != TAOS_ALLOC_MODE_DEFAULT) {
printf("memory allocation mode can only be set once.\n");
return;
}
if (path == NULL || path[0] == 0) {
fpAllocLog = stdout;
} else if ((fpAllocLog = fopen(path, "w")) != NULL) {
atexit(taosCloseAllocLog);
} else {
printf("failed to open memory allocation log file '%s', errno=%d\n", path, errno);
return;
}
allocMode = mode;
if (mode == TAOS_ALLOC_MODE_RANDOM_FAIL) {
startTime = taosGetTimestampSec() + 10;
return;
}
if (autoDump && mode == TAOS_ALLOC_MODE_DETECT_LEAK) {
atexit(taosDumpMemoryLeakImp);
struct sigaction act = {0};
act.sa_handler = taosDumpMemoryLeakOnSig;
sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGILL, &act, NULL);
}
}
void taosDumpMemoryLeak() {
taosDumpMemoryLeakImp();
taosCloseAllocLog();
}
#else // 'TAOS_MEM_CHECK' not defined
void taosSetAllocMode(int mode, const char* path, bool autoDump) {
// do nothing
}
void taosDumpMemoryLeak() {
// do nothing
}
#endif // TAOS_MEM_CHECK
void *taosTMalloc(size_t size) {
if (size <= 0) return NULL;
void *ret = malloc(size + sizeof(size_t));
if (ret == NULL) return NULL;
*(size_t *)ret = size;
return (void *)((char *)ret + sizeof(size_t));
}
void *taosTCalloc(size_t nmemb, size_t size) {
size_t tsize = nmemb * size;
void * ret = taosTMalloc(tsize);
if (ret == NULL) return NULL;
taosTMemset(ret, 0);
return ret;
}
size_t taosTSizeof(void *ptr) { return (ptr) ? (*(size_t *)((char *)ptr - sizeof(size_t))) : 0; }
void taosTMemset(void *ptr, int c) { memset(ptr, c, taosTSizeof(ptr)); }
void * taosTRealloc(void *ptr, size_t size) {
if (ptr == NULL) return taosTMalloc(size);
if (size <= taosTSizeof(ptr)) return ptr;
void * tptr = (void *)((char *)ptr - sizeof(size_t));
size_t tsize = size + sizeof(size_t);
void* tptr1 = realloc(tptr, tsize);
if (tptr1 == NULL) return NULL;
tptr = tptr1;
*(size_t *)tptr = size;
return (void *)((char *)tptr + sizeof(size_t));
}
void* taosTZfree(void* ptr) {
if (ptr) {
free((void*)((char*)ptr - sizeof(size_t)));
}
return NULL;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#if !defined (_TD_DARWIN_64)
int32_t tsem_wait(tsem_t* sem) {
int ret = 0;
do {
ret = sem_wait(sem);
} while (ret != 0 && errno == EINTR);
return ret;
}
#endif
#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) || defined (_TD_DARWIN_64))
bool taosCheckPthreadValid(pthread_t thread) { return thread != 0; }
int64_t taosGetSelfPthreadId() {
static __thread int id = 0;
if (id != 0) return id;
id = syscall(SYS_gettid);
return id;
}
int64_t taosGetPthreadId(pthread_t thread) { return (int64_t)thread; }
void taosResetPthread(pthread_t *thread) { *thread = 0; }
bool taosComparePthread(pthread_t first, pthread_t second) { return first == second; }
int32_t taosGetPId() { return getpid(); }
int32_t taosGetCurrentAPPName(char *name, int32_t* len) {
const char* self = "/proc/self/exe";
char path[PATH_MAX] = {0};
if (readlink(self, path, PATH_MAX) <= 0) {
return -1;
}
path[PATH_MAX - 1] = 0;
char* end = strrchr(path, '/');
if (end == NULL) {
return -1;
}
++end;
strcpy(name, end);
if (len != NULL) {
*len = strlen(name);
}
return 0;
}
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32))
typedef void (*FLinuxSignalHandler)(int32_t signum, siginfo_t *sigInfo, void *context);
void taosSetSignal(int32_t signum, FSignalHandler sigfp) {
struct sigaction act; memset(&act, 0, sizeof(act));
#if 1
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = (FLinuxSignalHandler)sigfp;
#else
act.sa_handler = sigfp;
#endif
sigaction(signum, &act, NULL);
}
void taosIgnSignal(int32_t signum) {
signal(signum, SIG_IGN);
}
void taosDflSignal(int32_t signum) {
signal(signum, SIG_DFL);
}
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
int64_t taosStr2int64(char *str) {
char *endptr = NULL;
return strtoll(str, &endptr, 10);
}
#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32))
int32_t tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int32_t bytes) {
return wcsncmp((wchar_t *)f1_ucs4, (wchar_t *)f2_ucs4, bytes / TSDB_NCHAR_SIZE);
}
#endif
#ifdef USE_LIBICONV
#include "iconv.h"
int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) {
iconv_t cd = iconv_open(tsCharset, DEFAULT_UNICODE_ENCODEC);
size_t ucs4_input_len = ucs4_max_len;
size_t outLen = ucs4_max_len;
if (iconv(cd, (char **)&ucs4, &ucs4_input_len, &mbs, &outLen) == -1) {
iconv_close(cd);
return -1;
}
iconv_close(cd);
return (int32_t)(ucs4_max_len - outLen);
}
bool taosMbsToUcs4(char *mbs, size_t mbsLength, char *ucs4, int32_t ucs4_max_len, int32_t *len) {
memset(ucs4, 0, ucs4_max_len);
iconv_t cd = iconv_open(DEFAULT_UNICODE_ENCODEC, tsCharset);
size_t ucs4_input_len = mbsLength;
size_t outLeft = ucs4_max_len;
if (iconv(cd, &mbs, &ucs4_input_len, &ucs4, &outLeft) == -1) {
iconv_close(cd);
return false;
}
iconv_close(cd);
if (len != NULL) {
*len = (int32_t)(ucs4_max_len - outLeft);
if (*len < 0) {
return false;
}
}
return true;
}
bool taosValidateEncodec(const char *encodec) {
iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC);
if (cd == (iconv_t)(-1)) {
return false;
}
iconv_close(cd);
return true;
}
#else
int32_t taosUcs4ToMbs(void *ucs4, int32_t ucs4_max_len, char *mbs) {
mbstate_t state = {0};
int32_t len = (int32_t)wcsnrtombs(NULL, (const wchar_t **)&ucs4, ucs4_max_len / 4, 0, &state);
if (len < 0) {
return -1;
}
memset(&state, 0, sizeof(state));
len = wcsnrtombs(mbs, (const wchar_t **)&ucs4, ucs4_max_len / 4, (size_t)len, &state);
if (len < 0) {
return -1;
}
return len;
}
bool taosMbsToUcs4(char *mbs, size_t mbsLength, char *ucs4, int32_t ucs4_max_len, int32_t *len) {
memset(ucs4, 0, ucs4_max_len);
mbstate_t state = {0};
int32_t retlen = mbsnrtowcs((wchar_t *)ucs4, (const char **)&mbs, mbsLength, ucs4_max_len / 4, &state);
*len = retlen;
return retlen >= 0;
}
bool taosValidateEncodec(const char *encodec) {
return true;
}
#endif
typedef struct CharsetPair {
char *oldCharset;
char *newCharset;
} CharsetPair;
char *taosCharsetReplace(char *charsetstr) {
CharsetPair charsetRep[] = {
{ "utf8", "UTF-8" }, { "936", "CP936" },
};
for (int32_t i = 0; i < tListLen(charsetRep); ++i) {
if (strcasecmp(charsetRep[i].oldCharset, charsetstr) == 0) {
return strdup(charsetRep[i].newCharset);
}
}
return strdup(charsetstr);
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "ttimer.h"
#include "tulog.h"
#if !(defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) || defined(_TD_DARWIN_64))
static void taosDeleteTimer(void *tharg) {
timer_t *pTimer = tharg;
timer_delete(*pTimer);
}
static pthread_t timerThread;
static timer_t timerId;
static volatile bool stopTimer = false;
static void *taosProcessAlarmSignal(void *tharg) {
// Block the signal
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
sigprocmask(SIG_BLOCK, &sigset, NULL);
void (*callback)(int) = tharg;
struct sigevent sevent = {{0}};
setThreadName("tmr");
#ifdef _ALPINE
sevent.sigev_notify = SIGEV_THREAD;
sevent.sigev_value.sival_int = syscall(__NR_gettid);
#else
sevent.sigev_notify = SIGEV_THREAD_ID;
sevent._sigev_un._tid = syscall(__NR_gettid);
#endif
sevent.sigev_signo = SIGALRM;
if (timer_create(CLOCK_REALTIME, &sevent, &timerId) == -1) {
uError("Failed to create timer");
}
pthread_cleanup_push(taosDeleteTimer, &timerId);
struct itimerspec ts;
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK;
if (timer_settime(timerId, 0, &ts, NULL)) {
uError("Failed to init timer");
return NULL;
}
int signo;
while (!stopTimer) {
if (sigwait(&sigset, &signo)) {
uError("Failed to wait signal: number %d", signo);
continue;
}
/* printf("Signal handling: number %d ......\n", signo); */
callback(0);
}
pthread_cleanup_pop(1);
return NULL;
}
int taosInitTimer(void (*callback)(int), int ms) {
pthread_attr_t tattr;
pthread_attr_init(&tattr);
int code = pthread_create(&timerThread, &tattr, taosProcessAlarmSignal, callback);
pthread_attr_destroy(&tattr);
if (code != 0) {
uError("failed to create timer thread");
return -1;
} else {
uDebug("timer thread:0x%08" PRIx64 " is created", taosGetPthreadId(timerThread));
}
return 0;
}
void taosUninitTimer() {
stopTimer = true;
uDebug("join timer thread:0x%08" PRIx64, taosGetPthreadId(timerThread));
pthread_join(timerThread, NULL);
}
#endif
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
AUX_SOURCE_DIRECTORY(. SRC)
ADD_LIBRARY(oslinux ${SRC})
TARGET_LINK_LIBRARIES(oslinux m rt z dl)
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
void osInit() {
#ifdef _TD_POWER_
if (configDir[0] == 0) {
strcpy(configDir, "/etc/power");
}
strcpy(tsDataDir, "/var/lib/power");
strcpy(tsLogDir, "/var/log/power");
strcpy(tsScriptDir, "/etc/power");
#elif (_TD_TQ_ == true)
if (configDir[0] == 0) {
strcpy(configDir, "/etc/tq");
}
strcpy(tsDataDir, "/var/lib/tq");
strcpy(tsLogDir, "/var/log/tq");
strcpy(tsScriptDir, "/etc/tq");
#else
if (configDir[0] == 0) {
strcpy(configDir, "/etc/taos");
}
strcpy(tsDataDir, "/var/lib/taos");
strcpy(tsLogDir, "/var/log/taos");
strcpy(tsScriptDir, "/etc/taos");
#endif
strcpy(tsVnodeDir, "");
strcpy(tsDnodeDir, "");
strcpy(tsMnodeDir, "");
strcpy(tsOsName, "Linux");
}
char* taosGetCmdlineByPID(int pid) {
static char cmdline[1024];
sprintf(cmdline, "/proc/%d/cmdline", pid);
int fd = open(cmdline, O_RDONLY);
if (fd >= 0) {
int n = read(fd, cmdline, sizeof(cmdline) - 1);
if (n < 0) n = 0;
if (n > 0 && cmdline[n - 1] == '\n') --n;
cmdline[n] = 0;
close(fd);
} else {
cmdline[0] = 0;
}
return cmdline;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tconfig.h"
#include "tglobal.h"
#include "tulog.h"
void* taosLoadDll(const char *filename) {
void *handle = dlopen (filename, RTLD_LAZY);
if (!handle) {
uError("load dll:%s failed, error:%s", filename, dlerror());
return NULL;
}
uDebug("dll %s loaded", filename);
return handle;
}
void* taosLoadSym(void* handle, char* name) {
void* sym = dlsym(handle, name);
char* error = NULL;
if ((error = dlerror()) != NULL) {
uWarn("load sym:%s failed, error:%s", name, dlerror());
return NULL;
}
uDebug("sym %s loaded", name)
return sym;
}
void taosCloseDll(void *handle) {
if (handle) {
dlclose(handle);
}
}
int taosSetConsoleEcho(bool on)
{
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
int err;
struct termios term;
if (tcgetattr(STDIN_FILENO, &term) == -1) {
perror("Cannot get the attribution of the terminal");
return -1;
}
if (on)
term.c_lflag |= ECHOFLAGS;
else
term.c_lflag &= ~ECHOFLAGS;
err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term);
if (err == -1 || err == EINTR) {
perror("Cannot set the attribution of the terminal");
return -1;
}
return 0;
}
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
AUX_SOURCE_DIRECTORY(. SRC)
ADD_LIBRARY(oswindows ${SRC})
TARGET_LINK_LIBRARIES(oswindows winmm IPHLPAPI ws2_32 MsvcLibXw)
\ No newline at end of file
/* getline.c -- Replacement for GNU C library function getline
Copyright (C) 1993 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details. */
/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <stdint.h>
#if STDC_HEADERS
#include <stdlib.h>
#else
char *malloc(), *realloc();
#endif
/* Always add at least this many bytes when extending the buffer. */
#define MIN_CHUNK 64
/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
+ OFFSET (and null-terminate it). *LINEPTR is a pointer returned from
malloc (or NULL), pointing to *N characters of space. It is realloc'd
as necessary. Return the number of characters read (not including the
null terminator), or -1 on error or EOF. On a -1 return, the caller
should check feof(), if not then errno has been set to indicate
the error. */
int32_t getstr(char **lineptr, size_t *n, FILE *stream, char terminator, int32_t offset) {
int32_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */
char * read_pos; /* Where we're reading into *LINEPTR. */
int32_t ret;
if (!lineptr || !n || !stream) {
errno = EINVAL;
return -1;
}
if (!*lineptr) {
*n = MIN_CHUNK;
*lineptr = malloc(*n);
if (!*lineptr) {
errno = ENOMEM;
return -1;
}
}
nchars_avail = (int32_t)(*n - offset);
read_pos = *lineptr + offset;
for (;;) {
int32_t save_errno;
register int32_t c = getc(stream);
save_errno = errno;
/* We always want at least one char left in the buffer, since we
always (unless we get an error while reading the first char)
NUL-terminate the line buffer. */
assert((*lineptr + *n) == (read_pos + nchars_avail));
if (nchars_avail < 2) {
if (*n > MIN_CHUNK)
*n *= 2;
else
*n += MIN_CHUNK;
nchars_avail = (int32_t)(*n + *lineptr - read_pos);
char* lineptr1 = realloc(*lineptr, *n);
if (!lineptr1) {
errno = ENOMEM;
return -1;
}
*lineptr = lineptr1;
read_pos = *n - nchars_avail + *lineptr;
assert((*lineptr + *n) == (read_pos + nchars_avail));
}
if (ferror(stream)) {
/* Might like to return partial line, but there is no
place for us to store errno. And we don't want to just
lose errno. */
errno = save_errno;
return -1;
}
if (c == EOF) {
/* Return partial line, if any. */
if (read_pos == *lineptr)
return -1;
else
break;
}
*read_pos++ = c;
nchars_avail--;
if (c == terminator) /* Return the line. */
break;
}
/* Done - NUL terminate and return the number of chars read. */
*read_pos = '\0';
ret = (int32_t)(read_pos - (*lineptr + offset));
return ret;
}
int32_t tgetline(char **lineptr, size_t *n, FILE *stream) { return getstr(lineptr, n, stream, '\n', 0); }
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tglobal.h"
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
#include <windows.h>
bool taosCheckPthreadValid(pthread_t thread) { return thread.p != NULL; }
void taosResetPthread(pthread_t* thread) { thread->p = 0; }
int64_t taosGetPthreadId(pthread_t thread) {
#ifdef PTW32_VERSION
return pthread_getw32threadid_np(thread);
#else
return (int64_t)thread;
#endif
}
int64_t taosGetSelfPthreadId() { return GetCurrentThreadId(); }
bool taosComparePthread(pthread_t first, pthread_t second) { return first.p == second.p; }
int32_t taosGetPId() { return GetCurrentProcessId(); }
int32_t taosGetCurrentAPPName(char* name, int32_t* len) {
char filepath[1024] = {0};
GetModuleFileName(NULL, filepath, MAX_PATH);
char* sub = strrchr(filepath, '.');
if (sub != NULL) {
*sub = '\0';
}
strcpy(name, filepath);
if (len != NULL) {
*len = (int32_t)strlen(filepath);
}
return 0;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os.h"
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <winsock2.h>
#include <stdio.h>
#include <string.h>
#include <ws2def.h>
#include <tchar.h>
void taosWinSocketInit() {
static char flag = 0;
if (flag == 0) {
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 1);
if (WSAStartup(wVersionRequested, &wsaData) == 0) {
flag = 1;
}
}
}
int32_t taosSetNonblocking(SOCKET sock, int32_t on) {
u_long mode;
if (on) {
mode = 1;
ioctlsocket(sock, FIONBIO, &mode);
} else {
mode = 0;
ioctlsocket(sock, FIONBIO, &mode);
}
return 0;
}
void taosIgnSIGPIPE() {}
void taosBlockSIGPIPE() {}
void taosSetMaskSIGPIPE() {}
int32_t taosSetSockOpt(SOCKET socketfd, int32_t level, int32_t optname, void *optval, int32_t optlen) {
if (level == SOL_SOCKET && optname == TCP_KEEPCNT) {
return 0;
}
if (level == SOL_TCP && optname == TCP_KEEPIDLE) {
return 0;
}
if (level == SOL_TCP && optname == TCP_KEEPINTVL) {
return 0;
}
if (level == SOL_TCP && optname == TCP_KEEPCNT) {
return 0;
}
return setsockopt(socketfd, level, optname, optval, optlen);
}
#ifdef _MSC_VER
//#if _MSC_VER >= 1900
uint32_t taosInetAddr(char *ipAddr) {
uint32_t value;
int32_t ret = inet_pton(AF_INET, ipAddr, &value);
if (ret <= 0) {
return INADDR_NONE;
} else {
return value;
}
}
const char *taosInetNtoa(struct in_addr ipInt) {
// not thread safe, only for debug usage while print log
static char tmpDstStr[16];
return inet_ntop(AF_INET, &ipInt, tmpDstStr, INET6_ADDRSTRLEN);
}
//#endif
#endif
#if defined(_TD_GO_DLL_)
uint64_t htonll(uint64_t val) { return (((uint64_t)htonl(val)) << 32) + htonl(val >> 32); }
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
void syslog(int unused, const char *format, ...) {}
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tconfig.h"
#include "tglobal.h"
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
#include "taoserror.h"
#if (_WIN64)
#include <iphlpapi.h>
#include <mswsock.h>
#include <psapi.h>
#include <stdio.h>
#include <windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Mswsock.lib ")
#endif
#include <objbase.h>
#pragma warning(push)
#pragma warning(disable : 4091)
#include <DbgHelp.h>
#pragma warning(pop)
static int32_t taosGetTotalMemory() {
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) {
return 0;
}
float nMemTotal = memsStat.ullTotalPhys / (1024.0f * 1024.0f);
return (int32_t)nMemTotal;
}
bool taosGetSysMemory(float *memoryUsedMB) {
MEMORYSTATUSEX memsStat;
memsStat.dwLength = sizeof(memsStat);
if (!GlobalMemoryStatusEx(&memsStat)) {
return false;
}
float nMemFree = memsStat.ullAvailPhys / (1024.0f * 1024.0f);
float nMemTotal = memsStat.ullTotalPhys / (1024.0f * 1024.0f);
*memoryUsedMB = nMemTotal - nMemFree;
return true;
}
bool taosGetProcMemory(float *memoryUsedMB) {
unsigned bytes_used = 0;
#if defined(_WIN64) && defined(_MSC_VER)
PROCESS_MEMORY_COUNTERS pmc;
HANDLE cur_proc = GetCurrentProcess();
if (GetProcessMemoryInfo(cur_proc, &pmc, sizeof(pmc))) {
bytes_used = (unsigned)(pmc.WorkingSetSize + pmc.PagefileUsage);
}
#endif
*memoryUsedMB = (float)bytes_used / 1024 / 1024;
return true;
}
static void taosGetSystemTimezone() {
// get and set default timezone
SGlobalCfg *cfg_timezone = taosGetConfigOption("timezone");
if (cfg_timezone && cfg_timezone->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
char *tz = getenv("TZ");
if (tz == NULL || strlen(tz) == 0) {
strcpy(tsTimezone, "not configured");
} else {
strcpy(tsTimezone, tz);
}
cfg_timezone->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uInfo("timezone not configured, use default");
}
}
static void taosGetSystemLocale() {
// get and set default locale
SGlobalCfg *cfg_locale = taosGetConfigOption("locale");
if (cfg_locale && cfg_locale->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
char *locale = setlocale(LC_CTYPE, "chs");
if (locale != NULL) {
tstrncpy(tsLocale, locale, TSDB_LOCALE_LEN);
cfg_locale->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uInfo("locale not configured, set to default:%s", tsLocale);
}
}
SGlobalCfg *cfg_charset = taosGetConfigOption("charset");
if (cfg_charset && cfg_charset->cfgStatus < TAOS_CFG_CSTATUS_DEFAULT) {
strcpy(tsCharset, "cp936");
cfg_charset->cfgStatus = TAOS_CFG_CSTATUS_DEFAULT;
uInfo("charset not configured, set to default:%s", tsCharset);
}
}
int32_t taosGetCpuCores() {
SYSTEM_INFO info;
GetSystemInfo(&info);
return (int32_t)info.dwNumberOfProcessors;
}
bool taosGetCpuUsage(float *sysCpuUsage, float *procCpuUsage) {
*sysCpuUsage = 0;
*procCpuUsage = 0;
return true;
}
int32_t taosGetDiskSize(char *dataDir, SysDiskSize *diskSize) {
unsigned _int64 i64FreeBytesToCaller;
unsigned _int64 i64TotalBytes;
unsigned _int64 i64FreeBytes;
BOOL fResult = GetDiskFreeSpaceExA(dataDir, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes,
(PULARGE_INTEGER)&i64FreeBytes);
if (fResult) {
diskSize->tsize = (int64_t)(i64TotalBytes);
diskSize->avail = (int64_t)(i64FreeBytesToCaller);
diskSize->used = (int64_t)(i64TotalBytes - i64FreeBytes);
return 0;
} else {
uError("failed to get disk size, dataDir:%s errno:%s", tsDataDir, strerror(errno));
terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
}
}
bool taosGetCardInfo(int64_t *bytes, int64_t *rbytes, int64_t *tbytes) {
if (bytes) *bytes = 0;
if (rbytes) *rbytes = 0;
if (tbytes) *tbytes = 0;
return true;
}
bool taosGetBandSpeed(float *bandSpeedKb) {
*bandSpeedKb = 0;
return true;
}
bool taosReadProcIO(int64_t *readbyte, int64_t *writebyte) {
IO_COUNTERS io_counter;
if (GetProcessIoCounters(GetCurrentProcess(), &io_counter)) {
if (readbyte) *readbyte = io_counter.ReadTransferCount;
if (writebyte) *writebyte = io_counter.WriteTransferCount;
return true;
}
return false;
}
bool taosGetProcIO(float *readKB, float *writeKB) {
static int64_t lastReadbyte = -1;
static int64_t lastWritebyte = -1;
int64_t curReadbyte = 0;
int64_t curWritebyte = 0;
if (!taosReadProcIO(&curReadbyte, &curWritebyte)) {
return false;
}
if (lastReadbyte == -1 || lastWritebyte == -1) {
lastReadbyte = curReadbyte;
lastWritebyte = curWritebyte;
return false;
}
*readKB = (float)((double)(curReadbyte - lastReadbyte) / 1024);
*writeKB = (float)((double)(curWritebyte - lastWritebyte) / 1024);
if (*readKB < 0) *readKB = 0;
if (*writeKB < 0) *writeKB = 0;
lastReadbyte = curReadbyte;
lastWritebyte = curWritebyte;
return true;
}
void taosGetSystemInfo() {
tsNumOfCores = taosGetCpuCores();
tsTotalMemoryMB = taosGetTotalMemory();
float tmp1, tmp2;
// taosGetDisk();
taosGetBandSpeed(&tmp1);
taosGetCpuUsage(&tmp1, &tmp2);
taosGetProcIO(&tmp1, &tmp2);
taosGetSystemTimezone();
taosGetSystemLocale();
}
void taosPrintOsInfo() {
uInfo(" os numOfCores: %d", tsNumOfCores);
uInfo(" os totalMemory: %d(MB)", tsTotalMemoryMB);
uInfo("==================================");
}
void taosPrintDiskInfo() {
uInfo("==================================");
uInfo(" os totalDisk: %f(GB)", tsTotalDataDirGB);
uInfo(" os usedDisk: %f(GB)", tsUsedDataDirGB);
uInfo(" os availDisk: %f(GB)", tsAvailDataDirGB);
uInfo("==================================");
}
void taosKillSystem() {
uError("function taosKillSystem, exit!");
exit(0);
}
int taosSystem(const char *cmd) {
uError("taosSystem not support");
return -1;
}
int flock(int fd, int option) { return 0; }
LONG WINAPI FlCrashDump(PEXCEPTION_POINTERS ep) {
typedef BOOL(WINAPI * FxMiniDumpWriteDump)(IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile,
IN MINIDUMP_TYPE DumpType,
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
HMODULE dll = LoadLibrary("dbghelp.dll");
if (dll == NULL) return EXCEPTION_CONTINUE_SEARCH;
FxMiniDumpWriteDump mdwd = (FxMiniDumpWriteDump)(GetProcAddress(dll, "MiniDumpWriteDump"));
if (mdwd == NULL) {
FreeLibrary(dll);
return EXCEPTION_CONTINUE_SEARCH;
}
TCHAR path[MAX_PATH];
DWORD len = GetModuleFileName(NULL, path, _countof(path));
path[len - 3] = 'd';
path[len - 2] = 'm';
path[len - 1] = 'p';
HANDLE file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = ep;
mei.ClientPointers = FALSE;
(*mdwd)(GetCurrentProcess(), GetCurrentProcessId(), file, MiniDumpWithHandleData, &mei, NULL, NULL);
CloseHandle(file);
FreeLibrary(dll);
return EXCEPTION_CONTINUE_SEARCH;
}
void taosSetCoreDump() { SetUnhandledExceptionFilter(&FlCrashDump); }
bool taosGetSystemUid(char *uid) {
GUID guid;
CoCreateGuid(&guid);
sprintf(
uid,
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);
return true;
}
char *taosGetCmdlineByPID(int pid) { return ""; }
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tglobal.h"
#include "tulog.h"
void* taosLoadDll(const char *filename) {
return NULL;
}
void* taosLoadSym(void* handle, char* name) {
return NULL;
}
void taosCloseDll(void *handle) {
}
int taosSetConsoleEcho(bool on)
{
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0;
GetConsoleMode(hStdin, &mode );
if (on) {
mode |= ENABLE_ECHO_INPUT;
} else {
mode &= ~ENABLE_ECHO_INPUT;
}
SetConsoleMode(hStdin, mode);
return 0;
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <time.h>
#include <winsock2.h>
int gettimeofday(struct timeval *tv, struct timezone *tz) {
time_t t;
t = time(NULL);
SYSTEMTIME st;
GetLocalTime(&st);
tv->tv_sec = (long)t;
tv->tv_usec = st.wMilliseconds * 1000;
return 0;
}
struct tm *localtime_r(const time_t *timep, struct tm *result) {
localtime_s(result, timep);
return result;
}
\ No newline at end of file
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Windows.h>
#include <Mmsystem.h>
#include <stdio.h>
#include <stdint.h>
#pragma warning( disable : 4244 )
typedef void (*win_timer_f)(int signo);
void WINAPI taosWinOnTimer(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dwl, DWORD_PTR dw2) {
win_timer_f callback = *((win_timer_f *)&dwUser);
if (callback != NULL) {
callback(0);
}
}
static MMRESULT timerId;
int taosInitTimer(win_timer_f callback, int ms) {
DWORD_PTR param = *((int64_t *) & callback);
timerId = timeSetEvent(ms, 1, (LPTIMECALLBACK)taosWinOnTimer, param, TIME_PERIODIC);
if (timerId == 0) {
return -1;
}
return 0;
}
void taosUninitTimer() {
timeKillEvent(timerId);
}
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tglobal.h"
#include "ttimer.h"
#include "tulog.h"
#include "tutil.h"
int wordexp(char *words, wordexp_t *pwordexp, int flags) {
pwordexp->we_offs = 0;
pwordexp->we_wordc = 1;
pwordexp->we_wordv[0] = pwordexp->wordPos;
memset(pwordexp->wordPos, 0, 1025);
if (_fullpath(pwordexp->wordPos, words, 1024) == NULL) {
pwordexp->we_wordv[0] = words;
uError("failed to parse relative path:%s to abs path", words);
return -1;
}
uTrace("parse relative path:%s to abs path:%s", words, pwordexp->wordPos);
return 0;
}
void wordfree(wordexp_t *pwordexp) {}
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
FIND_PATH(HEADER_GTEST_INCLUDE_DIR gtest.h /usr/include/gtest /usr/local/include/gtest)
FIND_LIBRARY(LIB_GTEST_STATIC_DIR libgtest.a /usr/lib/ /usr/local/lib /usr/lib64)
FIND_LIBRARY(LIB_GTEST_SHARED_DIR libgtest.so /usr/lib/ /usr/local/lib /usr/lib64)
IF (HEADER_GTEST_INCLUDE_DIR AND (LIB_GTEST_STATIC_DIR OR LIB_GTEST_SHARED_DIR))
MESSAGE(STATUS "gTest library found, build unit test")
# GoogleTest requires at least C++11
SET(CMAKE_CXX_STANDARD 11)
INCLUDE_DIRECTORIES(/usr/include /usr/local/include)
LINK_DIRECTORIES(/usr/lib /usr/local/lib)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
ADD_EXECUTABLE(osTest ${SOURCE_LIST})
TARGET_LINK_LIBRARIES(osTest taos os tutil common gtest pthread)
ENDIF()
#include "os.h"
#include <gtest/gtest.h>
#include <cassert>
#include <iostream>
#include "taos.h"
#include "ttoken.h"
#include "tutil.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
// test function in os module
TEST(testCase, parse_time) {
taos_options(TSDB_OPTION_TIMEZONE, "GMT-8");
deltaToUtcInitOnce();
// window: 1500000001000, 1500002000000
// pQueryAttr->interval: interval: 86400000, sliding:3600000
int64_t key = 1500000001000;
SInterval interval = {0};
interval.interval = 86400000;
interval.intervalUnit = 'd';
interval.sliding = 3600000;
interval.slidingUnit = 'h';
int64_t s = taosTimeTruncate(key, &interval, TSDB_TIME_PRECISION_MILLI);
ASSERT_TRUE(s + interval.interval >= key);
}
......@@ -398,7 +398,7 @@ int32_t columnValueAscendingComparator(char *f1, char *f2, int32_t type, int32_t
if (len1 != len2) {
return len1 > len2 ? 1 : -1;
} else {
int32_t ret = tasoUcs4Compare(varDataVal(f1), varDataVal(f2), len1);
int32_t ret = tasoUcs4Compare(varDataVal(f1), varDataVal(f2), len1, TSDB_NCHAR_SIZE);
if (ret == 0) {
return 0;
}
......
......@@ -252,7 +252,7 @@ int tfsMkdirAt(const char *rname, int level, int id) {
char aname[TMPNAME_LEN];
snprintf(aname, TMPNAME_LEN, "%s/%s", DISK_DIR(pDisk), rname);
if (taosMkDir(aname, 0755) != 0) {
if (!taosMkDir(aname, 0755)) {
terrno = TAOS_SYSTEM_ERROR(errno);
return -1;
}
......
aux_source_directory(source UTIL_SRC)
add_library(util ${UTIL_SRC})
target_include_directories(
util
PUBLIC "${CMAKE_SOURCE_DIR}/include/util"
PRIVATE "${CMAKE_SOURCE_DIR}/include"
)
target_link_libraries(
util
PRIVATE os
)
\ No newline at end of file
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/rpc/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/sync/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/rmonotonic/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/TSZ/sz/include)
AUX_SOURCE_DIRECTORY(src SRC)
ADD_LIBRARY(tutil ${SRC})
TARGET_LINK_LIBRARIES(tutil pthread os lz4 z rmonotonic ${VAR_TSZ} )
IF (TD_LINUX)
TARGET_LINK_LIBRARIES(tutil m rt)
ADD_SUBDIRECTORY(tests)
FIND_PATH(ICONV_INCLUDE_EXIST iconv.h /usr/include/ /usr/local/include/)
IF (ICONV_INCLUDE_EXIST)
FIND_PATH(ICONV_LIBRARY_A_EXIST libiconv.a /usr/lib/ /usr/local/lib/ /lib64)
FIND_PATH(ICONV_LIBRARY_SO_EXIST libiconv.so /usr/lib/ /usr/local/lib/ /lib64)
IF (ICONV_LIBRARY_A_EXIST OR ICONV_LIBRARY_SO_EXIST)
MESSAGE(STATUS "Use the installed libiconv library")
TARGET_LINK_LIBRARIES(tutil iconv)
ELSE ()
# libiconv library is already included in GLIBC,
MESSAGE(STATUS "Use the iconv functions in GLIBC")
ENDIF ()
ELSE ()
MESSAGE(STATUS "Failed to find iconv, use default encoding method")
ENDIF ()
ELSEIF (TD_WINDOWS)
TARGET_LINK_LIBRARIES(tutil iconv regex winmm IPHLPAPI ws2_32 wepoll)
ELSEIF(TD_DARWIN)
TARGET_LINK_LIBRARIES(tutil m)
TARGET_LINK_LIBRARIES(tutil iconv)
ENDIF()
IF (TD_STORAGE)
TARGET_LINK_LIBRARIES(tutil storage)
ENDIF ()
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TIDPOOL_H
#define TDENGINE_TIDPOOL_H
#ifdef __cplusplus
extern "C" {
#endif
void *taosInitIdPool(int maxId);
int taosUpdateIdPool(void *handle, int maxId);
int taosIdPoolMaxSize(void *handle);
int taosAllocateId(void *handle);
void taosFreeId(void *handle, int id);
void taosIdPoolCleanUp(void *handle);
int taosIdPoolNumOfUsed(void *handle);
bool taosIdPoolMarkStatus(void *handle, int id);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TLOG_H
#define TDENGINE_TLOG_H
#ifdef __cplusplus
extern "C" {
#endif
#define DEBUG_FATAL 1U
#define DEBUG_ERROR DEBUG_FATAL
#define DEBUG_WARN 2U
#define DEBUG_INFO DEBUG_WARN
#define DEBUG_DEBUG 4U
#define DEBUG_TRACE 8U
#define DEBUG_DUMP 16U
#define DEBUG_SCREEN 64U
#define DEBUG_FILE 128U
int32_t taosInitLog(char *logName, int32_t numOfLogLines, int32_t maxFiles);
void taosCloseLog();
void taosResetLog();
void taosPrintLog(const char *flags, int32_t dflag, const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
;
void taosPrintLongString(const char * flags, int32_t dflag, const char *format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
;
void taosDumpData(unsigned char *msg, int32_t len);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TMEMPOOL_H
#define TDENGINE_TMEMPOOL_H
#ifdef __cplusplus
extern "C" {
#endif
#define mpool_h void *
mpool_h taosMemPoolInit(int maxNum, int blockSize);
char *taosMemPoolMalloc(mpool_h handle);
void taosMemPoolFree(mpool_h handle, char *p);
void taosMemPoolCleanUp(mpool_h handle);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TREF_H
#define TDENGINE_TREF_H
#ifdef __cplusplus
extern "C" {
#endif
// open a reference set, max is the mod used by hash, fp is the pointer to free resource function
// return rsetId which will be used by other APIs. On error, -1 is returned, and terrno is set appropriately
int taosOpenRef(int max, void (*fp)(void *));
// close the reference set, refId is the return value by taosOpenRef
// return 0 if success. On error, -1 is returned, and terrno is set appropriately
int taosCloseRef(int refId);
// add ref, p is the pointer to resource or pointer ID
// return Reference ID(rid) allocated. On error, -1 is returned, and terrno is set appropriately
int64_t taosAddRef(int refId, void *p);
// remove ref, rid is the reference ID returned by taosAddRef
// return 0 if success. On error, -1 is returned, and terrno is set appropriately
int taosRemoveRef(int rsetId, int64_t rid);
// acquire ref, rid is the reference ID returned by taosAddRef
// return the resource p. On error, NULL is returned, and terrno is set appropriately
void *taosAcquireRef(int rsetId, int64_t rid);
// release ref, rid is the reference ID returned by taosAddRef
// return 0 if success. On error, -1 is returned, and terrno is set appropriately
int taosReleaseRef(int rsetId, int64_t rid);
// return the first reference if rid is 0, otherwise return the next after current reference.
// if return value is NULL, it means list is over(if terrno is set, it means error happens)
void *taosIterateRef(int rsetId, int64_t rid);
// return the number of references in system
int taosListRef();
#define RID_VALID(x) ((x) > 0)
/* sample code to iterate the refs
void demoIterateRefs(int rsetId) {
void *p = taosIterateRef(refId, 0);
while (p) {
// process P
// get the rid from p
p = taosIterateRef(rsetId, rid);
}
}
*/
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_TREF_H
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os.h"
#include "hash.h"
#include "tulog.h"
#include "taosdef.h"
#define EXT_SIZE 1024
#define HASH_NEED_RESIZE(_h) ((_h)->size >= (_h)->capacity * HASH_DEFAULT_LOAD_FACTOR)
#define DO_FREE_HASH_NODE(_n) \
do { \
tfree(_n); \
} while (0)
#define FREE_HASH_NODE(_h, _n) \
do { \
if ((_h)->freeFp) { \
(_h)->freeFp(GET_HASH_NODE_DATA(_n)); \
} \
\
DO_FREE_HASH_NODE(_n); \
} while (0);
static FORCE_INLINE void __wr_lock(void *lock, int32_t type) {
if (type == HASH_NO_LOCK) {
return;
}
taosWLockLatch(lock);
}
static FORCE_INLINE void __rd_lock(void *lock, int32_t type) {
if (type == HASH_NO_LOCK) {
return;
}
taosRLockLatch(lock);
}
static FORCE_INLINE void __rd_unlock(void *lock, int32_t type) {
if (type == HASH_NO_LOCK) {
return;
}
taosRUnLockLatch(lock);
}
static FORCE_INLINE void __wr_unlock(void *lock, int32_t type) {
if (type == HASH_NO_LOCK) {
return;
}
taosWUnLockLatch(lock);
}
static FORCE_INLINE int32_t taosHashCapacity(int32_t length) {
int32_t len = MIN(length, HASH_MAX_CAPACITY);
int32_t i = 4;
while (i < len) i = (i << 1u);
return i;
}
static FORCE_INLINE SHashNode *doSearchInEntryList(SHashObj *pHashObj, SHashEntry *pe, const void *key, size_t keyLen, uint32_t hashVal) {
SHashNode *pNode = pe->next;
while (pNode) {
if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) {
assert(pNode->hashVal == hashVal);
break;
}
pNode = pNode->next;
}
return pNode;
}
/**
* Resize the hash list if the threshold is reached
*
* @param pHashObj
*/
static void taosHashTableResize(SHashObj *pHashObj);
/**
* @param key key of object for hash, usually a null-terminated string
* @param keyLen length of key
* @param pData actually data. Requires a consecutive memory block, no pointer is allowed in pData.
* Pointer copy causes memory access error.
* @param dsize size of data
* @return SHashNode
*/
static SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal);
/**
* Update the hash node
*
* @param pNode hash node
* @param key key for generate hash value
* @param keyLen key length
* @param pData actual data
* @param dsize size of actual data
* @return hash node
*/
static FORCE_INLINE SHashNode *doUpdateHashNode(SHashObj *pHashObj, SHashEntry* pe, SHashNode* prev, SHashNode *pNode, SHashNode *pNewNode) {
assert(pNode->keyLen == pNewNode->keyLen);
pNode->count--;
if (prev != NULL) {
prev->next = pNewNode;
} else {
pe->next = pNewNode;
}
if (pNode->count <= 0) {
pNewNode->next = pNode->next;
DO_FREE_HASH_NODE(pNode);
} else {
pNewNode->next = pNode;
pe->num++;
atomic_add_fetch_64(&pHashObj->size, 1);
}
return pNewNode;
}
/**
* insert the hash node at the front of the linked list
*
* @param pHashObj
* @param pNode
*/
static void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode);
/**
* Check whether the hash table is empty or not.
*
* @param pHashObj the hash table object
* @return if the hash table is empty or not
*/
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj);
/**
* Get the next element in hash table for iterator
* @param pIter
* @return
*/
SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTypeE type) {
assert(fn != NULL);
if (capacity == 0) {
capacity = 4;
}
SHashObj *pHashObj = (SHashObj *)calloc(1, sizeof(SHashObj));
if (pHashObj == NULL) {
uError("failed to allocate memory, reason:%s", strerror(errno));
return NULL;
}
// the max slots is not defined by user
pHashObj->capacity = taosHashCapacity((int32_t)capacity);
assert((pHashObj->capacity & (pHashObj->capacity - 1)) == 0);
pHashObj->equalFp = memcmp;
pHashObj->hashFp = fn;
pHashObj->type = type;
pHashObj->enableUpdate = update;
pHashObj->hashList = (SHashEntry **)calloc(pHashObj->capacity, sizeof(void *));
if (pHashObj->hashList == NULL) {
free(pHashObj);
uError("failed to allocate memory, reason:%s", strerror(errno));
return NULL;
} else {
pHashObj->pMemBlock = taosArrayInit(8, sizeof(void *));
void *p = calloc(pHashObj->capacity, sizeof(SHashEntry));
for (int32_t i = 0; i < pHashObj->capacity; ++i) {
pHashObj->hashList[i] = (void *)((char *)p + i * sizeof(SHashEntry));
}
taosArrayPush(pHashObj->pMemBlock, &p);
}
return pHashObj;
}
void taosHashSetEqualFp(SHashObj *pHashObj, _equal_fn_t fp) {
if (pHashObj != NULL && fp != NULL) {
pHashObj->equalFp = fp;
}
}
int32_t taosHashGetSize(const SHashObj *pHashObj) {
if (!pHashObj) {
return 0;
}
return (int32_t)atomic_load_64(&pHashObj->size);
}
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj) {
return taosHashGetSize(pHashObj) == 0;
}
int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t size) {
uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
SHashNode *pNewNode = doCreateHashNode(key, keyLen, data, size, hashVal);
if (pNewNode == NULL) {
return -1;
}
// need the resize process, write lock applied
if (HASH_NEED_RESIZE(pHashObj)) {
__wr_lock(&pHashObj->lock, pHashObj->type);
taosHashTableResize(pHashObj);
__wr_unlock(&pHashObj->lock, pHashObj->type);
}
__rd_lock(&pHashObj->lock, pHashObj->type);
int32_t slot = HASH_INDEX(hashVal, pHashObj->capacity);
SHashEntry *pe = pHashObj->hashList[slot];
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWLockLatch(&pe->latch);
}
SHashNode *pNode = pe->next;
if (pe->num > 0) {
assert(pNode != NULL);
} else {
assert(pNode == NULL);
}
SHashNode* prev = NULL;
while (pNode) {
if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) {
assert(pNode->hashVal == hashVal);
break;
}
prev = pNode;
pNode = pNode->next;
}
if (pNode == NULL) {
// no data in hash table with the specified key, add it into hash table
pushfrontNodeInEntryList(pe, pNewNode);
if (pe->num == 0) {
assert(pe->next == NULL);
} else {
assert(pe->next != NULL);
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
// enable resize
__rd_unlock(&pHashObj->lock, pHashObj->type);
atomic_add_fetch_64(&pHashObj->size, 1);
return 0;
} else {
// not support the update operation, return error
if (pHashObj->enableUpdate) {
doUpdateHashNode(pHashObj, pe, prev, pNode, pNewNode);
} else {
DO_FREE_HASH_NODE(pNewNode);
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
// enable resize
__rd_unlock(&pHashObj->lock, pHashObj->type);
return pHashObj->enableUpdate ? 0 : -1;
}
}
void *taosHashGet(SHashObj *pHashObj, const void *key, size_t keyLen) {
return taosHashGetClone(pHashObj, key, keyLen, NULL, NULL);
}
//TODO(yihaoDeng), merge with taosHashGetClone
void* taosHashGetCloneExt(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void** d, size_t *sz) {
if (taosHashTableEmpty(pHashObj) || keyLen == 0 || key == NULL) {
return NULL;
}
uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
// only add the read lock to disable the resize process
__rd_lock(&pHashObj->lock, pHashObj->type);
int32_t slot = HASH_INDEX(hashVal, pHashObj->capacity);
SHashEntry *pe = pHashObj->hashList[slot];
// no data, return directly
if (atomic_load_32(&pe->num) == 0) {
__rd_unlock(&pHashObj->lock, pHashObj->type);
return NULL;
}
char *data = NULL;
// lock entry
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosRLockLatch(&pe->latch);
}
if (pe->num > 0) {
assert(pe->next != NULL);
} else {
assert(pe->next == NULL);
}
SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal);
if (pNode != NULL) {
if (fp != NULL) {
fp(GET_HASH_NODE_DATA(pNode));
}
if (*d == NULL) {
*sz = pNode->dataLen + EXT_SIZE;
*d = calloc(1, *sz);
} else if (*sz < pNode->dataLen){
*sz = pNode->dataLen + EXT_SIZE;
*d = realloc(*d, *sz);
}
memcpy((char *)(*d), GET_HASH_NODE_DATA(pNode), pNode->dataLen);
// just make runtime happy
if ((*sz) - pNode->dataLen > 0) {
memset((char *)(*d) + pNode->dataLen, 0, (*sz) - pNode->dataLen);
}
data = GET_HASH_NODE_DATA(pNode);
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosRUnLockLatch(&pe->latch);
}
__rd_unlock(&pHashObj->lock, pHashObj->type);
return data;
}
void* taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void (*fp)(void *), void* d) {
if (taosHashTableEmpty(pHashObj) || keyLen == 0 || key == NULL) {
return NULL;
}
uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
// only add the read lock to disable the resize process
__rd_lock(&pHashObj->lock, pHashObj->type);
int32_t slot = HASH_INDEX(hashVal, pHashObj->capacity);
SHashEntry *pe = pHashObj->hashList[slot];
// no data, return directly
if (atomic_load_32(&pe->num) == 0) {
__rd_unlock(&pHashObj->lock, pHashObj->type);
return NULL;
}
char *data = NULL;
// lock entry
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosRLockLatch(&pe->latch);
}
if (pe->num > 0) {
assert(pe->next != NULL);
} else {
assert(pe->next == NULL);
}
SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal);
if (pNode != NULL) {
if (fp != NULL) {
fp(GET_HASH_NODE_DATA(pNode));
}
if (d != NULL) {
memcpy(d, GET_HASH_NODE_DATA(pNode), pNode->dataLen);
}
data = GET_HASH_NODE_DATA(pNode);
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosRUnLockLatch(&pe->latch);
}
__rd_unlock(&pHashObj->lock, pHashObj->type);
return data;
}
int32_t taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen) {
return taosHashRemoveWithData(pHashObj, key, keyLen, NULL, 0);
}
int32_t taosHashRemoveWithData(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t dsize) {
if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
return -1;
}
uint32_t hashVal = (*pHashObj->hashFp)(key, (uint32_t)keyLen);
// disable the resize process
__rd_lock(&pHashObj->lock, pHashObj->type);
int32_t slot = HASH_INDEX(hashVal, pHashObj->capacity);
SHashEntry *pe = pHashObj->hashList[slot];
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWLockLatch(&pe->latch);
}
// double check after locked
if (pe->num == 0) {
assert(pe->next == NULL);
taosWUnLockLatch(&pe->latch);
__rd_unlock(&pHashObj->lock, pHashObj->type);
return -1;
}
int code = -1;
SHashNode *pNode = pe->next;
SHashNode *prevNode = NULL;
while (pNode) {
if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0)
break;
prevNode = pNode;
pNode = pNode->next;
}
if (pNode) {
code = 0; // it is found
pNode->count--;
pNode->removed = 1;
if (pNode->count <= 0) {
if (prevNode) {
prevNode->next = pNode->next;
} else {
pe->next = pNode->next;
}
if (data) memcpy(data, GET_HASH_NODE_DATA(pNode), dsize);
pe->num--;
atomic_sub_fetch_64(&pHashObj->size, 1);
FREE_HASH_NODE(pHashObj, pNode);
}
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
__rd_unlock(&pHashObj->lock, pHashObj->type);
return code;
}
int32_t taosHashCondTraverse(SHashObj *pHashObj, bool (*fp)(void *, void *), void *param) {
if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
return 0;
}
// disable the resize process
__rd_lock(&pHashObj->lock, pHashObj->type);
int32_t numOfEntries = (int32_t)pHashObj->capacity;
for (int32_t i = 0; i < numOfEntries; ++i) {
SHashEntry *pEntry = pHashObj->hashList[i];
if (pEntry->num == 0) {
continue;
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWLockLatch(&pEntry->latch);
}
// todo remove the first node
SHashNode *pNode = NULL;
while((pNode = pEntry->next) != NULL) {
if (fp && (!fp(param, GET_HASH_NODE_DATA(pNode)))) {
pEntry->num -= 1;
atomic_sub_fetch_64(&pHashObj->size, 1);
pEntry->next = pNode->next;
if (pEntry->num == 0) {
assert(pEntry->next == NULL);
} else {
assert(pEntry->next != NULL);
}
FREE_HASH_NODE(pHashObj, pNode);
} else {
break;
}
}
// handle the following node
if (pNode != NULL) {
assert(pNode == pEntry->next);
SHashNode *pNext = NULL;
while ((pNext = pNode->next) != NULL) {
// not qualified, remove it
if (fp && (!fp(param, GET_HASH_NODE_DATA(pNext)))) {
pNode->next = pNext->next;
pEntry->num -= 1;
atomic_sub_fetch_64(&pHashObj->size, 1);
if (pEntry->num == 0) {
assert(pEntry->next == NULL);
} else {
assert(pEntry->next != NULL);
}
FREE_HASH_NODE(pHashObj, pNext);
} else {
pNode = pNext;
}
}
}
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pEntry->latch);
}
}
__rd_unlock(&pHashObj->lock, pHashObj->type);
return 0;
}
void taosHashClear(SHashObj *pHashObj) {
if (pHashObj == NULL) {
return;
}
SHashNode *pNode, *pNext;
__wr_lock(&pHashObj->lock, pHashObj->type);
for (int32_t i = 0; i < pHashObj->capacity; ++i) {
SHashEntry *pEntry = pHashObj->hashList[i];
if (pEntry->num == 0) {
assert(pEntry->next == 0);
continue;
}
pNode = pEntry->next;
assert(pNode != NULL);
while (pNode) {
pNext = pNode->next;
FREE_HASH_NODE(pHashObj, pNode);
pNode = pNext;
}
pEntry->num = 0;
pEntry->next = NULL;
}
pHashObj->size = 0;
__wr_unlock(&pHashObj->lock, pHashObj->type);
}
void taosHashCleanup(SHashObj *pHashObj) {
if (pHashObj == NULL) {
return;
}
taosHashClear(pHashObj);
tfree(pHashObj->hashList);
// destroy mem block
size_t memBlock = taosArrayGetSize(pHashObj->pMemBlock);
for (int32_t i = 0; i < memBlock; ++i) {
void *p = taosArrayGetP(pHashObj->pMemBlock, i);
tfree(p);
}
taosArrayDestroy(pHashObj->pMemBlock);
memset(pHashObj, 0, sizeof(SHashObj));
free(pHashObj);
}
// for profile only
int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj) {
if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
return 0;
}
int32_t num = 0;
for (int32_t i = 0; i < pHashObj->size; ++i) {
SHashEntry *pEntry = pHashObj->hashList[i];
if (num < pEntry->num) {
num = pEntry->num;
}
}
return num;
}
void taosHashTableResize(SHashObj *pHashObj) {
if (!HASH_NEED_RESIZE(pHashObj)) {
return;
}
// double the original capacity
SHashNode *pNode = NULL;
SHashNode *pNext = NULL;
int32_t newSize = (int32_t)(pHashObj->capacity << 1u);
if (newSize > HASH_MAX_CAPACITY) {
// uDebug("current capacity:%d, maximum capacity:%d, no resize applied due to limitation is reached",
// pHashObj->capacity, HASH_MAX_CAPACITY);
return;
}
int64_t st = taosGetTimestampUs();
void *pNewEntryList = realloc(pHashObj->hashList, sizeof(void *) * newSize);
if (pNewEntryList == NULL) { // todo handle error
// uDebug("cache resize failed due to out of memory, capacity remain:%d", pHashObj->capacity);
return;
}
pHashObj->hashList = pNewEntryList;
size_t inc = newSize - pHashObj->capacity;
void * p = calloc(inc, sizeof(SHashEntry));
for (int32_t i = 0; i < inc; ++i) {
pHashObj->hashList[i + pHashObj->capacity] = (void *)((char *)p + i * sizeof(SHashEntry));
}
taosArrayPush(pHashObj->pMemBlock, &p);
pHashObj->capacity = newSize;
for (int32_t i = 0; i < pHashObj->capacity; ++i) {
SHashEntry *pe = pHashObj->hashList[i];
if (pe->num == 0) {
assert(pe->next == NULL);
} else {
assert(pe->next != NULL);
}
if (pe->num == 0) {
assert(pe->next == NULL);
continue;
}
while ((pNode = pe->next) != NULL) {
int32_t j = HASH_INDEX(pNode->hashVal, pHashObj->capacity);
if (j != i) {
pe->num -= 1;
pe->next = pNode->next;
if (pe->num == 0) {
assert(pe->next == NULL);
} else {
assert(pe->next != NULL);
}
SHashEntry *pNewEntry = pHashObj->hashList[j];
pushfrontNodeInEntryList(pNewEntry, pNode);
} else {
break;
}
}
if (pNode != NULL) {
while ((pNext = pNode->next) != NULL) {
int32_t j = HASH_INDEX(pNext->hashVal, pHashObj->capacity);
if (j != i) {
pe->num -= 1;
pNode->next = pNext->next;
pNext->next = NULL;
// added into new slot
SHashEntry *pNewEntry = pHashObj->hashList[j];
if (pNewEntry->num == 0) {
assert(pNewEntry->next == NULL);
} else {
assert(pNewEntry->next != NULL);
}
pushfrontNodeInEntryList(pNewEntry, pNext);
} else {
pNode = pNext;
}
}
if (pe->num == 0) {
assert(pe->next == NULL);
} else {
assert(pe->next != NULL);
}
}
}
int64_t et = taosGetTimestampUs();
uDebug("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms", (int32_t)pHashObj->capacity,
((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
}
SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal) {
SHashNode *pNewNode = malloc(sizeof(SHashNode) + keyLen + dsize);
if (pNewNode == NULL) {
uError("failed to allocate memory, reason:%s", strerror(errno));
return NULL;
}
pNewNode->keyLen = (uint32_t)keyLen;
pNewNode->hashVal = hashVal;
pNewNode->dataLen = (uint32_t) dsize;
pNewNode->count = 1;
pNewNode->removed = 0;
pNewNode->next = NULL;
memcpy(GET_HASH_NODE_DATA(pNewNode), pData, dsize);
memcpy(GET_HASH_NODE_KEY(pNewNode), key, keyLen);
return pNewNode;
}
void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode) {
assert(pNode != NULL && pEntry != NULL);
pNode->next = pEntry->next;
pEntry->next = pNode;
pEntry->num += 1;
}
size_t taosHashGetMemSize(const SHashObj *pHashObj) {
if (pHashObj == NULL) {
return 0;
}
return (pHashObj->capacity * (sizeof(SHashEntry) + POINTER_BYTES)) + sizeof(SHashNode) * taosHashGetSize(pHashObj) + sizeof(SHashObj);
}
FORCE_INLINE void *taosHashGetDataKey(SHashObj *pHashObj, void *data) {
SHashNode * node = GET_HASH_PNODE(data);
return GET_HASH_NODE_KEY(node);
}
FORCE_INLINE uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data) {
SHashNode * node = GET_HASH_PNODE(data);
return node->keyLen;
}
// release the pNode, return next pNode, and lock the current entry
static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) {
SHashNode *pOld = (SHashNode *)GET_HASH_PNODE(p);
SHashNode *prevNode = NULL;
*slot = HASH_INDEX(pOld->hashVal, pHashObj->capacity);
SHashEntry *pe = pHashObj->hashList[*slot];
// lock entry
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWLockLatch(&pe->latch);
}
SHashNode *pNode = pe->next;
while (pNode) {
if (pNode == pOld)
break;
prevNode = pNode;
pNode = pNode->next;
}
if (pNode) {
pNode = pNode->next;
while (pNode) {
if (pNode->removed == 0) break;
pNode = pNode->next;
}
pOld->count--;
if (pOld->count <=0) {
if (prevNode) {
prevNode->next = pOld->next;
} else {
pe->next = pOld->next;
}
pe->num--;
atomic_sub_fetch_64(&pHashObj->size, 1);
FREE_HASH_NODE(pHashObj, pOld);
}
} else {
uError("pNode:%p data:%p is not there!!!", pNode, p);
}
return pNode;
}
void *taosHashIterate(SHashObj *pHashObj, void *p) {
if (pHashObj == NULL) return NULL;
int slot = 0;
char *data = NULL;
// only add the read lock to disable the resize process
__rd_lock(&pHashObj->lock, pHashObj->type);
SHashNode *pNode = NULL;
if (p) {
pNode = taosHashReleaseNode(pHashObj, p, &slot);
if (pNode == NULL) {
SHashEntry *pe = pHashObj->hashList[slot];
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
slot = slot + 1;
}
}
if (pNode == NULL) {
for (; slot < pHashObj->capacity; ++slot) {
SHashEntry *pe = pHashObj->hashList[slot];
// lock entry
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWLockLatch(&pe->latch);
}
pNode = pe->next;
while (pNode) {
if (pNode->removed == 0) break;
pNode = pNode->next;
}
if (pNode) break;
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
}
}
if (pNode) {
SHashEntry *pe = pHashObj->hashList[slot];
pNode->count++;
data = GET_HASH_NODE_DATA(pNode);
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
}
__rd_unlock(&pHashObj->lock, pHashObj->type);
return data;
}
void taosHashCancelIterate(SHashObj *pHashObj, void *p) {
if (pHashObj == NULL || p == NULL) return;
// only add the read lock to disable the resize process
__rd_lock(&pHashObj->lock, pHashObj->type);
int slot;
taosHashReleaseNode(pHashObj, p, &slot);
SHashEntry *pe = pHashObj->hashList[slot];
if (pHashObj->type == HASH_ENTRY_LOCK) {
taosWUnLockLatch(&pe->latch);
}
__rd_unlock(&pHashObj->lock, pHashObj->type);
}
......@@ -139,7 +139,7 @@ void walClose(void *handle) {
}
static int32_t walInitObj(SWal *pWal) {
if (taosMkDir(pWal->path, 0755) != 0) {
if (!taosMkDir(pWal->path, 0755)) {
wError("vgId:%d, path:%s, failed to create directory since %s", pWal->vgId, pWal->path, strerror(errno));
return TAOS_SYSTEM_ERROR(errno);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册