Compare commits

...

17 Commits

Author SHA1 Message Date
YuQing 4c6efd434b INSTALL changed for V1.0.88 2026-09-06 14:57:35 +08:00
YuQing 02227ff318 upgrade version to 1.0.88 2026-09-04 11:10:27 +08:00
YuQing 9493e1ad47 add functions: parse_timestamp and iniGetTimestampValueEx 2026-09-04 09:53:07 +08:00
YuQing 15424dfc1c local_host_ip_addrs_to_string: fix buffer overflow 2026-09-03 15:21:36 +08:00
YuQing 564facf33e INSTALL changed for 1.0.87 2026-08-24 15:21:41 +08:00
YuQing f6f664b33d call getFileContentEx with offset constant 2026-07-22 15:34:16 +08:00
YuQing 7b06207f6f doc/ini_file_reader-Chinese.md beautify 2026-07-15 11:55:03 +08:00
YuQing d21a95b02e upgrade version to 1.0.87 2026-07-14 08:30:01 +08:00
YuQing a755beb263 README.md small changes 2026-07-11 09:21:27 +08:00
YuQing 369fe740d3 README.md: beautify layout 2026-07-10 20:45:30 +08:00
YuQing 176cf19576 rename README to README.md 2026-07-10 20:39:34 +08:00
YuQing 598ae419e7 README add doc links 2026-07-10 20:34:54 +08:00
YuQing 4f87de79ec ini_file_readers can refer env variable as %{env::XXX} 2026-07-10 19:45:08 +08:00
YuQing 3cca66ac15 upgrade version to 1.0.86 2026-06-30 09:51:38 +08:00
YuQing 79cd21f667 change return type of format_ip_address and format_ip_port 2026-06-26 11:08:50 +08:00
YuQing 1edcae9cf4 add function fc_parse_version 2026-06-25 15:13:06 +08:00
YuQing 724b008b0e fc_version() return combined integer version 2026-06-24 08:21:27 +08:00
19 changed files with 331 additions and 119 deletions

12
HISTORY
View File

@ -1,4 +1,16 @@
Version 1.88 2026-09-04
* local_host_ip_addrs_to_string: fix buffer overflow
* shared_func.[hc]: add function parse_timestamp
* ini_file_reader.[hc]: add function iniGetTimestampValueEx
Version 1.87 2026-07-10
* ini_file_readers can refer env variable such as %{env::FASTDFS_IPADDR}
Version 1.86 2026-06-26
* add function fc_parse_version
* change return type of format_ip_address and format_ip_port
Version 1.85 2026-06-23 Version 1.85 2026-06-23
* add functions fc_safe_srand and fc_safe_rand for more security under Linux * add functions fc_safe_srand and fc_safe_rand for more security under Linux
* add function seconds_to_human_str * add function seconds_to_human_str

View File

@ -21,5 +21,5 @@ Debian, Ubuntu etc.:
# the command lines as: # the command lines as:
git clone https://github.com/happyfish100/libfastcommon.git git clone https://github.com/happyfish100/libfastcommon.git
cd libfastcommon; git checkout V1.0.85 cd libfastcommon; git checkout V1.0.88
./make.sh clean && ./make.sh && sudo ./make.sh install ./make.sh clean && ./make.sh && sudo ./make.sh install

View File

@ -1,11 +1,3 @@
Copyright (C) 2010 Happy Fish / YuQing
libfastcommon may be copied only under the terms of the Less GNU General
Public License(LGPL).
Please visit the libfastcommon Home Page for more detail.
English language: https://github.com/happyfish100/libfastcommon
Chinese language: http://www.fastken.com/
c common functions library extracted from my open source projects FastDFS and c common functions library extracted from my open source projects FastDFS and
FastDHT. this library is very simple and stable. FastDHT. this library is very simple and stable.
@ -14,20 +6,29 @@ some functions are wrappered into php extension, such as fastcommon_gethostaddrs
fastcommon_id_generator_xxx, fastcommon_get_ifconfigs, fastcommon_get_sysinfo etc. fastcommon_id_generator_xxx, fastcommon_get_ifconfigs, fastcommon_get_sysinfo etc.
C function including: C function including:
logger: [logger.h] asynchronously sync to disk for high performance, thread safe, logger: [logger.h] asynchronously sync to disk for high performance, thread safe,
log rotate, auto delete old log files, compress log file etc. log rotate, auto delete old log files, compress log file etc.
ini file reader: [ini_file_reader.h] support sections marked by [SectionName] ini file reader: [ini_file_reader.h] support sections marked by [SectionName],
support a config item ocurs multiple times for multiple values, such as: support a config item ocurs multiple times for multiple values, such as:
tracker_server = ip1 ```
tracker_server = ip2 tracker_server = ip1
#include directive to include other ini file tracker_server = ip2
#@function directive for annotation ```
#@set directive to set variables for condition of #@if directive
support control statements for special purpose as:
#@if, #@else, #@endif, #@for, #@endfor
id generator: [id_generator.h] generate unique 64 bits integer ID for multi processes ```
#include directive to include other ini file
#@function directive for annotation
#@set directive to set variables for condition of #@if directive
support control statements for special purpose as:
#@if, #@else, #@endif, #@for, #@endfor
```
for more detail, please see [ini file reader guide](doc/ini_file_reader-Chinese.md)
id generator: [id_generator.h] generate unique 64 bits integer ID for multi processes.
for more detail, please see [id generator description](doc/id_generator-Chinese.md)
string operation: [shared_func.h] uppercase, lowercase, trim etc. string operation: [shared_func.h] uppercase, lowercase, trim etc.
@ -72,5 +73,5 @@ C function including:
char convert: [char_converter.h] and [char_convert_loader.h] for fast char convert char convert: [char_converter.h] and [char_convert_loader.h] for fast char convert
detail info please see the c header files. more detail info please see the c header files.

View File

@ -10,38 +10,42 @@ libfastcommon是在github开源的⼀个C函数库。它提供了ini⽂件解析
## ini_file_reader的主要特点 ## ini_file_reader的主要特点
### 1、⽀持section ### 1、⽀持section
例如:
``` ```
例如: [workers] [workers]
threads = 4
# 其他配置项
``` ```
### 2、⼀个配置项可以出现多次 ### 2、⼀个配置项可以出现多次
通过iniGetValues或者iniGetValuesEx获取。例如
``` ```
通过iniGetValues或者iniGetValuesEx获取。例如 tracker_server = 172.16.168.10
tracker_server = ip1 tracker_server = 172.16.168.11
tracker_server = ip2
``` ```
### 3、 #include指令包含其他配置⽂件 ### 3、 #include指令包含其他配置⽂件
可以包含本地配置⽂件也可以包含URL目前仅⽀持HTTP。例如
``` ```
可以包含本地⽂件也可以包含URL目前仅⽀持HTTP。例如 #include http.conf
#include http.conf
``` ```
### 4、 #@function指令⽀持标注 ### 4、 #@function指令⽀持标注
配置项的取值为扩展(外部)动态库的返回值。
⽀持三个内置标注:
``` ```
配置项的取值为扩展(外部)动态库的返回值
V1.39⽀持三个内置标注:
I. LOCAL_IP_GET [inner | private | outer | public] 获取本机IP地址 I. LOCAL_IP_GET [inner | private | outer | public] 获取本机IP地址
inner或private表示获取内网IPouter或public表示获取外网IP inner或private表示获取内网IPouter或public表示获取外网IP
[index]表示获取指定序号的本机IP0表示获取第一个IP-1表示获取最后一个IP [index]表示获取指定序号的本机IP0表示获取第一个IP-1表示获取最后一个IP
例如:[0]、inner[-1], outer[1]等等 例如:[0]、inner[-1], outer[1]等等
II. SHELL_EXEC 获取命令⾏输出执行的command为配置项 II. SHELL_EXEC 获取命令⾏输出执行的command为配置项
III. REPLACE_VARS 替换配置项中%{VARIABLE}格式的变量,变量由#@set指令设置 III. REPLACE_VARS 替换配置项中%{VARIABLE}格式的变量,普通变量由#@set指令设置。
可以引用环境变量,格式为 %{env::VARIABLE},例如 %{env::FASTDFS_IPADDR}
``` ```
```
配置⽰例: 配置⽰例:
```
#@function SHELL_EXEC #@function SHELL_EXEC
host = hostname host = hostname
@ -57,12 +61,14 @@ libfastcommon是在github开源的⼀个C函数库。它提供了ini⽂件解析
### 5、 #@add_annotation 扩展#@function标签 ### 5、 #@add_annotation 扩展#@function标签
```
格式: 格式:
```
#@add_annotation <function> <动态库文件名> [参数1, 参数2, ...] #@add_annotation <function> <动态库文件名> [参数1, 参数2, ...]
```
参数个数0到3个。 参数个数0到3个。
使用libshmcache扩展标签CONFIG_GET示例 使用libshmcache扩展标签CONFIG_GET示例
```
#@add_annotation CONFIG_GET /usr/lib/libshmcache.so /etc/libshmcache.conf #@add_annotation CONFIG_GET /usr/lib/libshmcache.so /etc/libshmcache.conf
#@function CONFIG_GET #@function CONFIG_GET

View File

@ -3,7 +3,7 @@
%define CommitVersion %(echo $COMMIT_VERSION) %define CommitVersion %(echo $COMMIT_VERSION)
Name: libfastcommon Name: libfastcommon
Version: 1.0.85 Version: 1.0.88
Release: 1%{?dist} Release: 1%{?dist}
Summary: c common functions library extracted from my open source projects FastDFS Summary: c common functions library extracted from my open source projects FastDFS
License: LGPL License: LGPL

View File

@ -372,6 +372,16 @@ typedef void* (*MallocFunc)(size_t size);
#define FC_SET_CHAIN_TAIL_NEXT(chain, type, ptr) \ #define FC_SET_CHAIN_TAIL_NEXT(chain, type, ptr) \
((type *)(chain).tail)->next = ptr ((type *)(chain).tail)->next = ptr
#define FC_VERSION_TO_INT(major, minor, patch) \
(major * 1000 * 1000 + minor * 1000 + patch)
#define FC_VERSION_TO_INT1(version) \
FC_VERSION_TO_INT((version).major, \
(version).minor, (version).patch)
#define FC_COMPARE_INT_VERSIONS_TO_OPERATOR_STR(v1, v2) \
(v1 < v2 ? "<" : (v1 == v2 ? "==" : ">"))
#ifdef WIN32 #ifdef WIN32
#define strcasecmp _stricmp #define strcasecmp _stricmp
#endif #endif

View File

@ -180,6 +180,7 @@ int fast_buffer_append_binary(FastBuffer *buffer,
int fast_buffer_append_file(FastBuffer *buffer, const char *filename) int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
{ {
const int64_t offset = 0;
struct stat st; struct stat st;
int result; int result;
int64_t file_size; int64_t file_size;
@ -213,7 +214,7 @@ int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
} }
if ((result=getFileContentEx(filename, buffer->data + buffer->length, if ((result=getFileContentEx(filename, buffer->data + buffer->length,
0, &file_size)) != 0) offset, &file_size)) != 0)
{ {
return result; return result;
} }

View File

@ -15,9 +15,10 @@
#include "fc_version.h" #include "fc_version.h"
void fc_version(Version *version) int fc_version(Version *version)
{ {
version->major = FC_MAJOR_VERSION; version->major = FC_MAJOR_VERSION;
version->minor = FC_MINOR_VERSION; version->minor = FC_MINOR_VERSION;
version->patch = FC_PATCH_VERSION; version->patch = FC_PATCH_VERSION;
return FC_VERSION_TO_INT1(*version);
} }

View File

@ -22,13 +22,16 @@
#define FC_MAJOR_VERSION 1 #define FC_MAJOR_VERSION 1
#define FC_MINOR_VERSION 0 #define FC_MINOR_VERSION 0
#define FC_PATCH_VERSION 85 #define FC_PATCH_VERSION 88
#define FC_VERSION_INT FC_VERSION_TO_INT(FC_MAJOR_VERSION, \
FC_MINOR_VERSION, FC_PATCH_VERSION)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void fc_version(Version *version); int fc_version(Version *version);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -299,6 +299,11 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
{ {
#define VARIABLE_TAG_MIN_LENGTH 4 //%{v} #define VARIABLE_TAG_MIN_LENGTH 4 //%{v}
#define ENV_VAR_NAME_STARTWITH_STR "env::"
#define ENV_VAR_NAME_STARTWITH_LEN (sizeof(ENV_VAR_NAME_STARTWITH_STR) - 1)
#define ENV_VARIABLE_MARK_STR "%{"ENV_VAR_NAME_STARTWITH_STR
SetDirectiveVars *set; SetDirectiveVars *set;
const char *p; const char *p;
const char *e; const char *e;
@ -319,11 +324,13 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
set = iniGetVars(pContext); set = iniGetVars(pContext);
if (set == NULL || set->vars == NULL) { if (set == NULL || set->vars == NULL) {
logWarning("file: "__FILE__", line: %d, " if (strstr(param, ENV_VARIABLE_MARK_STR) == NULL) {
"NO set directives before, set value to %s", logWarning("file: "__FILE__", line: %d, "
__LINE__, param); "NO set directives before, set value to %s",
fc_strlcpy(output, param, FAST_INI_ITEM_VALUE_SIZE); __LINE__, param);
return output; fc_strlcpy(output, param, FAST_INI_ITEM_VALUE_SIZE);
return output;
}
} }
pEnd = param + strlen(param); pEnd = param + strlen(param);
@ -354,25 +361,33 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
*(name + name_len) = '\0'; *(name + name_len) = '\0';
fc_trim(name); fc_trim(name);
name_len = strlen(name); name_len = strlen(name);
if (name_len > 0) { if (name_len > ENV_VAR_NAME_STARTWITH_LEN &&
value = (char *)fc_hash_find(set->vars, name, name_len); memcmp(name, ENV_VAR_NAME_STARTWITH_STR,
ENV_VAR_NAME_STARTWITH_LEN) == 0)
{
value = getenv(name + ENV_VAR_NAME_STARTWITH_LEN);
} else if (name_len > 0) {
if (set != NULL && set->vars != NULL) {
value = (char *)fc_hash_find(set->vars, name, name_len);
} else {
value = NULL;
}
} else { } else {
value = NULL; value = NULL;
} }
if (value != NULL) { if (value != NULL) {
len = strlen(value); len = strlen(value);
} } else {
else {
logWarning("file: "__FILE__", line: %d, " logWarning("file: "__FILE__", line: %d, "
"name: %s NOT found, keep the origin", "variable \"%s\" NOT found, keep the origin",
__LINE__, name); __LINE__, name);
value = start - 2; value = start - 2;
len = p - value; len = p - value;
} }
pDest += iniCopyBuffer(pDest, FAST_INI_ITEM_VALUE_SIZE - pDest += iniCopyBuffer(pDest, FAST_INI_ITEM_VALUE_SIZE -
(pDest - output), value, len); (pDest - output), value, len);
} } else {
else {
if (pDest - output < FAST_INI_ITEM_VALUE_LEN) { if (pDest - output < FAST_INI_ITEM_VALUE_LEN) {
*pDest++ = *p++; *pDest++ = *p++;
} }
@ -3516,3 +3531,26 @@ int iniGetPercentValueEx(IniFullContext *ini_ctx,
return 0; return 0;
} }
int64_t iniGetTimestampValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int64_t nDefaultValue, const int nDefaultUnitTS,
const bool bRetryGlobal)
{
char *pValue;
int64_t nValue;
pValue = iniGetStrValueEx(szSectionName,
szItemName, pContext, bRetryGlobal);
if (pValue == NULL)
{
return nDefaultValue;
}
if (parse_timestamp(pValue, nDefaultUnitTS, &nValue) != 0)
{
return nDefaultValue;
}
return nValue;
}

View File

@ -140,6 +140,10 @@ extern "C" {
#define iniGetPercentValue(ini_ctx, item_name, item_value, default_value) \ #define iniGetPercentValue(ini_ctx, item_name, item_value, default_value) \
iniGetPercentValueEx(ini_ctx, item_name, item_value, default_value, false) iniGetPercentValueEx(ini_ctx, item_name, item_value, default_value, false)
#define iniGetTimestampValue(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetTimestampValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, 1, false)
#define iniGetByteValue(szSectionName, szItemName, pContext, nDefaultValue) \ #define iniGetByteValue(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetByteValueEx(szSectionName, szItemName, \ iniGetByteValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, 1, false) pContext, nDefaultValue, 1, false)
@ -424,6 +428,22 @@ int64_t iniGetByteCorrectValueEx(IniFullContext *pIniContext,
const int nDefaultUnitBytes, const int64_t nMinValue, const int nDefaultUnitBytes, const int64_t nMinValue,
const int64_t nMaxValue, const bool bRetryGlobal); const int64_t nMaxValue, const bool bRetryGlobal);
/** get item timestamp value (64 bits integer)
* parameters:
* szSectionName: the section name, NULL or empty string for
* global section
* szItemName: the item name
* pContext: the ini context
* nDefaultValue: the default value
* nDefaultUnitBytes: the default timestamp unit, such as 1 for second, 86400 for day
* bRetryGlobal: if fetch from global section when the item not exist
* return: int64 value, return nDefaultValue when the item not exist
*/
int64_t iniGetTimestampValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int64_t nDefaultValue, const int nDefaultUnitTS,
const bool bRetryGlobal);
/** get item boolean value /** get item boolean value
* parameters: * parameters:
* szSectionName: the section name, NULL or empty string for * szSectionName: the section name, NULL or empty string for

View File

@ -70,12 +70,21 @@ const char *local_host_ip_addrs_to_string(char *buff, const int size)
len = snprintf(buff, size, "local_host_ip_count: %d,", len = snprintf(buff, size, "local_host_ip_count: %d,",
g_local_host_ip_count); g_local_host_ip_count);
if (len >= size)
{
return buff;
}
pEnd = g_local_host_ip_addrs + pEnd = g_local_host_ip_addrs +
IP_ADDRESS_SIZE * g_local_host_ip_count; IP_ADDRESS_SIZE * g_local_host_ip_count;
for (p=g_local_host_ip_addrs; p<pEnd; p+=IP_ADDRESS_SIZE) for (p=g_local_host_ip_addrs; p<pEnd; p+=IP_ADDRESS_SIZE)
{ {
len += snprintf(buff + len, size - len, " %s", p); len += snprintf(buff + len, size - len, " %s", p);
} if (len >= size)
{
break;
}
}
return buff; return buff;
} }

View File

@ -140,26 +140,27 @@ static int fast_multi_sock_client_do_send(FastMultiSockClient *client,
if (errno == EAGAIN || errno == EWOULDBLOCK) { if (errno == EAGAIN || errno == EWOULDBLOCK) {
break; break;
} else if (errno == EINTR) { //should retry } else if (errno == EINTR) { //should retry
format_ip_address(entry->conn->ip_addr, formatted_ip);
logDebug("file: "__FILE__", line: %d, " logDebug("file: "__FILE__", line: %d, "
"server: %s:%u, ignore interupt signal", __LINE__, "server: %s:%u, ignore interupt signal", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip), formatted_ip, entry->conn->port);
entry->conn->port);
continue; continue;
} else { } else {
result = errno != 0 ? errno : ECONNRESET; result = errno != 0 ? errno : ECONNRESET;
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"send to server %s:%u fail, " "send to server %s:%u fail, "
"errno: %d, error info: %s", __LINE__, "errno: %d, error info: %s", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip), formatted_ip, entry->conn->port,
entry->conn->port, result, strerror(result)); result, strerror(result));
break; break;
} }
} else if (bytes == 0) { } else if (bytes == 0) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"send to server %s:%u, sock: %d fail, " "send to server %s:%u, sock: %d fail, "
"connection disconnected", __LINE__, "connection disconnected", __LINE__, formatted_ip,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, entry->conn->sock); entry->conn->port, entry->conn->sock);
result = ECONNRESET; result = ECONNRESET;
@ -203,10 +204,10 @@ static int fast_multi_sock_client_send_data(FastMultiSockClient *client,
if (client->entries[i].conn->sock < 0) { if (client->entries[i].conn->sock < 0) {
client->entries[i].error_no = ENOTCONN; client->entries[i].error_no = ENOTCONN;
client->entries[i].done = true; client->entries[i].done = true;
format_ip_address(client->entries[i].conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"NOT connected to %s:%u", __LINE__, "NOT connected to %s:%u", __LINE__,
format_ip_address(client->entries[i].conn->ip_addr, formatted_ip, client->entries[i].conn->port);
formatted_ip), client->entries[i].conn->port);
continue; continue;
} }
@ -256,26 +257,27 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
if (errno == EAGAIN || errno == EWOULDBLOCK) { if (errno == EAGAIN || errno == EWOULDBLOCK) {
break; break;
} else if (errno == EINTR) { //should retry } else if (errno == EINTR) { //should retry
format_ip_address(entry->conn->ip_addr, formatted_ip);
logDebug("file: "__FILE__", line: %d, " logDebug("file: "__FILE__", line: %d, "
"server: %s:%u, ignore interupt signal", __LINE__, "server: %s:%u, ignore interupt signal", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip), formatted_ip, entry->conn->port);
entry->conn->port);
continue; continue;
} else { } else {
result = errno != 0 ? errno : ECONNRESET; result = errno != 0 ? errno : ECONNRESET;
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"server: %s:%u, recv failed, " "server: %s:%u, recv failed, "
"errno: %d, error info: %s", __LINE__, "errno: %d, error info: %s", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip), formatted_ip, entry->conn->port,
entry->conn->port, result, strerror(result)); result, strerror(result));
break; break;
} }
} else if (bytes == 0) { } else if (bytes == 0) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"server: %s:%u, sock: %d, recv failed, " "server: %s:%u, sock: %d, recv failed, "
"connection disconnected", __LINE__, "connection disconnected", __LINE__, formatted_ip,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, entry->conn->sock); entry->conn->port, entry->conn->sock);
result = ECONNRESET; result = ECONNRESET;
@ -290,10 +292,10 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
entry->recv_stage = fms_stage_recv_body; entry->recv_stage = fms_stage_recv_body;
body_length = client->get_body_length_func(&entry->recv_buffer); body_length = client->get_body_length_func(&entry->recv_buffer);
if (body_length < 0) { if (body_length < 0) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"server: %s:%u, body_length: %d < 0", __LINE__, "server: %s:%u, body_length: %d < 0", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip), formatted_ip, entry->conn->port, body_length);
entry->conn->port, body_length);
result = EPIPE; result = EPIPE;
break; break;
} else if (body_length == 0) { } else if (body_length == 0) {
@ -374,10 +376,10 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
&client->ioevent, index); &client->ioevent, index);
if (event & IOEVENT_ERROR) { if (event & IOEVENT_ERROR) {
format_ip_address(entry->conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"server: %s:%u, recv error event: %d, connection " "server: %s:%u, recv error event: %d, connection reset",
"reset", __LINE__, format_ip_address(entry->conn-> __LINE__, formatted_ip, entry->conn->port, event);
ip_addr, formatted_ip), entry->conn->port, event);
fast_multi_sock_client_finish(client, entry, ECONNRESET); fast_multi_sock_client_finish(client, entry, ECONNRESET);
continue; continue;
@ -404,10 +406,10 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
if (!client->entries[i].done) { if (!client->entries[i].done) {
fast_multi_sock_client_finish(client, fast_multi_sock_client_finish(client,
client->entries + i, ETIMEDOUT); client->entries + i, ETIMEDOUT);
format_ip_address(client->entries[i].conn->ip_addr, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"recv from %s:%u timedout", __LINE__, "recv from %s:%u timedout", __LINE__,
format_ip_address(client->entries[i].conn->ip_addr, formatted_ip, client->entries[i].conn->port);
formatted_ip), client->entries[i].conn->port);
} }
} }
} }

View File

@ -24,6 +24,7 @@
int get_pid_from_file(const char *pidFilename, pid_t *pid) int get_pid_from_file(const char *pidFilename, pid_t *pid)
{ {
const int64_t offset = 0;
char buff[32]; char buff[32];
int64_t file_size; int64_t file_size;
int result; int result;
@ -33,7 +34,7 @@ int get_pid_from_file(const char *pidFilename, pid_t *pid)
} }
file_size = sizeof(buff); file_size = sizeof(buff);
if ((result=getFileContentEx(pidFilename, buff, 0, &file_size)) != 0) { if ((result=getFileContentEx(pidFilename, buff, offset, &file_size)) != 0) {
return result; return result;
} }
@ -183,12 +184,13 @@ static const char *process_get_exename(const char* program)
static const char *get_exename_by_pid(const pid_t pid, char *buff, static const char *get_exename_by_pid(const pid_t pid, char *buff,
const int buff_size, int *result) const int buff_size, int *result)
{ {
const int64_t offset = 0;
char cmdfile[MAX_PATH_SIZE]; char cmdfile[MAX_PATH_SIZE];
int64_t cmdsz; int64_t cmdsz;
cmdsz = buff_size; cmdsz = buff_size;
sprintf(cmdfile, "/proc/%d/cmdline", pid); sprintf(cmdfile, "/proc/%d/cmdline", pid);
if ((*result=getFileContentEx(cmdfile, buff, 0, &cmdsz)) != 0) { if ((*result=getFileContentEx(cmdfile, buff, offset, &cmdsz)) != 0) {
fprintf(stderr, "read file %s fail, errno: %d, error info: %s\n", fprintf(stderr, "read file %s fail, errno: %d, error info: %s\n",
cmdfile, *result, strerror(*result)); cmdfile, *result, strerror(*result));
return NULL; return NULL;

View File

@ -259,11 +259,11 @@ static int fc_server_check_ip_port(FCServerConfig *ctx,
id1 = current->server->id; id1 = current->server->id;
id2 = previous->server->id; id2 = previous->server->id;
} }
format_ip_address(previous->ip_addr.str, formatted_ip);
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"config file: %s, duplicate ip:port %s:%u, " "config file: %s, duplicate ip:port %s:%u, "
"the server ids: %d, %d", __LINE__, "the server ids: %d, %d", __LINE__, config_filename,
config_filename, format_ip_address(previous->ip_addr.str, formatted_ip, previous->port, id1, id2);
formatted_ip), previous->port, id1, id2);
return EEXIST; return EEXIST;
} }
@ -714,14 +714,14 @@ static int check_addresses_duplicate(FCServerConfig *ctx,
ppend = group_addr->address_array.addrs + group_addr->address_array.count; ppend = group_addr->address_array.addrs + group_addr->address_array.count;
for (ppaddr=group_addr->address_array.addrs+1; ppaddr<ppend; ppaddr++) { for (ppaddr=group_addr->address_array.addrs+1; ppaddr<ppend; ppaddr++) {
if (fc_server_cmp_address_ptr(ppaddr, pprevious) == 0) { if (fc_server_cmp_address_ptr(ppaddr, pprevious) == 0) {
format_ip_address((*ppaddr)->conn.ip_addr, formatted_ip),
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, group: %.*s, " "config filename: %s, section: %s, group: %.*s, "
"duplicate ip and port: %s:%u", __LINE__, "duplicate ip and port: %s:%u", __LINE__,
config_filename, section_name, config_filename, section_name,
group_addr->server_group->group_name.len, group_addr->server_group->group_name.len,
group_addr->server_group->group_name.str, group_addr->server_group->group_name.str,
format_ip_address((*ppaddr)->conn.ip_addr, formatted_ip), formatted_ip, (*ppaddr)->conn.port);
(*ppaddr)->conn.port);
return EEXIST; return EEXIST;
} }
pprevious = ppaddr; pprevious = ppaddr;
@ -967,12 +967,12 @@ static int fc_server_set_host(FCServerConfig *ctx, FCServerInfo *server,
} }
if (!ctx->share_between_groups && (count > 1 && addr->conn.port > 0)) { if (!ctx->share_between_groups && (count > 1 && addr->conn.port > 0)) {
format_ip_address(addr->conn.ip_addr, formatted_ip),
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, " "config filename: %s, section: %s, "
"host %s:%u belongs to %d groups", "host %s:%u belongs to %d groups",
__LINE__, config_filename, section_name, __LINE__, config_filename, section_name,
format_ip_address(addr->conn.ip_addr, formatted_ip), formatted_ip, addr->conn.port, count);
addr->conn.port, count);
return EEXIST; return EEXIST;
} }
@ -1544,9 +1544,10 @@ static void fc_group_servers_to_string(FCServerConfig *ctx,
gaddr->server_group->group_name.str, gaddr->server_group->group_name.str,
SERVER_ITEM_HOST_AFFIX_STR); SERVER_ITEM_HOST_AFFIX_STR);
} }
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
fast_buffer_append(buffer, " = %s:%u\n", fast_buffer_append(buffer, " = %s:%u\n",
format_ip_address((*addr)->conn.ip_addr, formatted_ip), formatted_ip, (*addr)->conn.port);
(*addr)->conn.port);
} }
} }
@ -1655,9 +1656,9 @@ static void fc_server_log_group_servers(FCGroupAddresses *gaddr)
end = gaddr->address_array.addrs + gaddr->address_array.count; end = gaddr->address_array.addrs + gaddr->address_array.count;
for (addr=gaddr->address_array.addrs; addr<end; addr++) { for (addr=gaddr->address_array.addrs; addr<end; addr++) {
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
logInfo(" %d. %s:%u", (int)(addr - gaddr->address_array.addrs + 1), logInfo(" %d. %s:%u", (int)(addr - gaddr->address_array.addrs + 1),
format_ip_address((*addr)->conn.ip_addr, formatted_ip), formatted_ip, (*addr)->conn.port);
(*addr)->conn.port);
} }
} }

View File

@ -2484,6 +2484,88 @@ int parse_bytes(const char *pStr, const int default_unit_bytes, int64_t *bytes)
return result; return result;
} }
int parse_timestamp(const char *str, const int default_unit_secs, int64_t *seconds)
{
char *pReservedEnd;
int result;
pReservedEnd = NULL;
*seconds = strtoll(str, &pReservedEnd, 10);
if (*seconds < 0)
{
logError("file: "__FILE__", line: %d, "
"timestamp: %"PRId64" < 0, input string: %s",
__LINE__, *seconds, str);
return EINVAL;
}
if (pReservedEnd == NULL || *pReservedEnd == '\0')
{
*seconds *= default_unit_secs;
return 0;
}
if (*pReservedEnd == ' ' || *pReservedEnd == '\t')
{
do {
++pReservedEnd;
} while (*pReservedEnd == ' ' || *pReservedEnd == '\t');
if (*pReservedEnd == '\0')
{
*seconds *= default_unit_secs;
return 0;
}
}
if (*(pReservedEnd + 1) != '\0')
{
logError("file: "__FILE__", line: %d, "
"unkown timestamp unit: \"%s\", input string: \"%s\"",
__LINE__, pReservedEnd, str);
return EINVAL;
}
switch (*pReservedEnd)
{
case 's':
result = 0;
break;
case 'm':
*seconds *= 60;
result = 0;
break;
case 'h':
*seconds *= 3600;
result = 0;
break;
case 'd':
*seconds *= 86400;
result = 0;
break;
case 'W':
*seconds *= 7 * 86400;
result = 0;
break;
case 'M':
*seconds *= 30 * 86400;
result = 0;
break;
case 'Y':
*seconds *= 365 * 86400;
result = 0;
break;
default:
result = EINVAL;
logError("file: "__FILE__", line: %d, "
"unkown timestamp unit: \"%s\", input string: \"%s\"",
__LINE__, pReservedEnd, str);
break;
}
return result;
}
int set_rand_seed() int set_rand_seed()
{ {
time_t ts; time_t ts;
@ -3283,6 +3365,7 @@ static int format_bytes_string(const int64_t input_bytes,
} }
p = buff + fc_itoa(n, buff); p = buff + fc_itoa(n, buff);
} }
return p - buff; return p - buff;
} }
@ -4090,12 +4173,13 @@ int fc_check_rename_ex(const char *oldpath, const char *newpath,
int fc_get_first_line(const char *filename, char *buff, int fc_get_first_line(const char *filename, char *buff,
const int buff_size, string_t *line) const int buff_size, string_t *line)
{ {
const int64_t offset = 0;
int result; int result;
int64_t read_bytes; int64_t read_bytes;
char *line_end; char *line_end;
read_bytes = buff_size - 1; read_bytes = buff_size - 1;
if ((result=getFileContentEx(filename, buff, 0, &read_bytes)) != 0) { if ((result=getFileContentEx(filename, buff, offset, &read_bytes)) != 0) {
FC_SET_STRING_EMPTY(*line, buff); FC_SET_STRING_EMPTY(*line, buff);
return result; return result;
} }
@ -4121,6 +4205,7 @@ int fc_get_first_line(const char *filename, char *buff,
int fc_get_first_lines(const char *filename, char *buff, int fc_get_first_lines(const char *filename, char *buff,
const int buff_size, string_t *lines, int *count) const int buff_size, string_t *lines, int *count)
{ {
const int64_t offset = 0;
int result; int result;
int target_count; int target_count;
int64_t read_bytes; int64_t read_bytes;
@ -4134,7 +4219,7 @@ int fc_get_first_lines(const char *filename, char *buff,
} }
read_bytes = buff_size - 1; read_bytes = buff_size - 1;
if ((result=getFileContentEx(filename, buff, 0, &read_bytes)) != 0) { if ((result=getFileContentEx(filename, buff, offset, &read_bytes)) != 0) {
*count = 0; *count = 0;
FC_SET_STRING_EMPTY(*lines, buff); FC_SET_STRING_EMPTY(*lines, buff);
return result; return result;
@ -4691,3 +4776,27 @@ int fc_safe_rand()
return (n & RAND_MAX); return (n & RAND_MAX);
} }
#endif #endif
int fc_parse_version(const char *src, Version *version)
{
const char *p;
int numbers[2];
int i;
numbers[0] = numbers[1] = 0;
p = src;
for (i=0; i<2; i++) {
p = strchr(p, '.');
if (p == NULL) {
break;
}
p++;
numbers[i] = strtol(p, NULL, 10);
}
version->major = strtol(src, NULL, 10);
version->minor = numbers[0];
version->patch = numbers[1];
return FC_VERSION_TO_INT1(*version);
}

View File

@ -878,7 +878,7 @@ int getFileContentEx1(int fd, const char *filename, char *buff,
* size: specify the size to fetch and return the fetched size * size: specify the size to fetch and return the fetched size
* return: error no , 0 success, != 0 fail * return: error no , 0 success, != 0 fail
*/ */
int getFileContentEx(const char *filename, char *buff, \ int getFileContentEx(const char *filename, char *buff,
int64_t offset, int64_t *size); int64_t offset, int64_t *size);
/** get file size /** get file size
@ -979,12 +979,22 @@ int fc_compare_int64_ptr(const int64_t *n1, const int64_t *n2);
/** parse bytes /** parse bytes
* parameters: * parameters:
* pStr: the string to parse * pStr: the string to parse
* default_unit_bytes: default unit if not specified the unit like MB etc. * default_unit_bytes: default unit if not specified, the unit like MB etc.
* bytes: store the parsed bytes * bytes: store the parsed bytes
* return: error no , 0 success, != 0 fail * return: error no , 0 success, != 0 fail
*/ */
int parse_bytes(const char *pStr, const int default_unit_bytes, int64_t *bytes); int parse_bytes(const char *pStr, const int default_unit_bytes, int64_t *bytes);
/** parse timestamp
* parameters:
* str: the string to parse
* default_unit_secs: default unit if not specified
* seconds: store the parsed seconds
* return: error no , 0 success, != 0 fail
*/
int parse_timestamp(const char *str, const int default_unit_secs, int64_t *seconds);
/** set rand seed /** set rand seed
* return: error no , 0 success, != 0 fail * return: error no , 0 success, != 0 fail
*/ */
@ -1877,6 +1887,8 @@ int fc_safe_rand();
#define fc_safe_rand() rand() #define fc_safe_rand() rand()
#endif #endif
int fc_parse_version(const char *src, Version *version);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -706,11 +706,11 @@ static inline bool is_ipv6_addr(const char *ip)
return (*ip == ':' || strchr(ip, ':') != NULL); //ipv6 return (*ip == ':' || strchr(ip, ':') != NULL); //ipv6
} }
static inline const char *format_ip_address(const char *ip, char *buff) static inline int format_ip_address(const char *ip, char *buff)
{ {
int ip_len;
if (is_ipv6_addr(ip)) if (is_ipv6_addr(ip))
{ {
int ip_len;
char *p; char *p;
ip_len = strlen(ip); ip_len = strlen(ip);
@ -720,17 +720,17 @@ static inline const char *format_ip_address(const char *ip, char *buff)
p += ip_len; p += ip_len;
*p++ = ']'; *p++ = ']';
*p = '\0'; *p = '\0';
return p - buff;
} }
else else
{ {
strcpy(buff, ip); ip_len = strlen(ip);
memcpy(buff, ip, ip_len + 1);
return ip_len;
} }
return buff;
} }
static inline const char *format_ip_port(const char *ip, static inline int format_ip_port(const char *ip, const int port, char *buff)
const int port, char *buff)
{ {
int ip_len; int ip_len;
bool is_ipv6; bool is_ipv6;
@ -753,7 +753,7 @@ static inline const char *format_ip_port(const char *ip,
p += fc_itoa(port, p); p += fc_itoa(port, p);
*p = '\0'; *p = '\0';
return buff; return p - buff;
} }
void tcp_set_try_again_when_interrupt(const bool value); void tcp_set_try_again_when_interrupt(const bool value);

View File

@ -118,12 +118,13 @@ int get_sys_cpu_count()
int get_boot_time(struct timeval *boot_time) int get_boot_time(struct timeval *boot_time)
{ {
#ifdef OS_LINUX #ifdef OS_LINUX
const int64_t offset = 0;
char buff[256]; char buff[256];
int64_t bytes; int64_t bytes;
struct sysinfo si; struct sysinfo si;
bytes = sizeof(buff); bytes = sizeof(buff);
if (getFileContentEx("/proc/uptime", buff, 0, &bytes) == 0) if (getFileContentEx("/proc/uptime", buff, offset, &bytes) == 0)
{ {
double uptime; double uptime;
double btime; double btime;
@ -621,6 +622,7 @@ static void parse_proc_stat(char *buff, const int len,
int get_processes(struct fast_process_info **processes, int *count) int get_processes(struct fast_process_info **processes, int *count)
{ {
const int64_t offset = 0;
const char *dirname = "/proc"; const char *dirname = "/proc";
char filename[128]; char filename[128];
char buff[4096]; char buff[4096];
@ -679,7 +681,7 @@ int get_processes(struct fast_process_info **processes, int *count)
sprintf(filename, "%s/%s/stat", dirname, ent->d_name); sprintf(filename, "%s/%s/stat", dirname, ent->d_name);
bytes = sizeof(buff); bytes = sizeof(buff);
if (getFileContentEx(filename, buff, 0, &bytes) != 0) if (getFileContentEx(filename, buff, offset, &bytes) != 0)
{ {
continue; continue;
} }
@ -960,33 +962,16 @@ int get_sysinfo(struct fast_sysinfo *info)
int get_kernel_version(Version *version) int get_kernel_version(Version *version)
{ {
struct utsname name; struct utsname name;
char *p;
int numbers[2];
int i;
if (uname(&name) < 0) if (uname(&name) < 0)
{ {
logError("file: "__FILE__", line: %d, " logError("file: "__FILE__", line: %d, "
"call uname fail, errno: %d, error info: %s", "call uname fail, errno: %d, error info: %s",
__LINE__, errno, STRERROR(errno)); __LINE__, errno, STRERROR(errno));
return errno != 0 ? errno : EFAULT; return errno != 0 ? errno : EFAULT;
} }
numbers[0] = numbers[1] = 0; fc_parse_version(name.release, version);
p = name.release;
for (i=0; i<2; i++) {
p = strchr(p, '.');
if (p == NULL) {
break;
}
p++;
numbers[i] = strtol(p, NULL, 10);
}
version->major = strtol(name.release, NULL, 10);
version->minor = numbers[0];
version->patch = numbers[1];
return 0; return 0;
} }