From 4df1107fa3a626c13c9c0edd870de7c1fb842615 Mon Sep 17 00:00:00 2001 From: YuQing <384681@qq.com> Date: Mon, 29 May 2023 18:15:59 +0800 Subject: [PATCH] add function fc_safe_writev --- HISTORY | 3 +- src/common_define.h | 6 +++ src/shared_func.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ src/shared_func.h | 12 +++++- src/sockopt.c | 6 --- 5 files changed, 109 insertions(+), 8 deletions(-) diff --git a/HISTORY b/HISTORY index 1e6dc03..9f98889 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.67 2023-05-28 +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 @@ -7,6 +7,7 @@ Version 1.67 2023-05-28 * 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 diff --git a/src/common_define.h b/src/common_define.h index 5e92ed0..737a065 100644 --- a/src/common_define.h +++ b/src/common_define.h @@ -109,6 +109,12 @@ extern int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind); #define SYNC_LOG_BUFF_DEF_INTERVAL 10 #define TIME_NONE -1 +#if defined(IOV_MAX) && IOV_MAX > 256 +#define FC_IOV_BATCH_SIZE 256 +#else +#define FC_IOV_BATCH_SIZE IOV_MAX +#endif + #define IP_ADDRESS_SIZE 16 #define INFINITE_FILE_SIZE (256 * 1024LL * 1024 * 1024 * 1024 * 1024LL) diff --git a/src/shared_func.c b/src/shared_func.c index 8b186ad..45ec09b 100644 --- a/src/shared_func.c +++ b/src/shared_func.c @@ -2986,6 +2986,96 @@ ssize_t fc_safe_write(int fd, const char *buf, const size_t nbyte) return nbyte; } +ssize_t fc_safe_writev(int fd, const struct iovec *iov, int iovcnt) +{ + int write_bytes; + int bytes; + ssize_t total_written; + int remain_count; + int current_count; + int current_done; + int remain_len; + struct iovec *iob; + struct iovec iov_array[FC_IOV_BATCH_SIZE]; + struct iovec *iovp; + + iovp = (struct iovec *)iov; + remain_count = current_count = iovcnt; + total_written = 0; + while (remain_count > 0) + { + write_bytes = writev(fd, iovp, current_count); + if (write_bytes < 0) + { + if (errno == EINTR) + { + continue; + } + return total_written > 0 ? total_written : -1; + } else if (write_bytes == 0) { + return total_written; + } + total_written += write_bytes; + + iob = iovp; + bytes = iob->iov_len; + while (bytes < write_bytes) + { + ++iob; + bytes += iob->iov_len; + } + if (bytes == write_bytes) + { + ++iob; + if (iob < iovp + current_count) { + bytes += iob->iov_len; + } + } + + current_done = iob - iovp; + remain_count -= current_done; + if (remain_count == 0) { + break; + } + + if (current_done == current_count) //full done + { + current_count = ((remain_count <= FC_IOV_BATCH_SIZE) ? + remain_count : FC_IOV_BATCH_SIZE); + memcpy(iov_array, iov + (iovcnt - remain_count), + current_count * sizeof(struct iovec)); + iovp = iov_array; + } + else //partial done + { + if (iovp == (struct iovec *)iov) + { + current_count = ((remain_count <= FC_IOV_BATCH_SIZE) ? + remain_count : FC_IOV_BATCH_SIZE); + memcpy(iov_array, iob, current_count * + sizeof(struct iovec)); + iovp = iov_array; + } + else + { + current_count -= current_done; + iovp = iob; + } + + /* adjust the first element */ + remain_len = bytes - write_bytes; + if (remain_len < iovp->iov_len) + { + iovp->iov_base = (char *)iovp->iov_base + + (iovp->iov_len - remain_len); + iovp->iov_len = remain_len; + } + } + } + + return total_written; +} + ssize_t fc_lock_write(int fd, const char *buf, const size_t nbyte) { int lock_result; diff --git a/src/shared_func.h b/src/shared_func.h index 9fe4955..7e1ffb3 100644 --- a/src/shared_func.h +++ b/src/shared_func.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "common_define.h" #ifdef OS_LINUX #include @@ -886,7 +887,7 @@ bool isLeadingSpacesLine(const char *content, const char *current); */ bool isTrailingSpacesLine(const char *tail, const char *end); -/** write to file +/** safe write wrapper * parameters: * fd: the fd to write * buf: the buffer @@ -895,6 +896,15 @@ 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 diff --git a/src/sockopt.c b/src/sockopt.c index 6f02311..ace45f0 100644 --- a/src/sockopt.c +++ b/src/sockopt.c @@ -33,12 +33,6 @@ #define SUB_NET_TYPE_INNER_172_STR3 "inner172" #define SUB_NET_TYPE_INNER_192_STR3 "inner192" -#if defined(IOV_MAX) && IOV_MAX > 256 -#define FC_IOV_BATCH_SIZE 256 -#else -#define FC_IOV_BATCH_SIZE IOV_MAX -#endif - #if defined(OS_LINUX) || defined(OS_FREEBSD) #include #endif