Compare commits
89 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
795b328bd6 | |
|
|
ac5f4a584f | |
|
|
c044906e63 | |
|
|
ccc84945d3 | |
|
|
c4b6f1fcb5 | |
|
|
017ca1efe7 | |
|
|
71b2229427 | |
|
|
446fa6b815 | |
|
|
98948c11bf | |
|
|
d60b141a21 | |
|
|
86bab518c6 | |
|
|
4b9ef52da2 | |
|
|
e8a9967801 | |
|
|
96c896b09a | |
|
|
8d9feff6e2 | |
|
|
cbcd38a9af | |
|
|
cd55792a89 | |
|
|
511b1066c4 | |
|
|
ddf6b5dfe9 | |
|
|
23cd03bc76 | |
|
|
065184a203 | |
|
|
de80dc19dc | |
|
|
dac653d694 | |
|
|
d5dbe3d030 | |
|
|
7973d81b69 | |
|
|
4576f22e24 | |
|
|
cb6f6f13f3 | |
|
|
012b2038ee | |
|
|
48a0ea2e30 | |
|
|
aa48e3cd9a | |
|
|
47fa7f99df | |
|
|
ec8e47f831 | |
|
|
d9d6255621 | |
|
|
2f75958a4a | |
|
|
a4cae13e07 | |
|
|
f136821c0d | |
|
|
b97f23ced2 | |
|
|
84a1f90a9a | |
|
|
3f19715e45 | |
|
|
ce4c5e23d4 | |
|
|
d59da03d60 | |
|
|
8e51f4de3e | |
|
|
0afae48142 | |
|
|
158924f259 | |
|
|
bf7c6e5144 | |
|
|
6f4b3b7cd8 | |
|
|
b1f3c7894e | |
|
|
ec2db7cd33 | |
|
|
63ef9aa8f4 | |
|
|
1d2f938a30 | |
|
|
e4898affdd | |
|
|
558670bc63 | |
|
|
cf16c41054 | |
|
|
7fbb5c620b | |
|
|
9acc202481 | |
|
|
dd0d4dbc19 | |
|
|
a1ae1cbcb0 | |
|
|
fda2679435 | |
|
|
f0484579e0 | |
|
|
6a18162a12 | |
|
|
8e834f7165 | |
|
|
a256976600 | |
|
|
62a29b55a5 | |
|
|
a6dc24e2f3 | |
|
|
70f6ad56ed | |
|
|
7f1a85b025 | |
|
|
eafb8aae74 | |
|
|
de1e9e7ec4 | |
|
|
aa144b5981 | |
|
|
a0654b83c0 | |
|
|
19dcd0c5c4 | |
|
|
d764571f6e | |
|
|
13fc696432 | |
|
|
e4a9fccddb | |
|
|
5477593ce8 | |
|
|
ce0c23358f | |
|
|
f4020e7622 | |
|
|
ed65725833 | |
|
|
13e213e3f8 | |
|
|
83f757672b | |
|
|
21366a4a2e | |
|
|
aad48cc03d | |
|
|
7a108ec5a2 | |
|
|
98e3471433 | |
|
|
8a97e84e1c | |
|
|
8ce0119aa2 | |
|
|
1b777792ab | |
|
|
2ab381d5e3 | |
|
|
a0f1ac59c8 |
|
|
@ -1,5 +1,6 @@
|
||||||
# Makefile.in
|
# Makefile.in
|
||||||
src/Makefile
|
src/Makefile
|
||||||
|
src/tests/Makefile
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
*.d
|
*.d
|
||||||
|
|
@ -62,6 +63,9 @@ src/tests/test_sorted_array
|
||||||
src/tests/test_sorted_queue
|
src/tests/test_sorted_queue
|
||||||
src/tests/test_thread_local
|
src/tests/test_thread_local
|
||||||
src/tests/test_memcpy
|
src/tests/test_memcpy
|
||||||
|
src/tests/mblock_benchmark
|
||||||
|
src/tests/cpool_benchmark
|
||||||
|
src/tests/test_fast_buffer
|
||||||
|
|
||||||
# other
|
# other
|
||||||
*.swp
|
*.swp
|
||||||
|
|
|
||||||
40
HISTORY
40
HISTORY
|
|
@ -1,4 +1,44 @@
|
||||||
|
|
||||||
|
Version 1.83 2025-11-15
|
||||||
|
* fast_task_queue.h: remove field finish_callback
|
||||||
|
|
||||||
|
Version 1.82 2025-11-04
|
||||||
|
* set use_io_uring explicitly
|
||||||
|
|
||||||
|
Version 1.81 2025-10-05
|
||||||
|
* support Linux io_uring
|
||||||
|
* free_queue support parameter: need_shrink and set task->shrinked
|
||||||
|
* IOEventCallback: change event type from short to int
|
||||||
|
|
||||||
|
Version 1.80 2025-09-10
|
||||||
|
* getIpaddrByNameEx: IPv4 has priority over IPv6
|
||||||
|
* shared_func.[hc]: add function fc_ftoa
|
||||||
|
|
||||||
|
Version 1.79 2025-08-29
|
||||||
|
* logger.h export function log_it_ex3
|
||||||
|
* shared_func.[hc]: add function bytes_to_human_str
|
||||||
|
|
||||||
|
Version 1.78 2025-08-07
|
||||||
|
* getIpaddrByName: normalize ip addr when input addr is IPv4 or IPv6
|
||||||
|
* add files: spinlock.[hc]
|
||||||
|
* shared_func.[hc]: change int2buff, buff2int etc. functions to static inline
|
||||||
|
* shared_func.[hc]: add functions short2hex, int2hex, long2hex etc.
|
||||||
|
* performance opt.: replace sprintf and snprintf as necessary
|
||||||
|
|
||||||
|
Version 1.77 2025-03-18
|
||||||
|
* impl. shorten_path for /./ and /../
|
||||||
|
* add function fc_compare_int64_ptr
|
||||||
|
|
||||||
|
Version 1.76 2025-01-27
|
||||||
|
* get_mounted_filesystems act as program df
|
||||||
|
* add function get_statfs_by_path
|
||||||
|
* add function is_rotational_device_by_path
|
||||||
|
* conn_pool_get_connection_ex add parameter: shared
|
||||||
|
|
||||||
|
Version 1.75 2024-09-22
|
||||||
|
* task init callback support extra argument
|
||||||
|
* connection pool performance optimization
|
||||||
|
|
||||||
Version 1.74 2024-05-18
|
Version 1.74 2024-05-18
|
||||||
* add functions: get_log_level and get_log_level_caption
|
* add functions: get_log_level and get_log_level_caption
|
||||||
* adapt to FreeBSD 13
|
* adapt to FreeBSD 13
|
||||||
|
|
|
||||||
13
INSTALL
13
INSTALL
|
|
@ -6,11 +6,20 @@ Please visit the libfastcommon Home Page for more detail.
|
||||||
English language: https://github.com/happyfish100/libfastcommon
|
English language: https://github.com/happyfish100/libfastcommon
|
||||||
Chinese language: http://www.fastken.com/
|
Chinese language: http://www.fastken.com/
|
||||||
|
|
||||||
|
[Optional Step]
|
||||||
|
You can enable io_uring for higher performance when Linux kernel version >= 6.2,
|
||||||
|
CentOS, RockyLinux, AlmaLinux, RHEL etc.:
|
||||||
|
sudo yum install liburing-devel -y
|
||||||
|
|
||||||
|
Debian, Ubuntu etc.:
|
||||||
|
sudo apt install liburing-dev -y
|
||||||
|
|
||||||
|
|
||||||
# download libfastcommon source codes and install it,
|
# download libfastcommon source codes and install it,
|
||||||
# github address: https://github.com/happyfish100/libfastcommon.git
|
# github address: https://github.com/happyfish100/libfastcommon.git
|
||||||
# gitee address: https://gitee.com/fastdfs100/libfastcommon.git
|
# gitee address: https://gitee.com/fastdfs100/libfastcommon.git
|
||||||
# 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.72
|
cd libfastcommon; git checkout V1.0.83
|
||||||
./make.sh clean && ./make.sh && ./make.sh install
|
./make.sh clean && ./make.sh && sudo ./make.sh install
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,45 @@
|
||||||
|
libfastcommon (1.0.83-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.83-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sun, 23 Nov 2025 10:47:37 +0000
|
||||||
|
|
||||||
|
libfastcommon (1.0.83-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.83-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sun, 23 Nov 2025 10:00:00 +0000
|
||||||
|
|
||||||
|
libfastcommon (1.0.83-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.83-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sun, 23 Nov 2025 09:05:57 +0000
|
||||||
|
|
||||||
|
libfastcommon (1.0.78-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.78-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sat, 16 Aug 2025 16:31:05 +0000
|
||||||
|
|
||||||
|
libfastcommon (1.0.77-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.77-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sun, 06 Apr 2025 16:55:50 +0000
|
||||||
|
|
||||||
|
libfastcommon (1.0.75-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.75-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sun, 29 Sep 2024 15:23:57 +0000
|
||||||
|
|
||||||
|
libfastcommon (1.0.74-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* upgrade to 1.0.74-1
|
||||||
|
|
||||||
|
-- YuQing <384681@qq.com> Sat, 15 Jun 2024 14:45:01 +0000
|
||||||
|
|
||||||
libfastcommon (1.0.73-1) unstable; urgency=medium
|
libfastcommon (1.0.73-1) unstable; urgency=medium
|
||||||
|
|
||||||
* upgrade to 1.0.73-1
|
* upgrade to 1.0.73-1
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
%define CommitVersion %(echo $COMMIT_VERSION)
|
%define CommitVersion %(echo $COMMIT_VERSION)
|
||||||
|
|
||||||
Name: libfastcommon
|
Name: libfastcommon
|
||||||
Version: 1.0.74
|
Version: 1.0.83
|
||||||
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
|
||||||
|
|
@ -17,6 +17,14 @@ BuildRequires: libcurl-devel
|
||||||
Requires: libcurl
|
Requires: libcurl
|
||||||
Requires: %__cp %__mv %__chmod %__grep %__mkdir %__install %__id
|
Requires: %__cp %__mv %__chmod %__grep %__mkdir %__install %__id
|
||||||
|
|
||||||
|
%define kernel_major %(uname -r | cut -d'.' -f1)
|
||||||
|
%define kernel_minor %(uname -r | cut -d'.' -f2)
|
||||||
|
%define kernel_ver_int %(expr %{kernel_major} \\* 100 + %{kernel_minor})
|
||||||
|
%if %{kernel_ver_int} >= 514
|
||||||
|
BuildRequires: liburing-devel >= 2.4
|
||||||
|
Requires: liburing >= 2.4
|
||||||
|
%endif
|
||||||
|
|
||||||
%description
|
%description
|
||||||
c common functions library extracted from my open source projects FastDFS.
|
c common functions library extracted from my open source projects FastDFS.
|
||||||
this library is very simple and stable. functions including: string, logger,
|
this library is very simple and stable. functions including: string, logger,
|
||||||
|
|
|
||||||
26
make.sh
26
make.sh
|
|
@ -112,7 +112,21 @@ HAVE_VMMETER_H=0
|
||||||
HAVE_USER_H=0
|
HAVE_USER_H=0
|
||||||
if [ "$uname" = "Linux" ]; then
|
if [ "$uname" = "Linux" ]; then
|
||||||
OS_NAME=OS_LINUX
|
OS_NAME=OS_LINUX
|
||||||
IOEVENT_USE=IOEVENT_USE_EPOLL
|
|
||||||
|
major_version=$(uname -r | awk -F . '{print $1;}')
|
||||||
|
minor_version=$(uname -r | awk -F . '{print $2;}')
|
||||||
|
if [ $major_version -eq 5 -a $minor_version -ge 14 ] || [ $major_version -gt 5 ]; then
|
||||||
|
out=$(grep -F IORING_OP_SEND_ZC /usr/include/liburing/io_uring.h 2>/dev/null)
|
||||||
|
if [ -n "$out" ]; then
|
||||||
|
IOEVENT_USE=IOEVENT_USE_URING
|
||||||
|
LIBS="$LIBS -luring"
|
||||||
|
else
|
||||||
|
IOEVENT_USE=IOEVENT_USE_EPOLL
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
IOEVENT_USE=IOEVENT_USE_EPOLL
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $glibc_minor -lt 17 ]; then
|
if [ $glibc_minor -lt 17 ]; then
|
||||||
LIBS="$LIBS -lrt"
|
LIBS="$LIBS -lrt"
|
||||||
fi
|
fi
|
||||||
|
|
@ -250,6 +264,7 @@ sed_replace()
|
||||||
|
|
||||||
cd src
|
cd src
|
||||||
cp Makefile.in Makefile
|
cp Makefile.in Makefile
|
||||||
|
sed_replace "s#\\\$(CC)#gcc#g" Makefile
|
||||||
sed_replace "s#\\\$(CFLAGS)#$CFLAGS#g" Makefile
|
sed_replace "s#\\\$(CFLAGS)#$CFLAGS#g" Makefile
|
||||||
sed_replace "s#\\\$(INCS)#$INCS#g" Makefile
|
sed_replace "s#\\\$(INCS)#$INCS#g" Makefile
|
||||||
sed_replace "s#\\\$(LIBS)#$LIBS#g" Makefile
|
sed_replace "s#\\\$(LIBS)#$LIBS#g" Makefile
|
||||||
|
|
@ -260,3 +275,12 @@ make $1 $2 $3
|
||||||
if [ "$1" = "clean" ]; then
|
if [ "$1" = "clean" ]; then
|
||||||
/bin/rm -f Makefile _os_define.h
|
/bin/rm -f Makefile _os_define.h
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
cd tests
|
||||||
|
cp Makefile.in Makefile
|
||||||
|
sed_replace "s#\\\$(CC)#gcc#g" Makefile
|
||||||
|
sed_replace "s#\\\$(INCS)#$INCS#g" Makefile
|
||||||
|
sed_replace "s#\\\$(LIBS)#$LIBS#g" Makefile
|
||||||
|
if [ "$1" = "clean" ]; then
|
||||||
|
/bin/rm -f Makefile
|
||||||
|
fi
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \
|
||||||
multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \
|
multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \
|
||||||
json_parser.lo buffered_file_writer.lo server_id_func.lo \
|
json_parser.lo buffered_file_writer.lo server_id_func.lo \
|
||||||
fc_queue.lo sorted_queue.lo fc_memory.lo shared_buffer.lo \
|
fc_queue.lo sorted_queue.lo fc_memory.lo shared_buffer.lo \
|
||||||
thread_pool.lo array_allocator.lo sorted_array.lo
|
thread_pool.lo array_allocator.lo sorted_array.lo spinlock.lo
|
||||||
|
|
||||||
FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
|
FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
|
||||||
logger.o sockopt.o base64.o sched_thread.o \
|
logger.o sockopt.o base64.o sched_thread.o \
|
||||||
|
|
@ -31,7 +31,7 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
|
||||||
multi_socket_client.o skiplist_set.o uniq_skiplist.o \
|
multi_socket_client.o skiplist_set.o uniq_skiplist.o \
|
||||||
json_parser.o buffered_file_writer.o server_id_func.o \
|
json_parser.o buffered_file_writer.o server_id_func.o \
|
||||||
fc_queue.o sorted_queue.o fc_memory.o shared_buffer.o \
|
fc_queue.o sorted_queue.o fc_memory.o shared_buffer.o \
|
||||||
thread_pool.o array_allocator.o sorted_array.o
|
thread_pool.o array_allocator.o sorted_array.o spinlock.o
|
||||||
|
|
||||||
HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
|
HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
|
||||||
shared_func.h pthread_func.h ini_file_reader.h _os_define.h \
|
shared_func.h pthread_func.h ini_file_reader.h _os_define.h \
|
||||||
|
|
@ -47,7 +47,7 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
|
||||||
fc_list.h locked_list.h json_parser.h buffered_file_writer.h \
|
fc_list.h locked_list.h json_parser.h buffered_file_writer.h \
|
||||||
server_id_func.h fc_queue.h sorted_queue.h fc_memory.h \
|
server_id_func.h fc_queue.h sorted_queue.h fc_memory.h \
|
||||||
shared_buffer.h thread_pool.h fc_atomic.h array_allocator.h \
|
shared_buffer.h thread_pool.h fc_atomic.h array_allocator.h \
|
||||||
sorted_array.h
|
sorted_array.h spinlock.h
|
||||||
|
|
||||||
ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS)
|
ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ int array_allocator_init_ex(ArrayAllocatorContext *ctx,
|
||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "%s-array", name_prefix);
|
fc_combine_two_strings(name_prefix, "array", '-', name);
|
||||||
return fast_allocator_init_ex(&ctx->allocator, name,
|
return fast_allocator_init_ex(&ctx->allocator, name,
|
||||||
obj_size, NULL, regions, region - regions, 0,
|
obj_size, NULL, regions, region - regions, 0,
|
||||||
0.9999, reclaim_interval, need_lock);
|
0.9999, reclaim_interval, need_lock);
|
||||||
|
|
|
||||||
11
src/base64.c
11
src/base64.c
|
|
@ -24,6 +24,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "fc_memory.h"
|
#include "fc_memory.h"
|
||||||
|
#include "shared_func.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -53,15 +54,11 @@ void base64_set_line_length(struct base64_context *context, const int length)
|
||||||
* Usually contains only a combination of chars \n and \r.
|
* Usually contains only a combination of chars \n and \r.
|
||||||
* Could be any chars not in set A-Z a-z 0-9 + /.
|
* Could be any chars not in set A-Z a-z 0-9 + /.
|
||||||
*/
|
*/
|
||||||
void base64_set_line_separator(struct base64_context *context, \
|
void base64_set_line_separator(struct base64_context *context,
|
||||||
const char *pLineSeparator)
|
const char *pLineSeparator)
|
||||||
{
|
{
|
||||||
context->line_sep_len = snprintf(context->line_separator, \
|
context->line_sep_len = fc_safe_strcpy(context->
|
||||||
sizeof(context->line_separator), "%s", pLineSeparator);
|
line_separator, pLineSeparator);
|
||||||
if (context->line_sep_len >= sizeof(context->line_separator))
|
|
||||||
{
|
|
||||||
context->line_sep_len = sizeof(context->line_separator) - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void base64_init_ex(struct base64_context *context, const int nLineLength, \
|
void base64_init_ex(struct base64_context *context, const int nLineLength, \
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ int buffered_file_writer_open_ex(BufferedFileWriter *writer,
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(writer->filename, sizeof(writer->filename), "%s", filename);
|
fc_safe_strcpy(writer->filename, filename);
|
||||||
writer->fd = open(writer->filename, O_WRONLY |
|
writer->fd = open(writer->filename, O_WRONLY |
|
||||||
O_CREAT | O_TRUNC | O_CLOEXEC, mode);
|
O_CREAT | O_TRUNC | O_CLOEXEC, mode);
|
||||||
if (writer->fd < 0)
|
if (writer->fd < 0)
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ static inline struct common_blocked_node *common_blocked_queue_alloc_node(
|
||||||
struct common_blocked_node *node;
|
struct common_blocked_node *node;
|
||||||
|
|
||||||
pthread_mutex_lock(&(queue->lc_pair.lock));
|
pthread_mutex_lock(&(queue->lc_pair.lock));
|
||||||
node = fast_mblock_alloc_object(&queue->mblock);
|
node = (struct common_blocked_node *)fast_mblock_alloc_object(&queue->mblock);
|
||||||
pthread_mutex_unlock(&(queue->lc_pair.lock));
|
pthread_mutex_unlock(&(queue->lc_pair.lock));
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,13 +112,21 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
|
||||||
#define SYNC_LOG_BUFF_DEF_INTERVAL 10
|
#define SYNC_LOG_BUFF_DEF_INTERVAL 10
|
||||||
#define TIME_NONE -1
|
#define TIME_NONE -1
|
||||||
|
|
||||||
|
#define FC_BYTES_ONE_KB ( 1 << 10)
|
||||||
|
#define FC_BYTES_ONE_MB ( 1 << 20)
|
||||||
|
#define FC_BYTES_ONE_GB ( 1 << 30)
|
||||||
|
#define FC_BYTES_ONE_TB (1LL << 40)
|
||||||
|
#define FC_BYTES_ONE_PB (1LL << 50)
|
||||||
|
#define FC_BYTES_ONE_EB (1LL << 60)
|
||||||
|
|
||||||
#if defined(IOV_MAX) && IOV_MAX > 256
|
#if defined(IOV_MAX) && IOV_MAX > 256
|
||||||
#define FC_IOV_BATCH_SIZE 256
|
#define FC_IOV_BATCH_SIZE 256
|
||||||
#else
|
#else
|
||||||
#define FC_IOV_BATCH_SIZE IOV_MAX
|
#define FC_IOV_BATCH_SIZE IOV_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 由于要支持IPv6,所以将IP_ADDRESS_SIZE的值由16修改为46
|
#define IPV4_ADDRESS_SIZE INET_ADDRSTRLEN //16
|
||||||
|
#define IPV6_ADDRESS_SIZE INET6_ADDRSTRLEN //46
|
||||||
#define IP_ADDRESS_SIZE INET6_ADDRSTRLEN //46
|
#define IP_ADDRESS_SIZE INET6_ADDRSTRLEN //46
|
||||||
#define FORMATTED_IP_SIZE (IP_ADDRESS_SIZE + 2)
|
#define FORMATTED_IP_SIZE (IP_ADDRESS_SIZE + 2)
|
||||||
#define INFINITE_FILE_SIZE (256 * 1024LL * 1024 * 1024 * 1024 * 1024LL)
|
#define INFINITE_FILE_SIZE (256 * 1024LL * 1024 * 1024 * 1024 * 1024LL)
|
||||||
|
|
@ -447,6 +455,14 @@ static inline int fc_string_compare(const string_t *s1, const string_t *s2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool fc_string_equal_ex(const char *str1,
|
||||||
|
const int len1, const char *str2, const int len2)
|
||||||
|
{
|
||||||
|
return (len1 == len2) && (memcmp(str1, str2, len1) == 0);
|
||||||
|
}
|
||||||
|
#define fc_string_equals_ex(str1, len1, str2, len2) \
|
||||||
|
fc_string_equal_ex(str1, len1, str2, len2)
|
||||||
|
|
||||||
static inline bool fc_string_equal(const string_t *s1, const string_t *s2)
|
static inline bool fc_string_equal(const string_t *s1, const string_t *s2)
|
||||||
{
|
{
|
||||||
return (s1->len == s2->len) && (memcmp(s1->str, s2->str, s1->len) == 0);
|
return (s1->len == s2->len) && (memcmp(s1->str, s2->str, s1->len) == 0);
|
||||||
|
|
@ -540,6 +556,8 @@ static inline int fc_fallocate(int fd, const int64_t size)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FC_MACRO_STRINGIFY(x) #x
|
||||||
|
#define FC_MACRO_TOSTRING(x) FC_MACRO_STRINGIFY(x)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "sockopt.h"
|
#include "sockopt.h"
|
||||||
#include "shared_func.h"
|
#include "shared_func.h"
|
||||||
|
|
@ -24,10 +25,20 @@
|
||||||
#include "server_id_func.h"
|
#include "server_id_func.h"
|
||||||
#include "connection_pool.h"
|
#include "connection_pool.h"
|
||||||
|
|
||||||
|
static void conn_pool_disconnect_server_cb(ConnectionInfo *conn)
|
||||||
|
{
|
||||||
|
conn_pool_disconnect_server(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool conn_pool_is_connected_cb(ConnectionInfo *conn)
|
||||||
|
{
|
||||||
|
return conn_pool_is_connected(conn);
|
||||||
|
}
|
||||||
|
|
||||||
ConnectionCallbacks g_connection_callbacks = {
|
ConnectionCallbacks g_connection_callbacks = {
|
||||||
false, {{conn_pool_connect_server_ex1,
|
false, {{conn_pool_connect_server_ex1,
|
||||||
conn_pool_disconnect_server,
|
conn_pool_disconnect_server_cb,
|
||||||
conn_pool_is_connected},
|
conn_pool_is_connected_cb},
|
||||||
{NULL, NULL, NULL}}, {NULL}
|
{NULL, NULL, NULL}}, {NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -48,6 +59,159 @@ static int node_init_for_rdma(ConnectionNode *node,
|
||||||
rdma.buffer_size, cp->extra_params.rdma.pd);
|
rdma.buffer_size, cp->extra_params.rdma.pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void conn_pool_get_key(const ConnectionInfo *conn,
|
||||||
|
char *key, int *key_len)
|
||||||
|
{
|
||||||
|
*key_len = strlen(conn->ip_addr);
|
||||||
|
memcpy(key, conn->ip_addr, *key_len);
|
||||||
|
*(key + (*key_len)++) = '-';
|
||||||
|
*key_len += fc_itoa(conn->port, key + (*key_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_conn(ConnectionPool *cp, ConnectionManager *cm,
|
||||||
|
ConnectionInfo *conn, const bool bForce)
|
||||||
|
{
|
||||||
|
ConnectionNode *node;
|
||||||
|
char formatted_ip[FORMATTED_IP_SIZE];
|
||||||
|
|
||||||
|
node = (ConnectionNode *)((char *)conn - sizeof(ConnectionNode));
|
||||||
|
if (node->manager != cm)
|
||||||
|
{
|
||||||
|
format_ip_address(conn->ip_addr, formatted_ip);
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"manager of server entry %s:%u is invalid!",
|
||||||
|
__LINE__, formatted_ip, conn->port);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bForce)
|
||||||
|
{
|
||||||
|
cm->total_count--;
|
||||||
|
|
||||||
|
if (FC_LOG_BY_LEVEL(LOG_DEBUG)) {
|
||||||
|
format_ip_address(conn->ip_addr, formatted_ip);
|
||||||
|
logDebug("file: "__FILE__", line: %d, "
|
||||||
|
"server %s:%u, release connection: %d, "
|
||||||
|
"total_count: %d, free_count: %d",
|
||||||
|
__LINE__, formatted_ip, conn->port,
|
||||||
|
conn->sock, cm->total_count, cm->free_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
|
||||||
|
close_connection(conn);
|
||||||
|
fast_mblock_free_object(&cp->node_allocator, node);
|
||||||
|
|
||||||
|
node = cm->head;
|
||||||
|
while (node != NULL)
|
||||||
|
{
|
||||||
|
node->conn->validate_flag = true;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node->atime = get_current_time();
|
||||||
|
node->next = cm->head;
|
||||||
|
cm->head = node;
|
||||||
|
cm->free_count++;
|
||||||
|
|
||||||
|
if (FC_LOG_BY_LEVEL(LOG_DEBUG)) {
|
||||||
|
format_ip_address(conn->ip_addr, formatted_ip);
|
||||||
|
logDebug("file: "__FILE__", line: %d, "
|
||||||
|
"server %s:%u, free connection: %d, "
|
||||||
|
"total_count: %d, free_count: %d",
|
||||||
|
__LINE__, formatted_ip, conn->port,
|
||||||
|
conn->sock, cm->total_count, cm->free_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ConnectionManager *find_manager(ConnectionPool *cp,
|
||||||
|
ConnectionBucket *bucket, const string_t *key,
|
||||||
|
const bool need_create)
|
||||||
|
{
|
||||||
|
ConnectionManager *cm;
|
||||||
|
|
||||||
|
if (bucket->head != NULL)
|
||||||
|
{
|
||||||
|
if (fc_string_equal(&bucket->head->key, key)) //fast path
|
||||||
|
{
|
||||||
|
return bucket->head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cm = bucket->head->next;
|
||||||
|
while (cm != NULL)
|
||||||
|
{
|
||||||
|
if (fc_string_equal(&cm->key, key))
|
||||||
|
{
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
cm = cm->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!need_create)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cm = (ConnectionManager *)fast_mblock_alloc_object(
|
||||||
|
&cp->manager_allocator);
|
||||||
|
if (cm == NULL)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"malloc %d bytes fail", __LINE__,
|
||||||
|
(int)sizeof(ConnectionManager));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cm->head = NULL;
|
||||||
|
cm->total_count = 0;
|
||||||
|
cm->free_count = 0;
|
||||||
|
if ((cm->key.str=fc_malloc(key->len + 1)) == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(cm->key.str, key->str, key->len + 1);
|
||||||
|
cm->key.len = key->len;
|
||||||
|
|
||||||
|
//add to manager chain
|
||||||
|
cm->next = bucket->head;
|
||||||
|
bucket->head = cm;
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_connection(ConnectionPool *cp, ConnectionInfo *conn,
|
||||||
|
const string_t *key, uint32_t hash_code, const bool bForce)
|
||||||
|
{
|
||||||
|
ConnectionBucket *bucket;
|
||||||
|
ConnectionManager *cm;
|
||||||
|
char formatted_ip[FORMATTED_IP_SIZE];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
bucket = cp->hashtable.buckets + hash_code % cp->hashtable.capacity;
|
||||||
|
pthread_mutex_lock(&bucket->lock);
|
||||||
|
if ((cm=find_manager(cp, bucket, key, false)) != NULL)
|
||||||
|
{
|
||||||
|
result = close_conn(cp, cm, conn, bForce);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format_ip_address(conn->ip_addr, formatted_ip);
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"hash entry of server %s:%u not exist",
|
||||||
|
__LINE__, formatted_ip, conn->port);
|
||||||
|
result = ENOENT;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&bucket->lock);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void cp_tls_destroy(void *ptr)
|
static void cp_tls_destroy(void *ptr)
|
||||||
{
|
{
|
||||||
ConnectionThreadHashTable *htable;
|
ConnectionThreadHashTable *htable;
|
||||||
|
|
@ -55,7 +219,11 @@ static void cp_tls_destroy(void *ptr)
|
||||||
ConnectionNode **end;
|
ConnectionNode **end;
|
||||||
ConnectionNode *current;
|
ConnectionNode *current;
|
||||||
ConnectionNode *node;
|
ConnectionNode *node;
|
||||||
|
string_t key;
|
||||||
|
uint32_t hash_code;
|
||||||
|
char key_buff[INET6_ADDRSTRLEN + 8];
|
||||||
|
|
||||||
|
key.str = key_buff;
|
||||||
htable = ptr;
|
htable = ptr;
|
||||||
end = htable->buckets + htable->cp->extra_params.tls.htable_capacity;
|
end = htable->buckets + htable->cp->extra_params.tls.htable_capacity;
|
||||||
for (pp=htable->buckets; pp<end; pp++) {
|
for (pp=htable->buckets; pp<end; pp++) {
|
||||||
|
|
@ -67,30 +235,65 @@ static void cp_tls_destroy(void *ptr)
|
||||||
do {
|
do {
|
||||||
current = node;
|
current = node;
|
||||||
node = node->next;
|
node = node->next;
|
||||||
conn_pool_close_connection(htable->cp, current->conn);
|
|
||||||
|
conn_pool_get_key(current->conn, key.str, &key.len);
|
||||||
|
hash_code = fc_simple_hash(key.str, key.len);
|
||||||
|
close_connection(htable->cp, current->conn, &key, hash_code, false);
|
||||||
} while (node != NULL);
|
} while (node != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int conn_pool_init_ex1(ConnectionPool *cp, int connect_timeout,
|
static int init_hashtable(ConnectionPool *cp, const int htable_capacity)
|
||||||
|
{
|
||||||
|
int bytes;
|
||||||
|
int result;
|
||||||
|
unsigned int *hash_capacity;
|
||||||
|
ConnectionBucket *bucket;
|
||||||
|
ConnectionBucket *end;
|
||||||
|
|
||||||
|
if (htable_capacity > 0)
|
||||||
|
{
|
||||||
|
hash_capacity = fc_hash_get_prime_capacity(htable_capacity);
|
||||||
|
cp->hashtable.capacity = (hash_capacity != NULL ?
|
||||||
|
*hash_capacity : fc_ceil_prime(htable_capacity));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cp->hashtable.capacity = 163;
|
||||||
|
}
|
||||||
|
bytes = sizeof(ConnectionBucket) * cp->hashtable.capacity;
|
||||||
|
if ((cp->hashtable.buckets=fc_malloc(bytes)) == NULL)
|
||||||
|
{
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = cp->hashtable.buckets + cp->hashtable.capacity;
|
||||||
|
for (bucket=cp->hashtable.buckets; bucket<end; bucket++)
|
||||||
|
{
|
||||||
|
bucket->head = NULL;
|
||||||
|
if ((result=init_pthread_lock(&bucket->lock)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_pool_init_ex1(ConnectionPool *cp, const int connect_timeout,
|
||||||
const int max_count_per_entry, const int max_idle_time,
|
const int max_count_per_entry, const int max_idle_time,
|
||||||
const int htable_init_capacity,
|
const int htable_capacity, fc_connection_callback_func connect_done_func,
|
||||||
fc_connection_callback_func connect_done_func, void *connect_done_args,
|
void *connect_done_args, fc_connection_callback_func validate_func,
|
||||||
fc_connection_callback_func validate_func, void *validate_args,
|
void *validate_args, const int extra_data_size,
|
||||||
const int extra_data_size, const ConnectionExtraParams *extra_params)
|
const ConnectionExtraParams *extra_params)
|
||||||
{
|
{
|
||||||
const int64_t alloc_elements_limit = 0;
|
const int64_t alloc_elements_limit = 0;
|
||||||
int result;
|
int result;
|
||||||
int init_capacity;
|
|
||||||
int extra_connection_size;
|
int extra_connection_size;
|
||||||
fast_mblock_object_init_func obj_init_func;
|
fast_mblock_object_init_func obj_init_func;
|
||||||
|
|
||||||
if ((result=init_pthread_lock(&cp->lock)) != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
cp->connect_timeout_ms = connect_timeout * 1000;
|
cp->connect_timeout_ms = connect_timeout * 1000;
|
||||||
cp->max_count_per_entry = max_count_per_entry;
|
cp->max_count_per_entry = max_count_per_entry;
|
||||||
cp->max_idle_time = max_idle_time;
|
cp->max_idle_time = max_idle_time;
|
||||||
|
|
@ -100,30 +303,33 @@ int conn_pool_init_ex1(ConnectionPool *cp, int connect_timeout,
|
||||||
cp->validate_callback.func = validate_func;
|
cp->validate_callback.func = validate_func;
|
||||||
cp->validate_callback.args = validate_args;
|
cp->validate_callback.args = validate_args;
|
||||||
|
|
||||||
init_capacity = htable_init_capacity > 0 ? htable_init_capacity : 256;
|
|
||||||
if ((result=fast_mblock_init_ex1(&cp->manager_allocator, "cpool-manager",
|
if ((result=fast_mblock_init_ex1(&cp->manager_allocator, "cpool-manager",
|
||||||
sizeof(ConnectionManager), init_capacity,
|
sizeof(ConnectionManager), 256, alloc_elements_limit,
|
||||||
alloc_elements_limit, NULL, NULL, false)) != 0)
|
NULL, NULL, true)) != 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extra_params != NULL) {
|
if (extra_params != NULL && extra_params->rdma.pd != NULL) {
|
||||||
extra_connection_size = G_RDMA_CONNECTION_CALLBACKS.
|
extra_connection_size = G_RDMA_CONNECTION_CALLBACKS.
|
||||||
get_connection_size();
|
get_connection_size();
|
||||||
obj_init_func = (fast_mblock_object_init_func)node_init_for_rdma;
|
obj_init_func = (fast_mblock_object_init_func)node_init_for_rdma;
|
||||||
cp->extra_params = *extra_params;
|
cp->extra_params = *extra_params;
|
||||||
} else {
|
} else {
|
||||||
extra_connection_size = 0;
|
extra_connection_size = 0;
|
||||||
cp->extra_params.tls.enabled = false;
|
if (extra_params != NULL) {
|
||||||
cp->extra_params.tls.htable_capacity = 0;
|
cp->extra_params = *extra_params;
|
||||||
cp->extra_params.rdma.buffer_size = 0;
|
} else {
|
||||||
cp->extra_params.rdma.pd = NULL;
|
cp->extra_params.tls.enabled = false;
|
||||||
|
cp->extra_params.tls.htable_capacity = 163;
|
||||||
|
cp->extra_params.rdma.buffer_size = 0;
|
||||||
|
cp->extra_params.rdma.pd = NULL;
|
||||||
|
}
|
||||||
obj_init_func = (fast_mblock_object_init_func)node_init_for_socket;
|
obj_init_func = (fast_mblock_object_init_func)node_init_for_socket;
|
||||||
}
|
}
|
||||||
if ((result=fast_mblock_init_ex1(&cp->node_allocator, "cpool-node",
|
if ((result=fast_mblock_init_ex1(&cp->node_allocator, "cpool-node",
|
||||||
sizeof(ConnectionNode) + sizeof(ConnectionInfo) +
|
sizeof(ConnectionNode) + sizeof(ConnectionInfo) +
|
||||||
extra_data_size + extra_connection_size, init_capacity,
|
extra_data_size + extra_connection_size, 256,
|
||||||
alloc_elements_limit, obj_init_func, cp, true)) != 0)
|
alloc_elements_limit, obj_init_func, cp, true)) != 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -142,61 +348,77 @@ int conn_pool_init_ex1(ConnectionPool *cp, int connect_timeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fc_hash_init(&(cp->hash_array), fc_simple_hash, init_capacity, 0.75);
|
return init_hashtable(cp, htable_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coon_pool_close_connections(const int index,
|
typedef void (*cp_hash_walk_callback)(ConnectionPool *cp,
|
||||||
const HashData *data, void *args)
|
ConnectionManager *cm, void *args);
|
||||||
|
|
||||||
|
static void conn_pool_hash_walk(ConnectionPool *cp,
|
||||||
|
cp_hash_walk_callback callback, void *args)
|
||||||
{
|
{
|
||||||
ConnectionPool *cp;
|
ConnectionBucket *bucket;
|
||||||
|
ConnectionBucket *end;
|
||||||
ConnectionManager *cm;
|
ConnectionManager *cm;
|
||||||
|
ConnectionManager *current;
|
||||||
|
|
||||||
cp = (ConnectionPool *)args;
|
end = cp->hashtable.buckets + cp->hashtable.capacity;
|
||||||
cm = (ConnectionManager *)data->value;
|
for (bucket=cp->hashtable.buckets; bucket<end; bucket++)
|
||||||
if (cm != NULL)
|
|
||||||
{
|
{
|
||||||
ConnectionNode *node;
|
pthread_mutex_lock(&bucket->lock);
|
||||||
ConnectionNode *deleted;
|
cm = bucket->head;
|
||||||
|
while (cm != NULL)
|
||||||
node = cm->head;
|
|
||||||
while (node != NULL)
|
|
||||||
{
|
{
|
||||||
deleted = node;
|
current = cm;
|
||||||
node = node->next;
|
cm = cm->next;
|
||||||
|
callback(cp, current, args);
|
||||||
G_COMMON_CONNECTION_CALLBACKS[deleted->conn->comm_type].
|
|
||||||
close_connection(deleted->conn);
|
|
||||||
fast_mblock_free_object(&cp->node_allocator, deleted);
|
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&bucket->lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fast_mblock_free_object(&cp->manager_allocator, cm);
|
static void cp_destroy_walk_callback(ConnectionPool *cp,
|
||||||
|
ConnectionManager *cm, void *args)
|
||||||
|
{
|
||||||
|
ConnectionNode *node;
|
||||||
|
ConnectionNode *deleted;
|
||||||
|
|
||||||
|
node = cm->head;
|
||||||
|
while (node != NULL)
|
||||||
|
{
|
||||||
|
deleted = node;
|
||||||
|
node = node->next;
|
||||||
|
G_COMMON_CONNECTION_CALLBACKS[deleted->conn->comm_type].
|
||||||
|
close_connection(deleted->conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
free(cm->key.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void conn_pool_destroy(ConnectionPool *cp)
|
void conn_pool_destroy(ConnectionPool *cp)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&cp->lock);
|
ConnectionBucket *bucket;
|
||||||
fc_hash_walk(&(cp->hash_array), coon_pool_close_connections, cp);
|
ConnectionBucket *end;
|
||||||
fc_hash_destroy(&(cp->hash_array));
|
|
||||||
pthread_mutex_unlock(&cp->lock);
|
|
||||||
|
|
||||||
pthread_mutex_destroy(&cp->lock);
|
if (cp->hashtable.buckets == NULL) {
|
||||||
}
|
return;
|
||||||
|
|
||||||
void conn_pool_disconnect_server(ConnectionInfo *conn)
|
|
||||||
{
|
|
||||||
if (conn->sock >= 0)
|
|
||||||
{
|
|
||||||
close(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool conn_pool_is_connected(ConnectionInfo *conn)
|
conn_pool_hash_walk(cp, cp_destroy_walk_callback, cp);
|
||||||
{
|
|
||||||
return (conn->sock >= 0);
|
end = cp->hashtable.buckets + cp->hashtable.capacity;
|
||||||
|
for (bucket=cp->hashtable.buckets; bucket<end; bucket++) {
|
||||||
|
pthread_mutex_destroy(&bucket->lock);
|
||||||
|
}
|
||||||
|
free(cp->hashtable.buckets);
|
||||||
|
cp->hashtable.buckets = NULL;
|
||||||
|
|
||||||
|
if (cp->extra_params.tls.enabled) {
|
||||||
|
pthread_key_delete(cp->tls_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
fast_mblock_destroy(&cp->manager_allocator);
|
||||||
|
fast_mblock_destroy(&cp->node_allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
int conn_pool_connect_server_ex1(ConnectionInfo *conn,
|
int conn_pool_connect_server_ex1(ConnectionInfo *conn,
|
||||||
|
|
@ -270,53 +492,17 @@ int conn_pool_async_connect_server_ex(ConnectionInfo *conn,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void conn_pool_get_key(const ConnectionInfo *conn,
|
static ConnectionInfo *get_conn(ConnectionPool *cp,
|
||||||
char *key, int *key_len)
|
ConnectionManager *cm, pthread_mutex_t *lock,
|
||||||
|
const ConnectionInfo *conn, const char *service_name,
|
||||||
|
int *err_no)
|
||||||
{
|
{
|
||||||
*key_len = sprintf(key, "%s-%u", conn->ip_addr, conn->port);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ConnectionInfo *get_connection(ConnectionPool *cp,
|
|
||||||
const ConnectionInfo *conn, const string_t *key,
|
|
||||||
const char *service_name, int *err_no)
|
|
||||||
{
|
|
||||||
ConnectionManager *cm;
|
|
||||||
ConnectionNode *node;
|
ConnectionNode *node;
|
||||||
ConnectionInfo *ci;
|
ConnectionInfo *ci;
|
||||||
char formatted_ip[FORMATTED_IP_SIZE];
|
char formatted_ip[FORMATTED_IP_SIZE];
|
||||||
time_t current_time;
|
time_t current_time;
|
||||||
|
|
||||||
pthread_mutex_lock(&cp->lock);
|
|
||||||
cm = (ConnectionManager *)fc_hash_find(
|
|
||||||
&cp->hash_array, key->str, key->len);
|
|
||||||
if (cm == NULL)
|
|
||||||
{
|
|
||||||
cm = (ConnectionManager *)fast_mblock_alloc_object(
|
|
||||||
&cp->manager_allocator);
|
|
||||||
if (cm == NULL)
|
|
||||||
{
|
|
||||||
*err_no = ENOMEM;
|
|
||||||
logError("file: "__FILE__", line: %d, "
|
|
||||||
"malloc %d bytes fail", __LINE__,
|
|
||||||
(int)sizeof(ConnectionManager));
|
|
||||||
pthread_mutex_unlock(&cp->lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cm->head = NULL;
|
|
||||||
cm->total_count = 0;
|
|
||||||
cm->free_count = 0;
|
|
||||||
if ((*err_no=init_pthread_lock(&cm->lock)) != 0)
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&cp->lock);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
fc_hash_insert(&cp->hash_array, key->str, key->len, cm);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&cp->lock);
|
|
||||||
|
|
||||||
current_time = get_current_time();
|
current_time = get_current_time();
|
||||||
pthread_mutex_lock(&cm->lock);
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (cm->head == NULL)
|
if (cm->head == NULL)
|
||||||
|
|
@ -331,7 +517,6 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
__LINE__, cm->total_count, service_name != NULL ?
|
__LINE__, cm->total_count, service_name != NULL ?
|
||||||
service_name : "", service_name != NULL ? " " : "",
|
service_name : "", service_name != NULL ? " " : "",
|
||||||
formatted_ip, conn->port, cp->max_count_per_entry);
|
formatted_ip, conn->port, cp->max_count_per_entry);
|
||||||
pthread_mutex_unlock(&cm->lock);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,7 +528,6 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
logError("file: "__FILE__", line: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
"malloc %d bytes fail", __LINE__, (int)
|
"malloc %d bytes fail", __LINE__, (int)
|
||||||
(sizeof(ConnectionNode) + sizeof(ConnectionInfo)));
|
(sizeof(ConnectionNode) + sizeof(ConnectionInfo)));
|
||||||
pthread_mutex_unlock(&cm->lock);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -352,7 +536,7 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
node->atime = 0;
|
node->atime = 0;
|
||||||
|
|
||||||
cm->total_count++;
|
cm->total_count++;
|
||||||
pthread_mutex_unlock(&cm->lock);
|
pthread_mutex_unlock(lock);
|
||||||
|
|
||||||
memcpy(node->conn->ip_addr, conn->ip_addr, sizeof(conn->ip_addr));
|
memcpy(node->conn->ip_addr, conn->ip_addr, sizeof(conn->ip_addr));
|
||||||
node->conn->port = conn->port;
|
node->conn->port = conn->port;
|
||||||
|
|
@ -372,11 +556,10 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
{
|
{
|
||||||
G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
|
G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
|
||||||
close_connection(node->conn);
|
close_connection(node->conn);
|
||||||
pthread_mutex_lock(&cm->lock);
|
|
||||||
cm->total_count--; //rollback
|
|
||||||
fast_mblock_free_object(&cp->node_allocator, node);
|
fast_mblock_free_object(&cp->node_allocator, node);
|
||||||
pthread_mutex_unlock(&cm->lock);
|
|
||||||
|
|
||||||
|
pthread_mutex_lock(lock);
|
||||||
|
cm->total_count--; //rollback
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,6 +572,8 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
node->conn->sock, cm->total_count,
|
node->conn->sock, cm->total_count,
|
||||||
cm->free_count);
|
cm->free_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(lock);
|
||||||
return node->conn;
|
return node->conn;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -448,8 +633,6 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&cm->lock);
|
|
||||||
|
|
||||||
if (FC_LOG_BY_LEVEL(LOG_DEBUG)) {
|
if (FC_LOG_BY_LEVEL(LOG_DEBUG)) {
|
||||||
format_ip_address(conn->ip_addr, formatted_ip);
|
format_ip_address(conn->ip_addr, formatted_ip);
|
||||||
logDebug("file: "__FILE__", line: %d, "
|
logDebug("file: "__FILE__", line: %d, "
|
||||||
|
|
@ -465,8 +648,37 @@ static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConnectionInfo *get_connection(ConnectionPool *cp,
|
||||||
|
const ConnectionInfo *conn, const string_t *key,
|
||||||
|
const uint32_t hash_code, const char *service_name,
|
||||||
|
const bool shared, int *err_no)
|
||||||
|
{
|
||||||
|
ConnectionBucket *bucket;
|
||||||
|
ConnectionManager *cm;
|
||||||
|
ConnectionInfo *ci;
|
||||||
|
|
||||||
|
bucket = cp->hashtable.buckets + hash_code % cp->hashtable.capacity;
|
||||||
|
pthread_mutex_lock(&bucket->lock);
|
||||||
|
if ((cm=find_manager(cp, bucket, key, true)) != NULL)
|
||||||
|
{
|
||||||
|
ci = get_conn(cp, cm, &bucket->lock, conn, service_name, err_no);
|
||||||
|
if (ci != NULL)
|
||||||
|
{
|
||||||
|
ci->shared = shared;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*err_no = ENOMEM;
|
||||||
|
ci = NULL;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&bucket->lock);
|
||||||
|
return ci;
|
||||||
|
}
|
||||||
|
|
||||||
ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
||||||
const ConnectionInfo *conn, const char *service_name, int *err_no)
|
const ConnectionInfo *conn, const char *service_name,
|
||||||
|
const bool shared, int *err_no)
|
||||||
{
|
{
|
||||||
string_t key;
|
string_t key;
|
||||||
int bytes;
|
int bytes;
|
||||||
|
|
@ -479,8 +691,10 @@ ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
||||||
|
|
||||||
key.str = key_buff;
|
key.str = key_buff;
|
||||||
conn_pool_get_key(conn, key.str, &key.len);
|
conn_pool_get_key(conn, key.str, &key.len);
|
||||||
if (!cp->extra_params.tls.enabled) {
|
hash_code = fc_simple_hash(key.str, key.len);
|
||||||
return get_connection(cp, conn, &key, service_name, err_no);
|
if (!cp->extra_params.tls.enabled || !shared) {
|
||||||
|
return get_connection(cp, conn, &key, hash_code,
|
||||||
|
service_name, shared, err_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
htable = pthread_getspecific(cp->tls_key);
|
htable = pthread_getspecific(cp->tls_key);
|
||||||
|
|
@ -500,7 +714,6 @@ ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_code = fc_simple_hash(key.str, key.len);
|
|
||||||
bucket = htable->buckets + hash_code % cp->
|
bucket = htable->buckets + hash_code % cp->
|
||||||
extra_params.tls.htable_capacity;
|
extra_params.tls.htable_capacity;
|
||||||
if (*bucket == NULL) {
|
if (*bucket == NULL) {
|
||||||
|
|
@ -521,12 +734,13 @@ ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
||||||
*err_no = 0;
|
*err_no = 0;
|
||||||
return node->conn;
|
return node->conn;
|
||||||
} else {
|
} else {
|
||||||
if ((ci=get_connection(cp, conn, &key, service_name,
|
if ((ci=get_connection(cp, conn, &key, hash_code,
|
||||||
err_no)) == NULL)
|
service_name, shared, err_no)) == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//add to thread local hashtable
|
||||||
node = (ConnectionNode *)((char *)ci - sizeof(ConnectionNode));
|
node = (ConnectionNode *)((char *)ci - sizeof(ConnectionNode));
|
||||||
node->next = *bucket;
|
node->next = *bucket;
|
||||||
*bucket = node;
|
*bucket = node;
|
||||||
|
|
@ -535,81 +749,6 @@ ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int close_connection(ConnectionPool *cp, ConnectionInfo *conn,
|
|
||||||
const string_t *key, const bool bForce)
|
|
||||||
{
|
|
||||||
ConnectionManager *cm;
|
|
||||||
ConnectionNode *node;
|
|
||||||
char formatted_ip[FORMATTED_IP_SIZE];
|
|
||||||
|
|
||||||
pthread_mutex_lock(&cp->lock);
|
|
||||||
cm = (ConnectionManager *)fc_hash_find(&cp->hash_array, key->str, key->len);
|
|
||||||
pthread_mutex_unlock(&cp->lock);
|
|
||||||
if (cm == NULL)
|
|
||||||
{
|
|
||||||
format_ip_address(conn->ip_addr, formatted_ip);
|
|
||||||
logError("file: "__FILE__", line: %d, "
|
|
||||||
"hash entry of server %s:%u not exist",
|
|
||||||
__LINE__, formatted_ip, conn->port);
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = (ConnectionNode *)((char *)conn - sizeof(ConnectionNode));
|
|
||||||
if (node->manager != cm)
|
|
||||||
{
|
|
||||||
format_ip_address(conn->ip_addr, formatted_ip);
|
|
||||||
logError("file: "__FILE__", line: %d, "
|
|
||||||
"manager of server entry %s:%u is invalid!",
|
|
||||||
__LINE__, formatted_ip, conn->port);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&cm->lock);
|
|
||||||
if (bForce)
|
|
||||||
{
|
|
||||||
cm->total_count--;
|
|
||||||
|
|
||||||
if (FC_LOG_BY_LEVEL(LOG_DEBUG)) {
|
|
||||||
format_ip_address(conn->ip_addr, formatted_ip);
|
|
||||||
logDebug("file: "__FILE__", line: %d, "
|
|
||||||
"server %s:%u, release connection: %d, "
|
|
||||||
"total_count: %d, free_count: %d",
|
|
||||||
__LINE__, formatted_ip, conn->port,
|
|
||||||
conn->sock, cm->total_count, cm->free_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
|
|
||||||
close_connection(conn);
|
|
||||||
fast_mblock_free_object(&cp->node_allocator, node);
|
|
||||||
|
|
||||||
node = cm->head;
|
|
||||||
while (node != NULL)
|
|
||||||
{
|
|
||||||
node->conn->validate_flag = true;
|
|
||||||
node = node->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
node->atime = get_current_time();
|
|
||||||
node->next = cm->head;
|
|
||||||
cm->head = node;
|
|
||||||
cm->free_count++;
|
|
||||||
|
|
||||||
if (FC_LOG_BY_LEVEL(LOG_DEBUG)) {
|
|
||||||
format_ip_address(conn->ip_addr, formatted_ip);
|
|
||||||
logDebug("file: "__FILE__", line: %d, "
|
|
||||||
"server %s:%u, free connection: %d, "
|
|
||||||
"total_count: %d, free_count: %d",
|
|
||||||
__LINE__, formatted_ip, conn->port,
|
|
||||||
conn->sock, cm->total_count, cm->free_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&cm->lock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int conn_pool_close_connection_ex(ConnectionPool *cp,
|
int conn_pool_close_connection_ex(ConnectionPool *cp,
|
||||||
ConnectionInfo *conn, const bool bForce)
|
ConnectionInfo *conn, const bool bForce)
|
||||||
{
|
{
|
||||||
|
|
@ -623,20 +762,23 @@ int conn_pool_close_connection_ex(ConnectionPool *cp,
|
||||||
|
|
||||||
key.str = key_buff;
|
key.str = key_buff;
|
||||||
conn_pool_get_key(conn, key.str, &key.len);
|
conn_pool_get_key(conn, key.str, &key.len);
|
||||||
if (!cp->extra_params.tls.enabled) {
|
hash_code = fc_simple_hash(key.str, key.len);
|
||||||
return close_connection(cp, conn, &key, bForce);
|
if (!cp->extra_params.tls.enabled || !conn->shared) {
|
||||||
|
return close_connection(cp, conn, &key, hash_code, bForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//thread local logic
|
||||||
if (!bForce) {
|
if (!bForce) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
htable = pthread_getspecific(cp->tls_key);
|
htable = pthread_getspecific(cp->tls_key);
|
||||||
if (htable == NULL) {
|
if (htable == NULL) {
|
||||||
return close_connection(cp, conn, &key, bForce);
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"the thread local key NOT exist!", __LINE__);
|
||||||
|
return close_connection(cp, conn, &key, hash_code, bForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_code = fc_simple_hash(key.str, key.len);
|
|
||||||
bucket = htable->buckets + hash_code % cp->
|
bucket = htable->buckets + hash_code % cp->
|
||||||
extra_params.tls.htable_capacity;
|
extra_params.tls.htable_capacity;
|
||||||
if (*bucket == NULL) {
|
if (*bucket == NULL) {
|
||||||
|
|
@ -663,35 +805,45 @@ int conn_pool_close_connection_ex(ConnectionPool *cp,
|
||||||
} else {
|
} else {
|
||||||
previous->next = node->next;
|
previous->next = node->next;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"%.*s NOT in the thread local hashtable!",
|
||||||
|
__LINE__, key.len, key.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
return close_connection(cp, conn, &key, bForce);
|
return close_connection(cp, conn, &key, hash_code, bForce);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _conn_count_walk(const int index, const HashData *data, void *args)
|
static void cp_stat_walk_callback(ConnectionPool *cp,
|
||||||
|
ConnectionManager *cm, void *args)
|
||||||
{
|
{
|
||||||
int *count;
|
ConnectionPoolStat *stat;
|
||||||
ConnectionManager *cm;
|
|
||||||
ConnectionNode *node;
|
|
||||||
|
|
||||||
count = (int *)args;
|
stat = args;
|
||||||
cm = (ConnectionManager *)data->value;
|
stat->server_count++;
|
||||||
node = cm->head;
|
stat->connection.total_count += cm->total_count;
|
||||||
while (node != NULL)
|
stat->connection.free_count += cm->free_count;
|
||||||
{
|
|
||||||
(*count)++;
|
|
||||||
node = node->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int conn_pool_get_connection_count(ConnectionPool *cp)
|
void conn_pool_stat(ConnectionPool *cp, ConnectionPoolStat *stat)
|
||||||
{
|
{
|
||||||
int count;
|
ConnectionBucket *bucket;
|
||||||
count = 0;
|
ConnectionBucket *end;
|
||||||
fc_hash_walk(&cp->hash_array, _conn_count_walk, &count);
|
|
||||||
return count;
|
stat->htable_capacity = cp->hashtable.capacity;
|
||||||
|
stat->server_count = 0;
|
||||||
|
stat->connection.total_count = 0;
|
||||||
|
stat->connection.free_count = 0;
|
||||||
|
conn_pool_hash_walk(cp, cp_stat_walk_callback, stat);
|
||||||
|
|
||||||
|
stat->bucket_used = 0;
|
||||||
|
end = cp->hashtable.buckets + cp->hashtable.capacity;
|
||||||
|
for (bucket=cp->hashtable.buckets; bucket<end; bucket++)
|
||||||
|
{
|
||||||
|
if (bucket->head != NULL) {
|
||||||
|
stat->bucket_used++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int conn_pool_parse_server_info(const char *pServerStr,
|
int conn_pool_parse_server_info(const char *pServerStr,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int sock;
|
int sock;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
short af; //address family, AF_INET, AF_INET6 or AF_UNSPEC for auto dedect
|
uint8_t af; //address family, AF_INET, AF_INET6 or AF_UNSPEC for auto dedect
|
||||||
|
bool shared; //for connection pool
|
||||||
FCCommunicationType comm_type;
|
FCCommunicationType comm_type;
|
||||||
bool validate_flag; //for connection pool
|
bool validate_flag; //for connection pool
|
||||||
char ip_addr[IP_ADDRESS_SIZE];
|
char ip_addr[IP_ADDRESS_SIZE];
|
||||||
|
|
@ -151,12 +152,18 @@ typedef struct tagConnectionNode {
|
||||||
} ConnectionNode;
|
} ConnectionNode;
|
||||||
|
|
||||||
typedef struct tagConnectionManager {
|
typedef struct tagConnectionManager {
|
||||||
ConnectionNode *head;
|
string_t key;
|
||||||
int total_count; //total connections
|
ConnectionNode *head;
|
||||||
int free_count; //free connections
|
int total_count; //total connections
|
||||||
pthread_mutex_t lock;
|
int free_count; //free connections
|
||||||
|
struct tagConnectionManager *next;
|
||||||
} ConnectionManager;
|
} ConnectionManager;
|
||||||
|
|
||||||
|
typedef struct tagConnectionBucket {
|
||||||
|
ConnectionManager *head;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
} ConnectionBucket;
|
||||||
|
|
||||||
struct tagConnectionPool;
|
struct tagConnectionPool;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -165,8 +172,11 @@ typedef struct {
|
||||||
} ConnectionThreadHashTable;
|
} ConnectionThreadHashTable;
|
||||||
|
|
||||||
typedef struct tagConnectionPool {
|
typedef struct tagConnectionPool {
|
||||||
HashArray hash_array; //key is ip-port, value is ConnectionManager
|
struct {
|
||||||
pthread_mutex_t lock;
|
ConnectionBucket *buckets;
|
||||||
|
uint32_t capacity;
|
||||||
|
} hashtable;
|
||||||
|
|
||||||
int connect_timeout_ms;
|
int connect_timeout_ms;
|
||||||
int max_count_per_entry; //0 means no limit
|
int max_count_per_entry; //0 means no limit
|
||||||
|
|
||||||
|
|
@ -194,6 +204,16 @@ typedef struct tagConnectionPool {
|
||||||
pthread_key_t tls_key; //for ConnectionThreadHashTable
|
pthread_key_t tls_key; //for ConnectionThreadHashTable
|
||||||
} ConnectionPool;
|
} ConnectionPool;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int htable_capacity;
|
||||||
|
int bucket_used;
|
||||||
|
int server_count;
|
||||||
|
struct {
|
||||||
|
int total_count;
|
||||||
|
int free_count;
|
||||||
|
} connection;
|
||||||
|
} ConnectionPoolStat;
|
||||||
|
|
||||||
extern ConnectionCallbacks g_connection_callbacks;
|
extern ConnectionCallbacks g_connection_callbacks;
|
||||||
|
|
||||||
int conn_pool_global_init_for_rdma();
|
int conn_pool_global_init_for_rdma();
|
||||||
|
|
@ -209,7 +229,7 @@ int conn_pool_global_init_for_rdma();
|
||||||
* max_count_per_entry: max connection count per host:port
|
* max_count_per_entry: max connection count per host:port
|
||||||
* max_idle_time: reconnect the server after max idle time in seconds
|
* max_idle_time: reconnect the server after max idle time in seconds
|
||||||
* af: the socket domain
|
* af: the socket domain
|
||||||
* htable_init_capacity: the init capacity of connection hash table
|
* htable_capacity: the capacity of connection hash table
|
||||||
* connect_done_func: the connect done connection callback
|
* connect_done_func: the connect done connection callback
|
||||||
* connect_done_args: the args for connect done connection callback
|
* connect_done_args: the args for connect done connection callback
|
||||||
* validate_func: the validate connection callback
|
* validate_func: the validate connection callback
|
||||||
|
|
@ -218,12 +238,12 @@ int conn_pool_global_init_for_rdma();
|
||||||
* extra_params: for RDMA
|
* extra_params: for RDMA
|
||||||
* return 0 for success, != 0 for error
|
* return 0 for success, != 0 for error
|
||||||
*/
|
*/
|
||||||
int conn_pool_init_ex1(ConnectionPool *cp, int connect_timeout,
|
int conn_pool_init_ex1(ConnectionPool *cp, const int connect_timeout,
|
||||||
const int max_count_per_entry, const int max_idle_time,
|
const int max_count_per_entry, const int max_idle_time,
|
||||||
const int htable_init_capacity,
|
const int htable_capacity, fc_connection_callback_func connect_done_func,
|
||||||
fc_connection_callback_func connect_done_func, void *connect_done_args,
|
void *connect_done_args, fc_connection_callback_func validate_func,
|
||||||
fc_connection_callback_func validate_func, void *validate_args,
|
void *validate_args, const int extra_data_size,
|
||||||
const int extra_data_size, const ConnectionExtraParams *extra_params);
|
const ConnectionExtraParams *extra_params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init ex function
|
* init ex function
|
||||||
|
|
@ -234,14 +254,15 @@ int conn_pool_init_ex1(ConnectionPool *cp, int connect_timeout,
|
||||||
* max_idle_time: reconnect the server after max idle time in seconds
|
* max_idle_time: reconnect the server after max idle time in seconds
|
||||||
* return 0 for success, != 0 for error
|
* return 0 for success, != 0 for error
|
||||||
*/
|
*/
|
||||||
static inline int conn_pool_init_ex(ConnectionPool *cp, int connect_timeout,
|
static inline int conn_pool_init_ex(ConnectionPool *cp,
|
||||||
const int max_count_per_entry, const int max_idle_time)
|
const int connect_timeout, const int max_count_per_entry,
|
||||||
|
const int max_idle_time)
|
||||||
{
|
{
|
||||||
const int htable_init_capacity = 0;
|
const int htable_capacity = 0;
|
||||||
const int extra_data_size = 0;
|
const int extra_data_size = 0;
|
||||||
const ConnectionExtraParams *extra_params = NULL;
|
const ConnectionExtraParams *extra_params = NULL;
|
||||||
return conn_pool_init_ex1(cp, connect_timeout, max_count_per_entry,
|
return conn_pool_init_ex1(cp, connect_timeout, max_count_per_entry,
|
||||||
max_idle_time, htable_init_capacity, NULL, NULL, NULL, NULL,
|
max_idle_time, htable_capacity, NULL, NULL, NULL, NULL,
|
||||||
extra_data_size, extra_params);
|
extra_data_size, extra_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,14 +275,14 @@ static inline int conn_pool_init_ex(ConnectionPool *cp, int connect_timeout,
|
||||||
* max_idle_time: reconnect the server after max idle time in seconds
|
* max_idle_time: reconnect the server after max idle time in seconds
|
||||||
* return 0 for success, != 0 for error
|
* return 0 for success, != 0 for error
|
||||||
*/
|
*/
|
||||||
static inline int conn_pool_init(ConnectionPool *cp, int connect_timeout,
|
static inline int conn_pool_init(ConnectionPool *cp, const int connect_timeout,
|
||||||
const int max_count_per_entry, const int max_idle_time)
|
const int max_count_per_entry, const int max_idle_time)
|
||||||
{
|
{
|
||||||
const int htable_init_capacity = 0;
|
const int htable_capacity = 0;
|
||||||
const int extra_data_size = 0;
|
const int extra_data_size = 0;
|
||||||
const ConnectionExtraParams *extra_params = NULL;
|
const ConnectionExtraParams *extra_params = NULL;
|
||||||
return conn_pool_init_ex1(cp, connect_timeout, max_count_per_entry,
|
return conn_pool_init_ex1(cp, connect_timeout, max_count_per_entry,
|
||||||
max_idle_time, htable_init_capacity, NULL, NULL, NULL, NULL,
|
max_idle_time, htable_capacity, NULL, NULL, NULL, NULL,
|
||||||
extra_data_size, extra_params);
|
extra_data_size, extra_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,14 +300,16 @@ void conn_pool_destroy(ConnectionPool *cp);
|
||||||
* cp: the ConnectionPool
|
* cp: the ConnectionPool
|
||||||
* conn: the connection
|
* conn: the connection
|
||||||
* service_name: the service name to log
|
* service_name: the service name to log
|
||||||
|
* shared: if the connection shared
|
||||||
* err_no: return the the errno, 0 for success
|
* err_no: return the the errno, 0 for success
|
||||||
* return != NULL for success, NULL for error
|
* return != NULL for success, NULL for error
|
||||||
*/
|
*/
|
||||||
ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
|
||||||
const ConnectionInfo *conn, const char *service_name, int *err_no);
|
const ConnectionInfo *conn, const char *service_name,
|
||||||
|
const bool shared, int *err_no);
|
||||||
|
|
||||||
#define conn_pool_get_connection(cp, conn, err_no) \
|
#define conn_pool_get_connection(cp, conn, err_no) \
|
||||||
conn_pool_get_connection_ex(cp, conn, NULL, err_no)
|
conn_pool_get_connection_ex(cp, conn, NULL, false, err_no)
|
||||||
|
|
||||||
#define conn_pool_close_connection(cp, conn) \
|
#define conn_pool_close_connection(cp, conn) \
|
||||||
conn_pool_close_connection_ex(cp, conn, false)
|
conn_pool_close_connection_ex(cp, conn, false)
|
||||||
|
|
@ -308,9 +331,19 @@ int conn_pool_close_connection_ex(ConnectionPool *cp,
|
||||||
* conn: the connection
|
* conn: the connection
|
||||||
* return 0 for success, != 0 for error
|
* return 0 for success, != 0 for error
|
||||||
*/
|
*/
|
||||||
void conn_pool_disconnect_server(ConnectionInfo *conn);
|
static inline void conn_pool_disconnect_server(ConnectionInfo *conn)
|
||||||
|
{
|
||||||
|
if (conn->sock >= 0)
|
||||||
|
{
|
||||||
|
close(conn->sock);
|
||||||
|
conn->sock = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool conn_pool_is_connected(ConnectionInfo *conn);
|
static inline bool conn_pool_is_connected(ConnectionInfo *conn)
|
||||||
|
{
|
||||||
|
return (conn->sock >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* connect to the server
|
* connect to the server
|
||||||
|
|
@ -395,12 +428,13 @@ int conn_pool_async_connect_server_ex(ConnectionInfo *conn,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get connection count of the pool
|
* connection pool stat
|
||||||
* parameters:
|
* parameters:
|
||||||
* cp: the ConnectionPool
|
* cp: the ConnectionPool
|
||||||
* return current connection count
|
* stat: the output stat
|
||||||
|
* return none
|
||||||
*/
|
*/
|
||||||
int conn_pool_get_connection_count(ConnectionPool *cp);
|
void conn_pool_stat(ConnectionPool *cp, ConnectionPoolStat *stat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* load server info from config file
|
* load server info from config file
|
||||||
|
|
@ -438,8 +472,7 @@ int conn_pool_parse_server_info(const char *pServerStr,
|
||||||
static inline void conn_pool_set_server_info(ConnectionInfo *pServerInfo,
|
static inline void conn_pool_set_server_info(ConnectionInfo *pServerInfo,
|
||||||
const char *ip_addr, const int port)
|
const char *ip_addr, const int port)
|
||||||
{
|
{
|
||||||
snprintf(pServerInfo->ip_addr, sizeof(pServerInfo->ip_addr),
|
fc_safe_strcpy(pServerInfo->ip_addr, ip_addr);
|
||||||
"%s", ip_addr);
|
|
||||||
pServerInfo->port = port;
|
pServerInfo->port = port;
|
||||||
pServerInfo->af = is_ipv6_addr(ip_addr) ? AF_INET6 : AF_INET;
|
pServerInfo->af = is_ipv6_addr(ip_addr) ? AF_INET6 : AF_INET;
|
||||||
pServerInfo->sock = -1;
|
pServerInfo->sock = -1;
|
||||||
|
|
|
||||||
|
|
@ -26,23 +26,28 @@
|
||||||
#include "fc_memory.h"
|
#include "fc_memory.h"
|
||||||
#include "fast_buffer.h"
|
#include "fast_buffer.h"
|
||||||
|
|
||||||
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity)
|
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity,
|
||||||
|
const bool binary_mode, const bool check_capacity)
|
||||||
{
|
{
|
||||||
buffer->length = 0;
|
buffer->length = 0;
|
||||||
|
buffer->binary_mode = binary_mode;
|
||||||
if (init_capacity > 0)
|
if (init_capacity > 0)
|
||||||
{
|
{
|
||||||
buffer->alloc_size = init_capacity;
|
buffer->alloc_size = init_capacity;
|
||||||
|
buffer->check_capacity = check_capacity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer->alloc_size = 256;
|
buffer->alloc_size = 256;
|
||||||
|
buffer->check_capacity = true;
|
||||||
}
|
}
|
||||||
buffer->data = (char *)fc_malloc(buffer->alloc_size);
|
buffer->data = (char *)fc_malloc(buffer->alloc_size);
|
||||||
if (buffer->data == NULL)
|
if (buffer->data == NULL)
|
||||||
{
|
{
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
*(buffer->data) = '\0';
|
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +93,9 @@ int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity)
|
||||||
|
|
||||||
if (buffer->length > 0) {
|
if (buffer->length > 0) {
|
||||||
memcpy(buff, buffer->data, buffer->length);
|
memcpy(buff, buffer->data, buffer->length);
|
||||||
*(buff + buffer->length) = '\0';
|
if (!buffer->binary_mode) {
|
||||||
|
*(buff + buffer->length) = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer->data);
|
free(buffer->data);
|
||||||
|
|
@ -127,7 +134,7 @@ int fast_buffer_append(FastBuffer *buffer, const char *format, ...)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(buffer->data + buffer->length) = '\0'; //restore
|
fast_buffer_set_null_terminator(buffer); //restore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -148,7 +155,7 @@ int fast_buffer_append_buff(FastBuffer *buffer, const char *data, const int len)
|
||||||
|
|
||||||
memcpy(buffer->data + buffer->length, data, len);
|
memcpy(buffer->data + buffer->length, data, len);
|
||||||
buffer->length += len;
|
buffer->length += len;
|
||||||
*(buffer->data + buffer->length) = '\0';
|
fast_buffer_set_null_terminator(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,32 +178,6 @@ int fast_buffer_append_binary(FastBuffer *buffer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_buffer_append_int(FastBuffer *buffer, const int n)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if ((result=fast_buffer_check(buffer, 16)) != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->length += sprintf(buffer->data + buffer->length, "%d", n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fast_buffer_append_int64(FastBuffer *buffer, const int64_t n)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if ((result=fast_buffer_check(buffer, 32)) != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->length += sprintf(buffer->data + buffer->length, "%"PRId64, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
|
int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,14 @@
|
||||||
#define __FAST_BUFFER_H__
|
#define __FAST_BUFFER_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "common_define.h"
|
#include "shared_func.h"
|
||||||
|
|
||||||
typedef struct fast_buffer {
|
typedef struct fast_buffer {
|
||||||
char *data;
|
char *data;
|
||||||
int alloc_size;
|
int alloc_size;
|
||||||
int length;
|
int length;
|
||||||
|
bool binary_mode;
|
||||||
|
bool check_capacity;
|
||||||
} FastBuffer;
|
} FastBuffer;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -39,26 +41,39 @@ static inline char *fast_buffer_data(FastBuffer *buffer)
|
||||||
return buffer->data;
|
return buffer->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity);
|
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity,
|
||||||
|
const bool binary_mode, const bool check_capacity);
|
||||||
|
|
||||||
|
static inline int fast_buffer_init1(FastBuffer *buffer, const int init_capacity)
|
||||||
|
{
|
||||||
|
const bool binary_mode = false;
|
||||||
|
const bool check_capacity = true;
|
||||||
|
return fast_buffer_init_ex(buffer, init_capacity,
|
||||||
|
binary_mode, check_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int fast_buffer_init(FastBuffer *buffer)
|
static inline int fast_buffer_init(FastBuffer *buffer)
|
||||||
{
|
{
|
||||||
return fast_buffer_init_ex(buffer, 0);
|
const int init_capacity = 0;
|
||||||
|
return fast_buffer_init1(buffer, init_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define fast_buffer_set_null_terminator(buffer) \
|
||||||
|
if (!buffer->binary_mode) *(buffer->data + buffer->length) = '\0'
|
||||||
|
|
||||||
|
#define fast_buffer_check(buffer, inc_len) \
|
||||||
|
((buffer)->check_capacity ? fast_buffer_check_inc_size(buffer, inc_len) : 0)
|
||||||
|
|
||||||
#define fast_buffer_clear(buffer) fast_buffer_reset(buffer)
|
#define fast_buffer_clear(buffer) fast_buffer_reset(buffer)
|
||||||
|
|
||||||
static inline void fast_buffer_reset(FastBuffer *buffer)
|
static inline void fast_buffer_reset(FastBuffer *buffer)
|
||||||
{
|
{
|
||||||
buffer->length = 0;
|
buffer->length = 0;
|
||||||
*buffer->data = '\0';
|
fast_buffer_set_null_terminator(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fast_buffer_destroy(FastBuffer *buffer);
|
void fast_buffer_destroy(FastBuffer *buffer);
|
||||||
|
|
||||||
#define fast_buffer_check(buffer, inc_len) \
|
|
||||||
fast_buffer_check_inc_size(buffer, inc_len)
|
|
||||||
|
|
||||||
int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity);
|
int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity);
|
||||||
|
|
||||||
static inline int fast_buffer_check_capacity(FastBuffer *buffer,
|
static inline int fast_buffer_check_capacity(FastBuffer *buffer,
|
||||||
|
|
@ -86,9 +101,50 @@ int fast_buffer_append_buff(FastBuffer *buffer,
|
||||||
int fast_buffer_append_binary(FastBuffer *buffer,
|
int fast_buffer_append_binary(FastBuffer *buffer,
|
||||||
const void *data, const int len);
|
const void *data, const int len);
|
||||||
|
|
||||||
int fast_buffer_append_int(FastBuffer *buffer, const int n);
|
static inline int fast_buffer_append_char(FastBuffer *buffer, const char ch)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
int fast_buffer_append_int64(FastBuffer *buffer, const int64_t n);
|
if ((result=fast_buffer_check(buffer, 1)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(buffer->data + buffer->length++) = ch;
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fast_buffer_append_int32(FastBuffer *buffer, const int n)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result=fast_buffer_check(buffer, 16)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->length += fc_itoa(n, buffer->data + buffer->length);
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fast_buffer_append_int64(FastBuffer *buffer, const int64_t n)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result=fast_buffer_check(buffer, 32)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->length += fc_itoa(n, buffer->data + buffer->length);
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fast_buffer_append_int(buffer, n) \
|
||||||
|
fast_buffer_append_int64(buffer, n)
|
||||||
|
|
||||||
int fast_buffer_append_file(FastBuffer *buffer, const char *filename);
|
int fast_buffer_append_file(FastBuffer *buffer, const char *filename);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -477,8 +477,8 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
((struct fast_mblock_node *)pLast)->next = mblock->free_chain_head;
|
((struct fast_mblock_node *)pLast)->next = mblock->freelist.head;
|
||||||
mblock->free_chain_head = (struct fast_mblock_node *)pTrunkStart;
|
mblock->freelist.head = (struct fast_mblock_node *)pTrunkStart;
|
||||||
|
|
||||||
pMallocNode->ref_count = 0;
|
pMallocNode->ref_count = 0;
|
||||||
pMallocNode->alloc_count = alloc_count;
|
pMallocNode->alloc_count = alloc_count;
|
||||||
|
|
@ -558,7 +558,7 @@ int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
|
||||||
mblock->info.trunk_total_count = 0;
|
mblock->info.trunk_total_count = 0;
|
||||||
mblock->info.trunk_used_count = 0;
|
mblock->info.trunk_used_count = 0;
|
||||||
mblock->info.delay_free_elements = 0;
|
mblock->info.delay_free_elements = 0;
|
||||||
mblock->free_chain_head = NULL;
|
mblock->freelist.head = NULL;
|
||||||
mblock->delay_free_chain.head = NULL;
|
mblock->delay_free_chain.head = NULL;
|
||||||
mblock->delay_free_chain.tail = NULL;
|
mblock->delay_free_chain.tail = NULL;
|
||||||
mblock->info.element_total_count = 0;
|
mblock->info.element_total_count = 0;
|
||||||
|
|
@ -584,7 +584,7 @@ int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
{
|
{
|
||||||
snprintf(mblock->info.name, sizeof(mblock->info.name), "%s", name);
|
fc_safe_strcpy(mblock->info.name, name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -714,7 +714,7 @@ void fast_mblock_destroy(struct fast_mblock_man *mblock)
|
||||||
INIT_HEAD(&mblock->trunks.head);
|
INIT_HEAD(&mblock->trunks.head);
|
||||||
mblock->info.trunk_total_count = 0;
|
mblock->info.trunk_total_count = 0;
|
||||||
mblock->info.trunk_used_count = 0;
|
mblock->info.trunk_used_count = 0;
|
||||||
mblock->free_chain_head = NULL;
|
mblock->freelist.head = NULL;
|
||||||
mblock->info.element_used_count = 0;
|
mblock->info.element_used_count = 0;
|
||||||
mblock->info.delay_free_elements = 0;
|
mblock->info.delay_free_elements = 0;
|
||||||
mblock->info.element_total_count = 0;
|
mblock->info.element_total_count = 0;
|
||||||
|
|
@ -732,10 +732,10 @@ static inline struct fast_mblock_node *alloc_node(
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (mblock->free_chain_head != NULL)
|
if (mblock->freelist.head != NULL)
|
||||||
{
|
{
|
||||||
pNode = mblock->free_chain_head;
|
pNode = mblock->freelist.head;
|
||||||
mblock->free_chain_head = pNode->next;
|
mblock->freelist.head = pNode->next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -757,8 +757,8 @@ static inline struct fast_mblock_node *alloc_node(
|
||||||
|
|
||||||
if ((result=fast_mblock_prealloc(mblock)) == 0)
|
if ((result=fast_mblock_prealloc(mblock)) == 0)
|
||||||
{
|
{
|
||||||
pNode = mblock->free_chain_head;
|
pNode = mblock->freelist.head;
|
||||||
mblock->free_chain_head = pNode->next;
|
mblock->freelist.head = pNode->next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -829,9 +829,9 @@ int fast_mblock_free(struct fast_mblock_man *mblock,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify = (mblock->free_chain_head == NULL);
|
notify = (mblock->freelist.head == NULL);
|
||||||
pNode->next = mblock->free_chain_head;
|
pNode->next = mblock->freelist.head;
|
||||||
mblock->free_chain_head = pNode;
|
mblock->freelist.head = pNode;
|
||||||
fast_mblock_ref_counter_dec(mblock, pNode);
|
fast_mblock_ref_counter_dec(mblock, pNode);
|
||||||
|
|
||||||
if (mblock->alloc_elements.need_wait && notify)
|
if (mblock->alloc_elements.need_wait && notify)
|
||||||
|
|
@ -855,18 +855,21 @@ static inline void batch_free(struct fast_mblock_man *mblock,
|
||||||
struct fast_mblock_chain *chain)
|
struct fast_mblock_chain *chain)
|
||||||
{
|
{
|
||||||
bool notify;
|
bool notify;
|
||||||
|
int count;
|
||||||
struct fast_mblock_node *pNode;
|
struct fast_mblock_node *pNode;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
pNode = chain->head;
|
pNode = chain->head;
|
||||||
while (pNode != NULL)
|
while (pNode != NULL)
|
||||||
{
|
{
|
||||||
|
++count;
|
||||||
fast_mblock_ref_counter_dec(mblock, pNode);
|
fast_mblock_ref_counter_dec(mblock, pNode);
|
||||||
pNode = pNode->next;
|
pNode = pNode->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify = (mblock->free_chain_head == NULL);
|
notify = (mblock->freelist.head == NULL);
|
||||||
chain->tail->next = mblock->free_chain_head;
|
chain->tail->next = mblock->freelist.head;
|
||||||
mblock->free_chain_head = chain->head;
|
mblock->freelist.head = chain->head;
|
||||||
if (mblock->alloc_elements.need_wait && notify)
|
if (mblock->alloc_elements.need_wait && notify)
|
||||||
{
|
{
|
||||||
pthread_cond_broadcast(&mblock->lcp.cond);
|
pthread_cond_broadcast(&mblock->lcp.cond);
|
||||||
|
|
@ -1066,7 +1069,7 @@ static int fast_mblock_chain_count(struct fast_mblock_man *mblock,
|
||||||
|
|
||||||
int fast_mblock_free_count(struct fast_mblock_man *mblock)
|
int fast_mblock_free_count(struct fast_mblock_man *mblock)
|
||||||
{
|
{
|
||||||
return fast_mblock_chain_count(mblock, mblock->free_chain_head);
|
return fast_mblock_chain_count(mblock, mblock->freelist.head);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_mblock_delay_free_count(struct fast_mblock_man *mblock)
|
int fast_mblock_delay_free_count(struct fast_mblock_man *mblock)
|
||||||
|
|
@ -1088,8 +1091,8 @@ static int fast_mblock_do_reclaim(struct fast_mblock_man *mblock,
|
||||||
*reclaim_count = 0;
|
*reclaim_count = 0;
|
||||||
freelist = NULL;
|
freelist = NULL;
|
||||||
free_chain_prev = NULL;
|
free_chain_prev = NULL;
|
||||||
current = mblock->free_chain_head;
|
current = mblock->freelist.head;
|
||||||
mblock->free_chain_head = NULL;
|
mblock->freelist.head = NULL;
|
||||||
while (current != NULL)
|
while (current != NULL)
|
||||||
{
|
{
|
||||||
malloc_node = FAST_MBLOCK_GET_TRUNK(current);
|
malloc_node = FAST_MBLOCK_GET_TRUNK(current);
|
||||||
|
|
@ -1103,7 +1106,7 @@ static int fast_mblock_do_reclaim(struct fast_mblock_man *mblock,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mblock->free_chain_head = current;
|
mblock->freelist.head = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_chain_prev = current;
|
free_chain_prev = current;
|
||||||
|
|
@ -1160,7 +1163,6 @@ OUTER:
|
||||||
free_chain_prev->next = NULL;
|
free_chain_prev->next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
bool old_need_lock;
|
bool old_need_lock;
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,11 @@ struct fast_mblock_man
|
||||||
int64_t limit; //<= 0 for no limit
|
int64_t limit; //<= 0 for no limit
|
||||||
bool *pcontinue_flag;
|
bool *pcontinue_flag;
|
||||||
} alloc_elements;
|
} alloc_elements;
|
||||||
struct fast_mblock_node *free_chain_head; //free node chain
|
|
||||||
|
struct {
|
||||||
|
struct fast_mblock_node *head;
|
||||||
|
} freelist; //free node chain
|
||||||
|
|
||||||
struct fast_mblock_trunks trunks;
|
struct fast_mblock_trunks trunks;
|
||||||
struct fast_mblock_chain delay_free_chain; //delay free node chain
|
struct fast_mblock_chain delay_free_chain; //delay free node chain
|
||||||
|
|
||||||
|
|
@ -407,7 +411,7 @@ return the delay free node count of the mblock, return -1 if fail
|
||||||
*/
|
*/
|
||||||
int fast_mblock_delay_free_count(struct fast_mblock_man *mblock);
|
int fast_mblock_delay_free_count(struct fast_mblock_man *mblock);
|
||||||
|
|
||||||
#define fast_mblock_total_count(mblock) (mblock)->total_count
|
#define fast_mblock_total_count(mblock) (mblock)->info.element_total_count
|
||||||
|
|
||||||
/**
|
/**
|
||||||
init mblock manager
|
init mblock manager
|
||||||
|
|
|
||||||
|
|
@ -53,16 +53,17 @@ static int task_alloc_init(struct fast_task_info *task,
|
||||||
|
|
||||||
task->free_queue = queue;
|
task->free_queue = queue;
|
||||||
if (queue->init_callback != NULL) {
|
if (queue->init_callback != NULL) {
|
||||||
return queue->init_callback(task);
|
return queue->init_callback(task, queue->init_arg);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
|
int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
|
||||||
const bool double_buffers, const int max_connections,
|
const bool double_buffers, const bool need_shrink,
|
||||||
const int alloc_task_once, const int min_buff_size,
|
const int max_connections, const int alloc_task_once,
|
||||||
const int max_buff_size, const int padding_size,
|
const int min_buff_size, const int max_buff_size,
|
||||||
const int arg_size, TaskInitCallback init_callback)
|
const int padding_size, const int arg_size,
|
||||||
|
TaskInitCallback init_callback, void *init_arg)
|
||||||
{
|
{
|
||||||
#define MAX_DATA_SIZE (256 * 1024 * 1024)
|
#define MAX_DATA_SIZE (256 * 1024 * 1024)
|
||||||
int alloc_once;
|
int alloc_once;
|
||||||
|
|
@ -122,11 +123,13 @@ int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
queue->double_buffers = double_buffers;
|
queue->double_buffers = double_buffers;
|
||||||
|
queue->need_shrink = need_shrink;
|
||||||
queue->min_buff_size = aligned_min_size;
|
queue->min_buff_size = aligned_min_size;
|
||||||
queue->max_buff_size = aligned_max_size;
|
queue->max_buff_size = aligned_max_size;
|
||||||
queue->padding_size = aligned_padding_size;
|
queue->padding_size = aligned_padding_size;
|
||||||
queue->arg_size = aligned_arg_size;
|
queue->arg_size = aligned_arg_size;
|
||||||
queue->init_callback = init_callback;
|
queue->init_callback = init_callback;
|
||||||
|
queue->init_arg = init_arg;
|
||||||
queue->release_callback = NULL;
|
queue->release_callback = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -140,7 +143,7 @@ int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
|
||||||
(int64_t)max_data_size);
|
(int64_t)max_data_size);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
snprintf(aname, sizeof(aname), "%s-task", name);
|
fc_combine_two_strings(name, "task", '-', aname);
|
||||||
return fast_mblock_init_ex1(&queue->allocator, aname,
|
return fast_mblock_init_ex1(&queue->allocator, aname,
|
||||||
queue->block_size, alloc_once, max_connections,
|
queue->block_size, alloc_once, max_connections,
|
||||||
(fast_mblock_object_init_func)task_alloc_init,
|
(fast_mblock_object_init_func)task_alloc_init,
|
||||||
|
|
@ -181,16 +184,23 @@ void free_queue_push(struct fast_task_info *task)
|
||||||
task->send.ptr->length = 0;
|
task->send.ptr->length = 0;
|
||||||
task->send.ptr->offset = 0;
|
task->send.ptr->offset = 0;
|
||||||
task->req_count = 0;
|
task->req_count = 0;
|
||||||
if (task->send.ptr->size > task->free_queue->min_buff_size) {//need thrink
|
if (task->free_queue->need_shrink && task->send.
|
||||||
_realloc_buffer(task->send.ptr, task->free_queue->min_buff_size, false);
|
ptr->size > task->free_queue->min_buff_size)
|
||||||
|
{ //need thrink
|
||||||
|
_realloc_buffer(task->send.ptr, task->free_queue->
|
||||||
|
min_buff_size, false);
|
||||||
|
task->shrinked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->free_queue->double_buffers) {
|
if (task->free_queue->double_buffers) {
|
||||||
task->recv.ptr->length = 0;
|
task->recv.ptr->length = 0;
|
||||||
task->recv.ptr->offset = 0;
|
task->recv.ptr->offset = 0;
|
||||||
if (task->recv.ptr->size > task->free_queue->min_buff_size) {
|
if (task->free_queue->need_shrink && task->recv.
|
||||||
|
ptr->size > task->free_queue->min_buff_size)
|
||||||
|
{
|
||||||
_realloc_buffer(task->recv.ptr, task->free_queue->
|
_realloc_buffer(task->recv.ptr, task->free_queue->
|
||||||
min_buff_size, false);
|
min_buff_size, false);
|
||||||
|
task->shrinked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,21 +37,27 @@ struct nio_thread_data;
|
||||||
struct fast_task_info;
|
struct fast_task_info;
|
||||||
|
|
||||||
typedef int (*ThreadLoopCallback) (struct nio_thread_data *pThreadData);
|
typedef int (*ThreadLoopCallback) (struct nio_thread_data *pThreadData);
|
||||||
typedef int (*TaskFinishCallback) (struct fast_task_info *task);
|
|
||||||
typedef void (*TaskCleanUpCallback) (struct fast_task_info *task);
|
typedef void (*TaskCleanUpCallback) (struct fast_task_info *task);
|
||||||
typedef int (*TaskInitCallback)(struct fast_task_info *task);
|
typedef int (*TaskInitCallback)(struct fast_task_info *task, void *arg);
|
||||||
typedef void (*TaskReleaseCallback)(struct fast_task_info *task);
|
typedef void (*TaskReleaseCallback)(struct fast_task_info *task);
|
||||||
|
|
||||||
typedef void (*IOEventCallback) (int sock, short event, void *arg);
|
typedef void (*IOEventCallback) (int sock, const int event, void *arg);
|
||||||
typedef int (*TaskContinueCallback)(struct fast_task_info *task);
|
typedef int (*TaskContinueCallback)(struct fast_task_info *task);
|
||||||
|
|
||||||
struct sf_network_handler;
|
struct sf_network_handler;
|
||||||
struct fast_task_info;
|
struct fast_task_info;
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
#define FC_URING_OP_TYPE(task) (task)->uring.op_type
|
||||||
|
#define FC_URING_IS_CLIENT(task) (task)->uring.is_client
|
||||||
|
#define FC_URING_IS_SEND_ZC(task) ((task)->uring.op_type == IORING_OP_SEND_ZC)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct ioevent_entry
|
typedef struct ioevent_entry
|
||||||
{
|
{
|
||||||
FastTimerEntry timer; //must first
|
FastTimerEntry timer; //must first
|
||||||
int fd;
|
int fd;
|
||||||
|
int res; //just for io_uring, since v1.0.81
|
||||||
IOEventCallback callback;
|
IOEventCallback callback;
|
||||||
} IOEventEntry;
|
} IOEventEntry;
|
||||||
|
|
||||||
|
|
@ -119,12 +125,19 @@ struct fast_task_info
|
||||||
struct fast_net_buffer_wrapper recv; //recv buffer
|
struct fast_net_buffer_wrapper recv; //recv buffer
|
||||||
|
|
||||||
uint16_t port; //peer port
|
uint16_t port; //peer port
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int8_t is_client;
|
||||||
|
uint8_t op_type;
|
||||||
|
} uring; //just for io_uring, since v1.0.81
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t current;
|
uint8_t current;
|
||||||
volatile uint8_t notify;
|
volatile uint8_t notify;
|
||||||
} nio_stages; //stages for network IO
|
} nio_stages; //stages for network IO
|
||||||
volatile int8_t reffer_count;
|
|
||||||
volatile int8_t canceled; //if task canceled
|
volatile int8_t canceled; //if task canceled
|
||||||
|
volatile int8_t shrinked; //if task shrinked, since V1.0.81
|
||||||
|
volatile int reffer_count;
|
||||||
int pending_send_count;
|
int pending_send_count;
|
||||||
int64_t req_count; //request count
|
int64_t req_count; //request count
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -135,7 +148,6 @@ struct fast_task_info
|
||||||
struct fc_list_head dlink; //for polling queue
|
struct fc_list_head dlink; //for polling queue
|
||||||
} polling; //for RDMA busy polling
|
} polling; //for RDMA busy polling
|
||||||
TaskContinueCallback continue_callback; //for continue stage
|
TaskContinueCallback continue_callback; //for continue stage
|
||||||
TaskFinishCallback finish_callback;
|
|
||||||
struct nio_thread_data *thread_data;
|
struct nio_thread_data *thread_data;
|
||||||
struct sf_network_handler *handler; //network handler for libserverframe nio
|
struct sf_network_handler *handler; //network handler for libserverframe nio
|
||||||
struct fast_task_info *next; //for free queue and deleted list
|
struct fast_task_info *next; //for free queue and deleted list
|
||||||
|
|
@ -153,8 +165,10 @@ struct fast_task_queue
|
||||||
int block_size;
|
int block_size;
|
||||||
bool malloc_whole_block;
|
bool malloc_whole_block;
|
||||||
bool double_buffers; //if send buffer and recv buffer are independent
|
bool double_buffers; //if send buffer and recv buffer are independent
|
||||||
|
bool need_shrink;
|
||||||
struct fast_mblock_man allocator;
|
struct fast_mblock_man allocator;
|
||||||
TaskInitCallback init_callback;
|
TaskInitCallback init_callback;
|
||||||
|
void *init_arg;
|
||||||
TaskReleaseCallback release_callback;
|
TaskReleaseCallback release_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -163,21 +177,22 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
|
int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
|
||||||
const bool double_buffers, const int max_connections,
|
const bool double_buffers, const bool need_shrink,
|
||||||
const int alloc_task_once, const int min_buff_size,
|
const int max_connections, const int alloc_task_once,
|
||||||
const int max_buff_size, const int padding_size,
|
const int min_buff_size, const int max_buff_size,
|
||||||
const int arg_size, TaskInitCallback init_callback);
|
const int padding_size, const int arg_size,
|
||||||
|
TaskInitCallback init_callback, void *init_arg);
|
||||||
|
|
||||||
static inline int free_queue_init_ex(struct fast_task_queue *queue,
|
static inline int free_queue_init_ex(struct fast_task_queue *queue,
|
||||||
const char *name, const bool double_buffers,
|
const char *name, const bool double_buffers,
|
||||||
const int max_connections, const int alloc_task_once,
|
const bool need_shrink, const int max_connections,
|
||||||
const int min_buff_size, const int max_buff_size,
|
const int alloc_task_once, const int min_buff_size,
|
||||||
const int arg_size)
|
const int max_buff_size, const int arg_size)
|
||||||
{
|
{
|
||||||
const int padding_size = 0;
|
const int padding_size = 0;
|
||||||
return free_queue_init_ex2(queue, name, double_buffers, max_connections,
|
return free_queue_init_ex2(queue, name, double_buffers, need_shrink,
|
||||||
alloc_task_once, min_buff_size, max_buff_size, padding_size,
|
max_connections, alloc_task_once, min_buff_size, max_buff_size,
|
||||||
arg_size, NULL);
|
padding_size, arg_size, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int free_queue_init(struct fast_task_queue *queue,
|
static inline int free_queue_init(struct fast_task_queue *queue,
|
||||||
|
|
@ -186,9 +201,11 @@ static inline int free_queue_init(struct fast_task_queue *queue,
|
||||||
{
|
{
|
||||||
const char *name = "";
|
const char *name = "";
|
||||||
const bool double_buffers = false;
|
const bool double_buffers = false;
|
||||||
|
const bool need_shrink = true;
|
||||||
const int arg_size = 0;
|
const int arg_size = 0;
|
||||||
return free_queue_init_ex(queue, name, double_buffers, max_connections,
|
return free_queue_init_ex(queue, name, double_buffers,
|
||||||
alloc_task_once, min_buff_size, max_buff_size, arg_size);
|
need_shrink, max_connections, alloc_task_once,
|
||||||
|
min_buff_size, max_buff_size, arg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void free_queue_set_release_callback(
|
static inline void free_queue_set_release_callback(
|
||||||
|
|
@ -203,7 +220,7 @@ void free_queue_destroy(struct fast_task_queue *queue);
|
||||||
static inline struct fast_task_info *free_queue_pop(
|
static inline struct fast_task_info *free_queue_pop(
|
||||||
struct fast_task_queue *queue)
|
struct fast_task_queue *queue)
|
||||||
{
|
{
|
||||||
return fast_mblock_alloc_object(&queue->allocator);
|
return (struct fast_task_info *)fast_mblock_alloc_object(&queue->allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_queue_push(struct fast_task_info *task);
|
void free_queue_push(struct fast_task_info *task);
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ int fast_timer_modify(FastTimer *timer, FastTimerEntry *entry,
|
||||||
if ((result=fast_timer_remove(timer, entry)) == 0) {
|
if ((result=fast_timer_remove(timer, entry)) == 0) {
|
||||||
fast_timer_add_ex(timer, entry, new_expires, true);
|
fast_timer_add_ex(timer, entry, new_expires, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -185,6 +186,7 @@ int fast_timer_timeouts_get(FastTimer *timer, const int64_t current_time,
|
||||||
} else {
|
} else {
|
||||||
last->rehash = false;
|
last->rehash = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else { //expired
|
} else { //expired
|
||||||
|
|
|
||||||
11
src/hash.c
11
src/hash.c
|
|
@ -768,23 +768,22 @@ int64_t fc_hash_inc_value(const HashData *old_data, const int inc,
|
||||||
{
|
{
|
||||||
if (old_data->value_len < *new_value_len)
|
if (old_data->value_len < *new_value_len)
|
||||||
{
|
{
|
||||||
memcpy(new_value, old_data->value, old_data->value_len);
|
memcpy(new_value, old_data->value, old_data->value_len);
|
||||||
new_value[old_data->value_len] = '\0';
|
new_value[old_data->value_len] = '\0';
|
||||||
n = strtoll(new_value, NULL, 10);
|
n = strtoll(new_value, NULL, 10);
|
||||||
n += inc;
|
n += inc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
n = inc;
|
n = inc;
|
||||||
}
|
}
|
||||||
*new_value_len = sprintf(new_value, "%"PRId64, n);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
n = inc;
|
n = inc;
|
||||||
*new_value_len = sprintf(new_value, "%"PRId64, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*new_value_len = fc_itoa(n, new_value);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ static int iniAnnotationFuncLocalIpGet(IniContext *context,
|
||||||
(int)(square_start - param), param);
|
(int)(square_start - param), param);
|
||||||
index = atoi(square_start + 1);
|
index = atoi(square_start + 1);
|
||||||
} else {
|
} else {
|
||||||
snprintf(name_part, sizeof(name_part) - 1, "%s", param);
|
fc_safe_strcpy(name_part, param);
|
||||||
index = -2;
|
index = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -322,7 +322,7 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"NO set directives before, set value to %s",
|
"NO set directives before, set value to %s",
|
||||||
__LINE__, param);
|
__LINE__, param);
|
||||||
snprintf(output, FAST_INI_ITEM_VALUE_SIZE, "%s", param);
|
fc_strlcpy(output, param, FAST_INI_ITEM_VALUE_SIZE);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -652,7 +652,7 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
|
||||||
if (IS_URL_RESOURCE(szFilename))
|
if (IS_URL_RESOURCE(szFilename))
|
||||||
{
|
{
|
||||||
*pContext->config_path = '\0';
|
*pContext->config_path = '\0';
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s", szFilename);
|
fc_safe_strcpy(full_filename, szFilename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -675,8 +675,7 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
|
||||||
|
|
||||||
memcpy(pContext->config_path, szFilename, len);
|
memcpy(pContext->config_path, szFilename, len);
|
||||||
*(pContext->config_path + len) = '\0';
|
*(pContext->config_path + len) = '\0';
|
||||||
snprintf(full_filename, sizeof(full_filename), \
|
fc_safe_strcpy(full_filename, szFilename);
|
||||||
"%s", szFilename);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -699,9 +698,8 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
|
||||||
*(pContext->config_path + len) = '\0';
|
*(pContext->config_path + len) = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(full_filename, sizeof(full_filename), \
|
fc_combine_full_filename(pContext->config_path,
|
||||||
"%s/%s", pContext->config_path, szFilename);
|
szFilename, full_filename);
|
||||||
|
|
||||||
pLast = strrchr(szFilename, '/');
|
pLast = strrchr(szFilename, '/');
|
||||||
if (pLast != NULL)
|
if (pLast != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -914,7 +912,7 @@ static int iniAddAnnotation(char *params)
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(symbol, sizeof(symbol), "%s_init_annotation", func_name);
|
fc_combine_two_strings(func_name, "init_annotation", '_', symbol);
|
||||||
init_func = dlsym(dlhandle, symbol);
|
init_func = dlsym(dlhandle, symbol);
|
||||||
if (init_func == NULL)
|
if (init_func == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1013,14 +1011,12 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
|
||||||
strncasecmp(pLine+1, "include", 7) == 0 && \
|
strncasecmp(pLine+1, "include", 7) == 0 && \
|
||||||
(*(pLine+8) == ' ' || *(pLine+8) == '\t'))
|
(*(pLine+8) == ' ' || *(pLine+8) == '\t'))
|
||||||
{
|
{
|
||||||
snprintf(pIncludeFilename, sizeof(pIncludeFilename),
|
fc_safe_strcpy(pIncludeFilename, pLine + 9);
|
||||||
"%s", pLine + 9);
|
|
||||||
fc_trim(pIncludeFilename);
|
fc_trim(pIncludeFilename);
|
||||||
if (IS_URL_RESOURCE(pIncludeFilename))
|
if (IS_URL_RESOURCE(pIncludeFilename))
|
||||||
{
|
{
|
||||||
snprintf(full_filename, sizeof(full_filename),
|
fc_safe_strcpy(full_filename, pIncludeFilename);
|
||||||
"%s", pIncludeFilename);
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IS_FILE_RESOURCE(pIncludeFilename))
|
if (IS_FILE_RESOURCE(pIncludeFilename))
|
||||||
|
|
@ -1034,25 +1030,23 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
|
||||||
|
|
||||||
if (*pTrueFilename == '/')
|
if (*pTrueFilename == '/')
|
||||||
{
|
{
|
||||||
snprintf(full_filename, sizeof(full_filename), \
|
fc_safe_strcpy(full_filename, pTrueFilename);
|
||||||
"%s", pTrueFilename);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(full_filename, sizeof(full_filename), \
|
fc_combine_full_filename(pContext->config_path,
|
||||||
"%s/%s", pContext->config_path, \
|
pTrueFilename, full_filename);
|
||||||
pTrueFilename);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!fileExists(full_filename))
|
if (!fileExists(full_filename))
|
||||||
{
|
{
|
||||||
logError("file: "__FILE__", line: %d, " \
|
logError("file: "__FILE__", line: %d, "
|
||||||
"include file \"%s\" not exists, " \
|
"include file \"%s\" not exists, "
|
||||||
"line: \"%s\"", __LINE__, \
|
"line: \"%s\"", __LINE__,
|
||||||
pTrueFilename, pLine);
|
pTrueFilename, pLine);
|
||||||
result = ENOENT;
|
result = ENOENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pContext->current_section = &pContext->global;
|
pContext->current_section = &pContext->global;
|
||||||
|
|
@ -2629,8 +2623,7 @@ static char *iniProccessFor(char *content, const int content_len,
|
||||||
char *pRemain;
|
char *pRemain;
|
||||||
int remainLen;
|
int remainLen;
|
||||||
|
|
||||||
valueLen = sprintf(value, "%d", i);
|
valueLen = fc_itoa(i, value);
|
||||||
|
|
||||||
pRemain = pForBlock;
|
pRemain = pForBlock;
|
||||||
remainLen = forBlockLen;
|
remainLen = forBlockLen;
|
||||||
while (remainLen >= tagLen)
|
while (remainLen >= tagLen)
|
||||||
|
|
@ -2817,7 +2810,7 @@ do { \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
snprintf(targetItem.name, sizeof(targetItem.name), "%s", szItemName); \
|
fc_safe_strcpy(targetItem.name, szItemName); \
|
||||||
pItem = (IniItem *)bsearch(&targetItem, pSection->items, \
|
pItem = (IniItem *)bsearch(&targetItem, pSection->items, \
|
||||||
pSection->count, sizeof(IniItem), iniCompareByItemName); \
|
pSection->count, sizeof(IniItem), iniCompareByItemName); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
||||||
227
src/ioevent.c
227
src/ioevent.c
|
|
@ -45,71 +45,119 @@ int kqueue_ev_convert(int16_t event, uint16_t flags)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ioevent_init(IOEventPoller *ioevent, const int size,
|
int ioevent_init(IOEventPoller *ioevent, const char *service_name,
|
||||||
const int timeout_ms, const int extra_events)
|
const bool use_io_uring, const int size, const int timeout_ms,
|
||||||
|
const int extra_events)
|
||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
|
|
||||||
ioevent->size = size;
|
ioevent->iterator.index = 0;
|
||||||
ioevent->extra_events = extra_events;
|
ioevent->iterator.count = 0;
|
||||||
ioevent->iterator.index = 0;
|
ioevent->service_name = service_name;
|
||||||
ioevent->iterator.count = 0;
|
ioevent->size = size;
|
||||||
|
ioevent->extra_events = extra_events;
|
||||||
|
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
ioevent->poll_fd = epoll_create(ioevent->size);
|
#if IOEVENT_USE_URING
|
||||||
if (ioevent->poll_fd < 0) {
|
ioevent->use_io_uring = use_io_uring;
|
||||||
return errno != 0 ? errno : ENOMEM;
|
if (use_io_uring) {
|
||||||
}
|
int result;
|
||||||
bytes = sizeof(struct epoll_event) * size;
|
if ((result=io_uring_queue_init(size, &ioevent->ring, 0)) < 0) {
|
||||||
ioevent->events = (struct epoll_event *)fc_malloc(bytes);
|
return -result;
|
||||||
|
}
|
||||||
|
ioevent->cqe = NULL;
|
||||||
|
ioevent->submit_count = 0;
|
||||||
|
ioevent->send_zc_logged = false;
|
||||||
|
ioevent->send_zc_done_notify = false;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
ioevent->poll_fd = epoll_create(ioevent->size);
|
||||||
|
if (ioevent->poll_fd < 0) {
|
||||||
|
return errno != 0 ? errno : ENOMEM;
|
||||||
|
}
|
||||||
|
bytes = sizeof(struct epoll_event) * size;
|
||||||
|
ioevent->events = (struct epoll_event *)fc_malloc(bytes);
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
ioevent->poll_fd = kqueue();
|
ioevent->poll_fd = kqueue();
|
||||||
if (ioevent->poll_fd < 0) {
|
if (ioevent->poll_fd < 0) {
|
||||||
return errno != 0 ? errno : ENOMEM;
|
return errno != 0 ? errno : ENOMEM;
|
||||||
}
|
}
|
||||||
bytes = sizeof(struct kevent) * size;
|
bytes = sizeof(struct kevent) * size;
|
||||||
ioevent->events = (struct kevent *)fc_malloc(bytes);
|
ioevent->events = (struct kevent *)fc_malloc(bytes);
|
||||||
#elif IOEVENT_USE_PORT
|
#elif IOEVENT_USE_PORT
|
||||||
ioevent->poll_fd = port_create();
|
ioevent->poll_fd = port_create();
|
||||||
if (ioevent->poll_fd < 0) {
|
if (ioevent->poll_fd < 0) {
|
||||||
return errno != 0 ? errno : ENOMEM;
|
return errno != 0 ? errno : ENOMEM;
|
||||||
}
|
}
|
||||||
bytes = sizeof(port_event_t) * size;
|
bytes = sizeof(port_event_t) * size;
|
||||||
ioevent->events = (port_event_t *)fc_malloc(bytes);
|
ioevent->events = (port_event_t *)fc_malloc(bytes);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ioevent->events == NULL) {
|
#if IOEVENT_USE_URING
|
||||||
close(ioevent->poll_fd);
|
if (!ioevent->use_io_uring) {
|
||||||
ioevent->poll_fd = -1;
|
#endif
|
||||||
return ENOMEM;
|
if (ioevent->events == NULL) {
|
||||||
}
|
close(ioevent->poll_fd);
|
||||||
ioevent_set_timeout(ioevent, timeout_ms);
|
ioevent->poll_fd = -1;
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
ioevent_set_timeout(ioevent, timeout_ms);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ioevent_destroy(IOEventPoller *ioevent)
|
void ioevent_destroy(IOEventPoller *ioevent)
|
||||||
{
|
{
|
||||||
if (ioevent->events != NULL) {
|
#if IOEVENT_USE_URING
|
||||||
free(ioevent->events);
|
if (ioevent->use_io_uring) {
|
||||||
ioevent->events = NULL;
|
io_uring_queue_exit(&ioevent->ring);
|
||||||
}
|
} else {
|
||||||
|
#endif
|
||||||
|
if (ioevent->events != NULL) {
|
||||||
|
free(ioevent->events);
|
||||||
|
ioevent->events = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ioevent->poll_fd >= 0) {
|
if (ioevent->poll_fd >= 0) {
|
||||||
close(ioevent->poll_fd);
|
close(ioevent->poll_fd);
|
||||||
ioevent->poll_fd = -1;
|
ioevent->poll_fd = -1;
|
||||||
}
|
}
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ioevent_attach(IOEventPoller *ioevent, const int fd, const int e,
|
int ioevent_attach(IOEventPoller *ioevent, const int fd,
|
||||||
void *data)
|
const int e, void *data)
|
||||||
{
|
{
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
struct epoll_event ev;
|
#if IOEVENT_USE_URING
|
||||||
memset(&ev, 0, sizeof(ev));
|
if (ioevent->use_io_uring) {
|
||||||
ev.events = e | ioevent->extra_events;
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&ioevent->ring);
|
||||||
ev.data.ptr = data;
|
if (sqe == NULL) {
|
||||||
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_ADD, fd, &ev);
|
return ENOSPC;
|
||||||
|
}
|
||||||
|
io_uring_prep_poll_multishot(sqe, fd, e | ioevent->extra_events);
|
||||||
|
sqe->user_data = (long)data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
struct epoll_event ev;
|
||||||
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
ev.events = e | ioevent->extra_events;
|
||||||
|
ev.data.ptr = data;
|
||||||
|
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_ADD, fd, &ev);
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
struct kevent ev[2];
|
struct kevent ev[2];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
@ -128,15 +176,32 @@ int ioevent_attach(IOEventPoller *ioevent, const int fd, const int e,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int ioevent_modify(IOEventPoller *ioevent, const int fd, const int e,
|
int ioevent_modify(IOEventPoller *ioevent, const int fd,
|
||||||
void *data)
|
const int e, void *data)
|
||||||
{
|
{
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
struct epoll_event ev;
|
#if IOEVENT_USE_URING
|
||||||
memset(&ev, 0, sizeof(ev));
|
if (ioevent->use_io_uring) {
|
||||||
ev.events = e | ioevent->extra_events;
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&ioevent->ring);
|
||||||
ev.data.ptr = data;
|
if (sqe == NULL) {
|
||||||
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_MOD, fd, &ev);
|
return ENOSPC;
|
||||||
|
}
|
||||||
|
io_uring_prep_poll_update(sqe, sqe->user_data, sqe->user_data,
|
||||||
|
e | ioevent->extra_events, IORING_POLL_UPDATE_EVENTS);
|
||||||
|
sqe->user_data = (long)data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
struct epoll_event ev;
|
||||||
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
ev.events = e | ioevent->extra_events;
|
||||||
|
ev.data.ptr = data;
|
||||||
|
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_MOD, fd, &ev);
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
struct kevent ev[2];
|
struct kevent ev[2];
|
||||||
int result;
|
int result;
|
||||||
|
|
@ -171,8 +236,25 @@ int ioevent_modify(IOEventPoller *ioevent, const int fd, const int e,
|
||||||
|
|
||||||
int ioevent_detach(IOEventPoller *ioevent, const int fd)
|
int ioevent_detach(IOEventPoller *ioevent, const int fd)
|
||||||
{
|
{
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_DEL, fd, NULL);
|
#if IOEVENT_USE_URING
|
||||||
|
if (ioevent->use_io_uring) {
|
||||||
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&ioevent->ring);
|
||||||
|
if (sqe == NULL) {
|
||||||
|
return ENOSPC;
|
||||||
|
}
|
||||||
|
io_uring_prep_cancel_fd(sqe, fd, 0);
|
||||||
|
/* set sqe->flags MUST after io_uring_prep_xxx */
|
||||||
|
sqe->flags = IOSQE_CQE_SKIP_SUCCESS;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_DEL, fd, NULL);
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
struct kevent ev[1];
|
struct kevent ev[1];
|
||||||
int r, w;
|
int r, w;
|
||||||
|
|
@ -191,15 +273,33 @@ int ioevent_detach(IOEventPoller *ioevent, const int fd)
|
||||||
|
|
||||||
int ioevent_poll(IOEventPoller *ioevent)
|
int ioevent_poll(IOEventPoller *ioevent)
|
||||||
{
|
{
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
return epoll_wait(ioevent->poll_fd, ioevent->events, ioevent->size, ioevent->timeout);
|
#if IOEVENT_USE_URING
|
||||||
|
if (ioevent->use_io_uring) {
|
||||||
|
int result;
|
||||||
|
result = io_uring_wait_cqe_timeout(&ioevent->ring,
|
||||||
|
&ioevent->cqe, &ioevent->timeout);
|
||||||
|
if (result < 0) {
|
||||||
|
errno = -result;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
return epoll_wait(ioevent->poll_fd, ioevent->events,
|
||||||
|
ioevent->size, ioevent->timeout_ms);
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
return kevent(ioevent->poll_fd, NULL, 0, ioevent->events, ioevent->size, &ioevent->timeout);
|
return kevent(ioevent->poll_fd, NULL, 0, ioevent->events,
|
||||||
|
ioevent->size, &ioevent->timeout);
|
||||||
#elif IOEVENT_USE_PORT
|
#elif IOEVENT_USE_PORT
|
||||||
int result;
|
int result;
|
||||||
int retval;
|
int retval;
|
||||||
unsigned int nget = 1;
|
unsigned int nget = 1;
|
||||||
if((retval = port_getn(ioevent->poll_fd, ioevent->events,
|
if((retval=port_getn(ioevent->poll_fd, ioevent->events,
|
||||||
ioevent->size, &nget, &ioevent->timeout)) == 0)
|
ioevent->size, &nget, &ioevent->timeout)) == 0)
|
||||||
{
|
{
|
||||||
result = (int)nget;
|
result = (int)nget;
|
||||||
|
|
@ -225,4 +325,3 @@ int ioevent_poll(IOEventPoller *ioevent)
|
||||||
#error port me
|
#error port me
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
186
src/ioevent.h
186
src/ioevent.h
|
|
@ -20,17 +20,28 @@
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "_os_define.h"
|
#include "_os_define.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
#define IOEVENT_TIMEOUT 0x8000
|
#define IOEVENT_TIMEOUT (1 << 20)
|
||||||
|
#define IOEVENT_NOTIFY (1 << 21) //for io_uring send_zc done callback
|
||||||
|
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#define IOEVENT_EDGE_TRIGGER EPOLLET
|
#define IOEVENT_EDGE_TRIGGER EPOLLET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if IOEVENT_USE_EPOLL
|
||||||
#define IOEVENT_READ EPOLLIN
|
#define IOEVENT_READ EPOLLIN
|
||||||
#define IOEVENT_WRITE EPOLLOUT
|
#define IOEVENT_WRITE EPOLLOUT
|
||||||
#define IOEVENT_ERROR (EPOLLERR | EPOLLPRI | EPOLLHUP)
|
#define IOEVENT_ERROR (EPOLLERR | EPOLLPRI | EPOLLHUP)
|
||||||
|
|
||||||
|
#elif IOEVENT_USE_URING
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <liburing.h>
|
||||||
|
#define IOEVENT_READ POLLIN
|
||||||
|
#define IOEVENT_WRITE POLLOUT
|
||||||
|
#define IOEVENT_ERROR (POLLERR | POLLPRI | POLLHUP)
|
||||||
|
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
#include <sys/event.h>
|
#include <sys/event.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
|
@ -65,18 +76,33 @@ int kqueue_ev_convert(int16_t event, uint16_t flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct ioevent_puller {
|
typedef struct ioevent_puller {
|
||||||
|
const char *service_name;
|
||||||
int size; //max events (fd)
|
int size; //max events (fd)
|
||||||
int extra_events;
|
int extra_events;
|
||||||
int poll_fd;
|
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
struct io_uring ring;
|
||||||
|
int submit_count;
|
||||||
|
bool send_zc_logged;
|
||||||
|
bool send_zc_done_notify; //if callback when send_zc done
|
||||||
|
bool use_io_uring;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int poll_fd;
|
||||||
struct {
|
struct {
|
||||||
int index;
|
int index;
|
||||||
int count;
|
int count;
|
||||||
} iterator; //for deal event loop
|
} iterator; //for deal event loop
|
||||||
|
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
struct epoll_event *events;
|
struct epoll_event *events;
|
||||||
int timeout;
|
int timeout_ms; //for epoll
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
struct io_uring_cqe *cqe;
|
||||||
|
struct __kernel_timespec timeout;
|
||||||
|
#endif
|
||||||
|
bool zero_timeout;
|
||||||
|
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
struct kevent *events;
|
struct kevent *events;
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
|
|
@ -84,9 +110,10 @@ typedef struct ioevent_puller {
|
||||||
port_event_t *events;
|
port_event_t *events;
|
||||||
timespec_t timeout;
|
timespec_t timeout;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} IOEventPoller;
|
} IOEventPoller;
|
||||||
|
|
||||||
#if IOEVENT_USE_EPOLL
|
#if OS_LINUX
|
||||||
#define IOEVENT_GET_EVENTS(ioevent, index) \
|
#define IOEVENT_GET_EVENTS(ioevent, index) \
|
||||||
(ioevent)->events[index].events
|
(ioevent)->events[index].events
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
|
|
@ -99,7 +126,7 @@ typedef struct ioevent_puller {
|
||||||
#error port me
|
#error port me
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
#define IOEVENT_GET_DATA(ioevent, index) \
|
#define IOEVENT_GET_DATA(ioevent, index) \
|
||||||
(ioevent)->events[index].data.ptr
|
(ioevent)->events[index].data.ptr
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
|
|
@ -112,7 +139,7 @@ typedef struct ioevent_puller {
|
||||||
#error port me
|
#error port me
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IOEVENT_USE_EPOLL
|
#ifdef OS_LINUX
|
||||||
#define IOEVENT_CLEAR_DATA(ioevent, index) \
|
#define IOEVENT_CLEAR_DATA(ioevent, index) \
|
||||||
(ioevent)->events[index].data.ptr = NULL
|
(ioevent)->events[index].data.ptr = NULL
|
||||||
#elif IOEVENT_USE_KQUEUE
|
#elif IOEVENT_USE_KQUEUE
|
||||||
|
|
@ -129,24 +156,39 @@ typedef struct ioevent_puller {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ioevent_init(IOEventPoller *ioevent, const int size,
|
int ioevent_init(IOEventPoller *ioevent, const char *service_name,
|
||||||
const int timeout_ms, const int extra_events);
|
const bool use_io_uring, const int size, const int timeout_ms,
|
||||||
|
const int extra_events);
|
||||||
void ioevent_destroy(IOEventPoller *ioevent);
|
void ioevent_destroy(IOEventPoller *ioevent);
|
||||||
|
|
||||||
int ioevent_attach(IOEventPoller *ioevent, const int fd, const int e,
|
int ioevent_attach(IOEventPoller *ioevent, const int fd,
|
||||||
void *data);
|
const int e, void *data);
|
||||||
int ioevent_modify(IOEventPoller *ioevent, const int fd, const int e,
|
int ioevent_modify(IOEventPoller *ioevent, const int fd,
|
||||||
void *data);
|
const int e, void *data);
|
||||||
int ioevent_detach(IOEventPoller *ioevent, const int fd);
|
int ioevent_detach(IOEventPoller *ioevent, const int fd);
|
||||||
int ioevent_poll(IOEventPoller *ioevent);
|
int ioevent_poll(IOEventPoller *ioevent);
|
||||||
|
|
||||||
static inline void ioevent_set_timeout(IOEventPoller *ioevent, const int timeout_ms)
|
static inline void ioevent_set_timeout(IOEventPoller *ioevent,
|
||||||
|
const int timeout_ms)
|
||||||
{
|
{
|
||||||
#if IOEVENT_USE_EPOLL
|
#if IOEVENT_USE_EPOLL
|
||||||
ioevent->timeout = timeout_ms;
|
ioevent->timeout_ms = timeout_ms;
|
||||||
#else
|
#else
|
||||||
ioevent->timeout.tv_sec = timeout_ms / 1000;
|
#if IOEVENT_USE_URING
|
||||||
ioevent->timeout.tv_nsec = 1000000 * (timeout_ms % 1000);
|
if (!ioevent->use_io_uring) {
|
||||||
|
ioevent->timeout_ms = timeout_ms;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
ioevent->timeout.tv_sec = timeout_ms / 1000;
|
||||||
|
ioevent->timeout.tv_nsec = 1000000 * (timeout_ms % 1000);
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
ioevent->zero_timeout = (timeout_ms == 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,6 +198,114 @@ static inline int ioevent_poll_ex(IOEventPoller *ioevent, const int timeout_ms)
|
||||||
return ioevent_poll(ioevent);
|
return ioevent_poll(ioevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
static inline void ioevent_set_send_zc_done_notify(
|
||||||
|
IOEventPoller *ioevent, const bool need_notify)
|
||||||
|
{
|
||||||
|
ioevent->send_zc_done_notify = need_notify;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ioevent_uring_submit(IOEventPoller *ioevent)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ioevent->submit_count = 0;
|
||||||
|
while (1) {
|
||||||
|
result = io_uring_submit(&ioevent->ring);
|
||||||
|
if (result < 0) {
|
||||||
|
if (result != -EINTR) {
|
||||||
|
return -result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct io_uring_sqe *ioevent_uring_get_sqe(IOEventPoller *ioevent)
|
||||||
|
{
|
||||||
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&ioevent->ring);
|
||||||
|
if (sqe == NULL) {
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"io_uring_get_sqe fail", __LINE__);
|
||||||
|
}
|
||||||
|
return sqe;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_recv(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, int sockfd,
|
||||||
|
void *buf, size_t size, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_recv(sqe, sockfd, buf, size, 0);
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_send(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, int sockfd,
|
||||||
|
void *buf, size_t len, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_send(sqe, sockfd, buf, len, 0);
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_writev(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, int sockfd, const struct iovec *iovecs,
|
||||||
|
unsigned nr_vecs, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_writev(sqe, sockfd, iovecs, nr_vecs, 0);
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_send_zc(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, int sockfd,
|
||||||
|
void *buf, size_t len, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_send_zc(sqe, sockfd, buf, len, 0,
|
||||||
|
#ifdef IORING_SEND_ZC_REPORT_USAGE
|
||||||
|
IORING_SEND_ZC_REPORT_USAGE
|
||||||
|
#else
|
||||||
|
0
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_close(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, int fd, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_close(sqe, fd);
|
||||||
|
if (user_data == NULL) {
|
||||||
|
/* set sqe->flags MUST after io_uring_prep_xxx */
|
||||||
|
sqe->flags = IOSQE_CQE_SKIP_SUCCESS;
|
||||||
|
} else {
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
}
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_cancel(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_cancel(sqe, user_data, 0);
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ioevent_uring_prep_connect(IOEventPoller *ioevent,
|
||||||
|
struct io_uring_sqe *sqe, int fd, const struct sockaddr *addr,
|
||||||
|
socklen_t addrlen, void *user_data)
|
||||||
|
{
|
||||||
|
io_uring_prep_connect(sqe, fd, addr, addrlen);
|
||||||
|
sqe->user_data = (long)user_data;
|
||||||
|
ioevent->submit_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,76 @@
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "ioevent_loop.h"
|
#include "ioevent_loop.h"
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
static int ioevent_process_by_uring(IOEventPoller *ioevent)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
unsigned head;
|
||||||
|
unsigned count = 0;
|
||||||
|
IOEventEntry *pEntry;
|
||||||
|
|
||||||
|
result = io_uring_wait_cqe_timeout(&ioevent->ring,
|
||||||
|
&ioevent->cqe, &ioevent->timeout);
|
||||||
|
switch (result) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -ETIME:
|
||||||
|
case -EINTR:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
result *= -1;
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"io_uring_wait_cqe fail, errno: %d, error info: %s",
|
||||||
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
io_uring_for_each_cqe(&ioevent->ring, head, ioevent->cqe) {
|
||||||
|
count++;
|
||||||
|
pEntry = (IOEventEntry *)ioevent->cqe->user_data;
|
||||||
|
if (pEntry != NULL) {
|
||||||
|
if (ioevent->cqe->flags & IORING_CQE_F_NOTIF) {
|
||||||
|
if (ioevent->send_zc_done_notify) {
|
||||||
|
pEntry->callback(pEntry->fd, IOEVENT_NOTIFY, pEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef IORING_NOTIF_USAGE_ZC_COPIED
|
||||||
|
if (!ioevent->send_zc_logged) {
|
||||||
|
struct fast_task_info *task;
|
||||||
|
|
||||||
|
task = (struct fast_task_info *)pEntry;
|
||||||
|
ioevent->send_zc_logged = true;
|
||||||
|
if (ioevent->cqe->res & IORING_NOTIF_USAGE_ZC_COPIED) {
|
||||||
|
logWarning("file: "__FILE__", line: %d, %s "
|
||||||
|
"client %s:%u, io_uring send_zc: memory "
|
||||||
|
"copy instead of zero copy!", __LINE__,
|
||||||
|
ioevent->service_name, task->client_ip,
|
||||||
|
task->port);
|
||||||
|
} else {
|
||||||
|
logInfo("file: "__FILE__", line: %d, %s "
|
||||||
|
"client %s:%u, io_uring send_zc: zero "
|
||||||
|
"copy OK.", __LINE__, ioevent->service_name,
|
||||||
|
task->client_ip, task->port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
pEntry->res = ioevent->cqe->res;
|
||||||
|
pEntry->callback(pEntry->fd, 0, pEntry);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"io_uring unexpected flags: %d, result: %d", __LINE__,
|
||||||
|
ioevent->cqe->flags, ioevent->cqe->res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io_uring_cq_advance(&ioevent->ring, count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void deal_ioevents(IOEventPoller *ioevent)
|
static void deal_ioevents(IOEventPoller *ioevent)
|
||||||
{
|
{
|
||||||
int event;
|
int event;
|
||||||
|
|
@ -39,35 +109,25 @@ static void deal_ioevents(IOEventPoller *ioevent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ioevent_remove(IOEventPoller *ioevent, void *data)
|
static int ioevent_process_by_poll(IOEventPoller *ioevent)
|
||||||
{
|
{
|
||||||
IOEventEntry *pEntry;
|
int result;
|
||||||
int index;
|
|
||||||
|
|
||||||
if (ioevent->iterator.index >= ioevent->iterator.count)
|
ioevent->iterator.count = ioevent_poll(ioevent);
|
||||||
{
|
if (ioevent->iterator.count > 0) {
|
||||||
return ENOENT;
|
deal_ioevents(ioevent);
|
||||||
}
|
}
|
||||||
|
else if (ioevent->iterator.count < 0) {
|
||||||
pEntry = (IOEventEntry *)IOEVENT_GET_DATA(ioevent,
|
result = errno != 0 ? errno : EINVAL;
|
||||||
ioevent->iterator.index);
|
if (result != EINTR) {
|
||||||
if (pEntry != NULL && (void *)pEntry == data) {
|
logError("file: "__FILE__", line: %d, "
|
||||||
return 0; //do NOT clear current entry
|
"ioevent_poll fail, errno: %d, error info: %s",
|
||||||
}
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
for (index=ioevent->iterator.index + 1; index < ioevent->iterator.count;
|
|
||||||
index++)
|
|
||||||
{
|
|
||||||
pEntry = (IOEventEntry *)IOEVENT_GET_DATA(ioevent, index);
|
|
||||||
if (pEntry != NULL && (void *)pEntry == data) {
|
|
||||||
logDebug("file: "__FILE__", line: %d, "
|
|
||||||
"clear ioevent data: %p", __LINE__, data);
|
|
||||||
IOEVENT_CLEAR_DATA(ioevent, index);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ENOENT;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deal_timeouts(FastTimerEntry *head)
|
static void deal_timeouts(FastTimerEntry *head)
|
||||||
|
|
@ -82,12 +142,10 @@ static void deal_timeouts(FastTimerEntry *head)
|
||||||
current = entry;
|
current = entry;
|
||||||
entry = entry->next;
|
entry = entry->next;
|
||||||
|
|
||||||
current->prev = current->next = NULL; //must set NULL because NOT in time wheel
|
/* must set NULL because NOT in time wheel */
|
||||||
|
current->prev = current->next = NULL;
|
||||||
pEventEntry = (IOEventEntry *)current;
|
pEventEntry = (IOEventEntry *)current;
|
||||||
if (pEventEntry != NULL)
|
pEventEntry->callback(pEventEntry->fd, IOEVENT_TIMEOUT, current);
|
||||||
{
|
|
||||||
pEventEntry->callback(pEventEntry->fd, IOEVENT_TIMEOUT, current);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,10 +189,9 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
|
|
||||||
thread_data->deleted_list = NULL;
|
thread_data->deleted_list = NULL;
|
||||||
last_check_time = g_current_time;
|
last_check_time = g_current_time;
|
||||||
while (*continue_flag)
|
while (*continue_flag) {
|
||||||
{
|
|
||||||
#ifdef OS_LINUX
|
#ifdef OS_LINUX
|
||||||
if (thread_data->ev_puller.timeout == 0) {
|
if (thread_data->ev_puller.zero_timeout) {
|
||||||
sched_pull = (sched_counter++ & 8) != 0;
|
sched_pull = (sched_counter++ & 8) != 0;
|
||||||
} else {
|
} else {
|
||||||
sched_pull = true;
|
sched_pull = true;
|
||||||
|
|
@ -143,43 +200,52 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
sched_pull = true;
|
sched_pull = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sched_pull)
|
#if IOEVENT_USE_URING
|
||||||
{
|
if (thread_data->ev_puller.use_io_uring) {
|
||||||
thread_data->ev_puller.iterator.count = ioevent_poll(
|
if (thread_data->ev_puller.submit_count > 0) {
|
||||||
&thread_data->ev_puller);
|
if ((result=ioevent_uring_submit(&thread_data->
|
||||||
if (thread_data->ev_puller.iterator.count > 0)
|
ev_puller)) != 0)
|
||||||
{
|
|
||||||
deal_ioevents(&thread_data->ev_puller);
|
|
||||||
}
|
|
||||||
else if (thread_data->ev_puller.iterator.count < 0)
|
|
||||||
{
|
|
||||||
result = errno != 0 ? errno : EINVAL;
|
|
||||||
if (result != EINTR)
|
|
||||||
{
|
{
|
||||||
logError("file: "__FILE__", line: %d, " \
|
logError("file: "__FILE__", line: %d, "
|
||||||
"ioevent_poll fail, " \
|
"io_uring_submit fail, errno: %d, error info: %s",
|
||||||
"errno: %d, error info: %s", \
|
|
||||||
__LINE__, result, STRERROR(result));
|
__LINE__, result, STRERROR(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (thread_data->busy_polling_callback != NULL)
|
if (sched_pull) {
|
||||||
{
|
#if IOEVENT_USE_URING
|
||||||
|
if (thread_data->ev_puller.use_io_uring) {
|
||||||
|
if ((result=ioevent_process_by_uring(&thread_data->
|
||||||
|
ev_puller)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
if ((result=ioevent_process_by_poll(&thread_data->
|
||||||
|
ev_puller)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread_data->busy_polling_callback != NULL) {
|
||||||
thread_data->busy_polling_callback(thread_data);
|
thread_data->busy_polling_callback(thread_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread_data->deleted_list != NULL)
|
if (thread_data->deleted_list != NULL) {
|
||||||
{
|
//count = 0;
|
||||||
count = 0;
|
while (thread_data->deleted_list != NULL) {
|
||||||
while (thread_data->deleted_list != NULL)
|
|
||||||
{
|
|
||||||
task = thread_data->deleted_list;
|
task = thread_data->deleted_list;
|
||||||
thread_data->deleted_list = task->next;
|
thread_data->deleted_list = task->next;
|
||||||
|
|
||||||
if (task->polling.in_queue)
|
if (task->polling.in_queue) {
|
||||||
{
|
|
||||||
fc_list_del_init(&task->polling.dlink);
|
fc_list_del_init(&task->polling.dlink);
|
||||||
task->polling.in_queue = false;
|
task->polling.in_queue = false;
|
||||||
if (fc_list_empty(&task->thread_data->polling_queue)) {
|
if (fc_list_empty(&task->thread_data->polling_queue)) {
|
||||||
|
|
@ -188,13 +254,12 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean_up_callback(task);
|
clean_up_callback(task);
|
||||||
count++;
|
//count++;
|
||||||
}
|
}
|
||||||
//logInfo("cleanup task count: %d", count);
|
//logInfo("cleanup task count: %d", count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_current_time - last_check_time > 0)
|
if (g_current_time - last_check_time > 0) {
|
||||||
{
|
|
||||||
last_check_time = g_current_time;
|
last_check_time = g_current_time;
|
||||||
count = fast_timer_timeouts_get(
|
count = fast_timer_timeouts_get(
|
||||||
&thread_data->timer, g_current_time, &head);
|
&thread_data->timer, g_current_time, &head);
|
||||||
|
|
@ -204,8 +269,7 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread_data->notify.enabled)
|
if (thread_data->notify.enabled) {
|
||||||
{
|
|
||||||
int64_t n;
|
int64_t n;
|
||||||
if ((n=__sync_fetch_and_add(&thread_data->notify.counter, 0)) != 0)
|
if ((n=__sync_fetch_and_add(&thread_data->notify.counter, 0)) != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -219,8 +283,7 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread_data->thread_loop_callback != NULL)
|
if (thread_data->thread_loop_callback != NULL) {
|
||||||
{
|
|
||||||
thread_data->thread_loop_callback(thread_data);
|
thread_data->thread_loop_callback(thread_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -229,22 +292,46 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
int ioevent_set(struct fast_task_info *task, struct nio_thread_data *pThread,
|
int ioevent_set(struct fast_task_info *task, struct nio_thread_data *pThread,
|
||||||
int sock, short event, IOEventCallback callback, const int timeout)
|
int sock, short event, IOEventCallback callback,
|
||||||
|
const int timeout)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
task->thread_data = pThread;
|
task->thread_data = pThread;
|
||||||
task->event.fd = sock;
|
task->event.fd = sock;
|
||||||
task->event.callback = callback;
|
task->event.callback = callback;
|
||||||
if (ioevent_attach(&pThread->ev_puller, sock, event, task) < 0)
|
#if IOEVENT_USE_URING
|
||||||
{
|
if (pThread->ev_puller.use_io_uring) {
|
||||||
result = errno != 0 ? errno : ENOENT;
|
if (FC_URING_OP_TYPE(task) == IORING_OP_NOP) {
|
||||||
logError("file: "__FILE__", line: %d, "
|
if ((result=uring_prep_first_recv(task)) != 0) {
|
||||||
"ioevent_attach fail, fd: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
"errno: %d, error info: %s",
|
"uring_prep_recv fail, fd: %d, "
|
||||||
__LINE__, sock, result, STRERROR(result));
|
"errno: %d, error info: %s",
|
||||||
return result;
|
__LINE__, sock, result, STRERROR(result));
|
||||||
}
|
return result;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"skip uring_prep_recv, fd: %d, port: %d, "
|
||||||
|
"in progress op type: %d, timeout: %"PRId64,
|
||||||
|
__LINE__, sock, task->port, FC_URING_OP_TYPE(task),
|
||||||
|
task->event.timer.expires);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
if (ioevent_attach(&pThread->ev_puller, sock, event, task) < 0) {
|
||||||
|
result = errno != 0 ? errno : ENOENT;
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"ioevent_attach fail, fd: %d, "
|
||||||
|
"errno: %d, error info: %s",
|
||||||
|
__LINE__, sock, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
task->event.timer.expires = g_current_time + timeout;
|
task->event.timer.expires = g_current_time + timeout;
|
||||||
fast_timer_add(&pThread->timer, &task->event.timer);
|
fast_timer_add(&pThread->timer, &task->event.timer);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,14 @@
|
||||||
#define _IOEVENT_LOOP_H
|
#define _IOEVENT_LOOP_H
|
||||||
|
|
||||||
#include "fast_task_queue.h"
|
#include "fast_task_queue.h"
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
#include "sockopt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define fc_hold_task_ex(task, inc_count) __sync_add_and_fetch( \
|
||||||
|
&task->reffer_count, inc_count)
|
||||||
|
|
||||||
|
#define fc_hold_task(task) fc_hold_task_ex(task, 1)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -26,11 +34,9 @@ int ioevent_loop(struct nio_thread_data *thread_data,
|
||||||
IOEventCallback recv_notify_callback, TaskCleanUpCallback
|
IOEventCallback recv_notify_callback, TaskCleanUpCallback
|
||||||
clean_up_callback, volatile bool *continue_flag);
|
clean_up_callback, volatile bool *continue_flag);
|
||||||
|
|
||||||
//remove entry from ready list
|
int ioevent_set(struct fast_task_info *task, struct nio_thread_data *pThread,
|
||||||
int ioevent_remove(IOEventPoller *ioevent, void *data);
|
int sock, short event, IOEventCallback callback,
|
||||||
|
const int timeout);
|
||||||
int ioevent_set(struct fast_task_info *pTask, struct nio_thread_data *pThread,
|
|
||||||
int sock, short event, IOEventCallback callback, const int timeout);
|
|
||||||
|
|
||||||
int ioevent_reset(struct fast_task_info *task, int new_fd, short event);
|
int ioevent_reset(struct fast_task_info *task, int new_fd, short event);
|
||||||
|
|
||||||
|
|
@ -75,9 +81,170 @@ static inline int ioevent_notify_thread(struct nio_thread_data *thread_data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
|
||||||
|
#define SET_OP_TYPE_AND_HOLD_TASK(task, _op_type) \
|
||||||
|
struct io_uring_sqe *sqe; \
|
||||||
|
if ((sqe=ioevent_uring_get_sqe(&task->thread_data->ev_puller)) == NULL) { \
|
||||||
|
return ENOSPC; \
|
||||||
|
} \
|
||||||
|
FC_URING_OP_TYPE(task) = _op_type; \
|
||||||
|
fc_hold_task(task)
|
||||||
|
|
||||||
|
static inline int uring_prep_recv_data(struct fast_task_info *task,
|
||||||
|
char *buff, const int len)
|
||||||
|
{
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_RECV);
|
||||||
|
ioevent_uring_prep_recv(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, buff, len, task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_first_recv(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_RECV);
|
||||||
|
ioevent_uring_prep_recv(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->recv.ptr->data,
|
||||||
|
task->recv.ptr->size, task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_next_recv(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_RECV);
|
||||||
|
ioevent_uring_prep_recv(&task->thread_data->ev_puller, sqe,
|
||||||
|
task->event.fd, task->recv.ptr->data + task->recv.ptr->offset,
|
||||||
|
task->recv.ptr->length - task->recv.ptr->offset, task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_first_send(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
if (task->iovec_array.iovs != NULL) {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_WRITEV);
|
||||||
|
ioevent_uring_prep_writev(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->iovec_array.iovs,
|
||||||
|
FC_MIN(task->iovec_array.count, IOV_MAX),
|
||||||
|
task);
|
||||||
|
} else {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_SEND);
|
||||||
|
ioevent_uring_prep_send(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->send.ptr->data,
|
||||||
|
task->send.ptr->length, task);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_next_send(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
if (task->iovec_array.iovs != NULL) {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_WRITEV);
|
||||||
|
ioevent_uring_prep_writev(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->iovec_array.iovs,
|
||||||
|
FC_MIN(task->iovec_array.count, IOV_MAX),
|
||||||
|
task);
|
||||||
|
} else {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_SEND);
|
||||||
|
ioevent_uring_prep_send(&task->thread_data->ev_puller, sqe,
|
||||||
|
task->event.fd, task->send.ptr->data + task->send.ptr->offset,
|
||||||
|
task->send.ptr->length - task->send.ptr->offset, task);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_first_send_zc(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
if (task->iovec_array.iovs != NULL) {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_WRITEV);
|
||||||
|
ioevent_uring_prep_writev(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->iovec_array.iovs,
|
||||||
|
FC_MIN(task->iovec_array.count, IOV_MAX),
|
||||||
|
task);
|
||||||
|
} else if (task->send.ptr->length < 4096) {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_SEND);
|
||||||
|
ioevent_uring_prep_send(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->send.ptr->data,
|
||||||
|
task->send.ptr->length, task);
|
||||||
|
} else {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_SEND_ZC);
|
||||||
|
ioevent_uring_prep_send_zc(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->send.ptr->data,
|
||||||
|
task->send.ptr->length, task);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_next_send_zc(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
if (task->iovec_array.iovs != NULL) {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_WRITEV);
|
||||||
|
ioevent_uring_prep_writev(&task->thread_data->ev_puller,
|
||||||
|
sqe, task->event.fd, task->iovec_array.iovs,
|
||||||
|
FC_MIN(task->iovec_array.count, IOV_MAX),
|
||||||
|
task);
|
||||||
|
} else if (task->send.ptr->length - task->send.ptr->offset < 4096) {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_SEND);
|
||||||
|
ioevent_uring_prep_send(&task->thread_data->ev_puller, sqe,
|
||||||
|
task->event.fd, task->send.ptr->data + task->send.ptr->offset,
|
||||||
|
task->send.ptr->length - task->send.ptr->offset, task);
|
||||||
|
} else {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_SEND_ZC);
|
||||||
|
ioevent_uring_prep_send_zc(&task->thread_data->ev_puller, sqe,
|
||||||
|
task->event.fd, task->send.ptr->data + task->send.ptr->offset,
|
||||||
|
task->send.ptr->length - task->send.ptr->offset, task);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_close_fd(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
struct io_uring_sqe *sqe;
|
||||||
|
|
||||||
|
if ((sqe=ioevent_uring_get_sqe(&task->thread_data->ev_puller)) == NULL) {
|
||||||
|
return ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do NOT need callback */
|
||||||
|
ioevent_uring_prep_close(&task->thread_data->
|
||||||
|
ev_puller, sqe, task->event.fd, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_cancel(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_ASYNC_CANCEL);
|
||||||
|
ioevent_uring_prep_cancel(&task->thread_data->ev_puller, sqe, task);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int uring_prep_connect(struct fast_task_info *task)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
sockaddr_convert_t *convert;
|
||||||
|
|
||||||
|
if ((task->event.fd=socketCreateEx2(AF_UNSPEC, task->server_ip,
|
||||||
|
O_NONBLOCK, NULL, &result)) < 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
convert = (sockaddr_convert_t *)(task->send.ptr->data +
|
||||||
|
task->send.ptr->size - 2 * sizeof(sockaddr_convert_t));
|
||||||
|
if ((result=setsockaddrbyip(task->server_ip, task->port, convert)) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
SET_OP_TYPE_AND_HOLD_TASK(task, IORING_OP_CONNECT);
|
||||||
|
ioevent_uring_prep_connect(&task->thread_data->ev_puller, sqe,
|
||||||
|
task->event.fd, &convert->sa.addr, convert->len, task);
|
||||||
|
} while (0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
115
src/logger.c
115
src/logger.c
|
|
@ -50,21 +50,21 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock);
|
||||||
|
|
||||||
static int check_and_mk_log_dir(const char *base_path)
|
static int check_and_mk_log_dir(const char *base_path)
|
||||||
{
|
{
|
||||||
char data_path[MAX_PATH_SIZE];
|
char log_path[MAX_PATH_SIZE];
|
||||||
|
|
||||||
snprintf(data_path, sizeof(data_path), "%s/logs", base_path);
|
fc_combine_full_filename(base_path, "logs", log_path);
|
||||||
if (!fileExists(data_path))
|
if (!fileExists(log_path))
|
||||||
{
|
{
|
||||||
if (mkdir(data_path, 0755) != 0)
|
if (mkdir(log_path, 0755) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "mkdir \"%s\" fail, " \
|
fprintf(stderr, "mkdir \"%s\" fail, "
|
||||||
"errno: %d, error info: %s\n", \
|
"errno: %d, error info: %s\n",
|
||||||
data_path, errno, STRERROR(errno));
|
log_path, errno, STRERROR(errno));
|
||||||
return errno != 0 ? errno : EPERM;
|
return errno != 0 ? errno : EPERM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int log_init()
|
int log_init()
|
||||||
|
|
@ -112,7 +112,7 @@ int log_init_ex(LogContext *pContext)
|
||||||
}
|
}
|
||||||
pContext->pcurrent_buff = pContext->log_buff;
|
pContext->pcurrent_buff = pContext->log_buff;
|
||||||
|
|
||||||
if ((result=init_pthread_lock(&(pContext->log_thread_lock))) != 0)
|
if ((result=init_pthread_lock(&(pContext->lock))) != 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -136,8 +136,8 @@ static int log_print_header(LogContext *pContext)
|
||||||
if (pContext->current_size < 0)
|
if (pContext->current_size < 0)
|
||||||
{
|
{
|
||||||
result = errno != 0 ? errno : EACCES;
|
result = errno != 0 ? errno : EACCES;
|
||||||
fprintf(stderr, "lseek file \"%s\" fail, " \
|
fprintf(stderr, "lseek file \"%s\" fail, "
|
||||||
"errno: %d, error info: %s\n", \
|
"errno: %d, error info: %s\n",
|
||||||
pContext->log_filename, result, STRERROR(result));
|
pContext->log_filename, result, STRERROR(result));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -249,7 +249,7 @@ int log_set_filename_ex(LogContext *pContext, const char *log_filename)
|
||||||
|
|
||||||
if (*(pContext->log_filename) == '\0')
|
if (*(pContext->log_filename) == '\0')
|
||||||
{
|
{
|
||||||
snprintf(pContext->log_filename, MAX_PATH_SIZE, "%s", log_filename);
|
fc_strlcpy(pContext->log_filename, log_filename, MAX_PATH_SIZE);
|
||||||
return log_open(pContext);
|
return log_open(pContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +258,7 @@ int log_set_filename_ex(LogContext *pContext, const char *log_filename)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(pContext->log_filename, MAX_PATH_SIZE, "%s", log_filename);
|
fc_strlcpy(pContext->log_filename, log_filename, MAX_PATH_SIZE);
|
||||||
return log_reopen_ex(pContext);
|
return log_reopen_ex(pContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -296,9 +296,9 @@ void log_set_header_callback(LogContext *pContext, LogHeaderCallback header_call
|
||||||
{
|
{
|
||||||
int64_t current_size;
|
int64_t current_size;
|
||||||
|
|
||||||
pthread_mutex_lock(&(pContext->log_thread_lock));
|
pthread_mutex_lock(&(pContext->lock));
|
||||||
current_size = pContext->current_size;
|
current_size = pContext->current_size;
|
||||||
pthread_mutex_unlock(&(pContext->log_thread_lock));
|
pthread_mutex_unlock(&(pContext->lock));
|
||||||
if (current_size == 0)
|
if (current_size == 0)
|
||||||
{
|
{
|
||||||
log_print_header(pContext);
|
log_print_header(pContext);
|
||||||
|
|
@ -347,7 +347,7 @@ void log_destroy_ex(LogContext *pContext)
|
||||||
close(pContext->log_fd);
|
close(pContext->log_fd);
|
||||||
pContext->log_fd = STDERR_FILENO;
|
pContext->log_fd = STDERR_FILENO;
|
||||||
|
|
||||||
pthread_mutex_destroy(&pContext->log_thread_lock);
|
pthread_mutex_destroy(&pContext->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pContext->log_buff != NULL)
|
if (pContext->log_buff != NULL)
|
||||||
|
|
@ -385,12 +385,11 @@ static int log_delete_old_file(LogContext *pContext,
|
||||||
char full_filename[MAX_PATH_SIZE + 128];
|
char full_filename[MAX_PATH_SIZE + 128];
|
||||||
if (NEED_COMPRESS_LOG(pContext->compress_log_flags))
|
if (NEED_COMPRESS_LOG(pContext->compress_log_flags))
|
||||||
{
|
{
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s%s",
|
fc_concat_two_strings(old_filename, GZIP_EXT_NAME_STR, full_filename);
|
||||||
old_filename, GZIP_EXT_NAME_STR);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s", old_filename);
|
fc_safe_strcpy(full_filename, old_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlink(full_filename) != 0)
|
if (unlink(full_filename) != 0)
|
||||||
|
|
@ -590,7 +589,9 @@ static int log_get_matched_files(LogContext *pContext,
|
||||||
the_time = get_current_time() - days_before * 86400;
|
the_time = get_current_time() - days_before * 86400;
|
||||||
localtime_r(&the_time, &tm);
|
localtime_r(&the_time, &tm);
|
||||||
memset(filename_prefix, 0, sizeof(filename_prefix));
|
memset(filename_prefix, 0, sizeof(filename_prefix));
|
||||||
len = sprintf(filename_prefix, "%s.", log_filename);
|
len = strlen(log_filename);
|
||||||
|
memcpy(filename_prefix, log_filename, len);
|
||||||
|
*(filename_prefix + len++) = '.';
|
||||||
strftime(filename_prefix + len, sizeof(filename_prefix) - len,
|
strftime(filename_prefix + len, sizeof(filename_prefix) - len,
|
||||||
rotate_time_format_prefix, &tm);
|
rotate_time_format_prefix, &tm);
|
||||||
prefix_filename_len = strlen(filename_prefix);
|
prefix_filename_len = strlen(filename_prefix);
|
||||||
|
|
@ -651,8 +652,8 @@ static int log_delete_matched_old_files(LogContext *pContext,
|
||||||
log_get_file_path(pContext, log_filepath);
|
log_get_file_path(pContext, log_filepath);
|
||||||
for (i=0; i<filename_array.count; i++)
|
for (i=0; i<filename_array.count; i++)
|
||||||
{
|
{
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s%s",
|
fc_concat_two_strings(log_filepath, filename_array.
|
||||||
log_filepath, filename_array.filenames[i]);
|
filenames[i], full_filename);
|
||||||
if (unlink(full_filename) != 0)
|
if (unlink(full_filename) != 0)
|
||||||
{
|
{
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
|
|
@ -703,7 +704,9 @@ int log_delete_old_files(void *args)
|
||||||
the_time -= 86400;
|
the_time -= 86400;
|
||||||
localtime_r(&the_time, &tm);
|
localtime_r(&the_time, &tm);
|
||||||
memset(old_filename, 0, sizeof(old_filename));
|
memset(old_filename, 0, sizeof(old_filename));
|
||||||
len = sprintf(old_filename, "%s.", pContext->log_filename);
|
len = strlen(pContext->log_filename);
|
||||||
|
memcpy(old_filename, pContext->log_filename, len);
|
||||||
|
*(old_filename + len++) = '.';
|
||||||
strftime(old_filename + len, sizeof(old_filename) - len,
|
strftime(old_filename + len, sizeof(old_filename) - len,
|
||||||
pContext->rotate_time_format, &tm);
|
pContext->rotate_time_format, &tm);
|
||||||
if ((result=log_delete_old_file(pContext, old_filename)) != 0)
|
if ((result=log_delete_old_file(pContext, old_filename)) != 0)
|
||||||
|
|
@ -733,6 +736,7 @@ static void *log_gzip_func(void *args)
|
||||||
char log_filepath[MAX_PATH_SIZE];
|
char log_filepath[MAX_PATH_SIZE];
|
||||||
char full_filename[MAX_PATH_SIZE + 32];
|
char full_filename[MAX_PATH_SIZE + 32];
|
||||||
char output[512];
|
char output[512];
|
||||||
|
const char *gzip_cmd_filename;
|
||||||
int prefix_len;
|
int prefix_len;
|
||||||
int result;
|
int result;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -760,11 +764,10 @@ static void *log_gzip_func(void *args)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s%s",
|
gzip_cmd_filename = get_gzip_command_filename();
|
||||||
log_filepath, filename_array.filenames[i]);
|
fc_concat_two_strings(log_filepath, filename_array.
|
||||||
snprintf(cmd, sizeof(cmd), "%s %s",
|
filenames[i], full_filename);
|
||||||
get_gzip_command_filename(), full_filename);
|
fc_combine_two_strings(gzip_cmd_filename, full_filename, ' ', cmd);
|
||||||
|
|
||||||
result = getExecResult(cmd, output, sizeof(output));
|
result = getExecResult(cmd, output, sizeof(output));
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -843,7 +846,9 @@ int log_rotate(LogContext *pContext)
|
||||||
localtime_r(¤t_time, &tm);
|
localtime_r(¤t_time, &tm);
|
||||||
|
|
||||||
memset(old_filename, 0, sizeof(old_filename));
|
memset(old_filename, 0, sizeof(old_filename));
|
||||||
len = sprintf(old_filename, "%s.", pContext->log_filename);
|
len = strlen(pContext->log_filename);
|
||||||
|
memcpy(old_filename, pContext->log_filename, len);
|
||||||
|
*(old_filename + len++) = '.';
|
||||||
strftime(old_filename + len, sizeof(old_filename) - len,
|
strftime(old_filename + len, sizeof(old_filename) - len,
|
||||||
pContext->rotate_time_format, &tm);
|
pContext->rotate_time_format, &tm);
|
||||||
if (access(old_filename, F_OK) == 0)
|
if (access(old_filename, F_OK) == 0)
|
||||||
|
|
@ -913,19 +918,19 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
|
||||||
{
|
{
|
||||||
if (bNeedLock)
|
if (bNeedLock)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&(pContext->log_thread_lock));
|
pthread_mutex_lock(&(pContext->lock));
|
||||||
}
|
}
|
||||||
result = log_check_rotate(pContext);
|
result = log_check_rotate(pContext);
|
||||||
if (bNeedLock)
|
if (bNeedLock)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&(pContext->log_thread_lock));
|
pthread_mutex_unlock(&(pContext->lock));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bNeedLock && ((lock_res=pthread_mutex_lock( \
|
if (bNeedLock && ((lock_res=pthread_mutex_lock( \
|
||||||
&(pContext->log_thread_lock))) != 0))
|
&(pContext->lock))) != 0))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
||||||
"call pthread_mutex_lock fail, " \
|
"call pthread_mutex_lock fail, " \
|
||||||
|
|
@ -961,7 +966,7 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bNeedLock && ((lock_res=pthread_mutex_unlock( \
|
if (bNeedLock && ((lock_res=pthread_mutex_unlock( \
|
||||||
&(pContext->log_thread_lock))) != 0))
|
&(pContext->lock))) != 0))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
||||||
"call pthread_mutex_unlock fail, " \
|
"call pthread_mutex_unlock fail, " \
|
||||||
|
|
@ -972,8 +977,8 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doLogEx(LogContext *pContext, struct timeval *tv, \
|
void log_it_ex3(LogContext *pContext, struct timeval *tv,
|
||||||
const char *caption, const char *text, const int text_len, \
|
const char *caption, const char *text, const int text_len,
|
||||||
const bool bNeedSync, const bool bNeedLock)
|
const bool bNeedSync, const bool bNeedLock)
|
||||||
{
|
{
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
|
@ -998,7 +1003,7 @@ static void doLogEx(LogContext *pContext, struct timeval *tv, \
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bNeedLock && (result=pthread_mutex_lock(&pContext->log_thread_lock)) != 0)
|
if (bNeedLock && (result=pthread_mutex_lock(&pContext->lock)) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
||||||
"call pthread_mutex_lock fail, " \
|
"call pthread_mutex_lock fail, " \
|
||||||
|
|
@ -1013,12 +1018,12 @@ static void doLogEx(LogContext *pContext, struct timeval *tv, \
|
||||||
__LINE__, LOG_BUFF_SIZE, text_len + 64);
|
__LINE__, LOG_BUFF_SIZE, text_len + 64);
|
||||||
if (bNeedLock)
|
if (bNeedLock)
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock(&(pContext->log_thread_lock));
|
pthread_mutex_unlock(&(pContext->lock));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pContext->pcurrent_buff - pContext->log_buff) + text_len + 64 \
|
if ((pContext->pcurrent_buff - pContext->log_buff) + text_len + 64
|
||||||
> LOG_BUFF_SIZE)
|
> LOG_BUFF_SIZE)
|
||||||
{
|
{
|
||||||
log_fsync(pContext, false);
|
log_fsync(pContext, false);
|
||||||
|
|
@ -1045,10 +1050,14 @@ static void doLogEx(LogContext *pContext, struct timeval *tv, \
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caption != NULL)
|
if (caption != NULL)
|
||||||
{
|
{
|
||||||
buff_len = sprintf(pContext->pcurrent_buff, "%s - ", caption);
|
buff_len = strlen(caption);
|
||||||
pContext->pcurrent_buff += buff_len;
|
memcpy(pContext->pcurrent_buff, caption, buff_len);
|
||||||
}
|
pContext->pcurrent_buff += buff_len;
|
||||||
|
*pContext->pcurrent_buff++ = ' ';
|
||||||
|
*pContext->pcurrent_buff++ = '-';
|
||||||
|
*pContext->pcurrent_buff++ = ' ';
|
||||||
|
}
|
||||||
memcpy(pContext->pcurrent_buff, text, text_len);
|
memcpy(pContext->pcurrent_buff, text, text_len);
|
||||||
pContext->pcurrent_buff += text_len;
|
pContext->pcurrent_buff += text_len;
|
||||||
*pContext->pcurrent_buff++ = '\n';
|
*pContext->pcurrent_buff++ = '\n';
|
||||||
|
|
@ -1058,7 +1067,7 @@ static void doLogEx(LogContext *pContext, struct timeval *tv, \
|
||||||
log_fsync(pContext, false);
|
log_fsync(pContext, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bNeedLock && (result=pthread_mutex_unlock(&(pContext->log_thread_lock))) != 0)
|
if (bNeedLock && (result=pthread_mutex_unlock(&(pContext->lock))) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
fprintf(stderr, "file: "__FILE__", line: %d, " \
|
||||||
"call pthread_mutex_unlock fail, " \
|
"call pthread_mutex_unlock fail, " \
|
||||||
|
|
@ -1067,8 +1076,8 @@ static void doLogEx(LogContext *pContext, struct timeval *tv, \
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_it_ex2(LogContext *pContext, const char *caption, \
|
void log_it_ex2(LogContext *pContext, const char *caption,
|
||||||
const char *text, const int text_len, \
|
const char *text, const int text_len,
|
||||||
const bool bNeedSync, const bool bNeedLock)
|
const bool bNeedSync, const bool bNeedLock)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
@ -1083,10 +1092,10 @@ void log_it_ex2(LogContext *pContext, const char *caption, \
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
doLogEx(pContext, &tv, caption, text, text_len, bNeedSync, bNeedLock);
|
log_it_ex3(pContext, &tv, caption, text, text_len, bNeedSync, bNeedLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_it_ex1(LogContext *pContext, const int priority, \
|
void log_it_ex1(LogContext *pContext, const int priority,
|
||||||
const char *text, const int text_len)
|
const char *text, const int text_len)
|
||||||
{
|
{
|
||||||
bool bNeedSync;
|
bool bNeedSync;
|
||||||
|
|
@ -1282,7 +1291,7 @@ void logAccess(LogContext *pContext, struct timeval *tvStart, \
|
||||||
{
|
{
|
||||||
len = sizeof(text) - 1;
|
len = sizeof(text) - 1;
|
||||||
}
|
}
|
||||||
doLogEx(pContext, tvStart, NULL, text, len, false, true);
|
log_it_ex3(pContext, tvStart, NULL, text, len, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *log_get_level_caption_ex(LogContext *pContext)
|
const char *log_get_level_caption_ex(LogContext *pContext)
|
||||||
|
|
|
||||||
11
src/logger.h
11
src/logger.h
|
|
@ -62,7 +62,7 @@ typedef struct log_context
|
||||||
char *pcurrent_buff;
|
char *pcurrent_buff;
|
||||||
|
|
||||||
/* mutext lock */
|
/* mutext lock */
|
||||||
pthread_mutex_t log_thread_lock;
|
pthread_mutex_t lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
rotate the log when the log file exceeds this parameter
|
rotate the log when the log file exceeds this parameter
|
||||||
|
|
@ -343,7 +343,7 @@ void log_it_ex(LogContext *pContext, const int priority, \
|
||||||
* text_len: text string length (bytes)
|
* text_len: text string length (bytes)
|
||||||
* return: none
|
* return: none
|
||||||
*/
|
*/
|
||||||
void log_it_ex1(LogContext *pContext, const int priority, \
|
void log_it_ex1(LogContext *pContext, const int priority,
|
||||||
const char *text, const int text_len);
|
const char *text, const int text_len);
|
||||||
|
|
||||||
/** log to file
|
/** log to file
|
||||||
|
|
@ -355,10 +355,13 @@ void log_it_ex1(LogContext *pContext, const int priority, \
|
||||||
* bNeedSync: if sync to file immediatelly
|
* bNeedSync: if sync to file immediatelly
|
||||||
* return: none
|
* return: none
|
||||||
*/
|
*/
|
||||||
void log_it_ex2(LogContext *pContext, const char *caption, \
|
void log_it_ex2(LogContext *pContext, const char *caption,
|
||||||
const char *text, const int text_len, \
|
const char *text, const int text_len,
|
||||||
const bool bNeedSync, const bool bNeedLock);
|
const bool bNeedSync, const bool bNeedLock);
|
||||||
|
|
||||||
|
void log_it_ex3(LogContext *pContext, struct timeval *tv,
|
||||||
|
const char *caption, const char *text, const int text_len,
|
||||||
|
const bool bNeedSync, const bool bNeedLock);
|
||||||
|
|
||||||
/** sync log buffer to log file
|
/** sync log buffer to log file
|
||||||
* parameters:
|
* parameters:
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
|
||||||
fms_client_get_current_time_ms_func get_current_time_ms_func,
|
fms_client_get_current_time_ms_func get_current_time_ms_func,
|
||||||
const int init_recv_buffer_size, const int timeout_ms)
|
const int init_recv_buffer_size, const int timeout_ms)
|
||||||
{
|
{
|
||||||
|
const bool use_io_uring = false;
|
||||||
int result;
|
int result;
|
||||||
int new_init_recv_buffer_size;
|
int new_init_recv_buffer_size;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -65,8 +66,8 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result=ioevent_init(&client->ioevent, entry_count,
|
if ((result=ioevent_init(&client->ioevent, "client",
|
||||||
timeout_ms, 0)) != 0)
|
use_io_uring, entry_count, timeout_ms, 0)) != 0)
|
||||||
{
|
{
|
||||||
logError("file: "__FILE__", line: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
"ioevent_init fail, errno: %d, error info: %s",
|
"ioevent_init fail, errno: %d, error info: %s",
|
||||||
|
|
@ -85,7 +86,7 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<entry_count; i++) {
|
for (i=0; i<entry_count; i++) {
|
||||||
if ((result=fast_buffer_init_ex(&entries[i].recv_buffer,
|
if ((result=fast_buffer_init1(&entries[i].recv_buffer,
|
||||||
new_init_recv_buffer_size)) != 0)
|
new_init_recv_buffer_size)) != 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -316,9 +317,13 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
|
||||||
static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
|
static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
int event;
|
|
||||||
int count;
|
int count;
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
unsigned head;
|
||||||
|
#else
|
||||||
|
int event;
|
||||||
int index;
|
int index;
|
||||||
|
#endif
|
||||||
int remain_timeout;
|
int remain_timeout;
|
||||||
FastMultiSockEntry *entry;
|
FastMultiSockEntry *entry;
|
||||||
char formatted_ip[FORMATTED_IP_SIZE];
|
char formatted_ip[FORMATTED_IP_SIZE];
|
||||||
|
|
@ -330,6 +335,37 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IOEVENT_USE_URING
|
||||||
|
result = io_uring_wait_cqe_timeout(&client->ioevent.ring,
|
||||||
|
&client->ioevent.cqe, &client->ioevent.timeout);
|
||||||
|
switch (result) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -ETIME:
|
||||||
|
case -EAGAIN:
|
||||||
|
case -EINTR:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
result *= -1;
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"io_uring_wait_cqe fail, errno: %d, error info: %s",
|
||||||
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
io_uring_for_each_cqe(&client->ioevent.ring, head, client->ioevent.cqe) {
|
||||||
|
count++;
|
||||||
|
entry = (FastMultiSockEntry *)client->ioevent.cqe->user_data;
|
||||||
|
//logInfo("sock: %d, event: %d", entry->conn->sock, event);
|
||||||
|
result = entry->io_callback(client, entry);
|
||||||
|
if (result != 0 || entry->remain == 0) {
|
||||||
|
fast_multi_sock_client_finish(client, entry, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
io_uring_cq_advance(&client->ioevent.ring, count);
|
||||||
|
|
||||||
|
#else
|
||||||
count = ioevent_poll_ex(&client->ioevent, remain_timeout);
|
count = ioevent_poll_ex(&client->ioevent, remain_timeout);
|
||||||
//logInfo("poll count: %d\n", count);
|
//logInfo("poll count: %d\n", count);
|
||||||
for (index=0; index<count; index++) {
|
for (index=0; index<count; index++) {
|
||||||
|
|
@ -354,6 +390,7 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
|
||||||
fast_multi_sock_client_finish(client, entry, result);
|
fast_multi_sock_client_finish(client, entry, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,14 @@ int write_to_pid_file(const char *pidFilename)
|
||||||
char buff[32];
|
char buff[32];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(buff, "%d", (int)getpid());
|
len = fc_itoa(getpid(), buff);
|
||||||
return writeToFile(pidFilename, buff, len);
|
return writeToFile(pidFilename, buff, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int delete_pid_file(const char *pidFilename)
|
int delete_pid_file(const char *pidFilename)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
pid_t pid;
|
pid_t pid = 0;
|
||||||
|
|
||||||
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
|
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -112,14 +112,16 @@ static int do_stop(const char *pidFilename, const bool bShowError, pid_t *pid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_stop_ex(const char *pidFilename, const bool bShowError)
|
int process_stop_ex(const char *pidFilename,
|
||||||
|
const bool bShowError, bool *force)
|
||||||
{
|
{
|
||||||
#define MAX_WAIT_COUNT 300
|
#define MAX_WAIT_COUNT 300
|
||||||
pid_t pid;
|
pid_t pid = 0;
|
||||||
int result;
|
int result;
|
||||||
int sig;
|
int sig;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
*force = false;
|
||||||
if ((result=do_stop(pidFilename, bShowError, &pid)) != 0) {
|
if ((result=do_stop(pidFilename, bShowError, &pid)) != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -131,14 +133,15 @@ int process_stop_ex(const char *pidFilename, const bool bShowError)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(100 * 1000);
|
fc_sleep_ms(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == MAX_WAIT_COUNT) {
|
if (i == MAX_WAIT_COUNT) {
|
||||||
if (kill(pid, SIGKILL) == 0) {
|
if (kill(pid, SIGKILL) == 0) {
|
||||||
fprintf(stderr, "waiting for pid [%d] exit timeout, "
|
fprintf(stderr, "waiting for pid [%d] exit timeout, "
|
||||||
"force kill!\n", (int)pid);
|
"force kill!\n", (int)pid);
|
||||||
usleep(100 * 1000);
|
*force = true;
|
||||||
|
fc_sleep_ms(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,12 +152,16 @@ int process_stop_ex(const char *pidFilename, const bool bShowError)
|
||||||
int process_restart(const char *pidFilename)
|
int process_restart(const char *pidFilename)
|
||||||
{
|
{
|
||||||
const bool bShowError = false;
|
const bool bShowError = false;
|
||||||
|
bool force;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
result = process_stop_ex(pidFilename, bShowError);
|
result = process_stop_ex(pidFilename, bShowError, &force);
|
||||||
if (result == ENOENT || result == ESRCH) {
|
if (result == ENOENT || result == ESRCH) {
|
||||||
result = 0;
|
result = 0;
|
||||||
} else if (result == 0) {
|
} else if (result == 0) {
|
||||||
|
if (force) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
fprintf(stderr, "starting ...\n");
|
fprintf(stderr, "starting ...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,7 +199,7 @@ static const char *get_exename_by_pid(const pid_t pid, char *buff,
|
||||||
|
|
||||||
int process_start(const char* pidFilename)
|
int process_start(const char* pidFilename)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid = 0;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
|
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
|
||||||
|
|
@ -332,7 +339,6 @@ int get_base_path_from_conf_file_ex(const char *filename, char *base_path,
|
||||||
|
|
||||||
int process_action(const char *pidFilename, const char *action, bool *stop)
|
int process_action(const char *pidFilename, const char *action, bool *stop)
|
||||||
{
|
{
|
||||||
const bool bShowError = true;
|
|
||||||
int result;
|
int result;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
|
@ -345,7 +351,7 @@ int process_action(const char *pidFilename, const char *action, bool *stop)
|
||||||
if (strcmp(action, "stop") == 0)
|
if (strcmp(action, "stop") == 0)
|
||||||
{
|
{
|
||||||
*stop = true;
|
*stop = true;
|
||||||
return process_stop_ex(pidFilename, bShowError);
|
return process_stop(pidFilename);
|
||||||
}
|
}
|
||||||
else if (strcmp(action, "status") == 0)
|
else if (strcmp(action, "status") == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,15 @@ int write_to_pid_file(const char *pidFilename);
|
||||||
|
|
||||||
int delete_pid_file(const char *pidFilename);
|
int delete_pid_file(const char *pidFilename);
|
||||||
|
|
||||||
int process_stop_ex(const char *pidFilename, const bool bShowError);
|
int process_stop_ex(const char *pidFilename,
|
||||||
|
const bool bShowError, bool *force);
|
||||||
|
|
||||||
#define process_stop(pidFilename) process_stop_ex(pidFilename, true)
|
static inline int process_stop(const char *pidFilename)
|
||||||
|
{
|
||||||
|
const bool bShowError = true;
|
||||||
|
bool force;
|
||||||
|
return process_stop_ex(pidFilename, bShowError, &force);
|
||||||
|
}
|
||||||
|
|
||||||
int process_restart(const char *pidFilename);
|
int process_restart(const char *pidFilename);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -294,15 +294,18 @@ FCServerInfo *fc_server_get_by_ip_port_ex(FCServerConfig *ctx,
|
||||||
static inline void fc_server_set_group_ptr_name(FCServerGroupInfo *ginfo,
|
static inline void fc_server_set_group_ptr_name(FCServerGroupInfo *ginfo,
|
||||||
const char *group_name)
|
const char *group_name)
|
||||||
{
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
ginfo->group_name.str = ginfo->name_buff;
|
ginfo->group_name.str = ginfo->name_buff;
|
||||||
ginfo->group_name.len = snprintf(ginfo->name_buff,
|
len = strlen(group_name);
|
||||||
sizeof(ginfo->name_buff) - 1, "%s", group_name);
|
if (len >= sizeof(ginfo->name_buff)) {
|
||||||
if (ginfo->group_name.len == 0) {
|
len = sizeof(ginfo->name_buff) - 1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fc_trim(ginfo->group_name.str);
|
memcpy(ginfo->name_buff, group_name, len);
|
||||||
ginfo->group_name.len = strlen(ginfo->group_name.str);
|
*(ginfo->name_buff + len) = '\0';
|
||||||
|
fc_trim(ginfo->name_buff);
|
||||||
|
ginfo->group_name.len = strlen(ginfo->name_buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo,
|
static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo,
|
||||||
|
|
@ -310,8 +313,8 @@ static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo,
|
||||||
{
|
{
|
||||||
ginfo->filter.ip_prefix.str = ginfo->filter.prefix_buff;
|
ginfo->filter.ip_prefix.str = ginfo->filter.prefix_buff;
|
||||||
if (ip_prefix != NULL) {
|
if (ip_prefix != NULL) {
|
||||||
ginfo->filter.ip_prefix.len = snprintf(ginfo->filter.prefix_buff,
|
ginfo->filter.ip_prefix.len = fc_safe_strcpy(
|
||||||
sizeof(ginfo->filter.prefix_buff) - 1, "%s", ip_prefix);
|
ginfo->filter.prefix_buff, ip_prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1743,6 +1746,7 @@ int fc_server_make_connection_ex(FCAddressPtrArray *addr_array,
|
||||||
|
|
||||||
conn_pool_set_server_info(conn, (*addr)->conn.ip_addr,
|
conn_pool_set_server_info(conn, (*addr)->conn.ip_addr,
|
||||||
(*addr)->conn.port);
|
(*addr)->conn.port);
|
||||||
|
conn->comm_type = (*addr)->conn.comm_type;
|
||||||
if ((result=G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
|
if ((result=G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
|
||||||
make_connection(conn, service_name, connect_timeout * 1000,
|
make_connection(conn, service_name, connect_timeout * 1000,
|
||||||
bind_ipaddr, log_connect_error)) == 0)
|
bind_ipaddr, log_connect_error)) == 0)
|
||||||
|
|
@ -1797,7 +1801,9 @@ struct ibv_pd *fc_alloc_rdma_pd(fc_alloc_pd_callback alloc_pd,
|
||||||
}
|
}
|
||||||
|
|
||||||
end = address_array->addrs + address_array->count;
|
end = address_array->addrs + address_array->count;
|
||||||
for (addr=address_array->addrs, ip_addr=ip_addrs; addr<end; addr++) {
|
for (addr=address_array->addrs, ip_addr=ip_addrs;
|
||||||
|
addr<end; addr++, ip_addr++)
|
||||||
|
{
|
||||||
*ip_addr = (*addr)->conn.ip_addr;
|
*ip_addr = (*addr)->conn.ip_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool g_set_cloexec = false;
|
bool g_set_cloexec = false;
|
||||||
|
const char *g_lower_hex_chars = "0123456789abcdef";
|
||||||
|
const char *g_upper_hex_chars = "0123456789ABCDEF";
|
||||||
|
|
||||||
char *formatDatetime(const time_t nTime, \
|
char *formatDatetime(const time_t nTime, \
|
||||||
const char *szDateFormat, \
|
const char *szDateFormat, \
|
||||||
|
|
@ -145,7 +147,7 @@ char *getAbsolutePath(const char *filename, char *szAbsPath, \
|
||||||
|
|
||||||
if (szPath[0] == '/')
|
if (szPath[0] == '/')
|
||||||
{
|
{
|
||||||
snprintf(szAbsPath, pathSize, "%s", szPath);
|
fc_strlcpy(szAbsPath, szPath, pathSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -165,12 +167,13 @@ char *getAbsolutePath(const char *filename, char *szAbsPath, \
|
||||||
|
|
||||||
if (szPath[0] != '\0')
|
if (szPath[0] != '\0')
|
||||||
{
|
{
|
||||||
snprintf(szAbsPath, pathSize, "%s/%s", cwd, szPath);
|
fc_get_full_filepath_ex(cwd, strlen(cwd), szPath,
|
||||||
}
|
strlen(szPath), szAbsPath, pathSize);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(szAbsPath, pathSize, "%s", cwd);
|
fc_strlcpy(szAbsPath, cwd, pathSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return szAbsPath;
|
return szAbsPath;
|
||||||
|
|
@ -205,8 +208,7 @@ char *getExeAbsoluteFilename(const char *exeFilename, char *szAbsFilename, \
|
||||||
filename = exeFilename;
|
filename = exeFilename;
|
||||||
for (i=0; i<3; i++)
|
for (i=0; i<3; i++)
|
||||||
{
|
{
|
||||||
snprintf(cwd, sizeof(cwd), "%s/%s", \
|
fc_combine_full_filename(search_paths[i], filename, cwd);
|
||||||
search_paths[i], filename);
|
|
||||||
if (fileExists(cwd))
|
if (fileExists(cwd))
|
||||||
{
|
{
|
||||||
strcpy(szPath, search_paths[i]);
|
strcpy(szPath, search_paths[i]);
|
||||||
|
|
@ -225,11 +227,11 @@ char *getExeAbsoluteFilename(const char *exeFilename, char *szAbsFilename, \
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(szAbsFilename, maxSize, "%s/%s", \
|
fc_get_full_filename_ex(szPath, strlen(szPath), filename,
|
||||||
szPath, filename);
|
strlen(filename), szAbsFilename, maxSize);
|
||||||
return szAbsFilename;
|
return szAbsFilename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -241,8 +243,9 @@ char *getExeAbsoluteFilename(const char *exeFilename, char *szAbsFilename, \
|
||||||
|
|
||||||
if (*szPath == '/')
|
if (*szPath == '/')
|
||||||
{
|
{
|
||||||
snprintf(szAbsFilename, maxSize, "%s/%s", szPath, filename);
|
fc_get_full_filename_ex(szPath, strlen(szPath), filename,
|
||||||
}
|
strlen(filename), szAbsFilename, maxSize);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (getcwd(cwd, sizeof(cwd)) == NULL)
|
if (getcwd(cwd, sizeof(cwd)) == NULL)
|
||||||
|
|
@ -261,14 +264,14 @@ char *getExeAbsoluteFilename(const char *exeFilename, char *szAbsFilename, \
|
||||||
|
|
||||||
if (*szPath != '\0')
|
if (*szPath != '\0')
|
||||||
{
|
{
|
||||||
snprintf(szAbsFilename, maxSize, "%s/%s/%s", \
|
snprintf(szAbsFilename, maxSize, "%s/%s/%s",
|
||||||
cwd, szPath, filename);
|
cwd, szPath, filename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(szAbsFilename, maxSize, "%s/%s", \
|
fc_get_full_filename_ex(cwd, strlen(cwd), filename,
|
||||||
cwd, filename);
|
strlen(filename), szAbsFilename, maxSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return szAbsFilename;
|
return szAbsFilename;
|
||||||
|
|
@ -327,7 +330,7 @@ int getUserProcIds(const char *progName, const bool bAllOwners, \
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(fullpath, "%s/%s", path, dirp->d_name);
|
fc_combine_full_filepath(path, dirp->d_name, fullpath);
|
||||||
memset(&statbuf, 0, sizeof(statbuf));
|
memset(&statbuf, 0, sizeof(statbuf));
|
||||||
if (lstat(fullpath, &statbuf) < 0)
|
if (lstat(fullpath, &statbuf) < 0)
|
||||||
{
|
{
|
||||||
|
|
@ -336,7 +339,7 @@ int getUserProcIds(const char *progName, const bool bAllOwners, \
|
||||||
|
|
||||||
if ((bAllOwners || (statbuf.st_uid == myuid)) && S_ISDIR(statbuf.st_mode))
|
if ((bAllOwners || (statbuf.st_uid == myuid)) && S_ISDIR(statbuf.st_mode))
|
||||||
{
|
{
|
||||||
sprintf(filepath, "%s/cmdline", fullpath);
|
fc_combine_full_filename(fullpath, "cmdline", filepath);
|
||||||
if ((fd=open(filepath, O_RDONLY | O_CLOEXEC))<0)
|
if ((fd=open(filepath, O_RDONLY | O_CLOEXEC))<0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -357,12 +360,12 @@ int getUserProcIds(const char *progName, const bool bAllOwners, \
|
||||||
ptr = strrchr(buf, '/');
|
ptr = strrchr(buf, '/');
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
snprintf(procname, 64, "%s", buf);
|
fc_safe_strcpy(procname, buf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(procname, 64, "%s", ptr + 1);
|
fc_safe_strcpy(procname, ptr + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(procname, pTargetProg) == 0)
|
if (strcmp(procname, pTargetProg) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -530,16 +533,17 @@ char *bin2hex(const char *s, const int len, char *szHexBuff)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
unsigned char *pEnd;
|
unsigned char *pEnd;
|
||||||
int nLen;
|
char *dest;
|
||||||
|
|
||||||
nLen = 0;
|
dest = szHexBuff;
|
||||||
pEnd = (unsigned char *)s + len;
|
pEnd = (unsigned char *)s + len;
|
||||||
for (p=(unsigned char *)s; p<pEnd; p++)
|
for (p=(unsigned char *)s; p<pEnd; p++)
|
||||||
{
|
{
|
||||||
nLen += sprintf(szHexBuff + nLen, "%02x", *p);
|
*dest++ = g_lower_hex_chars[*p >> 4];
|
||||||
}
|
*dest++ = g_lower_hex_chars[*p & 0x0F];
|
||||||
|
}
|
||||||
|
|
||||||
szHexBuff[nLen] = '\0';
|
*dest = '\0';
|
||||||
return szHexBuff;
|
return szHexBuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1450,13 +1454,13 @@ int writeToFile(const char *filename, const char *buff, const int file_size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int safeWriteToFile(const char *filename, const char *buff, \
|
int safeWriteToFile(const char *filename, const char *buff,
|
||||||
const int file_size)
|
const int file_size)
|
||||||
{
|
{
|
||||||
char tmpFilename[PATH_MAX];
|
char tmpFilename[PATH_MAX];
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
snprintf(tmpFilename, sizeof(tmpFilename), "%s.tmp", filename);
|
fc_combine_two_strings(filename, "tmp", '.', tmpFilename);
|
||||||
if ((result=writeToFile(tmpFilename, buff, file_size)) != 0)
|
if ((result=writeToFile(tmpFilename, buff, file_size)) != 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1553,78 +1557,16 @@ int fc_copy_to_path(const char *src_filename, const char *dest_path)
|
||||||
fname = strrchr(src_filename, '/');
|
fname = strrchr(src_filename, '/');
|
||||||
if (fname == NULL)
|
if (fname == NULL)
|
||||||
{
|
{
|
||||||
snprintf(dest_filename, sizeof(dest_filename),
|
fc_combine_full_filename(dest_path, src_filename, dest_filename);
|
||||||
"%s/%s", dest_path, src_filename);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(dest_filename, sizeof(dest_filename),
|
fc_combine_full_filename(dest_path, fname, dest_filename);
|
||||||
"%s%s", dest_path, fname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fc_copy_file(src_filename, dest_filename);
|
return fc_copy_file(src_filename, dest_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void short2buff(const short n, char *buff)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
p = (unsigned char *)buff;
|
|
||||||
*p++ = (n >> 8) & 0xFF;
|
|
||||||
*p++ = n & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
short buff2short(const char *buff)
|
|
||||||
{
|
|
||||||
return (short)((((unsigned char)(*(buff))) << 8) | \
|
|
||||||
((unsigned char)(*(buff+1))));
|
|
||||||
}
|
|
||||||
|
|
||||||
void int2buff(const int n, char *buff)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
p = (unsigned char *)buff;
|
|
||||||
*p++ = (n >> 24) & 0xFF;
|
|
||||||
*p++ = (n >> 16) & 0xFF;
|
|
||||||
*p++ = (n >> 8) & 0xFF;
|
|
||||||
*p++ = n & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
int buff2int(const char *buff)
|
|
||||||
{
|
|
||||||
return (((unsigned char)(*buff)) << 24) | \
|
|
||||||
(((unsigned char)(*(buff+1))) << 16) | \
|
|
||||||
(((unsigned char)(*(buff+2))) << 8) | \
|
|
||||||
((unsigned char)(*(buff+3)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void long2buff(int64_t n, char *buff)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
p = (unsigned char *)buff;
|
|
||||||
*p++ = (n >> 56) & 0xFF;
|
|
||||||
*p++ = (n >> 48) & 0xFF;
|
|
||||||
*p++ = (n >> 40) & 0xFF;
|
|
||||||
*p++ = (n >> 32) & 0xFF;
|
|
||||||
*p++ = (n >> 24) & 0xFF;
|
|
||||||
*p++ = (n >> 16) & 0xFF;
|
|
||||||
*p++ = (n >> 8) & 0xFF;
|
|
||||||
*p++ = n & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t buff2long(const char *buff)
|
|
||||||
{
|
|
||||||
unsigned char *p;
|
|
||||||
p = (unsigned char *)buff;
|
|
||||||
return (((int64_t)(*p)) << 56) | \
|
|
||||||
(((int64_t)(*(p+1))) << 48) | \
|
|
||||||
(((int64_t)(*(p+2))) << 40) | \
|
|
||||||
(((int64_t)(*(p+3))) << 32) | \
|
|
||||||
(((int64_t)(*(p+4))) << 24) | \
|
|
||||||
(((int64_t)(*(p+5))) << 16) | \
|
|
||||||
(((int64_t)(*(p+6))) << 8) | \
|
|
||||||
((int64_t)(*(p+7)));
|
|
||||||
}
|
|
||||||
|
|
||||||
int fd_gets(int fd, char *buff, const int size, int once_bytes)
|
int fd_gets(int fd, char *buff, const int size, int once_bytes)
|
||||||
{
|
{
|
||||||
char *pDest;
|
char *pDest;
|
||||||
|
|
@ -2626,7 +2568,6 @@ int get_time_item_from_str(const char *pValue, const char *item_name,
|
||||||
|
|
||||||
char *urlencode(const char *src, const int src_len, char *dest, int *dest_len)
|
char *urlencode(const char *src, const int src_len, char *dest, int *dest_len)
|
||||||
{
|
{
|
||||||
static unsigned char hex_chars[] = "0123456789ABCDEF";
|
|
||||||
const unsigned char *pSrc;
|
const unsigned char *pSrc;
|
||||||
const unsigned char *pEnd;
|
const unsigned char *pEnd;
|
||||||
char *pDest;
|
char *pDest;
|
||||||
|
|
@ -2649,8 +2590,8 @@ char *urlencode(const char *src, const int src_len, char *dest, int *dest_len)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*pDest++ = '%';
|
*pDest++ = '%';
|
||||||
*pDest++ = hex_chars[(*pSrc) >> 4];
|
*pDest++ = g_upper_hex_chars[(*pSrc) >> 4];
|
||||||
*pDest++ = hex_chars[(*pSrc) & 0x0F];
|
*pDest++ = g_upper_hex_chars[(*pSrc) & 0x0F];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3291,7 +3232,7 @@ static void add_thousands_separator(char *str, const int len)
|
||||||
const char *int2str(const int n, char *buff, const bool thousands_separator)
|
const char *int2str(const int n, char *buff, const bool thousands_separator)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
len = sprintf(buff, "%d", n);
|
len = fc_ltostr(n, buff);
|
||||||
if (thousands_separator)
|
if (thousands_separator)
|
||||||
{
|
{
|
||||||
add_thousands_separator(buff, len);
|
add_thousands_separator(buff, len);
|
||||||
|
|
@ -3302,7 +3243,7 @@ const char *int2str(const int n, char *buff, const bool thousands_separator)
|
||||||
const char *long2str(const int64_t n, char *buff, const bool thousands_separator)
|
const char *long2str(const int64_t n, char *buff, const bool thousands_separator)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
len = sprintf(buff, "%"PRId64, n);
|
len = fc_ltostr(n, buff);
|
||||||
if (thousands_separator)
|
if (thousands_separator)
|
||||||
{
|
{
|
||||||
add_thousands_separator(buff, len);
|
add_thousands_separator(buff, len);
|
||||||
|
|
@ -3310,6 +3251,110 @@ const char *long2str(const int64_t n, char *buff, const bool thousands_separator
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int format_bytes_string(const int64_t input_bytes,
|
||||||
|
const int64_t unit_bytes, char *buff)
|
||||||
|
{
|
||||||
|
int64_t remain;
|
||||||
|
int n;
|
||||||
|
int fragment;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
n = input_bytes / unit_bytes;
|
||||||
|
remain = input_bytes - (n * unit_bytes);
|
||||||
|
if (n < 10)
|
||||||
|
{
|
||||||
|
fragment = (remain * 10LL + unit_bytes / 2) / unit_bytes;
|
||||||
|
if (fragment == 10)
|
||||||
|
{
|
||||||
|
++n;
|
||||||
|
fragment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buff + fc_itoa(n, buff);
|
||||||
|
if (n < 10)
|
||||||
|
{
|
||||||
|
*p++ = '.';
|
||||||
|
p += fc_itoa(fragment, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (remain >= unit_bytes / 2)
|
||||||
|
{
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
p = buff + fc_itoa(n, buff);
|
||||||
|
}
|
||||||
|
return p - buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *bytes_to_human_str(const int64_t bytes, char *buff)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (bytes < FC_BYTES_ONE_TB)
|
||||||
|
{
|
||||||
|
if (bytes < FC_BYTES_ONE_MB)
|
||||||
|
{
|
||||||
|
if (bytes < FC_BYTES_ONE_KB)
|
||||||
|
{
|
||||||
|
p = buff + fc_itoa(bytes, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = ' '; //for alignment
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = buff + format_bytes_string(bytes, FC_BYTES_ONE_KB, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = 'K';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bytes < FC_BYTES_ONE_GB)
|
||||||
|
{
|
||||||
|
p = buff + format_bytes_string(bytes, FC_BYTES_ONE_MB, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = 'M';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = buff + format_bytes_string(bytes, FC_BYTES_ONE_GB, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = 'G';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (bytes < FC_BYTES_ONE_EB)
|
||||||
|
{
|
||||||
|
if (bytes < FC_BYTES_ONE_PB)
|
||||||
|
{
|
||||||
|
p = buff + format_bytes_string(bytes, FC_BYTES_ONE_TB, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = 'T';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = buff + format_bytes_string(bytes, FC_BYTES_ONE_PB, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = 'P';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = buff + format_bytes_string(bytes, FC_BYTES_ONE_EB, buff);
|
||||||
|
*p++ = ' ';
|
||||||
|
*p++ = 'E';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p++ = 'B';
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
|
||||||
bool starts_with(const char *str, const char *needle)
|
bool starts_with(const char *str, const char *needle)
|
||||||
{
|
{
|
||||||
int str_len;
|
int str_len;
|
||||||
|
|
@ -3413,6 +3458,77 @@ char *format_http_date(time_t t, BufferInfo *buffer)
|
||||||
return buffer->buff;
|
return buffer->buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int shorten_path(char *filepath, const int len)
|
||||||
|
{
|
||||||
|
char src_path[PATH_MAX];
|
||||||
|
char *up_path;
|
||||||
|
char *src;
|
||||||
|
char *dest;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
if (strstr(filepath, "//") == NULL &&
|
||||||
|
strstr(filepath, "/.") == NULL &&
|
||||||
|
strstr(filepath, "/..") == NULL)
|
||||||
|
{
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > sizeof(src_path)) {
|
||||||
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
|
"filename length: %d exceeds PATH_MAX: %d",
|
||||||
|
__LINE__, len, (int)sizeof(src_path));
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(src_path, filepath, len + 1);
|
||||||
|
end = src_path + len;
|
||||||
|
src = src_path;
|
||||||
|
dest = filepath;
|
||||||
|
while (src < end) {
|
||||||
|
while (src < end && *src != '/') {
|
||||||
|
*dest++ = *src++;
|
||||||
|
}
|
||||||
|
if (src == end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip continuous slashes
|
||||||
|
do {
|
||||||
|
++src;
|
||||||
|
} while (src < end && *src == '/');
|
||||||
|
|
||||||
|
*dest++ = '/'; //keep the slash
|
||||||
|
while (src < end && *src == '.') {
|
||||||
|
if (*(src + 1) == '/' || *(src + 1) == '\0') {
|
||||||
|
/* ignore subdir "./" */
|
||||||
|
src += 2;
|
||||||
|
} else if ((*(src + 1) == '.') && (*(src + 2) == '/' ||
|
||||||
|
*(src + 2) == '\0'))
|
||||||
|
{
|
||||||
|
/* up one level for subdir "../" */
|
||||||
|
if (dest - filepath > 1) {
|
||||||
|
up_path = (char *)fc_memrchr(filepath,
|
||||||
|
'/', dest - filepath - 1);
|
||||||
|
if (up_path != NULL) {
|
||||||
|
dest = up_path + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
src += 3;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip continuous slashes
|
||||||
|
while (src < end && *src == '/') {
|
||||||
|
++src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = '\0';
|
||||||
|
return dest - filepath;
|
||||||
|
}
|
||||||
|
|
||||||
int normalize_path(const string_t *from, const string_t *filename,
|
int normalize_path(const string_t *from, const string_t *filename,
|
||||||
char *full_filename, const int size)
|
char *full_filename, const int size)
|
||||||
{
|
{
|
||||||
|
|
@ -3424,6 +3540,7 @@ int normalize_path(const string_t *from, const string_t *filename,
|
||||||
string_t true_filename;
|
string_t true_filename;
|
||||||
int up_count;
|
int up_count;
|
||||||
int path_len;
|
int path_len;
|
||||||
|
int len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (IS_FILE_RESOURCE_EX(filename)) {
|
if (IS_FILE_RESOURCE_EX(filename)) {
|
||||||
|
|
@ -3433,8 +3550,9 @@ int normalize_path(const string_t *from, const string_t *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*filename->str == '/') {
|
if (*filename->str == '/') {
|
||||||
return snprintf(full_filename, size, "%.*s",
|
len = snprintf(full_filename, size, "%.*s",
|
||||||
filename->len, filename->str);
|
filename->len, filename->str);
|
||||||
|
return shorten_path(full_filename, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from == NULL) {
|
if (from == NULL) {
|
||||||
|
|
@ -3497,14 +3615,16 @@ int normalize_path(const string_t *from, const string_t *filename,
|
||||||
}
|
}
|
||||||
path_len = last - from->str;
|
path_len = last - from->str;
|
||||||
}
|
}
|
||||||
return snprintf(full_filename, size, "%.*s/%.*s",
|
len = snprintf(full_filename, size, "%.*s/%.*s",
|
||||||
path_len, from->str, (int)(end - start), start);
|
path_len, from->str, (int)(end - start), start);
|
||||||
|
return shorten_path(full_filename, len);
|
||||||
} else {
|
} else {
|
||||||
logWarning("file: "__FILE__", line: %d, "
|
logWarning("file: "__FILE__", line: %d, "
|
||||||
"no \"/\" in the from filename: %.*s",
|
"no \"/\" in the from filename: %.*s",
|
||||||
__LINE__, from->len, from->str);
|
__LINE__, from->len, from->str);
|
||||||
return snprintf(full_filename, size, "%.*s",
|
len = snprintf(full_filename, size, "%.*s",
|
||||||
filename->len, filename->str);
|
filename->len, filename->str);
|
||||||
|
return shorten_path(full_filename, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3983,7 +4103,7 @@ int fc_get_last_line(const char *filename, char *buff,
|
||||||
int fc_get_last_lines(const char *filename, char *buff,
|
int fc_get_last_lines(const char *filename, char *buff,
|
||||||
const int buff_size, string_t *lines, int *count)
|
const int buff_size, string_t *lines, int *count)
|
||||||
{
|
{
|
||||||
int64_t file_size;
|
int64_t file_size = 0;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
int64_t read_bytes;
|
int64_t read_bytes;
|
||||||
int remain_len;
|
int remain_len;
|
||||||
|
|
@ -4197,15 +4317,13 @@ int fc_safe_write_file_init(SafeWriteFileInfo *fi,
|
||||||
{
|
{
|
||||||
char full_filename[PATH_MAX];
|
char full_filename[PATH_MAX];
|
||||||
|
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s/%s",
|
fc_combine_full_filename(file_path, redo_filename, full_filename);
|
||||||
file_path, redo_filename);
|
|
||||||
if ((fi->filename=fc_strdup(full_filename)) == NULL)
|
if ((fi->filename=fc_strdup(full_filename)) == NULL)
|
||||||
{
|
{
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(full_filename, sizeof(full_filename), "%s/%s",
|
fc_combine_full_filename(file_path, tmp_filename, full_filename);
|
||||||
file_path, tmp_filename);
|
|
||||||
if ((fi->tmp_filename=fc_strdup(full_filename)) == NULL)
|
if ((fi->tmp_filename=fc_strdup(full_filename)) == NULL)
|
||||||
{
|
{
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
@ -4287,3 +4405,121 @@ int fc_itoa(int64_t n, char *buff)
|
||||||
}
|
}
|
||||||
return (start - buff) + len;
|
return (start - buff) + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fc_ftoa(double d, const int scale, char *buff)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
bool positive;
|
||||||
|
int64_t n;
|
||||||
|
double fraction;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
positive = (d >= 0.00);
|
||||||
|
switch (scale)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
d += (positive ? 5e-1 : -5e-1);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
d += (positive ? 5e-2 : -5e-2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
d += (positive ? 5e-3 : -5e-3);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
d += (positive ? 5e-4 : -5e-4);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
d += (positive ? 5e-5 : -5e-5);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
d += (positive ? 5e-6 : -5e-6);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
d += (positive ? 5e-7 : -5e-7);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
d += (positive ? 5e-8 : -5e-8);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
d += (positive ? 5e-9 : -5e-9);
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
d += (positive ? 5e-10 : -5e-10);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
d += (positive ? 5e-11 : -5e-11);
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
d += (positive ? 5e-12 : -5e-12);
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
d += (positive ? 5e-13 : -5e-13);
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
d += (positive ? 5e-14 : -5e-14);
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
d += (positive ? 5e-15 : -5e-15);
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
d += (positive ? 5e-16 : -5e-16);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
d += (positive ? 5e-17 : -5e-17);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
d += (positive ? 5e-18 : -5e-18);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = (int64_t)d;
|
||||||
|
if (n > -10 && n < 10)
|
||||||
|
{
|
||||||
|
if (positive)
|
||||||
|
{
|
||||||
|
*buff = '0' + n;
|
||||||
|
len = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*buff = '-';
|
||||||
|
*(buff+1) = '0' + (-1) * n;
|
||||||
|
len = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
len = fc_itoa(n, buff);
|
||||||
|
}
|
||||||
|
if (scale <= 0)
|
||||||
|
{
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buff + len;
|
||||||
|
*p++ = '.';
|
||||||
|
if (positive)
|
||||||
|
{
|
||||||
|
fraction = d - (double)n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fraction = (double)n - d;
|
||||||
|
}
|
||||||
|
for (i=0; i<scale; i++)
|
||||||
|
{
|
||||||
|
fraction *= 10;
|
||||||
|
n = (int)fraction;
|
||||||
|
fraction -= n;
|
||||||
|
*p++ = '0' + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fc_compare_int64_ptr(const int64_t *n1, const int64_t *n2)
|
||||||
|
{
|
||||||
|
return fc_compare_int64(*n1, *n2);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern bool g_set_cloexec;
|
extern bool g_set_cloexec;
|
||||||
|
extern const char *g_lower_hex_chars;
|
||||||
|
extern const char *g_upper_hex_chars;
|
||||||
|
|
||||||
static inline void fc_enable_fd_cloexec(const bool cloexec)
|
static inline void fc_enable_fd_cloexec(const bool cloexec)
|
||||||
{
|
{
|
||||||
|
|
@ -196,14 +198,24 @@ void printBuffHex(const char *s, const int len);
|
||||||
* buff: the buffer, at least 2 bytes space, no tail \0
|
* buff: the buffer, at least 2 bytes space, no tail \0
|
||||||
* return: none
|
* return: none
|
||||||
*/
|
*/
|
||||||
void short2buff(const short n, char *buff);
|
static inline void short2buff(const short n, char *buff)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = (n >> 8) & 0xFF;
|
||||||
|
*p++ = n & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
/** buffer convert to 16 bits int
|
/** buffer convert to 16 bits int
|
||||||
* parameters:
|
* parameters:
|
||||||
* buff: big-endian 2 bytes buffer
|
* buff: big-endian 2 bytes buffer
|
||||||
* return: 16 bits int value
|
* return: 16 bits int value
|
||||||
*/
|
*/
|
||||||
short buff2short(const char *buff);
|
static inline short buff2short(const char *buff)
|
||||||
|
{
|
||||||
|
return (short)((((unsigned char)(*(buff))) << 8) |
|
||||||
|
((unsigned char)(*(buff+1))));
|
||||||
|
}
|
||||||
|
|
||||||
/** 32 bits int convert to buffer (big-endian)
|
/** 32 bits int convert to buffer (big-endian)
|
||||||
* parameters:
|
* parameters:
|
||||||
|
|
@ -211,14 +223,28 @@ short buff2short(const char *buff);
|
||||||
* buff: the buffer, at least 4 bytes space, no tail \0
|
* buff: the buffer, at least 4 bytes space, no tail \0
|
||||||
* return: none
|
* return: none
|
||||||
*/
|
*/
|
||||||
void int2buff(const int n, char *buff);
|
static inline void int2buff(const int n, char *buff)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = (n >> 24) & 0xFF;
|
||||||
|
*p++ = (n >> 16) & 0xFF;
|
||||||
|
*p++ = (n >> 8) & 0xFF;
|
||||||
|
*p++ = n & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
/** buffer convert to 32 bits int
|
/** buffer convert to 32 bits int
|
||||||
* parameters:
|
* parameters:
|
||||||
* buff: big-endian 4 bytes buffer
|
* buff: big-endian 4 bytes buffer
|
||||||
* return: 32 bits int value
|
* return: 32 bits int value
|
||||||
*/
|
*/
|
||||||
int buff2int(const char *buff);
|
static inline int buff2int(const char *buff)
|
||||||
|
{
|
||||||
|
return (((unsigned char)(*buff)) << 24) |
|
||||||
|
(((unsigned char)(*(buff+1))) << 16) |
|
||||||
|
(((unsigned char)(*(buff+2))) << 8) |
|
||||||
|
((unsigned char)(*(buff+3)));
|
||||||
|
}
|
||||||
|
|
||||||
/** long (64 bits) convert to buffer (big-endian)
|
/** long (64 bits) convert to buffer (big-endian)
|
||||||
* parameters:
|
* parameters:
|
||||||
|
|
@ -226,15 +252,38 @@ int buff2int(const char *buff);
|
||||||
* buff: the buffer, at least 8 bytes space, no tail \0
|
* buff: the buffer, at least 8 bytes space, no tail \0
|
||||||
* return: none
|
* return: none
|
||||||
*/
|
*/
|
||||||
void long2buff(int64_t n, char *buff);
|
static inline void long2buff(int64_t n, char *buff)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = (n >> 56) & 0xFF;
|
||||||
|
*p++ = (n >> 48) & 0xFF;
|
||||||
|
*p++ = (n >> 40) & 0xFF;
|
||||||
|
*p++ = (n >> 32) & 0xFF;
|
||||||
|
*p++ = (n >> 24) & 0xFF;
|
||||||
|
*p++ = (n >> 16) & 0xFF;
|
||||||
|
*p++ = (n >> 8) & 0xFF;
|
||||||
|
*p++ = n & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
/** buffer convert to 64 bits int
|
/** buffer convert to 64 bits int
|
||||||
* parameters:
|
* parameters:
|
||||||
* buff: big-endian 8 bytes buffer
|
* buff: big-endian 8 bytes buffer
|
||||||
* return: 64 bits int value
|
* return: 64 bits int value
|
||||||
*/
|
*/
|
||||||
int64_t buff2long(const char *buff);
|
static inline int64_t buff2long(const char *buff)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
return (((int64_t)(*p)) << 56) |
|
||||||
|
(((int64_t)(*(p+1))) << 48) |
|
||||||
|
(((int64_t)(*(p+2))) << 40) |
|
||||||
|
(((int64_t)(*(p+3))) << 32) |
|
||||||
|
(((int64_t)(*(p+4))) << 24) |
|
||||||
|
(((int64_t)(*(p+5))) << 16) |
|
||||||
|
(((int64_t)(*(p+6))) << 8) |
|
||||||
|
((int64_t)(*(p+7)));
|
||||||
|
}
|
||||||
|
|
||||||
/** 32 bits float convert to buffer (big-endian)
|
/** 32 bits float convert to buffer (big-endian)
|
||||||
* parameters:
|
* parameters:
|
||||||
|
|
@ -292,6 +341,154 @@ static inline double buff2double(const char *buff)
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int padding_hex(char *buff, const int len, const int padding_len)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
char *end;
|
||||||
|
char *stop;
|
||||||
|
int new_len;
|
||||||
|
int fill_len;
|
||||||
|
|
||||||
|
if (padding_len == len) {
|
||||||
|
return len;
|
||||||
|
} else if (padding_len > len) {
|
||||||
|
fill_len = padding_len - len;
|
||||||
|
memmove(buff + fill_len, buff, len + 1);
|
||||||
|
memset(buff, '0', fill_len);
|
||||||
|
return padding_len;
|
||||||
|
} else if (*buff != '0') {
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = buff + len;
|
||||||
|
if (padding_len <= 0) {
|
||||||
|
stop = end - 1;
|
||||||
|
} else {
|
||||||
|
stop = end - padding_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buff + 1;
|
||||||
|
while (p < stop && *p == '0') {
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_len = end - p;
|
||||||
|
memmove(buff, p, new_len + 1);
|
||||||
|
return new_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int short2hex(const short n, char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 12) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 8) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 4) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[n & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
return padding_hex(buff, 4, padding_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int short2HEX(const short n, char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 12) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 8) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 4) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[n & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
return padding_hex(buff, 4, padding_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int int2hex(const int n, char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 28) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 24) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 20) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 16) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 12) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 8) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 4) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[n & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
return padding_hex(buff, 8, padding_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int int2HEX(const int n, char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 28) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 24) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 20) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 16) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 12) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 8) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 4) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[n & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
return padding_hex(buff, 8, padding_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int long2hex(const int64_t n,
|
||||||
|
char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 60) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 56) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 52) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 48) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 44) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 40) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 36) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 32) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 28) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 24) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 20) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 16) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 12) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 8) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[(n >> 4) & 0x0F];
|
||||||
|
*p++ = g_lower_hex_chars[n & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
return padding_hex(buff, 16, padding_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int long2HEX(const int64_t n,
|
||||||
|
char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
p = (unsigned char *)buff;
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 60) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 56) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 52) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 48) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 44) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 40) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 36) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 32) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 28) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 24) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 20) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 16) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 12) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 8) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[(n >> 4) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[n & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
return padding_hex(buff, 16, padding_len);
|
||||||
|
}
|
||||||
|
|
||||||
/** trim leading spaces ( \t\r\n)
|
/** trim leading spaces ( \t\r\n)
|
||||||
* parameters:
|
* parameters:
|
||||||
* pStr: the string to trim
|
* pStr: the string to trim
|
||||||
|
|
@ -777,6 +974,8 @@ int set_run_by(const char *group_name, const char *username);
|
||||||
*/
|
*/
|
||||||
int cmp_by_ip_addr_t(const void *p1, const void *p2);
|
int cmp_by_ip_addr_t(const void *p1, const void *p2);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@ -992,6 +1191,8 @@ static inline const char *long_to_comma_str(const int64_t n, char *buff)
|
||||||
return long2str(n, buff, true);
|
return long2str(n, buff, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *bytes_to_human_str(const int64_t bytes, char *buff);
|
||||||
|
|
||||||
/** if the string starts with the needle string
|
/** if the string starts with the needle string
|
||||||
* parameters:
|
* parameters:
|
||||||
* str: the string to detect
|
* str: the string to detect
|
||||||
|
|
@ -1089,6 +1290,190 @@ static inline int resolve_path(const char *from, const char *filename,
|
||||||
size, NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS);
|
size, NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int fc_combine_two_strings_ex(
|
||||||
|
const char *first_str, const int first_len,
|
||||||
|
const char *second_str, const int second_len,
|
||||||
|
const char seperator, char *combined_str, const int size)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (first_len + 1 + second_len >= size) {
|
||||||
|
return snprintf(combined_str, size, "%s%c%s",
|
||||||
|
first_str, seperator, second_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(combined_str, first_str, first_len);
|
||||||
|
p = combined_str + first_len;
|
||||||
|
if (seperator != '\0') {
|
||||||
|
*p++ = seperator;
|
||||||
|
}
|
||||||
|
memcpy(p, second_str, second_len);
|
||||||
|
p += second_len;
|
||||||
|
*p = '\0';
|
||||||
|
return p - combined_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fc_combine_two_strings_s(first, second, seperator, combined, size) \
|
||||||
|
fc_combine_two_strings_ex(first, strlen(first), second, strlen(second), \
|
||||||
|
seperator, combined, size)
|
||||||
|
|
||||||
|
#define fc_combine_two_strings(first, second, seperator, combined) \
|
||||||
|
fc_combine_two_strings_s(first, second, seperator, \
|
||||||
|
combined, sizeof(combined))
|
||||||
|
|
||||||
|
#define fc_concat_two_strings(first, second, combined) \
|
||||||
|
fc_combine_two_strings(first, second, '\0', combined)
|
||||||
|
|
||||||
|
static inline int fc_get_full_filename_ex(
|
||||||
|
const char *base_path_str, const int base_path_len,
|
||||||
|
const char *filename_str, const int filename_len,
|
||||||
|
char *full_filename, const int size)
|
||||||
|
{
|
||||||
|
const char seperator = '/';
|
||||||
|
return fc_combine_two_strings_ex(base_path_str, base_path_len,
|
||||||
|
filename_str, filename_len, seperator, full_filename, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fc_get_full_filename(base_path_str, base_path_len, \
|
||||||
|
filename_str, filename_len, full_filename) \
|
||||||
|
fc_get_full_filename_ex(base_path_str, base_path_len, \
|
||||||
|
filename_str, filename_len, full_filename, sizeof(full_filename))
|
||||||
|
|
||||||
|
#define fc_combine_full_filename(base_path, filename, full_filename) \
|
||||||
|
fc_get_full_filename(base_path, strlen(base_path), \
|
||||||
|
filename, strlen(filename), full_filename)
|
||||||
|
|
||||||
|
#define fc_get_full_filepath_ex(base_path_str, base_path_len, \
|
||||||
|
filepath_str, filepath_len, full_filename, size) \
|
||||||
|
fc_get_full_filename_ex(base_path_str, base_path_len, \
|
||||||
|
filepath_str, filepath_len, full_filename, size)
|
||||||
|
|
||||||
|
#define fc_get_full_filepath(base_path_str, base_path_len, \
|
||||||
|
filepath_str, filepath_len, full_filename) \
|
||||||
|
fc_get_full_filename(base_path_str, base_path_len, \
|
||||||
|
filepath_str, filepath_len, full_filename)
|
||||||
|
|
||||||
|
#define fc_combine_full_filepath(base_path, filepath, full_filename) \
|
||||||
|
fc_combine_full_filename(base_path, filepath, full_filename)
|
||||||
|
|
||||||
|
static inline int fc_get_hex_subdir_filepath(const char *base_path,
|
||||||
|
const int base_len, const int subdir_index, char *file_path)
|
||||||
|
{
|
||||||
|
const int padding_len = 2;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
memcpy(file_path, base_path, base_len);
|
||||||
|
p = file_path + base_len;
|
||||||
|
*p++ = '/';
|
||||||
|
if (subdir_index <= UINT8_MAX) {
|
||||||
|
*p++ = g_upper_hex_chars[(subdir_index >> 4) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[subdir_index & 0x0F];
|
||||||
|
*p = '\0';
|
||||||
|
} else {
|
||||||
|
if (subdir_index <= UINT16_MAX) {
|
||||||
|
p += short2HEX(subdir_index, p, padding_len);
|
||||||
|
} else {
|
||||||
|
p += int2HEX(subdir_index, p, padding_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fc_get_two_subdirs_full_filepath_ex(
|
||||||
|
const char *base_path, const int base_len,
|
||||||
|
const char *subdir_str1, const int subdir_len1,
|
||||||
|
const char *subdir_str2, const int subdir_len2,
|
||||||
|
char *file_path, const int size)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (base_len + 1 + subdir_len1 + 1 + subdir_len2 >= size) {
|
||||||
|
return snprintf(file_path, size, "%s/%s/%s",
|
||||||
|
base_path, subdir_str1, subdir_str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(file_path, base_path, base_len);
|
||||||
|
p = file_path + base_len;
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, subdir_str1, subdir_len1);
|
||||||
|
p += subdir_len1;
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, subdir_str2, subdir_len2);
|
||||||
|
p += subdir_len2;
|
||||||
|
*p = '\0';
|
||||||
|
return p - file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fc_get_two_subdirs_full_filepath(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, file_path) \
|
||||||
|
fc_get_two_subdirs_full_filepath_ex(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
file_path, sizeof(file_path))
|
||||||
|
|
||||||
|
#define fc_get_one_subdir_full_filename_ex(base_path, base_len, subdir_str, \
|
||||||
|
subdir_len, filename_str, filename_len, full_filename, size) \
|
||||||
|
fc_get_two_subdirs_full_filepath_ex(base_path, base_len, \
|
||||||
|
subdir_str, subdir_len, filename_str, filename_len, \
|
||||||
|
full_filename, size)
|
||||||
|
|
||||||
|
#define fc_get_one_subdir_full_filename(base_path, base_len, subdir_str, \
|
||||||
|
subdir_len, filename_str, filename_len, full_filename) \
|
||||||
|
fc_get_one_subdir_full_filename_ex(base_path, base_len, \
|
||||||
|
subdir_str, subdir_len, filename_str, filename_len, \
|
||||||
|
full_filename, sizeof(full_filename))
|
||||||
|
|
||||||
|
static inline int fc_get_three_subdirs_full_filepath_ex(
|
||||||
|
const char *base_path, const int base_len,
|
||||||
|
const char *subdir_str1, const int subdir_len1,
|
||||||
|
const char *subdir_str2, const int subdir_len2,
|
||||||
|
const char *subdir_str3, const int subdir_len3,
|
||||||
|
char *file_path, const int size)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (base_len + 1 + subdir_len1 + 1 + subdir_len2 + subdir_len3 >= size) {
|
||||||
|
return snprintf(file_path, size, "%s/%s/%s/%s",
|
||||||
|
base_path, subdir_str1, subdir_str2, subdir_str3);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(file_path, base_path, base_len);
|
||||||
|
p = file_path + base_len;
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, subdir_str1, subdir_len1);
|
||||||
|
p += subdir_len1;
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, subdir_str2, subdir_len2);
|
||||||
|
p += subdir_len2;
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, subdir_str3, subdir_len3);
|
||||||
|
p += subdir_len3;
|
||||||
|
*p = '\0';
|
||||||
|
return p - file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fc_get_three_subdirs_full_filepath(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
subdir_str3, subdir_len3, file_path) \
|
||||||
|
fc_get_three_subdirs_full_filepath_ex(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
subdir_str3, subdir_len3, file_path, sizeof(file_path))
|
||||||
|
|
||||||
|
#define fc_get_two_subdirs_full_filename_ex(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
filename_str, filename_len, full_filename, size) \
|
||||||
|
fc_get_three_subdirs_full_filepath_ex(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
filename_str, filename_len, full_filename, size)
|
||||||
|
|
||||||
|
#define fc_get_two_subdirs_full_filename(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
filename_str, filename_len, full_filename) \
|
||||||
|
fc_get_two_subdirs_full_filename_ex(base_path, base_len, \
|
||||||
|
subdir_str1, subdir_len1, subdir_str2, subdir_len2, \
|
||||||
|
filename_str, filename_len, full_filename, sizeof(full_filename))
|
||||||
|
|
||||||
|
|
||||||
/** get gzip command full filename
|
/** get gzip command full filename
|
||||||
* return: the gzip command full filename
|
* return: the gzip command full filename
|
||||||
*/
|
*/
|
||||||
|
|
@ -1218,12 +1603,82 @@ bool fc_path_contains(const string_t *path, const string_t *needle,
|
||||||
|
|
||||||
/** itoa output as decimal number
|
/** itoa output as decimal number
|
||||||
* parameters:
|
* parameters:
|
||||||
* n: the number to convert
|
* n: the integer number to convert
|
||||||
* buff: store the converted string
|
* buff: store the converted string, NOT null-terminated
|
||||||
* return: string length
|
* return: converted string length
|
||||||
*/
|
*/
|
||||||
int fc_itoa(int64_t n, char *buff);
|
int fc_itoa(int64_t n, char *buff);
|
||||||
|
|
||||||
|
/** ftoa output as decimal number
|
||||||
|
* parameters:
|
||||||
|
* d: the double number to convert
|
||||||
|
* scale: number of decimal places (round off)
|
||||||
|
* buff: store the converted string, NOT null-terminated
|
||||||
|
* return: converted string length
|
||||||
|
*/
|
||||||
|
int fc_ftoa(double d, const int scale, char *buff);
|
||||||
|
|
||||||
|
/** output as decimal number
|
||||||
|
* parameters:
|
||||||
|
* n: the integer number to convert
|
||||||
|
* buff: store the converted string, null-terminated
|
||||||
|
* padding_len: padding length (padding with charactor '0')
|
||||||
|
* return: converted string length
|
||||||
|
*/
|
||||||
|
static inline int fc_ltostr_ex(int64_t n, char *buff, const int padding_len)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int fill_len;
|
||||||
|
|
||||||
|
len = fc_itoa(n, buff);
|
||||||
|
*(buff + len) = '\0';
|
||||||
|
if (padding_len <= len) {
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_LINUX) && defined(__GNUC__) && __GNUC__ >= 8
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fill_len = padding_len - len;
|
||||||
|
memmove(buff + fill_len, buff, len + 1);
|
||||||
|
memset(buff, '0', fill_len);
|
||||||
|
|
||||||
|
#if defined(OS_LINUX) && defined(__GNUC__) && __GNUC__ >= 8
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return padding_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fc_ltostr(int64_t n, char *buff)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = fc_itoa(n, buff);
|
||||||
|
*(buff + len) = '\0';
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t fc_strlcpy(char *dest, const char *src, const size_t size)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = strlen(src);
|
||||||
|
if (len < size) {
|
||||||
|
memcpy(dest, src, len + 1);
|
||||||
|
} else {
|
||||||
|
len = size - 1;
|
||||||
|
memcpy(dest, src, len);
|
||||||
|
*(dest + len) = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define fc_safe_strcpy(dest, src) fc_strlcpy(dest, src, sizeof(dest))
|
||||||
|
|
||||||
/** sleep in microseconds
|
/** sleep in microseconds
|
||||||
* parameters:
|
* parameters:
|
||||||
* microseconds: microseconds to sleep
|
* microseconds: microseconds to sleep
|
||||||
|
|
|
||||||
|
|
@ -1194,53 +1194,62 @@ char *getHostnameByIp(const char *szIpAddr, char *buff, const int bufferSize)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf(buff, bufferSize, "%s", ent->h_name);
|
fc_strlcpy(buff, ent->h_name, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
|
in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
|
||||||
const int bufferSize, short *af)
|
const int bufferSize, uint8_t *af)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res, *p;
|
struct addrinfo hints, *res, *p;
|
||||||
struct in_addr addr4;
|
struct in_addr addr4;
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
in_addr_64_t ip_addr;
|
in_addr_64_t ip_addr;
|
||||||
|
|
||||||
if ((*name >= '0' && *name <= '9') &&
|
if (strchr(name, ':') != NULL) //IPv6
|
||||||
|
{
|
||||||
|
if (strchr(name, '%') == NULL &&
|
||||||
|
inet_pton(AF_INET6, name, &addr6) == 1)
|
||||||
|
{
|
||||||
|
if (buff != NULL)
|
||||||
|
{
|
||||||
|
if (inet_ntop(AF_INET6, &addr6, buff, bufferSize) == NULL)
|
||||||
|
{
|
||||||
|
*buff = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*af = AF_INET6;
|
||||||
|
return *((in_addr_64_t *)((char *)&addr6 + 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((*name >= '0' && *name <= '9') &&
|
||||||
inet_pton(AF_INET, name, &addr4) == 1)
|
inet_pton(AF_INET, name, &addr4) == 1)
|
||||||
{
|
{
|
||||||
if (buff != NULL)
|
if (buff != NULL)
|
||||||
{
|
{
|
||||||
snprintf(buff, bufferSize, "%s", name);
|
if (inet_ntop(AF_INET, &addr4, buff, bufferSize) == NULL)
|
||||||
|
{
|
||||||
|
*buff = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*af = AF_INET;
|
*af = AF_INET;
|
||||||
return addr4.s_addr;
|
return addr4.s_addr;
|
||||||
}
|
}
|
||||||
if (strchr(name, ':') != NULL && inet_pton(
|
|
||||||
AF_INET6, name, &addr6) == 1)
|
|
||||||
{
|
|
||||||
if (buff != NULL)
|
|
||||||
{
|
|
||||||
snprintf(buff, bufferSize, "%s", name);
|
|
||||||
}
|
|
||||||
*af = AF_INET6;
|
|
||||||
return *((in_addr_64_t *)((char *)&addr6 + 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
*af = AF_UNSPEC;
|
||||||
memset(&hints, 0, sizeof hints);
|
memset(&hints, 0, sizeof hints);
|
||||||
hints.ai_family = AF_UNSPEC; // 支持IPv4和IPv6
|
hints.ai_family = AF_UNSPEC;
|
||||||
if (getaddrinfo(name, NULL, &hints, &res) != 0)
|
if (getaddrinfo(name, NULL, &hints, &res) != 0)
|
||||||
{
|
{
|
||||||
*af = AF_UNSPEC;
|
|
||||||
return INADDR_NONE;
|
return INADDR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip_addr = INADDR_NONE;
|
||||||
for (p = res; p != NULL; p = p->ai_next)
|
for (p = res; p != NULL; p = p->ai_next)
|
||||||
{
|
{
|
||||||
*af = p->ai_family;
|
if (p->ai_family == AF_INET) //IPv4 address
|
||||||
if (p->ai_family == AF_INET) // 处理IPv4地址
|
|
||||||
{
|
{
|
||||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
||||||
if (buff != NULL)
|
if (buff != NULL)
|
||||||
|
|
@ -1251,11 +1260,11 @@ in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*af = p->ai_family;
|
||||||
ip_addr = ipv4->sin_addr.s_addr;
|
ip_addr = ipv4->sin_addr.s_addr;
|
||||||
freeaddrinfo(res);
|
break;
|
||||||
return ip_addr;
|
|
||||||
}
|
}
|
||||||
else if (p->ai_family == AF_INET6) // 处理IPv6地址
|
else if (p->ai_family == AF_INET6) //IPv6 address
|
||||||
{
|
{
|
||||||
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||||
if (buff != NULL)
|
if (buff != NULL)
|
||||||
|
|
@ -1272,15 +1281,14 @@ in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*af = p->ai_family;
|
||||||
ip_addr = *((in_addr_64_t *)((char *)&ipv6->sin6_addr + 8));
|
ip_addr = *((in_addr_64_t *)((char *)&ipv6->sin6_addr + 8));
|
||||||
freeaddrinfo(res);
|
continue;
|
||||||
return ip_addr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
*af = AF_UNSPEC;
|
return ip_addr;
|
||||||
return INADDR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getIpaddrsByName(const char *name,
|
int getIpaddrsByName(const char *name,
|
||||||
|
|
@ -1393,14 +1401,12 @@ int nbaccept(int sock, const int timeout, int *err_no)
|
||||||
int socketBind2(int af, int sock, const char *bind_ipaddr, const int port)
|
int socketBind2(int af, int sock, const char *bind_ipaddr, const int port)
|
||||||
{
|
{
|
||||||
sockaddr_convert_t convert;
|
sockaddr_convert_t convert;
|
||||||
char bind_ip_prompt[256];
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
memset(&convert, 0, sizeof(convert));
|
memset(&convert, 0, sizeof(convert));
|
||||||
convert.sa.addr.sa_family = af;
|
convert.sa.addr.sa_family = af;
|
||||||
if (bind_ipaddr == NULL || *bind_ipaddr == '\0')
|
if (bind_ipaddr == NULL || *bind_ipaddr == '\0')
|
||||||
{
|
{
|
||||||
*bind_ip_prompt = '\0';
|
|
||||||
if (af == AF_INET)
|
if (af == AF_INET)
|
||||||
{
|
{
|
||||||
convert.len = sizeof(convert.sa.addr4);
|
convert.len = sizeof(convert.sa.addr4);
|
||||||
|
|
@ -1420,11 +1426,15 @@ int socketBind2(int af, int sock, const char *bind_ipaddr, const int port)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
sprintf(bind_ip_prompt, "bind ip %s, ", bind_ipaddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(sock, &convert.sa.addr, convert.len) < 0)
|
if (bind(sock, &convert.sa.addr, convert.len) < 0) {
|
||||||
{
|
char bind_ip_prompt[256];
|
||||||
|
if (bind_ipaddr == NULL || *bind_ipaddr == '\0') {
|
||||||
|
*bind_ip_prompt = '\0';
|
||||||
|
} else {
|
||||||
|
sprintf(bind_ip_prompt, "bind ip %s, ", bind_ipaddr);
|
||||||
|
}
|
||||||
logError("file: "__FILE__", line: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
"%sbind port %d failed, "
|
"%sbind port %d failed, "
|
||||||
"errno: %d, error info: %s.",
|
"errno: %d, error info: %s.",
|
||||||
|
|
@ -2180,10 +2190,10 @@ int tcpprintkeepalive(int fd)
|
||||||
return errno != 0 ? errno : EINVAL;
|
return errno != 0 ? errno : EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("keepAlive=%d, keepIdle=%d, keepInterval=%d, keepCount=%d",
|
logDebug("keepAlive=%d, keepIdle=%d, keepInterval=%d, keepCount=%d",
|
||||||
keepAlive, keepIdle, keepInterval, keepCount);
|
keepAlive, keepIdle, keepInterval, keepCount);
|
||||||
#else
|
#else
|
||||||
logInfo("keepAlive=%d", keepAlive);
|
logDebug("keepAlive=%d", keepAlive);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2568,10 +2578,14 @@ static inline int formatifmac(char *buff, const int buff_size,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = buff + sprintf(buff, "%02x", *hwaddr);
|
dest = buff;
|
||||||
|
*dest++ = g_lower_hex_chars[*hwaddr >> 4];
|
||||||
|
*dest++ = g_lower_hex_chars[*hwaddr & 0x0F];
|
||||||
for (ptr=hwaddr+1; ptr<end; ptr++)
|
for (ptr=hwaddr+1; ptr<end; ptr++)
|
||||||
{
|
{
|
||||||
dest += sprintf(dest, ":%02x", *ptr);
|
*dest++ = ':';
|
||||||
|
*dest++ = g_lower_hex_chars[*ptr >> 4];
|
||||||
|
*dest++ = g_lower_hex_chars[*ptr & 0x0F];
|
||||||
}
|
}
|
||||||
return dest - buff;
|
return dest - buff;
|
||||||
}
|
}
|
||||||
|
|
@ -2620,7 +2634,7 @@ static int getifmac(FastIFConfig *config)
|
||||||
fc_trim(output);
|
fc_trim(output);
|
||||||
if (*output != '\0')
|
if (*output != '\0')
|
||||||
{
|
{
|
||||||
snprintf(config->mac, sizeof(config->mac), "%s", output);
|
fc_safe_strcpy(config->mac, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2724,7 +2738,7 @@ int getifconfigs(FastIFConfig *if_configs, const int max_count, int *count)
|
||||||
return ENOSPC;
|
return ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(config->name, "%s", ifc->ifa_name);
|
strcpy(config->name, ifc->ifa_name);
|
||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include "common_define.h"
|
#include "common_define.h"
|
||||||
|
#include "shared_func.h"
|
||||||
|
|
||||||
#define FC_NET_TYPE_NONE 0
|
#define FC_NET_TYPE_NONE 0
|
||||||
#define FC_NET_TYPE_OUTER 1 //extranet IP
|
#define FC_NET_TYPE_OUTER 1 //extranet IP
|
||||||
|
|
@ -53,16 +54,6 @@
|
||||||
|
|
||||||
#define FAST_WRITE_BUFF_SIZE (256 * 1024)
|
#define FAST_WRITE_BUFF_SIZE (256 * 1024)
|
||||||
|
|
||||||
#define FC_FORMAT_IP_ADDRESS(old_ip_addr, new_ip_addr) \
|
|
||||||
char new_ip_addr[FORMATTED_IP_SIZE]; \
|
|
||||||
do { \
|
|
||||||
if (is_ipv6_addr(old_ip_addr)) { \
|
|
||||||
sprintf(new_ip_addr, "[%s]", old_ip_addr); \
|
|
||||||
} else { \
|
|
||||||
strcpy(new_ip_addr, old_ip_addr); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
typedef struct fast_if_config {
|
typedef struct fast_if_config {
|
||||||
char name[IF_NAMESIZE]; //if name
|
char name[IF_NAMESIZE]; //if name
|
||||||
char mac[64];
|
char mac[64];
|
||||||
|
|
@ -391,12 +382,12 @@ char *getHostnameByIp(const char *szIpAddr, char *buff, const int bufferSize);
|
||||||
* return: in_addr_64_t, INADDR_NONE for fail
|
* return: in_addr_64_t, INADDR_NONE for fail
|
||||||
*/
|
*/
|
||||||
in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
|
in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
|
||||||
const int bufferSize, short *af);
|
const int bufferSize, uint8_t *af);
|
||||||
|
|
||||||
static inline in_addr_64_t getIpaddrByName(const char *name,
|
static inline in_addr_64_t getIpaddrByName(const char *name,
|
||||||
char *buff, const int bufferSize)
|
char *buff, const int bufferSize)
|
||||||
{
|
{
|
||||||
short af;
|
uint8_t af;
|
||||||
return getIpaddrByNameEx(name, buff, bufferSize, &af);
|
return getIpaddrByNameEx(name, buff, bufferSize, &af);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -719,7 +710,16 @@ static inline const char *format_ip_address(const char *ip, char *buff)
|
||||||
{
|
{
|
||||||
if (is_ipv6_addr(ip))
|
if (is_ipv6_addr(ip))
|
||||||
{
|
{
|
||||||
sprintf(buff, "[%s]", ip);
|
int ip_len;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
ip_len = strlen(ip);
|
||||||
|
p = buff;
|
||||||
|
*p++ = '[';
|
||||||
|
memcpy(p, ip, ip_len);
|
||||||
|
p += ip_len;
|
||||||
|
*p++ = ']';
|
||||||
|
*p = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -732,14 +732,26 @@ static inline const char *format_ip_address(const char *ip, char *buff)
|
||||||
static inline const char *format_ip_port(const char *ip,
|
static inline const char *format_ip_port(const char *ip,
|
||||||
const int port, char *buff)
|
const int port, char *buff)
|
||||||
{
|
{
|
||||||
if (is_ipv6_addr(ip))
|
int ip_len;
|
||||||
|
bool is_ipv6;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
is_ipv6 = is_ipv6_addr(ip);
|
||||||
|
ip_len = strlen(ip);
|
||||||
|
p = buff;
|
||||||
|
if (is_ipv6)
|
||||||
{
|
{
|
||||||
sprintf(buff, "[%s]:%u", ip, port);
|
*p++ = '[';
|
||||||
}
|
}
|
||||||
else
|
memcpy(p, ip, ip_len);
|
||||||
|
p += ip_len;
|
||||||
|
if (is_ipv6)
|
||||||
{
|
{
|
||||||
sprintf(buff, "%s:%u", ip, port);
|
*p++ = ']';
|
||||||
}
|
}
|
||||||
|
*p++ = ':';
|
||||||
|
p += fc_itoa(port, p);
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), 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 Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common_define.h"
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <linux/futex.h>
|
||||||
|
#define FUTEX(ptr, op, val) syscall(SYS_futex, ptr, op, val, NULL, NULL, 0)
|
||||||
|
#else
|
||||||
|
#include "pthread_func.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
static inline int fc_futex(int *ptr, int op, int val)
|
||||||
|
{
|
||||||
|
if (FUTEX(ptr, op, val) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return errno != 0 ? errno : EBUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int fc_spinlock_init(FCSpinlock *lock, int *cond)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
lock->cond = cond;
|
||||||
|
return pthread_spin_init(&lock->mutex, 0);
|
||||||
|
#else
|
||||||
|
return init_pthread_lock_cond_pair(&lock->lcp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void fc_spinlock_destroy(FCSpinlock *lock)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
#else
|
||||||
|
destroy_pthread_lock_cond_pair(&lock->lcp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int fc_spinlock_lock(FCSpinlock *lock)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
return pthread_spin_lock(&lock->mutex);
|
||||||
|
#else
|
||||||
|
return pthread_mutex_lock(&lock->lcp.lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int fc_spinlock_trylock(FCSpinlock *lock)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
return pthread_spin_trylock(&lock->mutex);
|
||||||
|
#else
|
||||||
|
return pthread_mutex_trylock(&lock->lcp.lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int fc_spinlock_unlock(FCSpinlock *lock)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
return pthread_spin_unlock(&lock->mutex);
|
||||||
|
#else
|
||||||
|
return pthread_mutex_unlock(&lock->lcp.lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int fc_spinlock_wait(FCSpinlock *lock, const int expected)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
int result;
|
||||||
|
int lock_ret;
|
||||||
|
|
||||||
|
if ((result=pthread_spin_unlock(&lock->mutex)) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = fc_futex(lock->cond, FUTEX_WAIT_PRIVATE, expected);
|
||||||
|
lock_ret = pthread_spin_lock(&lock->mutex);
|
||||||
|
return result == 0 ? lock_ret : result;
|
||||||
|
#else
|
||||||
|
return pthread_cond_wait(&lock->lcp.cond, &lock->lcp.lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int fc_spinlock_wake_ex(FCSpinlock *lock, const int count)
|
||||||
|
{
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
if (FUTEX(lock->cond, FUTEX_WAKE_PRIVATE, count) >= 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return errno != 0 ? errno : EBUSY;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (count == 1) {
|
||||||
|
return pthread_cond_signal(&lock->lcp.cond);
|
||||||
|
} else {
|
||||||
|
return pthread_cond_broadcast(&lock->lcp.cond);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), 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 Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FC_SPINLOCK_H
|
||||||
|
#define FC_SPINLOCK_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "common_define.h"
|
||||||
|
|
||||||
|
typedef struct fc_spinlock_t {
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
pthread_spinlock_t mutex;
|
||||||
|
int *cond;
|
||||||
|
#else
|
||||||
|
pthread_lock_cond_pair_t lcp;
|
||||||
|
#endif
|
||||||
|
} FCSpinlock;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int fc_spinlock_init(FCSpinlock *lock, int *cond);
|
||||||
|
|
||||||
|
void fc_spinlock_destroy(FCSpinlock *lock);
|
||||||
|
|
||||||
|
int fc_spinlock_lock(FCSpinlock *lock);
|
||||||
|
|
||||||
|
int fc_spinlock_trylock(FCSpinlock *lock);
|
||||||
|
|
||||||
|
int fc_spinlock_unlock(FCSpinlock *lock);
|
||||||
|
|
||||||
|
int fc_spinlock_wait(FCSpinlock *lock, const int expected);
|
||||||
|
|
||||||
|
int fc_spinlock_wake_ex(FCSpinlock *lock, const int count);
|
||||||
|
|
||||||
|
static inline int fc_spinlock_wake(FCSpinlock *lock)
|
||||||
|
{
|
||||||
|
const int count = 1;
|
||||||
|
return fc_spinlock_wake_ex(lock, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -194,11 +194,54 @@ int get_boot_time(struct timeval *boot_time)
|
||||||
|
|
||||||
#define SET_MNT_FIELDS(left, fstypename, mntfromname, mntonname) \
|
#define SET_MNT_FIELDS(left, fstypename, mntfromname, mntonname) \
|
||||||
do { \
|
do { \
|
||||||
snprintf(left.f_fstypename, sizeof(left.f_fstypename), "%s", fstypename); \
|
fc_safe_strcpy(left.f_fstypename, fstypename); \
|
||||||
snprintf(left.f_mntfromname, sizeof(left.f_mntfromname), "%s", mntfromname); \
|
fc_safe_strcpy(left.f_mntfromname, mntfromname); \
|
||||||
snprintf(left.f_mntonname, sizeof(left.f_mntonname), "%s", mntonname); \
|
fc_safe_strcpy(left.f_mntonname, mntonname); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
static int get_device_type(const char *type_name, FastDeviceType *device_type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *disk_ftypes[] = {"ext2", "ext3", "ext4", "xfs",
|
||||||
|
"btrfs", "f2fs", "jfs", "reiserfs", "nilfs", "zfs",
|
||||||
|
"ufs", "ntfs", "vfat", "udf", "romfs", "squashfs"};
|
||||||
|
const int disk_ftype_count = sizeof(disk_ftypes) / sizeof(char *);
|
||||||
|
|
||||||
|
for (i=0; i<disk_ftype_count; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(type_name, disk_ftypes[i]) == 0)
|
||||||
|
{
|
||||||
|
*device_type = fast_device_type_disk;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(type_name, "tmpfs") == 0 || strcmp(type_name, "devtmpfs") == 0
|
||||||
|
|| strcmp(type_name, "ramfs") == 0)
|
||||||
|
{
|
||||||
|
*device_type = fast_device_type_memory;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(type_name, "nfs") == 0 || strcmp(type_name, "smb") == 0 ||
|
||||||
|
strcmp(type_name, "cifs") == 0 || strcmp(type_name, "afp") == 0)
|
||||||
|
{
|
||||||
|
*device_type = fast_device_type_network;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(type_name, "fuse") == 0)
|
||||||
|
{
|
||||||
|
*device_type = fast_device_type_fuse;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*device_type = fast_device_type_unkown;
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int get_mounted_filesystems(struct fast_statfs *stats,
|
int get_mounted_filesystems(struct fast_statfs *stats,
|
||||||
const int size, int *count)
|
const int size, int *count)
|
||||||
{
|
{
|
||||||
|
|
@ -240,15 +283,14 @@ int get_mounted_filesystems(struct fast_statfs *stats,
|
||||||
mntfromname = strsep(&p, " \t");
|
mntfromname = strsep(&p, " \t");
|
||||||
mntonname = strsep(&p, " \t");
|
mntonname = strsep(&p, " \t");
|
||||||
fstypename = strsep(&p, " \t");
|
fstypename = strsep(&p, " \t");
|
||||||
|
toLowercase(fstypename);
|
||||||
snprintf(stats[*count].f_mntfromname,
|
if (get_device_type(fstypename, &stats[*count].device_type) == 0)
|
||||||
sizeof(stats[*count].f_mntfromname), "%s", mntfromname);
|
{
|
||||||
snprintf(stats[*count].f_mntonname,
|
fc_safe_strcpy(stats[*count].f_mntfromname, mntfromname);
|
||||||
sizeof(stats[*count].f_mntonname), "%s", mntonname);
|
fc_safe_strcpy(stats[*count].f_mntonname, mntonname);
|
||||||
snprintf(stats[*count].f_fstypename,
|
fc_safe_strcpy(stats[*count].f_fstypename, fstypename);
|
||||||
sizeof(stats[*count].f_fstypename), "%s", fstypename);
|
(*count)++;
|
||||||
|
}
|
||||||
(*count)++;
|
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
|
@ -279,7 +321,7 @@ int get_mounted_filesystems(struct fast_statfs *stats,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mnts = NULL;
|
mnts = NULL;
|
||||||
*count = getmntinfo(&mnts, 0);
|
*count = getmntinfo(&mnts, MNT_NOWAIT);
|
||||||
if (*count == 0)
|
if (*count == 0)
|
||||||
{
|
{
|
||||||
result = errno != 0 ? errno : EPERM;
|
result = errno != 0 ? errno : EPERM;
|
||||||
|
|
@ -306,6 +348,7 @@ int get_mounted_filesystems(struct fast_statfs *stats,
|
||||||
#ifdef HAVE_FILE_SYSTEM_ID
|
#ifdef HAVE_FILE_SYSTEM_ID
|
||||||
stats[i].f_fsid = mnts[i].f_fsid;
|
stats[i].f_fsid = mnts[i].f_fsid;
|
||||||
#endif
|
#endif
|
||||||
|
stats[i].device_type = fast_device_type_unkown;
|
||||||
SET_MNT_FIELDS(stats[i], mnts[i].f_fstypename,
|
SET_MNT_FIELDS(stats[i], mnts[i].f_fstypename,
|
||||||
mnts[i].f_mntfromname, mnts[i].f_mntonname);
|
mnts[i].f_mntfromname, mnts[i].f_mntonname);
|
||||||
}
|
}
|
||||||
|
|
@ -318,6 +361,114 @@ int get_mounted_filesystems(struct fast_statfs *stats,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_statfs_by_path(const char *path, FastStatFS *statfs)
|
||||||
|
{
|
||||||
|
#define MAX_STATFS_COUNT 256
|
||||||
|
int result;
|
||||||
|
int count;
|
||||||
|
int path_len;
|
||||||
|
int mnt_len;
|
||||||
|
int matched_len;
|
||||||
|
char resolved_path[PATH_MAX];
|
||||||
|
struct fast_statfs stats[MAX_STATFS_COUNT];
|
||||||
|
struct fast_statfs *entry;
|
||||||
|
struct fast_statfs *end;
|
||||||
|
|
||||||
|
if ((result=get_mounted_filesystems(stats, MAX_STATFS_COUNT,
|
||||||
|
&count)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realpath(path, resolved_path) == NULL)
|
||||||
|
{
|
||||||
|
return errno != 0 ? errno : ENOENT;
|
||||||
|
}
|
||||||
|
path_len = strlen(resolved_path);
|
||||||
|
matched_len = 0;
|
||||||
|
end = stats + count;
|
||||||
|
for (entry=stats; entry<end; entry++)
|
||||||
|
{
|
||||||
|
mnt_len = strlen(entry->f_mntonname);
|
||||||
|
if (mnt_len <= path_len && memcmp(resolved_path, entry->
|
||||||
|
f_mntonname, mnt_len) == 0)
|
||||||
|
{
|
||||||
|
if ((mnt_len > 1 && mnt_len < path_len) &&
|
||||||
|
*(resolved_path + mnt_len) != '/')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mnt_len > matched_len)
|
||||||
|
{
|
||||||
|
matched_len = mnt_len;
|
||||||
|
*statfs = *entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (matched_len > 0 ? 0 : ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_rotational_device_by_path(const char *path)
|
||||||
|
{
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
#define DEV_PATH_PREFIX_STR "/dev/"
|
||||||
|
#define DEV_PATH_PREFIX_LEN (sizeof(DEV_PATH_PREFIX_STR) - 1)
|
||||||
|
|
||||||
|
int result;
|
||||||
|
int fd;
|
||||||
|
int len;
|
||||||
|
FastStatFS statfs;
|
||||||
|
char resolved_path[PATH_MAX];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
char buff[8];
|
||||||
|
char *device_name;
|
||||||
|
|
||||||
|
if ((result=get_statfs_by_path(path, &statfs)) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statfs.device_type == fast_device_type_memory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(statfs.device_type == fast_device_type_disk &&
|
||||||
|
strncmp(statfs.f_mntfromname, DEV_PATH_PREFIX_STR,
|
||||||
|
DEV_PATH_PREFIX_LEN) == 0))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (realpath(statfs.f_mntfromname, resolved_path) == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (strncmp(resolved_path, DEV_PATH_PREFIX_STR,
|
||||||
|
DEV_PATH_PREFIX_LEN) != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
device_name = resolved_path + DEV_PATH_PREFIX_LEN;
|
||||||
|
sprintf(filename, "/sys/class/block/%s/queue/rotational", device_name);
|
||||||
|
if ((fd=open(filename, O_RDONLY)) < 0) {
|
||||||
|
sprintf(filename, "/sys/class/block/%s/../queue/rotational", device_name);
|
||||||
|
if ((fd=open(filename, O_RDONLY)) < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len = read(fd, buff, sizeof(buff));
|
||||||
|
close(fd);
|
||||||
|
if (len == 1 || len == 2) {
|
||||||
|
return (buff[0] != '0');
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
||||||
|
|
||||||
typedef struct fast_process_array {
|
typedef struct fast_process_array {
|
||||||
|
|
@ -617,7 +768,7 @@ int get_processes(struct fast_process_info **processes, int *count)
|
||||||
mib[0] = CTL_KERN;
|
mib[0] = CTL_KERN;
|
||||||
mib[1] = KERN_PROC;
|
mib[1] = KERN_PROC;
|
||||||
mib[2] = KERN_PROC_ALL;
|
mib[2] = KERN_PROC_ALL;
|
||||||
mib[3] = 0;
|
mib[3] = 0;
|
||||||
size = 0;
|
size = 0;
|
||||||
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
|
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
|
||||||
{
|
{
|
||||||
|
|
@ -687,8 +838,7 @@ int get_processes(struct fast_process_info **processes, int *count)
|
||||||
for (i=0; i<nproc; i++)
|
for (i=0; i<nproc; i++)
|
||||||
{
|
{
|
||||||
process->field_count = 9;
|
process->field_count = 9;
|
||||||
snprintf(process->comm, sizeof(process->comm),
|
fc_safe_strcpy(process->comm, procs[i].ki_comm);
|
||||||
"%s", procs[i].ki_comm);
|
|
||||||
process->pid = procs[i].ki_pid;
|
process->pid = procs[i].ki_pid;
|
||||||
process->ppid = procs[i].ki_ppid;
|
process->ppid = procs[i].ki_ppid;
|
||||||
process->starttime = procs[i].ki_start;
|
process->starttime = procs[i].ki_start;
|
||||||
|
|
@ -887,8 +1037,7 @@ static int get_block_size_by_write(const char *path, int *block_size)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(tmp_filename, sizeof(tmp_filename),
|
fc_combine_full_filename(path, ".blksize-test.tmp", tmp_filename);
|
||||||
"%s/.blksize-test.tmp", path);
|
|
||||||
if ((fd=open(tmp_filename, O_WRONLY | O_CREAT |
|
if ((fd=open(tmp_filename, O_WRONLY | O_CREAT |
|
||||||
O_DIRECT | O_CLOEXEC, 0755)) < 0)
|
O_DIRECT | O_CLOEXEC, 0755)) < 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,14 @@ extern "C" {
|
||||||
#define MNAMELEN 128
|
#define MNAMELEN 128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum fast_device_type {
|
||||||
|
fast_device_type_unkown = 0,
|
||||||
|
fast_device_type_disk,
|
||||||
|
fast_device_type_memory,
|
||||||
|
fast_device_type_fuse,
|
||||||
|
fast_device_type_network
|
||||||
|
} FastDeviceType;
|
||||||
|
|
||||||
typedef struct fast_statfs {
|
typedef struct fast_statfs {
|
||||||
long f_type; /* type of file system (see below) */
|
long f_type; /* type of file system (see below) */
|
||||||
long f_bsize; /* optimal transfer block size */
|
long f_bsize; /* optimal transfer block size */
|
||||||
|
|
@ -56,6 +64,7 @@ extern "C" {
|
||||||
char f_fstypename[MFSNAMELEN]; /* fs type name */
|
char f_fstypename[MFSNAMELEN]; /* fs type name */
|
||||||
char f_mntfromname[MNAMELEN]; /* mounted file system */
|
char f_mntfromname[MNAMELEN]; /* mounted file system */
|
||||||
char f_mntonname[MNAMELEN]; /* directory on which mounted */
|
char f_mntonname[MNAMELEN]; /* directory on which mounted */
|
||||||
|
FastDeviceType device_type;
|
||||||
} FastStatFS;
|
} FastStatFS;
|
||||||
|
|
||||||
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
||||||
|
|
@ -120,6 +129,23 @@ extern "C" {
|
||||||
} FastProcessInfo;
|
} FastProcessInfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline const char *get_device_type_caption(
|
||||||
|
const FastDeviceType device_type)
|
||||||
|
{
|
||||||
|
switch (device_type) {
|
||||||
|
case fast_device_type_disk:
|
||||||
|
return "disk";
|
||||||
|
case fast_device_type_memory:
|
||||||
|
return "memory";
|
||||||
|
case fast_device_type_fuse:
|
||||||
|
return "fuse";
|
||||||
|
case fast_device_type_network:
|
||||||
|
return "network";
|
||||||
|
default:
|
||||||
|
return "unkown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** get system total memory size
|
/** get system total memory size
|
||||||
* parameters:
|
* parameters:
|
||||||
* mem_size: return the total memory size
|
* mem_size: return the total memory size
|
||||||
|
|
@ -151,6 +177,21 @@ int get_boot_time(struct timeval *boot_time);
|
||||||
int get_mounted_filesystems(struct fast_statfs *stats,
|
int get_mounted_filesystems(struct fast_statfs *stats,
|
||||||
const int size, int *count);
|
const int size, int *count);
|
||||||
|
|
||||||
|
/** get statfs by path
|
||||||
|
* parameters:
|
||||||
|
* path: the path
|
||||||
|
* statfs: return the statfs
|
||||||
|
* return: error no, 0 success, != 0 fail
|
||||||
|
*/
|
||||||
|
int get_statfs_by_path(const char *path, FastStatFS *statfs);
|
||||||
|
|
||||||
|
/** is rotational device by path
|
||||||
|
* parameters:
|
||||||
|
* path: the path
|
||||||
|
* return: true for rotational device, otherwise false
|
||||||
|
*/
|
||||||
|
bool is_rotational_device_by_path(const char *path);
|
||||||
|
|
||||||
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
||||||
/** get processes
|
/** get processes
|
||||||
* parameters:
|
* parameters:
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
.SUFFIXES: .c .o
|
.SUFFIXES: .c .o
|
||||||
|
|
||||||
COMPILE = $(CC) -g -O3 -Wall -D_FILE_OFFSET_BITS=64 -g -DDEBUG_FLAG
|
COMPILE = $(CC) -g -O3 -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -g -DDEBUG_FLAG
|
||||||
INC_PATH = -I/usr/local/include
|
INC_PATH = $(INCS)
|
||||||
LIB_PATH = -lfastcommon -lpthread
|
LIB_PATH = -lfastcommon $(LIBS)
|
||||||
|
|
||||||
ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blocked_queue \
|
ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blocked_queue \
|
||||||
test_id_generator test_ini_parser test_char_convert test_char_convert_loader \
|
test_id_generator test_ini_parser test_char_convert test_char_convert_loader \
|
||||||
|
|
@ -11,13 +11,10 @@ ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blo
|
||||||
test_server_id_func test_pipe test_atomic test_file_write_hole test_file_lock \
|
test_server_id_func test_pipe test_atomic test_file_write_hole test_file_lock \
|
||||||
test_pthread_wait test_thread_pool test_data_visible test_mutex_lock_perf \
|
test_pthread_wait test_thread_pool test_data_visible test_mutex_lock_perf \
|
||||||
test_queue_perf test_normalize_path test_sorted_array test_sorted_queue \
|
test_queue_perf test_normalize_path test_sorted_array test_sorted_queue \
|
||||||
test_thread_local test_memcpy
|
test_thread_local test_memcpy test_fast_buffer mblock_benchmark cpool_benchmark
|
||||||
|
|
||||||
all: $(ALL_PRGS)
|
all: $(ALL_PRGS)
|
||||||
|
|
||||||
test_memcpy: test_memcpy.c
|
|
||||||
$(CC) -g -Wall -o $@ $< $(LIB_PATH) $(INC_PATH)
|
|
||||||
|
|
||||||
.c:
|
.c:
|
||||||
$(COMPILE) -o $@ $< $(LIB_PATH) $(INC_PATH)
|
$(COMPILE) -o $@ $< $(LIB_PATH) $(INC_PATH)
|
||||||
.c.o:
|
.c.o:
|
||||||
|
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), 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 Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "fastcommon/logger.h"
|
||||||
|
#include "fastcommon/shared_func.h"
|
||||||
|
#include "fastcommon/pthread_func.h"
|
||||||
|
#include "fastcommon/connection_pool.h"
|
||||||
|
|
||||||
|
#define USE_CONN_POOL 1
|
||||||
|
//#define USE_CAS_LOCK 1
|
||||||
|
|
||||||
|
static int thread_count = 16;
|
||||||
|
static int64_t loop_count = 10000000;
|
||||||
|
static ConnectionPool cpool;
|
||||||
|
static char buff[1024];
|
||||||
|
static pthread_mutex_t lock;
|
||||||
|
volatile int mutex = 0;
|
||||||
|
|
||||||
|
#ifndef USE_CONN_POOL
|
||||||
|
static int64_t test_var1 = 0;
|
||||||
|
static int64_t test_var2 = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void conn_pool_get_key(const ConnectionInfo *conn,
|
||||||
|
char *key, int *key_len)
|
||||||
|
{
|
||||||
|
*key_len = strlen(conn->ip_addr);
|
||||||
|
memcpy(key, conn->ip_addr, *key_len);
|
||||||
|
*(key + (*key_len)++) = '-';
|
||||||
|
*(key + (*key_len)++) = (conn->port >> 8) & 0xFF;
|
||||||
|
*(key + (*key_len)++) = conn->port & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *thread_run(void *args)
|
||||||
|
{
|
||||||
|
int thread_index;
|
||||||
|
int result;
|
||||||
|
int64_t i;
|
||||||
|
ConnectionInfo cinfo;
|
||||||
|
#ifdef USE_CONN_POOL
|
||||||
|
ConnectionInfo *conn;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
thread_index = (long)args;
|
||||||
|
printf("thread #%d start\n", thread_index);
|
||||||
|
|
||||||
|
if ((result=conn_pool_parse_server_info("127.0.0.1", &cinfo, 23000)) != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (i=0; i<loop_count; i++) {
|
||||||
|
#ifdef USE_CONN_POOL
|
||||||
|
if ((conn=conn_pool_get_connection_ex(&cpool, &cinfo,
|
||||||
|
NULL, true, &result)) == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//fc_sleep_us(1);
|
||||||
|
conn_pool_close_connection(&cpool, conn);
|
||||||
|
#else
|
||||||
|
char key_buff[INET6_ADDRSTRLEN + 8];
|
||||||
|
string_t key;
|
||||||
|
uint32_t hash_code;
|
||||||
|
for (int j=0; j<2; j++) {
|
||||||
|
key.str = key_buff;
|
||||||
|
conn_pool_get_key(&cinfo, key.str, &key.len);
|
||||||
|
hash_code = fc_simple_hash(key.str, key.len);
|
||||||
|
#ifdef USE_CAS_LOCK
|
||||||
|
while (!__sync_bool_compare_and_swap(&mutex, 0, 1)) {
|
||||||
|
sched_yield();
|
||||||
|
}
|
||||||
|
__sync_fetch_and_add(&test_var1, 1);
|
||||||
|
__sync_fetch_and_add(&test_var2, 1);
|
||||||
|
#else
|
||||||
|
PTHREAD_MUTEX_LOCK(&lock);
|
||||||
|
test_var1++;
|
||||||
|
test_var2++;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_CAS_LOCK
|
||||||
|
__sync_bool_compare_and_swap(&mutex, 1, 0);
|
||||||
|
#else
|
||||||
|
PTHREAD_MUTEX_UNLOCK(&lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == loop_count) {
|
||||||
|
printf("thread #%d done\n", thread_index);
|
||||||
|
} else {
|
||||||
|
printf("thread #%d loop count: %"PRId64"\n", thread_index, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const int stack_size = 64 * 1024;
|
||||||
|
const int connect_timeout = 2;
|
||||||
|
const int max_count_per_entry = 0;
|
||||||
|
const int max_idle_time = 3600;
|
||||||
|
const int htable_capacity = 163;
|
||||||
|
const int extra_data_size = 0;
|
||||||
|
int result;
|
||||||
|
int i;
|
||||||
|
int64_t qps;
|
||||||
|
pthread_t *tids;
|
||||||
|
pthread_attr_t thread_attr;
|
||||||
|
int64_t start_time;
|
||||||
|
int64_t end_time;
|
||||||
|
int64_t time_used;
|
||||||
|
ConnectionExtraParams params;
|
||||||
|
|
||||||
|
log_init();
|
||||||
|
g_log_context.log_level = LOG_INFO;
|
||||||
|
g_schedule_flag = true;
|
||||||
|
g_current_time = time(NULL);
|
||||||
|
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
params.tls.enabled = false;
|
||||||
|
params.tls.htable_capacity = 13;
|
||||||
|
if ((result=conn_pool_init_ex1(&cpool, connect_timeout, max_count_per_entry,
|
||||||
|
max_idle_time, htable_capacity, NULL, NULL, NULL, NULL,
|
||||||
|
extra_data_size, ¶ms)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
if ((result=init_pthread_lock(&lock)) != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((result=pthread_attr_init(&thread_attr)) != 0) {
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"call pthread_attr_init fail, "
|
||||||
|
"errno: %d, error info: %s",
|
||||||
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if ((result=pthread_attr_setstacksize(&thread_attr,
|
||||||
|
stack_size)) != 0)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"call pthread_attr_setstacksize to %d fail, "
|
||||||
|
"errno: %d, error info: %s", __LINE__,
|
||||||
|
stack_size, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
tids = fc_malloc(sizeof(pthread_t) * thread_count);
|
||||||
|
|
||||||
|
start_time = get_current_time_us();
|
||||||
|
for (i=0; i<thread_count; i++) {
|
||||||
|
if ((result=pthread_create(tids + i, &thread_attr,
|
||||||
|
thread_run, (void *)((long)i))) != 0)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"create thread failed, "
|
||||||
|
"errno: %d, error info: %s",
|
||||||
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<thread_count; i++) {
|
||||||
|
pthread_join(tids[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
end_time = get_current_time_us();
|
||||||
|
time_used = end_time - start_time;
|
||||||
|
qps = (thread_count * loop_count * 1000 * 1000) / time_used;
|
||||||
|
printf("time used: %"PRId64" ms, QPS: %"PRId64"\n", time_used / 1000, qps);
|
||||||
|
|
||||||
|
{
|
||||||
|
ConnectionPoolStat stat;
|
||||||
|
conn_pool_stat(&cpool, &stat);
|
||||||
|
printf("htable_capacity: %d, bucket_used: %d, server_count: %d, "
|
||||||
|
"connection {total_count: %d, free_count: %d}\n",
|
||||||
|
stat.htable_capacity, stat.bucket_used, stat.server_count,
|
||||||
|
stat.connection.total_count, stat.connection.free_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tids);
|
||||||
|
conn_pool_destroy(&cpool);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), 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 Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "fastcommon/logger.h"
|
||||||
|
#include "fastcommon/shared_func.h"
|
||||||
|
#include "fastcommon/pthread_func.h"
|
||||||
|
#include "fastcommon/fast_mblock.h"
|
||||||
|
|
||||||
|
static int thread_count = 4;
|
||||||
|
static int64_t loop_count = 10000000;
|
||||||
|
static struct fast_mblock_man mblock;
|
||||||
|
|
||||||
|
static void *thread_run(void *args)
|
||||||
|
{
|
||||||
|
int thread_index;
|
||||||
|
int i;
|
||||||
|
void *obj;
|
||||||
|
|
||||||
|
thread_index = (long)args;
|
||||||
|
printf("thread #%d start\n", thread_index);
|
||||||
|
|
||||||
|
for (i=0; i<loop_count; i++) {
|
||||||
|
obj = fast_mblock_alloc_object(&mblock);
|
||||||
|
fast_mblock_free_object(&mblock, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("thread #%d done\n", thread_index);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const int stack_size = 64 * 1024;
|
||||||
|
int result;
|
||||||
|
int limit;
|
||||||
|
int i;
|
||||||
|
bool continue_flag = true;
|
||||||
|
int64_t qps;
|
||||||
|
pthread_t *tids;
|
||||||
|
pthread_attr_t thread_attr;
|
||||||
|
int64_t start_time;
|
||||||
|
int64_t end_time;
|
||||||
|
int64_t time_used;
|
||||||
|
|
||||||
|
log_init();
|
||||||
|
g_log_context.log_level = LOG_DEBUG;
|
||||||
|
|
||||||
|
limit = (thread_count + 1) / 2;
|
||||||
|
fast_mblock_manager_init();
|
||||||
|
if ((result=fast_mblock_init_ex1(&mblock, "mblock", 1024,
|
||||||
|
limit, limit, NULL, NULL, true)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
fast_mblock_set_need_wait(&mblock, true, &continue_flag);
|
||||||
|
|
||||||
|
if ((result=pthread_attr_init(&thread_attr)) != 0) {
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"call pthread_attr_init fail, "
|
||||||
|
"errno: %d, error info: %s",
|
||||||
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if ((result=pthread_attr_setstacksize(&thread_attr,
|
||||||
|
stack_size)) != 0)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"call pthread_attr_setstacksize to %d fail, "
|
||||||
|
"errno: %d, error info: %s", __LINE__,
|
||||||
|
stack_size, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
tids = fc_malloc(sizeof(pthread_t) * thread_count);
|
||||||
|
|
||||||
|
start_time = get_current_time_us();
|
||||||
|
for (i=0; i<thread_count; i++) {
|
||||||
|
if ((result=pthread_create(tids + i, &thread_attr,
|
||||||
|
thread_run, (void *)((long)i))) != 0)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"create thread failed, "
|
||||||
|
"errno: %d, error info: %s",
|
||||||
|
__LINE__, result, STRERROR(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<thread_count; i++) {
|
||||||
|
pthread_join(tids[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
end_time = get_current_time_us();
|
||||||
|
time_used = end_time - start_time;
|
||||||
|
qps = (thread_count * loop_count * 1000 * 1000) / time_used;
|
||||||
|
printf("time used: %"PRId64" ms, QPS: %"PRId64"\n", time_used / 1000, qps);
|
||||||
|
|
||||||
|
free(tids);
|
||||||
|
fast_mblock_manager_stat_print(false);
|
||||||
|
fast_mblock_destroy(&mblock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,331 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 YuQing <384681@qq.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can use, redistribute, and/or modify
|
||||||
|
* it under the terms of the Lesser GNU General Public License, version 3
|
||||||
|
* or later ("LGPL"), 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 Lesser GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "fastcommon/logger.h"
|
||||||
|
#include "fastcommon/fast_buffer.h"
|
||||||
|
#include "fastcommon/sched_thread.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TEST_TYPE_NONE = 0,
|
||||||
|
TEST_TYPE_ITOA,
|
||||||
|
TEST_TYPE_FTOA,
|
||||||
|
TEST_TYPE_INT2HEX,
|
||||||
|
TEST_TYPE_APPEND
|
||||||
|
} TestType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DA_SLICE_TYPE_FILE = 'F', /* in file slice */
|
||||||
|
DA_SLICE_TYPE_CACHE = 'C', /* in memory cache */
|
||||||
|
DA_SLICE_TYPE_ALLOC = 'A' /* allocate slice (index and space allocate only) */
|
||||||
|
} DASliceType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_t version;
|
||||||
|
uint64_t trunk_id; //0 for not inited
|
||||||
|
uint32_t length; //data length
|
||||||
|
uint32_t offset; //space offset
|
||||||
|
uint32_t size; //space size
|
||||||
|
} DAPieceFieldStorage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int64_t version; //for stable sort only
|
||||||
|
uint64_t oid; //object ID
|
||||||
|
uint64_t fid; //field ID (key)
|
||||||
|
uint32_t extra; //such as slice offset
|
||||||
|
char op_type;
|
||||||
|
DASliceType slice_type;
|
||||||
|
DAPieceFieldStorage storage;
|
||||||
|
} DATrunkSpaceLogRecord;
|
||||||
|
|
||||||
|
static inline void log_pack_by_append(const DATrunkSpaceLogRecord
|
||||||
|
*record, FastBuffer *buffer, const bool have_extra_field)
|
||||||
|
{
|
||||||
|
fast_buffer_append_int64(buffer, (uint32_t)g_current_time);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->storage.version);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->oid);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->fid);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_char(buffer, record->op_type);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->storage.trunk_id);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->storage.length);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->storage.offset);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_int64(buffer, record->storage.size);
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_char(buffer, record->slice_type);
|
||||||
|
|
||||||
|
if (have_extra_field) {
|
||||||
|
fast_buffer_append_char(buffer, ' ');
|
||||||
|
fast_buffer_append_char(buffer, record->extra);
|
||||||
|
fast_buffer_append_char(buffer, '\n');
|
||||||
|
} else {
|
||||||
|
fast_buffer_append_char(buffer, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void log_pack_by_sprintf(const DATrunkSpaceLogRecord
|
||||||
|
*record, FastBuffer *buffer, const bool have_extra_field)
|
||||||
|
{
|
||||||
|
buffer->length += sprintf(buffer->data + buffer->length,
|
||||||
|
"%u %"PRId64" %"PRId64" %"PRId64" %c %"PRId64" %u %u %u %c",
|
||||||
|
(uint32_t)g_current_time, record->storage.version,
|
||||||
|
record->oid, record->fid, record->op_type,
|
||||||
|
record->storage.trunk_id, record->storage.length,
|
||||||
|
record->storage.offset, record->storage.size,
|
||||||
|
record->slice_type);
|
||||||
|
if (have_extra_field) {
|
||||||
|
buffer->length += sprintf(buffer->data + buffer->length,
|
||||||
|
" %u\n", record->extra);
|
||||||
|
} else {
|
||||||
|
*(buffer->data + buffer->length++) = '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BINLOG_FILENAME_PREFIX_STR "binlog."
|
||||||
|
#define BINLOG_FILENAME_PREFIX_LEN (sizeof(BINLOG_FILENAME_PREFIX_STR) - 1)
|
||||||
|
|
||||||
|
static inline int cache_binlog_filename_by_sprintf(
|
||||||
|
const char *data_path, const char *subdir_name,
|
||||||
|
const uint32_t subdirs, const uint64_t id,
|
||||||
|
char *full_filename, const int size)
|
||||||
|
{
|
||||||
|
int path_index;
|
||||||
|
path_index = id % subdirs;
|
||||||
|
return sprintf(full_filename, "%s/%s/%02X/%02X/%s%08"PRIX64,
|
||||||
|
data_path, subdir_name, path_index, path_index,
|
||||||
|
BINLOG_FILENAME_PREFIX_STR, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int cache_binlog_filename_by_append(
|
||||||
|
const char *data_path, const char *subdir_name,
|
||||||
|
const uint32_t subdirs, const uint64_t id,
|
||||||
|
char *full_filename, const int size)
|
||||||
|
{
|
||||||
|
int path_index;
|
||||||
|
int path_len;
|
||||||
|
int subdir_len;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
path_index = id % subdirs;
|
||||||
|
path_len = strlen(data_path);
|
||||||
|
subdir_len = strlen(subdir_name);
|
||||||
|
p = full_filename;
|
||||||
|
memcpy(p, data_path, path_len);
|
||||||
|
p += path_len;
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, subdir_name, subdir_len);
|
||||||
|
p += subdir_len;
|
||||||
|
*p++ = '/';
|
||||||
|
*p++ = g_upper_hex_chars[(path_index >> 4) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[path_index & 0x0F];
|
||||||
|
*p++ = '/';
|
||||||
|
*p++ = g_upper_hex_chars[(path_index >> 4) & 0x0F];
|
||||||
|
*p++ = g_upper_hex_chars[path_index & 0x0F];
|
||||||
|
*p++ = '/';
|
||||||
|
memcpy(p, BINLOG_FILENAME_PREFIX_STR, BINLOG_FILENAME_PREFIX_LEN);
|
||||||
|
p += BINLOG_FILENAME_PREFIX_LEN;
|
||||||
|
if (id <= UINT32_MAX) {
|
||||||
|
p += int2HEX(id, p, 8);
|
||||||
|
} else {
|
||||||
|
p += long2HEX(id, p, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p - full_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(const char *program)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [-t {itoa | ftoa | int2hex | append | all}]\n",
|
||||||
|
program);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const bool binary_mode = true;
|
||||||
|
const bool check_capacity = false;
|
||||||
|
const bool have_extra_field = false;
|
||||||
|
const int LOOP = 10 * 1000 * 1000;
|
||||||
|
const char *data_path = "/opt/fastcfs/fdir/data";
|
||||||
|
const char *subdir_name = "binlog";
|
||||||
|
const uint32_t subdirs = 256;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
TestType test_type = TEST_TYPE_ITOA;
|
||||||
|
TestType type_start;
|
||||||
|
TestType type_last;
|
||||||
|
uint64_t id = 123456;
|
||||||
|
double d = 123.456;
|
||||||
|
int ch;
|
||||||
|
int i;
|
||||||
|
int len;
|
||||||
|
int64_t start_time_us;
|
||||||
|
int convert_time_us;
|
||||||
|
int sprintf_time_us;
|
||||||
|
double ratio;
|
||||||
|
FastBuffer buffer;
|
||||||
|
DATrunkSpaceLogRecord record;
|
||||||
|
char full_filename1[PATH_MAX];
|
||||||
|
char full_filename2[PATH_MAX];
|
||||||
|
char buff[32] = {0};
|
||||||
|
char *caption;
|
||||||
|
|
||||||
|
log_init();
|
||||||
|
g_current_time = time(NULL);
|
||||||
|
if ((result=fast_buffer_init_ex(&buffer, 256,
|
||||||
|
binary_mode, check_capacity)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_start = type_last = TEST_TYPE_ITOA;
|
||||||
|
while ((ch=getopt(argc, argv, "ht:")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
case 't':
|
||||||
|
if (strcasecmp(optarg, "itoa") == 0) {
|
||||||
|
type_start = type_last = TEST_TYPE_ITOA;
|
||||||
|
} else if (strcasecmp(optarg, "ftoa") == 0) {
|
||||||
|
type_start = type_last = TEST_TYPE_FTOA;
|
||||||
|
} else if (strcasecmp(optarg, "int2hex") == 0) {
|
||||||
|
type_start = type_last = TEST_TYPE_INT2HEX;
|
||||||
|
} else if (strcasecmp(optarg, "append") == 0) {
|
||||||
|
type_start = type_last = TEST_TYPE_APPEND;
|
||||||
|
} else if (strcasecmp(optarg, "all") == 0) {
|
||||||
|
type_start = TEST_TYPE_ITOA;
|
||||||
|
type_last = TEST_TYPE_APPEND;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "invalid type: %s\n", optarg);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (test_type=type_start; test_type<=type_last; test_type++) {
|
||||||
|
if (test_type == TEST_TYPE_APPEND) {
|
||||||
|
memset(&record, 0, sizeof(record));
|
||||||
|
record.op_type = 'C';
|
||||||
|
record.slice_type = DA_SLICE_TYPE_FILE;
|
||||||
|
record.storage.version = 1111;
|
||||||
|
record.oid = 9007211709265131LL;
|
||||||
|
record.fid = 0;
|
||||||
|
record.storage.trunk_id = 61;
|
||||||
|
record.storage.length = 62;
|
||||||
|
record.storage.offset = 12345;
|
||||||
|
record.storage.size = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_time_us = get_current_time_us();
|
||||||
|
for (i=0; i<LOOP; i++) {
|
||||||
|
switch (test_type) {
|
||||||
|
case TEST_TYPE_APPEND:
|
||||||
|
cache_binlog_filename_by_sprintf(data_path, subdir_name,
|
||||||
|
subdirs, ++id, full_filename1, sizeof(full_filename1));
|
||||||
|
fast_buffer_reset(&buffer);
|
||||||
|
log_pack_by_sprintf(&record, &buffer, have_extra_field);
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_ITOA:
|
||||||
|
sprintf(buff, "%"PRId64, id);
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_FTOA:
|
||||||
|
sprintf(buff, "%.2f", d);
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_INT2HEX:
|
||||||
|
sprintf(buff, "%x", (int)id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf_time_us = (get_current_time_us() - start_time_us);
|
||||||
|
|
||||||
|
start_time_us = get_current_time_us();
|
||||||
|
for (i=0; i<LOOP; i++) {
|
||||||
|
switch (test_type) {
|
||||||
|
case TEST_TYPE_APPEND:
|
||||||
|
cache_binlog_filename_by_append(data_path, subdir_name,
|
||||||
|
subdirs, ++id, full_filename2, sizeof(full_filename2));
|
||||||
|
fast_buffer_reset(&buffer);
|
||||||
|
log_pack_by_append(&record, &buffer, have_extra_field);
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_ITOA:
|
||||||
|
len = fc_itoa(id, buff);
|
||||||
|
*(buff + len) = '\0';
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_FTOA:
|
||||||
|
len = fc_ftoa(d, 2, buff);
|
||||||
|
*(buff + len) = '\0';
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_INT2HEX:
|
||||||
|
int2hex(id, buff, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
convert_time_us = (get_current_time_us() - start_time_us);
|
||||||
|
|
||||||
|
if (convert_time_us > 0) {
|
||||||
|
ratio = (double)sprintf_time_us / (double)convert_time_us;
|
||||||
|
} else {
|
||||||
|
ratio = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (test_type) {
|
||||||
|
case TEST_TYPE_ITOA:
|
||||||
|
caption = "itoa";
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_FTOA:
|
||||||
|
caption = "ftoa";
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_INT2HEX:
|
||||||
|
caption = "int2hex";
|
||||||
|
break;
|
||||||
|
case TEST_TYPE_APPEND:
|
||||||
|
caption = "append";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
caption = "unkown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("sprintf time: %d ms, %s time: %d ms, "
|
||||||
|
"sprintf time / %s time: %d%%\n",
|
||||||
|
sprintf_time_us / 1000, caption, convert_time_us / 1000,
|
||||||
|
caption, (int)(ratio * 100.00));
|
||||||
|
}
|
||||||
|
|
||||||
|
fast_buffer_destroy(&buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include "fastcommon/logger.h"
|
#include "fastcommon/logger.h"
|
||||||
#include "fastcommon/shared_func.h"
|
#include "fastcommon/shared_func.h"
|
||||||
|
#include "fastcommon/pthread_func.h"
|
||||||
|
|
||||||
#define OneArgument(a) printf("One Argument func is called!\n")
|
#define OneArgument(a) printf("One Argument func is called!\n")
|
||||||
#define TwoArguments(a, b) printf("Two Arguments func is called!\n")
|
#define TwoArguments(a, b) printf("Two Arguments func is called!\n")
|
||||||
|
|
@ -36,7 +37,6 @@ static inline int get_lock_info(int fd, struct flock *lock)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
memset(lock, 0, sizeof(struct flock));
|
|
||||||
lock->l_whence = SEEK_SET;
|
lock->l_whence = SEEK_SET;
|
||||||
lock->l_type = F_WRLCK;
|
lock->l_type = F_WRLCK;
|
||||||
lock->l_pid = getpid();
|
lock->l_pid = getpid();
|
||||||
|
|
@ -53,6 +53,69 @@ static inline int get_lock_info(int fd, struct flock *lock)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int set_lock(int fd, const int operation,
|
||||||
|
const int start, const int length)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
struct flock lock;
|
||||||
|
|
||||||
|
memset(&lock, 0, sizeof(struct flock));
|
||||||
|
lock.l_whence = SEEK_SET;
|
||||||
|
lock.l_type = operation;
|
||||||
|
lock.l_start = start;
|
||||||
|
lock.l_len = length;
|
||||||
|
lock.l_pid = getpid();
|
||||||
|
do {
|
||||||
|
if ((result=fcntl(fd, F_SETLKW, &lock)) != 0)
|
||||||
|
{
|
||||||
|
result = errno != 0 ? errno : ENOMEM;
|
||||||
|
fprintf(stderr, "line: %d, call fcntl fail, "
|
||||||
|
"errno: %d, error info: %s\n", __LINE__,
|
||||||
|
result, STRERROR(result));
|
||||||
|
} else {
|
||||||
|
printf("line: %d, call fcntl %d result: %d\n",
|
||||||
|
__LINE__, operation, result);
|
||||||
|
}
|
||||||
|
} while (result == EINTR);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *unlock_thread(void *args)
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
int result;
|
||||||
|
int fd;
|
||||||
|
struct flock lock;
|
||||||
|
|
||||||
|
filename = (char *)args;
|
||||||
|
fd = open(filename, O_RDWR | O_CREAT, 0644);
|
||||||
|
if (fd < 0) {
|
||||||
|
result = errno != 0 ? errno : EIO;
|
||||||
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
"open file %s fail, "
|
||||||
|
"errno: %d, error info: %s",
|
||||||
|
__LINE__, filename,
|
||||||
|
result, STRERROR(result));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&lock, 0, sizeof(struct flock));
|
||||||
|
lock.l_start = 100;
|
||||||
|
if ((result=get_lock_info(fd, &lock)) == 0) {
|
||||||
|
logInfo("lock info: { type: %d, whence: %d, start: %"PRId64", "
|
||||||
|
"len: %"PRId64", pid: %d }",
|
||||||
|
lock.l_type, lock.l_whence, (int64_t)lock.l_start,
|
||||||
|
(int64_t)lock.l_len, lock.l_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
//set_lock(fd, F_WRLCK, 0, 0);
|
||||||
|
sleep(5);
|
||||||
|
//set_lock(fd, F_UNLCK, 0, 0);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#define SEEK_POS (2 * 1024)
|
#define SEEK_POS (2 * 1024)
|
||||||
|
|
@ -61,12 +124,15 @@ int main(int argc, char *argv[])
|
||||||
int result;
|
int result;
|
||||||
int sleep_seconds;
|
int sleep_seconds;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
pthread_t tid;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
|
|
||||||
Macro(1);
|
Macro(1);
|
||||||
Macro(1, 2);
|
Macro(1, 2);
|
||||||
Macro(1, 2, 3);
|
Macro(1, 2, 3);
|
||||||
|
|
||||||
|
printf("%0*d\n", 3, 1);
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
|
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -80,7 +146,7 @@ int main(int argc, char *argv[])
|
||||||
sleep_seconds = 1;
|
sleep_seconds = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(filename, O_RDWR | O_CREAT, 0644);
|
fd = open(filename, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
result = errno != 0 ? errno : EIO;
|
result = errno != 0 ? errno : EIO;
|
||||||
logError("file: "__FILE__", line: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
|
|
@ -91,6 +157,61 @@ int main(int argc, char *argv[])
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
flags = fcntl(fd, F_GETFD, 0);
|
||||||
|
if (flags < 0)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, " \
|
||||||
|
"fcntl failed, errno: %d, error info: %s.", \
|
||||||
|
__LINE__, errno, STRERROR(errno));
|
||||||
|
return errno != 0 ? errno : EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("flags: %d, on: %d\n", flags, (flags & FD_CLOEXEC));
|
||||||
|
|
||||||
|
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
|
||||||
|
{
|
||||||
|
logError("file: "__FILE__", line: %d, " \
|
||||||
|
"fcntl failed, errno: %d, error info: %s.", \
|
||||||
|
__LINE__, errno, STRERROR(errno));
|
||||||
|
return errno != 0 ? errno : EACCES;
|
||||||
|
}
|
||||||
|
flags = fcntl(fd, F_GETFD, 0);
|
||||||
|
printf("flags: %d, on: %d\n", flags, (flags & FD_CLOEXEC));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fork();
|
||||||
|
|
||||||
|
memset(&lock, 0, sizeof(struct flock));
|
||||||
|
lock.l_start = 1024;
|
||||||
|
if ((result=get_lock_info(fd, &lock)) == 0) {
|
||||||
|
logInfo("pid: %d, lock info: { type: %d, whence: %d, "
|
||||||
|
"start: %"PRId64", len: %"PRId64", pid: %d }", getpid(),
|
||||||
|
lock.l_type, lock.l_whence, (int64_t)lock.l_start,
|
||||||
|
(int64_t)lock.l_len, lock.l_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_lock(fd, F_WRLCK, 0, 10);
|
||||||
|
set_lock(fd, F_WRLCK, 10, 10);
|
||||||
|
set_lock(fd, F_WRLCK, 30, 10);
|
||||||
|
//set_lock(fd, F_WRLCK, 0, 0);
|
||||||
|
//set_lock(fd, F_UNLCK, 0, 10);
|
||||||
|
//set_lock(fd, F_UNLCK, 5, 35);
|
||||||
|
|
||||||
|
fc_create_thread(&tid, unlock_thread, filename, 64 * 1024);
|
||||||
|
|
||||||
|
sleep(100);
|
||||||
|
memset(&lock, 0, sizeof(struct flock));
|
||||||
|
lock.l_start = 100;
|
||||||
|
if ((result=get_lock_info(fd, &lock)) == 0) {
|
||||||
|
logInfo("lock info: { type: %d, whence: %d, start: %"PRId64", "
|
||||||
|
"len: %"PRId64", pid: %d }",
|
||||||
|
lock.l_type, lock.l_whence, (int64_t)lock.l_start,
|
||||||
|
(int64_t)lock.l_len, lock.l_pid);
|
||||||
|
}
|
||||||
|
|
||||||
if (flock(fd, LOCK_EX) < 0) {
|
if (flock(fd, LOCK_EX) < 0) {
|
||||||
logError("file: "__FILE__", line: %d, "
|
logError("file: "__FILE__", line: %d, "
|
||||||
"flock file %s fail, "
|
"flock file %s fail, "
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ int main(int argc, char *argv[])
|
||||||
int fd;
|
int fd;
|
||||||
int result;
|
int result;
|
||||||
int n;
|
int n;
|
||||||
|
int i;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
|
|
@ -50,7 +51,7 @@ int main(int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
|
//fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
|
||||||
fd = open(filename, O_RDWR | O_CREAT, 0644);
|
fd = open(filename, O_RDWR | O_CREAT | O_APPEND, 0644);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
result = errno != 0 ? errno : EIO;
|
result = errno != 0 ? errno : EIO;
|
||||||
logError("file: "__FILE__", line: %d, " \
|
logError("file: "__FILE__", line: %d, " \
|
||||||
|
|
@ -69,7 +70,8 @@ int main(int argc, char *argv[])
|
||||||
return errno != 0 ? errno : EIO;
|
return errno != 0 ? errno : EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lseek(fd, SEEK_POS, SEEK_SET) < 0) {
|
for (i=0; i<5; i++) {
|
||||||
|
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||||
logError("file: "__FILE__", line: %d, " \
|
logError("file: "__FILE__", line: %d, " \
|
||||||
"lseek file %s fail, " \
|
"lseek file %s fail, " \
|
||||||
"errno: %d, error info: %s", __LINE__, \
|
"errno: %d, error info: %s", __LINE__, \
|
||||||
|
|
@ -86,6 +88,7 @@ int main(int argc, char *argv[])
|
||||||
return errno != 0 ? errno : EIO;
|
return errno != 0 ? errno : EIO;
|
||||||
}
|
}
|
||||||
printf("write bytes: %d\n", n);
|
printf("write bytes: %d\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
if (lseek(fd, 0, SEEK_SET) < 0) {
|
if (lseek(fd, 0, SEEK_SET) < 0) {
|
||||||
logError("file: "__FILE__", line: %d, " \
|
logError("file: "__FILE__", line: %d, " \
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/file.h>
|
||||||
#include "fastcommon/logger.h"
|
#include "fastcommon/logger.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
|
@ -36,6 +37,15 @@ int main(int argc, char *argv[])
|
||||||
log_take_over_stdout();
|
log_take_over_stdout();
|
||||||
log_set_compress_log_flags(LOG_COMPRESS_FLAGS_ENABLED | LOG_COMPRESS_FLAGS_NEW_THREAD);
|
log_set_compress_log_flags(LOG_COMPRESS_FLAGS_ENABLED | LOG_COMPRESS_FLAGS_NEW_THREAD);
|
||||||
|
|
||||||
|
log_set_filename("/opt/fastcfs/fuse/test.log");
|
||||||
|
|
||||||
|
|
||||||
|
if (flock(g_log_context.log_fd, LOCK_EX) != 0) {
|
||||||
|
logError("flock fail");
|
||||||
|
}
|
||||||
|
|
||||||
|
flock(g_log_context.log_fd, LOCK_UN);
|
||||||
|
|
||||||
printf("sizeof(LogContext): %d, time_precision: %d, compress_log_flags: %d, "
|
printf("sizeof(LogContext): %d, time_precision: %d, compress_log_flags: %d, "
|
||||||
"use_file_write_lock: %d\n", (int)sizeof(LogContext),
|
"use_file_write_lock: %d\n", (int)sizeof(LogContext),
|
||||||
g_log_context.time_precision,
|
g_log_context.time_precision,
|
||||||
|
|
@ -46,7 +56,7 @@ int main(int argc, char *argv[])
|
||||||
"by log_it_ex, timestamp: %d", (int)time(NULL));
|
"by log_it_ex, timestamp: %d", (int)time(NULL));
|
||||||
|
|
||||||
len = sprintf(buff, "this is by log_it_ex1, "
|
len = sprintf(buff, "this is by log_it_ex1, "
|
||||||
"timestamp: %d", (int)time(NULL));
|
"timestamp: %ld", (long)time(NULL));
|
||||||
log_it_ex1(&g_log_context, LOG_INFO, buff, len);
|
log_it_ex1(&g_log_context, LOG_INFO, buff, len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ int main(int argc, char *argv[])
|
||||||
volatile bool continue_flag = true;
|
volatile bool continue_flag = true;
|
||||||
FastIFConfig if_configs[32];
|
FastIFConfig if_configs[32];
|
||||||
struct fast_statfs stats[32];
|
struct fast_statfs stats[32];
|
||||||
|
char *path;
|
||||||
|
FastStatFS statfs;
|
||||||
|
|
||||||
start_time = get_current_time_ms();
|
start_time = get_current_time_ms();
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
@ -86,10 +88,19 @@ int main(int argc, char *argv[])
|
||||||
printf("mounted fs count: %d\n", count);
|
printf("mounted fs count: %d\n", count);
|
||||||
for (i=0; i<count; i++) {
|
for (i=0; i<count; i++) {
|
||||||
printf("%s => %s %s %ld %ld %ld %ld %ld %ld %ld\n",
|
printf("%s => %s %s %ld %ld %ld %ld %ld %ld %ld\n",
|
||||||
stats[i].f_mntfromname, stats[i].f_mntonname, stats[i].f_fstypename,
|
stats[i].f_mntfromname, stats[i].f_mntonname,
|
||||||
stats[i].f_type, stats[i].f_bsize, stats[i].f_blocks,
|
stats[i].f_fstypename, stats[i].f_type, stats[i].f_bsize,
|
||||||
stats[i].f_bfree, stats[i].f_bavail, stats[i].f_files,
|
stats[i].f_blocks, stats[i].f_bfree, stats[i].f_bavail,
|
||||||
stats[i].f_ffree);
|
stats[i].f_files, stats[i].f_ffree);
|
||||||
|
}
|
||||||
|
|
||||||
|
path = "/";
|
||||||
|
if (get_statfs_by_path(path, &statfs) == 0) {
|
||||||
|
printf("\ninput path: %s, %s => %s, type: %s, category: %s, "
|
||||||
|
"rotational: %d\n\n", path, statfs.f_mntfromname,
|
||||||
|
statfs.f_mntonname, statfs.f_fstypename,
|
||||||
|
get_device_type_caption(statfs.device_type),
|
||||||
|
is_rotational_device_by_path(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
#if defined(OS_LINUX) || defined(OS_FREEBSD)
|
||||||
|
|
@ -139,31 +150,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
char *filename;
|
|
||||||
IniContext iniContext;
|
|
||||||
if (argc > 1) {
|
|
||||||
filename = argv[1];
|
|
||||||
} else {
|
|
||||||
filename = "/etc/mc/worker.conf";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ((result=iniLoadFromFile(filename, &iniContext)) != 0) {
|
|
||||||
logError("file: "__FILE__", line: %d, "
|
|
||||||
"load conf file \"%s\" fail, ret code: %d",
|
|
||||||
__LINE__, filename, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//iniPrintItems(&iniContext);
|
|
||||||
iniFreeContext(&iniContext);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
sched_enable_delay_task();
|
sched_enable_delay_task();
|
||||||
scheduleArray.entries = scheduleEntries;
|
scheduleArray.entries = scheduleEntries;
|
||||||
scheduleArray.count = 0;
|
scheduleArray.count = 0;
|
||||||
|
|
@ -176,7 +162,7 @@ int main(int argc, char *argv[])
|
||||||
printf("cpu count: %d\n", get_sys_cpu_count());
|
printf("cpu count: %d\n", get_sys_cpu_count());
|
||||||
|
|
||||||
end_time = get_current_time_ms();
|
end_time = get_current_time_ms();
|
||||||
logInfo("time used: %d ms", (int)(end_time - start_time));
|
logInfo("time used: %d ms\n", (int)(end_time - start_time));
|
||||||
|
|
||||||
fast_mblock_manager_init();
|
fast_mblock_manager_init();
|
||||||
|
|
||||||
|
|
@ -196,19 +182,33 @@ int main(int argc, char *argv[])
|
||||||
sched_add_delay_task(test_delay, objs + i, delay, false);
|
sched_add_delay_task(test_delay, objs + i, delay, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("mblock1 total count: %"PRId64", free count: %u\n",
|
||||||
|
fast_mblock_total_count(&mblock1),
|
||||||
|
fast_mblock_free_count(&mblock1));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
for (i=0; i<count; i++)
|
for (i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
fast_mblock_free_object(&mblock1, objs[i]);
|
fast_mblock_free_object(objs[i].mblock, objs[i].obj);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
obj1 = fast_mblock_alloc_object(&mblock1);
|
obj1 = fast_mblock_alloc_object(&mblock1);
|
||||||
obj2 = fast_mblock_alloc_object(&mblock1);
|
obj2 = fast_mblock_alloc_object(&mblock1);
|
||||||
fast_mblock_free_object(&mblock1, obj1);
|
fast_mblock_free_object(&mblock1, obj1);
|
||||||
|
|
||||||
|
|
||||||
|
printf("mblock1 total count: %"PRId64", free count: %u\n",
|
||||||
|
fast_mblock_total_count(&mblock1),
|
||||||
|
fast_mblock_free_count(&mblock1));
|
||||||
|
|
||||||
//fast_mblock_delay_free_object(&mblock1, obj2, 10);
|
//fast_mblock_delay_free_object(&mblock1, obj2, 10);
|
||||||
fast_mblock_free_object(&mblock1, obj2);
|
fast_mblock_free_object(&mblock1, obj2);
|
||||||
|
|
||||||
|
printf("mblock1 total count: %"PRId64", free count: %u\n\n",
|
||||||
|
fast_mblock_total_count(&mblock1),
|
||||||
|
fast_mblock_free_count(&mblock1));
|
||||||
|
|
||||||
obj1 = fast_mblock_alloc_object(&mblock2);
|
obj1 = fast_mblock_alloc_object(&mblock2);
|
||||||
obj2 = fast_mblock_alloc_object(&mblock2);
|
obj2 = fast_mblock_alloc_object(&mblock2);
|
||||||
fast_mblock_delay_free_object(&mblock2, obj1, 20);
|
fast_mblock_delay_free_object(&mblock2, obj1, 20);
|
||||||
|
|
@ -220,6 +220,13 @@ int main(int argc, char *argv[])
|
||||||
fast_mblock_reclaim(&mblock1, reclaim_target, &reclaim_count, NULL);
|
fast_mblock_reclaim(&mblock1, reclaim_target, &reclaim_count, NULL);
|
||||||
fast_mblock_reclaim(&mblock2, reclaim_target, &reclaim_count, NULL);
|
fast_mblock_reclaim(&mblock2, reclaim_target, &reclaim_count, NULL);
|
||||||
|
|
||||||
|
printf("\nmblock1 total count: %"PRId64", free count: %u, "
|
||||||
|
"mblock2 total count: %"PRId64", free count: %u\n\n",
|
||||||
|
fast_mblock_total_count(&mblock1),
|
||||||
|
fast_mblock_free_count(&mblock1),
|
||||||
|
fast_mblock_total_count(&mblock2),
|
||||||
|
fast_mblock_free_count(&mblock2));
|
||||||
|
|
||||||
fast_mblock_manager_stat_print(false);
|
fast_mblock_manager_stat_print(false);
|
||||||
|
|
||||||
sleep(31);
|
sleep(31);
|
||||||
|
|
@ -231,11 +238,25 @@ int main(int argc, char *argv[])
|
||||||
fast_mblock_reclaim(&mblock1, reclaim_target, &reclaim_count, NULL);
|
fast_mblock_reclaim(&mblock1, reclaim_target, &reclaim_count, NULL);
|
||||||
fast_mblock_reclaim(&mblock2, reclaim_target, &reclaim_count, NULL);
|
fast_mblock_reclaim(&mblock2, reclaim_target, &reclaim_count, NULL);
|
||||||
|
|
||||||
|
printf("\nmblock1 total count: %"PRId64", free count: %u, "
|
||||||
|
"mblock2 total count: %"PRId64", free count: %u\n\n",
|
||||||
|
fast_mblock_total_count(&mblock1),
|
||||||
|
fast_mblock_free_count(&mblock1),
|
||||||
|
fast_mblock_total_count(&mblock2),
|
||||||
|
fast_mblock_free_count(&mblock2));
|
||||||
|
|
||||||
fast_mblock_manager_stat_print(false);
|
fast_mblock_manager_stat_print(false);
|
||||||
|
|
||||||
obj1 = fast_mblock_alloc_object(&mblock1);
|
obj1 = fast_mblock_alloc_object(&mblock1);
|
||||||
obj2 = fast_mblock_alloc_object(&mblock2);
|
obj2 = fast_mblock_alloc_object(&mblock2);
|
||||||
|
|
||||||
|
printf("mblock1 total count: %"PRId64", free count: %u, "
|
||||||
|
"mblock2 total count: %"PRId64", free count: %u\n\n",
|
||||||
|
fast_mblock_total_count(&mblock1),
|
||||||
|
fast_mblock_free_count(&mblock1),
|
||||||
|
fast_mblock_total_count(&mblock2),
|
||||||
|
fast_mblock_free_count(&mblock2));
|
||||||
|
|
||||||
fast_mblock_manager_stat_print(false);
|
fast_mblock_manager_stat_print(false);
|
||||||
|
|
||||||
fast_mblock_destroy(&mblock1);
|
fast_mblock_destroy(&mblock1);
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,56 @@ static void sigQuitHandler(int sig)
|
||||||
__LINE__, sig);
|
__LINE__, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_remove()
|
||||||
|
{
|
||||||
|
#define COUNT 8
|
||||||
|
typedef struct node {
|
||||||
|
int n;
|
||||||
|
struct node *next;
|
||||||
|
} Node;
|
||||||
|
struct fc_queue queue;
|
||||||
|
Node nodes[COUNT];
|
||||||
|
Node *node;
|
||||||
|
Node *end;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result=fc_queue_init(&queue, (long)&((Node *)NULL)->next)) != 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc_queue_push(&queue, nodes);
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, nodes + 1));
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, nodes + 2));
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, nodes));
|
||||||
|
printf("count: %d\n", fc_queue_count(&queue));
|
||||||
|
|
||||||
|
end = nodes + COUNT / 2;
|
||||||
|
for (node=nodes; node<end; node++) {
|
||||||
|
node->n = (node - nodes) + 1;
|
||||||
|
fc_queue_push(&queue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, node));
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, node - 1));
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, node - 3));
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, nodes));
|
||||||
|
|
||||||
|
end = nodes + COUNT;
|
||||||
|
for (; node<end; node++) {
|
||||||
|
node->n = (node - nodes) + 1;
|
||||||
|
fc_queue_push(&queue, node);
|
||||||
|
}
|
||||||
|
printf("count: %d\n\n", fc_queue_count(&queue));
|
||||||
|
|
||||||
|
for (node=end-1; node>=nodes; node--) {
|
||||||
|
printf("remove: %d\n", fc_queue_remove(&queue, node));
|
||||||
|
fc_queue_push(&queue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("count: %d\n", fc_queue_count(&queue));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
const int alloc_elements_once = 8 * 1024;
|
const int alloc_elements_once = 8 * 1024;
|
||||||
|
|
@ -107,6 +157,9 @@ int main(int argc, char *argv[])
|
||||||
log_init();
|
log_init();
|
||||||
g_log_context.log_level = LOG_DEBUG;
|
g_log_context.log_level = LOG_DEBUG;
|
||||||
|
|
||||||
|
test_remove();
|
||||||
|
return 0;
|
||||||
|
|
||||||
memset(&act, 0, sizeof(act));
|
memset(&act, 0, sizeof(act));
|
||||||
sigemptyset(&act.sa_mask);
|
sigemptyset(&act.sa_mask);
|
||||||
act.sa_handler = sigQuitHandler;
|
act.sa_handler = sigQuitHandler;
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
setup_mblock_stat_task();
|
setup_mblock_stat_task();
|
||||||
|
|
||||||
if ((result=fast_buffer_init_ex(&buffer, 1024)) != 0) {
|
if ((result=fast_buffer_init1(&buffer, 1024)) != 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
fc_server_to_config_string(&ctx, &buffer);
|
fc_server_to_config_string(&ctx, &buffer);
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ int fc_thread_pool_init_ex(FCThreadPool *pool, const char *name,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(pool->name, sizeof(pool->name), "%s", name);
|
fc_safe_strcpy(pool->name, name);
|
||||||
pool->stack_size = stack_size;
|
pool->stack_size = stack_size;
|
||||||
pool->max_idle_time = max_idle_time;
|
pool->max_idle_time = max_idle_time;
|
||||||
if (min_idle_count > limit) {
|
if (min_idle_count > limit) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue