diff --git a/src/Makefile.in b/src/Makefile.in
index 2dd611c..15ab52a 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -9,7 +9,7 @@ TOP_HEADERS = sf_types.h sf_global.h sf_define.h sf_nio.h sf_service.h \
sf_func.h sf_util.h sf_configs.h sf_proto.h sf_binlog_writer.h \
sf_cluster_cfg.h sf_sharding_htable.h sf_connection_manager.h \
sf_serializer.h sf_binlog_index.h sf_file_writer.h \
- sf_ordered_writer.h
+ sf_ordered_writer.h sf_iov.h
IDEMP_SERVER_HEADER = idempotency/server/server_types.h \
idempotency/server/server_channel.h \
@@ -24,7 +24,7 @@ IDEMP_CLIENT_HEADER = idempotency/client/client_types.h \
ALL_HEADERS = $(TOP_HEADERS) $(IDEMP_SERVER_HEADER) $(IDEMP_CLIENT_HEADER)
-SHARED_OBJS = sf_nio.lo sf_service.lo sf_global.lo \
+SHARED_OBJS = sf_nio.lo sf_iov.lo sf_service.lo sf_global.lo \
sf_func.lo sf_util.lo sf_configs.lo sf_proto.lo \
sf_binlog_writer.lo sf_sharding_htable.lo \
sf_cluster_cfg.lo sf_connection_manager.lo \
diff --git a/src/sf_iov.c b/src/sf_iov.c
new file mode 100644
index 0000000..6aa65c4
--- /dev/null
+++ b/src/sf_iov.c
@@ -0,0 +1,131 @@
+/*
+ * 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 .
+ */
+
+#include "fastcommon/logger.h"
+#include "fastcommon/sockopt.h"
+#include "sf_define.h"
+#include "sf_iov.h"
+
+int sf_iova_consume(SFDynamicIOVArray *iova, const int consume_len)
+{
+ struct iovec *iob;
+ int bytes;
+ int remain_len;
+ int result;
+
+ if (iova->cnt <= 0) {
+ logError("file: "__FILE__", line: %d, "
+ "invalid iov count: %d", __LINE__, iova->cnt);
+ return EINVAL;
+ }
+
+ if ((result=sf_iova_check_alloc(iova)) != 0) {
+ return result;
+ }
+
+ iob = iova->iov;
+ bytes = iob->iov_len;
+ while (bytes < consume_len) {
+ ++iob;
+ bytes += iob->iov_len;
+ }
+ if (bytes == consume_len) {
+ ++iob;
+ if (iob < (iova->iov + iova->cnt)) {
+ bytes += iob->iov_len;
+ }
+ }
+
+ iova->cnt -= (iob - iova->iov);
+ iova->iov = iob;
+ if (iova->cnt == 0) {
+ struct iovec *last;
+ last = iob - 1;
+ last->iov_base = (char *)last->iov_base + last->iov_len;
+ last->iov_len = 0;
+ } else {
+ /* adjust the first element */
+ remain_len = bytes - consume_len;
+ if (remain_len < iob->iov_len) {
+ iob->iov_base = (char *)iob->iov_base +
+ (iob->iov_len - remain_len);
+ iob->iov_len = remain_len;
+ }
+ }
+
+ return 0;
+}
+
+static inline void iova_slice(SFDynamicIOVArray *iova, const int slice_len)
+{
+ struct iovec *iob;
+ struct iovec *end;
+ int bytes;
+ int exceed_len;
+
+ bytes = 0;
+ end = iova->ptr + iova->input.cnt;
+ for (iob=iova->iov; iobiov_len;
+ if (bytes > slice_len) {
+ exceed_len = bytes - slice_len;
+ iob->iov_len -= exceed_len;
+ break;
+ } else if (bytes == slice_len) {
+ break;
+ }
+ }
+
+ iova->cnt = (iob - iova->iov) + 1;
+}
+
+int sf_iova_first_slice(SFDynamicIOVArray *iova, const int slice_len)
+{
+ int result;
+
+ if ((result=sf_iova_check_alloc(iova)) != 0) {
+ return result;
+ }
+
+ iova_slice(iova, slice_len);
+ return 0;
+}
+
+int sf_iova_next_slice(SFDynamicIOVArray *iova,
+ const int consume_len, const int slice_len)
+{
+ struct iovec *last;
+ struct iovec *origin;
+ int remain_len;
+ int result;
+
+ if ((result=sf_iova_consume(iova, consume_len)) != 0) {
+ return result;
+ }
+
+ last = iova->iov + iova->cnt - 1;
+ origin = iova->input.iov + (last - iova->ptr);
+ remain_len = ((char *)origin->iov_base + origin->iov_len) -
+ (char *)last->iov_base;
+ if (last->iov_len != remain_len) {
+ last->iov_len = remain_len;
+ if (iova->cnt == 0) {
+ iova->iov = last;
+ }
+ }
+
+ iova_slice(iova, slice_len);
+ return 0;
+}
diff --git a/src/sf_iov.h b/src/sf_iov.h
new file mode 100644
index 0000000..3e21ee9
--- /dev/null
+++ b/src/sf_iov.h
@@ -0,0 +1,82 @@
+/*
+ * 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 .
+ */
+
+#ifndef _SF_IOV_H
+#define _SF_IOV_H
+
+#include "fastcommon/shared_func.h"
+#include "sf_types.h"
+
+#define SF_IOV_FIXED_SIZE 256
+
+typedef struct sf_dynamic_iov_array {
+ struct iovec holder[SF_IOV_FIXED_SIZE];
+ struct iovec *ptr;
+
+ struct {
+ struct iovec *iov;
+ int cnt;
+ } input;
+
+ struct iovec *iov;
+ int cnt;
+} SFDynamicIOVArray;
+
+#define sf_iova_init(iova, _iov, _cnt) \
+ (iova).iov = (iova).input.iov = _iov; \
+ (iova).cnt = (iova).input.cnt = _cnt
+
+#define sf_iova_destroy(iova) \
+ if ((iova).iov != (iova).input.iov && \
+ (iova).ptr != (iova).holder) \
+ free((iova).ptr)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int sf_iova_check_alloc(SFDynamicIOVArray *iova)
+{
+ if (iova->iov == iova->input.iov) {
+ if (iova->input.cnt <= SF_IOV_FIXED_SIZE) {
+ iova->ptr = iova->holder;
+ } else {
+ iova->ptr = fc_malloc(iova->input.cnt *
+ sizeof(struct iovec));
+ if (iova->ptr == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ memcpy(iova->ptr, iova->input.iov, iova->input.cnt *
+ sizeof(struct iovec));
+ iova->iov = iova->ptr;
+ }
+
+ return 0;
+}
+
+int sf_iova_consume(SFDynamicIOVArray *iova, const int consume_len);
+
+int sf_iova_first_slice(SFDynamicIOVArray *iova, const int slice_len);
+
+int sf_iova_next_slice(SFDynamicIOVArray *iova,
+ const int consume_len, const int slice_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif