Compare commits

..

10 Commits

Author SHA1 Message Date
leitner
fdebbb224e update for new files added 2024-04-13 15:06:54 +00:00
leitner
ae3749aa31 test client and server for iom 2024-04-11 22:11:25 +00:00
leitner
08e6338d23 update iom_add man page, add iom_requeue man page 2024-04-11 21:06:17 +00:00
leitner
0756884d41 add iom_requeue 2024-04-11 21:01:04 +00:00
leitner
7100af72ca add entries for new files 2024-04-08 12:36:31 +00:00
leitner
5dbad67352 autofree mode for io_batch 2024-04-08 12:35:11 +00:00
leitner
f045b33647 document the new functions 2024-04-08 12:34:08 +00:00
leitner
af8a2d7215 typo 2024-04-05 17:55:16 +00:00
leitner
6f8e168ae3 proper return value handling 2024-04-05 17:37:38 +00:00
leitner
cf112a57fa timespec is absolute, not relative! 2024-04-05 16:26:43 +00:00
26 changed files with 602 additions and 60 deletions

View File

@ -614,21 +614,30 @@ iob_addfile.o: io/iob_addfile.c iob_internal.h iob.h libowfat/io.h \
iob_addfile_close.o: io/iob_addfile_close.c iob_internal.h iob.h \
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
libowfat/uint32.h libowfat/compiler.h libowfat/array.h array.h
iob_adds.o: io/iob_adds.c str.h libowfat/compiler.h iob.h libowfat/io.h \
iob_adds.o: io/iob_adds.c iob_internal.h iob.h libowfat/io.h \
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
libowfat/array.h
iob_adds_free.o: io/iob_adds_free.c str.h libowfat/compiler.h iob.h \
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
libowfat/uint32.h libowfat/array.h
iob_bytesleft.o: io/iob_bytesleft.c iob.h libowfat/io.h libowfat/uint64.h \
libowfat/taia.h libowfat/tai.h libowfat/uint32.h libowfat/compiler.h \
libowfat/array.h
libowfat/compiler.h libowfat/array.h array.h
iob_adds_free.o: io/iob_adds_free.c iob_internal.h iob.h libowfat/io.h \
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
libowfat/compiler.h libowfat/array.h array.h
iob_bytesleft.o: io/iob_bytesleft.c iob_internal.h iob.h libowfat/io.h \
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
libowfat/compiler.h libowfat/array.h array.h
iob_free.o: io/iob_free.c iob_internal.h iob.h libowfat/io.h \
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
libowfat/compiler.h libowfat/array.h array.h
iob_init.o: io/iob_init.c byte.h libowfat/compiler.h iob_internal.h iob.h \
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
libowfat/uint32.h libowfat/array.h array.h
iob_init_autofree.o: io/iob_init_autofree.c iob_internal.h iob.h \
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
libowfat/uint32.h libowfat/compiler.h libowfat/array.h array.h
iob_new.o: io/iob_new.c byte.h libowfat/compiler.h iob_internal.h iob.h \
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
libowfat/uint32.h libowfat/array.h array.h
iob_new_autofree.o: io/iob_new_autofree.c iob_internal.h iob.h \
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
libowfat/uint32.h libowfat/compiler.h libowfat/array.h array.h
iob_prefetch.o: io/iob_prefetch.c iob_internal.h iob.h libowfat/io.h \
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
libowfat/compiler.h libowfat/array.h array.h
@ -655,6 +664,10 @@ iom_init.o: io/iom_init.c io_internal.h libowfat/io.h libowfat/uint64.h \
libowfat/taia.h libowfat/tai.h libowfat/uint32.h libowfat/compiler.h \
libowfat/array.h libowfat/iarray.h haveepoll.h havekqueue.h \
havedevpoll.h havesigio.h
iom_requeue.o: io/iom_requeue.c io_internal.h libowfat/io.h \
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
libowfat/compiler.h libowfat/array.h libowfat/iarray.h haveepoll.h \
havekqueue.h havedevpoll.h havesigio.h
iom_wait.o: io/iom_wait.c io_internal.h libowfat/io.h libowfat/uint64.h \
libowfat/taia.h libowfat/tai.h libowfat/uint32.h libowfat/compiler.h \
libowfat/array.h libowfat/iarray.h haveepoll.h havekqueue.h \
@ -883,7 +896,8 @@ socket_tcp4.o: socket/socket_tcp4.c socket.h libowfat/compiler.h \
socket_tcp4b.o: socket/socket_tcp4b.c windoze.h socket.h \
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h
socket_tcp6.o: socket/socket_tcp6.c haveip6.h socket.h \
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h \
windoze.h
socket_tcp6b.o: socket/socket_tcp6b.c windoze.h haveip6.h socket.h \
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h
socket_tryreservein.o: socket/socket_tryreservein.c windoze.h socket.h \
@ -1063,25 +1077,25 @@ t.o: t.c fmt.h libowfat/byte.h libowfat/compiler.h scan.h str.h uint16.h \
parse.h libowfat/buffer.h CAS.h io_internal.h libowfat/io.h \
libowfat/array.h libowfat/iarray.h haveepoll.h havekqueue.h \
havedevpoll.h havesigio.h
BYTE_OBJS=byte_chr.o byte_copy.o byte_copyr.o byte_diff.o byte_equal_notimingattack.o byte_rchr.o byte_zero.o
FMT_OBJS=fmt_8long.o fmt_8longlong.o fmt_asn1derlength.o fmt_asn1dertag.o fmt_double.o fmt_escapecharc.o fmt_escapecharhtml.o fmt_escapecharjson.o fmt_escapecharquotedprintable.o fmt_escapecharquotedprintableutf8.o fmt_escapecharxml.o fmt_fill.o fmt_httpdate.o fmt_human.o fmt_humank.o fmt_iso8601.o fmt_long.o fmt_longlong.o fmt_minus.o fmt_netstring.o fmt_pad.o fmt_pb_double.o fmt_pb_float.o fmt_pb_int.o fmt_pb_sint.o fmt_pb_string.o fmt_pb_tag.o fmt_pb_type0_sint.o fmt_pb_type1_double.o fmt_pb_type1_fixed64.o fmt_pb_type2_string.o fmt_pb_type5_fixed32.o fmt_pb_type5_float.o fmt_plusminus.o fmt_str.o fmt_strm_internal.o fmt_strn.o fmt_tohex.o fmt_ulong.o fmt_ulong0.o fmt_ulonglong.o fmt_utf8.o fmt_varint.o fmt_xlong.o fmt_xlonglong.o fmt_xmlescape.o
BYTE_OBJS=byte_chr.o byte_copy.o byte_copyr.o byte_diff.o byte_equal_notimingattack.o byte_rchr.o byte_start.o byte_starts.o byte_zero.o
FMT_OBJS=fmt_8long.o fmt_8longlong.o fmt_asn1derlength.o fmt_asn1dertag.o fmt_double.o fmt_escapecharc.o fmt_escapecharhtml.o fmt_escapecharjson.o fmt_escapecharquotedprintable.o fmt_escapecharquotedprintableutf8.o fmt_escapecharxml.o fmt_fill.o fmt_httpdate.o fmt_human.o fmt_humank.o fmt_iso8601.o fmt_long.o fmt_longlong.o fmt_minus.o fmt_netstring.o fmt_pad.o fmt_pb_double.o fmt_pb_float.o fmt_pb_int.o fmt_pb_sint.o fmt_pb_string.o fmt_pb_tag.o fmt_pb_type0_sint.o fmt_pb_type1_double.o fmt_pb_type1_fixed64.o fmt_pb_type2_string.o fmt_pb_type5_fixed32.o fmt_pb_type5_float.o fmt_plusminus.o fmt_str.o fmt_strm_internal.o fmt_strn.o fmt_tohex.o fmt_ulong0.o fmt_ulong.o fmt_ulonglong.o fmt_utf8.o fmt_varint.o fmt_xlong.o fmt_xlonglong.o fmt_xmlescape.o
SCAN_OBJS=scan_8int.o scan_8long.o scan_8longlong.o scan_8longn.o scan_8short.o scan_asn1derlength.o scan_asn1dertag.o scan_charsetnskip.o scan_double.o scan_fromhex.o scan_httpdate.o scan_int.o scan_iso8601.o scan_long.o scan_longlong.o scan_longn.o scan_netstring.o scan_noncharsetnskip.o scan_nonwhitenskip.o scan_pb_tag.o scan_pb_type0_sint.o scan_pb_type1_double.o scan_pb_type1_fixed64.o scan_pb_type2_stringlen.o scan_pb_type5_fixed32.o scan_pb_type5_float.o scan_plusminus.o scan_short.o scan_uint.o scan_ulong.o scan_ulonglong.o scan_ulongn.o scan_ushort.o scan_utf8.o scan_utf8_sem.o scan_varint.o scan_whitenskip.o scan_xint.o scan_xlong.o scan_xlonglong.o scan_xlongn.o scan_xshort.o
STR_OBJS=str_chr.o str_copy.o str_diff.o str_diffn.o str_len.o str_rchr.o str_start.o
UINT_OBJS=uint16_pack.o uint16_pack_big.o uint16_read.o uint16_read_big.o uint16_unpack.o uint16_unpack_big.o uint32_pack.o uint32_pack_big.o uint32_read.o uint32_read_big.o uint32_unpack.o uint32_unpack_big.o uint64_pack.o uint64_pack_big.o uint64_read.o uint64_read_big.o uint64_unpack.o uint64_unpack_big.o
OPEN_OBJS=open_append.o open_excl.o open_read.o open_rw.o open_trunc.o open_write.o openreadclose.o readclose.o
STRALLOC_OBJS=stralloc_append.o stralloc_cat.o stralloc_catb.o stralloc_catlong0.o stralloc_catm_internal.o stralloc_cats.o stralloc_catulong0.o stralloc_chomp.o stralloc_chop.o stralloc_copy.o stralloc_copyb.o stralloc_copys.o stralloc_diff.o stralloc_diffs.o stralloc_free.o stralloc_init.o stralloc_ready.o stralloc_readyplus.o stralloc_starts.o stralloc_zero.o
UINT_OBJS=uint16_pack_big.o uint16_pack.o uint16_read_big.o uint16_read.o uint16_unpack_big.o uint16_unpack.o uint32_pack_big.o uint32_pack.o uint32_read_big.o uint32_read.o uint32_unpack_big.o uint32_unpack.o uint64_pack_big.o uint64_pack.o uint64_read_big.o uint64_read.o uint64_unpack_big.o uint64_unpack.o
OPEN_OBJS=open_append.o open_excl.o open_read.o openreadclose.o open_rw.o open_trunc.o open_write.o readclose.o
STRALLOC_OBJS=stralloc_append.o stralloc_catb.o stralloc_cat.o stralloc_catlong0.o stralloc_catm_internal.o stralloc_cats.o stralloc_catulong0.o stralloc_chomp.o stralloc_chop.o stralloc_copyb.o stralloc_copy.o stralloc_copys.o stralloc_diff.o stralloc_diffs.o stralloc_free.o stralloc_init.o stralloc_ready.o stralloc_readyplus.o stralloc_starts.o stralloc_zero.o
UNIX_OBJS=iopause.o ndelay_off.o ndelay_on.o winsock2errno.o
SOCKET_OBJS=fmt_ip4.o fmt_ip6.o fmt_ip6_flat.o fmt_ip6c.o fmt_ip6if.o fmt_ip6ifc.o init.o scan_ip4.o scan_ip6.o scan_ip6_flat.o scan_ip6if.o socket_accept4.o socket_accept6.o socket_bind4.o socket_bind4_reuse.o socket_bind6.o socket_bind6_reuse.o socket_broadcast.o socket_connect4.o socket_connect6.o socket_connected.o socket_deferaccept.o socket_fastopen.o socket_fastopen_connect4.o socket_fastopen_connect6.o socket_getifidx.o socket_getifname.o socket_ip4loopback.o socket_listen.o socket_local4.o socket_local6.o socket_mchopcount6.o socket_mcjoin4.o socket_mcjoin6.o socket_mcleave4.o socket_mcleave6.o socket_mcloop4.o socket_mcloop6.o socket_mcttl4.o socket_noipv6.o socket_quickack.o socket_recv4.o socket_recv6.o socket_remote4.o socket_remote6.o socket_sctp4.o socket_sctp4b.o socket_sctp6.o socket_sctp6b.o socket_send4.o socket_send6.o socket_tcp4.o socket_tcp4b.o socket_tcp6.o socket_tcp6b.o socket_tryreservein.o socket_udp4.o socket_udp6.o socket_v4mappedprefix.o socket_v6any.o socket_v6loopback.o
BUFFER_OBJS=buffer_0.o buffer_0small.o buffer_1.o buffer_1small.o buffer_2.o buffer_close.o buffer_feed.o buffer_flush.o buffer_free.o buffer_fromarray.o buffer_frombuf.o buffer_fromsa.o buffer_get.o buffer_get_new_token_sa.o buffer_get_new_token_sa_pred.o buffer_get_token.o buffer_get_token_pred.o buffer_get_token_sa.o buffer_get_token_sa_pred.o buffer_getc.o buffer_getline.o buffer_getline_sa.o buffer_getn.o buffer_getnewline_sa.o buffer_init.o buffer_init_free.o buffer_mmapread.o buffer_munmap.o buffer_peek.o buffer_put.o buffer_put8long.o buffer_putalign.o buffer_puterror.o buffer_puterror2.o buffer_putflush.o buffer_putlong.o buffer_putlonglong.o buffer_putm_internal.o buffer_putm_internal_flush.o buffer_putnlflush.o buffer_puts.o buffer_putsa.o buffer_putsaflush.o buffer_putsalign.o buffer_putsflush.o buffer_putspace.o buffer_putulong.o buffer_putulonglong.o buffer_putxlong.o buffer_seek.o buffer_stubborn.o buffer_stubborn2.o buffer_tosa.o errmsg_iam.o errmsg_info.o errmsg_infosys.o errmsg_puts.o errmsg_warn.o errmsg_warnsys.o errmsg_write.o
MMAP_OBJS=mmap_private.o mmap_read.o mmap_readat.o mmap_shared.o mmap_unmap.o
SOCKET_OBJS=fmt_ip4.o fmt_ip6.o fmt_ip6c.o fmt_ip6_flat.o fmt_ip6if.o fmt_ip6ifc.o init.o scan_ip4.o scan_ip6.o scan_ip6_flat.o scan_ip6if.o socket_accept4.o socket_accept4_flags.o socket_accept4_makenonblocking.o socket_accept4_makenonblocking_setcloseonexec.o socket_accept4_setcloseonexec.o socket_accept6.o socket_accept6_flags.o socket_accept6_makenonblocking.o socket_accept6_makenonblocking_setcloseonexec.o socket_accept6_setcloseonexec.o socket_bind4.o socket_bind4_reuse.o socket_bind6.o socket_bind6_reuse.o socket_broadcast.o socket_connect4.o socket_connect6.o socket_connected.o socket_deferaccept.o socket_fastopen.o socket_fastopen_connect4.o socket_fastopen_connect6.o socket_getifidx.o socket_getifname.o socket_ip4loopback.o socket_listen.o socket_local4.o socket_local6.o socket_mchopcount6.o socket_mcjoin4.o socket_mcjoin6.o socket_mcleave4.o socket_mcleave6.o socket_mcloop4.o socket_mcloop6.o socket_mcttl4.o socket_noipv6.o socket_quickack.o socket_recv4.o socket_recv6.o socket_remote4.o socket_remote6.o socket_sctp4b.o socket_sctp4.o socket_sctp6b.o socket_sctp6.o socket_send4.o socket_send6.o socket_tcp4b.o socket_tcp4.o socket_tcp6b.o socket_tcp6.o socket_tryreservein.o socket_udp4.o socket_udp6.o socket_v4mappedprefix.o socket_v6any.o socket_v6loopback.o
BUFFER_OBJS=bs_capacityassert.o bs_capacitycheck.o bs_capacityleft.o bs_consumeleftovers.o bs_err.o bs_get.o bs_init_bstream_size.o bs_init_iobuf.o bs_init_iobuf_size.o bs_init_membuf.o bs_nomoredataassert.o bs_peek.o bs_seterrorstate.o bs_skip.o buffer_0.o buffer_0small.o buffer_1.o buffer_1small.o buffer_2.o buffer_close.o buffer_feed.o buffer_flush.o buffer_free.o buffer_fromarray.o buffer_frombuf.o buffer_fromsa.o buffer_get.o buffer_getc.o buffer_getline.o buffer_getline_sa.o buffer_getn.o buffer_getnewline_sa.o buffer_get_new_token_sa.o buffer_get_new_token_sa_pred.o buffer_get_token.o buffer_get_token_pred.o buffer_get_token_sa.o buffer_get_token_sa_pred.o buffer_init_allocbuf.o buffer_init.o buffer_init_free.o buffer_init_read_allocbuf.o buffer_init_read.o buffer_init_staticcontents.o buffer_init_staticcontents_free.o buffer_init_write_allocbuf.o buffer_init_write.o buffer_mmapread.o buffer_munmap.o buffer_peek.o buffer_peekc.o buffer_put8long.o buffer_putalign.o buffer_put.o buffer_puterror2.o buffer_puterror.o buffer_putflush.o buffer_putlong.o buffer_putlonglong.o buffer_putm_internal.o buffer_putm_internal_flush.o buffer_putnlflush.o buffer_putsa.o buffer_putsaflush.o buffer_putsalign.o buffer_puts.o buffer_putsflush.o buffer_putspace.o buffer_putulong.o buffer_putulonglong.o buffer_putxlong.o buffer_seek.o buffer_stubborn2.o buffer_stubborn.o buffer_tosa.o errmsg_iam.o errmsg_info.o errmsg_infosys.o errmsg_puts.o errmsg_warn.o errmsg_warnsys.o errmsg_write.o prs_asciiz.o prs_asciiz_fixedlen.o prs_readblob.o prs_u16_big.o prs_u16.o prs_u32_big.o prs_u32.o prs_u64_big.o prs_u64.o
MMAP_OBJS=mmap_private.o mmap_readat.o mmap_read.o mmap_shared.o mmap_unmap.o
TAIA_OBJS=taia_add.o taia_addsec.o taia_approx.o taia_frac.o taia_half.o taia_less.o taia_now.o taia_pack.o taia_sub.o taia_tai.o taia_uint.o taia_unpack.o
TAI_OBJS=tai_add.o tai_now.o tai_pack.o tai_sub.o tai_uint.o tai_unpack.o
DNS_OBJS=dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ip6.o dns_ipq.o dns_ipq6.o dns_mx.o dns_name.o dns_nd.o dns_nd6.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o dns_resolve.o dns_sortip.o dns_sortip6.o dns_transmit.o dns_txt.o
DNS_OBJS=dns_dfd.o dns_domain.o dns_dtda.o dns_ip6.o dns_ip.o dns_ipq6.o dns_ipq.o dns_mx.o dns_name.o dns_nd6.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o dns_resolve.o dns_sortip6.o dns_sortip.o dns_transmit.o dns_txt.o
CASE_OBJS=case_diffb.o case_diffs.o case_lowerb.o case_lowers.o case_starts.o
MULT_OBJS=imult16.o imult32.o imult64.o range_arrayinbuf.o range_str2inbuf.o range_str4inbuf.o range_strinbuf.o umult16.o umult32.o umult64.o
ARRAY_OBJS=array_allocate.o array_bytes.o array_cat.o array_cat0.o array_catb.o array_cate.o array_cats.o array_cats0.o array_equal.o array_fail.o array_get.o array_length.o array_reset.o array_start.o array_trunc.o array_truncate.o iarray_allocate.o iarray_free.o iarray_get.o iarray_init.o iarray_length.o
IO_OBJS=io_appendfile.o io_block.o io_canread.o io_canwrite.o io_check.o io_close.o io_closeonexec.o io_createfile.o io_debugstring.o io_dontwantread.o io_dontwantwrite.o io_eagain.o io_eagain_read.o io_eagain_write.o io_fd.o io_finishandshutdown.o io_getcookie.o io_mmapwritefile.o io_nonblock.o io_passfd.o io_pipe.o io_readfile.o io_readwritefile.o io_receivefd.o io_sendfile.o io_setcookie.o io_sigpipe.o io_socketpair.o io_timedout.o io_timeout.o io_timeouted.o io_tryread.o io_tryreadtimeout.o io_trywrite.o io_trywritetimeout.o io_wait.o io_waitread.o io_waituntil.o io_waituntil2.o io_waitwrite.o io_wantread.o io_wantwrite.o iob_addbuf.o iob_addbuf_free.o iob_addbuf_internal.o iob_addbuf_munmap.o iob_addfile.o iob_addfile_close.o iob_adds.o iob_adds_free.o iob_bytesleft.o iob_free.o iob_new.o iob_prefetch.o iob_reset.o iob_send.o iob_write.o
TEXTCODE_OBJS=base64.o base64url.o fmt_base64.o fmt_base64url.o fmt_cescape.o fmt_foldwhitespace.o fmt_hexdump.o fmt_html.o fmt_html_tagarg.o fmt_jsonescape.o fmt_ldapescape.o fmt_ldapescape2.o fmt_quotedprintable.o fmt_to_array.o fmt_to_sa.o fmt_tofrom_array.o fmt_urlencoded.o fmt_uuencoded.o fmt_xml.o fmt_yenc.o scan_base64.o scan_base64url.o scan_cescape.o scan_hexdump.o scan_html.o scan_jsonescape.o scan_ldapescape.o scan_quotedprintable.o scan_to_array.o scan_to_sa.o scan_tofrom_array.o scan_urlencoded.o scan_uuencoded.o scan_yenc.o
ARRAY_OBJS=array_allocate.o array_bytes.o array_cat0.o array_catb.o array_cat.o array_cate.o array_cats0.o array_cats.o array_equal.o array_fail.o array_get.o array_length.o array_reset.o array_start.o array_truncate.o array_trunc.o iarray_allocate.o iarray_free.o iarray_get.o iarray_init.o iarray_length.o
IO_OBJS=io_appendfile.o iob_addbuf.o iob_addbuf_free.o iob_addbuf_internal.o iob_addbuf_munmap.o iob_addfile.o iob_addfile_close.o iob_adds.o iob_adds_free.o iob_bytesleft.o iob_free.o iob_init_autofree.o iob_init.o io_block.o iob_new_autofree.o iob_new.o iob_prefetch.o iob_reset.o iob_send.o iob_write.o io_canread.o io_canwrite.o io_check.o io_close.o io_closeonexec.o io_createfile.o io_debugstring.o io_dontwantread.o io_dontwantwrite.o io_eagain.o io_eagain_read.o io_eagain_write.o io_fd.o io_finishandshutdown.o io_getcookie.o iom_abort.o iom_add.o iom_init.o io_mmapwritefile.o iom_requeue.o iom_wait.o io_nonblock.o io_passfd.o io_pipe.o io_readfile.o io_readwritefile.o io_receivefd.o io_sendfile.o io_setcookie.o io_sigpipe.o io_socketpair.o io_timedout.o io_timeout.o io_timeouted.o io_tryread.o io_tryreadtimeout.o io_trywrite.o io_trywritetimeout.o io_wait.o io_waitread.o io_waituntil2.o io_waituntil.o io_waitwrite.o io_wantread.o io_wantwrite.o
TEXTCODE_OBJS=base64.o base64url.o fmt_base64.o fmt_base64url.o fmt_cescape.o fmt_foldwhitespace.o fmt_hexdump.o fmt_html.o fmt_html_tagarg.o fmt_jsonescape.o fmt_ldapescape2.o fmt_ldapescape.o fmt_quotedprintable.o fmt_to_array.o fmt_tofrom_array.o fmt_to_sa.o fmt_urlencoded.o fmt_uuencoded.o fmt_xml.o fmt_yenc.o scan_base64.o scan_base64url.o scan_cescape.o scan_hexdump.o scan_html.o scan_jsonescape.o scan_ldapescape.o scan_quotedprintable.o scan_to_array.o scan_tofrom_array.o scan_to_sa.o scan_urlencoded.o scan_uuencoded.o scan_yenc.o
CDB_OBJS=cdb.o cdb_hash.o cdb_make.o cdb_traverse.o
CRITBIT_OBJS=critbit.o

View File

@ -478,7 +478,10 @@
{ "directory": "@", "file": "io/iob_adds_free.c", "output": "iob_adds_free.o", "arguments": [ "clang", "-c", "io/iob_adds_free.c", "-I." ]},
{ "directory": "@", "file": "io/iob_bytesleft.c", "output": "iob_bytesleft.o", "arguments": [ "clang", "-c", "io/iob_bytesleft.c", "-I." ]},
{ "directory": "@", "file": "io/iob_free.c", "output": "iob_free.o", "arguments": [ "clang", "-c", "io/iob_free.c", "-I." ]},
{ "directory": "@", "file": "io/iob_init.c", "output": "iob_init.o", "arguments": [ "clang", "-c", "io/iob_init.c", "-I." ]},
{ "directory": "@", "file": "io/iob_init_autofree.c", "output": "iob_init_autofree.o", "arguments": [ "clang", "-c", "io/iob_init_autofree.c", "-I." ]},
{ "directory": "@", "file": "io/iob_new.c", "output": "iob_new.o", "arguments": [ "clang", "-c", "io/iob_new.c", "-I." ]},
{ "directory": "@", "file": "io/iob_new_autofree.c", "output": "iob_new_autofree.o", "arguments": [ "clang", "-c", "io/iob_new_autofree.c", "-I." ]},
{ "directory": "@", "file": "io/iob_prefetch.c", "output": "iob_prefetch.o", "arguments": [ "clang", "-c", "io/iob_prefetch.c", "-I." ]},
{ "directory": "@", "file": "io/iob_reset.c", "output": "iob_reset.o", "arguments": [ "clang", "-c", "io/iob_reset.c", "-I." ]},
{ "directory": "@", "file": "io/iob_send.c", "output": "iob_send.o", "arguments": [ "clang", "-c", "io/iob_send.c", "-I." ]},

6
io.h
View File

@ -249,12 +249,16 @@ enum {
IOM_WRITE=2,
IOM_ERROR=4
};
/* signal interest in events from a socket */
/* return -1 if error, events can be IOM_READ or IOM_WRITE */
int iom_add(iomux_t* c,int64 s,unsigned int events);
/* signal interest in more events from a socket */
int iom_requeue(iomux_t* c,int64 s,unsigned int events);
/* Blocking wait for single event, timeout in milliseconds */
/* return -1 if error, 0 if ok; s set to fd, revents set to known events on that fd */
/* when done with the fd, call iom_add on it again! */
/* when done with the fd, call iom_requeue on it to receive more events! */
/* This can be called by multiple threads in parallel */
int iom_wait(iomux_t* c,int64* s,unsigned int* revents,unsigned long timeout);

View File

@ -1,6 +1,6 @@
#include "str.h"
#include "iob.h"
#include <string.h>
#include "iob_internal.h"
int iob_adds(io_batch* b,const char* s) {
return iob_addbuf(b,s,str_len(s));
return iob_addbuf(b,s,strlen(s));
}

View File

@ -1,6 +1,6 @@
#include "str.h"
#include "iob.h"
#include <string.h>
#include "iob_internal.h"
int iob_adds_free(io_batch* b,const char* s) {
return iob_addbuf_free(b,s,str_len(s));
return iob_addbuf_free(b,s,strlen(s));
}

View File

@ -1,4 +1,4 @@
#include "iob.h"
#include "iob_internal.h"
uint64 iob_bytesleft(const io_batch* b) {
return b->bytesleft;

25
io/iob_init.3 Normal file
View File

@ -0,0 +1,25 @@
.TH iob_init 3
.SH NAME
iob_init \- initialize new I/O batch
.SH SYNTAX
.B #include <libowfat/iob.h>
int \fBiob_init\fP(io_batch* b,size_t hint_entries);
.SH DESCRIPTION
iob_init initializes \fI*b\fR with enough space allocated for
\fIhint_entries\fR entries (buffers or files). This is purely a
performance hint, if you are unsure just pass 1.
You can add buffers, strings and files to an I/O batch and then send it
all at once using iob_send.
The benefit of the I/O batch API is that it exploits platform specific
APIs like FreeBSD's sendfile. The file contents will always be sent in
a way that allows the operating systems to perform zero copy TCP, and
the buffers will always be sent using as few syscalls as possible and
avoiding unnecessary copying (using writev).
.SH "RETURN VALUE"
iob_init returns 0 on success. If there was a memory allocation error,
it returns -1 instead.
.SH "SEE ALSO"
iob_new(3), iob_init_autofree(3), iob_reset(3), iob_send(3), iob_addbuf(3), iob_adds_free(3), iob_addfile(3)

13
io/iob_init.c Normal file
View File

@ -0,0 +1,13 @@
#include <stdlib.h>
#include "byte.h"
#include "iob_internal.h"
int iob_init(io_batch* b,size_t hint_entries) {
byte_zero(b,sizeof(io_batch));
if (hint_entries) {
if (!array_allocate(&b->b,sizeof(iob_entry),hint_entries))
return -1;
array_trunc(&b->b);
}
return 0;
}

31
io/iob_init_autofree.3 Normal file
View File

@ -0,0 +1,31 @@
.TH iob_init 3
.SH NAME
iob_init_autofree \- initialize new I/O batch with autofree flag set
.SH SYNTAX
.B #include <libowfat/iob.h>
int \fBiob_init_autofree\fP(io_batch* b,size_t hint_entries);
.SH DESCRIPTION
iob_init_autofree initializes \fI*b\fR with enough space allocated for
\fIhint_entries\fR entries (buffers or files). This is purely a
performance hint, if you are unsure just pass 1.
The autofree flag will be set, which means resources will be freed in
\fIiob_send\fR once they have been sent out, not only once you call \fIiob_reset\fR
or \fIiob_free\fR at the end. You still have to call those as autofree only
frees resources to be sent in the batch, not the resources of the batch
itself.
You can add buffers, strings and files to an I/O batch and then send it
all at once using iob_send.
The benefit of the I/O batch API is that it exploits platform specific
APIs like FreeBSD's sendfile. The file contents will always be sent in
a way that allows the operating systems to perform zero copy TCP, and
the buffers will always be sent using as few syscalls as possible and
avoiding unnecessary copying (using writev).
.SH "RETURN VALUE"
iob_init returns 0 on success. If there was a memory allocation error,
it returns -1 instead.
.SH "SEE ALSO"
iob_new(3), iob_init_autofree(3), iob_reset(3), iob_send(3), iob_addbuf(3), iob_adds_free(3), iob_addfile(3)

7
io/iob_init_autofree.c Normal file
View File

@ -0,0 +1,7 @@
#include "iob_internal.h"
int iob_init_autofree(io_batch* b,size_t hint_entries) {
int r=iob_init(b,hint_entries);
b->autofree=1;
return r;
}

View File

@ -4,7 +4,7 @@ iob_new \- create new I/O batch
.SH SYNTAX
.B #include <libowfat/iob.h>
io_batch* \fBiob_new\fP(int hint_entries);
io_batch* \fBiob_new\fP(size_t hint_entries);
.SH DESCRIPTION
iob_new creates a new I/O batch with enough space allocated for
\fIhint_entries\fR entries (buffers or files). This is purely a

View File

@ -2,7 +2,7 @@
#include "byte.h"
#include "iob_internal.h"
io_batch* iob_new(int hint_entries) {
io_batch* iob_new(size_t hint_entries) {
io_batch* b=(io_batch*)malloc(sizeof(io_batch));
if (!b) return 0;
byte_zero(b,sizeof(io_batch));

31
io/iob_new_autofree.3 Normal file
View File

@ -0,0 +1,31 @@
.TH iob_new_autofree 3
.SH NAME
iob_new_autofree \- create new I/O batch with autofree flag set
.SH SYNTAX
.B #include <libowfat/iob.h>
io_batch* \fBiob_new_autofree\fP(size_t hint_entries);
.SH DESCRIPTION
iob_new_autofree creates a new I/O batch with enough space allocated for
\fIhint_entries\fR entries (buffers or files). This is purely a
performance hint. If you are unsure just pass 1.
The autofree flag will be set, which means resources will be freed in
\fIiob_send\fR once they have been sent out, not only once you call \fIiob_reset\fR
or \fIiob_free\fR at the end. You still have to call those as autofree only
frees resources to be sent in the batch, not the resources of the batch
itself.
You can add buffers, strings and files to an I/O batch and then send it
all at once using iob_send.
The benefit of the I/O batch API is that it exploits platform specific
APIs like FreeBSD's sendfile. The file contents will always be sent in
a way that allows the operating systems to perform zero copy TCP, and
the buffers will always be sent using as few syscalls as possible and
avoiding unnecessary copying (using writev).
.SH "RETURN VALUE"
iob_new_autofree returns a pointer to an I/O batch data structure. If
there was a memory allocation error, it returns NULL instead.
.SH "SEE ALSO"
iob_new(3), iob_init(3), iob_reset(3), iob_send(3), iob_addbuf(3), iob_adds_free(3), iob_addfile(3)

8
io/iob_new_autofree.c Normal file
View File

@ -0,0 +1,8 @@
#include "iob_internal.h"
io_batch* iob_new_autofree(size_t hint_entries) {
io_batch* b=iob_new(hint_entries);
if (b)
b->autofree=1;
return b;
}

View File

@ -7,6 +7,14 @@
#include "iob_internal.h"
#include <stdio.h>
/*
__ ___ _
\ \ / (_)_ __ __| | _____ _____
\ \ /\ / /| | '_ \ / _` |/ _ \ \ /\ / / __|
\ V V / | | | | | (_| | (_) \ V V /\__ \
\_/\_/ |_|_| |_|\__,_|\___/ \_/\_/ |___/
*/
int64 iob_send(int64 s,io_batch* b) {
/* Windows has a sendfile called TransmitFile, which can send one
* header and one trailer buffer. */
@ -108,6 +116,14 @@ int64 iob_send(int64 s,io_batch* b) {
#else
/*
_ _ _
| | | |_ __ (_)_ __
| | | | '_ \| \ \/ /
| |_| | | | | |> <
\___/|_| |_|_/_/\_\
*/
#include "havebsdsf.h"
#include <sys/types.h>
#include <sys/socket.h>
@ -145,7 +161,7 @@ int64 iob_send(int64 s,io_batch* b) {
if (b->bytesleft==0) return 0;
E=iarray_get(&io_fds,s);
if (!E) { errno=EBADF; return -3; }
// if (!E) { errno=EBADF; return -3; }
last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
v=alloca(b->bufs*sizeof(struct iovec));
total=0;
@ -167,6 +183,14 @@ int64 iob_send(int64 s,io_batch* b) {
}
headers=i;
#ifdef HAVE_BSDSENDFILE
/*
____ ____ ____
| __ ) ___|| _ \
| _ \___ \| | | |
| |_) |__) | |_| |
|____/____/|____/
*/
if (e+i<last && e[i].type==FROMFILE) {
#ifdef DEBUGONLINUX
@ -212,6 +236,14 @@ eagain:
}
}
#else
/*
_ _
| | (_)_ __ _ ___ __
| | | | '_ \| | | \ \/ /
| |___| | | | | |_| |> <
|_____|_|_| |_|\__,_/_/\_\
*/
/* Linux has two ways to coalesce sent data; either setsockopt
* TCP_CORK or sendto/sendmsg with MSG_MORE. MSG_MORE saves syscalls
* in one scenario: when there is n buffers and then possibly one
@ -245,7 +277,7 @@ eagain:
if (!nozerocopy && sum>=8*1024) {
/* MSG_ZEROCOPY has page table management overhead,
* it only pays off after 8k or so */
if (E->zerocopy==0) {
if (E && E->zerocopy==0) {
if (setsockopt(s, SOL_SOCKET, SO_ZEROCOPY, (int[]){ 1 },sizeof(int)) == 0) {
E->zerocopy=1;
ZEROCOPY=MSG_ZEROCOPY;
@ -273,9 +305,18 @@ eagain:
n = headers-skip; if (n > 50) n=50;
for (i=0; i<n; ++i) l += v[skip+i].iov_len;
// printf("writing %d records from offset %d, %d bytes\n", skip, n, l);
msg.msg_iov=v + skip;
msg.msg_iovlen=n;
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
if (E && E->notsock)
notsockwritev:
sent=writev(s,v+skip,n);
else {
msg.msg_iov=v + skip;
msg.msg_iovlen=n;
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
if (sent==-1 && errno==ENOTSOCK) {
if (E) E->notsock=1;
goto notsockwritev;
}
}
if (sent > 0) totalsent += sent;
if (sent == l) continue; // we sent as much as we wanted, go for next batch
if (sent >= 0) // we wrote something but not the whole batch
@ -294,8 +335,20 @@ eagain:
// if we get here, we wrote it all or we got an EAGAIN after
// writing something. Treat as regular partial write.
sent = totalsent;
} else
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
} else {
if (E && E->notsock)
notsockwritev2:
sent=writev(s,v,headers);
else {
msg.msg_iov=v;
msg.msg_iovlen=headers;
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
if (sent==-1 && errno==ENOTSOCK) {
if (E) E->notsock=1;
goto notsockwritev2;
}
}
}
}
}
if (sent==-1) {
@ -345,6 +398,11 @@ eagain:
for (i=0; e+i<last; ++i) {
if (e[i].n<=rest) {
rest-=e[i].n;
if (b->autofree) {
if (e[i].cleanup)
e[i].cleanup(e+i);
e[i].cleanup=0;
}
++b->next;
if (!rest) break;
} else {
@ -353,8 +411,10 @@ eagain:
goto abort;
}
}
io_eagain_write(s);
return total;
if (b->bytesleft==0) {
io_eagain_write(s);
return total;
}
} else break;
}
abort:

View File

@ -11,7 +11,7 @@ int64 iob_write2(int64 s,io_batch* b,io_write_callback cb,io_sendfile_callback s
total=0;
if (!(e=array_get(&b->b,sizeof(iob_entry),b->next)))
return -3; /* can't happen error */
for (i=0; e+i<last; ++i) {
for (i=b->next; e+i<last; ++i) {
int thatsit;
if (!e[i].n) continue;
if (e[i].type==FROMFILE)
@ -27,6 +27,13 @@ int64 iob_write2(int64 s,io_batch* b,io_write_callback cb,io_sendfile_callback s
total+=sent;
b->bytesleft-=sent;
if (thatsit) break;
// we have sent one full entry
if (b->autofree) {
if (e[i].cleanup)
e[i].cleanup(e+i);
e[i].cleanup=0;
}
++b->next;
}
if (total == b->bytesleft)
iob_reset(b);

View File

@ -12,12 +12,11 @@ iom_add adds an event you are interested in to an I/O multiplexer.
in, and \fIevents\fR is the operation you want to do. It can be IOM_READ
or IOM_WRITE.
If that operation becomes possible on that descriptor, and some thread
is calling \fIiom_wait\fR at the time, it will return and tell you the
fd and the event.
If that operation becomes possible on that descriptor, \fIiom_wait\fR
will return and tell you the fd and the event.
Note that the event registration is removed from the iomux_t context if
it occurs. You will have to call \fIiom_wait\fR again after you handled
it occurs. You will have to call \fIiom_requeue\fR after you handled
the event, if you are still interested in it.
Closing a file descriptor with registered events will discard the event
@ -30,4 +29,4 @@ step.
.SH "RETURN VALUE"
iom_add returns 0 on success and -1 on error, setting errno.
.SH "SEE ALSO"
iom_init, iom_wait, iom_abort
iom_init, iom_requeue, iom_wait, iom_abort

35
io/iom_requeue.3 Normal file
View File

@ -0,0 +1,35 @@
.TH iom_requeue 3
.SH NAME
iom_requeue \- re-add event to I/O multiplexer
.SH SYNTAX
.B #include <libowfat/io.h>
int \fBiom_requeue\fP(iomux_t* c, int64 fd, unsigned int events);
.SH DESCRIPTION
iom_requeue adds an event you are interested in to an I/O multiplexer.
\fIfd\fR is the file descriptor (usually a socket) you are interested
in, and \fIevents\fR is the operation you want to do. It can be IOM_READ
or IOM_WRITE.
If that operation becomes possible on that descriptor, \fIiom_wait\fR
will return and tell you the fd and the event.
Note that the event registration is removed from the iomux_t context if
it occurs. You will have to call \fIiom_requeue\fR again if you are
interested in more events for this descriptor. Do this only after you
are done handling this event, otherwise \fIiom_wait\fR might indicate a
new event to another thread while this thread is still working on the
descriptor, leading to unexpected behavior.
Closing a file descriptor with registered events will discard the event
registration.
.SH "LINKING"
You may have to add \fI-lpthread\fR to the command line in the linking
step.
.SH "RETURN VALUE"
iom_requeue returns 0 on success and -1 on error, setting errno.
.SH "SEE ALSO"
iom_init, iom_add, iom_wait, iom_abort

28
io/iom_requeue.c Normal file
View File

@ -0,0 +1,28 @@
#include "io_internal.h"
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
#endif
#ifdef HAVE_KQUEUE
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#endif
int iom_requeue(iomux_t* c,int64 s,unsigned int events) {
#ifdef HAVE_EPOLL
struct epoll_event e = { .events=EPOLLONESHOT, .data.fd=s };
if (events & IOM_READ) e.events|=EPOLLIN;
if (events & IOM_WRITE) e.events|=EPOLLOUT;
return epoll_ctl(c->ctx, EPOLL_CTL_MOD, s, &e);
#elif defined(HAVE_KQUEUE)
struct kevent kev;
struct timespec ts = { 0 };
EV_SET(&kev, s,
(events & IOM_READ ? EVFILT_READ : 0) +
(events & IOM_WRITE ? EVFILT_WRITE : 0),
EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, (void*)s);
return kevent(c->ctx, &kev, 1, 0, 0, &ts);
#else
#warning "only epoll and kqueue supported for now"
#endif
}

View File

@ -3,10 +3,10 @@
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
#endif
#include <sys/time.h>
#ifdef HAVE_KQUEUE
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#endif
#include <errno.h>
#ifdef __dietlibc__
@ -15,7 +15,7 @@
#include <semaphore.h>
#endif
// return the next event, waiting of none are queued
// return the next event, waiting if none are queued
// wait at most timeout milliseconds
// on success, return 1 and return the fd in *s and the events on it in *revents
// if we waited but ran into a timeout, return 0
@ -171,19 +171,40 @@ int iom_wait(iomux_t* c,int64* s,unsigned int* revents,unsigned long timeout) {
} else {
/* somebody else has the job to fill the queue */
struct timespec ts;
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000;
struct timeval tv;
gettimeofday(&tv, NULL);
tv.tv_sec += timeout/1000;
tv.tv_usec += timeout%1000;
if (tv.tv_usec>1000000) {
tv.tv_usec-=1000000;
++tv.tv_sec;
}
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#ifdef __dietlibc__
r=cnd_timedwait(&c->sem,&c->mtx,&ts);
switch (r) {
case thrd_success:
continue;
case thrd_timedout:
return 0;
case thrd_error:
return -1;
}
#elif defined(__APPLE__)
r=pthread_cond_timedwait(&c->sem,&c->mtx,&ts);
switch (r) {
case 0: continue;
case ETIMEDOUT: return 0;
default: return -1;
}
#else
r=sem_timedwait(&c->sem,&ts);
#endif
if (r==-1) {
if (errno==ETIMEDOUT) return 0;
return -1;
}
#endif
/* fall through into next loop iteration */
}
}

View File

@ -50,6 +50,7 @@ typedef struct {
unsigned int closed:1; /* io_close called, but close deferred because of outstanding events */
unsigned int zerocopy:1; /* linux: setsockopt SO_ZEROCOPY done */
unsigned int goterror:1; /* got POLLERR|POLLHUP */
unsigned int notsock:1; /* linux: got ENOTSOCKET from sendmsg, use writev */
#ifdef __MINGW32__
unsigned int readqueued:2;
unsigned int writequeued:2;

51
iob.h
View File

@ -21,34 +21,83 @@
extern "C" {
#endif
/* you should not have to touch any of the internals */
typedef struct io_batch {
/* array of iob_entry, defined in iob_internal.h */
array b;
/* bytes left in the batch (starts as sum of lengths of all iob_entries */
uint64 bytesleft;
/* next is the index of the first unsent batch in the array */
long next,bufs,files;
/* Ask iob_send to free entries from the array as we go.
* Usually when iob_send returns 0 or error, you call iob_reset.
* You still have to call iob_reset even with this flag set, as
* autofree operates on the buffers in the array but does not free the
* array itself */
int autofree;
} io_batch;
io_batch* iob_new(int hint_entries);
/* Initialize an io_batch. Return 0 on success, -1 on malloc failure for
* embedded array */
int iob_init(io_batch* b,size_t hint_entries);
/* initialize an io_batch that auto-frees entries as soon as
* iob_send/iob_write have written them. Return 0 on success, -1 on
* malloc failure for embedded array */
int iob_init_autofree(io_batch* b,size_t hint_entries);
/* malloc and initialize an io_batch */
io_batch* iob_new(size_t hint_entries);
/* malloc and initialize an io_batch that auto-frees entries as soon as
* iob_send/iob_write have written them */
io_batch* iob_new_autofree(size_t hint_entries);
/* queue buffer in io_batch */
att_readn(2,3)
int iob_addbuf(io_batch* b,const void* buf,uint64 n);
/* queue buffer in io_batch, and give ownership to batch. */
/* the io_batch functions will take care of freeing it. */
att_readn(2,3)
int iob_addbuf_free(io_batch* b,const void* buf,uint64 n);
/* queue mmapped memory reagion in io_batch, and give ownership to batch. */
/* the io_batch functions will take care of unmapping it. */
att_readn(2,3)
int iob_addbuf_munmap(io_batch* b,const void* buf,uint64 n);
/* queue asciiz string in io_batch. */
att_read(2)
int iob_adds(io_batch* b,const char* s);
/* queue asciiz string in io_batch, and give ownership to batch. */
/* the io_batch functions will take care of freeing it. */
att_read(2)
int iob_adds_free(io_batch* b,const char* s);
/* queue file contents in io_batch. */
int iob_addfile(io_batch* b,int64 fd,uint64 off,uint64 n);
/* queue file contents in io_batch, and give ownership to batch */
/* the io_batch functions will take care of closing it. */
int iob_addfile_close(io_batch* b,int64 fd,uint64 off,uint64 n);
/* send (rest of) io_batch over socket s */
/* return number of bytes written.
* return 0 means whole batch written successfully.
* return -1 means couldn't write more on non-blocking socket, try again later
* return -3 means error (errno set) */
int64 iob_send(int64 s,io_batch* b);
/* same as iob_send but don't use callback instead of write and
* sendfile. Use this to write via OpenSSL or so */
int64 iob_write(int64 s,io_batch* b,io_write_callback cb);
/* same as iob_write if the TLS library also has a sendfile function */
int64 iob_write2(int64 s,io_batch* b,io_write_callback cb,io_sendfile_callback sfcb);
/* iob_reset closes files and frees buffer in the io_batch, and the
* array with the buffer, but not the batch itself (in case it's a local
* variable and not malloced) */
void iob_reset(io_batch* b);
/* iob_free does iob_reset but also frees the batch itself */
void iob_free(io_batch* b);
void iob_prefetch(io_batch* b,uint64 bytes);
uint64 iob_bytesleft(const io_batch* b);

View File

@ -1,7 +1,7 @@
#include <assert.h>
#include "iob.h"
#include "buffer.h"
#include "libowfat/iob.h"
#include <unistd.h>
#include <string.h>
static int64 write_cb(int64 fd,const void* buf,uint64 len) {
if (len>2) len=2;
@ -11,14 +11,16 @@ static int64 write_cb(int64 fd,const void* buf,uint64 len) {
int main() {
int64 fd;
io_batch* b;
int64 r;
char* fnord=strdup(" fnord\n");
assert(fnord);
assert(io_readfile(&fd,"GNUmakefile"));
assert(b=iob_new(10));
assert((b=iob_new_autofree(10)));
assert(iob_addbuf(b,"Huhu",4));
assert(iob_addbuf(b," fnord\n",7));
assert(iob_addbuf_free(b,fnord,7));
assert(iob_addfile(b,fd,10,10));
iob_send(1,b);
#if 1
#if 0
int64 r;
do {
r=iob_write(1,b,write_cb);
} while (r>0);

View File

@ -14,7 +14,7 @@ int worker(void* arg) {
uintptr_t i=(uintptr_t)arg;
char buf[100];
int64 s;
int events;
unsigned int events;
write(1,buf,sprintf(buf,"starting thread %ld\n",i));
@ -73,7 +73,10 @@ int main() {
if (thrd_join(x[i],&r)==-1)
#else
void* tmp;
if (pthread_join(x[i],&tmp)==-1, r=(int)(uintptr_t)tmp)
if (pthread_join(x[i],&tmp)!=-1)
r=(int)(uintptr_t)tmp;
else
#endif
{
perror("thrd_join");
@ -82,5 +85,7 @@ int main() {
printf("thread %d returned %d\n",i,r);
}
fflush(stdout);
return 0;
}

85
test/iomcli.c Normal file
View File

@ -0,0 +1,85 @@
#include <libowfat/socket.h>
#include <libowfat/io.h>
#include <libowfat/errmsg.h>
#include <libowfat/ip6.h>
#include <libowfat/fmt.h>
#include <libowfat/scan.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <threads.h>
#include <stdatomic.h>
iomux_t iom;
int s[32];
atomic_int n;
#define TRANSACTIONS 100000
int w(void* a) {
(void)a;
for (;;) {
int64 s;
unsigned int events;
switch (iom_wait(&iom,&s,&events,1000)) {
case -1:
diesys(111,"iom_wait");
break;
case 0:
carp("iom_wait: timeout");
break;
case 1:
if (events&IOM_WRITE) {
if (write(s,"salut!\n",7) != 7)
diesys(111,"write");
if (iom_requeue(&iom,s,IOM_READ) == -1)
diesys(111,"iom_requeue");
} else {
char buf[100];
ssize_t r=read(s,buf,sizeof buf);
if (r<=0 || atomic_fetch_add(&n,1) >= TRANSACTIONS) {
close(s);
return 0;
}
if (iom_requeue(&iom,s,IOM_WRITE) == -1)
diesys(111,"iom_requeue");
}
}
}
return 0;
}
int main(int argc,char* argv[]) {
iom_init(&iom);
for (unsigned int i=0; i<sizeof(s)/sizeof(s[0]); ++i) {
s[i]=socket_tcp6b();
errmsg_iam("iomcli");
if (s[i]==-1)
diesys(111,"socket");
if (socket_connect6(s[i],V6loopback,8000,0)==-1 && errno!=EINPROGRESS)
diesys(111,"connect");
if (iom_add(&iom,s[i],IOM_WRITE)==-1)
diesys(111,"iom_add");
}
thrd_t t[32];
unsigned int nthr=1;
if (argc>1 && scan_uint(argv[1],&nthr)>0) {
if (nthr>sizeof(t)/sizeof(t[0])) {
char buf[FMT_LONG];
buf[fmt_ulong(buf,sizeof(t)/sizeof(t[0]))]=0;
die(111,"max threads > ",buf);
}
}
for (unsigned int i=0; i<nthr; ++i) {
if (thrd_create(&t[i],w,0)!=thrd_success)
die(111,"thread creation failed");
}
for (unsigned int i=0; i<nthr; ++i) {
int retval;
if (thrd_join(t[i],&retval)!=thrd_success)
die(111,"thread join failed");
}
return 0;
}

114
test/iomsrv.c Normal file
View File

@ -0,0 +1,114 @@
#include <libowfat/socket.h>
#include <libowfat/io.h>
#include <libowfat/errmsg.h>
#include <libowfat/ip6.h>
#include <libowfat/fmt.h>
#include <libowfat/scan.h>
#include <assert.h>
#include <unistd.h>
#include <threads.h>
iomux_t iom;
void read_data_from_socket(int s) {
char buf[1024];
ssize_t r=read(s,buf,sizeof buf);
if (r==-1) {
r=fmt_str(buf,"I/O error from fd ");
r+=fmt_ulong(buf+r,s);
buf[r]=0;
carpsys(buf);
close(s);
return;
}
if (r==0) {
close(s);
return;
}
/* we'd usually have some protocol parsing here but for this
* simplistic test program we'll just accept any input as valid
* request */
if (iom_requeue(&iom,s,IOM_WRITE)!=0) {
carpsys("iom_requeue");
close(s);
}
}
void write_data_to_socket(int s) {
if (write(s,"hello, world!\n",14) != 14) {
carpsys("write");
close(s);
}
if (iom_requeue(&iom,s,IOM_READ)!=0) {
carpsys("iom_requeue");
close(s);
}
}
int w(void* a) {
int servsock=*(int*)a;
for (;;) {
int64 s;
unsigned int events;
switch (iom_wait(&iom,&s,&events,1000)) {
case -1:
diesys(111,"iom_wait");
break;
case 0:
carp("iom_wait: timeout");
break;
case 1:
if (s==servsock) {
char ip[16];
uint16 port;
uint32 scope_id;
int conn=socket_accept6(s,ip,&port,&scope_id);
if (conn==-1)
diesys(111,"accept");
if (iom_add(&iom,conn,IOM_READ)==-1)
diesys(111,"iom_add");
if (iom_requeue(&iom,s,IOM_READ)==-1)
diesys(111,"iom_requeue");
} else if (events&IOM_READ)
read_data_from_socket(s);
else
write_data_to_socket(s);
}
}
return 0;
}
int main(int argc,char* argv[]) {
int servsock=socket_tcp6();
errmsg_iam("iomsrv");
if (servsock==-1)
diesys(111,"socket");
if (socket_bind6_reuse(servsock,V6loopback,8000,0)==-1)
diesys(111,"bind to localhost:8000");
if (socket_listen(servsock,16)==-1)
diesys(111,"listen");
iom_init(&iom);
if (iom_add(&iom,servsock,IOM_READ)==-1)
diesys(111,"iom_add");
thrd_t t[32];
unsigned int nthr=1;
if (argc>1 && scan_uint(argv[1],&nthr)>0) {
if (nthr>sizeof(t)/sizeof(t[0])) {
char buf[FMT_LONG];
buf[fmt_ulong(buf,sizeof(t)/sizeof(t[0]))]=0;
die(111,"max threads > ",buf);
}
}
for (unsigned int i=0; i<nthr; ++i) {
if (thrd_create(&t[i],w,(void*)&servsock)!=thrd_success)
die(111,"thread creation failed");
}
for (unsigned int i=0; i<nthr; ++i) {
int retval;
if (thrd_join(t[i],&retval)!=thrd_success)
die(111,"thread join failed");
}
return 0;
}