diff --git a/io/io_createfile.c b/io/io_createfile.c index a58dfb4..453d77b 100644 --- a/io/io_createfile.c +++ b/io/io_createfile.c @@ -6,11 +6,8 @@ int io_createfile(int64* d,const char* s) { long fd=open(s,O_WRONLY|O_CREAT|O_TRUNC,0600); if (fd != -1) { - if (io_fd(fd)) { - *d=fd; - return 1; - } - close(fd); + *d=fd; + return 1; } return 0; } diff --git a/io/io_readfile.c b/io/io_readfile.c index 177502b..7b262d5 100644 --- a/io/io_readfile.c +++ b/io/io_readfile.c @@ -6,11 +6,8 @@ int io_readfile(int64* d,const char* s) { long fd=open(s,O_RDONLY); if (fd != -1) { - if (io_fd(fd)) { - *d=fd; - return 1; - } - close(fd); + *d=fd; + return 1; } return 0; } diff --git a/io/iob_addbuf.c b/io/iob_addbuf.c new file mode 100644 index 0000000..3963555 --- /dev/null +++ b/io/iob_addbuf.c @@ -0,0 +1,15 @@ +#include "iob_internal.h" + +int iob_addbuf(io_batch* b,void* buf,uint64 n) { + io_entry* e=array_allocate(&b->b,sizeof(io_entry), + array_length(&b->b,sizeof(io_entry))); + if (!e) return 0; + e->type=FROMBUF; + e->fd=-1; + e->buf=buf; + e->n=n; + e->offset=0; + b->bytesleft+=n; + ++b->bufs; + return 1; +} diff --git a/io/iob_addfile.c b/io/iob_addfile.c new file mode 100644 index 0000000..4daf2e5 --- /dev/null +++ b/io/iob_addfile.c @@ -0,0 +1,15 @@ +#include "iob_internal.h" + +int iob_addfile(io_batch* b,int64 fd,uint64 off,uint64 n) { + io_entry* e=array_allocate(&b->b,sizeof(io_entry), + array_length(&b->b,sizeof(io_entry))); + if (!e) return 0; + e->type=FROMFILE; + e->fd=fd; + e->buf=0; + e->n=n; + e->offset=off; + b->bytesleft+=n; + ++b->files; + return 1; +} diff --git a/io/iob_new.c b/io/iob_new.c new file mode 100644 index 0000000..f4036f9 --- /dev/null +++ b/io/iob_new.c @@ -0,0 +1,17 @@ +#include +#include "iob_internal.h" + +io_batch* iob_new(int hint_entries) { + io_batch* b=(io_batch*)malloc(sizeof(io_batch)); + if (!b) return 0; + if (hint_entries) { + if (!array_allocate(&b->b,sizeof(io_entry),hint_entries)) { + free(b); + return 0; + } + array_trunc(&b->b); + } + b->next=b->bufs=b->files=0; + b->bytesleft=0; + return b; +} diff --git a/io/iob_reset.c b/io/iob_reset.c new file mode 100644 index 0000000..b5caa07 --- /dev/null +++ b/io/iob_reset.c @@ -0,0 +1,7 @@ +#include +#include "iob_internal.h" + +void iob_reset(io_batch* b) { + array_reset(&b->b); + free(b); +} diff --git a/io/iob_send.c b/io/iob_send.c new file mode 100644 index 0000000..06c2507 --- /dev/null +++ b/io/iob_send.c @@ -0,0 +1,83 @@ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#define BSD_SENDFILE +#endif + +#include +#include +#include +#include +#include + +#include "iob_internal.h" + +int64 iob_send(int64 s,io_batch* b) { + io_entry* e,* last; + struct iovec* v; + int64 sent; + long i; + long headers; +#ifdef BSD_SENDFILE + long trailers; +#endif + + if (b->bytesleft==0) return 0; + last=array_start(&b->b)+array_bytes(&b->b); + if (!(e=array_get(&b->b,sizeof(io_entry),b->next))) + return -1; /* can't happen error */ + v=alloca(b->bufs*sizeof(struct iovec)); +#ifdef BSD_SENDFILE + /* BSD sendfile can send headers and trailers. If we run on BSD, we + * should try to exploit this. */ + headers=trailers=0; +#endif + for (i=0; e+ibytesleft; + else if (r==-1 && errno==EAGAIN) + sent=sbytes; + else + sent=-1; + } else + sent=writev(s,v,headers); +#else + if (headers) + sent=writev(s,v,headers); + else + sent=io_sendfile(s,e->fd,e->offset,e->n); +#endif + if (sent==b->bytesleft) + b->bytesleft=0; + else if (sent>0) { + int64 rest=sent; + b->bytesleft-=rest; + for (i=0; e+inext; + } else { + e[i].offset+=rest; + break; + } + } + } + return sent; +} diff --git a/iob.h b/iob.h new file mode 100644 index 0000000..d0a49b8 --- /dev/null +++ b/iob.h @@ -0,0 +1,14 @@ +#ifndef _IOB_H +#define _IOB_H + +#include "io.h" + +typedef struct io_batch io_batch; + +io_batch* iob_new(int hint_entries); +int iob_addbuf(io_batch* b,void* buf,uint64 n); +int iob_addfile(io_batch* b,int64 fd,uint64 off,uint64 n); +int64 iob_send(int64 s,io_batch* b); +void iob_reset(io_batch* b); + +#endif diff --git a/iob_internal.h b/iob_internal.h new file mode 100644 index 0000000..fdabc35 --- /dev/null +++ b/iob_internal.h @@ -0,0 +1,15 @@ +#include "iob.h" +#include "array.h" + +struct io_batch { + array b; + uint64 bytesleft; + long next,bufs,files; +}; + +typedef struct io_entry { + enum { FROMBUF, FROMFILE } type; + int64 fd; + char* buf; + uint64 offset,n; +} io_entry;