Compare commits

..

No commits in common. "master" and "V1.0.52" have entirely different histories.

106 changed files with 3422 additions and 12476 deletions

8
.gitignore vendored
View File

@ -1,6 +1,5 @@
# Makefile.in
src/Makefile
src/tests/Makefile
# Prerequisites
*.d
@ -59,13 +58,6 @@ src/tests/test_pthread_wait
src/tests/test_mutex_lock_perf
src/tests/test_queue_perf
src/tests/test_normalize_path
src/tests/test_sorted_array
src/tests/test_sorted_queue
src/tests/test_thread_local
src/tests/test_memcpy
src/tests/mblock_benchmark
src/tests/cpool_benchmark
src/tests/test_fast_buffer
# other
*.swp

161
HISTORY
View File

@ -1,165 +1,4 @@
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
* add functions: get_log_level and get_log_level_caption
* adapt to FreeBSD 13
Version 1.73 2024-03-05
* add macro FC_SET_STRING_EMPTY
* struct fast_task_info remove fields: connect_timeout and network_timeout
* format ip address for IPv6
Version 1.72 2024-01-21
* call fast_mblock_ref_counter_dec for delay free node correctly
* fc_queue.[hc]: add function fc_queue_remove
Version 1.71 2023-12-23
* full support IPv6 by pull request #47
* replace inet_ntop to getnameinfo for IPv6
Version 1.70 2023-09-30
* get full mac address of infiniband NIC under Linux
* struct fast_task_info add field conn for RDMA connection
* server_id_func.[hc]: support communication type
* connection_pool.[hc] support callbacks for RDMA
* nio thread data support busy_polling_callback
* connection_pool.[hc] support thread local for performance
* struct fast_task_info support send and recv double buffers
* add functions: fc_queue_push_with_check and fc_queue_peek
Version 1.69 2023-08-05
* bugfixed: array_allocator_alloc MUST init the array
* uniq_skiplist support arg for free callback
Version 1.68 2023-07-05
* sorted_queue.[hc]: pop_compare_func support argument
Version 1.67 2023-05-29
* lc_pair in struct fc_queue change to lcp
* sorted queue use double link chain for quick push
* add function uniq_skiplist_clear
* fast_mblock_malloc_trunk_notify_func prototype changed
* fast_mblock_init_ex2 add parameter prealloc_trunk_count
* sorted_queue.[hc] support pop_compare_func
* bugfixed: fast_mblock_batch_alloc correct return value
* add function fc_safe_writev
Version 1.66 2023-02-12
* struct fast_task_info add field: notify_next for nio notify queue
Version 1.65 2023-01-09
* locked_list.h: add functions locked_list_move and locked_list_move_tail
* add function tcp_socket_connected
* parse_bytes support space charactors (before and after the unit)
* add function get_groups
Version 1.64 2022-11-19
* shared_func.[hc]: normalize_path use type string_t for general purpose
* bugfixed: common_blocked_queue_[alloc|free]_node must use lock
* bugfixed: can't use global malloc_allocator
Version 1.63 2022-10-16
* sockopt.[hc]: getIpAndPort support ipv6
Version 1.62 2022-09-28
* add function fc_sleep_us
* add function fc_itoa
Version 1.61 2022-09-21
* get_base_path_from_conf_file_ex support parameter: noent_log_level
* add function common_blocked_queue_push_chain
Version 1.60 2022-08-27
* normalize_path for base_path
* struct fast_task_info add field recv_body for dynamic recv buffer
* add functions: iniGetDoubleCorrectValueEx and iniGetPercentCorrectValueEx
* fast_allocator.[hc] support object size and callbacks
Version 1.59 2022-07-21
* open file with flag O_CLOEXEC
* add global var g_set_cloexec and macro FC_SET_CLOEXEC
* add function fc_get_first_lines
Version 1.58 2022-06-04
* add function conn_pool_connect_server_ex1 to support service name
* add function conn_pool_get_connection_ex to support service name
* add function iniGetCharValueEx
* json_parser.[hc] refined for better performance
Version 1.57 2022-04-22
* add function fc_format_path
* add functions: fc_get_path_child_count and fc_copy_file
* fast_mblock.[hc] support object destroy callback
* bugfixed: fc_get_file_line_count_ex should rewind file
Version 1.56 2022-03-09
* add function fc_gettid
* function normalize_path: NULL from parameter for getcwd
* sockopt.[hc] support tcpwritev and tcpreadv
* add function fc_iov_get_bytes
* rename hash_xxx to fc_hash_xxx
* rename trim to fc_trim
* add function fc_check_rename_ex
Version 1.55 2022-01-12
* fastcommon php extension adapt to php 8
* function fast_mblock_batch_alloc changed
* add function sched_delay_free_ptr
Version 1.54 2021-12-23
* fast_allocator.[hc]: correct reclaim_interval logic
* shared_func.[hc]: add functions getFileContentEx1 and getFileContent1
* fc_queue.[hc]: add function fc_queue_timedpeek
* pthread_func.[hc]: add function init_pthread_rwlock
* add files: sorted_queue.[hc]
* add files: array_allocator.[hc]
* add files: sorted_array.[hc]
* shared_func.[hc]: add function fc_read_lines
* normalize_path removes prefix one ./ and multi ../
Version 1.53 2021-06-30
* process_action support action status
* uniq_skiplist.h: add function uniq_skiplist_iterator_at
Version 1.52 2021-06-08
* process_stop more gracefully (kill -9 on timeout)
* add function fc_queue_pop_to_queue_ex

14
INSTALL
View File

@ -6,20 +6,12 @@ Please visit the libfastcommon Home Page for more detail.
English language: https://github.com/happyfish100/libfastcommon
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,
# github address: https://github.com/happyfish100/libfastcommon.git
# gitee address: https://gitee.com/fastdfs100/libfastcommon.git
# the command lines as:
git clone https://github.com/happyfish100/libfastcommon.git
cd libfastcommon; git checkout V1.0.83
./make.sh clean && ./make.sh && sudo ./make.sh install
cd libfastcommon; git checkout V1.0.48
./make.sh clean && ./make.sh && ./make.sh install

View File

@ -1,6 +0,0 @@
libfastcommon for Debian
-----------------------
<possible notes regarding this package - if none, delete this file>
-- zhangchunsheng <zhangchunsheng423@gmail.com> Mon, 24 May 2021 18:54:01 +0800

192
debian/changelog vendored
View File

@ -1,192 +0,0 @@
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
* upgrade to 1.0.73-1
-- YuQing <384681@qq.com> Sun, 17 Mar 2024 15:10:21 +0000
libfastcommon (1.0.72-1) unstable; urgency=medium
* upgrade to 1.0.72-1
-- YuQing <384681@qq.com> Wed, 31 Jan 2024 11:59:25 +0000
libfastcommon (1.0.71-1) unstable; urgency=medium
* upgrade to 1.0.71-1
-- YuQing <384681@qq.com> Mon, 01 Jan 2024 11:23:54 +0000
libfastcommon (1.0.70-3) unstable; urgency=medium
* upgrade to 1.0.70-3
-- YuQing <384681@qq.com> Tue, 21 Nov 2023 14:35:29 +0000
libfastcommon (1.0.70-2) unstable; urgency=medium
* upgrade to 1.0.70-2
-- YuQing <384681@qq.com> Mon, 20 Nov 2023 13:23:17 +0000
libfastcommon (1.0.70-1) unstable; urgency=medium
* upgrade to 1.0.70-1
-- YuQing <384681@qq.com> Sun, 19 Nov 2023 14:45:34 +0000
libfastcommon (1.0.69-1) unstable; urgency=medium
* upgrade to 1.0.69-1
-- YuQing <384681@qq.com> Sun, 06 Aug 2023 07:21:50 +0000
libfastcommon (1.0.68-1) unstable; urgency=medium
* upgrade to 1.0.68-1
-- YuQing <384681@qq.com> Sun, 23 Jul 2023 14:27:27 +0000
libfastcommon (1.0.67-1) unstable; urgency=medium
* upgrade to 1.0.67-1
-- YuQing <384681@qq.com> Sun, 04 Jun 2023 10:51:06 +0000
libfastcommon (1.0.66-1) unstable; urgency=medium
* upgrade to 1.0.66-1
-- YuQing <384681@qq.com> Sat, 18 Feb 2023 05:43:58 +0000
libfastcommon (1.0.65-1) unstable; urgency=medium
* upgrade to 1.0.65-1
-- YuQing <384681@qq.com> Sun, 15 Jan 2023 13:49:19 +0000
libfastcommon (1.0.63-1) unstable; urgency=medium
* upgrade to 1.0.63-1
-- YuQing <384681@qq.com> Mon, 21 Nov 2022 14:54:56 +0000
libfastcommon (1.0.62-1) unstable; urgency=medium
* upgrade to 1.0.62-1
-- YuQing <384681@qq.com> Sat, 08 Oct 2022 13:28:15 +0000
libfastcommon (1.0.61-1) unstable; urgency=medium
* upgrade to 1.0.61-1
-- YuQing <384681@qq.com> Thu, 22 Sep 2022 12:22:09 +0000
libfastcommon (1.0.60-1) unstable; urgency=medium
* upgrade to 1.0.60-1
-- YuQing <384681@qq.com> Wed, 07 Sep 2022 13:36:01 +0000
libfastcommon (1.0.59-1) unstable; urgency=medium
* upgrade to 1.0.59-1
-- YuQing <384681@qq.com> Mon, 25 Jul 2022 13:51:25 +0000
libfastcommon (1.0.58-1) unstable; urgency=medium
* upgrade to 1.0.58-1
-- YuQing <384681@qq.com> Wed, 15 Jun 2022 14:26:02 +0000
libfastcommon (1.0.57-1) unstable; urgency=medium
* upgrade to 1.0.57-1
-- YuQing <384681@qq.com> Thu, 28 Apr 2022 11:53:21 +0000
libfastcommon (1.0.56-1) unstable; urgency=medium
* check pthread_rwlockattr_getkind_np for porting
* correct pthread_rwlockattr getkind_np to setkind_np
* change include <sys/poll.h> to #include <poll.h>
* add function fc_gettid
* NULL from parameter for getcwd
* sockopt.[hc] support tcpwritev and tcpreadv
* add const modifier for unification
* make.sh refined
* add function fc_iov_get_bytes
* make.sh: generate macros for dirent fields
* add function log_try_init2
* rename hash_xxx to fc_hash_xxx
* rename trim to fc_trim
* php-fastcommon compile OK
* add function locked_list_destroy
* upgrade version to 1.0.56
* add function fc_check_rename_ex
* small changes for logger.[hc]
-- YuQing <384681@qq.com> Sun, 13 Mar 2022 16:43:08 +0800
libfastcommon (1.0.55-1) unstable; urgency=medium
* upgrade version to 1.0.55
-- YuQing <384681@qq.com> Sat, 15 Jan 2022 19:50:26 +0800
libfastcommon (1.0.54-1) unstable; urgency=medium
* upgrade version to 1.0.54
-- YuQing <384681@qq.com> Sun, 26 Dec 2021 20:29:05 +0800
libfastcommon (1.0.53-1) unstable; urgency=medium
* open for write MUST have the third parameter: mode
* uniq_skiplist.h: add function uniq_skiplist_iterator_at
* process_action support action status
-- YuQing <384681@qq.com> Tue, 6 Jul 2021 21:23:31 +0800

1
debian/compat vendored
View File

@ -1 +0,0 @@
11

25
debian/control vendored
View File

@ -1,25 +0,0 @@
Source: libfastcommon
Section: libs
Priority: optional
Maintainer: YuQing <384681@qq.com>
Build-Depends: debhelper (>=11~)
Standards-Version: 4.1.4
Homepage: http://github.com/happyfish100/libfastcommon/
Package: libfastcommon-dev
Architecture: any
Section: libdevel
Depends: libfastcommon (= ${binary:Version}), ${misc:Depends}
Description: libfastcommon (development files)
This package contains header files.
Package: libfastcommon
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: c common functions library
c common functions library extracted from my open source projects FastDFS and
FastDHT. this library is very simple and stable.
.
some functions are wrappered into php extension, such as fastcommon_gethostaddrs,
fastcommon_id_generator_xxx, fastcommon_get_ifconfigs, fastcommon_get_sysinfo etc.

530
debian/copyright vendored
View File

@ -1,530 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: libfastcommon
Source: http://github.com/happyfish100/libfastcommon/
#
# Please double check copyright with the licensecheck(1) command.
Files: php-fastcommon/fastcommon.c
php-fastcommon/fastcommon.h
src/avl_tree.c
src/avl_tree.h
src/base64.c
src/buffered_file_writer.c
src/buffered_file_writer.h
src/chain.c
src/chain.h
src/char_convert_loader.c
src/char_convert_loader.h
src/char_converter.c
src/char_converter.h
src/common_blocked_queue.c
src/common_blocked_queue.h
src/common_define.h
src/connection_pool.c
src/connection_pool.h
src/fast_allocator.c
src/fast_allocator.h
src/fast_blocked_queue.c
src/fast_blocked_queue.h
src/fast_buffer.c
src/fast_buffer.h
src/fast_mblock.c
src/fast_mblock.h
src/fast_mpool.c
src/fast_mpool.h
src/fast_task_queue.c
src/fast_task_queue.h
src/fast_timer.c
src/fast_timer.h
src/fc_atomic.h
src/fc_memory.c
src/fc_memory.h
src/fc_queue.c
src/fc_queue.h
src/flat_skiplist.c
src/flat_skiplist.h
src/hash.c
src/hash.h
src/http_func.h
src/id_generator.c
src/ini_file_reader.c
src/ini_file_reader.h
src/ioevent.c
src/ioevent.h
src/ioevent_loop.c
src/ioevent_loop.h
src/json_parser.c
src/json_parser.h
src/local_ip_func.c
src/local_ip_func.h
src/locked_timer.c
src/locked_timer.h
src/logger.c
src/multi_skiplist.c
src/multi_skiplist.h
src/multi_socket_client.c
src/multi_socket_client.h
src/process_ctrl.c
src/process_ctrl.h
src/pthread_func.c
src/pthread_func.h
src/sched_thread.c
src/sched_thread.h
src/server_id_func.c
src/server_id_func.h
src/shared_buffer.c
src/shared_buffer.h
src/shared_func.c
src/shared_func.h
src/skiplist_common.h
src/skiplist_set.c
src/system_info.c
src/system_info.h
src/tests/test_allocator.c
src/tests/test_atomic.c
src/tests/test_blocked_queue.c
src/tests/test_char_convert.c
src/tests/test_char_convert_loader.c
src/tests/test_crc32.c
src/tests/test_data_visible.c
src/tests/test_file_lock.c
src/tests/test_file_write_hole.c
src/tests/test_id_generator.c
src/tests/test_ini_parser.c
src/tests/test_json_parser.c
src/tests/test_logger.c
src/tests/test_mblock.c
src/tests/test_multi_skiplist.c
src/tests/test_mutex_lock_perf.c
src/tests/test_normalize_path.c
src/tests/test_pipe.c
src/tests/test_pthread_lock.c
src/tests/test_pthread_wait.c
src/tests/test_queue_perf.c
src/tests/test_sched_thread.c
src/tests/test_server_id_func.c
src/tests/test_skiplist.c
src/tests/test_skiplist_set.c
src/tests/test_split_string.c
src/tests/test_thourands_seperator.c
src/tests/test_thread_pool.c
src/tests/test_uniq_skiplist.c
src/thread_pool.c
src/thread_pool.h
src/uniq_skiplist.c
src/uniq_skiplist.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: .gitignore
HISTORY
INSTALL
debian/README.Debian
debian/compat
debian/control
debian/libfastcommon-dev.install
debian/libfastcommon.install
debian/rules
debian/source/format
debian/watch
doc/id_generator-Chinese.md
doc/ini_file_reader-Chinese.md
doc/php_log_file_performance-Chinese.md
libfastcommon.spec
make.sh
php-fastcommon/config.m4
php-fastcommon/fastcommon.ini
php-fastcommon/php-fastcommon.spec.in
src/Makefile.in
src/fast_link_library.sh
src/fc_list.h
src/io_opt.c
src/io_opt.h
src/locked_list.h
src/md5.c
src/md5.h
src/tests/Makefile
src/tests/servers.conf
src/tests/test.ini
Copyright: __NO_COPYRIGHT_NOR_LICENSE__
License: __NO_COPYRIGHT_NOR_LICENSE__
Files: src/skiplist.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
skiplist.h, support stable sort :)
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/skiplist_set.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
a set implemented by skiplist, the entry can occur only once
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/sockopt.c
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
socketopt.c
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/sockopt.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
socketopt.h
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/http_func.c
Copyright: 2008 Happy Fish / YuQing
2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
FastDFS may be copied only under the terms of the GNU General
Public License V3, which may be found in the FastDFS source kit.
Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/id_generator.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
64 bits id generator for multi processes, the generated id format:
32 bits timestamp + X bits machine id + Y bits of extra data + Z bits serial number
such as 12 bits machine id, 0 bits extra data and 20 bits serial number
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/php7_ext_wrapper.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
php7 extension wrapper
for compatibility, these wrapper functions are designed for old php version.
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/base64.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
base64.h
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: src/logger.h
Copyright: 2020 YuQing <384681@qq.com>
License: GPL-3.0+
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/>.
.
logger.h
.
On Debian systems, the complete text of the GNU General Public License
Version 3 can be found in `/usr/share/common-licenses/GPL-3'.
Files: README
Copyright: 2010 Happy Fish / YuQing
License: __UNKNOWN__
libfastcommon may be copied only under the terms of the Less GNU General
Public License(LGPL).
Please visit the libfastcommon Home Page for more detail.
English language: https://github.com/happyfish100/libfastcommon
Chinese language: http://www.fastken.com/
.
c common functions library extracted from my open source projects FastDFS and
FastDHT. this library is very simple and stable.
#----------------------------------------------------------------------------
# xml and html files (skipped):
# php-fastcommon/test_file_put_contents.php
# php-fastcommon/test.php
# php-fastcommon/test_error_log.php
#----------------------------------------------------------------------------
# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following
# license/copyright files.
#----------------------------------------------------------------------------
# License file: LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
.
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
.
.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
.
0. Additional Definitions.
.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
.
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
.
1. Exception to Section 3 of the GNU GPL.
.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
.
2. Conveying Modified Versions.
.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
.
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
.
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
.
3. Object Code Incorporating Material from Library Header Files.
.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
.
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
.
4. Combined Works.
.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
.
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
.
d) Do one of the following:
.
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
.
5. Combined Libraries.
.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
.
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
.
6. Revised Versions of the GNU Lesser General Public License.
.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1 +0,0 @@
usr/include/fastcommon/*

View File

@ -1 +0,0 @@
usr/lib/libfastcommon.so*

14
debian/rules vendored
View File

@ -1,14 +0,0 @@
#!/usr/bin/make -f
export DESTDIR = $(CURDIR)/debian/tmp
%:
dh $@
override_dh_auto_build:
./make.sh clean && ./make.sh
override_dh_auto_install:
./make.sh install
dh_auto_install

View File

@ -1 +0,0 @@
3.0 (quilt)

3
debian/watch vendored
View File

@ -1,3 +0,0 @@
version=3
opts="mode=git" https://github.com/happyfish100/libfastcommon.git \
refs/tags/v([\d\.]+) debian uupdate

View File

@ -1,9 +1,10 @@
%define LibFastcommonDevel libfastcommon-devel
%define LibFastcommonDebuginfo libfastcommon-debuginfo
%define CommitVersion %(echo $COMMIT_VERSION)
Name: libfastcommon
Version: 1.0.83
Version: 1.0.52
Release: 1%{?dist}
Summary: c common functions library extracted from my open source projects FastDFS
License: LGPL
@ -17,14 +18,6 @@ BuildRequires: libcurl-devel
Requires: libcurl
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
c common functions library extracted from my open source projects FastDFS.
this library is very simple and stable. functions including: string, logger,

144
make.sh
View File

@ -1,9 +1,3 @@
GCC_VERSION=$(gcc -dM -E - < /dev/null | grep -w __GNUC__ | awk '{print $NF;}')
if [ -z "$GCC_VERSION" ]; then
echo -e "gcc not found, please install gcc first\n" 1>&2
exit 2
fi
tmp_src_filename=fast_check_bits.c
cat <<EOF > $tmp_src_filename
#include <stdio.h>
@ -13,82 +7,56 @@ int main()
{
printf("%d\n", (int)sizeof(void*));
printf("%d\n", (int)sizeof(off_t));
#ifdef __GLIBC_MINOR__
printf("%d\n", __GLIBC_MINOR__);
#endif
return 0;
}
EOF
gcc -D_FILE_OFFSET_BITS=64 -o a.out $tmp_src_filename
output=$(./a.out)
if [ $? -ne 0 ]; then
echo -e "Can't find a.out program\n" 1>&2
exit 2
fi
output=`./a.out`
if [ -f /bin/expr ]; then
EXPR=/bin/expr
elif [ -f /usr/bin/expr ]; then
EXPR=/usr/bin/expr
else
EXPR=$(which expr)
if [ $? -ne 0 ]; then
echo -e "Can't find expr program\n" 1>&2
exit 2
fi
EXPR=/usr/bin/expr
fi
count=0
int_bytes=4
off_bytes=8
glibc_minor=0
LIB_VERSION=lib64
for col in $output; do
if [ $count -eq 0 ]; then
int_bytes=$col
elif [ $count -eq 1 ]; then
off_bytes=$col
else
glibc_minor=$col
off_bytes=$col
fi
count=$($EXPR $count + 1)
count=`$EXPR $count + 1`
done
/bin/rm -f a.out $tmp_src_filename
uname=$(uname)
TARGET_PREFIX=$DESTDIR/usr
if [ "$int_bytes" -eq 8 ]; then
OS_BITS=64
if [ $uname = 'Linux' ]; then
osname=$(cat /etc/os-release | grep -w NAME | awk -F '=' '{print $2;}' | \
awk -F '"' '{if (NF==3) {print $2} else {print $1}}' | awk '{print $1}')
if [ $osname = 'Ubuntu' -o $osname = 'Debian' ]; then
LIB_VERSION=lib
else
LIB_VERSION=lib64
fi
else
LIB_VERSION=lib
fi
OS_BITS=64
LIB_VERSION=lib64
else
OS_BITS=32
LIB_VERSION=lib
OS_BITS=32
LIB_VERSION=lib
fi
if [ "$off_bytes" -eq 8 ]; then
OFF_BITS=64
OFF_BITS=64
else
OFF_BITS=32
OFF_BITS=32
fi
DEBUG_FLAG=0
export CC=gcc
CFLAGS='-Wall'
GCC_VERSION=$(gcc -dM -E - < /dev/null | grep -w __GNUC__ | awk '{print $NF;}')
if [ -n "$GCC_VERSION" ] && [ $GCC_VERSION -ge 7 ]; then
CFLAGS="$CFLAGS -Wformat-truncation=0 -Wformat-overflow=0"
fi
@ -99,7 +67,6 @@ else
CFLAGS="$CFLAGS -g -O3"
fi
INCS=''
LIBS='-lm -ldl'
if [ -f /usr/include/curl/curl.h ] || [ -f /usr/local/include/curl/curl.h ]; then
CFLAGS="$CFLAGS -DUSE_LIBCURL"
@ -112,33 +79,14 @@ HAVE_VMMETER_H=0
HAVE_USER_H=0
if [ "$uname" = "Linux" ]; then
OS_NAME=OS_LINUX
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
LIBS="$LIBS -lrt"
fi
IOEVENT_USE=IOEVENT_USE_EPOLL
elif [ "$uname" = "FreeBSD" ] || [ "$uname" = "Darwin" ]; then
OS_NAME=OS_FREEBSD
IOEVENT_USE=IOEVENT_USE_KQUEUE
if [ "$uname" = "Darwin" ]; then
CFLAGS="$CFLAGS -DDARWIN"
TARGET_PREFIX=$TARGET_PREFIX/local
else
INCS="$INCS -I/usr/local/include"
LIBS="$LIBS -L/usr/local/lib"
LIB_VERSION=lib
fi
if [ -f /usr/include/sys/vmmeter.h ]; then
@ -165,36 +113,6 @@ else
IOEVENT_USE=IOEVENT_USE_NONE
fi
check_dirent_field()
{
field_name=$1
upper_fname=$(echo $field_name | tr '[a-z]' '[A-Z]')
tmp_src_filename=fast_check_dirent.c
cat <<EOF > $tmp_src_filename
#include <stdio.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
struct dirent dir;
dir.$field_name = 1;
printf("#define HAVE_DIRENT_$upper_fname %d\n", dir.$field_name);
return 0;
}
EOF
gcc -o a.out $tmp_src_filename 2>/dev/null && ./a.out
/bin/rm -f a.out $tmp_src_filename
}
tmp_filename=fast_dirent_macros.txt
check_dirent_field d_type > $tmp_filename
check_dirent_field d_reclen >> $tmp_filename
check_dirent_field d_namlen >> $tmp_filename
check_dirent_field d_off >> $tmp_filename
cat <<EOF > src/_os_define.h
#ifndef _OS_DEFINE_H
#define _OS_DEFINE_H
@ -217,35 +135,13 @@ cat <<EOF > src/_os_define.h
#ifndef HAVE_USER_H
#define HAVE_USER_H $HAVE_USER_H
#endif
$(cat $tmp_filename && /bin/rm -f $tmp_filename)
#endif
EOF
pthread_path=''
for path in /lib /lib64 /usr/lib /usr/lib64 /usr/local/lib; do
if [ -d $path ]; then
pthread_path=$(find $path -name libpthread.so | head -n 1)
if [ -n "$pthread_path" ]; then
break
fi
pthread_path=$(find $path -name libpthread.a | head -n 1)
if [ -n "$pthread_path" ]; then
break
fi
fi
done
if [ -n "$pthread_path" ]; then
if [ -f /usr/lib/libpthread.so ] || [ -f /usr/local/lib/libpthread.so ] || [ -f /usr/lib64/libpthread.so ] || [ -f /usr/lib/libpthread.a ] || [ -f /usr/local/lib/libpthread.a ] || [ -f /usr/lib64/libpthread.a ]; then
LIBS="$LIBS -lpthread"
line=$(nm $pthread_path 2>/dev/null | grep -F pthread_rwlockattr_setkind_np | grep -w T)
if [ -n "$line" ]; then
CFLAGS="$CFLAGS -DWITH_PTHREAD_RWLOCKATTR_SETKIND_NP=1"
fi
elif [ -f /usr/lib/libc_r.so ]; then
line=$(nm -D /usr/lib/libc_r.so 2>/dev/null | grep -F pthread_create | grep -w T)
line=`nm -D /usr/lib/libc_r.so | grep pthread_create | grep -w T`
if [ -n "$line" ]; then
LIBS="$LIBS -lc_r"
fi
@ -264,9 +160,7 @@ sed_replace()
cd src
cp Makefile.in Makefile
sed_replace "s#\\\$(CC)#gcc#g" Makefile
sed_replace "s#\\\$(CFLAGS)#$CFLAGS#g" Makefile
sed_replace "s#\\\$(INCS)#$INCS#g" Makefile
sed_replace "s#\\\$(LIBS)#$LIBS#g" Makefile
sed_replace "s#\\\$(TARGET_PREFIX)#$TARGET_PREFIX#g" Makefile
sed_replace "s#\\\$(LIB_VERSION)#$LIB_VERSION#g" Makefile
@ -276,11 +170,3 @@ if [ "$1" = "clean" ]; then
/bin/rm -f Makefile _os_define.h
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

View File

@ -12,6 +12,7 @@
* 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 "php7_ext_wrapper.h"
#include "ext/standard/info.h"
#include "ext/standard/file.h"
@ -93,111 +94,26 @@ const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, N
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
#endif
ZEND_BEGIN_ARG_INFO_EX(arginfo_version, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_gethostaddrs, 0, 0, 0)
ZEND_ARG_INFO(0, if_alias_prefix)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_time33_hash, 0, 0, 1)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_simple_hash, 0, 0, 1)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_line_distance_km, 0, 0, 4)
ZEND_ARG_INFO(0, lat1)
ZEND_ARG_INFO(0, lon1)
ZEND_ARG_INFO(0, lat2)
ZEND_ARG_INFO(0, lon2)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_first_local_ip, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_next_local_ip, 0, 0, 1)
ZEND_ARG_INFO(0, previous_ip)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_is_private_ip, 0, 0, 1)
ZEND_ARG_INFO(0, ip)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_id_generator_init, 0, 0, 0)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, machine_id)
ZEND_ARG_INFO(0, mid_bits)
ZEND_ARG_INFO(0, extra_bits)
ZEND_ARG_INFO(0, sn_bits)
ZEND_ARG_INFO(0, mode)
ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_id_generator_next, 0, 0, 0)
ZEND_ARG_INFO(0, extra)
ZEND_ARG_INFO(0, handle)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_id_generator_get_extra, 0, 0, 1)
ZEND_ARG_INFO(0, id)
ZEND_ARG_INFO(0, handle)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_id_generator_get_timestamp, 0, 0, 1)
ZEND_ARG_INFO(0, id)
ZEND_ARG_INFO(0, handle)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_id_generator_destroy, 0, 0, 0)
ZEND_ARG_INFO(0, handle)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_ifconfigs, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_cpu_count, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_sysinfo, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_error_log, 0, 0, 1)
ZEND_ARG_INFO(0, message)
ZEND_ARG_INFO(0, message_type)
ZEND_ARG_INFO(0, destination)
ZEND_ARG_INFO(0, headers)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_file_put_contents, 0, 0, 2)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, flags)
ZEND_ARG_INFO(0, context)
ZEND_END_ARG_INFO()
// Every user visible function must have an entry in fastcommon_functions[].
zend_function_entry fastcommon_functions[] = {
ZEND_FE(fastcommon_version, arginfo_version)
ZEND_FE(fastcommon_gethostaddrs, arginfo_gethostaddrs)
ZEND_FE(fastcommon_time33_hash, arginfo_time33_hash)
ZEND_FE(fastcommon_simple_hash, arginfo_simple_hash)
ZEND_FE(fastcommon_get_line_distance_km, arginfo_get_line_distance_km)
ZEND_FE(fastcommon_get_first_local_ip, arginfo_get_first_local_ip)
ZEND_FE(fastcommon_get_next_local_ip, arginfo_get_next_local_ip)
ZEND_FE(fastcommon_is_private_ip, arginfo_is_private_ip)
ZEND_FE(fastcommon_id_generator_init, arginfo_id_generator_init)
ZEND_FE(fastcommon_id_generator_next, arginfo_id_generator_next)
ZEND_FE(fastcommon_id_generator_get_extra, arginfo_id_generator_get_extra)
ZEND_FE(fastcommon_id_generator_get_timestamp, arginfo_id_generator_get_timestamp)
ZEND_FE(fastcommon_id_generator_destroy, arginfo_id_generator_destroy)
ZEND_FE(fastcommon_get_ifconfigs, arginfo_get_ifconfigs)
ZEND_FE(fastcommon_get_cpu_count, arginfo_get_cpu_count)
ZEND_FE(fastcommon_get_sysinfo, arginfo_get_sysinfo)
ZEND_FE(fastcommon_error_log, arginfo_error_log)
ZEND_FE(fastcommon_file_put_contents, arginfo_file_put_contents)
ZEND_FE(fastcommon_version, NULL)
ZEND_FE(fastcommon_gethostaddrs, NULL)
ZEND_FE(fastcommon_time33_hash, NULL)
ZEND_FE(fastcommon_simple_hash, NULL)
ZEND_FE(fastcommon_get_line_distance_km, NULL)
ZEND_FE(fastcommon_get_first_local_ip, NULL)
ZEND_FE(fastcommon_get_next_local_ip, NULL)
ZEND_FE(fastcommon_is_private_ip, NULL)
ZEND_FE(fastcommon_id_generator_init, NULL)
ZEND_FE(fastcommon_id_generator_next, NULL)
ZEND_FE(fastcommon_id_generator_get_extra, NULL)
ZEND_FE(fastcommon_id_generator_get_timestamp, NULL)
ZEND_FE(fastcommon_id_generator_destroy, NULL)
ZEND_FE(fastcommon_get_ifconfigs, NULL)
ZEND_FE(fastcommon_get_cpu_count, NULL)
ZEND_FE(fastcommon_get_sysinfo, NULL)
ZEND_FE(fastcommon_error_log, NULL)
ZEND_FE(fastcommon_file_put_contents, NULL)
{NULL, NULL, NULL} /* Must be the last line */
};
@ -252,7 +168,7 @@ PHP_MINIT_FUNCTION(fastcommon)
log_try_init();
le_consumer = zend_register_list_destructors_ex(id_generator_dtor, NULL,
PHP_IDG_RESOURCE_NAME, module_number);
if (fc_hash_init(&idg_htable, fc_simple_hash, 64, 0.75) != 0) {
if (hash_init(&idg_htable, simple_hash, 64, 0.75) != 0) {
return FAILURE;
}
@ -465,7 +381,7 @@ ZEND_FUNCTION(fastcommon_simple_hash)
RETURN_BOOL(false);
}
RETURN_LONG(fc_simple_hash(str, str_len) & 0x7FFFFFFF);
RETURN_LONG(simple_hash(str, str_len) & 0x7FFFFFFF);
}
/*
@ -602,7 +518,7 @@ static struct idg_context *get_idg_context(const char *filename,
key_info.extra_bits = extra_bits;
key_info.sn_bits = sn_bits;
idg_context = (struct idg_context *)fc_hash_find(&idg_htable,
idg_context = (struct idg_context *)hash_find(&idg_htable,
&key_info, sizeof(key_info));
if (idg_context == NULL) {
idg_context = (struct idg_context *)malloc(sizeof(struct idg_context));
@ -618,7 +534,7 @@ static struct idg_context *get_idg_context(const char *filename,
{
return NULL;
}
fc_hash_insert_ex(&idg_htable, &key_info, sizeof(key_info),
hash_insert_ex(&idg_htable, &key_info, sizeof(key_info),
idg_context, 0, false);
}
@ -1237,8 +1153,8 @@ static PHPFileContext *fetch_file_context(const char *filename)
static int fc_open_file(PHPFileContext *ctx)
{
if ((ctx->fd = open(ctx->filename, O_WRONLY | O_CREAT |
O_APPEND | O_CLOEXEC, 0644)) < 0)
if ((ctx->fd = open(ctx->filename, O_WRONLY |
O_CREAT | O_APPEND, 0644)) < 0)
{
logError("file: "__FILE__", line: %d, "
"open file \"%s\" to write fail, "

View File

@ -1,7 +1,7 @@
.SUFFIXES: .c .o .lo
COMPILE = $(CC) $(CFLAGS)
INC_PATH = $(INCS)
INC_PATH =
LIB_PATH = $(LIBS)
TARGET_LIB = $(TARGET_PREFIX)/$(LIB_VERSION)
@ -14,10 +14,9 @@ FAST_SHARED_OBJS = hash.lo chain.lo shared_func.lo ini_file_reader.lo \
fast_buffer.lo multi_skiplist.lo flat_skiplist.lo \
system_info.lo fast_blocked_queue.lo id_generator.lo \
char_converter.lo char_convert_loader.lo common_blocked_queue.lo \
multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \
json_parser.lo buffered_file_writer.lo server_id_func.lo \
fc_queue.lo sorted_queue.lo fc_memory.lo shared_buffer.lo \
thread_pool.lo array_allocator.lo sorted_array.lo spinlock.lo
multi_socket_client.lo skiplist_set.lo uniq_skiplist.lo \
json_parser.lo buffered_file_writer.lo server_id_func.lo \
fc_queue.lo fc_memory.lo shared_buffer.lo thread_pool.lo
FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
logger.o sockopt.o base64.o sched_thread.o \
@ -28,10 +27,9 @@ FAST_STATIC_OBJS = hash.o chain.o shared_func.o ini_file_reader.o \
fast_buffer.o multi_skiplist.o flat_skiplist.o \
system_info.o fast_blocked_queue.o id_generator.o \
char_converter.o char_convert_loader.o common_blocked_queue.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 \
fc_queue.o sorted_queue.o fc_memory.o shared_buffer.o \
thread_pool.o array_allocator.o sorted_array.o spinlock.o
fc_queue.o fc_memory.o shared_buffer.o thread_pool.o
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 \
@ -45,9 +43,8 @@ HEADER_FILES = common_define.h hash.h chain.h logger.h base64.h \
char_convert_loader.h common_blocked_queue.h \
multi_socket_client.h skiplist_set.h uniq_skiplist.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 \
shared_buffer.h thread_pool.h fc_atomic.h array_allocator.h \
sorted_array.h spinlock.h
server_id_func.h fc_queue.h fc_memory.h shared_buffer.h \
thread_pool.h fc_atomic.h
ALL_OBJS = $(FAST_STATIC_OBJS) $(FAST_SHARED_OBJS)
@ -78,7 +75,7 @@ install:
install -m 644 $(HEADER_FILES) $(TARGET_PREFIX)/include/fastcommon
@BUILDROOT=$$(echo "$(TARGET_PREFIX)" | grep BUILDROOT); \
if [ -z "$$BUILDROOT" ] && [ "$(TARGET_LIB)" != "$(TARGET_PREFIX)/lib" ]; then ln -sf $(TARGET_LIB)/libfastcommon.so $(TARGET_PREFIX)/lib/libfastcommon.so; fi
if [ -z "$$BUILDROOT" ] && [ ! -e $(TARGET_PREFIX)/lib/libfastcommon.so ]; then ln -s $(TARGET_LIB)/libfastcommon.so $(TARGET_PREFIX)/lib/libfastcommon.so; fi
clean:
rm -f $(ALL_OBJS) $(ALL_PRGS) $(ALL_LIBS)

View File

@ -1,129 +0,0 @@
/*
* 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 GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "shared_func.h"
#include "array_allocator.h"
int array_allocator_init_ex(ArrayAllocatorContext *ctx,
const char *name_prefix, const int element_size,
const int min_bits, const int max_bits,
const bool need_lock)
{
const int obj_size = 0;
const int reclaim_interval = 0;
char name[32];
struct fast_region_info regions[32];
struct fast_region_info *region;
int bit;
int start;
int end;
int alloc_elements_once;
int step;
ctx->element_size = element_size;
ctx->min_count = (1 << min_bits);
start = 0;
alloc_elements_once = (1 << (max_bits - min_bits + 2));
for (bit=min_bits, region=regions;
bit<=max_bits; bit++, region++)
{
end = sizeof(VoidArray) + (1 << bit) * ctx->element_size;
step = end - start;
FAST_ALLOCATOR_INIT_REGION(*region, start,
end, step, alloc_elements_once);
alloc_elements_once /= 2;
start = end;
}
fc_combine_two_strings(name_prefix, "array", '-', name);
return fast_allocator_init_ex(&ctx->allocator, name,
obj_size, NULL, regions, region - regions, 0,
0.9999, reclaim_interval, need_lock);
}
VoidArray *array_allocator_alloc(ArrayAllocatorContext *ctx,
const int target_count)
{
int alloc;
int bytes;
VoidArray *array;
if (target_count <= ctx->min_count) {
alloc = ctx->min_count;
} else if (is_power2(target_count)) {
alloc = target_count;
} else {
alloc = ctx->min_count;
while (alloc < target_count) {
alloc *= 2;
}
}
bytes = sizeof(VoidArray) + alloc * ctx->element_size;
if ((array=fast_allocator_alloc(&ctx->allocator, bytes)) != NULL) {
array->alloc = alloc;
array->count = 0;
}
return array;
}
VoidArray *array_allocator_realloc(ArrayAllocatorContext *ctx,
VoidArray *old_array, const int target_count)
{
VoidArray *new_array;
if (old_array == NULL) {
return array_allocator_alloc(ctx, target_count);
}
if (old_array->alloc >= target_count) {
return old_array;
}
if ((new_array=array_allocator_alloc(ctx, target_count)) != NULL) {
if (old_array->count > 0) {
memcpy(new_array->elts, old_array->elts, ctx->
element_size * old_array->count);
}
new_array->count = old_array->count;
}
array_allocator_free(ctx, old_array);
return new_array;
}
int array_compare_element_int64(const int64_t *n1, const int64_t *n2)
{
int64_t sub;
sub = *n1 - *n2;
if (sub < 0) {
return -1;
} else if (sub > 0) {
return 1;
} else {
return 0;
}
}
int array_compare_element_int32(const int32_t *n1, const int32_t *n2)
{
return *n1 - *n2;
}
int array_compare_element_id_name(const id_name_pair_t *pair1,
const id_name_pair_t *pair2)
{
return fc_compare_int64(pair1->id, pair2->id);
}

View File

@ -1,174 +0,0 @@
/*
* 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 GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef ARRAY_ALLOCATOR_H
#define ARRAY_ALLOCATOR_H
#include "fast_allocator.h"
typedef struct
{
int alloc;
int count;
char elts[0];
} VoidArray;
typedef struct
{
int alloc;
int count;
int64_t elts[0];
} I64Array;
typedef struct
{
int alloc;
int count;
int32_t elts[0];
} I32Array;
typedef struct
{
int alloc;
int count;
id_name_pair_t elts[0];
} IdNameArray;
typedef struct
{
int alloc;
int count;
void *elts[0];
} PointerArray;
typedef struct array_allocator_context
{
struct fast_allocator_context allocator;
int element_size;
int min_count;
} ArrayAllocatorContext;
#ifdef __cplusplus
extern "C" {
#endif
int array_allocator_init_ex(ArrayAllocatorContext *ctx,
const char *name_prefix, const int element_size,
const int min_bits, const int max_bits,
const bool need_lock);
VoidArray *array_allocator_alloc(ArrayAllocatorContext *ctx,
const int target_count);
VoidArray *array_allocator_realloc(ArrayAllocatorContext *ctx,
VoidArray *old_array, const int target_count);
static inline void array_allocator_free(ArrayAllocatorContext *ctx,
VoidArray *array)
{
fast_allocator_free(&ctx->allocator, array);
}
/* comparator for 64 bits integer */
int array_compare_element_int64(const int64_t *n1, const int64_t *n2);
/* comparator for 32 bits integer */
int array_compare_element_int32(const int32_t *n1, const int32_t *n2);
/* comparator for id name pair (sorted by id) */
int array_compare_element_id_name(const id_name_pair_t *pair1,
const id_name_pair_t *pair2);
#define array_allocator_init(ctx, name_prefix, \
element_size, min_bits, max_bits) \
array_allocator_init_ex(ctx, name_prefix, \
element_size, min_bits, max_bits, true)
#define i64_array_allocator_init_ex(ctx, min_bits, max_bits, need_lock) \
array_allocator_init_ex(ctx, "i64", sizeof(int64_t), \
min_bits, max_bits, need_lock)
#define i64_array_allocator_init(ctx, min_bits, max_bits) \
i64_array_allocator_init_ex(ctx, min_bits, max_bits, true)
#define i64_array_allocator_alloc(ctx, target_count) \
(I64Array *)array_allocator_alloc(ctx, target_count)
#define i64_array_allocator_realloc(ctx, old_array, target_count) \
(I64Array *)array_allocator_realloc(ctx, \
(VoidArray *)old_array, target_count)
#define i64_array_allocator_free(ctx, array) \
array_allocator_free(ctx, (VoidArray *)array)
#define i32_array_allocator_init_ex(ctx, min_bits, max_bits, need_lock) \
array_allocator_init_ex(ctx, "i32", sizeof(int32_t), \
min_bits, max_bits, need_lock)
#define i32_array_allocator_init(ctx, min_bits, max_bits) \
i32_array_allocator_init_ex(ctx, min_bits, max_bits, true)
#define i32_array_allocator_alloc(ctx, target_count) \
(I32Array *)array_allocator_alloc(ctx, target_count)
#define i32_array_allocator_realloc(ctx, old_array, target_count) \
(I32Array *)array_allocator_realloc(ctx, \
(VoidArray *)old_array, target_count)
#define i32_array_allocator_free(ctx, array) \
array_allocator_free(ctx, (VoidArray *)array)
#define id_name_array_allocator_init_ex(ctx, min_bits, max_bits, need_lock) \
array_allocator_init_ex(ctx, "id_name", sizeof(id_name_pair_t), \
min_bits, max_bits, need_lock)
#define id_name_array_allocator_init(ctx, min_bits, max_bits) \
id_name_array_allocator_init_ex(ctx, min_bits, max_bits, true)
#define id_name_array_allocator_alloc(ctx, target_count) \
(IdNameArray *)array_allocator_alloc(ctx, target_count)
#define id_name_array_allocator_realloc(ctx, old_array, target_count) \
(IdNameArray *)array_allocator_realloc(ctx, \
(VoidArray *)old_array, target_count)
#define id_name_array_allocator_free(ctx, array) \
array_allocator_free(ctx, (VoidArray *)array)
#define ptr_array_allocator_init_ex(ctx, min_bits, max_bits, need_lock) \
array_allocator_init_ex(ctx, "ptr", sizeof(void *), \
min_bits, max_bits, need_lock)
#define ptr_array_allocator_init(ctx, min_bits, max_bits) \
ptr_array_allocator_init_ex(ctx, min_bits, max_bits, true)
#define ptr_array_allocator_alloc(ctx, target_count) \
(PointerArray *)array_allocator_alloc(ctx, target_count)
#define ptr_array_allocator_realloc(ctx, old_array, target_count) \
(PointerArray *)array_allocator_realloc(ctx, \
(VoidArray *)old_array, target_count)
#define ptr_array_allocator_free(ctx, array) \
array_allocator_free(ctx, (VoidArray *)array)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -24,7 +24,6 @@
#include <fcntl.h>
#include <errno.h>
#include "fc_memory.h"
#include "shared_func.h"
#include "base64.h"
/**
@ -54,11 +53,15 @@ void base64_set_line_length(struct base64_context *context, const int length)
* Usually contains only a combination of chars \n and \r.
* 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)
{
context->line_sep_len = fc_safe_strcpy(context->
line_separator, pLineSeparator);
context->line_sep_len = snprintf(context->line_separator, \
sizeof(context->line_separator), "%s", 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, \

View File

@ -48,9 +48,8 @@ int buffered_file_writer_open_ex(BufferedFileWriter *writer,
return ENOMEM;
}
fc_safe_strcpy(writer->filename, filename);
writer->fd = open(writer->filename, O_WRONLY |
O_CREAT | O_TRUNC | O_CLOEXEC, mode);
snprintf(writer->filename, sizeof(writer->filename), "%s", filename);
writer->fd = open(writer->filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (writer->fd < 0)
{
result = errno != 0 ? errno : EIO;

View File

@ -34,7 +34,7 @@ int common_blocked_queue_init_ex(struct common_blocked_queue *queue,
return result;
}
if ((result=fast_mblock_init_ex1(&queue->mblock, "queue-node",
if ((result=fast_mblock_init_ex1(&queue->mblock, "queue_node",
sizeof(struct common_blocked_node),
alloc_elements_once, alloc_elements_limit,
NULL, NULL, false)) != 0)
@ -102,29 +102,6 @@ int common_blocked_queue_push_ex(struct common_blocked_queue *queue,
return 0;
}
void common_blocked_queue_push_chain_ex(struct common_blocked_queue *queue,
struct common_blocked_chain *chain, bool *notify)
{
if (chain->head == NULL)
{
return;
}
pthread_mutex_lock(&(queue->lc_pair.lock));
if (queue->head == NULL)
{
queue->head = chain->head;
*notify = true;
}
else
{
queue->tail->next = chain->head;
*notify = false;
}
queue->tail = chain->tail;
pthread_mutex_unlock(&(queue->lc_pair.lock));
}
void common_blocked_queue_return_nodes(struct common_blocked_queue *queue,
struct common_blocked_node *node)
{

View File

@ -31,12 +31,6 @@ struct common_blocked_node
struct common_blocked_node *next;
};
struct common_blocked_chain
{
struct common_blocked_node *head;
struct common_blocked_node *tail;
};
struct common_blocked_queue
{
struct common_blocked_node *head;
@ -94,41 +88,6 @@ static inline int common_blocked_queue_push(struct common_blocked_queue
return result;
}
static inline struct common_blocked_node *common_blocked_queue_alloc_node(
struct common_blocked_queue *queue)
{
struct common_blocked_node *node;
pthread_mutex_lock(&(queue->lc_pair.lock));
node = (struct common_blocked_node *)fast_mblock_alloc_object(&queue->mblock);
pthread_mutex_unlock(&(queue->lc_pair.lock));
return node;
}
static inline void common_blocked_queue_free_node(
struct common_blocked_queue *queue,
struct common_blocked_node *node)
{
pthread_mutex_lock(&(queue->lc_pair.lock));
fast_mblock_free_object(&queue->mblock, node);
pthread_mutex_unlock(&(queue->lc_pair.lock));
}
void common_blocked_queue_push_chain_ex(struct common_blocked_queue *queue,
struct common_blocked_chain *chain, bool *notify);
static inline void common_blocked_queue_push_chain(
struct common_blocked_queue *queue,
struct common_blocked_chain *chain)
{
bool notify;
common_blocked_queue_push_chain_ex(queue, chain, &notify);
if (notify)
{
pthread_cond_signal(&(queue->lc_pair.cond));
}
}
void common_blocked_queue_return_nodes(struct common_blocked_queue *queue,
struct common_blocked_node *node);
@ -136,36 +95,6 @@ void common_blocked_queue_return_nodes(struct common_blocked_queue *queue,
void *common_blocked_queue_pop_ex(struct common_blocked_queue *queue,
const bool blocked);
static inline bool common_blocked_queue_empty(
struct common_blocked_queue *queue)
{
bool empty;
pthread_mutex_lock(&queue->lc_pair.lock);
empty = (queue->head == NULL);
pthread_mutex_unlock(&queue->lc_pair.lock);
return empty;
}
static inline int common_blocked_queue_count(
struct common_blocked_queue *queue)
{
int count;
struct common_blocked_node *node;
count = 0;
pthread_mutex_lock(&queue->lc_pair.lock);
node = queue->head;
while (node != NULL)
{
++count;
node = node->next;
}
pthread_mutex_unlock(&queue->lc_pair.lock);
return count;
}
#define common_blocked_queue_pop(queue) \
common_blocked_queue_pop_ex(queue, true)
@ -182,7 +111,7 @@ struct common_blocked_node *common_blocked_queue_pop_all_nodes_ex(
common_blocked_queue_pop_all_nodes_ex(queue, false)
#define common_blocked_queue_free_one_node(queue, node) \
common_blocked_queue_free_node(&queue->mblock, node)
fast_mblock_free_object(&queue->mblock, node)
void common_blocked_queue_free_all_nodes(struct common_blocked_queue *queue,
struct common_blocked_node *node);

View File

@ -43,14 +43,6 @@ typedef DWORD (WINAPI *ThreadEntranceFunc)(LPVOID lpThreadParameter);
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#ifdef OS_FREEBSD
//#include <sys/syscall.h>
#endif
/* Internet address (兼容IPv6长度). */
typedef uint64_t in_addr_64_t;
#define FILE_SEPERATOR "/"
typedef int SOCKET;
#define closesocket close
@ -112,23 +104,7 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
#define SYNC_LOG_BUFF_DEF_INTERVAL 10
#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
#define FC_IOV_BATCH_SIZE 256
#else
#define FC_IOV_BATCH_SIZE IOV_MAX
#endif
#define IPV4_ADDRESS_SIZE INET_ADDRSTRLEN //16
#define IPV6_ADDRESS_SIZE INET6_ADDRSTRLEN //46
#define IP_ADDRESS_SIZE INET6_ADDRSTRLEN //46
#define FORMATTED_IP_SIZE (IP_ADDRESS_SIZE + 2)
#define IP_ADDRESS_SIZE 16
#define INFINITE_FILE_SIZE (256 * 1024LL * 1024 * 1024 * 1024 * 1024LL)
#define FILE_RESOURCE_TAG_STR "file://"
@ -138,11 +114,6 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
(strncasecmp(filename, FILE_RESOURCE_TAG_STR, \
FILE_RESOURCE_TAG_LEN) == 0)
#define IS_FILE_RESOURCE_EX(filename) \
((filename)->len >= FILE_RESOURCE_TAG_LEN && \
memcmp((filename)->str, FILE_RESOURCE_TAG_STR, \
FILE_RESOURCE_TAG_LEN) == 0)
#ifndef byte
#define byte signed char
#endif
@ -161,10 +132,6 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
#define ECANCELED 125
#endif
#ifndef ENODATA
#define ENODATA 61 /* No data available */
#endif
#ifndef ENONET
#define ENONET 64 /* Machine is not on the network */
#endif
@ -187,25 +154,6 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
#define FC_TIME_UNIT_USECOND 'u' //microsecond
#define FC_TIME_UNIT_NSECOND 'n' //nanosecond
#define FC_1E01 10LL
#define FC_1E02 100LL
#define FC_1E03 1000LL
#define FC_1E04 10000LL
#define FC_1E05 100000LL
#define FC_1E06 1000000LL
#define FC_1E07 10000000LL
#define FC_1E08 100000000LL
#define FC_1E09 1000000000LL
#define FC_1E10 10000000000LL
#define FC_1E11 100000000000LL
#define FC_1E12 1000000000000LL
#define FC_1E13 10000000000000LL
#define FC_1E14 100000000000000LL
#define FC_1E15 1000000000000000LL
#define FC_1E16 10000000000000000LL
#define FC_1E17 100000000000000000LL
#define FC_1E18 1000000000000000000LL
#define STRERROR(no) (strerror(no) != NULL ? strerror(no) : "Unkown error")
#if defined(OS_LINUX)
@ -215,12 +163,10 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
#define st_ctimensec st_ctim.tv_nsec
#endif
#elif defined(OS_FREEBSD)
#ifndef st_atimensec
#define st_atimensec st_atimespec.tv_nsec
#define st_mtimensec st_mtimespec.tv_nsec
#define st_ctimensec st_ctimespec.tv_nsec
#endif
#endif
#ifdef __cplusplus
extern "C" {
@ -297,30 +243,6 @@ typedef struct
int count;
} key_value_array_t;
typedef struct
{
int32_t *elts;
int count;
} int32_array_t;
typedef struct
{
int64_t *elts;
int count;
} int64_array_t;
typedef struct
{
id_name_pair_t *elts;
int count;
} id_name_array_t;
typedef struct
{
void *elts;
int count;
} void_array_t;
typedef struct
{
pthread_mutex_t lock;
@ -340,38 +262,17 @@ typedef struct
string_t s;
} FilenameString;
typedef struct {
char *filename;
char *tmp_filename;
int fd;
} SafeWriteFileInfo;
typedef struct {
char filename[PATH_MAX];
int fd;
} FilenameFDPair;
typedef void (*FreeDataFunc)(void *ptr);
typedef int (*CompareFunc)(void *p1, void *p2);
typedef void* (*MallocFunc)(size_t size);
#define TO_UPPERCASE(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 32 : c)
#define MEM_ALIGN_FLOOR(x, align_size) ((x) & (~(align_size - 1)))
#define MEM_ALIGN_FLOOR(x, align_size) ((x) & (~(align_size - 1)))
#define MEM_ALIGN_CEIL(x, align_size) \
(((x) + (align_size - 1)) & (~(align_size - 1)))
#define MEM_ALIGN(x) MEM_ALIGN_CEIL(x, 8)
#define MEM_ALIGN_FLOOR_BY_MASK(x, align_mask) ((x) & (~align_mask))
#define MEM_ALIGN_CEIL_BY_MASK(x, align_mask) \
(((x) + align_mask) & (~align_mask))
#define FC_INIT_CHAIN(chain) (chain).head = (chain).tail = NULL
#define FC_IS_CHAIN_EMPTY(chain) ((chain).head == NULL)
#define FC_SET_CHAIN_TAIL_NEXT(chain, type, ptr) \
((type *)(chain).tail)->next = ptr
#ifdef WIN32
#define strcasecmp _stricmp
#endif
@ -421,8 +322,6 @@ typedef void* (*MallocFunc)(size_t size);
(dest).len = l; \
} while (0)
#define FC_SET_STRING_EMPTY(dest, s) FC_SET_STRING_EX(dest, s, 0)
#define FC_SET_STRING_NULL(dest) \
do { \
(dest).str = NULL; \
@ -455,14 +354,6 @@ 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)
{
return (s1->len == s2->len) && (memcmp(s1->str, s2->str, s1->len) == 0);
@ -524,40 +415,11 @@ static inline int fc_compare_int64(const int64_t n1, const int64_t n2)
}
#ifdef OS_LINUX
static inline int fc_fallocate(int fd, const int64_t size)
{
if (fallocate(fd, 0, 0, size) < 0) {
if (errno == EOPNOTSUPP) {
return ftruncate(fd, size);
}
return -1;
}
return 0;
}
#define fc_fallocate(fd, size) fallocate(fd, 0, 0, size)
#else
#define fc_fallocate(fd, size) ftruncate(fd, size)
#define posix_fadvise(fd, offset, len, advice) 0
#ifndef POSIX_FADV_NORMAL
#define POSIX_FADV_NORMAL 0 /* No further special treatment. */
#define POSIX_FADV_RANDOM 1 /* Expect random page references. */
#define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */
#define POSIX_FADV_WILLNEED 3 /* Will need these pages. */
#define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */
#define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */
#endif
#ifdef OS_FREEBSD
//#define fdatasync(fd) syscall(SYS_fdatasync, fd)
#define fdatasync(fd) fsync(fd)
#endif
#endif
#define FC_MACRO_STRINGIFY(x) #x
#define FC_MACRO_TOSTRING(x) FC_MACRO_STRINGIFY(x)
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,6 @@
#include "fast_mblock.h"
#include "ini_file_reader.h"
#include "pthread_func.h"
#include "sockopt.h"
#include "hash.h"
#ifdef __cplusplus
@ -41,105 +40,16 @@ extern "C" {
(strcmp((conn1).ip_addr, (conn2).ip_addr) == 0 && \
(conn1).port == (conn2).port)
typedef enum {
fc_comm_type_sock = 0,
fc_comm_type_rdma,
fc_comm_type_both
} FCCommunicationType;
typedef struct {
int sock;
uint16_t port;
uint8_t af; //address family, AF_INET, AF_INET6 or AF_UNSPEC for auto dedect
bool shared; //for connection pool
FCCommunicationType comm_type;
typedef struct
{
int sock;
uint16_t port;
short socket_domain; //socket domain, AF_INET, AF_INET6 or AF_UNSPEC for auto dedect
bool validate_flag; //for connection pool
char ip_addr[IP_ADDRESS_SIZE];
void *arg1; //for RDMA
char ip_addr[INET6_ADDRSTRLEN];
char args[0]; //for extra data
} ConnectionInfo;
struct fc_server_config;
struct ibv_pd;
typedef void (*fc_set_busy_polling_callback)(const bool busy_polling);
typedef struct ibv_pd *(*fc_alloc_pd_callback)(const char **ip_addrs,
const int count, const int port);
typedef int (*fc_get_connection_size_callback)();
typedef int (*fc_init_connection_callback)(ConnectionInfo *conn,
const bool double_buffers, const int buffer_size, void *arg);
typedef int (*fc_make_connection_callback)(ConnectionInfo *conn,
const char *service_name, const int timeout_ms,
const char *bind_ipaddr, const bool log_connect_error);
typedef bool (*fc_is_connected_callback)(ConnectionInfo *conn);
typedef bool (*fc_send_done_callback)(ConnectionInfo *conn);
typedef void (*fc_close_connection_callback)(ConnectionInfo *conn);
typedef void (*fc_destroy_connection_callback)(ConnectionInfo *conn);
typedef BufferInfo *(*fc_rdma_get_recv_buffer_callback)(ConnectionInfo *conn);
typedef int (*fc_rdma_request_by_buf1_callback)(ConnectionInfo *conn,
const char *data, const int length, const int timeout_ms);
typedef int (*fc_rdma_request_by_buf2_callback)(ConnectionInfo *conn,
const char *data1, const int length1, const char *data2,
const int length2, const int timeout_ms);
typedef int (*fc_rdma_request_by_iov_callback)(ConnectionInfo *conn,
const struct iovec *iov, const int iovcnt,
const int timeout_ms);
typedef int (*fc_rdma_request_by_mix_callback)(ConnectionInfo *conn,
const char *data, const int length, const struct iovec *iov,
const int iovcnt, const int timeout_ms);
typedef int (*fc_rdma_send_by_buf1_callback)(ConnectionInfo *conn,
const char *data, const int length);
typedef int (*fc_rdma_recv_data_callback)(ConnectionInfo *conn,
const bool call_post_recv, const int timeout_ms);
typedef int (*fc_rdma_post_recv_callback)(ConnectionInfo *conn);
typedef struct {
fc_make_connection_callback make_connection;
fc_close_connection_callback close_connection;
fc_is_connected_callback is_connected;
} CommonConnectionCallbacks;
typedef struct {
fc_set_busy_polling_callback set_busy_polling;
fc_alloc_pd_callback alloc_pd;
fc_get_connection_size_callback get_connection_size;
fc_init_connection_callback init_connection;
fc_make_connection_callback make_connection;
fc_close_connection_callback close_connection;
fc_destroy_connection_callback destroy_connection;
fc_is_connected_callback is_connected;
fc_send_done_callback send_done;
fc_rdma_get_recv_buffer_callback get_recv_buffer;
fc_rdma_request_by_buf1_callback request_by_buf1;
fc_rdma_request_by_buf2_callback request_by_buf2;
fc_rdma_request_by_iov_callback request_by_iov;
fc_rdma_request_by_mix_callback request_by_mix;
fc_rdma_send_by_buf1_callback send_by_buf1;
fc_rdma_recv_data_callback recv_data;
fc_rdma_post_recv_callback post_recv;
} RDMAConnectionCallbacks;
typedef struct {
bool inited;
CommonConnectionCallbacks common_callbacks[2];
RDMAConnectionCallbacks rdma_callbacks;
} ConnectionCallbacks;
typedef struct {
struct {
bool enabled;
int htable_capacity;
} tls; //for thread local
struct {
bool double_buffers;
int buffer_size;
struct ibv_pd *pd;
} rdma;
} ConnectionExtraParams;
typedef int (*fc_connection_callback_func)(ConnectionInfo *conn, void *args);
struct tagConnectionManager;
@ -152,32 +62,16 @@ typedef struct tagConnectionNode {
} ConnectionNode;
typedef struct tagConnectionManager {
string_t key;
ConnectionNode *head;
int total_count; //total connections
int free_count; //free connections
struct tagConnectionManager *next;
ConnectionNode *head;
int total_count; //total connections
int free_count; //free connections
pthread_mutex_t lock;
} ConnectionManager;
typedef struct tagConnectionBucket {
ConnectionManager *head;
pthread_mutex_t lock;
} ConnectionBucket;
struct tagConnectionPool;
typedef struct {
ConnectionNode **buckets;
struct tagConnectionPool *cp;
} ConnectionThreadHashTable;
typedef struct tagConnectionPool {
struct {
ConnectionBucket *buckets;
uint32_t capacity;
} hashtable;
int connect_timeout_ms;
HashArray hash_array; //key is ip:port, value is ConnectionManager
pthread_mutex_t lock;
int connect_timeout;
int max_count_per_entry; //0 means no limit
/*
@ -185,6 +79,7 @@ typedef struct tagConnectionPool {
unit: second
*/
int max_idle_time;
int socket_domain; //socket domain
struct fast_mblock_man manager_allocator;
struct fast_mblock_man node_allocator;
@ -198,29 +93,8 @@ typedef struct tagConnectionPool {
fc_connection_callback_func func;
void *args;
} validate_callback;
int extra_data_size;
ConnectionExtraParams extra_params;
pthread_key_t tls_key; //for ConnectionThreadHashTable
} 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;
int conn_pool_global_init_for_rdma();
#define G_COMMON_CONNECTION_CALLBACKS g_connection_callbacks.common_callbacks
#define G_RDMA_CONNECTION_CALLBACKS g_connection_callbacks.rdma_callbacks
/**
* init ex function
* parameters:
@ -228,22 +102,21 @@ int conn_pool_global_init_for_rdma();
* connect_timeout: the connect timeout in seconds
* max_count_per_entry: max connection count per host:port
* max_idle_time: reconnect the server after max idle time in seconds
* af: the socket domain
* htable_capacity: the capacity of connection hash table
* socket_domain: the socket domain
* htable_init_capacity: the init capacity of connection hash table
* connect_done_func: the connect done connection callback
* connect_done_args: the args for connect done connection callback
* validate_func: the validate connection callback
* validate_args: the args for validate connection callback
* extra_data_size: the extra data size of connection
* extra_params: for RDMA
* return 0 for success, != 0 for error
*/
int conn_pool_init_ex1(ConnectionPool *cp, const int connect_timeout,
int conn_pool_init_ex1(ConnectionPool *cp, int connect_timeout,
const int max_count_per_entry, const int max_idle_time,
const int htable_capacity, fc_connection_callback_func connect_done_func,
void *connect_done_args, fc_connection_callback_func validate_func,
void *validate_args, const int extra_data_size,
const ConnectionExtraParams *extra_params);
const int socket_domain, const int htable_init_capacity,
fc_connection_callback_func connect_done_func, void *connect_done_args,
fc_connection_callback_func validate_func, void *validate_args,
const int extra_data_size);
/**
* init ex function
@ -252,18 +125,18 @@ int conn_pool_init_ex1(ConnectionPool *cp, const int connect_timeout,
* connect_timeout: the connect timeout in seconds
* max_count_per_entry: max connection count per host:port
* max_idle_time: reconnect the server after max idle time in seconds
* socket_domain: the socket domain
* return 0 for success, != 0 for error
*/
static inline int conn_pool_init_ex(ConnectionPool *cp,
const int connect_timeout, const int max_count_per_entry,
const int max_idle_time)
static inline int conn_pool_init_ex(ConnectionPool *cp, int connect_timeout,
const int max_count_per_entry, const int max_idle_time,
const int socket_domain)
{
const int htable_capacity = 0;
const int htable_init_capacity = 0;
const int extra_data_size = 0;
const ConnectionExtraParams *extra_params = NULL;
return conn_pool_init_ex1(cp, connect_timeout, max_count_per_entry,
max_idle_time, htable_capacity, NULL, NULL, NULL, NULL,
extra_data_size, extra_params);
max_idle_time, socket_domain, htable_init_capacity,
NULL, NULL, NULL, NULL, extra_data_size);
}
/**
@ -275,15 +148,15 @@ static inline int conn_pool_init_ex(ConnectionPool *cp,
* max_idle_time: reconnect the server after max idle time in seconds
* return 0 for success, != 0 for error
*/
static inline int conn_pool_init(ConnectionPool *cp, const int connect_timeout,
static inline int conn_pool_init(ConnectionPool *cp, int connect_timeout,
const int max_count_per_entry, const int max_idle_time)
{
const int htable_capacity = 0;
const int socket_domain = AF_INET;
const int htable_init_capacity = 0;
const int extra_data_size = 0;
const ConnectionExtraParams *extra_params = NULL;
return conn_pool_init_ex1(cp, connect_timeout, max_count_per_entry,
max_idle_time, htable_capacity, NULL, NULL, NULL, NULL,
extra_data_size, extra_params);
max_idle_time, socket_domain, htable_init_capacity,
NULL, NULL, NULL, NULL, extra_data_size);
}
/**
@ -299,17 +172,11 @@ void conn_pool_destroy(ConnectionPool *cp);
* parameters:
* cp: the ConnectionPool
* conn: the connection
* service_name: the service name to log
* shared: if the connection shared
* err_no: return the the errno, 0 for success
* return != NULL for success, NULL for error
*/
ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
const ConnectionInfo *conn, const char *service_name,
const bool shared, int *err_no);
#define conn_pool_get_connection(cp, conn, err_no) \
conn_pool_get_connection_ex(cp, conn, NULL, false, err_no)
ConnectionInfo *conn_pool_get_connection(ConnectionPool *cp,
const ConnectionInfo *conn, int *err_no);
#define conn_pool_close_connection(cp, conn) \
conn_pool_close_connection_ex(cp, conn, false)
@ -322,94 +189,61 @@ ConnectionInfo *conn_pool_get_connection_ex(ConnectionPool *cp,
* bForce: set true to close the socket, else only push back to connection pool
* return 0 for success, != 0 for error
*/
int conn_pool_close_connection_ex(ConnectionPool *cp,
ConnectionInfo *conn, const bool bForce);
int conn_pool_close_connection_ex(ConnectionPool *cp, ConnectionInfo *conn,
const bool bForce);
/**
* disconnect from the server
* parameters:
* conn: the connection
* pConnection: the connection
* return 0 for success, != 0 for error
*/
static inline void conn_pool_disconnect_server(ConnectionInfo *conn)
{
if (conn->sock >= 0)
{
close(conn->sock);
conn->sock = -1;
}
}
static inline bool conn_pool_is_connected(ConnectionInfo *conn)
{
return (conn->sock >= 0);
}
void conn_pool_disconnect_server(ConnectionInfo *pConnection);
/**
* connect to the server
* parameters:
* pConnection: the connection
* service_name: the service name to log
* connect_timeout_ms: the connect timeout in milliseconds
* connect_timeout: the connect timeout in seconds
* bind_ipaddr: the ip address to bind, NULL or empty for any
* log_connect_error: if log error info when connect fail
* NOTE: pConnection->sock will be closed when it >= 0 before connect
* return 0 for success, != 0 for error
*/
int conn_pool_connect_server_ex1(ConnectionInfo *conn,
const char *service_name, const int connect_timeout_ms,
const char *bind_ipaddr, const bool log_connect_error);
/**
* connect to the server
* parameters:
* pConnection: the connection
* connect_timeout_ms: the connect timeout in milliseconds
* bind_ipaddr: the ip address to bind, NULL or empty for any
* log_connect_error: if log error info when connect fail
* NOTE: pConnection->sock will be closed when it >= 0 before connect
* return 0 for success, != 0 for error
*/
static inline int conn_pool_connect_server_ex(ConnectionInfo *pConnection,
const int connect_timeout_ms, const char *bind_ipaddr,
const bool log_connect_error)
{
const char *service_name = NULL;
return conn_pool_connect_server_ex1(pConnection, service_name,
connect_timeout_ms, bind_ipaddr, log_connect_error);
}
int conn_pool_connect_server_ex(ConnectionInfo *pConnection,
const int connect_timeout, const char *bind_ipaddr,
const bool log_connect_error);
/**
* connect to the server
* parameters:
* pConnection: the connection
* connect_timeout_ms: the connect timeout in seconds
* connect_timeout: the connect timeout in seconds
* NOTE: pConnection->sock will be closed when it >= 0 before connect
* return 0 for success, != 0 for error
*/
static inline int conn_pool_connect_server(ConnectionInfo *pConnection,
const int connect_timeout_ms)
const int connect_timeout)
{
const char *service_name = NULL;
const char *bind_ipaddr = NULL;
return conn_pool_connect_server_ex1(pConnection, service_name,
connect_timeout_ms, bind_ipaddr, true);
return conn_pool_connect_server_ex(pConnection,
connect_timeout, bind_ipaddr, true);
}
/**
* connect to the server
* parameters:
* pConnection: the connection
* connect_timeout_ms: the connect timeout in seconds
* connect_timeout: the connect timeout in seconds
* return 0 for success, != 0 for error
*/
static inline int conn_pool_connect_server_anyway(ConnectionInfo *pConnection,
const int connect_timeout_ms)
const int connect_timeout)
{
const char *service_name = NULL;
const char *bind_ipaddr = NULL;
pConnection->sock = -1;
return conn_pool_connect_server_ex1(pConnection, service_name,
connect_timeout_ms, bind_ipaddr, true);
return conn_pool_connect_server_ex(pConnection,
connect_timeout, bind_ipaddr, true);
}
/**
@ -428,13 +262,12 @@ int conn_pool_async_connect_server_ex(ConnectionInfo *conn,
/**
* connection pool stat
* get connection count of the pool
* parameters:
* cp: the ConnectionPool
* stat: the output stat
* return none
* return current connection count
*/
void conn_pool_stat(ConnectionPool *cp, ConnectionPoolStat *stat);
int conn_pool_get_connection_count(ConnectionPool *cp);
/**
* load server info from config file
@ -472,9 +305,10 @@ int conn_pool_parse_server_info(const char *pServerStr,
static inline void conn_pool_set_server_info(ConnectionInfo *pServerInfo,
const char *ip_addr, const int port)
{
fc_safe_strcpy(pServerInfo->ip_addr, ip_addr);
snprintf(pServerInfo->ip_addr, sizeof(pServerInfo->ip_addr),
"%s", ip_addr);
pServerInfo->port = port;
pServerInfo->af = is_ipv6_addr(ip_addr) ? AF_INET6 : AF_INET;
pServerInfo->socket_domain = AF_UNSPEC;
pServerInfo->sock = -1;
}
@ -488,55 +322,6 @@ static inline int conn_pool_compare_ip_and_port(const char *ip1,
return port1 - port2;
}
ConnectionInfo *conn_pool_alloc_connection_ex(
const FCCommunicationType comm_type,
const int extra_data_size,
const ConnectionExtraParams *extra_params,
int *err_no);
static inline ConnectionInfo *conn_pool_alloc_connection(
const FCCommunicationType comm_type,
const ConnectionExtraParams *extra_params,
int *err_no)
{
const int extra_data_size = 0;
return conn_pool_alloc_connection_ex(comm_type,
extra_data_size, extra_params, err_no);
}
static inline void conn_pool_free_connection(ConnectionInfo *conn)
{
free(conn);
}
int conn_pool_set_rdma_extra_params_ex(ConnectionExtraParams *extra_params,
struct fc_server_config *server_cfg, const int server_group_index,
const bool double_buffers);
static inline int conn_pool_set_rdma_extra_params(
ConnectionExtraParams *extra_params,
struct fc_server_config *server_cfg,
const int server_group_index)
{
const bool double_buffers = false;
return conn_pool_set_rdma_extra_params_ex(extra_params,
server_cfg, server_group_index, double_buffers);
}
static inline const char *fc_comm_type_str(const FCCommunicationType type)
{
switch (type) {
case fc_comm_type_sock:
return "socket";
case fc_comm_type_rdma:
return "rdma";
case fc_comm_type_both:
return "both";
default:
return "unkown";
}
}
#ifdef __cplusplus
}
#endif

View File

@ -25,6 +25,14 @@
#define BYTES_ALIGN(x, pad_mask) (((x) + pad_mask) & (~pad_mask))
struct allocator_wrapper {
int alloc_bytes;
short allocator_index;
short magic_number;
};
static struct fast_allocator_info malloc_allocator;
#define ADD_ALLOCATOR_TO_ARRAY(acontext, allocator, _pooled) \
do { \
(allocator)->index = acontext->allocator_array.count; \
@ -55,19 +63,17 @@ static int fast_allocator_malloc_trunk_check(const int alloc_bytes, void *args)
acontext->allocator_array.malloc_bytes_limit ? 0 : EOVERFLOW;
}
static void fast_allocator_malloc_trunk_notify_func(
const enum fast_mblock_notify_type type,
const struct fast_mblock_malloc *node, void *args)
static void fast_allocator_malloc_trunk_notify_func(const int alloc_bytes, void *args)
{
if (type == fast_mblock_notify_type_alloc)
if (alloc_bytes > 0)
{
__sync_add_and_fetch(&((struct fast_allocator_context *)args)->
allocator_array.malloc_bytes, node->trunk_size);
allocator_array.malloc_bytes, alloc_bytes);
}
else
{
__sync_sub_and_fetch(&((struct fast_allocator_context *)args)->
allocator_array.malloc_bytes, node->trunk_size);
allocator_array.malloc_bytes, -1 * alloc_bytes);
}
}
@ -136,22 +142,20 @@ static int allocator_array_check_capacity(struct fast_allocator_context *acontex
}
static int region_init(struct fast_allocator_context *acontext,
const char *mblock_name_prefix, struct fast_mblock_object_callbacks
*object_callbacks, struct fast_region_info *region)
const char *mblock_name_prefix, struct fast_region_info *region)
{
const int64_t alloc_elements_limit = 0;
const int prealloc_trunk_count = 0;
int result;
int bytes;
int element_size;
struct fast_mblock_trunk_callbacks trunk_callbacks;
int allocator_count;
struct fast_allocator_info *allocator;
char *name;
char name_buff[FAST_MBLOCK_NAME_SIZE];
region->pad_mask = region->step - 1;
region->count = (region->end - region->start) / region->step;
bytes = sizeof(struct fast_allocator_info) * region->count;
allocator_count = (region->end - region->start) / region->step;
bytes = sizeof(struct fast_allocator_info) * allocator_count;
region->allocators = (struct fast_allocator_info *)fc_malloc(bytes);
if (region->allocators == NULL)
{
@ -159,29 +163,17 @@ static int region_init(struct fast_allocator_context *acontext,
}
memset(region->allocators, 0, bytes);
if ((result=allocator_array_check_capacity(acontext, region->count)) != 0)
if ((result=allocator_array_check_capacity(acontext, allocator_count)) != 0)
{
return result;
}
if (region->count == 1) {
if (region->start == 0) {
region->step += acontext->extra_size;
} else {
region->start += acontext->extra_size;
}
region->end += acontext->extra_size;
}
trunk_callbacks.check_func = fast_allocator_malloc_trunk_check;
trunk_callbacks.notify_func = fast_allocator_malloc_trunk_notify_func;
name = name_buff;
result = 0;
allocator = region->allocators;
for (element_size = region->start + region->step;
element_size <= region->end;
element_size += region->step, allocator++)
{
for (element_size=region->start+region->step; element_size<=region->end;
element_size+=region->step,allocator++)
{
if (mblock_name_prefix != NULL)
{
snprintf(name, FAST_MBLOCK_NAME_SIZE, "%s-%d",
@ -191,12 +183,10 @@ static int region_init(struct fast_allocator_context *acontext,
{
name = NULL;
}
trunk_callbacks.args = acontext;
result = fast_mblock_init_ex2(&allocator->mblock, name, element_size,
region->alloc_elements_once, alloc_elements_limit,
prealloc_trunk_count, object_callbacks,
acontext->need_lock, &trunk_callbacks);
region->alloc_elements_once, alloc_elements_limit, NULL, NULL,
acontext->need_lock, fast_allocator_malloc_trunk_check,
fast_allocator_malloc_trunk_notify_func, acontext);
if (result != 0)
{
break;
@ -226,11 +216,10 @@ static void region_destroy(struct fast_allocator_context *acontext,
}
int fast_allocator_init_ex(struct fast_allocator_context *acontext,
const char *mblock_name_prefix, const int obj_size,
struct fast_mblock_object_callbacks *object_callbacks,
struct fast_region_info *regions, const int region_count,
const int64_t alloc_bytes_limit, const double expect_usage_ratio,
const int reclaim_interval, const bool need_lock)
const char *mblock_name_prefix, struct fast_region_info *regions,
const int region_count, const int64_t alloc_bytes_limit,
const double expect_usage_ratio, const int reclaim_interval,
const bool need_lock)
{
int result;
int bytes;
@ -265,7 +254,6 @@ int fast_allocator_init_ex(struct fast_allocator_context *acontext,
acontext->allocator_array.malloc_bytes_limit = alloc_bytes_limit /
acontext->allocator_array.expect_usage_ratio;
acontext->allocator_array.reclaim_interval = reclaim_interval;
acontext->extra_size = sizeof(struct fast_allocator_wrapper) + obj_size;
acontext->need_lock = need_lock;
result = 0;
previous_end = 0;
@ -288,46 +276,33 @@ int fast_allocator_init_ex(struct fast_allocator_context *acontext,
result = EINVAL;
break;
}
if (pRegion->step <= 0)
if (pRegion->step <= 0 || !is_power2(pRegion->step))
{
logError("file: "__FILE__", line: %d, "
"invalid step: %d <= 0",
"invalid step: %d",
__LINE__, pRegion->step);
result = EINVAL;
break;
}
if ((pRegion->end - pRegion->start) / pRegion->step > 1)
{
if (!is_power2(pRegion->step))
{
logError("file: "__FILE__", line: %d, "
"invalid step: %d, expect power of 2",
__LINE__, pRegion->step);
result = EINVAL;
break;
}
if (pRegion->start % pRegion->step != 0)
{
logError("file: "__FILE__", line: %d, "
"invalid start: %d, must multiple of step: %d",
__LINE__, pRegion->start, pRegion->step);
result = EINVAL;
break;
}
if (pRegion->end % pRegion->step != 0)
{
logError("file: "__FILE__", line: %d, "
"invalid end: %d, must multiple of step: %d",
__LINE__, pRegion->end, pRegion->step);
result = EINVAL;
break;
}
}
if (pRegion->start % pRegion->step != 0)
{
logError("file: "__FILE__", line: %d, "
"invalid start: %d, must multiple of step: %d",
__LINE__, pRegion->start, pRegion->step);
result = EINVAL;
break;
}
if (pRegion->end % pRegion->step != 0)
{
logError("file: "__FILE__", line: %d, "
"invalid end: %d, must multiple of step: %d",
__LINE__, pRegion->end, pRegion->step);
result = EINVAL;
break;
}
previous_end = pRegion->end;
if ((result=region_init(acontext, mblock_name_prefix,
object_callbacks, pRegion)) != 0)
if ((result=region_init(acontext, mblock_name_prefix, pRegion)) != 0)
{
break;
}
@ -343,12 +318,10 @@ int fast_allocator_init_ex(struct fast_allocator_context *acontext,
return result;
}
ADD_ALLOCATOR_TO_ARRAY(acontext, &acontext->
allocator_array.malloc_allocator, false);
ADD_ALLOCATOR_TO_ARRAY(acontext, &malloc_allocator, false);
/*
logInfo("sizeof(struct fast_allocator_wrapper): %d, allocator_array count: %d",
(int)sizeof(struct fast_allocator_wrapper), acontext->allocator_array.count);
logInfo("sizeof(struct allocator_wrapper): %d, allocator_array count: %d",
(int)sizeof(struct allocator_wrapper), acontext->allocator_array.count);
*/
return result;
}
@ -360,7 +333,6 @@ int fast_allocator_init(struct fast_allocator_context *acontext,
{
#define DEFAULT_REGION_COUNT 5
const int obj_size = 0;
struct fast_region_info regions[DEFAULT_REGION_COUNT];
FAST_ALLOCATOR_INIT_REGION(regions[0], 0, 256, 8, 4096);
@ -369,9 +341,9 @@ int fast_allocator_init(struct fast_allocator_context *acontext,
FAST_ALLOCATOR_INIT_REGION(regions[3], 4096, 16384, 256, 64);
FAST_ALLOCATOR_INIT_REGION(regions[4], 16384, 65536, 1024, 16);
return fast_allocator_init_ex(acontext, mblock_name_prefix, obj_size,
NULL, regions, DEFAULT_REGION_COUNT, alloc_bytes_limit,
expect_usage_ratio, reclaim_interval, need_lock);
return fast_allocator_init_ex(acontext, mblock_name_prefix, regions,
DEFAULT_REGION_COUNT, alloc_bytes_limit, expect_usage_ratio,
reclaim_interval, need_lock);
}
void fast_allocator_destroy(struct fast_allocator_context *acontext)
@ -396,8 +368,8 @@ void fast_allocator_destroy(struct fast_allocator_context *acontext)
memset(acontext, 0, sizeof(*acontext));
}
static struct fast_allocator_info *get_allocator(struct fast_allocator_context
*acontext, int *alloc_bytes)
static struct fast_allocator_info *get_allocator(struct fast_allocator_context *acontext,
int *alloc_bytes)
{
struct fast_region_info *pRegion;
struct fast_region_info *region_end;
@ -406,19 +378,14 @@ static struct fast_allocator_info *get_allocator(struct fast_allocator_context
for (pRegion=acontext->regions; pRegion<region_end; pRegion++)
{
if (*alloc_bytes <= pRegion->end)
{
if (pRegion->count == 1) {
*alloc_bytes = pRegion->allocators[0].mblock.info.element_size;
return pRegion->allocators + 0;
} else {
*alloc_bytes = BYTES_ALIGN(*alloc_bytes, pRegion->pad_mask);
return pRegion->allocators + ((*alloc_bytes -
pRegion->start) / pRegion->step) - 1;
}
}
{
*alloc_bytes = BYTES_ALIGN(*alloc_bytes, pRegion->pad_mask);
return pRegion->allocators + ((*alloc_bytes -
pRegion->start) / pRegion->step) - 1;
}
}
return &acontext->allocator_array.malloc_allocator;
return &malloc_allocator;
}
int fast_allocator_retry_reclaim(struct fast_allocator_context *acontext,
@ -448,7 +415,7 @@ int fast_allocator_retry_reclaim(struct fast_allocator_context *acontext,
return EAGAIN;
}
for (i=0; i<acontext->allocator_array.count; i++)
for (i=0; i< acontext->allocator_array.count; i++)
{
if (fast_mblock_reclaim(&acontext->allocator_array.
allocators[i]->mblock, 0, &reclaim_count, NULL) == 0)
@ -463,15 +430,6 @@ int fast_allocator_retry_reclaim(struct fast_allocator_context *acontext,
return *total_reclaim_bytes > 0 ? 0 : EAGAIN;
}
static inline void malloc_trunk_notify(
const enum fast_mblock_notify_type type,
const int alloc_bytes, void *args)
{
struct fast_mblock_malloc node;
node.trunk_size = alloc_bytes;
fast_allocator_malloc_trunk_notify_func(type, &node, args);
}
void *fast_allocator_alloc(struct fast_allocator_context *acontext,
const int bytes)
{
@ -479,21 +437,20 @@ void *fast_allocator_alloc(struct fast_allocator_context *acontext,
int64_t total_reclaim_bytes;
struct fast_allocator_info *allocator_info;
void *ptr;
void *obj;
if (bytes < 0)
{
return NULL;
}
alloc_bytes = acontext->extra_size + bytes;
alloc_bytes = sizeof(struct allocator_wrapper) + bytes;
allocator_info = get_allocator(acontext, &alloc_bytes);
if (allocator_info->pooled)
{
ptr = fast_mblock_alloc_object(&allocator_info->mblock);
if (ptr == NULL)
{
if (acontext->allocator_array.reclaim_interval < 0)
if (acontext->allocator_array.reclaim_interval <= 0)
{
return NULL;
}
@ -512,7 +469,6 @@ void *fast_allocator_alloc(struct fast_allocator_context *acontext,
return NULL;
}
}
obj = (char *)ptr + sizeof(struct fast_allocator_wrapper);
}
else
{
@ -525,42 +481,29 @@ void *fast_allocator_alloc(struct fast_allocator_context *acontext,
{
return NULL;
}
malloc_trunk_notify(fast_mblock_notify_type_alloc,
alloc_bytes, acontext);
obj = (char *)ptr + sizeof(struct fast_allocator_wrapper);
if (acontext->allocator_array.allocators[0]->mblock.
object_callbacks.init_func != NULL)
{
struct fast_mblock_man *mblock;
mblock = &acontext->allocator_array.allocators[0]->mblock;
mblock->object_callbacks.init_func(obj,
mblock->object_callbacks.args);
}
fast_allocator_malloc_trunk_notify_func(alloc_bytes, acontext);
}
((struct fast_allocator_wrapper *)ptr)->allocator_index =
allocator_info->index;
((struct fast_allocator_wrapper *)ptr)->magic_number =
allocator_info->magic_number;
((struct fast_allocator_wrapper *)ptr)->alloc_bytes = alloc_bytes;
((struct allocator_wrapper *)ptr)->allocator_index = allocator_info->index;
((struct allocator_wrapper *)ptr)->magic_number = allocator_info->magic_number;
((struct allocator_wrapper *)ptr)->alloc_bytes = alloc_bytes;
__sync_add_and_fetch(&acontext->alloc_bytes, alloc_bytes);
return obj;
return (char *)ptr + sizeof(struct allocator_wrapper);
}
void fast_allocator_free(struct fast_allocator_context *acontext, void *obj)
void fast_allocator_free(struct fast_allocator_context *acontext, void *ptr)
{
struct fast_allocator_wrapper *pWrapper;
struct allocator_wrapper *pWrapper;
struct fast_allocator_info *allocator_info;
void *ptr;
if (obj == NULL)
void *obj;
if (ptr == NULL)
{
return;
}
ptr = (char *)obj - sizeof(struct fast_allocator_wrapper);
pWrapper = (struct fast_allocator_wrapper *)ptr;
obj = (char *)ptr - sizeof(struct allocator_wrapper);
pWrapper = (struct allocator_wrapper *)obj;
if (pWrapper->allocator_index < 0 || pWrapper->allocator_index >=
acontext->allocator_array.count)
{
@ -570,8 +513,7 @@ void fast_allocator_free(struct fast_allocator_context *acontext, void *obj)
return;
}
allocator_info = acontext->allocator_array.
allocators[pWrapper->allocator_index];
allocator_info = acontext->allocator_array.allocators[pWrapper->allocator_index];
if (pWrapper->magic_number != allocator_info->magic_number)
{
logError("file: "__FILE__", line: %d, "
@ -586,23 +528,13 @@ void fast_allocator_free(struct fast_allocator_context *acontext, void *obj)
pWrapper->magic_number = 0;
if (allocator_info->pooled)
{
fast_mblock_free_object(&allocator_info->mblock, ptr);
fast_mblock_free_object(&allocator_info->mblock, obj);
}
else
{
malloc_trunk_notify(fast_mblock_notify_type_reclaim,
pWrapper->alloc_bytes, acontext);
if (acontext->allocator_array.allocators[0]->mblock.
object_callbacks.destroy_func != NULL)
{
struct fast_mblock_man *mblock;
mblock = &acontext->allocator_array.allocators[0]->mblock;
mblock->object_callbacks.destroy_func(obj,
mblock->object_callbacks.args);
}
free(ptr);
}
{
fast_allocator_malloc_trunk_notify_func(-1 * pWrapper->alloc_bytes, acontext);
free(obj);
}
}
char *fast_allocator_memdup(struct fast_allocator_context *acontext,

View File

@ -40,48 +40,39 @@ struct fast_region_info
int step;
int alloc_elements_once;
int pad_mask; //for internal use
int count;
struct fast_allocator_info *allocators;
};
struct fast_allocator_array
{
int count;
int alloc;
int reclaim_interval; //< 0 for never reclaim
int last_reclaim_time;
volatile int64_t malloc_bytes; //total alloc bytes
int64_t malloc_bytes_limit; //water mark bytes for malloc
double expect_usage_ratio;
struct fast_allocator_info malloc_allocator;
struct fast_allocator_info **allocators;
};
struct fast_allocator_wrapper {
int alloc_bytes;
short allocator_index;
short magic_number;
int count;
int alloc;
int reclaim_interval; //<= 0 for never reclaim
int last_reclaim_time;
volatile int64_t malloc_bytes; //total alloc bytes
int64_t malloc_bytes_limit; //water mark bytes for malloc
double expect_usage_ratio;
struct fast_allocator_info **allocators;
};
struct fast_allocator_context
{
struct fast_region_info *regions;
int region_count;
int extra_size;
struct fast_allocator_array allocator_array;
int64_t alloc_bytes_limit; //water mark bytes for alloc
int64_t alloc_bytes_limit; //mater mark bytes for alloc
volatile int64_t alloc_bytes; //total alloc bytes
bool need_lock; //if need mutex lock for acontext
};
#define FAST_ALLOCATOR_INIT_REGION(region, _start, _end, _step, _alloc_once) \
do { \
(region).start = _start; \
(region).end = _end; \
(region).step = _step; \
(region).alloc_elements_once = _alloc_once; \
region.start = _start; \
region.end = _end; \
region.step = _step; \
region.alloc_elements_once = _alloc_once; \
} while(0)
#ifdef __cplusplus
@ -95,7 +86,7 @@ parameters:
mblock_name_prefix: the name prefix of mblock
alloc_bytes_limit: the alloc limit, 0 for no limit
expect_usage_ratio: the trunk usage ratio
reclaim_interval: reclaim interval in second, < 0 for never reclaim
reclaim_interval: reclaim interval in second, 0 for never reclaim
need_lock: if need lock
return error no, 0 for success, != 0 fail
*/
@ -108,23 +99,19 @@ int fast_allocator_init(struct fast_allocator_context *acontext,
allocator init
parameters:
acontext: the context pointer
mblock_name_prefix: name prefix of object alloctors
obj_size: element size of object as sizeof(obj)
object_callbacks: object init and destroy callbacks
regions: the region array
region_count: the region count
alloc_bytes_limit: the alloc limit, 0 for no limit
alloc_bytes_limit: the alloc limit, 0 for no limit
expect_usage_ratio: the trunk usage ratio
reclaim_interval: reclaim interval in second, < 0 for never reclaim
reclaim_interval: reclaim interval in second, 0 for never reclaim
need_lock: if need lock
return error no, 0 for success, != 0 fail
*/
int fast_allocator_init_ex(struct fast_allocator_context *acontext,
const char *mblock_name_prefix, const int obj_size,
struct fast_mblock_object_callbacks *object_callbacks,
struct fast_region_info *regions, const int region_count,
const int64_t alloc_bytes_limit, const double expect_usage_ratio,
const int reclaim_interval, const bool need_lock);
const char *mblock_name_prefix, struct fast_region_info *regions,
const int region_count, const int64_t alloc_bytes_limit,
const double expect_usage_ratio, const int reclaim_interval,
const bool need_lock);
/**
allocator destroy
@ -147,10 +134,10 @@ void* fast_allocator_alloc(struct fast_allocator_context *acontext,
free a node (put a node to the context)
parameters:
acontext: the context pointer
obj: the object ptr to free
ptr: the pointer to free
return none
*/
void fast_allocator_free(struct fast_allocator_context *acontext, void *obj);
void fast_allocator_free(struct fast_allocator_context *acontext, void *ptr);
/**
retry reclaim free trunks
@ -191,19 +178,9 @@ static inline int fast_allocator_alloc_string(struct fast_allocator_context
return fast_allocator_alloc_string_ex(acontext, dest, src->str, src->len);
}
static inline int64_t fast_allocator_avail_memory(
struct fast_allocator_context *acontext)
{
if (acontext->alloc_bytes_limit == 0) {
return INT64_MIN;
}
return acontext->alloc_bytes_limit - __sync_add_and_fetch(
&acontext->allocator_array.malloc_bytes, 0);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -26,28 +26,23 @@
#include "fc_memory.h"
#include "fast_buffer.h"
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity,
const bool binary_mode, const bool check_capacity)
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity)
{
buffer->length = 0;
buffer->binary_mode = binary_mode;
if (init_capacity > 0)
{
buffer->alloc_size = init_capacity;
buffer->check_capacity = check_capacity;
}
else
{
buffer->alloc_size = 256;
buffer->check_capacity = true;
}
buffer->data = (char *)fc_malloc(buffer->alloc_size);
if (buffer->data == NULL)
{
return ENOMEM;
}
fast_buffer_set_null_terminator(buffer);
*(buffer->data) = '\0';
return 0;
}
@ -93,9 +88,7 @@ int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity)
if (buffer->length > 0) {
memcpy(buff, buffer->data, buffer->length);
if (!buffer->binary_mode) {
*(buff + buffer->length) = '\0';
}
*(buff + buffer->length) = '\0';
}
free(buffer->data);
@ -134,7 +127,7 @@ int fast_buffer_append(FastBuffer *buffer, const char *format, ...)
}
else
{
fast_buffer_set_null_terminator(buffer); //restore
*(buffer->data + buffer->length) = '\0'; //restore
}
}
return result;
@ -155,7 +148,7 @@ int fast_buffer_append_buff(FastBuffer *buffer, const char *data, const int len)
memcpy(buffer->data + buffer->length, data, len);
buffer->length += len;
fast_buffer_set_null_terminator(buffer);
*(buffer->data + buffer->length) = '\0';
return 0;
}
@ -178,6 +171,32 @@ int fast_buffer_append_binary(FastBuffer *buffer,
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)
{
struct stat st;

View File

@ -17,14 +17,12 @@
#define __FAST_BUFFER_H__
#include <stdint.h>
#include "shared_func.h"
#include "common_define.h"
typedef struct fast_buffer {
char *data;
int alloc_size;
int length;
bool binary_mode;
bool check_capacity;
char *data;
int alloc_size;
int length;
} FastBuffer;
#ifdef __cplusplus
@ -41,39 +39,26 @@ static inline char *fast_buffer_data(FastBuffer *buffer)
return buffer->data;
}
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);
}
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity);
static inline int fast_buffer_init(FastBuffer *buffer)
{
const int init_capacity = 0;
return fast_buffer_init1(buffer, init_capacity);
return fast_buffer_init_ex(buffer, 0);
}
#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)
static inline void fast_buffer_reset(FastBuffer *buffer)
{
buffer->length = 0;
fast_buffer_set_null_terminator(buffer);
*buffer->data = '\0';
}
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);
static inline int fast_buffer_check_capacity(FastBuffer *buffer,
@ -101,50 +86,9 @@ int fast_buffer_append_buff(FastBuffer *buffer,
int fast_buffer_append_binary(FastBuffer *buffer,
const void *data, const int len);
static inline int fast_buffer_append_char(FastBuffer *buffer, const char ch)
{
int result;
int fast_buffer_append_int(FastBuffer *buffer, const int 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_int64(FastBuffer *buffer, const int64_t n);
int fast_buffer_append_file(FastBuffer *buffer, const char *filename);

View File

@ -35,13 +35,11 @@ struct _fast_mblock_manager
#define INIT_HEAD(head) (head)->next = (head)->prev = head
#define IS_EMPTY(head) ((head)->next == head)
#define CALC_USED_RATIO(info) \
(info->element_total_count > 0 ? 100.00 * (double) \
info->element_used_count / (double) \
info->element_total_count : 0.00)
static struct _fast_mblock_manager mblock_manager = {false, 0};
#define fast_mblock_get_trunk_size(mblock, block_size, element_count) \
(sizeof(struct fast_mblock_malloc) + block_size * element_count)
int fast_mblock_manager_init()
{
int result;
@ -61,20 +59,13 @@ int fast_mblock_manager_init()
static int cmp_mblock_info(struct fast_mblock_man *mb1, struct fast_mblock_man *mb2)
{
int result;
result = strcmp(mb1->info.name, mb2->info.name);
if (result != 0)
{
return result;
}
result = mb1->info.element_size - mb2->info.element_size;
if (result != 0)
{
return result;
}
return mb1->info.trunk_size - mb2->info.trunk_size;
return mb1->info.element_size - mb2->info.element_size;
}
static void add_to_mblock_list(struct fast_mblock_man *mblock)
@ -131,7 +122,6 @@ static void delete_from_mblock_list(struct fast_mblock_man *mblock)
if (copy_name) { \
strcpy(pStat->name, current->info.name); \
pStat->trunk_size = current->info.trunk_size; \
pStat->block_size = current->info.block_size; \
pStat->element_size = current->info.element_size; \
} \
pStat->element_total_count += current->info.element_total_count; \
@ -234,30 +224,10 @@ static int fast_mblock_info_cmp_by_element_size(const void *p1, const void *p2)
return pStat2->element_size - pStat1->element_size;
}
//desc order
static int fast_mblock_info_cmp_by_used_ratio(const void *p1, const void *p2)
{
struct fast_mblock_info *pStat1;
struct fast_mblock_info *pStat2;
double sub;
pStat1 = (struct fast_mblock_info *)p1;
pStat2 = (struct fast_mblock_info *)p2;
sub = CALC_USED_RATIO(pStat2) - CALC_USED_RATIO(pStat1);
if (sub <= -0.00005) {
return -1;
} else if (sub >= 0.00005) {
return 1;
} else {
return fast_mblock_info_cmp_by_alloc_bytes(p1, p2);
}
}
int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
{
int result;
int count;
int output_count;
int alloc_size;
struct fast_mblock_info *stats;
struct fast_mblock_info *pStat;
@ -265,7 +235,7 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
stats = NULL;
count = 0;
alloc_size = 256;
alloc_size = 64;
result = EOVERFLOW;
while (result == EOVERFLOW)
{
@ -285,37 +255,26 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
int64_t used_mem;
int64_t amem;
int64_t delay_free_mem;
int name_len;
char *size_caption;
char alloc_mem_str[32];
char used_mem_str[32];
char delay_free_mem_str[32];
if (order_by == FAST_MBLOCK_ORDER_BY_ELEMENT_SIZE)
if (order_by == FAST_MBLOCK_ORDER_BY_ALLOC_BYTES)
{
size_caption = "el_size";
qsort(stats, count, sizeof(struct fast_mblock_info),
fast_mblock_info_cmp_by_element_size);
}
else if (order_by == FAST_MBLOCK_ORDER_BY_ALLOC_BYTES)
{
size_caption = "tr_size";
qsort(stats, count, sizeof(struct fast_mblock_info),
fast_mblock_info_cmp_by_alloc_bytes);
}
else
{
size_caption = "tr_size";
qsort(stats, count, sizeof(struct fast_mblock_info),
fast_mblock_info_cmp_by_used_ratio);
fast_mblock_info_cmp_by_element_size);
}
output_count = 0;
alloc_mem = 0;
used_mem = 0;
delay_free_mem = 0;
logInfo("%20s %10s %8s %12s %11s %10s %10s %10s %10s %12s",
"name", size_caption, "instance", "alloc_bytes",
logInfo("%20s %8s %8s %12s %11s %10s %10s %10s %10s %12s",
"name", "el_size", "instance", "alloc_bytes",
"trunc_alloc", "trunk_used", "el_alloc",
"el_used", "delay_free", "used_ratio");
stat_end = stats + count;
@ -325,10 +284,10 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
{
amem = (int64_t)pStat->trunk_size * pStat->trunk_total_count;
alloc_mem += amem;
used_mem += fast_mblock_get_block_size(pStat->
element_size) * pStat->element_used_count;
delay_free_mem += fast_mblock_get_block_size(pStat->
element_size) * pStat->delay_free_elements;
used_mem += GET_BLOCK_SIZE(*pStat) *
pStat->element_used_count;
delay_free_mem += GET_BLOCK_SIZE(*pStat) *
pStat->delay_free_elements;
}
else
{
@ -339,19 +298,15 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
}
}
name_len = strlen(pStat->name);
if (name_len > 20) {
name_len = 20;
}
logInfo("%20.*s %10d %8d %12"PRId64" %11"PRId64" %10"PRId64
" %10"PRId64" %10"PRId64" %10"PRId64" %11.2f%%", name_len,
pStat->name, order_by == FAST_MBLOCK_ORDER_BY_ELEMENT_SIZE ?
pStat->element_size : pStat->trunk_size,
pStat->instance_count, amem, pStat->trunk_total_count,
pStat->trunk_used_count, pStat->element_total_count,
pStat->element_used_count, pStat->delay_free_elements,
CALC_USED_RATIO(pStat));
++output_count;
logInfo("%20s %8d %8d %12"PRId64" %11"PRId64" %10"PRId64
" %10"PRId64" %10"PRId64" %10"PRId64" %11.2f%%",
pStat->name, pStat->element_size, pStat->instance_count,
amem, pStat->trunk_total_count, pStat->trunk_used_count,
pStat->element_total_count, pStat->element_used_count,
pStat->delay_free_elements,
pStat->element_total_count > 0 ? 100.00 * (double)
pStat->element_used_count / (double)
pStat->element_total_count : 0.00);
}
if (alloc_mem < 1024)
@ -386,10 +341,10 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
(double)delay_free_mem / (1024 * 1024 * 1024));
}
logInfo("mblock count: %d, output count: %d, memory stat => "
"{alloc : %s, used: %s (%.2f%%), delay free: %s (%.2f%%) }",
mblock_manager.count, output_count, alloc_mem_str, used_mem_str,
alloc_mem > 0 ? 100.00 * (double)used_mem / alloc_mem : 0.00,
logInfo("mblock entry count: %d, memory stat => { alloc : %s, "
"used: %s (%.2f%%), delay free: %s (%.2f%%) }",
count, alloc_mem_str, used_mem_str, alloc_mem > 0 ?
100.00 * (double)used_mem / alloc_mem : 0.00,
delay_free_mem_str, alloc_mem > 0 ? 100.00 *
(double)delay_free_mem / alloc_mem : 0.00);
}
@ -398,6 +353,97 @@ int fast_mblock_manager_stat_print_ex(const bool hide_empty, const int order_by)
return 0;
}
int fast_mblock_init_ex(struct fast_mblock_man *mblock,
const int element_size, const int alloc_elements_once,
const int64_t alloc_elements_limit,
fast_mblock_alloc_init_func init_func, void *init_args,
const bool need_lock)
{
return fast_mblock_init_ex2(mblock, NULL, element_size,
alloc_elements_once, alloc_elements_limit, init_func,
init_args, need_lock, NULL, NULL, NULL);
}
int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
const int element_size, const int alloc_elements_once,
const int64_t alloc_elements_limit,
fast_mblock_alloc_init_func init_func,
void *init_args, const bool need_lock,
fast_mblock_malloc_trunk_check_func malloc_trunk_check,
fast_mblock_malloc_trunk_notify_func malloc_trunk_notify,
void *malloc_trunk_args)
{
int result;
int block_size;
if (element_size <= 0)
{
logError("file: "__FILE__", line: %d, " \
"invalid block size: %d", \
__LINE__, element_size);
return EINVAL;
}
mblock->info.element_size = MEM_ALIGN(element_size);
mblock->alloc_elements.limit = alloc_elements_limit;
block_size = fast_mblock_get_block_size(mblock);
if (alloc_elements_once > 0)
{
mblock->alloc_elements.once = alloc_elements_once;
}
else
{
mblock->alloc_elements.once = (1024 * 1024) / block_size;
}
if (mblock->alloc_elements.limit > 0 && mblock->alloc_elements.once >
mblock->alloc_elements.limit)
{
mblock->alloc_elements.once = mblock->alloc_elements.limit;
}
if (need_lock && (result=init_pthread_lock_cond_pair(&(mblock->lcp))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"init_pthread_lock fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
mblock->alloc_init_func = init_func;
mblock->init_args = init_args;
INIT_HEAD(&mblock->trunks.head);
mblock->info.trunk_total_count = 0;
mblock->info.trunk_used_count = 0;
mblock->info.delay_free_elements = 0;
mblock->free_chain_head = NULL;
mblock->delay_free_chain.head = NULL;
mblock->delay_free_chain.tail = NULL;
mblock->info.element_total_count = 0;
mblock->info.element_used_count = 0;
mblock->info.instance_count = 1;
mblock->info.trunk_size = fast_mblock_get_trunk_size(mblock,
block_size, mblock->alloc_elements.once);
mblock->need_lock = need_lock;
mblock->alloc_elements.need_wait = false;
mblock->alloc_elements.pcontinue_flag = NULL;
mblock->alloc_elements.exceed_log_level = LOG_ERR;
mblock->malloc_trunk_callback.check_func = malloc_trunk_check;
mblock->malloc_trunk_callback.notify_func = malloc_trunk_notify;
mblock->malloc_trunk_callback.args = malloc_trunk_args;
if (name != NULL)
{
snprintf(mblock->info.name, sizeof(mblock->info.name), "%s", name);
}
else
{
*mblock->info.name = '\0';
}
add_to_mblock_list(mblock);
return 0;
}
static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
{
struct fast_mblock_node *pNode;
@ -407,9 +453,11 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
char *p;
char *pLast;
int result;
int block_size;
int trunk_size;
int alloc_count;
block_size = fast_mblock_get_block_size(mblock);
if (mblock->alloc_elements.limit > 0)
{
int64_t avail_count;
@ -429,8 +477,8 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
alloc_count = avail_count > mblock->alloc_elements.once ?
mblock->alloc_elements.once : avail_count;
trunk_size = fast_mblock_get_trunk_size(
mblock->info.block_size, alloc_count);
trunk_size = fast_mblock_get_trunk_size(mblock,
block_size, alloc_count);
}
else
{
@ -438,9 +486,9 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
trunk_size = mblock->info.trunk_size;
}
if (mblock->trunk_callbacks.check_func != NULL &&
mblock->trunk_callbacks.check_func(trunk_size,
mblock->trunk_callbacks.args) != 0)
if (mblock->malloc_trunk_callback.check_func != NULL &&
mblock->malloc_trunk_callback.check_func(trunk_size,
mblock->malloc_trunk_callback.args) != 0)
{
return ENOMEM;
}
@ -453,32 +501,27 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
memset(pNew, 0, trunk_size);
pMallocNode = (struct fast_mblock_malloc *)pNew;
pTrunkStart = pNew + sizeof(struct fast_mblock_malloc);
pLast = pNew + (trunk_size - mblock->info.block_size);
for (p=pTrunkStart; p<=pLast; p += mblock->info.block_size)
pLast = pNew + (trunk_size - block_size);
for (p=pTrunkStart; p<=pLast; p += block_size)
{
pNode = (struct fast_mblock_node *)p;
if (mblock->object_callbacks.init_func != NULL)
if (mblock->alloc_init_func != NULL)
{
if ((result=mblock->object_callbacks.init_func(pNode->data,
mblock->object_callbacks.args)) != 0)
if ((result=mblock->alloc_init_func(pNode->data,
mblock->init_args)) != 0)
{
free(pNew);
return result;
}
}
pNode->offset = (int)(p - pNew);
pNode->next = (struct fast_mblock_node *)(p + mblock->info.block_size);
#ifdef FAST_MBLOCK_MAGIC_CHECK
pNode->index = (p - pTrunkStart) / mblock->info.block_size;
pNode->magic = FAST_MBLOCK_MAGIC_NUMBER;
#endif
pNode->next = (struct fast_mblock_node *)(p + block_size);
}
((struct fast_mblock_node *)pLast)->next = mblock->freelist.head;
mblock->freelist.head = (struct fast_mblock_node *)pTrunkStart;
((struct fast_mblock_node *)pLast)->next = NULL;
mblock->free_chain_head = (struct fast_mblock_node *)pTrunkStart;
pMallocNode->ref_count = 0;
pMallocNode->alloc_count = alloc_count;
@ -490,116 +533,11 @@ static int fast_mblock_prealloc(struct fast_mblock_man *mblock)
mblock->info.trunk_total_count++;
mblock->info.element_total_count += alloc_count;
if (mblock->trunk_callbacks.notify_func != NULL)
if (mblock->malloc_trunk_callback.notify_func != NULL)
{
mblock->trunk_callbacks.notify_func(fast_mblock_notify_type_alloc,
pMallocNode, mblock->trunk_callbacks.args);
}
return 0;
}
int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
const int element_size, const int alloc_elements_once,
const int64_t alloc_elements_limit, const int prealloc_trunk_count,
struct fast_mblock_object_callbacks *object_callbacks,
const bool need_lock, struct fast_mblock_trunk_callbacks
*trunk_callbacks)
{
int result;
int i;
if (element_size <= 0)
{
logError("file: "__FILE__", line: %d, " \
"invalid block size: %d", \
__LINE__, element_size);
return EINVAL;
}
mblock->info.element_size = MEM_ALIGN(element_size);
mblock->alloc_elements.limit = alloc_elements_limit;
mblock->info.block_size = fast_mblock_get_block_size(
mblock->info.element_size);
if (alloc_elements_once > 0)
{
mblock->alloc_elements.once = alloc_elements_once;
}
else
{
mblock->alloc_elements.once = (1024 * 1024) / mblock->info.block_size;
}
if (mblock->alloc_elements.limit > 0 && mblock->alloc_elements.once >
mblock->alloc_elements.limit)
{
mblock->alloc_elements.once = mblock->alloc_elements.limit;
}
if (need_lock && (result=init_pthread_lock_cond_pair(&(mblock->lcp))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"init_pthread_lock fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
if (object_callbacks == NULL)
{
mblock->object_callbacks.init_func = NULL;
mblock->object_callbacks.destroy_func = NULL;
mblock->object_callbacks.args = NULL;
}
else
{
mblock->object_callbacks = *object_callbacks;
}
INIT_HEAD(&mblock->trunks.head);
mblock->info.trunk_total_count = 0;
mblock->info.trunk_used_count = 0;
mblock->info.delay_free_elements = 0;
mblock->freelist.head = NULL;
mblock->delay_free_chain.head = NULL;
mblock->delay_free_chain.tail = NULL;
mblock->info.element_total_count = 0;
mblock->info.element_used_count = 0;
mblock->info.instance_count = 1;
mblock->info.trunk_size = fast_mblock_get_trunk_size(
mblock->info.block_size, mblock->alloc_elements.once);
mblock->need_lock = need_lock;
mblock->alloc_elements.need_wait = false;
mblock->alloc_elements.pcontinue_flag = NULL;
mblock->alloc_elements.exceed_log_level = LOG_ERR;
if (trunk_callbacks == NULL)
{
mblock->trunk_callbacks.check_func = NULL;
mblock->trunk_callbacks.notify_func = NULL;
mblock->trunk_callbacks.args = NULL;
}
else
{
mblock->trunk_callbacks = *trunk_callbacks;
}
if (name != NULL)
{
fc_safe_strcpy(mblock->info.name, name);
}
else
{
*mblock->info.name = '\0';
}
add_to_mblock_list(mblock);
for (i=0; i<prealloc_trunk_count; i++)
{
if ((result=fast_mblock_prealloc(mblock)) != 0)
{
fast_mblock_destroy(mblock);
return result;
}
mblock->malloc_trunk_callback.notify_func(trunk_size,
mblock->malloc_trunk_callback.args);
}
return 0;
@ -613,10 +551,10 @@ static inline void fast_mblock_remove_trunk(struct fast_mblock_man *mblock,
mblock->info.trunk_total_count--;
mblock->info.element_total_count -= pMallocNode->alloc_count;
if (mblock->trunk_callbacks.notify_func != NULL)
if (mblock->malloc_trunk_callback.notify_func != NULL)
{
mblock->trunk_callbacks.notify_func(fast_mblock_notify_type_reclaim,
pMallocNode, mblock->trunk_callbacks.args);
mblock->malloc_trunk_callback.notify_func(-1 * pMallocNode->trunk_size,
mblock->malloc_trunk_callback.args);
}
}
@ -628,24 +566,6 @@ static inline void fast_mblock_ref_counter_op(struct fast_mblock_man *mblock,
{
struct fast_mblock_malloc *pMallocNode;
#ifdef FAST_MBLOCK_MAGIC_CHECK
int calc_offset;
calc_offset = sizeof(struct fast_mblock_malloc) +
pNode->index * mblock->info.block_size;
if (pNode->magic != FAST_MBLOCK_MAGIC_NUMBER ||
pNode->offset != calc_offset)
{
logCrit("file: "__FILE__", line: %d, "
"magic check for %s %s fail, node: %p, index: %d, offset: %d, "
"offset by index: %d, magic number: %d, expect magic: %d",
__LINE__, (is_inc ? "alloc" : "free"), mblock->info.name,
pNode, pNode->index, pNode->offset, calc_offset,
pNode->magic, FAST_MBLOCK_MAGIC_NUMBER);
return;
}
#endif
pMallocNode = FAST_MBLOCK_GET_TRUNK(pNode);
if (is_inc)
{
@ -666,59 +586,38 @@ static inline void fast_mblock_ref_counter_op(struct fast_mblock_man *mblock,
}
#define fast_mblock_ref_counter_inc(mblock, pNode) \
mblock->info.element_used_count++; \
fast_mblock_ref_counter_op(mblock, pNode, true)
#define fast_mblock_ref_counter_dec(mblock, pNode) \
mblock->info.element_used_count--; \
fast_mblock_ref_counter_op(mblock, pNode, false)
static void fast_mblock_free_trunk(struct fast_mblock_man *mblock,
struct fast_mblock_malloc *trunk)
{
char *start;
char *p;
char *last;
if (mblock->object_callbacks.destroy_func != NULL)
{
start = (char *)(trunk + 1);
last = (char *)trunk + (trunk->trunk_size - mblock->info.block_size);
for (p = start; p <= last; p += mblock->info.block_size)
{
mblock->object_callbacks.destroy_func(
((struct fast_mblock_node *)p)->data,
mblock->object_callbacks.args);
}
}
free(trunk);
}
void fast_mblock_destroy(struct fast_mblock_man *mblock)
{
struct fast_mblock_malloc *pMallocNode;
struct fast_mblock_malloc *pMallocTmp;
if (!IS_EMPTY(&mblock->trunks.head))
{
pMallocNode = mblock->trunks.head.next;
while (pMallocNode != &mblock->trunks.head)
{
pMallocTmp = pMallocNode;
pMallocNode = pMallocNode->next;
if (IS_EMPTY(&mblock->trunks.head))
{
delete_from_mblock_list(mblock);
return;
}
fast_mblock_free_trunk(mblock, pMallocTmp);
}
pMallocNode = mblock->trunks.head.next;
while (pMallocNode != &mblock->trunks.head)
{
pMallocTmp = pMallocNode;
pMallocNode = pMallocNode->next;
INIT_HEAD(&mblock->trunks.head);
mblock->info.trunk_total_count = 0;
mblock->info.trunk_used_count = 0;
mblock->freelist.head = NULL;
mblock->info.element_used_count = 0;
mblock->info.delay_free_elements = 0;
mblock->info.element_total_count = 0;
}
free(pMallocTmp);
}
INIT_HEAD(&mblock->trunks.head);
mblock->info.trunk_total_count = 0;
mblock->info.trunk_used_count = 0;
mblock->free_chain_head = NULL;
mblock->info.element_used_count = 0;
mblock->info.delay_free_elements = 0;
mblock->info.element_total_count = 0;
if (mblock->need_lock) destroy_pthread_lock_cond_pair(&(mblock->lcp));
delete_from_mblock_list(mblock);
@ -732,10 +631,10 @@ static inline struct fast_mblock_node *alloc_node(
while (1)
{
if (mblock->freelist.head != NULL)
if (mblock->free_chain_head != NULL)
{
pNode = mblock->freelist.head;
mblock->freelist.head = pNode->next;
pNode = mblock->free_chain_head;
mblock->free_chain_head = pNode->next;
break;
}
@ -750,15 +649,14 @@ static inline struct fast_mblock_node *alloc_node(
mblock->delay_free_chain.tail = NULL;
}
fast_mblock_ref_counter_dec(mblock, pNode);
mblock->info.delay_free_elements--;
break;
}
if ((result=fast_mblock_prealloc(mblock)) == 0)
{
pNode = mblock->freelist.head;
mblock->freelist.head = pNode->next;
pNode = mblock->free_chain_head;
mblock->free_chain_head = pNode->next;
break;
}
@ -778,6 +676,7 @@ static inline struct fast_mblock_node *alloc_node(
if (pNode != NULL)
{
mblock->info.element_used_count++;
fast_mblock_ref_counter_inc(mblock, pNode);
}
@ -829,9 +728,10 @@ int fast_mblock_free(struct fast_mblock_man *mblock,
return result;
}
notify = (mblock->freelist.head == NULL);
pNode->next = mblock->freelist.head;
mblock->freelist.head = pNode;
notify = (mblock->free_chain_head == NULL);
pNode->next = mblock->free_chain_head;
mblock->free_chain_head = pNode;
mblock->info.element_used_count--;
fast_mblock_ref_counter_dec(mblock, pNode);
if (mblock->alloc_elements.need_wait && notify)
@ -855,79 +755,74 @@ static inline void batch_free(struct fast_mblock_man *mblock,
struct fast_mblock_chain *chain)
{
bool notify;
int count;
struct fast_mblock_node *pNode;
count = 0;
pNode = chain->head;
while (pNode != NULL)
{
++count;
mblock->info.element_used_count--;
fast_mblock_ref_counter_dec(mblock, pNode);
pNode = pNode->next;
}
notify = (mblock->freelist.head == NULL);
chain->tail->next = mblock->freelist.head;
mblock->freelist.head = chain->head;
notify = (mblock->free_chain_head == NULL);
chain->tail->next = mblock->free_chain_head;
mblock->free_chain_head = chain->head;
if (mblock->alloc_elements.need_wait && notify)
{
pthread_cond_broadcast(&mblock->lcp.cond);
}
}
int fast_mblock_batch_alloc(struct fast_mblock_man *mblock,
const int count, struct fast_mblock_chain *chain)
struct fast_mblock_node *fast_mblock_batch_alloc(
struct fast_mblock_man *mblock, const int count)
{
struct fast_mblock_chain chain;
struct fast_mblock_node *pNode;
int i;
int lr;
int result;
if (mblock->need_lock && (lr=pthread_mutex_lock(
if (mblock->need_lock && (result=pthread_mutex_lock(
&mblock->lcp.lock)) != 0)
{
logError("file: "__FILE__", line: %d, "
"call pthread_mutex_lock fail, "
"errno: %d, error info: %s",
__LINE__, lr, STRERROR(lr));
return lr;
__LINE__, result, STRERROR(result));
return NULL;
}
if ((chain->head=alloc_node(mblock)) != NULL) {
chain->tail = chain->head;
for (i=1; i<count; i++) {
if ((pNode=alloc_node(mblock)) == NULL) {
if ((chain.head=alloc_node(mblock)) != NULL)
{
chain.tail = chain.head;
for (i=1; i<count; i++)
{
if ((pNode=alloc_node(mblock)) == NULL)
{
break;
}
chain->tail->next = pNode;
chain->tail = pNode;
chain.tail->next = pNode;
chain.tail = pNode;
}
chain->tail->next = NULL;
chain.tail->next = NULL;
if (i == count) {
result = 0;
} else { //fail
batch_free(mblock, chain);
chain->head = chain->tail = NULL;
result = ENOMEM;
if (i != count) { //fail
batch_free(mblock, &chain);
chain.head = NULL;
}
} else {
chain->head = chain->tail = NULL;
result = ENOMEM;
}
if (mblock->need_lock && (lr=pthread_mutex_unlock(
if (mblock->need_lock && (result=pthread_mutex_unlock(
&mblock->lcp.lock)) != 0)
{
logError("file: "__FILE__", line: %d, "
"call pthread_mutex_unlock fail, "
"errno: %d, error info: %s",
__LINE__, lr, STRERROR(lr));
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return result;
return chain.head;
}
int fast_mblock_batch_free(struct fast_mblock_man *mblock,
@ -963,32 +858,6 @@ int fast_mblock_batch_free(struct fast_mblock_man *mblock,
return 0;
}
void fast_mblock_free_objects(struct fast_mblock_man *mblock,
void **objs, const int count)
{
void **obj;
void **end;
struct fast_mblock_node *previous;
struct fast_mblock_node *current;
struct fast_mblock_chain chain;
if (count == 0) {
return;
}
chain.head = previous = fast_mblock_to_node_ptr(objs[0]);
end = objs + count;
for (obj=objs+1; obj<end; obj++) {
current = fast_mblock_to_node_ptr(*obj);
previous->next = current;
previous = current;
}
previous->next = NULL;
chain.tail = previous;
fast_mblock_batch_free(mblock, &chain);
}
int fast_mblock_delay_free(struct fast_mblock_man *mblock,
struct fast_mblock_node *pNode, const int deley)
{
@ -1016,7 +885,9 @@ int fast_mblock_delay_free(struct fast_mblock_man *mblock,
mblock->delay_free_chain.tail = pNode;
pNode->next = NULL;
mblock->info.element_used_count--;
mblock->info.delay_free_elements++;
fast_mblock_ref_counter_dec(mblock, pNode);
if (mblock->need_lock && (result=pthread_mutex_unlock(
&mblock->lcp.lock)) != 0)
@ -1069,7 +940,7 @@ static int fast_mblock_chain_count(struct fast_mblock_man *mblock,
int fast_mblock_free_count(struct fast_mblock_man *mblock)
{
return fast_mblock_chain_count(mblock, mblock->freelist.head);
return fast_mblock_chain_count(mblock, mblock->free_chain_head);
}
int fast_mblock_delay_free_count(struct fast_mblock_man *mblock)
@ -1081,65 +952,65 @@ static int fast_mblock_do_reclaim(struct fast_mblock_man *mblock,
const int reclaim_target, int *reclaim_count,
struct fast_mblock_malloc **ppFreelist)
{
struct fast_mblock_node *free_chain_prev;
struct fast_mblock_node *current;
struct fast_mblock_malloc *malloc_node;
struct fast_mblock_node *pPrevious;
struct fast_mblock_node *pCurrent;
struct fast_mblock_malloc *pMallocNode;
struct fast_mblock_malloc *freelist;
bool lookup_done;
lookup_done = false;
*reclaim_count = 0;
freelist = NULL;
free_chain_prev = NULL;
current = mblock->freelist.head;
mblock->freelist.head = NULL;
while (current != NULL)
pPrevious = NULL;
pCurrent = mblock->free_chain_head;
mblock->free_chain_head = NULL;
while (pCurrent != NULL)
{
malloc_node = FAST_MBLOCK_GET_TRUNK(current);
if (malloc_node->ref_count > 0 ||
(malloc_node->ref_count == 0 && lookup_done))
{ /* keep in the free chain */
pMallocNode = FAST_MBLOCK_GET_TRUNK(pCurrent);
if (pMallocNode->ref_count > 0 ||
(pMallocNode->ref_count == 0 && lookup_done))
{ //keep in free chain
if (free_chain_prev != NULL)
if (pPrevious != NULL)
{
free_chain_prev->next = current;
pPrevious->next = pCurrent;
}
else
{
mblock->freelist.head = current;
mblock->free_chain_head = pCurrent;
}
free_chain_prev = current;
current = current->next;
if (current == NULL)
pPrevious = pCurrent;
pCurrent = pCurrent->next;
if (pCurrent == NULL)
{
goto OUTER;
}
malloc_node = FAST_MBLOCK_GET_TRUNK(current);
pMallocNode = FAST_MBLOCK_GET_TRUNK(pCurrent);
while (malloc_node->ref_count > 0 ||
(malloc_node->ref_count == 0 && lookup_done))
while (pMallocNode->ref_count > 0 ||
(pMallocNode->ref_count == 0 && lookup_done))
{
free_chain_prev = current;
current = current->next;
if (current == NULL)
pPrevious = pCurrent;
pCurrent = pCurrent->next;
if (pCurrent == NULL)
{
goto OUTER;
}
malloc_node = FAST_MBLOCK_GET_TRUNK(current);
pMallocNode = FAST_MBLOCK_GET_TRUNK(pCurrent);
}
}
while (malloc_node->ref_count < 0 ||
(malloc_node->ref_count == 0 && !lookup_done))
while (pMallocNode->ref_count < 0 ||
(pMallocNode->ref_count == 0 && !lookup_done))
{
if (malloc_node->ref_count == 0) //trigger by the first node only
if (pMallocNode->ref_count == 0) //trigger by the first node
{
fast_mblock_remove_trunk(mblock, malloc_node);
malloc_node->ref_count = -1;
fast_mblock_remove_trunk(mblock, pMallocNode);
pMallocNode->ref_count = -1;
malloc_node->next = freelist;
freelist = malloc_node;
pMallocNode->next = freelist;
freelist = pMallocNode;
(*reclaim_count)++;
if (reclaim_target > 0 && *reclaim_count == reclaim_target)
{
@ -1147,23 +1018,23 @@ static int fast_mblock_do_reclaim(struct fast_mblock_man *mblock,
}
}
current = current->next;
if (current == NULL)
pCurrent = pCurrent->next;
if (pCurrent == NULL)
{
goto OUTER;
}
malloc_node = FAST_MBLOCK_GET_TRUNK(current);
pMallocNode = FAST_MBLOCK_GET_TRUNK(pCurrent);
}
}
OUTER:
if (free_chain_prev != NULL)
if (pPrevious != NULL)
{
free_chain_prev->next = NULL;
pPrevious->next = NULL;
}
/*
{
bool old_need_lock;
old_need_lock = mblock->need_lock;
@ -1174,7 +1045,6 @@ OUTER:
mblock, *reclaim_count, fast_mblock_free_count(mblock));
mblock->need_lock = old_need_lock;
}
*/
*ppFreelist = freelist;
return (freelist != NULL ? 0 : ENOENT);
@ -1190,8 +1060,7 @@ void fast_mblock_free_trunks(struct fast_mblock_man *mblock,
{
pDeleted = freelist;
freelist = freelist->next;
fast_mblock_free_trunk(mblock, pDeleted);
free(pDeleted);
count++;
}
logDebug("file: "__FILE__", line: %d, "

View File

@ -24,25 +24,13 @@
#include <pthread.h>
#include "common_define.h"
#include "fc_memory.h"
#include "chain.h"
#include "logger.h"
/* following two macros for debug only */
/*
#define FAST_MBLOCK_MAGIC_CHECK 1
#define FAST_MBLOCK_MAGIC_NUMBER 1234567890
*/
#define FAST_MBLOCK_NAME_SIZE 32
#define FAST_MBLOCK_ORDER_BY_ALLOC_BYTES 1
#define FAST_MBLOCK_ORDER_BY_ELEMENT_SIZE 2
#define FAST_MBLOCK_ORDER_BY_USED_RATIO 3
enum fast_mblock_notify_type {
fast_mblock_notify_type_alloc,
fast_mblock_notify_type_reclaim,
};
/* free node chain */
struct fast_mblock_node
@ -50,10 +38,6 @@ struct fast_mblock_node
struct fast_mblock_node *next;
int offset; //trunk offset
int recycle_timestamp;
#ifdef FAST_MBLOCK_MAGIC_CHECK
int index;
int magic; //magic number
#endif
char data[0]; //the data buffer
};
@ -72,18 +56,13 @@ struct fast_mblock_chain {
struct fast_mblock_node *tail;
};
/* call by alloc trunk */
typedef int (*fast_mblock_object_init_func)(void *element, void *args);
/* call by free trunk */
typedef void (*fast_mblock_object_destroy_func)(void *element, void *args);
typedef int (*fast_mblock_alloc_init_func)(void *element, void *args);
typedef int (*fast_mblock_malloc_trunk_check_func)(
const int alloc_bytes, void *args);
typedef void (*fast_mblock_malloc_trunk_notify_func)(
const enum fast_mblock_notify_type type,
const struct fast_mblock_malloc *node, void *args);
const int alloc_bytes, void *args);
struct fast_mblock_info
{
@ -91,7 +70,6 @@ struct fast_mblock_info
int element_size; //element size
int trunk_size; //trunk size
int instance_count; //instance count
int block_size;
int64_t element_total_count; //total element count
int64_t element_used_count; //used element count
int64_t delay_free_elements; //delay free element count
@ -104,13 +82,7 @@ struct fast_mblock_trunks
struct fast_mblock_malloc head; //malloc chain to be freed
};
struct fast_mblock_object_callbacks {
fast_mblock_object_init_func init_func;
fast_mblock_object_destroy_func destroy_func;
void *args;
};
struct fast_mblock_trunk_callbacks
struct fast_mblock_malloc_trunk_callback
{
fast_mblock_malloc_trunk_check_func check_func;
fast_mblock_malloc_trunk_notify_func notify_func;
@ -127,28 +99,24 @@ struct fast_mblock_man
int64_t limit; //<= 0 for no limit
bool *pcontinue_flag;
} alloc_elements;
struct {
struct fast_mblock_node *head;
} freelist; //free node chain
struct fast_mblock_node *free_chain_head; //free node chain
struct fast_mblock_trunks trunks;
struct fast_mblock_chain delay_free_chain; //delay free node chain
struct fast_mblock_object_callbacks object_callbacks;
struct fast_mblock_trunk_callbacks trunk_callbacks;
fast_mblock_alloc_init_func alloc_init_func;
struct fast_mblock_malloc_trunk_callback malloc_trunk_callback;
bool need_lock; //if need mutex lock
pthread_lock_cond_pair_t lcp; //for read / write free node chain
struct fast_mblock_man *prev; //for stat manager
struct fast_mblock_man *next; //for stat manager
void *init_args; //args for alloc_init_func
};
#define fast_mblock_get_block_size(element_size) \
(MEM_ALIGN(sizeof(struct fast_mblock_node) + element_size))
#define GET_BLOCK_SIZE(info) \
(MEM_ALIGN(sizeof(struct fast_mblock_node) + (info).element_size))
#define fast_mblock_get_trunk_size(block_size, element_count) \
(sizeof(struct fast_mblock_malloc) + block_size * element_count)
#define fast_mblock_get_block_size(mblock) GET_BLOCK_SIZE(mblock->info)
#define fast_mblock_to_node_ptr(data_ptr) \
(struct fast_mblock_node *)((char *)data_ptr - ((size_t)(char *) \
@ -159,29 +127,26 @@ extern "C" {
#endif
#define fast_mblock_init(mblock, element_size, alloc_elements_once) \
fast_mblock_init_ex(mblock, element_size, alloc_elements_once, \
fast_mblock_init_ex(mblock, element_size, alloc_elements_once, \
0, NULL, NULL, true)
/**
mblock init
parameters:
name: the mblock name
mblock: the mblock pointer
element_size: element size, such as sizeof(struct xxx)
alloc_elements_once: malloc elements once, 0 for malloc 1MB memory once
alloc_elements_limit: malloc elements limit, <= 0 for no limit
prealloc_trunk_count: prealloc trunk node count
object_callbacks: the object callback functions and args
init_func: the init function
init_args: the args for init_func
need_lock: if need lock
trunk_callbacks: the trunk callback functions and args
return error no, 0 for success, != 0 fail
*/
int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
int fast_mblock_init_ex(struct fast_mblock_man *mblock,
const int element_size, const int alloc_elements_once,
const int64_t alloc_elements_limit, const int prealloc_trunk_count,
struct fast_mblock_object_callbacks *object_callbacks,
const bool need_lock, struct fast_mblock_trunk_callbacks
*trunk_callbacks);
const int64_t alloc_elements_limit,
fast_mblock_alloc_init_func init_func, void *init_args,
const bool need_lock);
/**
mblock init
@ -191,51 +156,48 @@ parameters:
element_size: element size, such as sizeof(struct xxx)
alloc_elements_once: malloc elements once, 0 for malloc 1MB memory once
alloc_elements_limit: malloc elements limit, <= 0 for no limit
init_func: the object init function
init_args: the args for object init function
init_func: the init function
init_args: the args for init_func
need_lock: if need lock
malloc_trunk_check: the malloc trunk check function pointor
malloc_trunk_notify: the malloc trunk notify function pointor
malloc_trunk_args: the malloc trunk args
return error no, 0 for success, != 0 fail
*/
int fast_mblock_init_ex2(struct fast_mblock_man *mblock, const char *name,
const int element_size, const int alloc_elements_once,
const int64_t alloc_elements_limit,
fast_mblock_alloc_init_func init_func,
void *init_args, const bool need_lock,
fast_mblock_malloc_trunk_check_func malloc_trunk_check,
fast_mblock_malloc_trunk_notify_func malloc_trunk_notify,
void *malloc_trunk_args);
/**
mblock init
parameters:
name: the mblock name
mblock: the mblock pointer
element_size: element size, such as sizeof(struct xxx)
alloc_elements_once: malloc elements once, 0 for malloc 1MB memory once
alloc_elements_limit: malloc elements limit, <= 0 for no limit
init_func: the init function
init_args: the args for init_func
need_lock: if need lock
return error no, 0 for success, != 0 fail
*/
static inline int fast_mblock_init_ex1(struct fast_mblock_man *mblock,
const char *name, const int element_size,
const int alloc_elements_once, const int64_t alloc_elements_limit,
fast_mblock_object_init_func init_func, void *init_args,
const bool need_lock)
const int alloc_elements_once,
const int64_t alloc_elements_limit,
fast_mblock_alloc_init_func init_func,
void *init_args, const bool need_lock)
{
const int prealloc_trunk_count = 0;
struct fast_mblock_object_callbacks object_callbacks;
object_callbacks.init_func = init_func;
object_callbacks.destroy_func = NULL;
object_callbacks.args = init_args;
return fast_mblock_init_ex2(mblock, name, element_size,
alloc_elements_once, alloc_elements_limit,
prealloc_trunk_count, &object_callbacks,
need_lock, NULL);
alloc_elements_once, alloc_elements_limit, init_func,
init_args, need_lock, NULL, NULL, NULL);
}
/**
mblock init
parameters:
mblock: the mblock pointer
element_size: element size, such as sizeof(struct xxx)
alloc_elements_once: malloc elements once, 0 for malloc 1MB memory once
alloc_elements_limit: malloc elements limit, <= 0 for no limit
object_callbacks: the object callback functions and args
need_lock: if need lock
return error no, 0 for success, != 0 fail
*/
static inline int fast_mblock_init_ex(struct fast_mblock_man *mblock,
const int element_size, const int alloc_elements_once,
const int64_t alloc_elements_limit, fast_mblock_object_init_func
init_func, void *init_args, const bool need_lock)
{
return fast_mblock_init_ex1(mblock, NULL, element_size,
alloc_elements_once, alloc_elements_limit,
init_func, init_args, need_lock);
}
/**
mblock destroy
parameters:
@ -263,15 +225,6 @@ static inline int fast_mblock_set_need_wait(struct fast_mblock_man *mblock,
return 0;
}
static inline void fast_mblock_set_exceed_log_level(
struct fast_mblock_man *mblock, const int log_level)
{
mblock->alloc_elements.exceed_log_level = log_level;
}
#define fast_mblock_set_exceed_silence(mblock) \
fast_mblock_set_exceed_log_level(mblock, LOG_NOTHING)
/**
alloc a node from the mblock
parameters:
@ -290,17 +243,6 @@ return 0 for success, return none zero if fail
int fast_mblock_free(struct fast_mblock_man *mblock,
struct fast_mblock_node *pNode);
/**
batch alloc nodes from the mblock
parameters:
mblock: the mblock pointer
count: alloc count
chain: return the mblock node chain
return 0 for success, return none zero if fail
*/
int fast_mblock_batch_alloc(struct fast_mblock_man *mblock,
const int count, struct fast_mblock_chain *chain);
/**
batch alloc nodes from the mblock
parameters:
@ -308,16 +250,8 @@ parameters:
count: alloc count
return the alloced node head, return NULL if fail
*/
static inline struct fast_mblock_node *fast_mblock_batch_alloc1(
struct fast_mblock_man *mblock, const int count)
{
struct fast_mblock_chain chain;
if (fast_mblock_batch_alloc(mblock, count, &chain) == 0) {
return chain.head;
} else {
return NULL;
}
}
struct fast_mblock_node *fast_mblock_batch_alloc(
struct fast_mblock_man *mblock, const int count);
/**
batch free nodes
@ -370,17 +304,6 @@ static inline int fast_mblock_free_object(struct fast_mblock_man *mblock,
return fast_mblock_free(mblock, fast_mblock_to_node_ptr(object));
}
/**
free objects (put objects to the mblock)
parameters:
mblock: the mblock pointer
objs: the object array to free
count: the count of the object array
return none
*/
void fast_mblock_free_objects(struct fast_mblock_man *mblock,
void **objs, const int count);
/**
delay free a object (put a node to the mblock)
parameters:
@ -411,7 +334,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);
#define fast_mblock_total_count(mblock) (mblock)->info.element_total_count
#define fast_mblock_total_count(mblock) (mblock)->total_count
/**
init mblock manager

View File

@ -48,10 +48,6 @@ int fast_mpool_init(struct fast_mpool_man *mpool,
mpool->malloc_chain_head = NULL;
mpool->free_chain_head = NULL;
mpool->alloc_count = 0;
mpool->alloc_bytes = 0;
mpool->reset.count = 0;
mpool->reset.last_alloc_count = 0;
return 0;
}
@ -142,8 +138,6 @@ static inline void *fast_mpool_do_alloc(struct fast_mpool_man *mpool,
fast_mpool_remove_free_node(mpool, pMallocNode);
}
mpool->alloc_count++;
mpool->alloc_bytes += size;
return ptr;
}
return NULL;
@ -202,26 +196,19 @@ void *fast_mpool_memdup(struct fast_mpool_man *mpool,
void fast_mpool_reset(struct fast_mpool_man *mpool)
{
struct fast_mpool_malloc *pMallocNode;
struct fast_mpool_malloc *pMallocNode;
mpool->reset.count++;
if (mpool->reset.last_alloc_count == mpool->alloc_count)
{
return;
}
mpool->reset.last_alloc_count = mpool->alloc_count;
mpool->free_chain_head = NULL;
pMallocNode = mpool->malloc_chain_head;
while (pMallocNode != NULL)
{
mpool->free_chain_head = NULL;
pMallocNode = mpool->malloc_chain_head;
while (pMallocNode != NULL)
{
pMallocNode->free_ptr = pMallocNode->base_ptr;
pMallocNode->free_next = mpool->free_chain_head;
mpool->free_chain_head = pMallocNode;
pMallocNode = pMallocNode->malloc_next;
}
pMallocNode = pMallocNode->malloc_next;
}
}
void fast_mpool_stats(struct fast_mpool_man *mpool,
@ -256,22 +243,12 @@ void fast_mpool_stats(struct fast_mpool_man *mpool,
void fast_mpool_log_stats(struct fast_mpool_man *mpool)
{
struct fast_mpool_stats stats;
char sz_total_bytes[32];
char sz_free_bytes[32];
char sz_alloc_bytes[32];
fast_mpool_stats(mpool, &stats);
long_to_comma_str(stats.total_bytes, sz_total_bytes);
long_to_comma_str(stats.free_bytes, sz_free_bytes);
long_to_comma_str(mpool->alloc_bytes, sz_alloc_bytes);
logInfo("alloc_size_once: %d, discard_size: %d, "
"bytes: {total: %s, free: %s}, "
"trunk_count: {total: %d, free: %d}, "
"alloc_count: %"PRId64", alloc_bytes: %s, "
"reset_count: %"PRId64, mpool->alloc_size_once,
mpool->discard_size, sz_total_bytes,
sz_free_bytes, stats.total_trunk_count,
stats.free_trunk_count, mpool->alloc_count,
sz_alloc_bytes, mpool->reset.count);
"bytes: {total: %"PRId64", free: %"PRId64"}, "
"trunk_count: {total: %d, free: %d}",
mpool->alloc_size_once, mpool->discard_size,
stats.total_bytes, stats.free_bytes,
stats.total_trunk_count, stats.free_trunk_count);
}

View File

@ -37,16 +37,10 @@ struct fast_mpool_malloc
struct fast_mpool_man
{
struct fast_mpool_malloc *malloc_chain_head; //malloc chain to be freed
struct fast_mpool_malloc *free_chain_head; //free node chain
int alloc_size_once; //alloc size once, default: 1MB
int discard_size; //discard size, default: 64 bytes
int64_t alloc_count;
int64_t alloc_bytes;
struct {
int64_t count;
int64_t last_alloc_count;
} reset;
struct fast_mpool_malloc *malloc_chain_head; //malloc chain to be freed
struct fast_mpool_malloc *free_chain_head; //free node chain
int alloc_size_once; //alloc size once, default: 1MB
int discard_size; //discard size, default: 64 bytes
};
struct fast_mpool_stats

View File

@ -25,214 +25,667 @@
#include "fc_memory.h"
#include "fast_task_queue.h"
static int task_alloc_init(struct fast_task_info *task,
struct fast_task_queue *queue)
static struct fast_task_queue g_free_queue;
struct mpool_node {
struct fast_task_info *blocks;
struct fast_task_info *last_block; //last block
struct mpool_node *next;
};
struct mpool_chain {
struct mpool_node *head;
struct mpool_node *tail;
};
static struct mpool_chain g_mpool = {NULL, NULL};
int task_queue_init(struct fast_task_queue *pQueue)
{
task->arg = (char *)task + ALIGNED_TASK_INFO_SIZE + queue->padding_size;
task->send.ptr = &task->send.holder;
task->send.ptr->size = queue->min_buff_size;
if (queue->malloc_whole_block) {
task->send.ptr->data = (char *)task->arg + queue->arg_size;
} else {
task->send.ptr->data = (char *)fc_malloc(task->send.ptr->size);
if (task->send.ptr->data == NULL) {
return ENOMEM;
}
}
int result;
if (queue->double_buffers) {
task->recv.ptr = &task->recv.holder;
task->recv.ptr->size = queue->min_buff_size;
task->recv.ptr->data = (char *)fc_malloc(task->recv.ptr->size);
if (task->recv.ptr->data == NULL) {
return ENOMEM;
}
} else {
task->recv.ptr = &task->send.holder;
}
if ((result=init_pthread_lock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"init_pthread_lock fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
task->free_queue = queue;
if (queue->init_callback != NULL) {
return queue->init_callback(task, queue->init_arg);
}
return 0;
pQueue->head = NULL;
pQueue->tail = NULL;
return 0;
}
int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
const bool double_buffers, const bool need_shrink,
const int max_connections, const int alloc_task_once,
const int min_buff_size, const int max_buff_size,
const int padding_size, const int arg_size,
TaskInitCallback init_callback, void *init_arg)
static void free_mpool(struct mpool_node *mpool, char *end)
{
char *pt;
for (pt=(char *)mpool->blocks; pt < end; pt += g_free_queue.block_size)
{
free(((struct fast_task_info *)pt)->data);
}
free(mpool->blocks);
free(mpool);
}
static struct mpool_node *malloc_mpool(const int total_alloc_size)
{
struct fast_task_info *pTask;
char *p;
char *pCharEnd;
struct mpool_node *mpool;
mpool = (struct mpool_node *)fc_malloc(sizeof(struct mpool_node));
if (mpool == NULL)
{
return NULL;
}
mpool->next = NULL;
mpool->blocks = (struct fast_task_info *)fc_malloc(total_alloc_size);
if (mpool->blocks == NULL)
{
free(mpool);
return NULL;
}
memset(mpool->blocks, 0, total_alloc_size);
pCharEnd = ((char *)mpool->blocks) + total_alloc_size;
for (p=(char *)mpool->blocks; p<pCharEnd; p += g_free_queue.block_size)
{
pTask = (struct fast_task_info *)p;
pTask->size = g_free_queue.min_buff_size;
pTask->arg = p + ALIGNED_TASK_INFO_SIZE;
if (g_free_queue.malloc_whole_block)
{
pTask->data = (char *)pTask->arg + \
g_free_queue.arg_size;
}
else
{
pTask->data = (char *)fc_malloc(pTask->size);
if (pTask->data == NULL)
{
free_mpool(mpool, p);
return NULL;
}
}
if (g_free_queue.init_callback != NULL)
{
if (g_free_queue.init_callback(pTask) != 0)
{
free_mpool(mpool, p);
return NULL;
}
}
}
mpool->last_block = (struct fast_task_info *)
(pCharEnd - g_free_queue.block_size);
for (p=(char *)mpool->blocks; p<(char *)mpool->last_block;
p += g_free_queue.block_size)
{
pTask = (struct fast_task_info *)p;
pTask->next = (struct fast_task_info *)(p + g_free_queue.block_size);
}
mpool->last_block->next = NULL;
return mpool;
}
int free_queue_init_ex2(const int max_connections, const int init_connections,
const int alloc_task_once, const int min_buff_size,
const int max_buff_size, const int arg_size,
TaskInitCallback init_callback)
{
#define MAX_DATA_SIZE (256 * 1024 * 1024)
int64_t total_size;
struct mpool_node *mpool;
int alloc_size;
int alloc_once;
int result;
int loop_count;
int aligned_min_size;
int aligned_max_size;
int aligned_padding_size;
int aligned_arg_size;
rlim_t max_data_size;
char aname[64];
if ((result=init_pthread_lock(&(g_free_queue.lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"init_pthread_lock fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
aligned_min_size = MEM_ALIGN(min_buff_size);
aligned_max_size = MEM_ALIGN(max_buff_size);
aligned_padding_size = MEM_ALIGN(padding_size);
aligned_arg_size = MEM_ALIGN(arg_size);
queue->block_size = ALIGNED_TASK_INFO_SIZE +
aligned_padding_size + aligned_arg_size;
if (alloc_task_once <= 0) {
alloc_once = FC_MIN(MAX_DATA_SIZE / queue->block_size, 256);
if (alloc_once == 0) {
alloc_once = 1;
}
} else {
alloc_once = alloc_task_once;
}
if (aligned_max_size > aligned_min_size) {
queue->malloc_whole_block = false;
g_free_queue.block_size = ALIGNED_TASK_INFO_SIZE + aligned_arg_size;
alloc_size = g_free_queue.block_size * init_connections;
if (aligned_max_size > aligned_min_size)
{
total_size = alloc_size;
g_free_queue.malloc_whole_block = false;
max_data_size = 0;
} else {
struct rlimit rlimit_data;
}
else
{
struct rlimit rlimit_data;
if (getrlimit(RLIMIT_DATA, &rlimit_data) < 0) {
logError("file: "__FILE__", line: %d, "
"call getrlimit fail, "
"errno: %d, error info: %s",
__LINE__, errno, STRERROR(errno));
return errno != 0 ? errno : EPERM;
}
if (rlimit_data.rlim_cur == RLIM_INFINITY) {
max_data_size = MAX_DATA_SIZE;
} else {
max_data_size = rlimit_data.rlim_cur;
if (max_data_size > MAX_DATA_SIZE) {
max_data_size = MAX_DATA_SIZE;
}
}
if (getrlimit(RLIMIT_DATA, &rlimit_data) < 0)
{
logError("file: "__FILE__", line: %d, " \
"call getrlimit fail, " \
"errno: %d, error info: %s", \
__LINE__, errno, STRERROR(errno));
return errno != 0 ? errno : EPERM;
}
if (rlimit_data.rlim_cur == RLIM_INFINITY)
{
max_data_size = MAX_DATA_SIZE;
}
else
{
max_data_size = rlimit_data.rlim_cur;
if (max_data_size > MAX_DATA_SIZE)
{
max_data_size = MAX_DATA_SIZE;
}
}
if (max_data_size >= (int64_t)(queue->block_size +
aligned_min_size) * (int64_t)alloc_once)
if (max_data_size >= (int64_t)(g_free_queue.block_size +
aligned_min_size) * (int64_t)init_connections)
{
total_size = alloc_size + (int64_t)aligned_min_size *
init_connections;
g_free_queue.malloc_whole_block = true;
g_free_queue.block_size += aligned_min_size;
}
else
{
total_size = alloc_size;
g_free_queue.malloc_whole_block = false;
max_data_size = 0;
}
}
g_free_queue.max_connections = max_connections;
g_free_queue.alloc_connections = init_connections;
if (alloc_task_once <= 0)
{
g_free_queue.alloc_task_once = 256;
alloc_once = MAX_DATA_SIZE / g_free_queue.block_size;
if (g_free_queue.alloc_task_once > alloc_once)
{
queue->malloc_whole_block = true;
queue->block_size += aligned_min_size;
} else {
queue->malloc_whole_block = false;
max_data_size = 0;
g_free_queue.alloc_task_once = alloc_once > 0 ? alloc_once : 1;
}
}
else
{
g_free_queue.alloc_task_once = alloc_task_once;
}
g_free_queue.min_buff_size = aligned_min_size;
g_free_queue.max_buff_size = aligned_max_size;
g_free_queue.arg_size = aligned_arg_size;
g_free_queue.init_callback = init_callback;
queue->double_buffers = double_buffers;
queue->need_shrink = need_shrink;
queue->min_buff_size = aligned_min_size;
queue->max_buff_size = aligned_max_size;
queue->padding_size = aligned_padding_size;
queue->arg_size = aligned_arg_size;
queue->init_callback = init_callback;
queue->init_arg = init_arg;
queue->release_callback = NULL;
/*
logInfo("file: "__FILE__", line: %d, [%s] double_buffers: %d, "
"max_connections: %d, alloc_once: %d, malloc_whole_block: %d, "
logDebug("file: "__FILE__", line: %d, "
"max_connections: %d, init_connections: %d, alloc_task_once: %d, "
"min_buff_size: %d, max_buff_size: %d, block_size: %d, "
"padding_size: %d, arg_size: %d, max_data_size: %"PRId64,
__LINE__, name, double_buffers, max_connections, alloc_once,
queue->malloc_whole_block, aligned_min_size, aligned_max_size,
queue->block_size, aligned_padding_size, aligned_arg_size,
(int64_t)max_data_size);
*/
"arg_size: %d, max_data_size: %d, total_size: %"PRId64,
__LINE__, max_connections, init_connections,
g_free_queue.alloc_task_once, aligned_min_size, aligned_max_size,
g_free_queue.block_size, aligned_arg_size, (int)max_data_size, total_size);
fc_combine_two_strings(name, "task", '-', aname);
return fast_mblock_init_ex1(&queue->allocator, aname,
queue->block_size, alloc_once, max_connections,
(fast_mblock_object_init_func)task_alloc_init,
queue, true);
if ((!g_free_queue.malloc_whole_block) || (total_size <= max_data_size))
{
loop_count = 1;
mpool = malloc_mpool(total_size);
if (mpool == NULL)
{
return errno != 0 ? errno : ENOMEM;
}
g_mpool.head = mpool;
g_mpool.tail = mpool;
}
else
{
int remain_count;
int alloc_count;
int current_alloc_size;
loop_count = 0;
remain_count = init_connections;
alloc_once = max_data_size / g_free_queue.block_size;
while (remain_count > 0)
{
alloc_count = (remain_count > alloc_once) ?
alloc_once : remain_count;
current_alloc_size = g_free_queue.block_size * alloc_count;
mpool = malloc_mpool(current_alloc_size);
if (mpool == NULL)
{
free_queue_destroy();
return errno != 0 ? errno : ENOMEM;
}
if (g_mpool.tail == NULL)
{
g_mpool.head = mpool;
}
else
{
g_mpool.tail->next = mpool;
g_mpool.tail->last_block->next = mpool->blocks; //link previous mpool to current
}
g_mpool.tail = mpool;
remain_count -= alloc_count;
loop_count++;
}
logDebug("file: "__FILE__", line: %d, " \
"alloc_once: %d", __LINE__, alloc_once);
}
logDebug("file: "__FILE__", line: %d, " \
"malloc task info as whole: %d, malloc loop count: %d", \
__LINE__, g_free_queue.malloc_whole_block, loop_count);
if (g_mpool.head != NULL)
{
g_free_queue.head = g_mpool.head->blocks;
g_free_queue.tail = g_mpool.tail->last_block;
}
return 0;
}
void free_queue_destroy(struct fast_task_queue *queue)
void free_queue_destroy()
{
fast_mblock_destroy(&queue->allocator);
struct mpool_node *mpool;
struct mpool_node *mp;
if (g_mpool.head == NULL)
{
return;
}
if (!g_free_queue.malloc_whole_block)
{
char *p;
char *pCharEnd;
struct fast_task_info *pTask;
mpool = g_mpool.head;
while (mpool != NULL)
{
pCharEnd = (char *)mpool->last_block + g_free_queue.block_size;
for (p=(char *)mpool->blocks; p<pCharEnd; p += g_free_queue.block_size)
{
pTask = (struct fast_task_info *)p;
if (pTask->data != NULL)
{
free(pTask->data);
pTask->data = NULL;
}
}
mpool = mpool->next;
}
}
mpool = g_mpool.head;
while (mpool != NULL)
{
mp = mpool;
mpool = mpool->next;
free(mp->blocks);
free(mp);
}
g_mpool.head = g_mpool.tail = NULL;
pthread_mutex_destroy(&(g_free_queue.lock));
}
static int _realloc_buffer(struct fast_net_buffer *buffer,
const int new_size, const bool copy_data)
static int free_queue_realloc()
{
char *new_buff;
struct mpool_node *mpool;
struct fast_task_info *head;
struct fast_task_info *tail;
int remain_count;
int alloc_count;
int current_alloc_size;
new_buff = (char *)fc_malloc(new_size);
if (new_buff == NULL) {
return ENOMEM;
head = tail = NULL;
remain_count = g_free_queue.max_connections -
g_free_queue.alloc_connections;
alloc_count = (remain_count > g_free_queue.alloc_task_once) ?
g_free_queue.alloc_task_once : remain_count;
if (alloc_count > 0)
{
current_alloc_size = g_free_queue.block_size * alloc_count;
mpool = malloc_mpool(current_alloc_size);
if (mpool == NULL)
{
return ENOMEM;
}
if (g_mpool.tail == NULL)
{
g_mpool.head = mpool;
}
else
{
g_mpool.tail->next = mpool;
}
g_mpool.tail = mpool;
head = mpool->blocks;
tail = mpool->last_block;
remain_count -= alloc_count;
}
else {
return ENOSPC;
}
if (copy_data && buffer->offset > 0) {
memcpy(new_buff, buffer->data, buffer->offset);
if (g_free_queue.head == NULL)
{
g_free_queue.head = head;
}
free(buffer->data);
buffer->size = new_size;
buffer->data = new_buff;
if (g_free_queue.tail != NULL)
{
g_free_queue.tail->next = head;
}
g_free_queue.tail = tail;
g_free_queue.alloc_connections += alloc_count;
logDebug("file: "__FILE__", line: %d, "
"alloc_connections: %d, realloc %d elements", __LINE__,
g_free_queue.alloc_connections, alloc_count);
return 0;
}
void free_queue_push(struct fast_task_info *task)
struct fast_task_info *free_queue_pop()
{
if (task->free_queue->release_callback != NULL) {
task->free_queue->release_callback(task);
struct fast_task_info *pTask;
int i;
if ((pTask=task_queue_pop(&g_free_queue)) != NULL)
{
return pTask;
}
*(task->client_ip) = '\0';
task->send.ptr->length = 0;
task->send.ptr->offset = 0;
task->req_count = 0;
if (task->free_queue->need_shrink && task->send.
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 (g_free_queue.alloc_connections >= g_free_queue.max_connections)
{
return NULL;
}
if (task->free_queue->double_buffers) {
task->recv.ptr->length = 0;
task->recv.ptr->offset = 0;
if (task->free_queue->need_shrink && task->recv.
ptr->size > task->free_queue->min_buff_size)
for (i=0; i<10; i++)
{
pthread_mutex_lock(&g_free_queue.lock);
if (g_free_queue.alloc_connections >= g_free_queue.max_connections)
{
_realloc_buffer(task->recv.ptr, task->free_queue->
min_buff_size, false);
task->shrinked = true;
if (g_free_queue.head == NULL)
{
pthread_mutex_unlock(&g_free_queue.lock);
return NULL;
}
}
else
{
if (g_free_queue.head == NULL && free_queue_realloc() != 0)
{
pthread_mutex_unlock(&g_free_queue.lock);
return NULL;
}
}
pthread_mutex_unlock(&g_free_queue.lock);
if ((pTask=task_queue_pop(&g_free_queue)) != NULL)
{
return pTask;
}
}
fast_mblock_free_object(&task->free_queue->allocator, task);
return NULL;
}
int free_queue_get_new_buffer_size(const int min_buff_size,
static int _realloc_buffer(struct fast_task_info *pTask, const int new_size,
const bool copy_data)
{
char *new_buff;
new_buff = (char *)fc_malloc(new_size);
if (new_buff == NULL)
{
return ENOMEM;
}
else
{
if (copy_data && pTask->offset > 0) {
memcpy(new_buff, pTask->data, pTask->offset);
}
free(pTask->data);
pTask->size = new_size;
pTask->data = new_buff;
return 0;
}
}
int free_queue_push(struct fast_task_info *pTask)
{
int result;
*(pTask->client_ip) = '\0';
pTask->length = 0;
pTask->offset = 0;
pTask->req_count = 0;
if (pTask->size > g_free_queue.min_buff_size) //need thrink
{
_realloc_buffer(pTask, g_free_queue.min_buff_size, false);
}
if ((result=pthread_mutex_lock(&g_free_queue.lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
pTask->next = g_free_queue.head;
g_free_queue.head = pTask;
if (g_free_queue.tail == NULL)
{
g_free_queue.tail = pTask;
}
if ((result=pthread_mutex_unlock(&g_free_queue.lock)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return result;
}
int free_queue_count()
{
return task_queue_count(&g_free_queue);
}
int free_queue_alloc_connections()
{
return g_free_queue.alloc_connections;
}
int free_queue_set_buffer_size(struct fast_task_info *pTask,
const int expect_size)
{
return task_queue_set_buffer_size(&g_free_queue, pTask, expect_size);
}
int free_queue_realloc_buffer(struct fast_task_info *pTask,
const int expect_size)
{
return task_queue_realloc_buffer(&g_free_queue, pTask, expect_size);
}
int free_queue_set_max_buffer_size(struct fast_task_info *pTask)
{
return task_queue_set_buffer_size(&g_free_queue, pTask,
g_free_queue.max_buff_size);
}
int free_queue_realloc_max_buffer(struct fast_task_info *pTask)
{
return task_queue_realloc_buffer(&g_free_queue, pTask,
g_free_queue.max_buff_size);
}
int task_queue_push(struct fast_task_queue *pQueue, \
struct fast_task_info *pTask)
{
int result;
if ((result=pthread_mutex_lock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
pTask->next = NULL;
if (pQueue->tail == NULL)
{
pQueue->head = pTask;
}
else
{
pQueue->tail->next = pTask;
}
pQueue->tail = pTask;
if ((result=pthread_mutex_unlock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return 0;
}
struct fast_task_info *task_queue_pop(struct fast_task_queue *pQueue)
{
struct fast_task_info *pTask;
int result;
if ((result=pthread_mutex_lock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return NULL;
}
pTask = pQueue->head;
if (pTask != NULL)
{
pQueue->head = pTask->next;
if (pQueue->head == NULL)
{
pQueue->tail = NULL;
}
}
if ((result=pthread_mutex_unlock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return pTask;
}
int task_queue_count(struct fast_task_queue *pQueue)
{
struct fast_task_info *pTask;
int count;
int result;
if ((result=pthread_mutex_lock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return 0;
}
count = 0;
pTask = pQueue->head;
while (pTask != NULL)
{
pTask = pTask->next;
count++;
}
if ((result=pthread_mutex_unlock(&(pQueue->lock))) != 0)
{
logError("file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
return count;
}
int task_queue_get_new_buffer_size(const int min_buff_size,
const int max_buff_size, const int expect_size, int *new_size)
{
if (min_buff_size == max_buff_size) {
if (min_buff_size == max_buff_size)
{
logError("file: "__FILE__", line: %d, "
"can't change buffer size because NOT supported", __LINE__);
return EOPNOTSUPP;
}
if (expect_size > max_buff_size) {
if (expect_size > max_buff_size)
{
logError("file: "__FILE__", line: %d, "
"can't change buffer size because expect buffer size: %d "
"exceeds max buffer size: %d", __LINE__, expect_size,
max_buff_size);
return EOVERFLOW;
} else if (expect_size == max_buff_size) {
*new_size = max_buff_size;
return 0;
}
*new_size = min_buff_size;
if (expect_size > min_buff_size) {
while (*new_size < expect_size) {
if (expect_size > min_buff_size)
{
while (*new_size < expect_size)
{
*new_size *= 2;
}
if (*new_size > max_buff_size) {
if (*new_size > max_buff_size)
{
*new_size = max_buff_size;
}
}
@ -240,43 +693,41 @@ int free_queue_get_new_buffer_size(const int min_buff_size,
return 0;
}
#define _get_new_buffer_size(queue, expect_size, new_size) \
free_queue_get_new_buffer_size(queue->min_buff_size, \
queue->max_buff_size, expect_size, new_size)
#define _get_new_buffer_size(pQueue, expect_size, new_size) \
task_queue_get_new_buffer_size(pQueue->min_buff_size, \
pQueue->max_buff_size, expect_size, new_size)
int free_queue_set_buffer_size(struct fast_task_info *task,
struct fast_net_buffer *buffer, const int expect_size)
int task_queue_set_buffer_size(struct fast_task_queue *pQueue,
struct fast_task_info *pTask, const int expect_size)
{
int result;
int new_size;
if ((result=_get_new_buffer_size(task->free_queue,
expect_size, &new_size)) != 0)
{
if ((result=_get_new_buffer_size(pQueue, expect_size, &new_size)) != 0) {
return result;
}
if (buffer->size == new_size) { //do NOT need change buffer size
if (pTask->size == new_size) //do NOT need change buffer size
{
return 0;
}
return _realloc_buffer(buffer, new_size, false);
return _realloc_buffer(pTask, new_size, false);
}
int free_queue_realloc_buffer(struct fast_task_info *task,
struct fast_net_buffer *buffer, const int expect_size)
int task_queue_realloc_buffer(struct fast_task_queue *pQueue,
struct fast_task_info *pTask, const int expect_size)
{
int result;
int new_size;
if (buffer->size >= expect_size) { //do NOT need change buffer size
if (pTask->size >= expect_size) //do NOT need change buffer size
{
return 0;
}
if ((result=_get_new_buffer_size(task->free_queue,
expect_size, &new_size)) != 0)
{
if ((result=_get_new_buffer_size(pQueue, expect_size, &new_size)) != 0) {
return result;
}
return _realloc_buffer(buffer, new_size, true);
return _realloc_buffer(pTask, new_size, true);
}

View File

@ -23,10 +23,8 @@
#include <string.h>
#include <pthread.h>
#include "common_define.h"
#include "fc_list.h"
#include "ioevent.h"
#include "fast_timer.h"
#include "fast_mblock.h"
#define FC_NOTIFY_READ_FD(tdata) (tdata)->pipe_fds[0]
#define FC_NOTIFY_WRITE_FD(tdata) (tdata)->pipe_fds[1]
@ -37,27 +35,18 @@ struct nio_thread_data;
struct fast_task_info;
typedef int (*ThreadLoopCallback) (struct nio_thread_data *pThreadData);
typedef void (*TaskCleanUpCallback) (struct fast_task_info *task);
typedef int (*TaskInitCallback)(struct fast_task_info *task, void *arg);
typedef void (*TaskReleaseCallback)(struct fast_task_info *task);
typedef int (*TaskFinishCallback) (struct fast_task_info *pTask);
typedef void (*TaskCleanUpCallback) (struct fast_task_info *pTask);
typedef int (*TaskInitCallback)(struct fast_task_info *pTask);
typedef void (*IOEventCallback) (int sock, const int event, void *arg);
typedef int (*TaskContinueCallback)(struct fast_task_info *task);
typedef void (*IOEventCallback) (int sock, short event, void *arg);
struct sf_network_handler;
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
{
FastTimerEntry timer; //must first
int fd;
int res; //just for io_uring, since v1.0.81
IOEventCallback callback;
} IOEventEntry;
@ -68,7 +57,6 @@ struct nio_thread_data
int pipe_fds[2]; //for notify
struct fast_task_info *deleted_list; //tasks for cleanup
ThreadLoopCallback thread_loop_callback;
ThreadLoopCallback busy_polling_callback;
void *arg; //extra argument pointer
struct {
struct fast_task_info *head;
@ -80,9 +68,6 @@ struct nio_thread_data
bool enabled;
volatile int64_t counter;
} notify; //for thread notify
int timeout_ms; //for restore
struct fc_list_head polling_queue; //for RDMA busy polling
};
struct ioevent_notify_entry
@ -91,225 +76,109 @@ struct ioevent_notify_entry
struct nio_thread_data *thread_data;
};
struct fast_net_buffer
{
int size; //alloc size
int length; //data length
int offset; //current offset
char *data; //buffer for write or read
};
struct fast_net_buffer_wrapper
{
struct fast_net_buffer holder;
struct fast_net_buffer *ptr;
};
struct fast_task_queue;
struct fast_task_info
{
IOEventEntry event; //must first
IOEventEntry event; //must first
union {
char server_ip[IP_ADDRESS_SIZE];
char client_ip[IP_ADDRESS_SIZE];
};
void *arg; //extra argument pointer
char *recv_body; //for extra (dynamic) recv buffer
void *arg; //extra argument pointer
char *data; //buffer for write or read
struct {
struct iovec *iovs;
int count;
} iovec_array; //for writev
struct fast_net_buffer_wrapper send; //send buffer
struct fast_net_buffer_wrapper recv; //recv buffer
int size; //alloc size
int length; //data length
int offset; //current offset
uint16_t port; //peer port
struct {
int8_t is_client;
uint8_t op_type;
} uring; //just for io_uring, since v1.0.81
struct {
uint8_t current;
volatile uint8_t notify;
} nio_stages; //stages for network IO
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;
int64_t req_count; //request count
struct {
int64_t last_req_count;
uint32_t last_calc_time;
uint16_t continuous_count;
bool in_queue;
struct fc_list_head dlink; //for polling queue
} polling; //for RDMA busy polling
TaskContinueCallback continue_callback; //for continue stage
struct nio_thread_data *thread_data;
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 *notify_next; //for nio notify queue
struct fast_task_queue *free_queue; //task allocator
char conn[0]; //for RDMA connection
int (*continue_callback)(struct fast_task_info *task); //for continue stage
volatile int8_t reffer_count;
volatile int8_t canceled; //if task canceled
short connect_timeout; //for client side
short network_timeout;
int64_t req_count; //request count
TaskFinishCallback finish_callback;
struct nio_thread_data *thread_data;
void *ctx; //context pointer for libserverframe nio
struct fast_task_info *next;
};
struct fast_task_queue
{
int min_buff_size;
int max_buff_size;
int padding_size; //for last field: conn[0]
int arg_size; //for arg pointer
int block_size;
bool malloc_whole_block;
bool double_buffers; //if send buffer and recv buffer are independent
bool need_shrink;
struct fast_mblock_man allocator;
struct fast_task_info *head;
struct fast_task_info *tail;
pthread_mutex_t lock;
int max_connections;
int alloc_connections;
int alloc_task_once;
int min_buff_size;
int max_buff_size;
int arg_size;
int block_size;
bool malloc_whole_block;
TaskInitCallback init_callback;
void *init_arg;
TaskReleaseCallback release_callback;
};
#ifdef __cplusplus
extern "C" {
#endif
int free_queue_init_ex2(struct fast_task_queue *queue, const char *name,
const bool double_buffers, const bool need_shrink,
const int max_connections, const int alloc_task_once,
const int min_buff_size, const int max_buff_size,
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,
const char *name, const bool double_buffers,
const bool need_shrink, const int max_connections,
int free_queue_init_ex2(const int max_connections, const int init_connections,
const int alloc_task_once, const int min_buff_size,
const int max_buff_size, const int arg_size)
const int max_buff_size, const int arg_size,
TaskInitCallback init_callback);
static inline int free_queue_init_ex(const int max_connections,
const int init_connections, const int alloc_task_once,
const int min_buff_size, const int max_buff_size, const int arg_size)
{
const int padding_size = 0;
return free_queue_init_ex2(queue, name, double_buffers, need_shrink,
max_connections, alloc_task_once, min_buff_size, max_buff_size,
padding_size, arg_size, NULL, NULL);
return free_queue_init_ex2(max_connections, init_connections,
alloc_task_once, min_buff_size, max_buff_size, arg_size, NULL);
}
static inline int free_queue_init(struct fast_task_queue *queue,
const int max_connections, const int alloc_task_once,
const int min_buff_size, const int max_buff_size)
static inline int free_queue_init(const int max_connections,
const int min_buff_size, const int max_buff_size, const int arg_size)
{
const char *name = "";
const bool double_buffers = false;
const bool need_shrink = true;
const int arg_size = 0;
return free_queue_init_ex(queue, name, double_buffers,
need_shrink, max_connections, alloc_task_once,
min_buff_size, max_buff_size, arg_size);
return free_queue_init_ex2(max_connections, max_connections,
0, min_buff_size, max_buff_size, arg_size, NULL);
}
static inline void free_queue_set_release_callback(
struct fast_task_queue *queue,
TaskReleaseCallback callback)
{
queue->release_callback = callback;
}
void free_queue_destroy();
void free_queue_destroy(struct fast_task_queue *queue);
int free_queue_push(struct fast_task_info *pTask);
struct fast_task_info *free_queue_pop();
int free_queue_count();
int free_queue_alloc_connections();
int free_queue_set_buffer_size(struct fast_task_info *pTask,
const int expect_size);
int free_queue_realloc_buffer(struct fast_task_info *pTask,
const int expect_size);
static inline struct fast_task_info *free_queue_pop(
struct fast_task_queue *queue)
{
return (struct fast_task_info *)fast_mblock_alloc_object(&queue->allocator);
}
int free_queue_set_max_buffer_size(struct fast_task_info *pTask);
void free_queue_push(struct fast_task_info *task);
int free_queue_realloc_max_buffer(struct fast_task_info *pTask);
static inline int free_queue_count(struct fast_task_queue *queue)
{
return queue->allocator.info.element_total_count -
queue->allocator.info.element_used_count;
}
int task_queue_init(struct fast_task_queue *pQueue);
int task_queue_push(struct fast_task_queue *pQueue, \
struct fast_task_info *pTask);
struct fast_task_info *task_queue_pop(struct fast_task_queue *pQueue);
int task_queue_count(struct fast_task_queue *pQueue);
int task_queue_set_buffer_size(struct fast_task_queue *pQueue,
struct fast_task_info *pTask, const int expect_size);
int task_queue_realloc_buffer(struct fast_task_queue *pQueue,
struct fast_task_info *pTask, const int expect_size);
static inline int free_queue_alloc_connections(struct fast_task_queue *queue)
{
return queue->allocator.info.element_total_count;
}
int free_queue_get_new_buffer_size(const int min_buff_size,
int task_queue_get_new_buffer_size(const int min_buff_size,
const int max_buff_size, const int expect_size, int *new_size);
int free_queue_set_buffer_size(struct fast_task_info *task,
struct fast_net_buffer *buffer, const int expect_size);
static inline int free_queue_set_max_buffer_size(
struct fast_task_info *task,
struct fast_net_buffer *buffer)
{
return free_queue_set_buffer_size(task, buffer,
task->free_queue->max_buff_size);
}
int free_queue_realloc_buffer(struct fast_task_info *task,
struct fast_net_buffer *buffer, const int expect_size);
static inline int free_queue_realloc_max_buffer(
struct fast_task_info *task,
struct fast_net_buffer *buffer)
{
return free_queue_realloc_buffer(task, buffer,
task->free_queue->max_buff_size);
}
/* send and recv buffer operations */
static inline int free_queue_set_send_buffer_size(
struct fast_task_info *task, const int expect_size)
{
return free_queue_set_buffer_size(task, task->send.ptr, expect_size);
}
static inline int free_queue_set_recv_buffer_size(
struct fast_task_info *task, const int expect_size)
{
return free_queue_set_buffer_size(task, task->recv.ptr, expect_size);
}
static inline int free_queue_set_send_max_buffer_size(
struct fast_task_info *task)
{
return free_queue_set_max_buffer_size(task, task->send.ptr);
}
static inline int free_queue_set_recv_max_buffer_size(
struct fast_task_info *task)
{
return free_queue_set_max_buffer_size(task, task->recv.ptr);
}
static inline int free_queue_realloc_send_buffer(
struct fast_task_info *task, const int expect_size)
{
return free_queue_realloc_buffer(task, task->send.ptr, expect_size);
}
static inline int free_queue_realloc_recv_buffer(
struct fast_task_info *task, const int expect_size)
{
return free_queue_realloc_buffer(task, task->recv.ptr, expect_size);
}
static inline int free_queue_realloc_send_max_buffer(
struct fast_task_info *task)
{
return free_queue_realloc_max_buffer(task, task->send.ptr);
}
static inline int free_queue_realloc_recv_max_buffer(
struct fast_task_info *task)
{
return free_queue_realloc_max_buffer(task, task->recv.ptr);
}
#ifdef __cplusplus
}
#endif

View File

@ -105,7 +105,6 @@ int fast_timer_modify(FastTimer *timer, FastTimerEntry *entry,
if ((result=fast_timer_remove(timer, entry)) == 0) {
fast_timer_add_ex(timer, entry, new_expires, true);
}
return result;
}
return 0;
@ -186,7 +185,6 @@ int fast_timer_timeouts_get(FastTimer *timer, const int64_t current_time,
} else {
last->rehash = false;
}
continue;
}
} else { //expired

View File

@ -36,7 +36,6 @@ extern "C" {
old_value = __sync_add_and_fetch(&var, 0); \
} while (new_value != old_value)
#define FC_ATOMIC_SET(var, new_value) \
do { \
typeof(var) _old_value; \
@ -49,27 +48,6 @@ extern "C" {
} while (new_value != _old_value); \
} while (0)
#define FC_ATOMIC_SET_BY_CONDITION(var, value, skip_operator) \
do { \
typeof(var) old; \
old = __sync_add_and_fetch(&var, 0); \
if (value skip_operator old) { \
break; \
} \
if (__sync_bool_compare_and_swap(&var, old, value)) { \
break; \
} \
} while (1)
#define FC_ATOMIC_SET_LARGER(var, value) \
FC_ATOMIC_SET_BY_CONDITION(var, value, <=)
#define FC_ATOMIC_SET_SMALLER(var, value) \
FC_ATOMIC_SET_BY_CONDITION(var, value, >=)
#ifdef __cplusplus
}
#endif

View File

@ -45,16 +45,6 @@ fc_list_add_before (struct fc_list_head *_new, struct fc_list_head *current)
_new->next->prev = _new;
}
static inline void
fc_list_add_after (struct fc_list_head *_new, struct fc_list_head *current)
{
_new->prev = current;
_new->next = current->next;
current->next->prev = _new;
current->next = _new;
}
static inline void
fc_list_add_internal (struct fc_list_head *_new, struct fc_list_head *prev,
struct fc_list_head *next)

View File

@ -15,14 +15,22 @@
//fc_queue.c
#include <errno.h>
#include <pthread.h>
#include <inttypes.h>
#include "logger.h"
#include "shared_func.h"
#include "pthread_func.h"
#include "fc_queue.h"
#define FC_QUEUE_NEXT_PTR(queue, data) \
*((void **)(((char *)data) + queue->next_ptr_offset))
int fc_queue_init(struct fc_queue *queue, const int next_ptr_offset)
{
int result;
if ((result=init_pthread_lock_cond_pair(&queue->lcp)) != 0)
if ((result=init_pthread_lock_cond_pair(&queue->lc_pair)) != 0)
{
return result;
}
@ -35,12 +43,12 @@ int fc_queue_init(struct fc_queue *queue, const int next_ptr_offset)
void fc_queue_destroy(struct fc_queue *queue)
{
destroy_pthread_lock_cond_pair(&queue->lcp);
destroy_pthread_lock_cond_pair(&queue->lc_pair);
}
void fc_queue_push_ex(struct fc_queue *queue, void *data, bool *notify)
{
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
FC_QUEUE_NEXT_PTR(queue, data) = NULL;
if (queue->tail == NULL) {
queue->head = data;
@ -50,58 +58,15 @@ void fc_queue_push_ex(struct fc_queue *queue, void *data, bool *notify)
*notify = false;
}
queue->tail = data;
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
}
static inline bool fc_queue_exists(struct fc_queue *queue, void *data)
{
void *current;
if (queue->head == NULL) {
return false;
}
current = queue->head;
do {
if (current == data) {
return true;
}
current = FC_QUEUE_NEXT_PTR(queue, current);
} while (current != NULL);
return false;
}
int fc_queue_push_with_check_ex(struct fc_queue *queue,
void *data, bool *notify)
{
int result;
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
if (fc_queue_exists(queue, data)) {
result = EEXIST;
*notify = false;
} else {
result = 0;
FC_QUEUE_NEXT_PTR(queue, data) = NULL;
if (queue->tail == NULL) {
queue->head = data;
*notify = true;
} else {
FC_QUEUE_NEXT_PTR(queue, queue->tail) = data;
*notify = false;
}
queue->tail = data;
}
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
return result;
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
}
void *fc_queue_pop_ex(struct fc_queue *queue, const bool blocked)
{
void *data;
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
do {
data = queue->head;
if (data == NULL) {
@ -109,7 +74,7 @@ void *fc_queue_pop_ex(struct fc_queue *queue, const bool blocked)
break;
}
pthread_cond_wait(&queue->lcp.cond, &queue->lcp.lock);
pthread_cond_wait(&queue->lc_pair.cond, &queue->lc_pair.lock);
data = queue->head;
}
@ -121,7 +86,7 @@ void *fc_queue_pop_ex(struct fc_queue *queue, const bool blocked)
}
} while (0);
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
return data;
}
@ -129,7 +94,7 @@ void *fc_queue_pop_all_ex(struct fc_queue *queue, const bool blocked)
{
void *data;
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
do {
data = queue->head;
if (data == NULL) {
@ -137,7 +102,7 @@ void *fc_queue_pop_all_ex(struct fc_queue *queue, const bool blocked)
break;
}
pthread_cond_wait(&queue->lcp.cond, &queue->lcp.lock);
pthread_cond_wait(&queue->lc_pair.cond, &queue->lc_pair.lock);
data = queue->head;
}
@ -146,7 +111,7 @@ void *fc_queue_pop_all_ex(struct fc_queue *queue, const bool blocked)
}
} while (0);
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
return data;
}
@ -158,7 +123,7 @@ void fc_queue_push_queue_to_head_ex(struct fc_queue *queue,
return;
}
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
FC_QUEUE_NEXT_PTR(queue, qinfo->tail) = queue->head;
queue->head = qinfo->head;
if (queue->tail == NULL) {
@ -167,7 +132,7 @@ void fc_queue_push_queue_to_head_ex(struct fc_queue *queue,
} else {
*notify = false;
}
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
}
void fc_queue_push_queue_to_tail_ex(struct fc_queue *queue,
@ -178,7 +143,7 @@ void fc_queue_push_queue_to_tail_ex(struct fc_queue *queue,
return;
}
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
if (queue->head == NULL) {
queue->head = qinfo->head;
*notify = true;
@ -187,16 +152,16 @@ void fc_queue_push_queue_to_tail_ex(struct fc_queue *queue,
*notify = false;
}
queue->tail = qinfo->tail;
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
}
void fc_queue_pop_to_queue_ex(struct fc_queue *queue,
struct fc_queue_info *qinfo, const bool blocked)
{
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
if (queue->head == NULL) {
if (blocked) {
pthread_cond_wait(&queue->lcp.cond, &queue->lcp.lock);
pthread_cond_wait(&queue->lc_pair.cond, &queue->lc_pair.lock);
}
}
@ -207,7 +172,7 @@ void fc_queue_pop_to_queue_ex(struct fc_queue *queue,
} else {
qinfo->head = qinfo->tail = NULL;
}
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
}
void *fc_queue_timedpop(struct fc_queue *queue,
@ -215,129 +180,22 @@ void *fc_queue_timedpop(struct fc_queue *queue,
{
void *data;
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
data = queue->head;
if (data == NULL) {
fc_cond_timedwait(&queue->lcp, timeout, time_unit);
PTHREAD_MUTEX_LOCK(&queue->lc_pair.lock);
do {
data = queue->head;
}
if (data != NULL) {
queue->head = FC_QUEUE_NEXT_PTR(queue, data);
if (queue->head == NULL) {
queue->tail = NULL;
if (data == NULL) {
fc_cond_timedwait(&queue->lc_pair, timeout, time_unit);
data = queue->head;
}
}
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
if (data != NULL) {
queue->head = FC_QUEUE_NEXT_PTR(queue, data);
if (queue->head == NULL) {
queue->tail = NULL;
}
}
} while (0);
PTHREAD_MUTEX_UNLOCK(&queue->lc_pair.lock);
return data;
}
void *fc_queue_timedpeek(struct fc_queue *queue,
const int timeout, const int time_unit)
{
void *data;
PTHREAD_MUTEX_LOCK(&queue->lcp.lock);
data = queue->head;
if (data == NULL) {
fc_cond_timedwait(&queue->lcp, timeout, time_unit);
data = queue->head;
}
PTHREAD_MUTEX_UNLOCK(&queue->lcp.lock);
return data;
}
int fc_queue_alloc_chain(struct fc_queue *queue, struct fast_mblock_man
*mblock, const int count, struct fc_queue_info *chain)
{
struct fast_mblock_node *node;
if ((node=fast_mblock_batch_alloc1(mblock, count)) == NULL) {
chain->head = chain->tail = NULL;
return ENOMEM;
}
chain->head = chain->tail = node->data;
while ((node=node->next) != NULL) {
FC_QUEUE_NEXT_PTR(queue, chain->tail) = node->data;
chain->tail = node->data;
}
FC_QUEUE_NEXT_PTR(queue, chain->tail) = NULL;
return 0;
}
int fc_queue_free_chain(struct fc_queue *queue, struct fast_mblock_man
*mblock, struct fc_queue_info *qinfo)
{
struct fast_mblock_node *previous;
struct fast_mblock_node *current;
struct fast_mblock_chain chain;
void *data;
if (qinfo->head == NULL) {
return 0;
}
chain.head = previous = fast_mblock_to_node_ptr(qinfo->head);
data = FC_QUEUE_NEXT_PTR(queue, qinfo->head);
while (data != NULL) {
current = fast_mblock_to_node_ptr(data);
previous->next = current;
previous = current;
data = FC_QUEUE_NEXT_PTR(queue, data);
}
previous->next = NULL;
chain.tail = previous;
return fast_mblock_batch_free(mblock, &chain);
}
int fc_queue_remove(struct fc_queue *queue, void *data)
{
void *previous;
void *current;
int result;
pthread_mutex_lock(&queue->lcp.lock);
if (queue->head == NULL)
{
result = ENOENT;
}
else if (queue->head == data)
{
queue->head = FC_QUEUE_NEXT_PTR(queue, queue->head);
if (queue->head == NULL)
{
queue->tail = NULL;
}
result = 0;
}
else
{
result = ENOENT;
previous = queue->head;
while ((current=FC_QUEUE_NEXT_PTR(queue, previous)) != NULL)
{
if (current == data)
{
FC_QUEUE_NEXT_PTR(queue, previous) =
FC_QUEUE_NEXT_PTR(queue, current);
if (queue->tail == current)
{
queue->tail = previous;
}
result = 0;
break;
}
previous = current;
}
}
pthread_mutex_unlock(&queue->lcp.lock);
return result;
}

View File

@ -18,8 +18,11 @@
#ifndef _FC_QUEUE_H
#define _FC_QUEUE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "common_define.h"
#include "fast_mblock.h"
struct fc_queue_info
{
@ -31,14 +34,10 @@ struct fc_queue
{
void *head;
void *tail;
pthread_lock_cond_pair_t lcp;
pthread_lock_cond_pair_t lc_pair;
int next_ptr_offset;
};
#define FC_QUEUE_NEXT_PTR(queue, data) \
*((void **)(((char *)data) + (queue)->next_ptr_offset))
#ifdef __cplusplus
extern "C" {
#endif
@ -49,7 +48,7 @@ void fc_queue_destroy(struct fc_queue *queue);
static inline void fc_queue_terminate(struct fc_queue *queue)
{
pthread_cond_signal(&queue->lcp.cond);
pthread_cond_signal(&queue->lc_pair.cond);
}
static inline void fc_queue_terminate_all(
@ -57,19 +56,12 @@ static inline void fc_queue_terminate_all(
{
int i;
for (i=0; i<count; i++) {
pthread_cond_signal(&(queue->lcp.cond));
pthread_cond_signal(&(queue->lc_pair.cond));
}
}
#define fc_queue_notify(queue) fc_queue_terminate(queue)
#define fc_queue_notify_all(queue, count) \
fc_queue_terminate_all(queue, count)
//notify by the caller
void fc_queue_push_ex(struct fc_queue *queue, void *data, bool *notify);
int fc_queue_push_with_check_ex(struct fc_queue *queue,
void *data, bool *notify);
static inline void fc_queue_push(struct fc_queue *queue, void *data)
{
@ -77,23 +69,10 @@ static inline void fc_queue_push(struct fc_queue *queue, void *data)
fc_queue_push_ex(queue, data, &notify);
if (notify) {
pthread_cond_signal(&(queue->lcp.cond));
pthread_cond_signal(&(queue->lc_pair.cond));
}
}
static inline int fc_queue_push_with_check(struct fc_queue *queue, void *data)
{
int result;
bool notify;
result = fc_queue_push_with_check_ex(queue, data, &notify);
if (notify) {
pthread_cond_signal(&(queue->lcp.cond));
}
return result;
}
static inline void fc_queue_push_silence(struct fc_queue *queue, void *data)
{
bool notify;
@ -110,7 +89,7 @@ static inline void fc_queue_push_queue_to_head(struct fc_queue *queue,
fc_queue_push_queue_to_head_ex(queue, qinfo, &notify);
if (notify) {
pthread_cond_signal(&(queue->lcp.cond));
pthread_cond_signal(&(queue->lc_pair.cond));
}
}
@ -131,7 +110,7 @@ static inline void fc_queue_push_queue_to_tail(struct fc_queue *queue,
fc_queue_push_queue_to_tail_ex(queue, qinfo, &notify);
if (notify) {
pthread_cond_signal(&(queue->lcp.cond));
pthread_cond_signal(&(queue->lc_pair.cond));
}
}
@ -163,39 +142,12 @@ static inline bool fc_queue_empty(struct fc_queue *queue)
{
bool empty;
pthread_mutex_lock(&queue->lcp.lock);
pthread_mutex_lock(&queue->lc_pair.lock);
empty = (queue->head == NULL);
pthread_mutex_unlock(&queue->lcp.lock);
pthread_mutex_unlock(&queue->lc_pair.lock);
return empty;
}
static inline int fc_queue_count(struct fc_queue *queue)
{
int count;
void *data;
count = 0;
pthread_mutex_lock(&queue->lcp.lock);
data = queue->head;
while (data != NULL)
{
++count;
data = FC_QUEUE_NEXT_PTR(queue, data);
}
pthread_mutex_unlock(&queue->lcp.lock);
return count;
}
static inline void *fc_queue_peek(struct fc_queue *queue)
{
void *data;
pthread_mutex_lock(&queue->lcp.lock);
data = queue->head;
pthread_mutex_unlock(&queue->lcp.lock);
return data;
}
void *fc_queue_timedpop(struct fc_queue *queue,
const int timeout, const int time_unit);
@ -208,26 +160,6 @@ void *fc_queue_timedpop(struct fc_queue *queue,
#define fc_queue_timedpop_us(queue, timeout_us) \
fc_queue_timedpop(queue, timeout_us, FC_TIME_UNIT_USECOND)
void *fc_queue_timedpeek(struct fc_queue *queue,
const int timeout, const int time_unit);
#define fc_queue_timedpeek_sec(queue, timeout) \
fc_queue_timedpeek(queue, timeout, FC_TIME_UNIT_SECOND)
#define fc_queue_timedpeek_ms(queue, timeout_ms) \
fc_queue_timedpeek(queue, timeout_ms, FC_TIME_UNIT_MSECOND)
#define fc_queue_timedpeek_us(queue, timeout_us) \
fc_queue_timedpeek(queue, timeout_us, FC_TIME_UNIT_USECOND)
int fc_queue_alloc_chain(struct fc_queue *queue, struct fast_mblock_man
*mblock, const int count, struct fc_queue_info *chain);
int fc_queue_free_chain(struct fc_queue *queue, struct fast_mblock_man
*mblock, struct fc_queue_info *qinfo);
int fc_queue_remove(struct fc_queue *queue, void *data);
#ifdef __cplusplus
}
#endif

View File

@ -79,7 +79,7 @@ static int _hash_alloc_buckets(HashArray *pHash, const unsigned int old_capacity
return 0;
}
unsigned int *fc_hash_get_prime_capacity(const int capacity)
unsigned int *hash_get_prime_capacity(const int capacity)
{
unsigned int *pprime;
unsigned int *prime_end;
@ -95,14 +95,14 @@ unsigned int *fc_hash_get_prime_capacity(const int capacity)
return NULL;
}
int fc_hash_init_ex(HashArray *pHash, HashFunc hash_func, \
int hash_init_ex(HashArray *pHash, HashFunc hash_func, \
const unsigned int capacity, const double load_factor, \
const int64_t max_bytes, const bool bMallocValue)
{
int result;
memset(pHash, 0, sizeof(HashArray));
pHash->capacity = fc_hash_get_prime_capacity(capacity);
pHash->capacity = hash_get_prime_capacity(capacity);
if (pHash->capacity == NULL)
{
return EINVAL;
@ -129,7 +129,7 @@ int fc_hash_init_ex(HashArray *pHash, HashFunc hash_func, \
return 0;
}
int fc_hash_set_locks(HashArray *pHash, const int lock_count)
int hash_set_locks(HashArray *pHash, const int lock_count)
{
size_t bytes;
pthread_mutex_t *lock;
@ -168,7 +168,7 @@ int fc_hash_set_locks(HashArray *pHash, const int lock_count)
return 0;
}
void fc_hash_destroy(HashArray *pHash)
void hash_destroy(HashArray *pHash)
{
HashData **ppBucket;
HashData **bucket_end;
@ -238,7 +238,7 @@ void fc_hash_destroy(HashArray *pHash)
}
int fc_hash_stat(HashArray *pHash, HashStat *pStat, \
int hash_stat(HashArray *pHash, HashStat *pStat, \
int *stat_by_lens, const int stat_size)
{
HashData **ppBucket;
@ -299,13 +299,13 @@ int fc_hash_stat(HashArray *pHash, HashStat *pStat, \
return 0;
}
void fc_hash_stat_print(HashArray *pHash)
void hash_stat_print(HashArray *pHash)
{
#define STAT_MAX_NUM 64
HashStat hs;
int stats[STAT_MAX_NUM];
if (fc_hash_stat(pHash, &hs, stats, STAT_MAX_NUM) != 0)
if (hash_stat(pHash, &hs, stats, STAT_MAX_NUM) != 0)
{
printf("hash max length exceeds %d!\n", STAT_MAX_NUM);
return;
@ -381,7 +381,7 @@ static int _rehash(HashArray *pHash)
pOldCapacity = pHash->capacity;
if (pHash->is_malloc_capacity)
{
pHash->capacity = fc_hash_get_prime_capacity(*pOldCapacity);
pHash->capacity = hash_get_prime_capacity(*pOldCapacity);
}
else
{
@ -456,7 +456,7 @@ static int _hash_conflict_count(HashArray *pHash)
return conflict_count;
}
int fc_hash_best_op(HashArray *pHash, const int suggest_capacity)
int hash_best_op(HashArray *pHash, const int suggest_capacity)
{
int old_capacity;
int conflict_count;
@ -513,7 +513,7 @@ int fc_hash_best_op(HashArray *pHash, const int suggest_capacity)
pHash->is_malloc_capacity = true;
//fc_hash_stat_print(pHash);
//hash_stat_print(pHash);
return 1;
}
@ -537,7 +537,7 @@ static HashData *_chain_find_entry(HashData **ppBucket, const void *key, \
return NULL;
}
HashData *fc_hash_find_ex(HashArray *pHash, const void *key, const int key_len)
HashData *hash_find_ex(HashArray *pHash, const void *key, const int key_len)
{
unsigned int hash_code;
HashData **ppBucket;
@ -553,7 +553,7 @@ HashData *fc_hash_find_ex(HashArray *pHash, const void *key, const int key_len)
return hash_data;
}
void *fc_hash_find(HashArray *pHash, const void *key, const int key_len)
void *hash_find(HashArray *pHash, const void *key, const int key_len)
{
unsigned int hash_code;
HashData **ppBucket;
@ -576,10 +576,10 @@ void *fc_hash_find(HashArray *pHash, const void *key, const int key_len)
}
}
int fc_hash_find2(HashArray *pHash, const string_t *key, string_t *value)
int hash_find2(HashArray *pHash, const string_t *key, string_t *value)
{
HashData *hdata;
if ((hdata=fc_hash_find1_ex(pHash, key)) == NULL)
if ((hdata=hash_find1_ex(pHash, key)) == NULL)
{
return ENOENT;
}
@ -589,12 +589,12 @@ int fc_hash_find2(HashArray *pHash, const string_t *key, string_t *value)
return 0;
}
HashData *fc_hash_find1_ex(HashArray *pHash, const string_t *key)
HashData *hash_find1_ex(HashArray *pHash, const string_t *key)
{
return fc_hash_find_ex(pHash, key->str, key->len);
return hash_find_ex(pHash, key->str, key->len);
}
int fc_hash_get(HashArray *pHash, const void *key, const int key_len,
int hash_get(HashArray *pHash, const void *key, const int key_len,
void *value, int *value_len)
{
unsigned int hash_code;
@ -628,7 +628,7 @@ int fc_hash_get(HashArray *pHash, const void *key, const int key_len,
return result;
}
int fc_hash_insert_ex(HashArray *pHash, const void *key, const int key_len,
int hash_insert_ex(HashArray *pHash, const void *key, const int key_len, \
void *value, const int value_len, const bool needLock)
{
unsigned int hash_code;
@ -760,7 +760,7 @@ int fc_hash_insert_ex(HashArray *pHash, const void *key, const int key_len,
return 1;
}
int64_t fc_hash_inc_value(const HashData *old_data, const int inc,
int64_t hash_inc_value(const HashData *old_data, const int inc,
char *new_value, int *new_value_len, void *arg)
{
int64_t n;
@ -768,26 +768,27 @@ int64_t fc_hash_inc_value(const HashData *old_data, const int inc,
{
if (old_data->value_len < *new_value_len)
{
memcpy(new_value, old_data->value, old_data->value_len);
new_value[old_data->value_len] = '\0';
n = strtoll(new_value, NULL, 10);
n += inc;
memcpy(new_value, old_data->value, old_data->value_len);
new_value[old_data->value_len] = '\0';
n = strtoll(new_value, NULL, 10);
n += inc;
}
else
{
n = inc;
}
*new_value_len = sprintf(new_value, "%"PRId64, n);
}
else
{
n = inc;
*new_value_len = sprintf(new_value, "%"PRId64, n);
}
*new_value_len = fc_itoa(n, new_value);
return n;
}
int fc_hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
int hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
const int inc, char *value, int *value_len,
ConvertValueFunc convert_func, void *arg)
{
@ -822,7 +823,7 @@ int fc_hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
}
}
}
result = fc_hash_insert_ex(pHash, key, key_len, value, *value_len, false);
result = hash_insert_ex(pHash, key, key_len, value, *value_len, false);
if (result < 0)
{
*value = '\0';
@ -838,7 +839,7 @@ int fc_hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
return result;
}
int fc_hash_partial_set(HashArray *pHash, const void *key, const int key_len,
int hash_partial_set(HashArray *pHash, const void *key, const int key_len,
const char *value, const int offset, const int value_len)
{
unsigned int hash_code;
@ -880,7 +881,7 @@ int fc_hash_partial_set(HashArray *pHash, const void *key, const int key_len,
memcpy(pNewBuff, hash_data->value, offset);
}
memcpy(pNewBuff + offset, value, value_len);
result = fc_hash_insert_ex(pHash, key, key_len, pNewBuff,
result = hash_insert_ex(pHash, key, key_len, pNewBuff,
offset + value_len, false);
free(pNewBuff);
}
@ -891,8 +892,8 @@ int fc_hash_partial_set(HashArray *pHash, const void *key, const int key_len,
result = ENOENT;
break;
}
result = fc_hash_insert_ex(pHash, key, key_len,
(void *)value, value_len, false);
result = hash_insert_ex(pHash, key, key_len, (void *)value,
value_len, false);
}
if (result < 0)
@ -909,7 +910,7 @@ int fc_hash_partial_set(HashArray *pHash, const void *key, const int key_len,
return result;
}
int fc_hash_delete(HashArray *pHash, const void *key, const int key_len)
int hash_delete(HashArray *pHash, const void *key, const int key_len)
{
HashData **ppBucket;
HashData *hash_data;
@ -942,7 +943,7 @@ int fc_hash_delete(HashArray *pHash, const void *key, const int key_len)
return result;
}
int fc_hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args)
int hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args)
{
HashData **ppBucket;
HashData **bucket_end;
@ -971,12 +972,12 @@ int fc_hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args)
return 0;
}
int fc_hash_count(HashArray *pHash)
int hash_count(HashArray *pHash)
{
return pHash->item_count;
}
int fc_hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index)
int hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index)
{
if (pHash->lock_count <= 0)
{
@ -987,7 +988,7 @@ int fc_hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index)
pHash->lock_count);
}
int fc_hash_bucket_unlock(HashArray *pHash, const unsigned int bucket_index)
int hash_bucket_unlock(HashArray *pHash, const unsigned int bucket_index)
{
if (pHash->lock_count <= 0)
{
@ -1314,12 +1315,12 @@ int calc_hashnr1_ex(const void* key, const int key_len, \
\
return h; \
int fc_simple_hash(const void* key, const int key_len)
int simple_hash(const void* key, const int key_len)
{
SIMPLE_HASH_FUNC(0)
}
int fc_simple_hash_ex(const void* key, const int key_len, \
int simple_hash_ex(const void* key, const int key_len, \
const int init_value)
{
SIMPLE_HASH_FUNC(init_value)

View File

@ -93,16 +93,16 @@ typedef struct tagHashStat
* parameters:
* index: item index based 0
* data: hash data, including key and value
* args: passed by fc_hash_walk function
* args: passed by hash_walk function
* return 0 for success, != 0 for error
*/
typedef int (*HashWalkFunc)(const int index, const HashData *data, void *args);
#define fc_hash_init(pHash, hash_func, capacity, load_factor) \
fc_hash_init_ex(pHash, hash_func, capacity, load_factor, 0, false)
#define hash_init(pHash, hash_func, capacity, load_factor) \
hash_init_ex(pHash, hash_func, capacity, load_factor, 0, false)
#define fc_hash_insert(pHash, key, key_len, value) \
fc_hash_insert_ex(pHash, key, key_len, value, 0, true)
#define hash_insert(pHash, key, key_len, value) \
hash_insert_ex(pHash, key, key_len, value, 0, true)
/**
* hash init function
@ -115,7 +115,7 @@ typedef int (*HashWalkFunc)(const int index, const HashData *data, void *args);
* bMallocValue: if need malloc value buffer
* return 0 for success, != 0 for error
*/
int fc_hash_init_ex(HashArray *pHash, HashFunc hash_func, \
int hash_init_ex(HashArray *pHash, HashFunc hash_func, \
const unsigned int capacity, const double load_factor, \
const int64_t max_bytes, const bool bMallocValue);
@ -125,7 +125,7 @@ int fc_hash_init_ex(HashArray *pHash, HashFunc hash_func, \
* lock_count: the lock count
* return 0 for success, != 0 for error
*/
int fc_hash_set_locks(HashArray *pHash, const int lock_count);
int hash_set_locks(HashArray *pHash, const int lock_count);
/**
* convert the value
@ -137,12 +137,12 @@ int fc_hash_set_locks(HashArray *pHash, const int lock_count);
* arg: the user data
* return the number after increasement
*/
int64_t fc_hash_inc_value(const HashData *old_data, const int inc,
int64_t hash_inc_value(const HashData *old_data, const int inc,
char *new_value, int *new_value_len, void *arg);
#define fc_hash_inc(pHash, key, key_len, inc, value, value_len) \
fc_hash_inc_ex(pHash, key, key_len, inc, value, value_len, \
fc_hash_inc_value, NULL)
#define hash_inc(pHash, key, key_len, inc, value, value_len) \
hash_inc_ex(pHash, key, key_len, inc, value, value_len, \
hash_inc_value, NULL)
/**
* atomic increase value
@ -158,7 +158,7 @@ int64_t fc_hash_inc_value(const HashData *old_data, const int inc,
* return 0 for success, != 0 for error (errno)
*
*/
int fc_hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
int hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
const int inc, char *value, int *value_len,
ConvertValueFunc convert_func, void *arg);
@ -168,7 +168,7 @@ int fc_hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
* pHash: the hash table
* return none
*/
void fc_hash_destroy(HashArray *pHash);
void hash_destroy(HashArray *pHash);
/**
* hash insert key
@ -182,7 +182,7 @@ void fc_hash_destroy(HashArray *pHash);
* return >= 0 for success, 0 for key already exist (update),
* 1 for new key (insert), < 0 for error
*/
int fc_hash_insert_ex(HashArray *pHash, const void *key, const int key_len, \
int hash_insert_ex(HashArray *pHash, const void *key, const int key_len, \
void *value, const int value_len, const bool needLock);
/**
@ -193,7 +193,7 @@ int fc_hash_insert_ex(HashArray *pHash, const void *key, const int key_len, \
* key_len: length of th key
* return user data, return NULL when the key not exist
*/
void *fc_hash_find(HashArray *pHash, const void *key, const int key_len);
void *hash_find(HashArray *pHash, const void *key, const int key_len);
/**
* hash find key
@ -203,7 +203,7 @@ void *fc_hash_find(HashArray *pHash, const void *key, const int key_len);
* key_len: length of th key
* return hash data, return NULL when the key not exist
*/
HashData *fc_hash_find_ex(HashArray *pHash, const void *key, const int key_len);
HashData *hash_find_ex(HashArray *pHash, const void *key, const int key_len);
/**
* hash find key
@ -212,9 +212,9 @@ HashData *fc_hash_find_ex(HashArray *pHash, const void *key, const int key_len);
* key: the key to find
* return user data, return NULL when the key not exist
*/
static inline void *fc_hash_find1(HashArray *pHash, const string_t *key)
static inline void *hash_find1(HashArray *pHash, const string_t *key)
{
return fc_hash_find(pHash, key->str, key->len);
return hash_find(pHash, key->str, key->len);
}
/**
@ -225,7 +225,7 @@ static inline void *fc_hash_find1(HashArray *pHash, const string_t *key)
* value: store the value
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_find2(HashArray *pHash, const string_t *key, string_t *value);
int hash_find2(HashArray *pHash, const string_t *key, string_t *value);
/**
* hash find key
@ -234,7 +234,7 @@ int fc_hash_find2(HashArray *pHash, const string_t *key, string_t *value);
* key: the key to find
* return hash data, return NULL when the key not exist
*/
HashData *fc_hash_find1_ex(HashArray *pHash, const string_t *key);
HashData *hash_find1_ex(HashArray *pHash, const string_t *key);
/**
* hash get the value of the key
@ -247,7 +247,7 @@ HashData *fc_hash_find1_ex(HashArray *pHash, const string_t *key);
* output for the length fo the value
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_get(HashArray *pHash, const void *key, const int key_len,
int hash_get(HashArray *pHash, const void *key, const int key_len,
void *value, int *value_len);
@ -262,7 +262,7 @@ int fc_hash_get(HashArray *pHash, const void *key, const int key_len,
* value_len: length of the value
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_partial_set(HashArray *pHash, const void *key, const int key_len,
int hash_partial_set(HashArray *pHash, const void *key, const int key_len,
const char *value, const int offset, const int value_len);
/**
@ -273,7 +273,7 @@ int fc_hash_partial_set(HashArray *pHash, const void *key, const int key_len,
* key_len: length of th key
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_delete(HashArray *pHash, const void *key, const int key_len);
int hash_delete(HashArray *pHash, const void *key, const int key_len);
/**
* hash walk (iterator)
@ -283,7 +283,7 @@ int fc_hash_delete(HashArray *pHash, const void *key, const int key_len);
* args: extra args which will be passed to walkFunc
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args);
int hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args);
/**
* get hash item count
@ -291,7 +291,7 @@ int fc_hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args);
* pHash: the hash table
* return item count
*/
int fc_hash_count(HashArray *pHash);
int hash_count(HashArray *pHash);
/**
* hash best optimize
@ -300,7 +300,7 @@ int fc_hash_count(HashArray *pHash);
* suggest_capacity: suggest init capacity for speed
* return >0 for success, < 0 fail (errno)
*/
int fc_hash_best_op(HashArray *pHash, const int suggest_capacity);
int hash_best_op(HashArray *pHash, const int suggest_capacity);
/**
* hash stat
@ -314,7 +314,7 @@ int fc_hash_best_op(HashArray *pHash, const int suggest_capacity);
* stat_size: stats array size (contain max elments)
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_stat(HashArray *pHash, HashStat *pStat, \
int hash_stat(HashArray *pHash, HashStat *pStat, \
int *stat_by_lens, const int stat_size);
/**
@ -323,7 +323,7 @@ int fc_hash_stat(HashArray *pHash, HashStat *pStat, \
* pHash: the hash table
* return none
*/
void fc_hash_stat_print(HashArray *pHash);
void hash_stat_print(HashArray *pHash);
/**
* lock the bucket of hash table
@ -332,7 +332,7 @@ void fc_hash_stat_print(HashArray *pHash);
* bucket_index: the index of bucket
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index);
int hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index);
/**
* unlock the bucket of hash table
@ -341,7 +341,7 @@ int fc_hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index);
* bucket_index: the index of bucket
* return 0 for success, != 0 fail (errno)
*/
int fc_hash_bucket_unlock(HashArray *pHash, const unsigned int bucket_index);
int hash_bucket_unlock(HashArray *pHash, const unsigned int bucket_index);
int RSHash(const void *key, const int key_len);
@ -383,8 +383,8 @@ int calc_hashnr1(const void* key, const int key_len);
int calc_hashnr1_ex(const void* key, const int key_len, \
const int init_value);
int fc_simple_hash(const void* key, const int key_len);
int fc_simple_hash_ex(const void* key, const int key_len, \
int simple_hash(const void* key, const int key_len);
int simple_hash_ex(const void* key, const int key_len, \
const int init_value);
int CRC32(const void *key, const int key_len);
@ -402,7 +402,7 @@ int64_t CRC32_ex(const void *key, const int key_len, \
#define CALC_HASH_CODES4(buff, buff_len, hash_codes) \
hash_codes[0] = CRC32_ex(buff, buff_len, hash_codes[0]); \
hash_codes[1] = ELFHash_ex(buff, buff_len, hash_codes[1]); \
hash_codes[2] = fc_simple_hash_ex(buff, buff_len, hash_codes[2]); \
hash_codes[2] = simple_hash_ex(buff, buff_len, hash_codes[2]); \
hash_codes[3] = Time33Hash_ex(buff, buff_len, hash_codes[3]); \
@ -410,7 +410,7 @@ int64_t CRC32_ex(const void *key, const int key_len, \
hash_codes[0] = CRC32_FINAL(hash_codes[0]); \
unsigned int *fc_hash_get_prime_capacity(const int capacity);
unsigned int *hash_get_prime_capacity(const int capacity);
#ifdef __cplusplus
}

View File

@ -27,10 +27,6 @@
((strncasecmp(str, "http://", 7) == 0) || \
(strncasecmp(str, "https://", 8) == 0))
#define IS_URL_RESOURCE_EX(s) \
((s)->len >= 8 && ((memcmp((s)->str, "http://", 7) == 0) || \
(memcmp((s)->str, "https://", 8) == 0)))
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -84,7 +84,6 @@ int id_generator_init_extra_ex(struct idg_context *context, const char *filename
const char *local_ip;
const char *private_ip;
struct in_addr ip_addr;
struct in6_addr ip6_addr;
private_ip = get_first_local_private_ip();
if (private_ip != NULL)
@ -101,28 +100,16 @@ int id_generator_init_extra_ex(struct idg_context *context, const char *filename
context->fd = -1;
return ENOENT;
}
else if (strcmp(local_ip, LOCAL_LOOPBACK_IPv4) == 0)
else if (strcmp(local_ip, LOCAL_LOOPBACK_IP) == 0)
{
/* 注意当系统存在IPv6回环地址时为了简化系统的改动
IPv6IPv4
IPv6
*/
logWarning("file: "__FILE__", line: %d, "
"can't get local ip address, set to %s or %s",
__LINE__, LOCAL_LOOPBACK_IPv4, LOCAL_LOOPBACK_IPv6);
"can't get local ip address, set to %s",
__LINE__, LOCAL_LOOPBACK_IP);
}
}
if (inet_pton(AF_INET, local_ip, &ip_addr) == 1)
{
//do nothing
}
else if(inet_pton(AF_INET6, local_ip, &ip6_addr) == 1)
{
ip_addr.s_addr = *((in_addr_64_t *)&ip6_addr);
}
else
{
if (inet_pton(AF_INET, local_ip, &ip_addr) != 1)
{
logError("file: "__FILE__", line: %d, "
"invalid local ip address: %s",
__LINE__, local_ip);
@ -136,14 +123,13 @@ int id_generator_init_extra_ex(struct idg_context *context, const char *filename
mid = ntohl(ip_addr.s_addr) & ((1 << mid_bits) - 1);
}
if ((context->fd = open(filename, O_RDWR | O_CLOEXEC)) < 0)
if ((context->fd = open(filename, O_RDWR)) < 0)
{
if (errno == ENOENT)
{
mode_t old_mode;
old_mode = umask(0);
if ((context->fd=open(filename, O_RDWR | O_CREAT |
O_CLOEXEC, mode)) < 0)
if ((context->fd=open(filename, O_RDWR | O_CREAT, mode)) < 0)
{
result = errno != 0 ? errno : EACCES;
}

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <fcntl.h>
#include "common_define.h"

View File

@ -115,6 +115,13 @@ static DynamicAnnotations *iniAllocAnnotations(IniContext *pContext,
static AnnotationEntry *iniGetAnnotations(IniContext *pContext);
static SetDirectiveVars *iniGetVars(IniContext *pContext);
#define STR_TRIM(pStr) \
do { \
trim_right(pStr); \
trim_left(pStr); \
} while (0)
#define RETRY_FETCH_GLOBAL(szSectionName, bRetryGlobal) \
((szSectionName != NULL && *szSectionName != '\0') && bRetryGlobal)
@ -198,7 +205,7 @@ static int iniAnnotationFuncLocalIpGet(IniContext *context,
(int)(square_start - param), param);
index = atoi(square_start + 1);
} else {
fc_safe_strcpy(name_part, param);
snprintf(name_part, sizeof(name_part) - 1, "%s", param);
index = -2;
}
@ -322,7 +329,7 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
logWarning("file: "__FILE__", line: %d, "
"NO set directives before, set value to %s",
__LINE__, param);
fc_strlcpy(output, param, FAST_INI_ITEM_VALUE_SIZE);
snprintf(output, FAST_INI_ITEM_VALUE_SIZE, "%s", param);
return output;
}
@ -352,10 +359,10 @@ static char *doReplaceVars(IniContext *pContext, const char *param,
memcpy(name, start, name_len);
}
*(name + name_len) = '\0';
fc_trim(name);
trim(name);
name_len = strlen(name);
if (name_len > 0) {
value = (char *)fc_hash_find(set->vars, name, name_len);
value = (char *)hash_find(set->vars, name, name_len);
} else {
value = NULL;
}
@ -546,10 +553,10 @@ static int iniInitContext(IniContext *pContext, const char annotation_type,
memset(pContext, 0, sizeof(IniContext));
pContext->current_section = &pContext->global;
if ((result=fc_hash_init(&pContext->sections, Time33Hash, 32, 0.75)) != 0)
if ((result=hash_init(&pContext->sections, Time33Hash, 32, 0.75)) != 0)
{
logError("file: "__FILE__", line: %d, " \
"fc_hash_init fail, errno: %d, error info: %s", \
"hash_init fail, errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
}
@ -579,7 +586,7 @@ static void iniSortItems(IniContext *pContext)
sizeof(IniItem), iniCompareByItemName);
}
fc_hash_walk(&pContext->sections, iniSortHashData, NULL);
hash_walk(&pContext->sections, iniSortHashData, NULL);
}
int iniLoadFromFile(const char *szFilename, IniContext *pContext)
@ -652,7 +659,7 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
if (IS_URL_RESOURCE(szFilename))
{
*pContext->config_path = '\0';
fc_safe_strcpy(full_filename, szFilename);
snprintf(full_filename, sizeof(full_filename), "%s", szFilename);
}
else
{
@ -675,7 +682,8 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
memcpy(pContext->config_path, szFilename, len);
*(pContext->config_path + len) = '\0';
fc_safe_strcpy(full_filename, szFilename);
snprintf(full_filename, sizeof(full_filename), \
"%s", szFilename);
}
else
{
@ -698,8 +706,9 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
*(pContext->config_path + len) = '\0';
}
fc_combine_full_filename(pContext->config_path,
szFilename, full_filename);
snprintf(full_filename, sizeof(full_filename), \
"%s/%s", pContext->config_path, szFilename);
pLast = strrchr(szFilename, '/');
if (pLast != NULL)
{
@ -857,7 +866,7 @@ static int iniAddAnnotation(char *params)
int count;
int result;
fc_trim(params);
trim(params);
count = fc_split_string(params, " \t", cols, MAX_PARAMS);
if (count < 2)
{
@ -912,7 +921,7 @@ static int iniAddAnnotation(char *params)
return EFAULT;
}
fc_combine_two_strings(func_name, "init_annotation", '_', symbol);
snprintf(symbol, sizeof(symbol), "%s_init_annotation", func_name);
init_func = dlsym(dlhandle, symbol);
if (init_func == NULL)
{
@ -1006,17 +1015,19 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
isAnnotation = 0;
}
fc_trim(pLine);
STR_TRIM(pLine);
if (*pLine == '#' && \
strncasecmp(pLine+1, "include", 7) == 0 && \
(*(pLine+8) == ' ' || *(pLine+8) == '\t'))
{
fc_safe_strcpy(pIncludeFilename, pLine + 9);
fc_trim(pIncludeFilename);
snprintf(pIncludeFilename, sizeof(pIncludeFilename),
"%s", pLine + 9);
STR_TRIM(pIncludeFilename);
if (IS_URL_RESOURCE(pIncludeFilename))
{
fc_safe_strcpy(full_filename, pIncludeFilename);
}
{
snprintf(full_filename, sizeof(full_filename),
"%s", pIncludeFilename);
}
else
{
if (IS_FILE_RESOURCE(pIncludeFilename))
@ -1030,23 +1041,25 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
if (*pTrueFilename == '/')
{
fc_safe_strcpy(full_filename, pTrueFilename);
snprintf(full_filename, sizeof(full_filename), \
"%s", pTrueFilename);
}
else
{
fc_combine_full_filename(pContext->config_path,
pTrueFilename, full_filename);
}
{
snprintf(full_filename, sizeof(full_filename), \
"%s/%s", pContext->config_path, \
pTrueFilename);
}
if (!fileExists(full_filename))
{
logError("file: "__FILE__", line: %d, "
"include file \"%s\" not exists, "
"line: \"%s\"", __LINE__,
pTrueFilename, pLine);
result = ENOENT;
break;
}
{
logError("file: "__FILE__", line: %d, " \
"include file \"%s\" not exists, " \
"line: \"%s\"", __LINE__, \
pTrueFilename, pLine);
result = ENOENT;
break;
}
}
pContext->current_section = &pContext->global;
@ -1079,7 +1092,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
}
memcpy(pFuncName, pLine + 11, nNameLen);
pFuncName[nNameLen] = '\0';
fc_trim(pFuncName);
STR_TRIM(pFuncName);
if ((int)strlen(pFuncName) > 0)
{
isAnnotation = 1;
@ -1119,7 +1132,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
*(pLine + (nLineLen - 1)) = '\0';
section_name = pLine + 1; //skip [
fc_trim(section_name);
STR_TRIM(section_name);
if (*section_name == '\0') //global section
{
pContext->current_section = &pContext->global;
@ -1129,7 +1142,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
}
section_len = strlen(section_name);
pSection = (IniSection *)fc_hash_find(&pContext->sections,\
pSection = (IniSection *)hash_find(&pContext->sections,\
section_name, section_len);
if (pSection == NULL)
{
@ -1141,7 +1154,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
}
memset(pSection, 0, sizeof(IniSection));
result = fc_hash_insert(&pContext->sections, \
result = hash_insert(&pContext->sections, \
section_name, section_len, pSection);
if (result < 0)
{
@ -1212,8 +1225,8 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
memcpy(pItem->name, pLine, nNameLen);
memcpy(pItem->value, pEqualChar + 1, nValueLen);
fc_trim(pItem->name);
fc_trim(pItem->value);
STR_TRIM(pItem->name);
STR_TRIM(pItem->value);
if (isAnnotation)
{
@ -1527,7 +1540,7 @@ static SetDirectiveVars *iniAllocVars(IniContext *pContext, const bool initVars)
{
return NULL;
}
if (fc_hash_init_ex(set->vars, fc_simple_hash, 17, 0.75, 0, true) != 0)
if (hash_init_ex(set->vars, simple_hash, 17, 0.75, 0, true) != 0)
{
free(set->vars);
set->vars = NULL;
@ -1994,7 +2007,7 @@ static bool iniCalcCondition(char *condition, const int condition_len,
set = iniGetVars(pContext);
if (set != NULL && set->vars != NULL)
{
value = (char *)fc_hash_find(set->vars, varStr, varLen);
value = (char *)hash_find(set->vars, varStr, varLen);
if (value == NULL)
{
logWarning("file: "__FILE__", line: %d, "
@ -2151,7 +2164,7 @@ static int iniDoProccessSet(char *pSet, char **ppSetEnd,
}
}
result = fc_hash_insert_ex(set->vars, key, strlen(key),
result = hash_insert_ex(set->vars, key, strlen(key),
new_value, value_len + 1, false);
if (new_value != value) {
free(new_value);
@ -2623,7 +2636,8 @@ static char *iniProccessFor(char *content, const int content_len,
char *pRemain;
int remainLen;
valueLen = fc_itoa(i, value);
valueLen = sprintf(value, "%d", i);
pRemain = pForBlock;
remainLen = forBlockLen;
while (remainLen >= tagLen)
@ -2772,13 +2786,13 @@ void iniFreeContext(IniContext *pContext)
memset(&pContext->global, 0, sizeof(IniSection));
}
fc_hash_walk(&pContext->sections, iniFreeHashData, NULL);
fc_hash_destroy(&pContext->sections);
hash_walk(&pContext->sections, iniFreeHashData, NULL);
hash_destroy(&pContext->sections);
set = iniGetVars(pContext);
if (set != NULL && set->vars != NULL)
{
fc_hash_destroy(set->vars);
hash_destroy(set->vars);
free(set->vars);
set->vars = NULL;
set->offset = 0;
@ -2795,7 +2809,7 @@ do { \
} \
else \
{ \
pSection = (IniSection *)fc_hash_find(&pContext->sections, \
pSection = (IniSection *)hash_find(&pContext->sections, \
szSectionName, strlen(szSectionName)); \
if (pSection == NULL) \
{ \
@ -2810,7 +2824,7 @@ do { \
break; \
} \
\
fc_safe_strcpy(targetItem.name, szItemName); \
snprintf(targetItem.name, sizeof(targetItem.name), "%s", szItemName); \
pItem = (IniItem *)bsearch(&targetItem, pSection->items, \
pSection->count, sizeof(IniItem), iniCompareByItemName); \
} while (0)
@ -2861,21 +2875,6 @@ char *iniGetStrValueEx(const char *szSectionName, const char *szItemName,
return pFound->value;
}
char iniGetCharValueEx(const char *szSectionName, const char *szItemName,
IniContext *pContext, const char cDefaultValue,
const bool bRetryGlobal)
{
char *value;
value = iniGetStrValueEx(szSectionName, szItemName,
pContext, bRetryGlobal);
if (value == NULL) {
return cDefaultValue;
} else {
return value[0];
}
}
#define INI_FILL_SECTION_PROMPT(prompt, size, section_name) \
do { \
if (section_name != NULL && *(section_name) != '\0') { \
@ -2914,64 +2913,6 @@ int64_t iniCheckAndCorrectIntValue(IniFullContext *pIniContext,
return nValue;
}
double iniCheckAndCorrectDoubleValue(IniFullContext *pIniContext,
const char *szItemName, const double dValue,
const double dMinValue, const double dMaxValue)
{
char section_prompt[128];
if (dValue < dMinValue) {
INI_FILL_SECTION_PROMPT(section_prompt, sizeof(section_prompt),
pIniContext->section_name);
logWarning("file: "__FILE__", line: %d, "
"config file: %s, %sitem name: %s, item value: %.2f"
" < min value: %.2f, set to min value: %.2f",
__LINE__, pIniContext->filename, section_prompt,
szItemName, dValue, dMinValue, dMinValue);
return dMinValue;
} else if (dValue > dMaxValue) {
INI_FILL_SECTION_PROMPT(section_prompt, sizeof(section_prompt),
pIniContext->section_name);
logWarning("file: "__FILE__", line: %d, "
"config file: %s, %sitem name: %s, item value: %.2f"
" > max value: %.2f, set to max value: %.2f",
__LINE__, pIniContext->filename, section_prompt,
szItemName, dValue, dMaxValue, dMaxValue);
return dMaxValue;
}
return dValue;
}
double iniCheckAndCorrectPercentValue(IniFullContext *pIniContext,
const char *szItemName, const double dValue,
const double dMinValue, const double dMaxValue)
{
char section_prompt[128];
if (dValue < dMinValue) {
INI_FILL_SECTION_PROMPT(section_prompt, sizeof(section_prompt),
pIniContext->section_name);
logWarning("file: "__FILE__", line: %d, "
"config file: %s, %sitem name: %s, item value: %.2f%%"
" < min value: %.2f%%, set to min value: %.2f%%",
__LINE__, pIniContext->filename, section_prompt,
szItemName, dValue * 100, dMinValue * 100, dMinValue * 100);
return dMinValue;
} else if (dValue > dMaxValue) {
INI_FILL_SECTION_PROMPT(section_prompt, sizeof(section_prompt),
pIniContext->section_name);
logWarning("file: "__FILE__", line: %d, "
"config file: %s, %sitem name: %s, item value: %.2f%%"
" > max value: %.2f%%, set to max value: %.2f%%",
__LINE__, pIniContext->filename, section_prompt,
szItemName, dValue * 100, dMaxValue * 100, dMaxValue * 100);
return dMaxValue;
}
return dValue;
}
int64_t iniGetInt64ValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int64_t nDefaultValue, const bool bRetryGlobal)
@ -3003,36 +2944,6 @@ int64_t iniGetInt64CorrectValueEx(IniFullContext *pIniContext,
value, nMinValue, nMaxValue);
}
double iniGetDoubleCorrectValueEx(IniFullContext *pIniContext,
const char *szItemName, const double dbDefaultValue,
const double dbMinValue, const double dbMaxValue,
const bool bRetryGlobal)
{
double value;
value = iniGetDoubleValueEx(pIniContext->section_name, szItemName,
pIniContext->context, dbDefaultValue, bRetryGlobal);
return iniCheckAndCorrectDoubleValue(pIniContext, szItemName,
value, dbMinValue, dbMaxValue);
}
int iniGetPercentCorrectValueEx(IniFullContext *pIniContext,
const char *szItemName, double *dbItemValue,
const double dbDefaultValue, const double dbMinValue,
const double dbMaxValue, const bool bRetryGlobal)
{
int result;
if ((result=iniGetPercentValueEx(pIniContext, szItemName, dbItemValue,
dbDefaultValue, bRetryGlobal)) == 0)
{
*dbItemValue = iniCheckAndCorrectPercentValue(pIniContext,
szItemName, *dbItemValue, dbMinValue, dbMaxValue);
}
return result;
}
int64_t iniGetByteValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int64_t nDefaultValue, const int nDefaultUnitBytes,
@ -3271,7 +3182,7 @@ void iniPrintItems(IniContext *pContext)
}
printf("\n");
fc_hash_walk(&pContext->sections, iniPrintHashData, NULL);
hash_walk(&pContext->sections, iniPrintHashData, NULL);
}
struct section_name_walk_arg {
@ -3335,7 +3246,7 @@ int iniGetSectionNamesEx(IniContext *pContext, IniSectionNameFilterFunc
walk_arg.args = args;
walk_arg.size = max_size;
walk_arg.count = 0;
result = fc_hash_walk(&pContext->sections, iniSectionNameWalkCallback,
result = hash_walk(&pContext->sections, iniSectionNameWalkCallback,
&walk_arg);
*nCount = walk_arg.count;
return result;
@ -3406,7 +3317,7 @@ int iniGetSectionCountEx(IniContext *pContext, IniSectionNameFilterFunc
walk_arg.filter_func = filter_func;
walk_arg.args = args;
walk_arg.count = 0;
fc_hash_walk(&pContext->sections, iniSectionCountWalkCallback, &walk_arg);
hash_walk(&pContext->sections, iniSectionCountWalkCallback, &walk_arg);
return walk_arg.count;
}
@ -3429,7 +3340,7 @@ IniItem *iniGetSectionItems(const char *szSectionName, IniContext *pContext,
}
else
{
pSection = (IniSection *)fc_hash_find(&pContext->sections,
pSection = (IniSection *)hash_find(&pContext->sections,
szSectionName, strlen(szSectionName));
if (pSection == NULL)
{

View File

@ -117,32 +117,28 @@ extern "C" {
#define iniGetStrValue(szSectionName, szItemName, pContext) \
iniGetStrValueEx(szSectionName, szItemName, pContext, false)
#define iniGetCharValue(szSectionName, szItemName, pContext, cDefaultValue) \
iniGetCharValueEx(szSectionName, szItemName, \
pContext, cDefaultValue, false)
#define iniGetIntValue(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetIntValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, false)
iniGetIntValueEx(szSectionName, szItemName, pContext, \
nDefaultValue, false)
#define iniGetInt64Value(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetInt64ValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, false)
iniGetInt64ValueEx(szSectionName, szItemName, pContext, \
nDefaultValue, false)
#define iniGetDoubleValue(szSectionName, szItemName, pContext, dbDefaultValue) \
iniGetDoubleValueEx(szSectionName, szItemName, \
pContext, dbDefaultValue, false)
iniGetDoubleValueEx(szSectionName, szItemName, pContext, \
dbDefaultValue, false)
#define iniGetBoolValue(szSectionName, szItemName, pContext, bDefaultValue) \
iniGetBoolValueEx(szSectionName, szItemName, \
pContext, bDefaultValue, false)
iniGetBoolValueEx(szSectionName, szItemName, pContext, \
bDefaultValue, false)
#define iniGetPercentValue(ini_ctx, item_name, item_value, default_value) \
iniGetPercentValueEx(ini_ctx, item_name, item_value, default_value, false)
#define iniGetByteValue(szSectionName, szItemName, pContext, nDefaultValue) \
iniGetByteValueEx(szSectionName, szItemName, \
pContext, nDefaultValue, 1, false)
iniGetByteValueEx(szSectionName, szItemName, pContext, \
nDefaultValue, 1, false)
#define iniGetIntCorrectValue(ini_ctx, item_name, \
default_value, min_value, max_value) \
@ -159,16 +155,6 @@ extern "C" {
iniGetByteCorrectValueEx(ini_ctx, item_name, \
default_value, 1, min_value, max_value, false)
#define iniGetDoubleCorrectValue(ini_ctx, item_name, \
default_value, min_value, max_value) \
iniGetDoubleCorrectValueEx(ini_ctx, item_name, \
default_value, 1, min_value, max_value, false)
#define iniGetPercentCorrectValue(ini_ctx, item_name, \
item_value, default_value, min_value, max_value) \
iniGetPercentCorrectValueEx(ini_ctx, item_name, item_value, \
default_value, min_value, max_value, false)
int iniSetAnnotationCallBack(AnnotationEntry *annotations, int count);
void iniDestroyAnnotationCallBack();
@ -257,20 +243,6 @@ void iniFreeContext(IniContext *pContext);
char *iniGetStrValueEx(const char *szSectionName, const char *szItemName,
IniContext *pContext, const bool bRetryGlobal);
/** get the first charactor
* parameters:
* szSectionName: the section name, NULL or empty string for
* global section
* szItemName: the item name
* pContext: the ini context
* cDefaultValue: the default value
* bRetryGlobal: if fetch from global section when the item not exist
* return: item value, return default value when the item not exist
*/
char iniGetCharValueEx(const char *szSectionName, const char *szItemName,
IniContext *pContext, const char cDefaultValue,
const bool bRetryGlobal);
/** get item string value
* parameters:
* szSectionName: the section name, NULL or empty string for
@ -298,7 +270,7 @@ int iniGetIntValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const int nDefaultValue, const bool bRetryGlobal);
/** check and correct int value
/** check and correct item value
* parameters:
* pIniContext: the full ini context
* szItemName: the item name
@ -311,32 +283,6 @@ int64_t iniCheckAndCorrectIntValue(IniFullContext *pIniContext,
const char *szItemName, const int64_t nValue,
const int64_t nMinValue, const int64_t nMaxValue);
/** check and correct double value
* parameters:
* pIniContext: the full ini context
* szItemName: the item name
* dValue: the item value
* dMinValue: the min value to check (including)
* dMaxValue: the max value to check (including)
* return: corrected value
*/
double iniCheckAndCorrectDoubleValue(IniFullContext *pIniContext,
const char *szItemName, const double dValue,
const double dMinValue, const double dMaxValue);
/** check and correct double value (show as percentage)
* parameters:
* pIniContext: the full ini context
* szItemName: the item name
* dValue: the item value
* dMinValue: the min value to check (including)
* dMaxValue: the max value to check (including)
* return: corrected value
*/
double iniCheckAndCorrectPercentValue(IniFullContext *pIniContext,
const char *szItemName, const double dValue,
const double dMinValue, const double dMaxValue);
/** get item correct value (32 bits integer)
* parameters:
* pIniContext: the full ini context
@ -452,20 +398,6 @@ double iniGetDoubleValueEx(const char *szSectionName,
const char *szItemName, IniContext *pContext,
const double dbDefaultValue, const bool bRetryGlobal);
/** get item correct double value
* parameters:
* pIniContext: the full ini context
* szItemName: the item name
* dbDefaultValue: the default value
* dbMinValue: the min value to check (including)
* dbMaxValue: the max value to check (including)
* bRetryGlobal: if fetch from global section when the item not exist
* return: double value, return dbDefaultValue when the item not exist
*/
double iniGetDoubleCorrectValueEx(IniFullContext *pIniContext,
const char *szItemName, const double dbDefaultValue,
const double dbMinValue, const double dbMaxValue,
const bool bRetryGlobal);
/** get item percent double value
* parameters:
@ -480,22 +412,6 @@ int iniGetPercentValueEx(IniFullContext *ini_ctx,
const char *item_name, double *item_value,
const double default_value, const bool retry_global);
/** get item correct double value (show as percentage)
* parameters:
* pIniContext: the full ini context
* szItemName: the item name
* dbItemValue: store the item value
* dbDefaultValue: the default value
* dbMinValue: the min value to check (including)
* dbMaxValue: the max value to check (including)
* bRetryGlobal: if fetch from global section when the item not exist
* return: error no, 0 for success, != 0 for fail
*/
int iniGetPercentCorrectValueEx(IniFullContext *pIniContext,
const char *szItemName, double *dbItemValue,
const double dbDefaultValue, const double dbMinValue,
const double dbMaxValue, const bool bRetryGlobal);
/** print all items
* parameters:
* pContext: the ini context

View File

@ -45,119 +45,71 @@ int kqueue_ev_convert(int16_t event, uint16_t flags)
}
#endif
int ioevent_init(IOEventPoller *ioevent, const char *service_name,
const bool use_io_uring, const int size, const int timeout_ms,
const int extra_events)
int ioevent_init(IOEventPoller *ioevent, const int size,
const int timeout_ms, const int extra_events)
{
int bytes;
int bytes;
ioevent->iterator.index = 0;
ioevent->iterator.count = 0;
ioevent->service_name = service_name;
ioevent->size = size;
ioevent->extra_events = extra_events;
ioevent->size = size;
ioevent->extra_events = extra_events;
ioevent->iterator.index = 0;
ioevent->iterator.count = 0;
#ifdef OS_LINUX
#if IOEVENT_USE_URING
ioevent->use_io_uring = use_io_uring;
if (use_io_uring) {
int result;
if ((result=io_uring_queue_init(size, &ioevent->ring, 0)) < 0) {
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
#if IOEVENT_USE_EPOLL
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);
#elif IOEVENT_USE_KQUEUE
ioevent->poll_fd = kqueue();
if (ioevent->poll_fd < 0) {
return errno != 0 ? errno : ENOMEM;
}
bytes = sizeof(struct kevent) * size;
ioevent->events = (struct kevent *)fc_malloc(bytes);
ioevent->poll_fd = kqueue();
if (ioevent->poll_fd < 0) {
return errno != 0 ? errno : ENOMEM;
}
bytes = sizeof(struct kevent) * size;
ioevent->events = (struct kevent *)fc_malloc(bytes);
#elif IOEVENT_USE_PORT
ioevent->poll_fd = port_create();
if (ioevent->poll_fd < 0) {
return errno != 0 ? errno : ENOMEM;
}
bytes = sizeof(port_event_t) * size;
ioevent->events = (port_event_t *)fc_malloc(bytes);
ioevent->poll_fd = port_create();
if (ioevent->poll_fd < 0) {
return errno != 0 ? errno : ENOMEM;
}
bytes = sizeof(port_event_t) * size;
ioevent->events = (port_event_t *)fc_malloc(bytes);
#endif
#if IOEVENT_USE_URING
if (!ioevent->use_io_uring) {
#endif
if (ioevent->events == NULL) {
close(ioevent->poll_fd);
ioevent->poll_fd = -1;
return ENOMEM;
}
#if IOEVENT_USE_URING
}
#endif
if (ioevent->events == NULL) {
close(ioevent->poll_fd);
ioevent->poll_fd = -1;
return ENOMEM;
}
ioevent_set_timeout(ioevent, timeout_ms);
ioevent_set_timeout(ioevent, timeout_ms);
return 0;
return 0;
}
void ioevent_destroy(IOEventPoller *ioevent)
{
#if IOEVENT_USE_URING
if (ioevent->use_io_uring) {
io_uring_queue_exit(&ioevent->ring);
} else {
#endif
if (ioevent->events != NULL) {
free(ioevent->events);
ioevent->events = NULL;
}
if (ioevent->events != NULL) {
free(ioevent->events);
ioevent->events = NULL;
}
if (ioevent->poll_fd >= 0) {
close(ioevent->poll_fd);
ioevent->poll_fd = -1;
}
#if IOEVENT_USE_URING
}
#endif
if (ioevent->poll_fd >= 0) {
close(ioevent->poll_fd);
ioevent->poll_fd = -1;
}
}
int ioevent_attach(IOEventPoller *ioevent, const int fd,
const int e, void *data)
int ioevent_attach(IOEventPoller *ioevent, const int fd, const int e,
void *data)
{
#ifdef OS_LINUX
#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_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
#if IOEVENT_USE_EPOLL
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);
#elif IOEVENT_USE_KQUEUE
struct kevent ev[2];
int n = 0;
@ -176,32 +128,15 @@ int ioevent_attach(IOEventPoller *ioevent, const int fd,
#endif
}
int ioevent_modify(IOEventPoller *ioevent, const int fd,
const int e, void *data)
int ioevent_modify(IOEventPoller *ioevent, const int fd, const int e,
void *data)
{
#ifdef OS_LINUX
#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_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
#if IOEVENT_USE_EPOLL
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);
#elif IOEVENT_USE_KQUEUE
struct kevent ev[2];
int result;
@ -236,25 +171,8 @@ int ioevent_modify(IOEventPoller *ioevent, const int fd,
int ioevent_detach(IOEventPoller *ioevent, const int fd)
{
#ifdef OS_LINUX
#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
#if IOEVENT_USE_EPOLL
return epoll_ctl(ioevent->poll_fd, EPOLL_CTL_DEL, fd, NULL);
#elif IOEVENT_USE_KQUEUE
struct kevent ev[1];
int r, w;
@ -273,33 +191,15 @@ int ioevent_detach(IOEventPoller *ioevent, const int fd)
int ioevent_poll(IOEventPoller *ioevent)
{
#ifdef OS_LINUX
#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
#if IOEVENT_USE_EPOLL
return epoll_wait(ioevent->poll_fd, ioevent->events, ioevent->size, ioevent->timeout);
#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
int result;
int retval;
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)
{
result = (int)nget;
@ -325,3 +225,4 @@ int ioevent_poll(IOEventPoller *ioevent)
#error port me
#endif
}

View File

@ -20,28 +20,17 @@
#include <poll.h>
#include <sys/time.h>
#include "_os_define.h"
#include "logger.h"
#define IOEVENT_TIMEOUT (1 << 20)
#define IOEVENT_NOTIFY (1 << 21) //for io_uring send_zc done callback
#ifdef OS_LINUX
#include <sys/epoll.h>
#define IOEVENT_EDGE_TRIGGER EPOLLET
#endif
#define IOEVENT_TIMEOUT 0x8000
#if IOEVENT_USE_EPOLL
#include <sys/epoll.h>
#define IOEVENT_EDGE_TRIGGER EPOLLET
#define IOEVENT_READ EPOLLIN
#define IOEVENT_WRITE EPOLLOUT
#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
#include <sys/event.h>
#include <sys/poll.h>
@ -76,33 +65,18 @@ int kqueue_ev_convert(int16_t event, uint16_t flags);
#endif
typedef struct ioevent_puller {
const char *service_name;
int size; //max events (fd)
int extra_events;
#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 {
int index;
int count;
} iterator; //for deal event loop
#ifdef OS_LINUX
#if IOEVENT_USE_EPOLL
struct epoll_event *events;
int timeout_ms; //for epoll
#if IOEVENT_USE_URING
struct io_uring_cqe *cqe;
struct __kernel_timespec timeout;
#endif
bool zero_timeout;
int timeout;
#elif IOEVENT_USE_KQUEUE
struct kevent *events;
struct timespec timeout;
@ -110,10 +84,9 @@ typedef struct ioevent_puller {
port_event_t *events;
timespec_t timeout;
#endif
} IOEventPoller;
#if OS_LINUX
#if IOEVENT_USE_EPOLL
#define IOEVENT_GET_EVENTS(ioevent, index) \
(ioevent)->events[index].events
#elif IOEVENT_USE_KQUEUE
@ -126,7 +99,7 @@ typedef struct ioevent_puller {
#error port me
#endif
#ifdef OS_LINUX
#if IOEVENT_USE_EPOLL
#define IOEVENT_GET_DATA(ioevent, index) \
(ioevent)->events[index].data.ptr
#elif IOEVENT_USE_KQUEUE
@ -139,7 +112,7 @@ typedef struct ioevent_puller {
#error port me
#endif
#ifdef OS_LINUX
#if IOEVENT_USE_EPOLL
#define IOEVENT_CLEAR_DATA(ioevent, index) \
(ioevent)->events[index].data.ptr = NULL
#elif IOEVENT_USE_KQUEUE
@ -156,39 +129,24 @@ typedef struct ioevent_puller {
extern "C" {
#endif
int ioevent_init(IOEventPoller *ioevent, const char *service_name,
const bool use_io_uring, const int size, const int timeout_ms,
const int extra_events);
int ioevent_init(IOEventPoller *ioevent, const int size,
const int timeout_ms, const int extra_events);
void ioevent_destroy(IOEventPoller *ioevent);
int ioevent_attach(IOEventPoller *ioevent, const int fd,
const int e, void *data);
int ioevent_modify(IOEventPoller *ioevent, const int fd,
const int e, void *data);
int ioevent_attach(IOEventPoller *ioevent, const int fd, const int e,
void *data);
int ioevent_modify(IOEventPoller *ioevent, const int fd, const int e,
void *data);
int ioevent_detach(IOEventPoller *ioevent, const int fd);
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
ioevent->timeout_ms = timeout_ms;
ioevent->timeout = timeout_ms;
#else
#if IOEVENT_USE_URING
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);
ioevent->timeout.tv_sec = timeout_ms / 1000;
ioevent->timeout.tv_nsec = 1000000 * (timeout_ms % 1000);
#endif
}
@ -198,114 +156,6 @@ static inline int ioevent_poll_ex(IOEventPoller *ioevent, const int timeout_ms)
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
}
#endif

View File

@ -17,76 +17,6 @@
#include "logger.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)
{
int event;
@ -109,25 +39,35 @@ static void deal_ioevents(IOEventPoller *ioevent)
}
}
static int ioevent_process_by_poll(IOEventPoller *ioevent)
int ioevent_remove(IOEventPoller *ioevent, void *data)
{
int result;
IOEventEntry *pEntry;
int index;
ioevent->iterator.count = ioevent_poll(ioevent);
if (ioevent->iterator.count > 0) {
deal_ioevents(ioevent);
if (ioevent->iterator.index >= ioevent->iterator.count)
{
return ENOENT;
}
else if (ioevent->iterator.count < 0) {
result = errno != 0 ? errno : EINVAL;
if (result != EINTR) {
logError("file: "__FILE__", line: %d, "
"ioevent_poll fail, errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
pEntry = (IOEventEntry *)IOEVENT_GET_DATA(ioevent,
ioevent->iterator.index);
if (pEntry != NULL && (void *)pEntry == data) {
return 0; //do NOT clear current entry
}
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 0;
return ENOENT;
}
static void deal_timeouts(FastTimerEntry *head)
@ -142,14 +82,16 @@ static void deal_timeouts(FastTimerEntry *head)
current = entry;
entry = entry->next;
/* must set NULL because NOT in time wheel */
current->prev = current->next = NULL;
current->prev = current->next = NULL; //must set NULL because NOT in time wheel
pEventEntry = (IOEventEntry *)current;
pEventEntry->callback(pEventEntry->fd, IOEVENT_TIMEOUT, current);
if (pEventEntry != NULL)
{
pEventEntry->callback(pEventEntry->fd, IOEVENT_TIMEOUT, current);
}
}
}
int ioevent_loop(struct nio_thread_data *thread_data,
int ioevent_loop(struct nio_thread_data *pThreadData,
IOEventCallback recv_notify_callback, TaskCleanUpCallback
clean_up_callback, volatile bool *continue_flag)
{
@ -158,133 +100,90 @@ int ioevent_loop(struct nio_thread_data *thread_data,
FastTimerEntry head;
struct fast_task_info *task;
time_t last_check_time;
int save_extra_events;
int count;
#ifdef OS_LINUX
uint32_t sched_counter;
#endif
bool sched_pull;
memset(&ev_notify, 0, sizeof(ev_notify));
ev_notify.event.fd = FC_NOTIFY_READ_FD(thread_data);
ev_notify.event.fd = FC_NOTIFY_READ_FD(pThreadData);
ev_notify.event.callback = recv_notify_callback;
ev_notify.thread_data = thread_data;
save_extra_events = thread_data->ev_puller.extra_events;
thread_data->ev_puller.extra_events = 0; //disable edge trigger temporarily
if (ioevent_attach(&thread_data->ev_puller, ev_notify.
event.fd, IOEVENT_READ, &ev_notify) != 0)
ev_notify.thread_data = pThreadData;
if (ioevent_attach(&pThreadData->ev_puller,
pThreadData->pipe_fds[0], IOEVENT_READ,
&ev_notify) != 0)
{
result = errno != 0 ? errno : ENOMEM;
logCrit("file: "__FILE__", line: %d, "
"ioevent_attach fail, errno: %d, error info: %s",
logCrit("file: "__FILE__", line: %d, " \
"ioevent_attach fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
thread_data->ev_puller.extra_events = save_extra_events; //restore
#ifdef OS_LINUX
sched_counter = 0;
#endif
thread_data->deleted_list = NULL;
pThreadData->deleted_list = NULL;
last_check_time = g_current_time;
while (*continue_flag) {
#ifdef OS_LINUX
if (thread_data->ev_puller.zero_timeout) {
sched_pull = (sched_counter++ & 8) != 0;
} else {
sched_pull = true;
}
#else
sched_pull = true;
#endif
while (*continue_flag)
{
pThreadData->ev_puller.iterator.count = ioevent_poll(
&pThreadData->ev_puller);
if (pThreadData->ev_puller.iterator.count > 0)
{
deal_ioevents(&pThreadData->ev_puller);
}
else if (pThreadData->ev_puller.iterator.count < 0)
{
result = errno != 0 ? errno : EINVAL;
if (result != EINTR)
{
logError("file: "__FILE__", line: %d, " \
"ioevent_poll fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
}
#if IOEVENT_USE_URING
if (thread_data->ev_puller.use_io_uring) {
if (thread_data->ev_puller.submit_count > 0) {
if ((result=ioevent_uring_submit(&thread_data->
ev_puller)) != 0)
{
logError("file: "__FILE__", line: %d, "
"io_uring_submit fail, errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
}
}
#endif
if (pThreadData->deleted_list != NULL)
{
count = 0;
while (pThreadData->deleted_list != NULL)
{
task = pThreadData->deleted_list;
pThreadData->deleted_list = task->next;
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);
}
if (thread_data->deleted_list != NULL) {
//count = 0;
while (thread_data->deleted_list != NULL) {
task = thread_data->deleted_list;
thread_data->deleted_list = task->next;
if (task->polling.in_queue) {
fc_list_del_init(&task->polling.dlink);
task->polling.in_queue = false;
if (fc_list_empty(&task->thread_data->polling_queue)) {
ioevent_set_timeout(&task->thread_data->ev_puller,
task->thread_data->timeout_ms);
}
}
clean_up_callback(task);
//count++;
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;
count = fast_timer_timeouts_get(
&thread_data->timer, g_current_time, &head);
&pThreadData->timer, g_current_time, &head);
if (count > 0)
{
deal_timeouts(&head);
}
}
if (thread_data->notify.enabled) {
if (pThreadData->notify.enabled)
{
int64_t n;
if ((n=__sync_fetch_and_add(&thread_data->notify.counter, 0)) != 0)
if ((n=__sync_fetch_and_add(&pThreadData->notify.counter, 0)) != 0)
{
__sync_fetch_and_sub(&thread_data->notify.counter, n);
__sync_fetch_and_sub(&pThreadData->notify.counter, n);
/*
logInfo("file: "__FILE__", line: %d, "
"n ==== %"PRId64", now: %"PRId64,
__LINE__, n, __sync_fetch_and_add(
&thread_data->notify.counter, 0));
&pThreadData->notify.counter, 0));
*/
}
}
if (thread_data->thread_loop_callback != NULL) {
thread_data->thread_loop_callback(thread_data);
if (pThreadData->thread_loop_callback != NULL)
{
pThreadData->thread_loop_callback(pThreadData);
}
}
@ -292,64 +191,25 @@ int ioevent_loop(struct nio_thread_data *thread_data,
}
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;
task->thread_data = pThread;
task->event.fd = sock;
task->event.callback = callback;
#if IOEVENT_USE_URING
if (pThread->ev_puller.use_io_uring) {
if (FC_URING_OP_TYPE(task) == IORING_OP_NOP) {
if ((result=uring_prep_first_recv(task)) != 0) {
logError("file: "__FILE__", line: %d, "
"uring_prep_recv fail, fd: %d, "
"errno: %d, error info: %s",
__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
if (ioevent_attach(&pThread->ev_puller,
sock, event, task) < 0)
{
result = errno != 0 ? errno : ENOENT;
logError("file: "__FILE__", line: %d, " \
"ioevent_attach fail, " \
"errno: %d, error info: %s", \
__LINE__, result, STRERROR(result));
return result;
}
task->event.timer.expires = g_current_time + timeout;
fast_timer_add(&pThread->timer, &task->event.timer);
return 0;
}
int ioevent_reset(struct fast_task_info *task, int new_fd, short event)
{
if (task->event.fd == new_fd)
{
return 0;
}
if (task->event.fd >= 0)
{
ioevent_detach(&task->thread_data->ev_puller, task->event.fd);
}
task->event.fd = new_fd;
return ioevent_attach(&task->thread_data->ev_puller, new_fd, event, task);
}

View File

@ -17,28 +17,20 @@
#define _IOEVENT_LOOP_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
extern "C" {
#endif
int ioevent_loop(struct nio_thread_data *thread_data,
int ioevent_loop(struct nio_thread_data *pThreadData,
IOEventCallback recv_notify_callback, TaskCleanUpCallback
clean_up_callback, volatile bool *continue_flag);
int ioevent_set(struct fast_task_info *task, struct nio_thread_data *pThread,
int sock, short event, IOEventCallback callback,
const int timeout);
//remove entry from ready list
int ioevent_remove(IOEventPoller *ioevent, void *data);
int ioevent_reset(struct fast_task_info *task, int new_fd, short event);
int ioevent_set(struct fast_task_info *pTask, struct nio_thread_data *pThread,
int sock, short event, IOEventCallback callback, const int timeout);
static inline bool ioevent_is_canceled(struct fast_task_info *task)
{
@ -81,170 +73,9 @@ static inline int ioevent_notify_thread(struct nio_thread_data *thread_data)
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
}
#endif
#endif

View File

@ -29,7 +29,7 @@
(ch >= '0' && ch <= '9') || (ch == '_' || ch == '-' || \
ch == '.'))
int fc_detect_json_type(const string_t *input)
int detect_json_type(const string_t *input)
{
if (input->len < 2) {
return FC_JSON_TYPE_STRING;
@ -45,9 +45,18 @@ int fc_detect_json_type(const string_t *input)
return FC_JSON_TYPE_STRING;
}
typedef struct {
const char *str; //input string
const char *p; //current
const char *end;
string_t element;
char *error_info;
int error_size;
} ParseContext;
static void set_parse_error(const char *str, const char *current,
const int expect_len, const char *front,
string_t *error_info, const int error_size)
char *error_info, const int error_size)
{
const char *show_str;
int show_len;
@ -57,18 +66,26 @@ static void set_parse_error(const char *str, const char *current,
show_len = expect_len;
}
show_str = current - show_len;
error_info->len = snprintf(error_info->str, error_size,
"%s, input: %.*s", front, show_len, show_str);
snprintf(error_info, error_size, "%s, input: %.*s",
front, show_len, show_str);
}
static int json_escape_string(fc_json_context_t *context,
const string_t *input, char *output)
static int json_escape_string(const string_t *input, string_t *output,
char *error_info, const int error_size)
{
const char *src;
const char *end;
char *dest;
int size;
dest = output;
size = 2 * input->len + 1;
output->str = (char *)fc_malloc(size);
if (output->str == NULL) {
snprintf(error_info, error_size, "malloc %d bytes fail", size);
return ENOMEM;
}
dest = output->str;
end = input->str + input->len;
for (src=input->str; src<end; src++) {
switch (*src) {
@ -92,21 +109,13 @@ static int json_escape_string(fc_json_context_t *context,
*dest++ = '\\';
*dest++ = 'b';
break;
case '\f':
*dest++ = '\\';
*dest++ = 'f';
break;
case '\"':
*dest++ = '\\';
*dest++ = '\"';
break;
case '\0':
case '\'':
*dest++ = '\\';
*dest++ = 'u';
*dest++ = '0';
*dest++ = '0';
*dest++ = '0';
*dest++ = '0';
*dest++ = '\'';
break;
default:
*dest++ = *src;
@ -114,19 +123,18 @@ static int json_escape_string(fc_json_context_t *context,
}
}
return dest - output;
*dest = '\0';
output->len = dest - output->str;
return 0;
}
static int next_json_element(fc_json_context_t *context)
static int next_json_element(ParseContext *context)
{
char *dest;
const char *start;
char buff[128];
char quote_ch;
int unicode;
int i;
dest = context->decode.element.str;
dest = context->element.str;
quote_ch = *context->p;
if (quote_ch == '\"' || quote_ch == '\'') {
context->p++;
@ -135,42 +143,9 @@ static int next_json_element(fc_json_context_t *context)
if (++context->p == context->end) {
set_parse_error(context->str, context->p,
EXPECT_STR_LEN, "expect a character after \\",
&context->error_info, context->error_size);
context->error_info, context->error_size);
return EINVAL;
}
if (*context->p == 'u') { //unicode
start = ++context->p; //skip charator 'u'
i = 0;
while (i < 4 && context->p < context->end &&
IS_HEX_CHAR(*context->p))
{
buff[i++] = *context->p;
++context->p;
}
if (i != 4) {
set_parse_error(context->str, start,
EXPECT_STR_LEN, "expect 4 hex characters "
"after \\u", &context->error_info,
context->error_size);
return EINVAL;
}
buff[i] = '\0';
unicode = strtol(buff, NULL, 16);
if (unicode < 0x80) {
*dest++ = unicode;
} else if (unicode < 0x800) {
*dest++ = 0xC0 | ((unicode >> 6) & 0x1F);
*dest++ = 0x80 | (unicode & 0x3F);
} else {
*dest++ = 0xE0 | ((unicode >> 12) & 0x0F);
*dest++ = 0x80 | ((unicode >> 6) & 0x3F);
*dest++ = 0x80 | (unicode & 0x3F);
}
continue;
}
switch (*context->p) {
case '\\':
*dest++ = '\\';
@ -187,21 +162,20 @@ static int next_json_element(fc_json_context_t *context)
case 'n':
*dest++ = '\n';
break;
case 'f':
*dest++ = '\f';
break;
case 'b':
*dest++ = '\b';
*dest++ = '\f';
break;
case '"':
*dest++ = '\"';
break;
case '\'':
*dest++ = '\'';
break;
default:
sprintf(buff, "invalid escaped character: %c(0x%x)",
*context->p, (unsigned char)*context->p);
set_parse_error(context->str, context->p + 1,
EXPECT_STR_LEN, buff, &context->error_info,
context->error_size);
set_parse_error(context->str, context->p + 1, EXPECT_STR_LEN,
buff, context->error_info, context->error_size);
return EINVAL;
}
context->p++;
@ -213,7 +187,7 @@ static int next_json_element(fc_json_context_t *context)
if (context->p == context->end) {
sprintf(buff, "expect closed character: %c", quote_ch);
set_parse_error(context->str, context->p, EXPECT_STR_LEN,
buff, &context->error_info, context->error_size);
buff, context->error_info, context->error_size);
return EINVAL;
}
context->p++; //skip quote char
@ -224,12 +198,12 @@ static int next_json_element(fc_json_context_t *context)
}
*dest = '\0';
context->decode.element.len = dest - context->decode.element.str;
context->element.len = dest - context->element.str;
return 0;
}
static int check_alloc_array(fc_json_context_t *context,
fc_common_array_t *array)
static int check_alloc_array(common_array_t *array,
char *error_info, const int error_size)
{
int bytes;
if (array->count < array->alloc) {
@ -245,320 +219,344 @@ static int check_alloc_array(fc_json_context_t *context,
bytes = array->element_size * array->alloc;
array->elements = fc_realloc(array->elements, bytes);
if (array->elements == NULL) {
context->error_info.len = snprintf(context->error_info.str,
context->error_size, "realloc %d bytes fail", bytes);
snprintf(error_info, error_size, "realloc %d bytes fail", bytes);
return ENOMEM;
}
return 0;
}
static int prepare_json_parse(fc_json_context_t *context,
const string_t *input, const char lquote,
const char rquote)
static inline int check_alloc_json_array(json_array_t *array,
char *error_info, const int error_size)
{
int expect_size;
int result;
return check_alloc_array((common_array_t *)array, error_info, error_size);
}
static inline int check_alloc_json_map(json_map_t *array,
char *error_info, const int error_size)
{
return check_alloc_array((common_array_t *)array, error_info, error_size);
}
static int prepare_json_parse(const string_t *input, common_array_t *array,
char *error_info, const int error_size,
const char lquote, const char rquote, ParseContext *context)
{
int buff_len;
array->elements = NULL;
array->count = array->alloc = 0;
array->buff = NULL;
if (input->len < 2) {
context->error_info.len = snprintf(context->error_info.str,
context->error_size, "json string is too short");
snprintf(error_info, error_size, "json string is too short");
return EINVAL;
}
if (input->str[0] != lquote) {
context->error_info.len = snprintf(context->error_info.str, context->
error_size, "json array must start with \"%c\"", lquote);
snprintf(error_info, error_size,
"json array must start with \"%c\"", lquote);
return EINVAL;
}
if (input->str[input->len - 1] != rquote) {
context->error_info.len = snprintf(context->error_info.str, context->
error_size, "json array must end with \"%c\"", rquote);
snprintf(error_info, error_size,
"json array must end with \"%c\"", rquote);
return EINVAL;
}
expect_size = input->len;
if (context->output.alloc_size < expect_size) {
if ((result=fc_realloc_buffer(&context->output, context->
init_buff_size, expect_size)) != 0)
{
context->error_info.len = snprintf(context->error_info.str,
context->error_size, "realloc buffer fail");
return result;
}
buff_len = input->len - 2;
array->buff = (char *)fc_malloc(buff_len + 1);
if (array->buff == NULL) {
snprintf(error_info, error_size,
"malloc %d bytes fail", buff_len + 1);
return ENOMEM;
}
context->decode.element.str = context->output.buff;
context->decode.element.len = 0;
context->error_info = error_info;
context->error_size = error_size;
context->element.str = array->buff;
context->element.len = 0;
context->str = input->str;
context->p = input->str + 1;
context->end = input->str + input->len - 1;
return 0;
}
static inline void json_quote_string(fc_json_context_t
*context, const string_t *input, char **buff)
int decode_json_array(const string_t *input, json_array_t *array,
char *error_info, const int error_size)
{
ParseContext context;
int result;
array->element_size = sizeof(string_t);
if ((result=prepare_json_parse(input, (common_array_t *)array,
error_info, error_size, '[', ']', &context)) != 0)
{
return result;
}
result = 0;
while (context.p < context.end) {
while (context.p < context.end && JSON_SPACE(*context.p)) {
context.p++;
}
if (context.p == context.end) {
break;
}
if (*context.p == ',') {
set_parse_error(input->str, context.p + 1,
EXPECT_STR_LEN, "unexpect comma \",\"",
error_info, error_size);
result = EINVAL;
break;
}
if ((result=next_json_element(&context)) != 0) {
break;
}
while (context.p < context.end && JSON_SPACE(*context.p)) {
context.p++;
}
if (context.p < context.end) {
if (*context.p == ',') {
context.p++; //skip comma
} else {
set_parse_error(input->str, context.p,
EXPECT_STR_LEN, "expect comma \",\"",
error_info, error_size);
result = EINVAL;
break;
}
}
if ((result=check_alloc_json_array(array, error_info, error_size)) != 0) {
array->count = 0;
break;
}
array->elements[array->count++] = context.element;
context.element.str += context.element.len + 1;
}
if (result != 0) {
free_json_array(array);
}
return result;
}
void free_common_array(common_array_t *array)
{
if (array->elements != NULL) {
free(array->elements);
array->elements = NULL;
array->count = 0;
}
if (array->buff != NULL) {
free(array->buff);
array->buff = NULL;
}
}
static int json_quote_string(const string_t *input, char **buff,
char *error_info, const int error_size)
{
int result;
string_t escaped;
char *p;
if ((result=json_escape_string(input, &escaped,
error_info, error_size)) != 0)
{
return result;
}
p = *buff;
*p++ = '"';
p += json_escape_string(context, input, p);
memcpy(p, escaped.str, escaped.len);
p += escaped.len;
*p++ = '"';
*buff = p;
free(escaped.str);
return 0;
}
int fc_encode_json_array_ex(fc_json_context_t *context,
const string_t *elements, const int count,
BufferInfo *buffer)
int encode_json_array(json_array_t *array, string_t *output,
char *error_info, const int error_size)
{
const string_t *el;
const string_t *end;
string_t *el;
string_t *end;
char *p;
int expect_size;
int result;
int size;
expect_size = 3;
end = elements + count;
for (el=elements; el<end; el++) {
expect_size += 6 * el->len + 3;
end = array->elements + array->count;
size = 3;
for (el=array->elements; el<end; el++) {
size += 2 * el->len + 3;
}
if (buffer->alloc_size < expect_size) {
if ((context->error_no=fc_realloc_buffer(buffer, context->
init_buff_size, expect_size)) != 0)
{
context->error_info.len = snprintf(context->error_info.str,
context->error_size, "realloc buffer fail");
return context->error_no;
}
output->str = (char *)fc_malloc(size);
if (output->str == NULL) {
snprintf(error_info, error_size, "malloc %d bytes fail", size);
return ENOMEM;
}
p = buffer->buff;
p = output->str;
*p++ = '[';
for (el=elements; el<end; el++) {
if (el > elements) {
for (el=array->elements; el<end; el++) {
if (el > array->elements) {
*p++ = ',';
}
json_quote_string(context, el, &p);
if ((result=json_quote_string(el, &p, error_info, error_size)) != 0) {
free_json_string(output);
return result;
}
}
*p++ = ']';
*p = '\0';
buffer->length = p - buffer->buff;
output->len = p - output->str;
return 0;
}
int fc_encode_json_map_ex(fc_json_context_t *context,
const key_value_pair_t *elements, const int count,
BufferInfo *buffer)
int decode_json_map(const string_t *input, json_map_t *map,
char *error_info, const int error_size)
{
const key_value_pair_t *pair;
const key_value_pair_t *end;
char *p;
int expect_size;
ParseContext context;
key_value_pair_t kv_pair;
int result;
expect_size = 3;
end = elements + count;
for (pair=elements; pair<end; pair++) {
expect_size += 6 * (pair->key.len + pair->value.len) + 5;
map->element_size = sizeof(key_value_pair_t);
if ((result=prepare_json_parse(input, (common_array_t *)map,
error_info, error_size, '{', '}', &context)) != 0)
{
return result;
}
if (buffer->alloc_size < expect_size) {
if ((context->error_no=fc_realloc_buffer(buffer, context->
init_buff_size, expect_size)) != 0)
{
context->error_info.len = snprintf(context->error_info.str,
context->error_size, "realloc buffer fail");
return context->error_no;
result = 0;
while (context.p < context.end) {
while (context.p < context.end && JSON_SPACE(*context.p)) {
context.p++;
}
if (context.p == context.end) {
break;
}
if (*context.p == ',') {
set_parse_error(input->str, context.p + 1,
EXPECT_STR_LEN, "unexpect comma \",\"",
error_info, error_size);
result = EINVAL;
break;
}
if ((result=next_json_element(&context)) != 0) {
break;
}
while (context.p < context.end && JSON_SPACE(*context.p)) {
context.p++;
}
if (!(context.p < context.end && *context.p == ':')) {
set_parse_error(input->str, context.p,
EXPECT_STR_LEN, "expect colon \":\"",
error_info, error_size);
result = EINVAL;
break;
}
context.p++; //skip colon
kv_pair.key = context.element;
context.element.str += context.element.len + 1;
while (context.p < context.end && JSON_SPACE(*context.p)) {
context.p++;
}
if ((result=next_json_element(&context)) != 0) {
break;
}
while (context.p < context.end && JSON_SPACE(*context.p)) {
context.p++;
}
if (context.p < context.end) {
if (*context.p == ',') {
context.p++; //skip comma
} else {
set_parse_error(input->str, context.p,
EXPECT_STR_LEN, "expect comma \",\"",
error_info, error_size);
result = EINVAL;
break;
}
}
kv_pair.value = context.element;
context.element.str += context.element.len + 1;
if ((result=check_alloc_json_map(map, error_info, error_size)) != 0) {
map->count = 0;
break;
}
map->elements[map->count++] = kv_pair;
}
p = buffer->buff;
if (result != 0) {
free_json_map(map);
}
return result;
}
int encode_json_map(json_map_t *map, string_t *output,
char *error_info, const int error_size)
{
key_value_pair_t *pair;
key_value_pair_t *end;
char *p;
int result;
int size;
end = map->elements + map->count;
size = 3;
for (pair=map->elements; pair<end; pair++) {
size += 2 * (pair->key.len + pair->value.len + 2) + 1;
}
output->str = (char *)fc_malloc(size);
if (output->str == NULL) {
snprintf(error_info, error_size, "malloc %d bytes fail", size);
return ENOMEM;
}
p = output->str;
*p++ = '{';
for (pair=elements; pair<end; pair++) {
if (pair > elements) {
for (pair=map->elements; pair<end; pair++) {
if (pair > map->elements) {
*p++ = ',';
}
json_quote_string(context, &pair->key, &p);
if ((result=json_quote_string(&pair->key, &p,
error_info, error_size)) != 0)
{
free_json_string(output);
return result;
}
*p++ = ':';
json_quote_string(context, &pair->value, &p);
if ((result=json_quote_string(&pair->value, &p,
error_info, error_size)) != 0)
{
free_json_string(output);
return result;
}
}
*p++ = '}';
*p = '\0';
buffer->length = p - buffer->buff;
output->len = p - output->str;
return 0;
}
#define JSON_DECODE_COPY_STRING(ctx, input, dest, src) \
do { \
if ((context->error_no=fast_mpool_alloc_string_ex2( \
&ctx->decode.mpool, dest, src)) != 0) \
{ \
set_parse_error(input->str, ctx->p, EXPECT_STR_LEN, \
"out of memory", &ctx->error_info, ctx->error_size); \
return NULL; \
} \
} while (0)
const fc_json_array_t *fc_decode_json_array(fc_json_context_t
*context, const string_t *input)
{
if ((context->error_no=prepare_json_parse(context,
input, '[', ']')) != 0)
{
return NULL;
}
context->jarray.count = 0;
while (context->p < context->end) {
while (context->p < context->end && JSON_SPACE(*context->p)) {
context->p++;
}
if (context->p == context->end) {
break;
}
if (*context->p == ',') {
set_parse_error(input->str, context->p + 1,
EXPECT_STR_LEN, "unexpect comma \",\"",
&context->error_info, context->error_size);
context->error_no = EINVAL;
return NULL;
}
if ((context->error_no=next_json_element(context)) != 0) {
return NULL;
}
while (context->p < context->end && JSON_SPACE(*context->p)) {
context->p++;
}
if (context->p < context->end) {
if (*context->p == ',') {
context->p++; //skip comma
} else {
set_parse_error(input->str, context->p,
EXPECT_STR_LEN, "expect comma \",\"",
&context->error_info, context->error_size);
context->error_no = EINVAL;
return NULL;
}
}
if ((context->error_no=check_alloc_array(context,
(fc_common_array_t *)
&context->jarray)) != 0)
{
return NULL;
}
if (context->decode.use_mpool) {
JSON_DECODE_COPY_STRING(context, input, context->jarray.elements +
context->jarray.count++, &context->decode.element);
} else {
context->jarray.elements[context->jarray.count++] =
context->decode.element;
}
context->decode.element.str += context->decode.element.len + 1;
}
return &context->jarray;
}
const fc_json_map_t *fc_decode_json_map(fc_json_context_t
*context, const string_t *input)
{
key_value_pair_t kv_pair;
if ((context->error_no=prepare_json_parse(context,
input, '{', '}')) != 0)
{
return NULL;
}
context->jmap.count = 0;
while (context->p < context->end) {
while (context->p < context->end && JSON_SPACE(*context->p)) {
context->p++;
}
if (context->p == context->end) {
break;
}
if (*context->p == ',') {
set_parse_error(input->str, context->p + 1,
EXPECT_STR_LEN, "unexpect comma \",\"",
&context->error_info, context->error_size);
context->error_no = EINVAL;
return NULL;
}
if ((context->error_no=next_json_element(context)) != 0) {
return NULL;
}
while (context->p < context->end && JSON_SPACE(*context->p)) {
context->p++;
}
if (!(context->p < context->end && *context->p == ':')) {
set_parse_error(input->str, context->p,
EXPECT_STR_LEN, "expect colon \":\"",
&context->error_info, context->error_size);
context->error_no = EINVAL;
return NULL;
}
context->p++; //skip colon
kv_pair.key = context->decode.element;
context->decode.element.str += context->decode.element.len + 1;
while (context->p < context->end && JSON_SPACE(*context->p)) {
context->p++;
}
if ((context->error_no=next_json_element(context)) != 0) {
return NULL;
}
while (context->p < context->end && JSON_SPACE(*context->p)) {
context->p++;
}
if (context->p < context->end) {
if (*context->p == ',') {
context->p++; //skip comma
} else {
set_parse_error(input->str, context->p,
EXPECT_STR_LEN, "expect comma \",\"",
&context->error_info, context->error_size);
context->error_no = EINVAL;
return NULL;
}
}
kv_pair.value = context->decode.element;
context->decode.element.str += context->decode.element.len + 1;
if ((context->error_no=check_alloc_array(context,
(fc_common_array_t *)
&context->jmap)) != 0)
{
return NULL;
}
if (context->decode.use_mpool) {
key_value_pair_t *dest;
dest = context->jmap.elements + context->jmap.count++;
JSON_DECODE_COPY_STRING(context, input,
&dest->key, &kv_pair.key);
JSON_DECODE_COPY_STRING(context, input,
&dest->value, &kv_pair.value);
} else {
context->jmap.elements[context->jmap.count++] = kv_pair;
}
}
return &context->jmap;
}

View File

@ -15,16 +15,14 @@
//json_parser.h
#ifndef _FC_JSON_PARSER_H
#define _FC_JSON_PARSER_H
#ifndef _JSON_PARSER_H
#define _JSON_PARSER_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "common_define.h"
#include "shared_func.h"
#include "fast_mpool.h"
#define FC_JSON_TYPE_STRING 1
#define FC_JSON_TYPE_ARRAY 2
@ -38,200 +36,55 @@
/* for internal use */ \
int element_size; \
int alloc; \
char *buff; \
} ARRAY_TYPE
DEFINE_ARRAY_STRUCT(void, fc_common_array_t);
DEFINE_ARRAY_STRUCT(string_t, fc_json_array_t);
DEFINE_ARRAY_STRUCT(key_value_pair_t, fc_json_map_t);
typedef struct {
BufferInfo output; //for json encode/decode
struct {
struct fast_mpool_man mpool;
string_t element; //string allocator use output buffer
bool use_mpool;
} decode;
int init_buff_size;
int error_no;
int error_size;
char error_holder[256];
string_t error_info;
fc_json_array_t jarray;
fc_json_map_t jmap;
/* for internal use */
const char *str; //input string
const char *p; //current
const char *end;
} fc_json_context_t;
DEFINE_ARRAY_STRUCT(void, common_array_t);
DEFINE_ARRAY_STRUCT(string_t, json_array_t);
DEFINE_ARRAY_STRUCT(key_value_pair_t, json_map_t);
#ifdef __cplusplus
extern "C" {
#endif
static inline void fc_init_common_array(fc_common_array_t *array,
const int element_size)
void free_common_array(common_array_t *array);
static inline void free_json_array(json_array_t *array)
{
array->elements = NULL;
array->element_size = element_size;
array->count = array->alloc = 0;
free_common_array((common_array_t *)array);
}
static inline void fc_init_json_array(fc_json_array_t *array)
static inline void free_json_map(json_map_t *array)
{
fc_init_common_array((fc_common_array_t *)array, sizeof(string_t));
free_common_array((common_array_t *)array);
}
static inline void fc_init_json_map(fc_json_map_t *array)
static inline void free_json_string(string_t *buffer)
{
fc_init_common_array((fc_common_array_t *)array,
sizeof(key_value_pair_t));
}
static inline void fc_free_common_array(fc_common_array_t *array)
{
if (array->elements != NULL) {
free(array->elements);
array->elements = NULL;
array->count = array->alloc = 0;
if (buffer->str != NULL) {
free(buffer->str);
buffer->str = NULL;
buffer->len = 0;
}
}
static inline void fc_free_json_array(fc_json_array_t *array)
{
fc_free_common_array((fc_common_array_t *)array);
}
int detect_json_type(const string_t *input);
static inline void fc_free_json_map(fc_json_map_t *array)
{
fc_free_common_array((fc_common_array_t *)array);
}
int decode_json_array(const string_t *input, json_array_t *array,
char *error_info, const int error_size);
static inline void fc_set_json_error_buffer(fc_json_context_t *ctx,
char *error_info, const int error_size)
{
if (error_info != NULL && error_size > 0) {
ctx->error_info.str = error_info;
ctx->error_size = error_size;
} else {
ctx->error_info.str = ctx->error_holder;
ctx->error_size = sizeof(ctx->error_holder);
}
int encode_json_array(json_array_t *array, string_t *output,
char *error_info, const int error_size);
ctx->error_info.len = 0;
*ctx->error_info.str = '\0';
}
int decode_json_map(const string_t *input, json_map_t *map,
char *error_info, const int error_size);
static inline int fc_init_json_context_ex(fc_json_context_t *ctx,
const bool decode_use_mpool, const int alloc_size_once,
const int init_buff_size, char *error_info,
const int error_size)
{
const int discard_size = 0;
ctx->output.buff = NULL;
ctx->output.alloc_size = ctx->output.length = 0;
FC_SET_STRING_NULL(ctx->decode.element);
if (init_buff_size > 0) {
ctx->init_buff_size = init_buff_size;
} else {
ctx->init_buff_size = 1024;
}
fc_init_json_array(&ctx->jarray);
fc_init_json_map(&ctx->jmap);
ctx->error_no = 0;
fc_set_json_error_buffer(ctx, error_info, error_size);
ctx->decode.use_mpool = decode_use_mpool;
if (decode_use_mpool) {
return fast_mpool_init(&ctx->decode.mpool,
alloc_size_once, discard_size);
} else {
return 0;
}
}
static inline int fc_init_json_context(fc_json_context_t *ctx)
{
const bool decode_use_mpool = false;
const int alloc_size_once = 0;
const int init_buff_size = 0;
return fc_init_json_context_ex(ctx, decode_use_mpool,
alloc_size_once, init_buff_size, NULL, 0);
}
static inline void fc_reset_json_context(fc_json_context_t *ctx)
{
if (ctx->decode.use_mpool) {
fast_mpool_reset(&ctx->decode.mpool);
}
}
static inline void fc_destroy_json_context(fc_json_context_t *ctx)
{
fc_free_buffer(&ctx->output);
fc_free_json_array(&ctx->jarray);
fc_free_json_map(&ctx->jmap);
if (ctx->decode.use_mpool) {
fast_mpool_destroy(&ctx->decode.mpool);
}
}
static inline int fc_json_parser_get_error_no(fc_json_context_t *ctx)
{
return ctx->error_no;
}
static inline const string_t *fc_json_parser_get_error_info(
fc_json_context_t *ctx)
{
return &ctx->error_info;
}
int fc_detect_json_type(const string_t *input);
int fc_encode_json_array_ex(fc_json_context_t *context,
const string_t *elements, const int count,
BufferInfo *buffer);
int fc_encode_json_map_ex(fc_json_context_t *context,
const key_value_pair_t *elements, const int count,
BufferInfo *buffer);
static inline const BufferInfo *fc_encode_json_array(fc_json_context_t
*context, const string_t *elements, const int count)
{
if (fc_encode_json_array_ex(context, elements, count,
&context->output) == 0)
{
return &context->output;
} else {
return NULL;
}
}
static inline const BufferInfo *fc_encode_json_map(fc_json_context_t
*context, const key_value_pair_t *elements, const int count)
{
if (fc_encode_json_map_ex(context, elements, count,
&context->output) == 0)
{
return &context->output;
} else {
return NULL;
}
}
const fc_json_array_t *fc_decode_json_array(fc_json_context_t
*context, const string_t *input);
const fc_json_map_t *fc_decode_json_map(fc_json_context_t
*context, const string_t *input);
int encode_json_map(json_map_t *map, string_t *output,
char *error_info, const int error_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -31,7 +31,7 @@ bool is_local_host_ip(const char *client_ip)
char *p;
char *pEnd;
pEnd = g_local_host_ip_addrs +
pEnd = g_local_host_ip_addrs + \
IP_ADDRESS_SIZE * g_local_host_ip_count;
for (p=g_local_host_ip_addrs; p<pEnd; p+=IP_ADDRESS_SIZE)
{
@ -56,8 +56,9 @@ int insert_into_local_host_ip(const char *client_ip)
return -1;
}
strcpy(g_local_host_ip_addrs + IP_ADDRESS_SIZE *
g_local_host_ip_count, client_ip);
strcpy(g_local_host_ip_addrs + \
IP_ADDRESS_SIZE * g_local_host_ip_count, \
client_ip);
g_local_host_ip_count++;
return 1;
}
@ -82,7 +83,7 @@ const char *local_host_ip_addrs_to_string(char *buff, const int size)
void log_local_host_ip_addrs()
{
char buff[1024];
char buff[512];
logInfo("%s", local_host_ip_addrs_to_string(buff, sizeof(buff)));
}
@ -95,7 +96,7 @@ void load_local_host_ip_addrs()
char *if_alias_prefixes[STORAGE_MAX_ALIAS_PREFIX_COUNT];
int alias_count;
insert_into_local_host_ip(LOCAL_LOOPBACK_IPv4);
insert_into_local_host_ip(LOCAL_LOOPBACK_IP);
memset(if_alias_prefixes, 0, sizeof(if_alias_prefixes));
if (*g_if_alias_prefix == '\0')
@ -159,8 +160,8 @@ const char *get_next_local_ip(const char *previous_ip)
pEnd = g_local_host_ip_addrs + \
IP_ADDRESS_SIZE * g_local_host_ip_count;
for (p=g_local_host_ip_addrs; p<pEnd; p+=IP_ADDRESS_SIZE)
{
if (!is_loopback_ip(p))
{
if (strcmp(p, LOCAL_LOOPBACK_IP) != 0)
{
if (found)
{
@ -171,7 +172,7 @@ const char *get_next_local_ip(const char *previous_ip)
found = true;
}
}
}
}
return NULL;
}
@ -186,10 +187,7 @@ const char *get_first_local_ip()
}
else
{
/* 注意当系统存在IPv6回环地址时为了简化系统的改动
IPv6IPv4
*/
return LOCAL_LOOPBACK_IPv4;
return LOCAL_LOOPBACK_IP;
}
}
@ -214,17 +212,3 @@ const char *get_first_local_private_ip()
return NULL;
}
void stat_local_host_ip(int *ipv4_count, int *ipv6_count)
{
const char *ip_addr;
*ipv4_count = *ipv6_count = 0;
ip_addr = NULL;
while ((ip_addr=get_next_local_ip(ip_addr)) != NULL) {
if (is_ipv6_addr(ip_addr)) {
++(*ipv6_count);
} else {
++(*ipv4_count);
}
}
}

View File

@ -25,32 +25,22 @@
#include "common_define.h"
#define FAST_IF_ALIAS_PREFIX_MAX_SIZE 32
#define FAST_MAX_LOCAL_IP_ADDRS 32
#define FAST_MAX_LOCAL_IP_ADDRS 16
#define LOCAL_LOOPBACK_IPv4 "127.0.0.1"
#define LOCAL_LOOPBACK_IPv6 "::1"
#define LOCAL_LOOPBACK_IP "127.0.0.1"
#ifdef __cplusplus
extern "C" {
#endif
extern int g_local_host_ip_count;
extern char g_local_host_ip_addrs[FAST_MAX_LOCAL_IP_ADDRS *
extern char g_local_host_ip_addrs[FAST_MAX_LOCAL_IP_ADDRS * \
IP_ADDRESS_SIZE];
extern char g_if_alias_prefix[FAST_IF_ALIAS_PREFIX_MAX_SIZE];
void load_local_host_ip_addrs();
bool is_local_host_ip(const char *client_ip);
static inline bool is_loopback_ip(const char *ip_addr)
{
return (strcmp(ip_addr, LOCAL_LOOPBACK_IPv4) == 0 ||
strcmp(ip_addr, LOCAL_LOOPBACK_IPv6) == 0 ||
strcasecmp(ip_addr, "fe80::1") == 0);
}
void stat_local_host_ip(int *ipv4_count, int *ipv6_count);
const char *get_first_local_ip();
const char *get_next_local_ip(const char *previous_ip);

View File

@ -13,9 +13,6 @@ typedef struct fc_locked_list {
extern "C" {
#endif
#define LOCKED_LIST_LOCK(list) PTHREAD_MUTEX_LOCK(&(list)->lock)
#define LOCKED_LIST_UNLOCK(list) PTHREAD_MUTEX_UNLOCK(&(list)->lock)
static inline int locked_list_init(FCLockedList *list)
{
int result;
@ -27,11 +24,6 @@ extern "C" {
return 0;
}
static inline void locked_list_destroy(FCLockedList *list)
{
pthread_mutex_destroy(&list->lock);
}
static inline void locked_list_add(struct fc_list_head *_new,
FCLockedList *list)
{
@ -48,22 +40,6 @@ extern "C" {
PTHREAD_MUTEX_UNLOCK(&list->lock);
}
static inline void locked_list_move(struct fc_list_head *obj,
FCLockedList *list)
{
PTHREAD_MUTEX_LOCK(&list->lock);
fc_list_move(obj, &list->head);
PTHREAD_MUTEX_UNLOCK(&list->lock);
}
static inline void locked_list_move_tail(struct fc_list_head *obj,
FCLockedList *list)
{
PTHREAD_MUTEX_LOCK(&list->lock);
fc_list_move_tail(obj, &list->head);
PTHREAD_MUTEX_UNLOCK(&list->lock);
}
static inline void locked_list_del(struct fc_list_head *old,
FCLockedList *list)
{
@ -72,15 +48,6 @@ extern "C" {
PTHREAD_MUTEX_UNLOCK(&list->lock);
}
static inline int locked_list_empty(FCLockedList *list)
{
int empty;
PTHREAD_MUTEX_LOCK(&list->lock);
empty = fc_list_empty(&list->head);
PTHREAD_MUTEX_UNLOCK(&list->lock);
return empty;
}
static inline int locked_list_count(FCLockedList *list)
{
int count;
@ -90,24 +57,6 @@ extern "C" {
return count;
}
#define locked_list_first_entry(list, type, member, var) \
PTHREAD_MUTEX_LOCK(&(list)->lock); \
var = fc_list_first_entry(&(list)->head, type, member); \
PTHREAD_MUTEX_UNLOCK(&(list)->lock)
#define locked_list_last_entry(list, type, member, var) \
PTHREAD_MUTEX_LOCK(&(list)->lock); \
var = fc_list_last_entry(&(list)->head, type, member); \
PTHREAD_MUTEX_UNLOCK(&(list)->lock)
#define locked_list_pop(list, type, member, var) \
PTHREAD_MUTEX_LOCK(&(list)->lock); \
var = fc_list_first_entry(&(list)->head, type, member); \
if (var != NULL) { \
fc_list_del_init(&var->member); \
} \
PTHREAD_MUTEX_UNLOCK(&(list)->lock)
#ifdef __cplusplus
}
#endif

View File

@ -50,21 +50,21 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock);
static int check_and_mk_log_dir(const char *base_path)
{
char log_path[MAX_PATH_SIZE];
char data_path[MAX_PATH_SIZE];
fc_combine_full_filename(base_path, "logs", log_path);
if (!fileExists(log_path))
{
if (mkdir(log_path, 0755) != 0)
{
fprintf(stderr, "mkdir \"%s\" fail, "
"errno: %d, error info: %s\n",
log_path, errno, STRERROR(errno));
return errno != 0 ? errno : EPERM;
}
}
snprintf(data_path, sizeof(data_path), "%s/logs", base_path);
if (!fileExists(data_path))
{
if (mkdir(data_path, 0755) != 0)
{
fprintf(stderr, "mkdir \"%s\" fail, " \
"errno: %d, error info: %s\n", \
data_path, errno, STRERROR(errno));
return errno != 0 ? errno : EPERM;
}
}
return 0;
return 0;
}
int log_init()
@ -112,7 +112,7 @@ int log_init_ex(LogContext *pContext)
}
pContext->pcurrent_buff = pContext->log_buff;
if ((result=init_pthread_lock(&(pContext->lock))) != 0)
if ((result=init_pthread_lock(&(pContext->log_thread_lock))) != 0)
{
return result;
}
@ -136,8 +136,8 @@ static int log_print_header(LogContext *pContext)
if (pContext->current_size < 0)
{
result = errno != 0 ? errno : EACCES;
fprintf(stderr, "lseek file \"%s\" fail, "
"errno: %d, error info: %s\n",
fprintf(stderr, "lseek file \"%s\" fail, " \
"errno: %d, error info: %s\n", \
pContext->log_filename, result, STRERROR(result));
}
else {
@ -158,8 +158,8 @@ static int log_print_header(LogContext *pContext)
static int log_open(LogContext *pContext)
{
int result;
if ((pContext->log_fd = open(pContext->log_filename, O_WRONLY | O_CREAT |
O_APPEND | O_CLOEXEC | pContext->fd_flags, 0644)) < 0)
if ((pContext->log_fd = open(pContext->log_filename, O_WRONLY | \
O_CREAT | O_APPEND | pContext->fd_flags, 0644)) < 0)
{
fprintf(stderr, "open log file \"%s\" to write fail, " \
"errno: %d, error info: %s\n", \
@ -222,44 +222,31 @@ int log_reopen_ex(LogContext *pContext)
return log_open(pContext);
}
int log_set_prefix_ex(LogContext *pContext, const char *base_path,
int log_set_prefix_ex(LogContext *pContext, const char *base_path, \
const char *filename_prefix)
{
int result;
char log_filename[MAX_PATH_SIZE];
int result;
if ((result=check_and_mk_log_dir(base_path)) != 0)
{
return result;
}
if ((result=check_and_mk_log_dir(base_path)) != 0)
{
return result;
}
snprintf(log_filename, MAX_PATH_SIZE, "%s/logs/%s.log",
base_path, filename_prefix);
return log_set_filename_ex(pContext, log_filename);
snprintf(pContext->log_filename, MAX_PATH_SIZE, "%s/logs/%s.log", \
base_path, filename_prefix);
return log_open(pContext);
}
int log_set_filename_ex(LogContext *pContext, const char *log_filename)
{
if (log_filename == NULL || *log_filename == '\0')
{
fprintf(stderr, "file: "__FILE__", line: %d, "
"log_filename is NULL or empty!\n", __LINE__);
if (log_filename == NULL) {
fprintf(stderr, "file: "__FILE__", line: %d, " \
"log_filename is NULL!\n", __LINE__);
return EINVAL;
}
if (*(pContext->log_filename) == '\0')
{
fc_strlcpy(pContext->log_filename, log_filename, MAX_PATH_SIZE);
return log_open(pContext);
}
if (strcmp(log_filename, pContext->log_filename) == 0)
{
return 0;
}
fc_strlcpy(pContext->log_filename, log_filename, MAX_PATH_SIZE);
return log_reopen_ex(pContext);
snprintf(pContext->log_filename, MAX_PATH_SIZE, "%s", log_filename);
return log_open(pContext);
}
void log_set_cache_ex(LogContext *pContext, const bool bLogCache)
@ -296,9 +283,9 @@ void log_set_header_callback(LogContext *pContext, LogHeaderCallback header_call
{
int64_t current_size;
pthread_mutex_lock(&(pContext->lock));
pthread_mutex_lock(&(pContext->log_thread_lock));
current_size = pContext->current_size;
pthread_mutex_unlock(&(pContext->lock));
pthread_mutex_unlock(&(pContext->log_thread_lock));
if (current_size == 0)
{
log_print_header(pContext);
@ -347,7 +334,7 @@ void log_destroy_ex(LogContext *pContext)
close(pContext->log_fd);
pContext->log_fd = STDERR_FILENO;
pthread_mutex_destroy(&pContext->lock);
pthread_mutex_destroy(&pContext->log_thread_lock);
}
if (pContext->log_buff != NULL)
@ -385,11 +372,12 @@ static int log_delete_old_file(LogContext *pContext,
char full_filename[MAX_PATH_SIZE + 128];
if (NEED_COMPRESS_LOG(pContext->compress_log_flags))
{
fc_concat_two_strings(old_filename, GZIP_EXT_NAME_STR, full_filename);
snprintf(full_filename, sizeof(full_filename), "%s%s",
old_filename, GZIP_EXT_NAME_STR);
}
else
{
fc_safe_strcpy(full_filename, old_filename);
snprintf(full_filename, sizeof(full_filename), "%s", old_filename);
}
if (unlink(full_filename) != 0)
@ -589,9 +577,7 @@ static int log_get_matched_files(LogContext *pContext,
the_time = get_current_time() - days_before * 86400;
localtime_r(&the_time, &tm);
memset(filename_prefix, 0, sizeof(filename_prefix));
len = strlen(log_filename);
memcpy(filename_prefix, log_filename, len);
*(filename_prefix + len++) = '.';
len = sprintf(filename_prefix, "%s.", log_filename);
strftime(filename_prefix + len, sizeof(filename_prefix) - len,
rotate_time_format_prefix, &tm);
prefix_filename_len = strlen(filename_prefix);
@ -652,8 +638,8 @@ static int log_delete_matched_old_files(LogContext *pContext,
log_get_file_path(pContext, log_filepath);
for (i=0; i<filename_array.count; i++)
{
fc_concat_two_strings(log_filepath, filename_array.
filenames[i], full_filename);
snprintf(full_filename, sizeof(full_filename), "%s%s",
log_filepath, filename_array.filenames[i]);
if (unlink(full_filename) != 0)
{
if (errno != ENOENT)
@ -704,9 +690,7 @@ int log_delete_old_files(void *args)
the_time -= 86400;
localtime_r(&the_time, &tm);
memset(old_filename, 0, sizeof(old_filename));
len = strlen(pContext->log_filename);
memcpy(old_filename, pContext->log_filename, len);
*(old_filename + len++) = '.';
len = sprintf(old_filename, "%s.", pContext->log_filename);
strftime(old_filename + len, sizeof(old_filename) - len,
pContext->rotate_time_format, &tm);
if ((result=log_delete_old_file(pContext, old_filename)) != 0)
@ -736,7 +720,6 @@ static void *log_gzip_func(void *args)
char log_filepath[MAX_PATH_SIZE];
char full_filename[MAX_PATH_SIZE + 32];
char output[512];
const char *gzip_cmd_filename;
int prefix_len;
int result;
int i;
@ -764,10 +747,11 @@ static void *log_gzip_func(void *args)
continue;
}
gzip_cmd_filename = get_gzip_command_filename();
fc_concat_two_strings(log_filepath, filename_array.
filenames[i], full_filename);
fc_combine_two_strings(gzip_cmd_filename, full_filename, ' ', cmd);
snprintf(full_filename, sizeof(full_filename), "%s%s",
log_filepath, filename_array.filenames[i]);
snprintf(cmd, sizeof(cmd), "%s %s",
get_gzip_command_filename(), full_filename);
result = getExecResult(cmd, output, sizeof(output));
if (result != 0)
{
@ -846,9 +830,7 @@ int log_rotate(LogContext *pContext)
localtime_r(&current_time, &tm);
memset(old_filename, 0, sizeof(old_filename));
len = strlen(pContext->log_filename);
memcpy(old_filename, pContext->log_filename, len);
*(old_filename + len++) = '.';
len = sprintf(old_filename, "%s.", pContext->log_filename);
strftime(old_filename + len, sizeof(old_filename) - len,
pContext->rotate_time_format, &tm);
if (access(old_filename, F_OK) == 0)
@ -918,19 +900,19 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
{
if (bNeedLock)
{
pthread_mutex_lock(&(pContext->lock));
pthread_mutex_lock(&(pContext->log_thread_lock));
}
result = log_check_rotate(pContext);
if (bNeedLock)
{
pthread_mutex_unlock(&(pContext->lock));
pthread_mutex_unlock(&(pContext->log_thread_lock));
}
return result;
}
}
if (bNeedLock && ((lock_res=pthread_mutex_lock( \
&(pContext->lock))) != 0))
&(pContext->log_thread_lock))) != 0))
{
fprintf(stderr, "file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
@ -955,10 +937,10 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
if (written != write_bytes)
{
result = errno != 0 ? errno : EIO;
fprintf(stderr, "file: "__FILE__", line: %d, "
"pid: %d, call write fail, fd: %d, errno: %d, error info: %s\n",
__LINE__, getpid(), pContext->log_fd, result, STRERROR(result));
}
fprintf(stderr, "file: "__FILE__", line: %d, " \
"call write fail, errno: %d, error info: %s\n",\
__LINE__, result, STRERROR(result));
}
if (pContext->rotate_immediately)
{
@ -966,7 +948,7 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
}
if (bNeedLock && ((lock_res=pthread_mutex_unlock( \
&(pContext->lock))) != 0))
&(pContext->log_thread_lock))) != 0))
{
fprintf(stderr, "file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
@ -977,8 +959,8 @@ static int log_fsync(LogContext *pContext, const bool bNeedLock)
return result;
}
void log_it_ex3(LogContext *pContext, struct timeval *tv,
const char *caption, const char *text, const int text_len,
static void doLogEx(LogContext *pContext, struct timeval *tv, \
const char *caption, const char *text, const int text_len, \
const bool bNeedSync, const bool bNeedLock)
{
struct tm tm;
@ -1003,7 +985,7 @@ void log_it_ex3(LogContext *pContext, struct timeval *tv,
}
}
if (bNeedLock && (result=pthread_mutex_lock(&pContext->lock)) != 0)
if (bNeedLock && (result=pthread_mutex_lock(&pContext->log_thread_lock)) != 0)
{
fprintf(stderr, "file: "__FILE__", line: %d, " \
"call pthread_mutex_lock fail, " \
@ -1018,12 +1000,12 @@ void log_it_ex3(LogContext *pContext, struct timeval *tv,
__LINE__, LOG_BUFF_SIZE, text_len + 64);
if (bNeedLock)
{
pthread_mutex_unlock(&(pContext->lock));
pthread_mutex_unlock(&(pContext->log_thread_lock));
}
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_fsync(pContext, false);
@ -1050,14 +1032,10 @@ void log_it_ex3(LogContext *pContext, struct timeval *tv,
}
if (caption != NULL)
{
buff_len = strlen(caption);
memcpy(pContext->pcurrent_buff, caption, buff_len);
pContext->pcurrent_buff += buff_len;
*pContext->pcurrent_buff++ = ' ';
*pContext->pcurrent_buff++ = '-';
*pContext->pcurrent_buff++ = ' ';
}
{
buff_len = sprintf(pContext->pcurrent_buff, "%s - ", caption);
pContext->pcurrent_buff += buff_len;
}
memcpy(pContext->pcurrent_buff, text, text_len);
pContext->pcurrent_buff += text_len;
*pContext->pcurrent_buff++ = '\n';
@ -1067,7 +1045,7 @@ void log_it_ex3(LogContext *pContext, struct timeval *tv,
log_fsync(pContext, false);
}
if (bNeedLock && (result=pthread_mutex_unlock(&(pContext->lock))) != 0)
if (bNeedLock && (result=pthread_mutex_unlock(&(pContext->log_thread_lock))) != 0)
{
fprintf(stderr, "file: "__FILE__", line: %d, " \
"call pthread_mutex_unlock fail, " \
@ -1076,8 +1054,8 @@ void log_it_ex3(LogContext *pContext, struct timeval *tv,
}
}
void log_it_ex2(LogContext *pContext, const char *caption,
const char *text, const int text_len,
void log_it_ex2(LogContext *pContext, const char *caption, \
const char *text, const int text_len, \
const bool bNeedSync, const bool bNeedLock)
{
struct timeval tv;
@ -1092,10 +1070,10 @@ void log_it_ex2(LogContext *pContext, const char *caption,
gettimeofday(&tv, NULL);
}
log_it_ex3(pContext, &tv, caption, text, text_len, bNeedSync, bNeedLock);
doLogEx(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)
{
bool bNeedSync;
@ -1291,12 +1269,45 @@ void logAccess(LogContext *pContext, struct timeval *tvStart, \
{
len = sizeof(text) - 1;
}
log_it_ex3(pContext, tvStart, NULL, text, len, false, true);
doLogEx(pContext, tvStart, NULL, text, len, false, true);
}
const char *log_get_level_caption_ex(LogContext *pContext)
{
return get_log_level_caption(pContext->log_level);
const char *caption;
switch (pContext->log_level)
{
case LOG_DEBUG:
caption = "DEBUG";
break;
case LOG_INFO:
caption = "INFO";
break;
case LOG_NOTICE:
caption = "NOTICE";
break;
case LOG_WARNING:
caption = "WARNING";
break;
case LOG_ERR:
caption = "ERROR";
break;
case LOG_CRIT:
caption = "CRIT";
break;
case LOG_ALERT:
caption = "ALERT";
break;
case LOG_EMERG:
caption = "EMERG";
break;
default:
caption = "UNKOWN";
break;
}
return caption;
}
#ifndef LOG_FORMAT_CHECK

View File

@ -62,7 +62,7 @@ typedef struct log_context
char *pcurrent_buff;
/* mutext lock */
pthread_mutex_t lock;
pthread_mutex_t log_thread_lock;
/*
rotate the log when the log file exceeds this parameter
@ -145,7 +145,6 @@ static inline int log_try_init()
*/
int log_init2();
#define log_reopen() log_reopen_ex(&g_log_context)
#define log_set_prefix(base_path, filename_prefix) \
@ -201,7 +200,7 @@ int log_reopen_ex(LogContext *pContext);
* filename_prefix: log filename prefix
* return: 0 for success, != 0 fail
*/
int log_set_prefix_ex(LogContext *pContext, const char *base_path,
int log_set_prefix_ex(LogContext *pContext, const char *base_path, \
const char *filename_prefix);
/** set log filename
@ -274,24 +273,6 @@ void log_take_over_stderr_ex(LogContext *pContext);
*/
void log_take_over_stdout_ex(LogContext *pContext);
/** init function using global log context
* do nothing when already inited
* return: 0 for success, != 0 fail
*/
static inline int log_try_init2()
{
int result;
if ((result=log_try_init()) != 0)
{
return result;
}
log_take_over_stderr();
log_take_over_stdout();
return 0;
}
/** set compress_log_flags to true
* parameters:
* pContext: the log context
@ -343,7 +324,7 @@ void log_it_ex(LogContext *pContext, const int priority, \
* text_len: text string length (bytes)
* 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);
/** log to file
@ -355,13 +336,10 @@ void log_it_ex1(LogContext *pContext, const int priority,
* bNeedSync: if sync to file immediatelly
* return: none
*/
void log_it_ex2(LogContext *pContext, const char *caption,
const char *text, const int text_len,
void log_it_ex2(LogContext *pContext, const char *caption, \
const char *text, const int text_len, \
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
* parameters:

View File

@ -311,7 +311,7 @@ MD5_memset(POINTER output, int value, unsigned int len)
/*
* Digests a string
*/
int my_md5_string(char *string, unsigned char digest[16])
int my_md5_string(char *string,unsigned char digest[16])
{
MD5_CTX context;
unsigned int len = strlen(string);
@ -332,22 +332,25 @@ int my_md5_buffer(char *buffer, unsigned int len, unsigned char digest[16])
return 0;
}
int my_md5_file(char *filename, unsigned char digest[16])
int my_md5_file(char *filename,unsigned char digest[16])
{
FILE *file;
MD5_CTX context;
int len;
unsigned char buff[16 * 1024];
unsigned char buffer[1024];
if ((file = fopen(filename, "rb")) == NULL) {
if ((file = fopen(filename, "rb")) == NULL)
return -1;
}
else {
my_md5_init(&context);
while ((len = fread(buffer, 1, 1024, file)) > 0)
{
my_md5_update(&context, buffer, len);
}
my_md5_final(digest, &context);
my_md5_init(&context);
while ((len = fread(buff, 1, sizeof(buff), file)) > 0) {
my_md5_update(&context, buff, len);
}
my_md5_final(digest, &context);
fclose(file);
return 0;
fclose(file);
}
return 0;
}

View File

@ -41,12 +41,12 @@ int my_md5_file(char *filename, unsigned char digest[16]);
*/
int my_md5_buffer(char *buffer, unsigned int len, unsigned char digest[16]);
void my_md5_init(MD5_CTX *context);
void my_md5_init (MD5_CTX *context);
void my_md5_update(MD5_CTX *context, unsigned char *input,
void my_md5_update (MD5_CTX *context, unsigned char *input,
unsigned int inputLen);
void my_md5_final(unsigned char digest[16], MD5_CTX *context);
void my_md5_final (unsigned char digest[16], MD5_CTX *context);
#ifdef __cplusplus
}

View File

@ -46,7 +46,6 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
fms_client_get_current_time_ms_func get_current_time_ms_func,
const int init_recv_buffer_size, const int timeout_ms)
{
const bool use_io_uring = false;
int result;
int new_init_recv_buffer_size;
int i;
@ -66,8 +65,8 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
return EINVAL;
}
if ((result=ioevent_init(&client->ioevent, "client",
use_io_uring, entry_count, timeout_ms, 0)) != 0)
if ((result=ioevent_init(&client->ioevent, entry_count,
timeout_ms, 0)) != 0)
{
logError("file: "__FILE__", line: %d, "
"ioevent_init fail, errno: %d, error info: %s",
@ -86,7 +85,7 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
}
for (i=0; i<entry_count; i++) {
if ((result=fast_buffer_init1(&entries[i].recv_buffer,
if ((result=fast_buffer_init_ex(&entries[i].recv_buffer,
new_init_recv_buffer_size)) != 0)
{
return result;
@ -129,7 +128,6 @@ static int fast_multi_sock_client_do_send(FastMultiSockClient *client,
{
int bytes;
int result;
char formatted_ip[FORMATTED_IP_SIZE];
result = 0;
while (entry->remain > 0) {
@ -141,26 +139,27 @@ static int fast_multi_sock_client_do_send(FastMultiSockClient *client,
break;
} else if (errno == EINTR) { //should retry
logDebug("file: "__FILE__", line: %d, "
"server: %s:%u, ignore interupt signal", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
"server: %s:%u, ignore interupt signal",
__LINE__, entry->conn->ip_addr,
entry->conn->port);
continue;
} else {
result = errno != 0 ? errno : ECONNRESET;
logError("file: "__FILE__", line: %d, "
"send to server %s:%u fail, "
"errno: %d, error info: %s", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, result, strerror(result));
"errno: %d, error info: %s",
__LINE__, entry->conn->ip_addr,
entry->conn->port,
result, strerror(result));
break;
}
} else if (bytes == 0) {
logError("file: "__FILE__", line: %d, "
"send to server %s:%u, sock: %d fail, "
"connection disconnected", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, entry->conn->sock);
"connection disconnected",
__LINE__, entry->conn->ip_addr, entry->conn->port,
entry->conn->sock);
result = ECONNRESET;
break;
@ -191,7 +190,6 @@ static int fast_multi_sock_client_send_data(FastMultiSockClient *client,
{
int i;
int result;
char formatted_ip[FORMATTED_IP_SIZE];
for (i=0; i<client->entry_count; i++) {
client->entries[i].remain = send_buffer->length;
@ -204,9 +202,9 @@ static int fast_multi_sock_client_send_data(FastMultiSockClient *client,
client->entries[i].error_no = ENOTCONN;
client->entries[i].done = true;
logError("file: "__FILE__", line: %d, "
"NOT connected to %s:%u", __LINE__,
format_ip_address(client->entries[i].conn->ip_addr,
formatted_ip), client->entries[i].conn->port);
"NOT connected to %s:%u",
__LINE__, client->entries[i].conn->ip_addr,
client->entries[i].conn->port);
continue;
}
@ -246,7 +244,6 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
{
int bytes;
int result;
char formatted_ip[FORMATTED_IP_SIZE];
result = 0;
while (entry->remain > 0) {
@ -257,26 +254,27 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
break;
} else if (errno == EINTR) { //should retry
logDebug("file: "__FILE__", line: %d, "
"server: %s:%u, ignore interupt signal", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
"server: %s:%u, ignore interupt signal",
__LINE__, entry->conn->ip_addr,
entry->conn->port);
continue;
} else {
result = errno != 0 ? errno : ECONNRESET;
logError("file: "__FILE__", line: %d, "
"server: %s:%u, recv failed, "
"errno: %d, error info: %s", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, result, strerror(result));
"errno: %d, error info: %s",
__LINE__, entry->conn->ip_addr,
entry->conn->port,
result, strerror(result));
break;
}
} else if (bytes == 0) {
logError("file: "__FILE__", line: %d, "
"server: %s:%u, sock: %d, recv failed, "
"connection disconnected", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
entry->conn->port, entry->conn->sock);
"connection disconnected",
__LINE__, entry->conn->ip_addr, entry->conn->port,
entry->conn->sock);
result = ECONNRESET;
break;
@ -291,8 +289,8 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
body_length = client->get_body_length_func(&entry->recv_buffer);
if (body_length < 0) {
logError("file: "__FILE__", line: %d, "
"server: %s:%u, body_length: %d < 0", __LINE__,
format_ip_address(entry->conn->ip_addr, formatted_ip),
"server: %s:%u, body_length: %d < 0",
__LINE__, entry->conn->ip_addr,
entry->conn->port, body_length);
result = EPIPE;
break;
@ -317,16 +315,11 @@ static int fast_multi_sock_client_do_recv(FastMultiSockClient *client,
static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
{
int result;
int count;
#if IOEVENT_USE_URING
unsigned head;
#else
int event;
int count;
int index;
#endif
int remain_timeout;
FastMultiSockEntry *entry;
char formatted_ip[FORMATTED_IP_SIZE];
while (client->pulling_count > 0) {
remain_timeout = client->deadline_time_ms -
@ -335,39 +328,8 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
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);
//logInfo("poll count: %d\n", count);
logInfo("poll count: %d\n", count);
for (index=0; index<count; index++) {
event = IOEVENT_GET_EVENTS(&client->ioevent, index);
entry = (FastMultiSockEntry *)IOEVENT_GET_DATA(
@ -375,22 +337,21 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
if (event & IOEVENT_ERROR) {
logError("file: "__FILE__", line: %d, "
"server: %s:%u, recv error event: %d, connection "
"reset", __LINE__, format_ip_address(entry->conn->
ip_addr, formatted_ip), entry->conn->port, event);
"server: %s:%u, recv error event: %d, "
"connection reset", __LINE__,
entry->conn->ip_addr, entry->conn->port, event);
fast_multi_sock_client_finish(client, entry, ECONNRESET);
continue;
}
//logInfo("sock: %d, event: %d", entry->conn->sock, event);
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);
}
}
#endif
}
/*
@ -405,9 +366,9 @@ static int fast_multi_sock_client_deal_io(FastMultiSockClient *client)
fast_multi_sock_client_finish(client,
client->entries + i, ETIMEDOUT);
logError("file: "__FILE__", line: %d, "
"recv from %s:%u timedout", __LINE__,
format_ip_address(client->entries[i].conn->ip_addr,
formatted_ip), client->entries[i].conn->port);
"recv from %s:%u timedout",
__LINE__, client->entries[i].conn->ip_addr,
client->entries[i].conn->port);
}
}
}

View File

@ -21,6 +21,7 @@
#include <net/if.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include "common_define.h"
#include "connection_pool.h"

View File

@ -34,22 +34,6 @@
#include <SAPI.h>
#include <php_ini.h>
#ifndef TSRMLS_DC
#define TSRMLS_DC
#endif
#ifndef TSRMLS_C
#define TSRMLS_C
#endif
#ifndef TSRMLS_CC
#define TSRMLS_CC
#endif
#ifndef TSRMLS_FETCH
#define TSRMLS_FETCH()
#endif
#if PHP_MAJOR_VERSION < 7
typedef int zend_size_t;
#define ZEND_RETURN_STRING(s, dup) RETURN_STRING(s, dup)

View File

@ -50,14 +50,14 @@ int write_to_pid_file(const char *pidFilename)
char buff[32];
int len;
len = fc_itoa(getpid(), buff);
len = sprintf(buff, "%d", (int)getpid());
return writeToFile(pidFilename, buff, len);
}
int delete_pid_file(const char *pidFilename)
{
int result;
pid_t pid = 0;
pid_t pid;
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
return result;
@ -112,16 +112,14 @@ static int do_stop(const char *pidFilename, const bool bShowError, pid_t *pid)
}
}
int process_stop_ex(const char *pidFilename,
const bool bShowError, bool *force)
int process_stop_ex(const char *pidFilename, const bool bShowError)
{
#define MAX_WAIT_COUNT 300
pid_t pid = 0;
pid_t pid;
int result;
int sig;
int i;
*force = false;
if ((result=do_stop(pidFilename, bShowError, &pid)) != 0) {
return result;
}
@ -133,15 +131,14 @@ int process_stop_ex(const char *pidFilename,
break;
}
fc_sleep_ms(100);
usleep(100 * 1000);
}
if (i == MAX_WAIT_COUNT) {
if (kill(pid, SIGKILL) == 0) {
fprintf(stderr, "waiting for pid [%d] exit timeout, "
"force kill!\n", (int)pid);
*force = true;
fc_sleep_ms(100);
usleep(100 * 1000);
}
}
@ -152,16 +149,12 @@ int process_stop_ex(const char *pidFilename,
int process_restart(const char *pidFilename)
{
const bool bShowError = false;
bool force;
int result;
result = process_stop_ex(pidFilename, bShowError, &force);
result = process_stop_ex(pidFilename, bShowError);
if (result == ENOENT || result == ESRCH) {
result = 0;
} else if (result == 0) {
if (force) {
sleep(1);
}
fprintf(stderr, "starting ...\n");
}
@ -199,7 +192,7 @@ static const char *get_exename_by_pid(const pid_t pid, char *buff,
int process_start(const char* pidFilename)
{
pid_t pid = 0;
pid_t pid;
int result;
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
@ -251,41 +244,40 @@ int process_start(const char* pidFilename)
}
}
int process_exist(const char *pidFilename, pid_t *pid)
int process_exist(const char *pidFilename)
{
pid_t pid;
int result;
if ((result=get_pid_from_file(pidFilename, pid)) != 0) {
if ((result=get_pid_from_file(pidFilename, &pid)) != 0) {
if (result == ENOENT) {
return result;
return false;
}
else {
fprintf(stderr, "get pid from file: %s fail, " \
"errno: %d, error info: %s\n",
pidFilename, result, strerror(result));
return result;
return true;
}
}
if (kill(*pid, 0) == 0) {
return 0;
if (kill(pid, 0) == 0) {
return true;
}
else if (errno == ENOENT || errno == ESRCH) {
return ENOENT;
return false;
}
else {
result = errno != 0 ? errno : EPERM;
fprintf(stderr, "kill pid: %d fail, errno: %d, error info: %s\n",
(int)*pid, result, strerror(result));
return result;
(int)pid, errno, strerror(errno));
return true;
}
}
int get_base_path_from_conf_file_ex(const char *filename, char *base_path,
const int path_size, const int noent_log_level)
int get_base_path_from_conf_file(const char *filename, char *base_path,
const int path_size)
{
char *pBasePath;
string_t path_string;
IniContext iniContext;
int result;
@ -302,7 +294,7 @@ int get_base_path_from_conf_file_ex(const char *filename, char *base_path,
do
{
pBasePath = iniGetStrValue(NULL, "base_path", &iniContext);
if (pBasePath == NULL || *pBasePath == '\0')
if (pBasePath == NULL)
{
logError("file: "__FILE__", line: %d, " \
"conf file \"%s\" must have item " \
@ -311,18 +303,16 @@ int get_base_path_from_conf_file_ex(const char *filename, char *base_path,
break;
}
FC_SET_STRING(path_string, pBasePath);
normalize_path(NULL, &path_string, base_path, path_size);
snprintf(base_path, path_size, "%s", pBasePath);
chopPath(base_path);
if (!fileExists(base_path))
{
result = errno != 0 ? errno : ENOENT;
log_it_ex(&g_log_context, noent_log_level,
"file: "__FILE__", line: %d, "
"\"%s\" can't be accessed, error info: %s",
__LINE__, base_path, STRERROR(result));
break;
}
{
logError("file: "__FILE__", line: %d, " \
"\"%s\" can't be accessed, error info: %s", \
__LINE__, base_path, STRERROR(errno));
result = errno != 0 ? errno : ENOENT;
break;
}
if (!isDir(base_path))
{
logError("file: "__FILE__", line: %d, " \
@ -339,9 +329,7 @@ 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 result;
pid_t pid;
const bool bShowError = true;
*stop = false;
if (action == NULL)
{
@ -351,24 +339,7 @@ int process_action(const char *pidFilename, const char *action, bool *stop)
if (strcmp(action, "stop") == 0)
{
*stop = true;
return process_stop(pidFilename);
}
else if (strcmp(action, "status") == 0)
{
*stop = true;
result = process_exist(pidFilename, &pid);
switch (result) {
case 0:
printf("Running, pid: %d\n", (int)pid);
break;
case ENOENT:
printf("NOT running\n");
break;
default:
printf("Unkown status\n");
break;
}
return result;
return process_stop_ex(pidFilename, bShowError);
}
else if (strcmp(action, "restart") == 0)
{

View File

@ -27,11 +27,8 @@
extern "C" {
#endif
int get_base_path_from_conf_file_ex(const char *filename, char *base_path,
const int path_size, const int noent_log_level);
#define get_base_path_from_conf_file(filename, base_path, path_size) \
get_base_path_from_conf_file_ex(filename, base_path, path_size, LOG_ERR)
int get_base_path_from_conf_file(const char *filename, char *base_path,
const int path_size);
int get_pid_from_file(const char *pidFilename, pid_t *pid);
@ -39,19 +36,13 @@ int write_to_pid_file(const char *pidFilename);
int delete_pid_file(const char *pidFilename);
int process_stop_ex(const char *pidFilename,
const bool bShowError, bool *force);
int process_stop_ex(const char *pidFilename, const bool bShowError);
static inline int process_stop(const char *pidFilename)
{
const bool bShowError = true;
bool force;
return process_stop_ex(pidFilename, bShowError, &force);
}
#define process_stop(pidFilename) process_stop_ex(pidFilename, true)
int process_restart(const char *pidFilename);
int process_exist(const char *pidFilename, pid_t *pid);
int process_exist(const char *pidFilename);
int process_action(const char *pidFilename, const char *action, bool *stop);

View File

@ -71,58 +71,6 @@ int init_pthread_lock(pthread_mutex_t *pthread_lock)
return 0;
}
int init_pthread_rwlock(pthread_rwlock_t *rwlock)
{
struct {
pthread_rwlockattr_t holder;
pthread_rwlockattr_t *ptr;
} attr;
int result;
#ifdef WITH_PTHREAD_RWLOCKATTR_SETKIND_NP
attr.ptr = &attr.holder;
if ((result=pthread_rwlockattr_init(attr.ptr)) != 0) {
logError("file: "__FILE__", line: %d, "
"call pthread_rwlockattr_init fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if ((result=pthread_rwlockattr_setkind_np(attr.ptr,
PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) != 0)
{
logError("file: "__FILE__", line: %d, "
"call pthread_rwlockattr_settype fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
#else
attr.ptr = NULL;
#endif
if ((result=pthread_rwlock_init(rwlock, attr.ptr)) != 0) {
logError("file: "__FILE__", line: %d, "
"call pthread_rwlock_init fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if (attr.ptr != NULL) {
if ((result=pthread_rwlockattr_destroy(attr.ptr)) != 0) {
logError("file: "__FILE__", line: %d, "
"call thread_rwlockattr_destroy fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
}
return 0;
}
int init_pthread_attr(pthread_attr_t *pattr, const int stack_size)
{
size_t old_stack_size;

View File

@ -32,7 +32,6 @@ extern "C" {
#endif
int init_pthread_lock(pthread_mutex_t *pthread_lock);
int init_pthread_rwlock(pthread_rwlock_t *rwlock);
int init_pthread_attr(pthread_attr_t *pattr, const int stack_size);
int init_pthread_lock_cond_pair(pthread_lock_cond_pair_t *lcp);
@ -64,45 +63,6 @@ void destroy_pthread_lock_cond_pair(pthread_lock_cond_pair_t *lcp);
} while (0)
#define PTHREAD_RWLOCK_WRLOCK(rwlock) \
do { \
int rwlock_res; \
if ((rwlock_res=pthread_rwlock_wrlock(rwlock)) != 0) \
{ \
logWarning("file: "__FILE__", line: %d, " \
"call pthread_rwlock_wrlock fail, " \
"errno: %d, error info: %s", \
__LINE__, rwlock_res, STRERROR(rwlock_res)); \
} \
} while (0)
#define PTHREAD_RWLOCK_RDLOCK(rwlock) \
do { \
int rwlock_res; \
if ((rwlock_res=pthread_rwlock_rdlock(rwlock)) != 0) \
{ \
logWarning("file: "__FILE__", line: %d, " \
"call pthread_rwlock_rdlock fail, " \
"errno: %d, error info: %s", \
__LINE__, rwlock_res, STRERROR(rwlock_res)); \
} \
} while (0)
#define PTHREAD_RWLOCK_UNLOCK(rwlock) \
do { \
int unlock_res; \
if ((unlock_res=pthread_rwlock_unlock(rwlock)) != 0) \
{ \
logWarning("file: "__FILE__", line: %d, " \
"call pthread_rwlock_unlock fail, " \
"errno: %d, error info: %s", \
__LINE__, unlock_res, STRERROR(unlock_res)); \
} \
} while (0)
#define lcp_timedwait_sec(lcp, timeout) \
fc_timedwait_sec(&(lcp)->lock, &(lcp)->cond, timeout)
@ -114,9 +74,9 @@ static inline void fc_timedwait_sec(pthread_mutex_t *lock,
{
struct timespec ts;
PTHREAD_MUTEX_LOCK(lock);
ts.tv_sec = get_current_time() + timeout;
ts.tv_nsec = 0;
PTHREAD_MUTEX_LOCK(lock);
pthread_cond_timedwait(cond, lock, &ts);
PTHREAD_MUTEX_UNLOCK(lock);
}
@ -128,9 +88,9 @@ static inline void fc_timedwait_ms(pthread_mutex_t *lock,
struct timespec ts;
expires_ms = get_current_time_ms() + timeout_ms;
PTHREAD_MUTEX_LOCK(lock);
ts.tv_sec = expires_ms / 1000;
ts.tv_nsec = (expires_ms % 1000) * (1000 * 1000);
PTHREAD_MUTEX_LOCK(lock);
pthread_cond_timedwait(cond, lock, &ts);
PTHREAD_MUTEX_UNLOCK(lock);
}

View File

@ -45,63 +45,16 @@ static int sched_cmp_by_next_call_time(const void *p1, const void *p2)
((ScheduleEntry *)p2)->next_call_time;
}
time_t sched_make_first_call_time(struct tm *tm_current,
const TimeInfo *time_base, const int interval)
{
int remain;
struct {
time_t time;
struct tm tm;
} base;
if (time_base->hour == TIME_NONE)
{
return g_current_time + interval;
}
if (tm_current->tm_hour > time_base->hour ||
(tm_current->tm_hour == time_base->hour
&& tm_current->tm_min >= time_base->minute))
{
base.tm = *tm_current;
}
else
{
base.time = g_current_time - 24 * 3600;
localtime_r(&base.time, &base.tm);
}
base.tm.tm_hour = time_base->hour;
base.tm.tm_min = time_base->minute;
if (time_base->second >= 0 && time_base->second <= 59)
{
base.tm.tm_sec = time_base->second;
}
else
{
base.tm.tm_sec = 0;
}
base.time = mktime(&base.tm);
remain = g_current_time - base.time;
if (remain > 0)
{
return g_current_time + interval - remain % interval;
}
else if (remain < 0)
{
return g_current_time + (-1 * remain) % interval;
}
else
{
return g_current_time;
}
}
static int sched_init_entries(ScheduleEntry *entries, const int count)
{
ScheduleEntry *pEntry;
ScheduleEntry *pEnd;
time_t time_base;
struct tm tm_current;
struct tm tm_base;
time_t current_time;
int remain;
int interval;
if (count < 0)
{
@ -115,8 +68,8 @@ static int sched_init_entries(ScheduleEntry *entries, const int count)
return 0;
}
g_current_time = time(NULL);
localtime_r((time_t *)&g_current_time, &tm_current);
current_time = time(NULL);
localtime_r((time_t *)&current_time, &tm_current);
pEnd = entries + count;
for (pEntry=entries; pEntry<pEnd; pEntry++)
{
@ -127,21 +80,65 @@ static int sched_init_entries(ScheduleEntry *entries, const int count)
if (pEntry->interval <= 0)
{
logError("file: "__FILE__", line: %d, "
"shedule id: %d, interval %d <= 0",
__LINE__, pEntry->id, pEntry->interval);
logError("file: "__FILE__", line: %d, " \
"shedule interval %d <= 0", \
__LINE__, pEntry->interval);
return EINVAL;
}
pEntry->next_call_time = sched_make_first_call_time(
&tm_current, &pEntry->time_base, pEntry->interval);
if (pEntry->time_base.hour == TIME_NONE)
{
pEntry->next_call_time = current_time +
pEntry->interval;
}
else
{
if (tm_current.tm_hour > pEntry->time_base.hour ||
(tm_current.tm_hour == pEntry->time_base.hour
&& tm_current.tm_min >= pEntry->time_base.minute))
{
tm_base = tm_current;
}
else
{
time_base = current_time - 24 * 3600;
localtime_r(&time_base, &tm_base);
}
tm_base.tm_hour = pEntry->time_base.hour;
tm_base.tm_min = pEntry->time_base.minute;
if (pEntry->time_base.second >= 0 && pEntry->time_base.second <= 59)
{
tm_base.tm_sec = pEntry->time_base.second;
}
else
{
tm_base.tm_sec = 0;
}
time_base = mktime(&tm_base);
remain = current_time - time_base;
if (remain > 0)
{
interval = pEntry->interval - remain % pEntry->interval;
}
else if (remain < 0)
{
interval = (-1 * remain) % pEntry->interval;
}
else
{
interval = 0;
}
pEntry->next_call_time = current_time + interval;
}
/*
{
char buff1[32];
char buff2[32];
logInfo("id=%d, current time=%s, first call time=%s",
pEntry->id, formatDatetime(g_current_time,
pEntry->id, formatDatetime(current_time,
"%Y-%m-%d %H:%M:%S", buff1, sizeof(buff1)),
formatDatetime(pEntry->next_call_time,
"%Y-%m-%d %H:%M:%S", buff2, sizeof(buff2)));
@ -719,7 +716,7 @@ int sched_start_ex(ScheduleArray *pScheduleArray, pthread_t *ptid,
if (timer_slot_count > 0)
{
if ((result=fast_mblock_init_ex1(&pContext->delay_task_allocator,
"sched-delay-task", sizeof(FastDelayTask),
"sched_delay_task", sizeof(FastDelayTask),
mblock_alloc_once, 0, NULL, NULL, true)) != 0)
{
free(pContext);
@ -963,16 +960,3 @@ uint32_t sched_generate_next_id()
{
return ++next_id;
}
static int sched_free_ptr_func(void *ptr)
{
free(ptr);
return 0;
}
int sched_delay_free_ptr(void *ptr, const int delay_seconds)
{
const bool new_thread = false;
return sched_add_delay_task_ex(schedule_context, sched_free_ptr_func,
ptr, delay_seconds, new_thread);
}

View File

@ -168,15 +168,6 @@ int sched_add_delay_task(TaskFunc task_func, void *func_args,
const int delay_seconds, const bool new_thread);
/** delay free a pointer
* parameters:
* ptr: the ptr to free
* delay_seconds: delay seconds to free the ptr
* return: error no, 0 for success, != 0 fail
*/
int sched_delay_free_ptr(void *ptr, const int delay_seconds);
/** init the schedule context
* parameters:
* pContext: store the ScheduleContext pointer
@ -206,9 +197,6 @@ int sched_start(ScheduleArray *pScheduleArray, pthread_t *ptid, \
*/
void sched_print_all_entries();
time_t sched_make_first_call_time(struct tm *tm_current,
const TimeInfo *time_base, const int interval);
#ifdef __cplusplus
}
#endif

View File

@ -244,7 +244,6 @@ static int fc_server_check_ip_port(FCServerConfig *ctx,
FCServerMap *previous;
FCServerMap *current;
FCServerMap *end;
char formatted_ip[FORMATTED_IP_SIZE];
int id1;
int id2;
@ -262,8 +261,8 @@ static int fc_server_check_ip_port(FCServerConfig *ctx,
logError("file: "__FILE__", line: %d, "
"config file: %s, duplicate ip:port %s:%u, "
"the server ids: %d, %d", __LINE__,
config_filename, format_ip_address(previous->ip_addr.str,
formatted_ip), previous->port, id1, id2);
config_filename, previous->ip_addr.str,
previous->port, id1, id2);
return EEXIST;
}
@ -294,18 +293,15 @@ FCServerInfo *fc_server_get_by_ip_port_ex(FCServerConfig *ctx,
static inline void fc_server_set_group_ptr_name(FCServerGroupInfo *ginfo,
const char *group_name)
{
int len;
ginfo->group_name.str = ginfo->name_buff;
len = strlen(group_name);
if (len >= sizeof(ginfo->name_buff)) {
len = sizeof(ginfo->name_buff) - 1;
ginfo->group_name.len = snprintf(ginfo->name_buff,
sizeof(ginfo->name_buff) - 1, "%s", group_name);
if (ginfo->group_name.len == 0) {
return;
}
memcpy(ginfo->name_buff, group_name, len);
*(ginfo->name_buff + len) = '\0';
fc_trim(ginfo->name_buff);
ginfo->group_name.len = strlen(ginfo->name_buff);
fc_trim(ginfo->group_name.str);
ginfo->group_name.len = strlen(ginfo->group_name.str);
}
static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo,
@ -313,111 +309,40 @@ static inline void fc_server_set_ip_prefix(FCServerGroupInfo *ginfo,
{
ginfo->filter.ip_prefix.str = ginfo->filter.prefix_buff;
if (ip_prefix != NULL) {
ginfo->filter.ip_prefix.len = fc_safe_strcpy(
ginfo->filter.prefix_buff, ip_prefix);
ginfo->filter.ip_prefix.len = snprintf(ginfo->filter.prefix_buff,
sizeof(ginfo->filter.prefix_buff) - 1, "%s", ip_prefix);
}
}
static inline int fc_server_set_comm_type(FCCommunicationType *comm_type,
const char *config_filename, const char *section_name,
const char *comm_type_str, const FCCommunicationType default_comm_type)
{
if (comm_type_str == NULL) {
*comm_type = default_comm_type;
return 0;
} else if (strcasecmp(comm_type_str, "socket") == 0) {
*comm_type = fc_comm_type_sock;
return 0;
} else if (strcasecmp(comm_type_str, "rdma") == 0) {
*comm_type = fc_comm_type_rdma;
return 0;
} else {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, "
"invalid communication: %s!", __LINE__,
config_filename, section_name, comm_type_str);
return EINVAL;
}
}
static int load_comm_type_and_smart_polling(IniFullContext *ini_ctx,
FCCommunicationType *comm_type, FCSmartPollingConfig *smart_polling,
const FCCommunicationType default_comm_type,
const FCSmartPollingConfig *default_smart_polling)
{
int result;
char *comm_type_str;
comm_type_str = iniGetStrValue(ini_ctx->section_name,
"communication", ini_ctx->context);
if (comm_type_str == NULL) {
comm_type_str = iniGetStrValue(ini_ctx->section_name,
"comm_type", ini_ctx->context);
}
if ((result=fc_server_set_comm_type(comm_type, ini_ctx->filename,
ini_ctx->section_name, comm_type_str,
default_comm_type)) != 0)
{
return result;
}
if (*comm_type == fc_comm_type_sock) {
smart_polling->enabled = false;
smart_polling->switch_on_iops = 0;
smart_polling->switch_on_count = 0;
} else {
smart_polling->enabled = iniGetBoolValue(ini_ctx->section_name,
"smart_polling", ini_ctx->context,
default_smart_polling->enabled);
smart_polling->switch_on_iops = iniGetIntValue(ini_ctx->section_name,
"polling_switch_on_iops", ini_ctx->context,
default_smart_polling->switch_on_iops);
smart_polling->switch_on_count = iniGetIntValue(ini_ctx->section_name,
"polling_switch_on_count", ini_ctx->context,
default_smart_polling->switch_on_count);
}
return 0;
}
static inline int load_buffer_size(IniFullContext *ini_ctx,
const int default_buffer_size)
{
int buffer_size;
buffer_size = iniGetByteValue(ini_ctx->section_name, "buffer_size",
ini_ctx->context, default_buffer_size);
return iniCheckAndCorrectIntValue(ini_ctx, "buffer_size",
buffer_size, 8 * 1024, 8 * 1024 * 1024);
}
static int fc_server_load_one_group(FCServerConfig *ctx,
IniFullContext *ini_ctx, const int group_count)
const char *config_filename, IniContext *ini_context,
const int group_count, const char *section_name)
{
int result;
FCServerGroupInfo *group;
char new_name[FAST_INI_ITEM_NAME_SIZE];
char *port_str;
char *net_type;
char *ip_prefix;
strcpy(new_name, ini_ctx->section_name);
strcpy(new_name, section_name);
group = ctx->group_array.groups + ctx->group_array.count;
fc_server_set_group_ptr_name(group, new_name + GROUP_SECTION_PREFIX_LEN);
if (group->group_name.len == 0) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, no group name!",
__LINE__, ini_ctx->filename, ini_ctx->section_name);
__LINE__, config_filename, section_name);
return EINVAL;
}
port_str = iniGetStrValue(ini_ctx->section_name,
SERVER_ITEM_PORT_STR, ini_ctx->context);
port_str = iniGetStrValue(section_name, SERVER_ITEM_PORT_STR, ini_context);
if (port_str == NULL) {
if (group_count == 1) {
group->port = ctx->default_port;
} else {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, no item: %s!",
__LINE__, ini_ctx->filename, ini_ctx->section_name,
__LINE__, config_filename, section_name,
SERVER_ITEM_PORT_STR);
return ENOENT;
}
@ -427,39 +352,24 @@ static int fc_server_load_one_group(FCServerConfig *ctx,
if (group->port <= 0 || (endptr != NULL && *endptr != '\0')) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, item: %s, "
"invalid port: %s", __LINE__, ini_ctx->filename,
ini_ctx->section_name, SERVER_ITEM_PORT_STR, port_str);
"invalid port: %s", __LINE__, config_filename,
section_name, SERVER_ITEM_PORT_STR, port_str);
return EINVAL;
}
}
net_type = iniGetStrValue(ini_ctx->section_name,
"net_type", ini_ctx->context);
net_type = iniGetStrValue(section_name, "net_type", ini_context);
group->filter.net_type = fc_get_net_type_by_name(net_type);
if (group->filter.net_type == FC_NET_TYPE_NONE) {
logError("file: "__FILE__", line: %d, "
"config filename: %s, section: %s, invalid net_type: %s",
__LINE__, ini_ctx->filename, group->group_name.str, net_type);
__LINE__, config_filename, group->group_name.str, net_type);
return EINVAL;
}
ip_prefix = iniGetStrValue(ini_ctx->section_name,
"ip_prefix", ini_ctx->context);
ip_prefix = iniGetStrValue(section_name, "ip_prefix", ini_context);
fc_server_set_ip_prefix(group, ip_prefix);
if ((result=load_comm_type_and_smart_polling(ini_ctx,
&group->comm_type, &group->smart_polling,
ctx->comm_type, &ctx->smart_polling)) != 0)
{
return result;
}
if (group->comm_type == fc_comm_type_sock) {
group->buffer_size = 0;
} else {
group->buffer_size = load_buffer_size(ini_ctx, ctx->buffer_size);
}
ctx->group_array.count++;
return 0;
}
@ -519,7 +429,7 @@ static void fc_server_sort_groups(FCServerConfig *ctx)
}
static int fc_server_load_groups(FCServerConfig *ctx,
IniFullContext *ini_ctx)
const char *config_filename, IniContext *ini_context)
{
int result;
int count;
@ -527,30 +437,30 @@ static int fc_server_load_groups(FCServerConfig *ctx,
IniSectionInfo *section;
IniSectionInfo *end;
if ((result=iniGetSectionNamesByPrefix(ini_ctx->context,
if ((result=iniGetSectionNamesByPrefix(ini_context,
GROUP_SECTION_PREFIX_STR, sections,
FC_MAX_GROUP_COUNT, &count)) != 0)
{
logError("file: "__FILE__", line: %d, "
"config filename: %s, get sections by prefix %s fail, "
"errno: %d, error info: %s", __LINE__, ini_ctx->filename,
"errno: %d, error info: %s", __LINE__, config_filename,
GROUP_SECTION_PREFIX_STR, result, STRERROR(result));
return result;
}
if (count == 0) {
ctx->group_array.count = 1;
memset(ctx->group_array.groups, 0, sizeof(FCServerGroupInfo));
fc_server_set_group_ptr_name(ctx->group_array.groups + 0, "");
ctx->group_array.groups[0].port = iniGetIntValue(NULL, "port",
ini_ctx->context, ctx->default_port);
ini_context, ctx->default_port);
return 0;
}
end = sections + count;
for (section=sections; section<end; section++) {
ini_ctx->section_name = section->section_name;
if ((result=fc_server_load_one_group(ctx, ini_ctx, count)) != 0) {
if ((result=fc_server_load_one_group(ctx, config_filename,
ini_context, count, section->section_name)) != 0)
{
return result;
}
}
@ -702,7 +612,6 @@ static int check_addresses_duplicate(FCServerConfig *ctx,
FCAddressInfo **ppaddr;
FCAddressInfo **ppend;
FCAddressInfo **pprevious;
char formatted_ip[FORMATTED_IP_SIZE];
if (group_addr->address_array.count <= 1) {
return 0;
@ -720,8 +629,7 @@ static int check_addresses_duplicate(FCServerConfig *ctx,
config_filename, section_name,
group_addr->server_group->group_name.len,
group_addr->server_group->group_name.str,
format_ip_address((*ppaddr)->conn.ip_addr, formatted_ip),
(*ppaddr)->conn.port);
(*ppaddr)->conn.ip_addr, (*ppaddr)->conn.port);
return EEXIST;
}
pprevious = ppaddr;
@ -886,7 +794,6 @@ static int fc_server_load_group_server(FCServerConfig *ctx,
return result;
}
address.conn.comm_type = group->comm_type;
if ((result=fc_server_set_group_server_address(server,
group_addr, &address)) != 0)
{
@ -905,7 +812,6 @@ static int fc_server_set_host(FCServerConfig *ctx, FCServerInfo *server,
FCGroupAddresses *group_addr;
const FCAddressInfo *new_addr;
FCAddressInfo addr_holder;
char formatted_ip[FORMATTED_IP_SIZE];
int result;
int count;
int group_index;
@ -929,16 +835,9 @@ static int fc_server_set_host(FCServerConfig *ctx, FCServerInfo *server,
if (addr->conn.port == 0) {
addr_holder = *addr;
addr_holder.conn.port = FC_SERVER_GROUP_PORT(group);
addr_holder.conn.comm_type = group->comm_type;
new_addr = &addr_holder;
} else {
if (addr->conn.comm_type == group->comm_type) {
new_addr = addr;
} else {
addr_holder = *addr;
addr_holder.conn.comm_type = group->comm_type;
new_addr = &addr_holder;
}
new_addr = addr;
}
if ((result=fc_server_set_group_server_address(server,
@ -971,8 +870,7 @@ static int fc_server_set_host(FCServerConfig *ctx, FCServerInfo *server,
"config filename: %s, section: %s, "
"host %s:%u belongs to %d groups",
__LINE__, config_filename, section_name,
format_ip_address(addr->conn.ip_addr, formatted_ip),
addr->conn.port, count);
addr->conn.ip_addr, addr->conn.port, count);
return EEXIST;
}
@ -1269,71 +1167,17 @@ static int fc_server_load_servers(FCServerConfig *ctx,
return result;
}
static void load_connection_thread_local(FCServerConfig *ctx,
IniContext *ini_context, const char *config_filename)
{
char *connection_thread_local;
connection_thread_local = iniGetStrValue(NULL,
"connection_thread_local", ini_context);
if (connection_thread_local == NULL || *connection_thread_local == '\0') {
ctx->connection_thread_local = fc_connection_thread_local_auto;
} else if (strcasecmp(connection_thread_local, "auto") == 0) {
ctx->connection_thread_local = fc_connection_thread_local_auto;
} else if (strcasecmp(connection_thread_local, "yes") == 0) {
ctx->connection_thread_local = fc_connection_thread_local_yes;
} else if (strcasecmp(connection_thread_local, "no") == 0) {
ctx->connection_thread_local = fc_connection_thread_local_no;
} else {
logWarning("file: "__FILE__", line: %d, "
"config file: %s, invalid connection_thread_local: %s, "
"set to auto!", __LINE__, config_filename,
connection_thread_local);
ctx->connection_thread_local = fc_connection_thread_local_auto;
}
}
static int fc_server_load_data(FCServerConfig *ctx,
IniContext *ini_context, const char *config_filename)
{
int result;
bool have_rdma;
IniFullContext full_ini_ctx;
FCSmartPollingConfig default_smart_polling;
FCServerGroupInfo *group;
FCServerGroupInfo *end;
FAST_INI_SET_FULL_CTX_EX(full_ini_ctx,
config_filename, NULL, ini_context);
default_smart_polling.enabled = true;
default_smart_polling.switch_on_iops = 10240;
default_smart_polling.switch_on_count = 3;
if ((result=load_comm_type_and_smart_polling(&full_ini_ctx,
&ctx->comm_type, &ctx->smart_polling,
fc_comm_type_sock, &default_smart_polling)) != 0)
if ((result=fc_server_load_groups(ctx, config_filename,
ini_context)) != 0)
{
return result;
}
ctx->buffer_size = load_buffer_size(&full_ini_ctx, 256 * 1024);
if ((result=fc_server_load_groups(ctx, &full_ini_ctx)) != 0) {
return result;
}
have_rdma = false;
end = ctx->group_array.groups + ctx->group_array.count;
for (group=ctx->group_array.groups; group<end; group++) {
if (group->comm_type != fc_comm_type_sock) {
have_rdma = true;
break;
}
}
if (!have_rdma) {
ctx->buffer_size = 0;
}
load_connection_thread_local(ctx, ini_context, config_filename);
if ((result=fc_server_load_servers(ctx, config_filename,
ini_context)) != 0)
{
@ -1496,31 +1340,13 @@ static int fc_groups_to_string(FCServerConfig *ctx, FastBuffer *buffer)
fast_buffer_append(buffer,
"[%s%.*s]\n"
"port = %d\n",
GROUP_SECTION_PREFIX_STR,
group->group_name.len, group->group_name.str,
group->port);
if (group->comm_type != fc_comm_type_sock) {
fast_buffer_append(buffer,
"communication = %s\n"
"smart_polling = %d\n"
"polling_switch_on_iops = %d\n"
"polling_switch_on_count = %d\n",
fc_comm_type_str(group->comm_type),
group->smart_polling.enabled,
group->smart_polling.switch_on_iops,
group->smart_polling.switch_on_count);
if (group->buffer_size != ctx->buffer_size) {
fast_buffer_append(buffer, "buffer_size = %d KB\n",
group->buffer_size / 1024);
}
}
fast_buffer_append(buffer,
"port = %d\n"
"net_type = %s\n"
"ip_prefix = %.*s\n\n",
net_type_caption, group->filter.ip_prefix.len,
GROUP_SECTION_PREFIX_STR,
group->group_name.len, group->group_name.str,
group->port, net_type_caption,
group->filter.ip_prefix.len,
group->filter.ip_prefix.str);
}
return 0;
@ -1531,7 +1357,6 @@ static void fc_group_servers_to_string(FCServerConfig *ctx,
{
FCAddressInfo **addr;
FCAddressInfo **end;
char formatted_ip[FORMATTED_IP_SIZE];
end = gaddr->address_array.addrs + gaddr->address_array.count;
for (addr=gaddr->address_array.addrs; addr<end; addr++) {
@ -1545,8 +1370,7 @@ static void fc_group_servers_to_string(FCServerConfig *ctx,
SERVER_ITEM_HOST_AFFIX_STR);
}
fast_buffer_append(buffer, " = %s:%u\n",
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
(*addr)->conn.port);
(*addr)->conn.ip_addr, (*addr)->conn.port);
}
}
@ -1599,14 +1423,6 @@ int fc_server_to_config_string(FCServerConfig *ctx, FastBuffer *buffer)
{
int result;
if (ctx->buffer_size > 0) {
if ((result=fast_buffer_check(buffer, 1024)) != 0) {
return result;
}
fast_buffer_append(buffer, "buffer_size = %d KB\n",
ctx->buffer_size / 1024);
}
fc_server_clear_server_port(&ctx->group_array);
if ((result=fc_groups_to_string(ctx, buffer)) != 0) {
return result;
@ -1619,31 +1435,13 @@ static void fc_server_log_groups(FCServerConfig *ctx)
{
FCServerGroupInfo *group;
FCServerGroupInfo *end;
char buff[1024];
char *p;
end = ctx->group_array.groups + ctx->group_array.count;
for (group=ctx->group_array.groups; group<end; group++) {
p = buff + sprintf(buff, "group_name: %.*s, port: %d",
group->group_name.len, group->group_name.str,
group->port);
if (group->comm_type != fc_comm_type_sock) {
p += sprintf(p, ", communication: %s, smart_polling: %d, "
"polling_switch_on_iops: %d, polling_switch_on_count: %d",
fc_comm_type_str(group->comm_type),
group->smart_polling.enabled,
group->smart_polling.switch_on_iops,
group->smart_polling.switch_on_count);
if (group->buffer_size != ctx->buffer_size) {
p += sprintf(p, ", buffer_size = %d KB",
group->buffer_size / 1024);
}
}
p += sprintf(p, ", net_type: %s, ip_prefix: %.*s",
logInfo("group_name: %.*s, port: %d, net_type: %s, ip_prefix: %.*s",
group->group_name.len, group->group_name.str, group->port,
get_net_type_caption(group->filter.net_type),
group->filter.ip_prefix.len, group->filter.ip_prefix.str);
log_it1(LOG_INFO, buff, p - buff);
}
}
@ -1651,13 +1449,11 @@ static void fc_server_log_group_servers(FCGroupAddresses *gaddr)
{
FCAddressInfo **addr;
FCAddressInfo **end;
char formatted_ip[FORMATTED_IP_SIZE];
end = gaddr->address_array.addrs + gaddr->address_array.count;
for (addr=gaddr->address_array.addrs; addr<end; addr++) {
logInfo(" %d. %s:%u", (int)(addr - gaddr->address_array.addrs + 1),
format_ip_address((*addr)->conn.ip_addr, formatted_ip),
(*addr)->conn.port);
(*addr)->conn.ip_addr, (*addr)->conn.port);
}
}
@ -1695,24 +1491,69 @@ static void fc_server_log_servers(FCServerConfig *ctx)
void fc_server_to_log(FCServerConfig *ctx)
{
char buff[256];
char *p;
p = buff + sprintf(buff, "connection_thread_local: %s",
fc_connection_thread_local_str(ctx->connection_thread_local));
if (ctx->buffer_size > 0) {
p += sprintf(p, ", buffer_size: %d KB", ctx->buffer_size / 1024);
}
log_it1(LOG_INFO, buff, p - buff);
fc_server_log_groups(ctx);
fc_server_log_servers(ctx);
}
int fc_server_make_connection_ex(FCAddressPtrArray *addr_array,
ConnectionInfo *conn, const char *service_name,
ConnectionInfo *fc_server_check_connect_ex(FCAddressPtrArray *addr_array,
const int connect_timeout, const char *bind_ipaddr,
const bool log_connect_error)
const bool log_connect_error, int *err_no)
{
FCAddressInfo **current;
FCAddressInfo **addr;
FCAddressInfo **end;
if (addr_array->count <= 0) {
*err_no = ENOENT;
return NULL;
}
current = addr_array->addrs + addr_array->index;
if ((*current)->conn.sock >= 0) {
return &(*current)->conn;
}
if ((*err_no=conn_pool_connect_server_ex(&(*current)->conn,
connect_timeout, bind_ipaddr, log_connect_error)) == 0)
{
return &(*current)->conn;
}
if (addr_array->count == 1) {
return NULL;
}
end = addr_array->addrs + addr_array->count;
for (addr=addr_array->addrs; addr<end; addr++) {
if (addr == current) {
continue;
}
if ((*err_no=conn_pool_connect_server_ex(&(*addr)->conn,
connect_timeout, bind_ipaddr,
log_connect_error)) == 0)
{
addr_array->index = addr - addr_array->addrs;
return &(*addr)->conn;
}
}
return NULL;
}
void fc_server_disconnect(FCAddressPtrArray *addr_array)
{
FCAddressInfo **current;
current = addr_array->addrs + addr_array->index;
if ((*current)->conn.sock >= 0) {
close((*current)->conn.sock);
(*current)->conn.sock = -1;
}
}
int fc_server_make_connection_ex(FCAddressPtrArray *addr_array,
ConnectionInfo *conn, const int connect_timeout,
const char *bind_ipaddr, const bool log_connect_error)
{
FCAddressInfo **current;
FCAddressInfo **addr;
@ -1724,11 +1565,9 @@ int fc_server_make_connection_ex(FCAddressPtrArray *addr_array,
}
current = addr_array->addrs + addr_array->index;
conn_pool_set_server_info(conn, (*current)->conn.ip_addr,
(*current)->conn.port);
conn->comm_type = (*current)->conn.comm_type;
if ((result=G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
make_connection(conn, service_name, connect_timeout * 1000,
*conn = (*current)->conn;
conn->sock = -1;
if ((result=conn_pool_connect_server_ex(conn, connect_timeout,
bind_ipaddr, log_connect_error)) == 0)
{
return 0;
@ -1744,11 +1583,9 @@ int fc_server_make_connection_ex(FCAddressPtrArray *addr_array,
continue;
}
conn_pool_set_server_info(conn, (*addr)->conn.ip_addr,
(*addr)->conn.port);
conn->comm_type = (*addr)->conn.comm_type;
if ((result=G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].
make_connection(conn, service_name, connect_timeout * 1000,
*conn = (*addr)->conn;
conn->sock = -1;
if ((result=conn_pool_connect_server_ex(conn, connect_timeout,
bind_ipaddr, log_connect_error)) == 0)
{
addr_array->index = addr - addr_array->addrs;
@ -1783,36 +1620,3 @@ const FCAddressInfo *fc_server_get_address_by_peer(
return *(addr_array->addrs);
}
struct ibv_pd *fc_alloc_rdma_pd(fc_alloc_pd_callback alloc_pd,
FCAddressPtrArray *address_array, int *result)
{
char *ip_addrs[FC_MAX_SERVER_IP_COUNT];
char **ip_addr;
FCAddressInfo **addr;
FCAddressInfo **end;
struct ibv_pd *pd;
int port;
if (address_array->count == 0) {
port = 0;
} else {
port = address_array->addrs[0]->conn.port;
}
end = address_array->addrs + address_array->count;
for (addr=address_array->addrs, ip_addr=ip_addrs;
addr<end; addr++, ip_addr++)
{
*ip_addr = (*addr)->conn.ip_addr;
}
if ((pd=alloc_pd((const char **)ip_addrs, address_array->
count, port)) != NULL)
{
*result = 0;
} else {
*result = ENODEV;
}
return pd;
}

View File

@ -52,21 +52,11 @@ typedef struct {
FCAddressInfo **addrs;
} FCAddressPtrArray;
typedef struct
{
bool enabled;
int switch_on_iops;
int switch_on_count;
} FCSmartPollingConfig;
typedef struct
{
string_t group_name;
int port; //default port
int server_port; //port in server section
int buffer_size; //for RDMA
FCCommunicationType comm_type;
FCSmartPollingConfig smart_polling;
struct {
int net_type;
string_t ip_prefix;
@ -121,21 +111,11 @@ typedef struct
FCServerMap *maps;
} FCServerMapArray;
typedef enum {
fc_connection_thread_local_auto,
fc_connection_thread_local_yes,
fc_connection_thread_local_no
} FCServerConnThreadLocal;
typedef struct fc_server_config
typedef struct
{
int default_port;
int min_hosts_each_group;
bool share_between_groups; //if an address shared between different groups
int buffer_size; //for RDMA
FCCommunicationType comm_type;
FCSmartPollingConfig smart_polling;
FCServerConnThreadLocal connection_thread_local;
FCServerGroupArray group_array;
struct {
FCServerInfoArray by_id; //sorted by server id
@ -160,16 +140,6 @@ static inline FCServerInfo *fc_server_get_by_ip_port(FCServerConfig *ctx,
FCServerGroupInfo *fc_server_get_group_by_name(FCServerConfig *ctx,
const string_t *group_name);
static inline FCServerGroupInfo *fc_server_get_group_by_index(
FCServerConfig *ctx, const int index)
{
if (index < 0 || index >= ctx->group_array.count) {
return NULL;
}
return ctx->group_array.groups + index;
}
static inline int fc_server_get_group_index_ex(FCServerConfig *ctx,
const string_t *group_name)
{
@ -241,47 +211,24 @@ int fc_server_to_config_string(FCServerConfig *ctx, FastBuffer *buffer);
void fc_server_to_log(FCServerConfig *ctx);
ConnectionInfo *fc_server_check_connect_ex(FCAddressPtrArray *addr_array,
const int connect_timeout, const char *bind_ipaddr,
const bool log_connect_error, int *err_no);
#define fc_server_check_connect(addr_array, connect_timeout, err_no) \
fc_server_check_connect_ex(addr_array, connect_timeout, NULL, true, err_no)
void fc_server_disconnect(FCAddressPtrArray *addr_array);
const FCAddressInfo *fc_server_get_address_by_peer(
FCAddressPtrArray *addr_array, const char *peer_ip);
int fc_server_make_connection_ex(FCAddressPtrArray *addr_array,
ConnectionInfo *conn, const char *service_name,
const int connect_timeout, const char *bind_ipaddr,
const bool log_connect_error);
ConnectionInfo *conn, const int connect_timeout,
const char *bind_ipaddr, const bool log_connect_error);
#define fc_server_make_connection(addr_array, \
conn, service_name, connect_timeout) \
fc_server_make_connection_ex(addr_array, conn, \
service_name, connect_timeout, NULL, true)
static inline void fc_server_close_connection(ConnectionInfo *conn)
{
G_COMMON_CONNECTION_CALLBACKS[conn->comm_type].close_connection(conn);
}
static inline void fc_server_destroy_connection(ConnectionInfo *conn)
{
fc_server_close_connection(conn);
conn_pool_free_connection(conn);
}
struct ibv_pd *fc_alloc_rdma_pd(fc_alloc_pd_callback alloc_pd,
FCAddressPtrArray *address_array, int *result);
static inline const char *fc_connection_thread_local_str(
const FCServerConnThreadLocal value)
{
switch (value) {
case fc_connection_thread_local_auto:
return "auto";
case fc_connection_thread_local_yes:
return "yes";
case fc_connection_thread_local_no:
return "no";
default:
return "unkown";
}
}
#define fc_server_make_connection(addr_array, conn, connect_timeout) \
fc_server_make_connection_ex(addr_array, conn, connect_timeout, NULL, true)
#ifdef __cplusplus
}

View File

@ -42,7 +42,7 @@ int shared_buffer_init_ex(SharedBufferContext *context,
int result;
context->buffer_init_capacity = buffer_init_capacity;
if ((result=fast_mblock_init_ex1(&context->allocator, "shared-buffer",
if ((result=fast_mblock_init_ex1(&context->allocator, "shared_buffer",
sizeof(SharedBuffer), alloc_elements_once,
alloc_elements_limit, shared_buffer_alloc_init,
context, need_lock)) != 0)

File diff suppressed because it is too large Load Diff

View File

@ -19,16 +19,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/uio.h>
#include "common_define.h"
#ifdef OS_LINUX
#include <sys/syscall.h>
#endif
#include "fc_memory.h"
#include "ini_file_reader.h"
@ -38,22 +33,14 @@
#define NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS \
(NORMALIZE_FLAGS_URL_ENABLED | NORMALIZE_FLAGS_URL_APPEND_PARAMS)
#define FC_SET_CLOEXEC(fd) \
if (g_set_cloexec) fd_set_cloexec(fd)
#define resolve_path(from, filename, full_filename, size) \
normalize_path_ex(from, filename, full_filename, size, \
NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS)
#ifdef __cplusplus
extern "C" {
#endif
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)
{
g_set_cloexec = cloexec;
}
/** lowercase the string
* parameters:
* src: input string, will be changed
@ -198,24 +185,14 @@ void printBuffHex(const char *s, const int len);
* buff: the buffer, at least 2 bytes space, no tail \0
* return: none
*/
static inline void short2buff(const short n, char *buff)
{
unsigned char *p;
p = (unsigned char *)buff;
*p++ = (n >> 8) & 0xFF;
*p++ = n & 0xFF;
}
void short2buff(const short n, char *buff);
/** buffer convert to 16 bits int
* parameters:
* buff: big-endian 2 bytes buffer
* return: 16 bits int value
*/
static inline short buff2short(const char *buff)
{
return (short)((((unsigned char)(*(buff))) << 8) |
((unsigned char)(*(buff+1))));
}
short buff2short(const char *buff);
/** 32 bits int convert to buffer (big-endian)
* parameters:
@ -223,28 +200,14 @@ static inline short buff2short(const char *buff)
* buff: the buffer, at least 4 bytes space, no tail \0
* return: none
*/
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;
}
void int2buff(const int n, char *buff);
/** buffer convert to 32 bits int
* parameters:
* buff: big-endian 4 bytes buffer
* return: 32 bits int value
*/
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)));
}
int buff2int(const char *buff);
/** long (64 bits) convert to buffer (big-endian)
* parameters:
@ -252,38 +215,15 @@ static inline int buff2int(const char *buff)
* buff: the buffer, at least 8 bytes space, no tail \0
* return: none
*/
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;
}
void long2buff(int64_t n, char *buff);
/** buffer convert to 64 bits int
* parameters:
* buff: big-endian 8 bytes buffer
* return: 64 bits int value
*/
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)));
}
int64_t buff2long(const char *buff);
/** 32 bits float convert to buffer (big-endian)
* parameters:
@ -341,154 +281,6 @@ static inline double buff2double(const char *buff)
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)
* parameters:
* pStr: the string to trim
@ -503,6 +295,13 @@ char *trim_left(char *pStr);
*/
char *trim_right(char *pStr);
/** trim leading and tail spaces ( \t\r\n)
* parameters:
* pStr: the string to trim
* return: trimed string porinter as pStr
*/
char *trim(char *pStr);
/** trim leading and tail spaces ( \t\r\n)
* parameters:
* pStr: the string to trim
@ -728,26 +527,11 @@ int load_log_level_ex(const char *conf_filename);
/** set global log level
* parameters:
* pLogLevel: the log level string value
* pLogLevel: log level string value
* return: none
*/
void set_log_level(char *pLogLevel);
/** get log level by caption
* parameters:
* pLogLevel: the log level string value
* default_value: the default log level
* return: the log level integer value
*/
int get_log_level(char *pLogLevel, const int default_value);
/** get log level caption
* parameters:
* log_level: the log level integer value
* return: the log level caption
*/
const char *get_log_level_caption(const int log_level);
/** load allow hosts from config context
* parameters:
* pIniContext: the config context
@ -756,7 +540,7 @@ const char *get_log_level_caption(const int log_level);
* return: error no , 0 success, != 0 fail
*/
int load_allow_hosts(IniContext *pIniContext, \
in_addr_64_t **allow_ip_addrs, int *allow_ip_count);
in_addr_t **allow_ip_addrs, int *allow_ip_count);
/** get time item from config context
@ -808,47 +592,6 @@ int get_time_item_from_str(const char *pValue, const char *item_name,
*/
void chopPath(char *filePath);
/** remove redundant slashes
* parameters:
* src: the input path
* dest: the output path
* size: the max size of dest path
* return: error no , 0 success, != 0 fail
*/
int fc_remove_redundant_slashes(const string_t *src,
string_t *dest, const int size);
static inline int fc_remove_redundant_slashes1(const char *input,
string_t *dest, const int size)
{
string_t src;
FC_SET_STRING(src, (char *)input);
return fc_remove_redundant_slashes(&src, dest, size);
}
static inline int fc_remove_redundant_slashes2(const char *input,
char *output, const int size)
{
string_t src;
string_t dest;
FC_SET_STRING(src, (char *)input);
dest.str = output;
return fc_remove_redundant_slashes(&src, &dest, size);
}
/** get file content by fd
* parameters:
* fd: the file descriptor
* filename: the filename
* buff: return the buff, must be freed
* file_size: store the file size
* return: error no , 0 success, != 0 fail
*/
int getFileContent1(int fd, const char *filename,
char **buff, int64_t *file_size);
/** get file content
* parameters:
* filename: the filename
@ -858,18 +601,6 @@ int getFileContent1(int fd, const char *filename,
*/
int getFileContent(const char *filename, char **buff, int64_t *file_size);
/** get file content
* parameters:
* fd: the file descriptor
* filename: the filename
* buff: the buff to store file content
* offset: the start offset
* size: specify the size to fetch and return the fetched size
* return: error no , 0 success, != 0 fail
*/
int getFileContentEx1(int fd, const char *filename, char *buff,
int64_t offset, int64_t *size);
/** get file content
* parameters:
* filename: the filename
@ -966,7 +697,7 @@ int fd_set_cloexec(int fd);
*/
int set_run_by(const char *group_name, const char *username);
/** compare ip address, type is (in_addr_64_t *)
/** compare ip address, type is (in_addr_t *)
* parameters:
* p1: the first ip address
* p2: the second ip address
@ -974,8 +705,6 @@ int set_run_by(const char *group_name, const char *username);
*/
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
* parameters:
* pStr: the string to parse
@ -1021,15 +750,6 @@ double get_line_distance_km(const double lat1, const double lon1,
*/
bool is_private_ip(const char* ip);
/** 从字符串中解析IP地址和端口号
* parameters:
* src: the source string, will be modified by this function
* parts: store split strings
* return: string array / column count
*/
int parseAddress(char *src, char *parts[2]);
/** get current time in ns
* return: current time
*/
@ -1047,10 +767,7 @@ int64_t get_current_time_us();
* n: the number to test
* return: true for power 2, otherwise false
*/
static inline bool is_power2(const int64_t n)
{
return ((n != 0) && (n & (n - 1)) == 0);
}
bool is_power2(const int64_t n);
/** set file read lock
* parameters:
@ -1110,7 +827,7 @@ bool isLeadingSpacesLine(const char *content, const char *current);
*/
bool isTrailingSpacesLine(const char *tail, const char *end);
/** safe write wrapper
/** write to file
* parameters:
* fd: the fd to write
* buf: the buffer
@ -1119,15 +836,6 @@ bool isTrailingSpacesLine(const char *tail, const char *end);
*/
ssize_t fc_safe_write(int fd, const char *buf, const size_t nbyte);
/** safe writev wrapper
* parameters:
* fd: the fd to write
* iov: the iov array
* iovcnt: the iov count
* return: written bytes for success, -1 when fail
*/
ssize_t fc_safe_writev(int fd, const struct iovec *iov, int iovcnt);
/** lock and write to file
* parameters:
* fd: the fd to write
@ -1146,15 +854,6 @@ ssize_t fc_lock_write(int fd, const char *buf, const size_t nbyte);
*/
ssize_t fc_safe_read(int fd, char *buf, const size_t count);
/** read integral lines from file
* parameters:
* fd: the fd to read
* buf: the buffer to store the line
* size: max read bytes
* return: error no , 0 success, != 0 fail
*/
ssize_t fc_read_lines(int fd, char *buf, const size_t size);
/** ftok with hash code
* parameters:
* path: the file path
@ -1191,8 +890,6 @@ static inline const char *long_to_comma_str(const int64_t n, char *buff)
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
* parameters:
* str: the string to detect
@ -1243,26 +940,25 @@ char *format_http_date(time_t t, BufferInfo *buffer);
/** return full path for the filename (the second parameter)
* parameters:
* from: the input full path filename to get base path,
* NULL for current work directory
* from: the input full path filename to get base path
* filename: the filename to resolve path
* full_filename: store the resolved full path filename
* size: the max size of full_filename
* return: length of the resolved full path
*/
int normalize_path(const string_t *from, const string_t *filename,
int normalize_path(const char *from, const char *filename,
char *full_filename, const int size);
static inline int normalize_path1(const char *from, const char *filename,
char *full_filename, const int size)
{
string_t from_string;
string_t filename_string;
FC_SET_STRING(from_string, (char *)from);
FC_SET_STRING(filename_string, (char *)filename);
return normalize_path(&from_string, &filename_string, full_filename, size);
}
/** return absolute uri (the second parameter)
* parameters:
* from: the input uri to get base path
* uri: the uri to resolve
* dest: store the resolved absolute uri
* size: the max size of dest
* return: length of the resolved uri
*/
int normalize_uri(const string_t *from, const char *uri,
char *dest, const int size);
/** return full path for the filename (the second parameter)
* parameters:
@ -1275,204 +971,9 @@ static inline int normalize_path1(const char *from, const char *filename,
* NORMALIZE_FLAGS_URL_APPEND_PARAMS: append params of from
* return: length of the resolved full path
*/
int normalize_path_ex(const string_t *from, const string_t *filename,
int normalize_path_ex(const char *from, const char *filename,
char *full_filename, const int size, const int flags);
static inline int resolve_path(const char *from, const char *filename,
char *full_filename, const int size)
{
string_t from_string;
string_t filename_string;
FC_SET_STRING(from_string, (char *)from);
FC_SET_STRING(filename_string, (char *)filename);
return normalize_path_ex(&from_string, &filename_string, full_filename,
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
* return: the gzip command full filename
@ -1529,15 +1030,6 @@ int fc_init_buffer(BufferInfo *buffer, const int buffer_size);
*/
void fc_free_buffer(BufferInfo *buffer);
/** realloc buffer
* parameters:
* buffer: the buffer to init
* init_buff_size: the init buffer size
* expect_size: the expect buffer size
* return: error no, 0 success, != 0 fail
*/
int fc_realloc_buffer(BufferInfo *buffer, const int
init_buff_size, const int expect_size);
static inline int fc_get_umask()
{
@ -1564,27 +1056,9 @@ static inline int fc_mkdirs(const char *path, const mode_t mode)
return fc_mkdirs_ex(path, mode, &create_count);
}
int fc_check_rename_ex(const char *oldpath, const char *newpath,
const bool overwritten);
static inline int fc_check_rename(const char *oldpath, const char *newpath)
{
const bool overwritten = true;
return fc_check_rename_ex(oldpath, newpath, overwritten);
}
int fc_get_path_child_count(const char *path);
int fc_copy_file(const char *src_filename, const char *dest_filename);
int fc_copy_to_path(const char *src_filename, const char *dest_path);
int fc_get_first_line(const char *filename, char *buff,
const int buff_size, string_t *line);
int fc_get_first_lines(const char *filename, char *buff,
const int buff_size, string_t *lines, int *count);
int fc_get_last_line(const char *filename, char *buff,
const int buff_size, int64_t *file_size, string_t *line);
@ -1601,100 +1075,6 @@ int fc_get_last_lines(const char *filename, char *buff,
bool fc_path_contains(const string_t *path, const string_t *needle,
int *result);
/** itoa output as decimal number
* parameters:
* n: the integer number to convert
* buff: store the converted string, NOT null-terminated
* return: converted string length
*/
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
* parameters:
* microseconds: microseconds to sleep
* return: 0 for success, != 0 for fail
*/
static inline int fc_sleep_us(const int microseconds)
{
struct timespec ts;
ts.tv_sec = microseconds / (1000 * 1000);
ts.tv_nsec = (microseconds % (1000 * 1000)) * 1000;
if (nanosleep(&ts, NULL) == 0) {
return 0;
} else {
return errno != 0 ? errno : EINVAL;
}
}
/** sleep in milliseconds
* parameters:
@ -1725,45 +1105,6 @@ int fc_check_filename(const string_t *filename, const char *caption);
*/
bool is_digital_string(const char *str);
int fc_safe_write_file_init(SafeWriteFileInfo *fi,
const char *file_path, const char *redo_filename,
const char *tmp_filename);
static inline int fc_safe_write_file_open(SafeWriteFileInfo *fi)
{
const int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC;
int result;
if ((fi->fd=open(fi->tmp_filename, flags, 0644)) < 0) {
result = errno != 0 ? errno : EIO;
logError("file: "__FILE__", line: %d, "
"open file %s fail, errno: %d, error info: %s",
__LINE__, fi->tmp_filename, result, STRERROR(result));
return result;
} else {
return 0;
}
}
static inline int fc_safe_write_file_close(SafeWriteFileInfo *fi)
{
int result;
close(fi->fd);
if (rename(fi->tmp_filename, fi->filename) != 0)
{
result = errno != 0 ? errno : EIO;
logError("file: "__FILE__", line: %d, "
"rename file \"%s\" to \"%s\" fail, "
"errno: %d, error info: %s", __LINE__,
fi->tmp_filename, fi->filename,
result, STRERROR(result));
return result;
} else {
return 0;
}
}
static inline int fc_check_realloc_iovec_array(
iovec_array_t *array, const int target_size)
{
@ -1797,59 +1138,6 @@ static inline int fc_check_realloc_iovec_array(
return 0;
}
static inline void fc_free_iovec_array(iovec_array_t *array)
{
if (array->iovs != NULL) {
free(array->iovs);
array->iovs = NULL;
array->alloc = 0;
}
}
static inline pid_t fc_gettid()
{
#ifdef OS_LINUX
#ifdef SYS_gettid
return (pid_t)syscall(SYS_gettid);
#else
return getpid();
#endif
#else
return getpid();
#endif
}
static inline size_t fc_iov_get_bytes(const
struct iovec *iov, const int iovcnt)
{
const struct iovec *iob;
const struct iovec *end;
size_t bytes;
switch (iovcnt) {
case 0:
return 0;
case 1:
return iov[0].iov_len;
case 2:
return iov[0].iov_len + iov[1].iov_len;
case 3:
return iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
case 4:
return iov[0].iov_len + iov[1].iov_len +
iov[2].iov_len + iov[3].iov_len;
default:
bytes = 0;
end = iov + iovcnt;
for (iob=iov; iob<end; iob++) {
bytes += iob->iov_len;
}
return bytes;
}
}
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -18,18 +18,16 @@
#ifndef _SOCKETOPT_H_
#define _SOCKETOPT_H_
#include <stdio.h>
#include <net/if.h>
#include <string.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include "common_define.h"
#include "shared_func.h"
#define FC_NET_TYPE_NONE 0
#define FC_NET_TYPE_OUTER 1 //extranet IP
@ -56,14 +54,14 @@
typedef struct fast_if_config {
char name[IF_NAMESIZE]; //if name
char mac[64];
char mac[32];
char ipv4[IP_ADDRESS_SIZE];
char ipv6[IP_ADDRESS_SIZE];
char ipv6[48];
} FastIFConfig;
typedef struct ip_addr_s {
char ip_addr[IP_ADDRESS_SIZE];
int af;
char ip_addr[INET6_ADDRSTRLEN];
int socket_domain;
} ip_addr_t;
typedef struct sockaddr_convert_s {
@ -109,13 +107,13 @@ extern "C" {
extern bool g_tcp_quick_ack;
#endif
typedef int (*getnamefunc)(int socket, struct sockaddr *address,
typedef int (*getnamefunc)(int socket, struct sockaddr *address, \
socklen_t *address_len);
typedef int (*tcpsenddatafunc)(int sock, void *data, const int size,
typedef int (*tcpsenddatafunc)(int sock, void* data, const int size, \
const int timeout);
typedef int (*tcprecvdata_exfunc)(int sock, void *data, const int size,
typedef int (*tcprecvdata_exfunc)(int sock, void *data, const int size, \
const int timeout, int *count);
#define getSockIpaddr(sock, buff, bufferSize) \
@ -146,7 +144,7 @@ int tcpgets(int sock, char *s, const int size, const int timeout);
* data: the buffer
* size: buffer size (max bytes can receive)
* timeout: read timeout
* count: store the bytes received
* count: store the bytes recveived
* return: error no, 0 success, != 0 fail
*/
int tcprecvdata_ex(int sock, void *data, const int size, \
@ -158,10 +156,10 @@ int tcprecvdata_ex(int sock, void *data, const int size, \
* data: the buffer
* size: buffer size (max bytes can receive)
* timeout: read timeout in seconds
* count: store the bytes received
* count: store the bytes recveived
* return: error no, 0 success, != 0 fail
*/
int tcprecvdata_nb_ex(int sock, void *data, const int size,
int tcprecvdata_nb_ex(int sock, void *data, const int size, \
const int timeout, int *count);
/** recv data (non-block mode) in ms
@ -169,45 +167,13 @@ int tcprecvdata_nb_ex(int sock, void *data, const int size,
* sock: the socket
* data: the buffer
* size: buffer size (max bytes can receive)
* timeout_ms: read timeout in milliseconds
* count: store the bytes received
* timeout: read timeout in milliseconds
* count: store the bytes recveived
* return: error no, 0 success, != 0 fail
*/
int tcprecvdata_nb_ms(int sock, void *data, const int size,
int tcprecvdata_nb_ms(int sock, void *data, const int size, \
const int timeout_ms, int *count);
/** recv data by readv (non-block mode) in ms
* parameters:
* sock: the socket
* size: the expect size
* iov: the iov to send
* iovcnt: the iov count
* timeout_ms: read timeout in milliseconds
* total_bytes: store the bytes received
* return: error no, 0 success, != 0 fail
*/
int tcpreadv_nb_ms(int sock, const int size, const struct iovec *iov,
const int iovcnt, const int timeout_ms, int *total_bytes);
/** recv data by readv (non-block mode)
* parameters:
* sock: the socket
* size: the expect size
* iov: the iov to send
* iovcnt: the iov count
* timeout: read timeout in seconds
* total_bytes: store the bytes received
* return: error no, 0 success, != 0 fail
*/
static inline int tcpreadv_nb_ex(int sock, const int size,
const struct iovec *iov, const int iovcnt,
const int timeout, int *total_bytes)
{
return tcpreadv_nb_ms(sock, size, iov, iovcnt,
timeout * 1000, total_bytes);
}
/** send data (block mode)
* parameters:
* sock: the socket
@ -216,7 +182,7 @@ static inline int tcpreadv_nb_ex(int sock, const int size,
* timeout: write timeout
* return: error no, 0 success, != 0 fail
*/
int tcpsenddata(int sock, void *data, const int size, const int timeout);
int tcpsenddata(int sock, void* data, const int size, const int timeout);
/** send data (non-block mode)
* parameters:
@ -226,18 +192,7 @@ int tcpsenddata(int sock, void *data, const int size, const int timeout);
* timeout: write timeout
* return: error no, 0 success, != 0 fail
*/
int tcpsenddata_nb(int sock, void *data, const int size, const int timeout);
/** send data by writev (non-block mode)
* parameters:
* sock: the socket
* iov: the iov to send
* iovcnt: the iov count
* timeout: write timeout
* return: error no, 0 success, != 0 fail
*/
int tcpwritev_nb(int sock, const struct iovec *iov,
const int iovcnt, const int timeout);
int tcpsenddata_nb(int sock, void* data, const int size, const int timeout);
/** connect to server by block mode
* parameters:
@ -347,9 +302,9 @@ int tcpprintkeepalive(int fd);
* sock: the socket
* buff: buffer to store the ip address
* bufferSize: the buffer size (max bytes)
* return: in_addr_64_t, INADDR_NONE for fail
* return: in_addr_t, INADDR_NONE for fail
*/
in_addr_64_t getIpaddr(getnamefunc getname, int sock, \
in_addr_t getIpaddr(getnamefunc getname, int sock, \
char *buff, const int bufferSize);
/** get ip address
@ -373,23 +328,14 @@ int getIpAndPort(getnamefunc getname, int sock,
*/
char *getHostnameByIp(const char *szIpAddr, char *buff, const int bufferSize);
/** get by IPv4 or IPv6 address by it's hostname
/** get by IPv4 address by it's hostname
* parameters:
* name: the hostname
* buff: buffer to store the ip address
* bufferSize: the buffer size (max bytes)
* af: store the address family
* return: in_addr_64_t, INADDR_NONE for fail
* return: in_addr_t, INADDR_NONE for fail
*/
in_addr_64_t getIpaddrByNameEx(const char *name, char *buff,
const int bufferSize, uint8_t *af);
static inline in_addr_64_t getIpaddrByName(const char *name,
char *buff, const int bufferSize)
{
uint8_t af;
return getIpaddrByNameEx(name, buff, bufferSize, &af);
}
in_addr_t getIpaddrByName(const char *name, char *buff, const int bufferSize);
/** get by ip addresses by it's hostname
* parameters:
@ -598,9 +544,6 @@ static inline int socketClientIPv6(const char *server_ip,
#define tcprecvdata_nb(sock, data, size, timeout) \
tcprecvdata_nb_ex(sock, data, size, timeout, NULL)
#define tcpreadv_nb(sock, size, iov, iovcnt, timeout) \
tcpreadv_nb_ex(sock, size, iov, iovcnt, timeout, NULL)
/** send a file
* parameters:
* sock: the socket
@ -698,64 +641,13 @@ int getifconfigs(FastIFConfig *if_configs, const int max_count, int *count);
* convert: the convert struct for IPv4 and IPv6 compatibility
* return: error no, 0 success, != 0 fail
*/
int setsockaddrbyip(const char *ip, const uint16_t port,
sockaddr_convert_t *convert);
int setsockaddrbyip(const char *ip, const uint16_t port, sockaddr_convert_t *convert);
static inline bool is_ipv6_addr(const char *ip)
{
return (*ip == ':' || strchr(ip, ':') != NULL); //ipv6
}
static inline const char *format_ip_address(const char *ip, char *buff)
{
if (is_ipv6_addr(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
{
strcpy(buff, ip);
}
return buff;
}
static inline const char *format_ip_port(const char *ip,
const int port, char *buff)
{
int ip_len;
bool is_ipv6;
char *p;
is_ipv6 = is_ipv6_addr(ip);
ip_len = strlen(ip);
p = buff;
if (is_ipv6)
{
*p++ = '[';
}
memcpy(p, ip, ip_len);
p += ip_len;
if (is_ipv6)
{
*p++ = ']';
}
*p++ = ':';
p += fc_itoa(port, p);
*p = '\0';
return buff;
}
void tcp_set_try_again_when_interrupt(const bool value);
static inline void tcp_dont_try_again_when_interrupt()
@ -765,15 +657,10 @@ static inline void tcp_dont_try_again_when_interrupt()
void tcp_set_quick_ack(const bool value);
bool tcp_socket_connected(int sock);
int fc_get_net_type_by_name(const char *net_type);
int fc_get_net_type_by_ip(const char *ip);
const char *fc_inet_ntop(const struct sockaddr *addr,
char *buff, const int bufferSize);
static inline bool is_network_error(const int err_no)
{
switch (err_no)

View File

@ -1,178 +0,0 @@
/*
* 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 GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "sorted_array.h"
void sorted_array_init(SortedArrayContext *ctx,
const int element_size, const bool allow_duplication,
int (*compare_func)(const void *, const void *))
{
ctx->element_size = element_size;
ctx->allow_duplication = allow_duplication;
ctx->compare_func = compare_func;
}
static char *sorted_array_bsearch(SortedArrayContext *ctx, char *base,
const int count, const void *elt, int *insert_pos)
{
int low;
int high;
int mid;
int compr;
char *current;
*insert_pos = 0;
low = 0;
high = count - 1;
while (low <= high) {
mid = (low + high) / 2;
current = base + ctx->element_size * mid;
compr = ctx->compare_func(current, elt);
if (compr < 0) {
low = mid + 1;
*insert_pos = low;
} else if (compr == 0) {
*insert_pos = mid;
return current;
} else {
high = mid - 1;
*insert_pos = mid;
}
}
return NULL;
}
int sorted_array_insert(SortedArrayContext *ctx,
void *base, int *count, const void *elt)
{
char *current;
if (*count == 0 || ctx->compare_func((char *)base +
ctx->element_size * (*count - 1), elt) < 0)
{ //fast path
current = (char *)base + ctx->element_size * (*count);
} else {
int insert_pos;
int move_count;
char *found;
char *end;
found = sorted_array_bsearch(ctx, base, *count, elt, &insert_pos);
if (found != NULL) {
if (!ctx->allow_duplication) {
return EEXIST;
}
found += ctx->element_size;
end = (char *)base + ctx->element_size * (*count);
while (found < end && ctx->compare_func(found, elt) == 0) {
insert_pos++;
found += ctx->element_size;
}
}
current = (char *)base + ctx->element_size * insert_pos;
move_count = *count - insert_pos;
if (move_count > 0) {
memmove((char *)base + ctx->element_size * (insert_pos + 1),
current, ctx->element_size * move_count);
}
}
switch (ctx->element_size) {
case 1:
*current = *((char *)elt);
break;
case 2:
*((short *)current) = *((short *)elt);
break;
case 4:
*((int32_t *)current) = *((int32_t *)elt);
break;
case 8:
*((int64_t *)current) = *((int64_t *)elt);
break;
default:
memcpy(current, elt, ctx->element_size);
break;
}
(*count)++;
return 0;
}
void sorted_array_delete_by_index(SortedArrayContext *ctx,
void *base, int *count, const int index)
{
int move_count;
char *start;
start = (char *)base + ctx->element_size * index;
move_count = *count - (index + 1);
if (move_count > 0) {
memmove(start, start + ctx->element_size,
ctx->element_size * move_count);
}
(*count)--;
}
int sorted_array_delete(SortedArrayContext *ctx,
void *base, int *count, const void *elt)
{
int move_count;
struct {
char *current;
char *start;
char *end;
} found;
char *array_end;
if ((found.current=bsearch(elt, base, *count, ctx->element_size,
ctx->compare_func)) == NULL)
{
return ENOENT;
}
array_end = (char *)base + ctx->element_size * (*count);
if (ctx->allow_duplication) {
found.start = found.current;
while (found.start > (char *)base && ctx->compare_func(
found.start - ctx->element_size, elt) == 0)
{
found.start -= ctx->element_size;
}
found.end = found.current + ctx->element_size;
while (found.end < array_end && ctx->compare_func(
found.end, elt) == 0)
{
found.end += ctx->element_size;
}
*count -= (found.end - found.start) / ctx->element_size;
} else {
found.start = found.current;
found.end = found.start + ctx->element_size;
(*count)--;
}
move_count = (array_end - found.end) / ctx->element_size;
if (move_count > 0) {
memmove(found.start, found.end, ctx->
element_size * move_count);
}
return 0;
}

View File

@ -1,112 +0,0 @@
/*
* 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 GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef SORTED_ARRAY_H
#define SORTED_ARRAY_H
#include "array_allocator.h"
typedef struct sorted_array_context
{
int element_size;
bool allow_duplication;
int (*compare_func)(const void *, const void *);
} SortedArrayContext;
#ifdef __cplusplus
extern "C" {
#endif
/** init the context for sorted array
* parameters:
* ctx: the context to init
* element_size: the size of one array element
* allow_duplication: if allow duplication
* compare_func: the compare function (comparator)
* return: none
*/
void sorted_array_init(SortedArrayContext *ctx,
const int element_size, const bool allow_duplication,
int (*compare_func)(const void *, const void *));
/** insert an element into the sorted array
* parameters:
* ctx: the context for sorted array
* base: the pointer of the sorted array (the first array element)
* count: the count of the sorted array (for input and output)
* elt: the element to insert
* return: 0 for success, != 0 for error
*/
int sorted_array_insert(SortedArrayContext *ctx,
void *base, int *count, const void *elt);
/** delete an element from the sorted array
* parameters:
* ctx: the context for sorted array
* base: the pointer of the sorted array (the first array element)
* count: the count of the sorted array (for input and output)
* elt: the element to delete
* return: 0 for success, != 0 for error
*/
int sorted_array_delete(SortedArrayContext *ctx,
void *base, int *count, const void *elt);
/** delete an element by index
* parameters:
* ctx: the context for sorted array
* base: the pointer of the sorted array (the first array element)
* count: the count of the sorted array (for input and output)
* index: the element index to delete
* return: 0 for success, != 0 for error
*/
void sorted_array_delete_by_index(SortedArrayContext *ctx,
void *base, int *count, const int index);
/** find element from the sorted array
* parameters:
* ctx: the context for sorted array
* base: the pointer of the sorted array (the first array element)
* count: the count of the sorted array
* key: the element to find
* return: 0 for success, != 0 for error
*/
static inline void *sorted_array_find(SortedArrayContext *ctx,
void *base, const int count, const void *key)
{
return bsearch(key, base, count, ctx->
element_size, ctx->compare_func);
}
#define sorted_i64_array_init(ctx, allow_duplication) \
sorted_array_init(ctx, sizeof(int64_t), allow_duplication, \
(int (*)(const void *, const void *))array_compare_element_int64)
#define sorted_i32_array_init(ctx, allow_duplication) \
sorted_array_init(ctx, sizeof(int32_t), allow_duplication, \
(int (*)(const void *, const void *))array_compare_element_int32)
#define sorted_id_name_array_init(ctx, allow_duplication) \
sorted_array_init(ctx, sizeof(id_name_pair_t), allow_duplication, \
(int (*)(const void *, const void *)) \
array_compare_element_id_name)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,194 +0,0 @@
/*
* 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/>.
*/
//sorted_queue.c
#include "pthread_func.h"
#include "sorted_queue.h"
int sorted_queue_init(struct sorted_queue *sq, const int dlink_offset,
int (*push_compare_func)(const void *data1, const void *data2),
int (*pop_compare_func)(const void *data, const
void *less_equal, void *arg), void *arg)
{
int result;
if ((result=init_pthread_lock_cond_pair(&sq->lcp)) != 0) {
return result;
}
FC_INIT_LIST_HEAD(&sq->head);
sq->dlink_offset = dlink_offset;
sq->arg = arg;
sq->push_compare_func = push_compare_func;
sq->pop_compare_func = pop_compare_func;
return 0;
}
void sorted_queue_destroy(struct sorted_queue *sq)
{
destroy_pthread_lock_cond_pair(&sq->lcp);
}
void sorted_queue_push_ex(struct sorted_queue *sq, void *data, bool *notify)
{
struct fc_list_head *dlink;
struct fc_list_head *current;
dlink = FC_SORTED_QUEUE_DLINK_PTR(sq, data);
PTHREAD_MUTEX_LOCK(&sq->lcp.lock);
if (fc_list_empty(&sq->head)) {
fc_list_add(dlink, &sq->head);
*notify = true;
} else {
if (sq->push_compare_func(data, FC_SORTED_QUEUE_DATA_PTR(
sq, sq->head.prev)) >= 0)
{
fc_list_add_tail(dlink, &sq->head);
*notify = false;
} else if (sq->push_compare_func(data, FC_SORTED_QUEUE_DATA_PTR(
sq, sq->head.next)) < 0)
{
fc_list_add(dlink, &sq->head);
*notify = true;
} else {
current = sq->head.prev->prev;
while (sq->push_compare_func(data, FC_SORTED_QUEUE_DATA_PTR(
sq, current)) < 0)
{
current = current->prev;
}
fc_list_add_after(dlink, current);
*notify = false;
}
}
PTHREAD_MUTEX_UNLOCK(&sq->lcp.lock);
}
void *sorted_queue_pop_ex(struct sorted_queue *sq,
void *less_equal, const bool blocked)
{
void *data;
struct fc_list_head *current;
PTHREAD_MUTEX_LOCK(&sq->lcp.lock);
do {
if (fc_list_empty(&sq->head)) {
if (!blocked) {
data = NULL;
break;
}
pthread_cond_wait(&sq->lcp.cond,
&sq->lcp.lock);
if (fc_list_empty(&sq->head)) {
data = NULL;
break;
}
}
current = sq->head.next;
data = FC_SORTED_QUEUE_DATA_PTR(sq, current);
if (sq->pop_compare_func(data, less_equal, sq->arg) <= 0) {
fc_list_del_init(current);
} else {
data = NULL;
}
} while (0);
PTHREAD_MUTEX_UNLOCK(&sq->lcp.lock);
return data;
}
void sorted_queue_pop_to_chain_ex(struct sorted_queue *sq,
void *less_equal, struct fc_list_head *head,
const bool blocked)
{
struct fc_list_head *current;
PTHREAD_MUTEX_LOCK(&sq->lcp.lock);
do {
if (fc_list_empty(&sq->head)) {
if (!blocked) {
FC_INIT_LIST_HEAD(head);
break;
}
pthread_cond_wait(&sq->lcp.cond,
&sq->lcp.lock);
}
if (fc_list_empty(&sq->head)) {
FC_INIT_LIST_HEAD(head);
} else {
current = sq->head.next;
if (sq->pop_compare_func(FC_SORTED_QUEUE_DATA_PTR(
sq, current), less_equal, sq->arg) <= 0)
{
head->next = current;
current->prev = head;
current = current->next;
while (current != &sq->head && sq->pop_compare_func(
FC_SORTED_QUEUE_DATA_PTR(sq, current),
less_equal, sq->arg) <= 0)
{
current = current->next;
}
head->prev = current->prev;
current->prev->next = head;
if (current == &sq->head) {
FC_INIT_LIST_HEAD(&sq->head);
} else {
sq->head.next = current;
current->prev = &sq->head;
}
} else {
FC_INIT_LIST_HEAD(head);
}
}
} while (0);
PTHREAD_MUTEX_UNLOCK(&sq->lcp.lock);
}
int sorted_queue_free_chain(struct sorted_queue *sq,
struct fast_mblock_man *mblock, struct fc_list_head *head)
{
struct fast_mblock_node *previous;
struct fast_mblock_node *current;
struct fast_mblock_chain chain;
struct fc_list_head *node;
if (fc_list_empty(&sq->head)) {
return 0;
}
node = head->next;
chain.head = previous = fast_mblock_to_node_ptr(
FC_SORTED_QUEUE_DATA_PTR(sq, node));
node = node->next;
while (node != head) {
current = fast_mblock_to_node_ptr(FC_SORTED_QUEUE_DATA_PTR(sq, node));
previous->next = current;
previous = current;
node = node->next;
}
previous->next = NULL;
chain.tail = previous;
return fast_mblock_batch_free(mblock, &chain);
}

View File

@ -1,128 +0,0 @@
/*
* 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/>.
*/
//sorted_queue.h
#ifndef _FC_SORTED_QUEUE_H
#define _FC_SORTED_QUEUE_H
#include "fast_mblock.h"
#include "fc_list.h"
#include "pthread_func.h"
struct sorted_queue
{
struct fc_list_head head;
pthread_lock_cond_pair_t lcp;
int dlink_offset;
void *arg;
int (*push_compare_func)(const void *data1, const void *data2);
int (*pop_compare_func)(const void *data,
const void *less_equal, void *arg);
};
#define FC_SORTED_QUEUE_DLINK_PTR(sq, data) \
((void *)(((char *)data) + (sq)->dlink_offset))
#define FC_SORTED_QUEUE_DATA_PTR(sq, dlink) \
((void *)((char *)(dlink) - (sq)->dlink_offset))
#ifdef __cplusplus
extern "C" {
#endif
int sorted_queue_init(struct sorted_queue *sq, const int dlink_offset,
int (*push_compare_func)(const void *data1, const void *data2),
int (*pop_compare_func)(const void *data, const
void *less_equal, void *arg), void *arg);
void sorted_queue_destroy(struct sorted_queue *sq);
static inline void sorted_queue_terminate(struct sorted_queue *sq)
{
pthread_cond_signal(&sq->lcp.cond);
}
static inline void sorted_queue_terminate_all(
struct sorted_queue *sq, const int count)
{
int i;
for (i=0; i<count; i++) {
pthread_cond_signal(&(sq->lcp.cond));
}
}
//notify by the caller
void sorted_queue_push_ex(struct sorted_queue *sq, void *data, bool *notify);
static inline void sorted_queue_push(struct sorted_queue *sq, void *data)
{
bool notify;
sorted_queue_push_ex(sq, data, &notify);
if (notify) {
pthread_cond_signal(&(sq->lcp.cond));
}
}
static inline void sorted_queue_push_silence(
struct sorted_queue *sq, void *data)
{
bool notify;
sorted_queue_push_ex(sq, data, &notify);
}
void *sorted_queue_pop_ex(struct sorted_queue *sq,
void *less_equal, const bool blocked);
#define sorted_queue_pop(sq, less_equal) \
sorted_queue_pop_ex(sq, less_equal, true)
#define sorted_queue_try_pop(sq, less_equal) \
sorted_queue_pop_ex(sq, less_equal, false)
void sorted_queue_pop_to_chain_ex(struct sorted_queue *sq,
void *less_equal, struct fc_list_head *head,
const bool blocked);
#define sorted_queue_pop_to_chain(sq, less_equal, head) \
sorted_queue_pop_to_chain_ex(sq, less_equal, head, true)
#define sorted_queue_try_pop_to_chain(sq, less_equal, head) \
sorted_queue_pop_to_chain_ex(sq, less_equal, head, false)
static inline bool sorted_queue_empty(struct sorted_queue *sq)
{
return fc_list_empty(&sq->head);
}
int sorted_queue_free_chain(struct sorted_queue *sq,
struct fast_mblock_man *mblock, struct fc_list_head *head);
static inline void sorted_queue_lock(struct sorted_queue *sq)
{
PTHREAD_MUTEX_LOCK(&sq->lcp.lock);
}
static inline void sorted_queue_unlock(struct sorted_queue *sq)
{
PTHREAD_MUTEX_UNLOCK(&sq->lcp.lock);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,116 +0,0 @@
/*
* 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
}

View File

@ -1,59 +0,0 @@
/*
* 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

View File

@ -72,11 +72,7 @@ int get_sys_total_mem_size(int64_t *mem_size)
size_t len;
mib[0] = CTL_HW;
#ifdef DARWIN
mib[1] = HW_MEMSIZE;
#else
mib[1] = HW_PHYSMEM;
#endif
len = sizeof(*mem_size);
if (sysctl(mib, 2, mem_size, &len, NULL, 0) != 0)
{
@ -194,54 +190,11 @@ int get_boot_time(struct timeval *boot_time)
#define SET_MNT_FIELDS(left, fstypename, mntfromname, mntonname) \
do { \
fc_safe_strcpy(left.f_fstypename, fstypename); \
fc_safe_strcpy(left.f_mntfromname, mntfromname); \
fc_safe_strcpy(left.f_mntonname, mntonname); \
snprintf(left.f_fstypename, sizeof(left.f_fstypename), "%s", fstypename); \
snprintf(left.f_mntfromname, sizeof(left.f_mntfromname), "%s", mntfromname); \
snprintf(left.f_mntonname, sizeof(left.f_mntonname), "%s", mntonname); \
} 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,
const int size, int *count)
{
@ -283,14 +236,15 @@ int get_mounted_filesystems(struct fast_statfs *stats,
mntfromname = strsep(&p, " \t");
mntonname = strsep(&p, " \t");
fstypename = strsep(&p, " \t");
toLowercase(fstypename);
if (get_device_type(fstypename, &stats[*count].device_type) == 0)
{
fc_safe_strcpy(stats[*count].f_mntfromname, mntfromname);
fc_safe_strcpy(stats[*count].f_mntonname, mntonname);
fc_safe_strcpy(stats[*count].f_fstypename, fstypename);
(*count)++;
}
snprintf(stats[*count].f_mntfromname,
sizeof(stats[*count].f_mntfromname), "%s", mntfromname);
snprintf(stats[*count].f_mntonname,
sizeof(stats[*count].f_mntonname), "%s", mntonname);
snprintf(stats[*count].f_fstypename,
sizeof(stats[*count].f_fstypename), "%s", fstypename);
(*count)++;
}
fclose(fp);
@ -321,7 +275,7 @@ int get_mounted_filesystems(struct fast_statfs *stats,
int i;
mnts = NULL;
*count = getmntinfo(&mnts, MNT_NOWAIT);
*count = getmntinfo(&mnts, 0);
if (*count == 0)
{
result = errno != 0 ? errno : EPERM;
@ -348,7 +302,6 @@ int get_mounted_filesystems(struct fast_statfs *stats,
#ifdef HAVE_FILE_SYSTEM_ID
stats[i].f_fsid = mnts[i].f_fsid;
#endif
stats[i].device_type = fast_device_type_unkown;
SET_MNT_FIELDS(stats[i], mnts[i].f_fstypename,
mnts[i].f_mntfromname, mnts[i].f_mntonname);
}
@ -361,114 +314,6 @@ int get_mounted_filesystems(struct fast_statfs *stats,
#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)
typedef struct fast_process_array {
@ -768,7 +613,7 @@ int get_processes(struct fast_process_info **processes, int *count)
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ALL;
mib[3] = 0;
mib[3] = 0;
size = 0;
if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
{
@ -838,7 +683,8 @@ int get_processes(struct fast_process_info **processes, int *count)
for (i=0; i<nproc; i++)
{
process->field_count = 9;
fc_safe_strcpy(process->comm, procs[i].ki_comm);
snprintf(process->comm, sizeof(process->comm),
"%s", procs[i].ki_comm);
process->pid = procs[i].ki_pid;
process->ppid = procs[i].ki_ppid;
process->starttime = procs[i].ki_start;
@ -930,6 +776,7 @@ int get_sysinfo(struct fast_sysinfo *info)
page_size = sysconf(_SC_PAGESIZE);
info->freeram = vm.t_free * page_size;
info->sharedram = vm.t_rmshr * page_size;
//info->bufferram = vm. //TODO:
}
#endif
@ -997,7 +844,7 @@ int get_device_block_size(const char *device, int *block_size)
int fd;
size_t bs;
if ((fd=open(device, O_RDONLY | O_CLOEXEC)) < 0) {
if ((fd=open(device, O_RDONLY)) < 0) {
result = errno != 0 ? errno : ENOENT;
logError("file: "__FILE__", line: %d, "
"open device %s fail, errno: %d, error info: %s",
@ -1037,10 +884,9 @@ static int get_block_size_by_write(const char *path, int *block_size)
return result;
}
fc_combine_full_filename(path, ".blksize-test.tmp", tmp_filename);
if ((fd=open(tmp_filename, O_WRONLY | O_CREAT |
O_DIRECT | O_CLOEXEC, 0755)) < 0)
{
snprintf(tmp_filename, sizeof(tmp_filename),
"%s/.blksize-test.tmp", path);
if ((fd=open(tmp_filename, O_WRONLY | O_CREAT | O_DIRECT)) < 0) {
result = errno != 0 ? errno : ENOENT;
logError("file: "__FILE__", line: %d, "
"open file %s fail, errno: %d, error info: %s",
@ -1110,94 +956,4 @@ int get_path_block_size(const char *path, int *block_size)
return get_block_size_by_write(path, block_size);
}
int get_groups(const pid_t pid, const gid_t gid, const int size, gid_t *list)
{
#define GROUPS_TAG_STR "\nGroups:"
#define GROUPS_TAG_LEN (sizeof(GROUPS_TAG_STR) - 1)
char filename[64];
char buff[1024];
char *p;
char *end;
int fd;
int len;
gid_t val;
int count;
sprintf(filename, "/proc/%d/status", pid);
fd = open(filename, O_RDONLY);
if (fd < 0) {
return 0;
}
len = read(fd, buff, sizeof(buff));
close(fd);
if (len <= 0) {
return 0;
}
buff[len - 1] = '\0';
if ((p=strstr(buff, GROUPS_TAG_STR)) == NULL) {
return 0;
}
p += GROUPS_TAG_LEN;
count = 0;
while (count < size) {
val = strtoul(p, &end, 10);
if (end == p) {
break;
}
if (val != gid) {
list[count++] = val;
}
p = end;
}
return count;
}
#elif defined(OS_FREEBSD)
int get_groups(const pid_t pid, const gid_t gid, const int size, gid_t *list)
{
int mibpath[4];
struct kinfo_proc kp;
size_t kplen;
int count;
int i;
#if defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PID)
mibpath[0] = CTL_KERN;
mibpath[1] = KERN_PROC;
mibpath[2] = KERN_PROC_PID;
#else
kplen = 4;
sysctlnametomib("kern.proc.pid", mibpath, &kplen);
#endif
mibpath[3] = pid;
kplen = sizeof(kp);
memset(&kp,0,sizeof(kp));
if (sysctl(mibpath, 4, &kp, &kplen, NULL, 0) != 0) {
return 0;
}
#if defined(DARWIN)
#define ki_ngroups kp_eproc.e_ucred.cr_ngroups
#define ki_groups kp_eproc.e_ucred.cr_groups
#endif
count = 0;
for (i=0; i<kp.ki_ngroups && count<size; i++) {
if (kp.ki_groups[i] != gid) {
list[count++] = kp.ki_groups[i];
}
}
return count;
}
#endif

View File

@ -42,14 +42,6 @@ extern "C" {
#define MNAMELEN 128
#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 {
long f_type; /* type of file system (see below) */
long f_bsize; /* optimal transfer block size */
@ -64,7 +56,6 @@ extern "C" {
char f_fstypename[MFSNAMELEN]; /* fs type name */
char f_mntfromname[MNAMELEN]; /* mounted file system */
char f_mntonname[MNAMELEN]; /* directory on which mounted */
FastDeviceType device_type;
} FastStatFS;
#if defined(OS_LINUX) || defined(OS_FREEBSD)
@ -129,41 +120,24 @@ extern "C" {
} FastProcessInfo;
#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
* parameters:
* mem_size: return the total memory size
* return: error no, 0 success, != 0 fail
* return: error no , 0 success, != 0 fail
*/
int get_sys_total_mem_size(int64_t *mem_size);
/** get system CPU count
* parameters:
* return: error no, 0 success, != 0 fail
* return: error no , 0 success, != 0 fail
*/
int get_sys_cpu_count();
/** get system boot time
* parameters:
* uptime: store the up time
* return: error no, 0 success, != 0 fail
* return: error no , 0 success, != 0 fail
*/
int get_boot_time(struct timeval *boot_time);
@ -172,32 +146,17 @@ int get_boot_time(struct timeval *boot_time);
* stats: the stat array
* size: max size of the array
* count: return the count of the array
* return: error no, 0 success, != 0 fail
* return: error no , 0 success, != 0 fail
*/
int get_mounted_filesystems(struct fast_statfs *stats,
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)
/** get processes
* parameters:
* processes: return the processes
* count: return the count of the processes
* return: error no, 0 success, != 0 fail
* return: error no , 0 success, != 0 fail
*/
int get_processes(struct fast_process_info **processes, int *count);
@ -205,8 +164,6 @@ int get_sysinfo(struct fast_sysinfo *info);
int get_kernel_version(Version *version);
int get_groups(const pid_t pid, const gid_t gid, const int size, gid_t *list);
#ifdef OS_LINUX
int get_device_block_size(const char *device, int *block_size);
int get_path_block_size(const char *path, int *block_size);

View File

@ -1,8 +1,8 @@
.SUFFIXES: .c .o
COMPILE = $(CC) -g -O3 -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -g -DDEBUG_FLAG
INC_PATH = $(INCS)
LIB_PATH = -lfastcommon $(LIBS)
COMPILE = $(CC) -g -O3 -Wall -D_FILE_OFFSET_BITS=64 -g -DDEBUG_FLAG
INC_PATH = -I/usr/local/include
LIB_PATH = -lfastcommon -lpthread
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 \
@ -10,11 +10,9 @@ ALL_PRGS = test_allocator test_skiplist test_multi_skiplist test_mblock test_blo
test_json_parser test_pthread_lock test_uniq_skiplist test_split_string \
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_queue_perf test_normalize_path test_sorted_array test_sorted_queue \
test_thread_local test_memcpy test_fast_buffer mblock_benchmark cpool_benchmark
test_queue_perf test_normalize_path
all: $(ALL_PRGS)
.c:
$(COMPILE) -o $@ $< $(LIB_PATH) $(INC_PATH)
.c.o:

View File

@ -1,211 +0,0 @@
/*
* 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(&params, 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, &params)) != 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;
}

View File

@ -1,125 +0,0 @@
/*
* 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;
}

View File

@ -30,7 +30,6 @@
static bool g_continue_flag = true;
static int64_t produce_count = 0;
static int64_t consume_count = 0;
static struct fast_task_queue free_queue;
static struct fast_blocked_queue blocked_queue;
#define MAX_USLEEP 10000
@ -52,7 +51,7 @@ void *producer_thread(void *arg)
printf("produce count: %"PRId64"\n", count);
}
pTask = free_queue_pop(&free_queue);
pTask = free_queue_pop();
if (pTask != NULL) {
blocked_queue_push(&blocked_queue, pTask);
}
@ -100,7 +99,7 @@ int main(int argc, char *argv[])
return errno;
}
result = free_queue_init(&free_queue, 1024, min_buff_size,
result = free_queue_init(1024, min_buff_size, \
max_buff_size, arg_size);
if (result != 0) {
return result;

View File

@ -1,331 +0,0 @@
/*
* 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;
}

View File

@ -25,7 +25,6 @@
#include <sys/file.h>
#include "fastcommon/logger.h"
#include "fastcommon/shared_func.h"
#include "fastcommon/pthread_func.h"
#define OneArgument(a) printf("One Argument func is called!\n")
#define TwoArguments(a, b) printf("Two Arguments func is called!\n")
@ -37,6 +36,7 @@ static inline int get_lock_info(int fd, struct flock *lock)
{
int result;
memset(lock, 0, sizeof(struct flock));
lock->l_whence = SEEK_SET;
lock->l_type = F_WRLCK;
lock->l_pid = getpid();
@ -53,69 +53,6 @@ static inline int get_lock_info(int fd, struct flock *lock)
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[])
{
#define SEEK_POS (2 * 1024)
@ -124,15 +61,12 @@ int main(int argc, char *argv[])
int result;
int sleep_seconds;
int n = 0;
pthread_t tid;
char buf[1024];
struct flock lock;
Macro(1);
Macro(1, 2);
Macro(1, 2, 3);
printf("%0*d\n", 3, 1);
if (argc < 2) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
return 1;
@ -146,7 +80,7 @@ int main(int argc, char *argv[])
sleep_seconds = 1;
}
fd = open(filename, O_RDWR | O_CREAT | O_CLOEXEC, 0644);
fd = open(filename, O_RDWR | O_CREAT, 0644);
if (fd < 0) {
result = errno != 0 ? errno : EIO;
logError("file: "__FILE__", line: %d, "
@ -157,61 +91,6 @@ int main(int argc, char *argv[])
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) {
logError("file: "__FILE__", line: %d, "
"flock file %s fail, "

View File

@ -32,7 +32,6 @@ int main(int argc, char *argv[])
int fd;
int result;
int n;
int i;
char buf[1024];
if (argc < 2) {
@ -51,7 +50,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_APPEND, 0644);
fd = open(filename, O_RDWR | O_CREAT, 0644);
if (fd < 0) {
result = errno != 0 ? errno : EIO;
logError("file: "__FILE__", line: %d, " \
@ -70,8 +69,7 @@ int main(int argc, char *argv[])
return errno != 0 ? errno : EIO;
}
for (i=0; i<5; i++) {
if (lseek(fd, 0, SEEK_SET) < 0) {
if (lseek(fd, SEEK_POS, SEEK_SET) < 0) {
logError("file: "__FILE__", line: %d, " \
"lseek file %s fail, " \
"errno: %d, error info: %s", __LINE__, \
@ -88,7 +86,6 @@ int main(int argc, char *argv[])
return errno != 0 ? errno : EIO;
}
printf("write bytes: %d\n", n);
}
if (lseek(fd, 0, SEEK_SET) < 0) {
logError("file: "__FILE__", line: %d, " \

View File

@ -28,16 +28,11 @@
int main(int argc, char *argv[])
{
const bool decode_use_mpool = false;
const int alloc_size_once = 1024;
const int init_buff_size = 1024;
int result;
int result;
int json_type;
fc_json_context_t json_ctx;
char error_info[256];
string_t input;
BufferInfo buffer;
const BufferInfo *output;
string_t output;
if (argc < 2) {
fprintf(stderr, "Usage: %s <json_string | json_array | json_map>\n",
@ -47,70 +42,52 @@ int main(int argc, char *argv[])
log_init();
if ((result=fc_init_json_context_ex(&json_ctx, decode_use_mpool,
alloc_size_once, init_buff_size, error_info,
sizeof(error_info))) != 0)
{
return result;
}
memset(&buffer, 0, sizeof(buffer));
input.str = argv[1];
input.len = strlen(input.str);
json_type = fc_detect_json_type(&input);
json_type = detect_json_type(&input);
if (json_type == FC_JSON_TYPE_ARRAY) {
const fc_json_array_t *array;
json_array_t array;
if ((array=fc_decode_json_array(&json_ctx, &input)) == NULL) {
if ((result=decode_json_array(&input, &array, error_info,
sizeof(error_info))) != 0)
{
fprintf(stderr, "decode json array fail, %s\n", error_info);
return fc_json_parser_get_error_no(&json_ctx);
return result;
}
if (decode_use_mpool) {
output = fc_encode_json_array(&json_ctx,
array->elements, array->count);
result = fc_json_parser_get_error_no(&json_ctx);
} else {
output = &buffer;
result = fc_encode_json_array_ex(&json_ctx,
array->elements, array->count, &buffer);
}
if (result != 0) {
if ((result=encode_json_array(&array, &output,
error_info, sizeof(error_info))) != 0)
{
fprintf(stderr, "encode json array fail, %s\n", error_info);
return result;
}
printf("%.*s\n", output->length, output->buff);
fc_free_buffer(&buffer);
printf("%s\n", output.str);
free_json_string(&output);
free_json_array(&array);
} else if (json_type == FC_JSON_TYPE_MAP) {
const fc_json_map_t *map;
json_map_t map;
if ((map=fc_decode_json_map(&json_ctx, &input)) == NULL) {
if ((result=decode_json_map(&input, &map, error_info,
sizeof(error_info))) != 0)
{
fprintf(stderr, "decode json map fail, %s\n", error_info);
return fc_json_parser_get_error_no(&json_ctx);
return result;
}
if (decode_use_mpool) {
output = fc_encode_json_map(&json_ctx,
map->elements, map->count);
result = fc_json_parser_get_error_no(&json_ctx);
} else {
output = &buffer;
result = fc_encode_json_map_ex(&json_ctx,
map->elements, map->count, &buffer);
}
if (result != 0) {
if ((result=encode_json_map(&map, &output,
error_info, sizeof(error_info))) != 0)
{
fprintf(stderr, "encode json map fail, %s\n", error_info);
return result;
}
printf("%.*s\n", output->length, output->buff);
fc_free_buffer(&buffer);
printf("%s\n", output.str);
free_json_string(&output);
free_json_map(&map);
} else {
fprintf(stderr, "string\n");
}
fc_destroy_json_context(&json_ctx);
return 0;
}

View File

@ -22,7 +22,6 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include "fastcommon/logger.h"
int main(int argc, char *argv[])
@ -37,15 +36,6 @@ int main(int argc, char *argv[])
log_take_over_stdout();
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, "
"use_file_write_lock: %d\n", (int)sizeof(LogContext),
g_log_context.time_precision,
@ -56,7 +46,7 @@ int main(int argc, char *argv[])
"by log_it_ex, timestamp: %d", (int)time(NULL));
len = sprintf(buff, "this is by log_it_ex1, "
"timestamp: %ld", (long)time(NULL));
"timestamp: %d", (int)time(NULL));
log_it_ex1(&g_log_context, LOG_INFO, buff, len);
return 0;

View File

@ -64,8 +64,6 @@ int main(int argc, char *argv[])
volatile bool continue_flag = true;
FastIFConfig if_configs[32];
struct fast_statfs stats[32];
char *path;
FastStatFS statfs;
start_time = get_current_time_ms();
srand(time(NULL));
@ -88,19 +86,10 @@ int main(int argc, char *argv[])
printf("mounted fs count: %d\n", count);
for (i=0; i<count; i++) {
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_type, stats[i].f_bsize,
stats[i].f_blocks, stats[i].f_bfree, stats[i].f_bavail,
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));
stats[i].f_mntfromname, stats[i].f_mntonname, stats[i].f_fstypename,
stats[i].f_type, stats[i].f_bsize, stats[i].f_blocks,
stats[i].f_bfree, stats[i].f_bavail, stats[i].f_files,
stats[i].f_ffree);
}
#if defined(OS_LINUX) || defined(OS_FREEBSD)
@ -150,6 +139,31 @@ int main(int argc, char *argv[])
#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();
scheduleArray.entries = scheduleEntries;
scheduleArray.count = 0;
@ -162,7 +176,7 @@ int main(int argc, char *argv[])
printf("cpu count: %d\n", get_sys_cpu_count());
end_time = get_current_time_ms();
logInfo("time used: %d ms\n", (int)(end_time - start_time));
logInfo("time used: %d ms", (int)(end_time - start_time));
fast_mblock_manager_init();
@ -182,33 +196,19 @@ int main(int argc, char *argv[])
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++)
{
fast_mblock_free_object(objs[i].mblock, objs[i].obj);
fast_mblock_free_object(&mblock1, objs[i]);
}
*/
obj1 = fast_mblock_alloc_object(&mblock1);
obj2 = fast_mblock_alloc_object(&mblock1);
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_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);
obj2 = fast_mblock_alloc_object(&mblock2);
fast_mblock_delay_free_object(&mblock2, obj1, 20);
@ -220,13 +220,6 @@ int main(int argc, char *argv[])
fast_mblock_reclaim(&mblock1, 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);
sleep(31);
@ -238,25 +231,11 @@ int main(int argc, char *argv[])
fast_mblock_reclaim(&mblock1, 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);
obj1 = fast_mblock_alloc_object(&mblock1);
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_destroy(&mblock1);

View File

@ -1,54 +0,0 @@
/*
* 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 "fastcommon/shared_func.h"
#define BUFF_SIZE (4 * 1024 * 1024)
int main(int argc, char *argv[])
{
char *buff1;
char *buff2;
char *dest;
int64_t start_time, end_time;
char time_buff[32];
int i;
buff1 = malloc(BUFF_SIZE);
buff2 = malloc(BUFF_SIZE);
dest = malloc(BUFF_SIZE);
memset(buff1, 'a', BUFF_SIZE);
memset(buff2, 'b', BUFF_SIZE);
memset(dest, 0, BUFF_SIZE);
start_time = get_current_time_us();
for (i=0; i<16 * 1024; i++) {
if (i % 2 == 0) {
memcpy(buff2, buff1, BUFF_SIZE);
} else {
memcpy(dest, buff2, BUFF_SIZE);
}
}
end_time = get_current_time_us();
printf("time used: %s us\n", long_to_comma_str(
end_time - start_time, time_buff));
return 0;
}

View File

@ -27,8 +27,8 @@
int main(int argc, char *argv[])
{
char full_filename[PATH_MAX];
string_t from;
string_t filename;
const char *from;
const char *filename;
int filename_len;
int result;
@ -38,14 +38,12 @@ int main(int argc, char *argv[])
}
log_init();
FC_SET_STRING(from, argv[1]);
FC_SET_STRING(filename, argv[2]);
filename_len = normalize_path_ex(&from, &filename,
from = argv[1];
filename = argv[2];
filename_len = normalize_path_ex(from, filename,
full_filename, sizeof(full_filename),
NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS);
printf("%s => {len1: %d, len2: %d}\n", full_filename,
(int)strlen(full_filename), filename_len);
printf("%s\n", full_filename);
if (IS_URL_RESOURCE(full_filename)) {
const int connect_timeout = 2;

View File

@ -47,7 +47,7 @@ void *producer_thread(void *arg)
while (g_continue_flag && count < LOOP_COUNT) {
qinfo.head = qinfo.tail = NULL;
node = fast_mblock_batch_alloc1(
node = fast_mblock_batch_alloc(
&record_allocator, BATCH_SIZE);
if (node == NULL) {
g_continue_flag = false;
@ -84,56 +84,6 @@ static void sigQuitHandler(int 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[])
{
const int alloc_elements_once = 8 * 1024;
@ -157,9 +107,6 @@ int main(int argc, char *argv[])
log_init();
g_log_context.log_level = LOG_DEBUG;
test_remove();
return 0;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_handler = sigQuitHandler;

View File

@ -112,7 +112,7 @@ int main(int argc, char *argv[])
setup_mblock_stat_task();
if ((result=fast_buffer_init1(&buffer, 1024)) != 0) {
if ((result=fast_buffer_init_ex(&buffer, 1024)) != 0) {
return result;
}
fc_server_to_config_string(&ctx, &buffer);

View File

@ -1,216 +0,0 @@
/*
* 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/time.h>
#include <assert.h>
#include "fastcommon/logger.h"
#include "fastcommon/shared_func.h"
#include "fastcommon/array_allocator.h"
#include "fastcommon/sorted_array.h"
#define ELEMENT_COUNT 64 * 1024
static bool silence;
static int test_i64()
{
const int min_bits = 2;
const int max_bits = 16;
const bool allow_duplication = false;
int result;
int i;
int index;
int last_index;
int64_t tmp;
int64_t start_time;
ArrayAllocatorContext allocator_ctx;
SortedArrayContext sarray_ctx;
I64Array *input;
I64Array *output;
start_time = get_current_time_us();
sorted_i64_array_init(&sarray_ctx, allow_duplication);
if ((result=i64_array_allocator_init(&allocator_ctx,
min_bits, max_bits)) != 0)
{
return result;
}
if ((input=i64_array_allocator_alloc(&allocator_ctx,
ELEMENT_COUNT)) == NULL)
{
return ENOMEM;
}
if ((output=i64_array_allocator_alloc(&allocator_ctx,
ELEMENT_COUNT)) == NULL)
{
return ENOMEM;
}
if (!silence) {
printf("input alloc count: %d, output alloc count: %d\n",
input->alloc, output->alloc);
}
input->count = ELEMENT_COUNT;
for (i=0; i<input->count; i++) {
input->elts[i] = i + 1;
}
last_index = ELEMENT_COUNT - 1;
for (i=0; i<ELEMENT_COUNT / 10; i++) {
index = (int64_t)rand() * last_index / (int64_t)RAND_MAX;
tmp = input->elts[index];
input->elts[index] = input->elts[last_index - index];
input->elts[last_index - index] = tmp;
}
for (i=0; i<input->count; i++) {
sorted_array_insert(&sarray_ctx, output->elts,
&output->count, input->elts + i);
}
assert(output->count == ELEMENT_COUNT);
for (i=0; i<output->count; i++) {
assert(output->elts[i] == i + 1);
}
for (i=last_index; i>=0; i--) {
sorted_array_delete(&sarray_ctx, output->elts,
&output->count, input->elts + i);
}
assert(output->count == 0);
i64_array_allocator_free(&allocator_ctx, input);
i64_array_allocator_free(&allocator_ctx, output);
if (!silence) {
printf("test i64 time used: %"PRId64" us\n",
get_current_time_us() - start_time);
}
return 0;
}
static int test_i32()
{
const int min_bits = 2;
const int max_bits = 16;
const bool allow_duplication = false;
int result;
int i;
int index;
int last_index;
int32_t tmp;
int64_t start_time;
ArrayAllocatorContext allocator_ctx;
SortedArrayContext sarray_ctx;
I32Array *input;
I32Array *output;
start_time = get_current_time_us();
sorted_i32_array_init(&sarray_ctx, allow_duplication);
if ((result=i32_array_allocator_init(&allocator_ctx,
min_bits, max_bits)) != 0)
{
return result;
}
if ((input=i32_array_allocator_alloc(&allocator_ctx,
ELEMENT_COUNT)) == NULL)
{
return ENOMEM;
}
if ((output=i32_array_allocator_alloc(&allocator_ctx,
ELEMENT_COUNT)) == NULL)
{
return ENOMEM;
}
input->count = ELEMENT_COUNT;
for (i=0; i<input->count; i++) {
input->elts[i] = i + 1;
}
last_index = ELEMENT_COUNT - 1;
for (i=0; i<input->count; i++) {
index = (int64_t)rand() * last_index / (int64_t)RAND_MAX;
tmp = input->elts[index];
input->elts[index] = input->elts[last_index - index];
input->elts[last_index - index] = tmp;
}
for (i=0; i<input->count; i++) {
sorted_array_insert(&sarray_ctx, output->elts,
&output->count, input->elts + i);
}
assert(output->count == ELEMENT_COUNT);
for (i=0; i<output->count; i++) {
assert(output->elts[i] == i + 1);
}
for (i=last_index; i>=0; i--) {
sorted_array_delete(&sarray_ctx, output->elts,
&output->count, input->elts + i);
}
assert(output->count == 0);
i32_array_allocator_free(&allocator_ctx, input);
i32_array_allocator_free(&allocator_ctx, output);
if (!silence) {
printf("test i32 time used: %"PRId64" us\n",
get_current_time_us() - start_time);
}
return 0;
}
int main(int argc, char *argv[])
{
int result;
int ch;
srand(time(NULL));
log_init();
while ((ch=getopt(argc, argv, "s")) != -1) {
switch (ch) {
case 's':
silence = true;
break;
default:
break;
}
}
if ((result=test_i64()) != 0) {
return result;
}
if ((result=test_i32()) != 0) {
return result;
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More