mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-24 13:42:16 +00:00
MINOR: fd: add fd_write_frag_line() to send a fragmented line to an fd
Currently both logs and event sinks may use a file descriptor to atomically emit some output contents. The two may use the same FD though nothing is done to make sure they use the same lock. Also there is quite some redundancy between the two. Better make a specific function to send a fragmented message to a file descriptor which will take care of the locking via the fd's lock. The function is also able to truncate a message and to enforce addition of a trailing LF when building the output message.
This commit is contained in:
parent
b88d231773
commit
931d8b79a8
@ -60,6 +60,8 @@ void fd_delete(int fd);
|
||||
*/
|
||||
void fd_remove(int fd);
|
||||
|
||||
ssize_t fd_write_frag_line(int fd, size_t maxlen, const struct ist pfx[], size_t npfx, const struct ist msg[], size_t nmsg, int nl);
|
||||
|
||||
/* close all FDs starting from <start> */
|
||||
void my_closefrom(int start);
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <common/ist.h>
|
||||
#include <types/port_range.h>
|
||||
|
||||
/* Direction for each FD event update */
|
||||
|
60
src/fd.c
60
src/fd.c
@ -106,6 +106,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#if defined(USE_POLL)
|
||||
#include <poll.h>
|
||||
@ -362,6 +363,65 @@ void fd_remove(int fd)
|
||||
fd_dodelete(fd, 0);
|
||||
}
|
||||
|
||||
/* Tries to send <npfx> parts from <prefix> followed by <nmsg> parts from <msg>
|
||||
* optionally followed by a newline if <nl> is non-null, to file descriptor
|
||||
* <fd>. The message is sent atomically using writev(). It may be truncated to
|
||||
* <maxlen> bytes if <maxlen> is non-null. There is no distinction between the
|
||||
* two lists, it's just a convenience to help the caller prepend some prefixes
|
||||
* when necessary. It takes the fd's lock to make sure no other thread will
|
||||
* write to the same fd in parallel. Returns the number of bytes sent, or <=0
|
||||
* on failure. A limit to 31 total non-empty segments is enforced. The caller
|
||||
* is responsible for taking care of making the fd non-blocking.
|
||||
*/
|
||||
ssize_t fd_write_frag_line(int fd, size_t maxlen, const struct ist pfx[], size_t npfx, const struct ist msg[], size_t nmsg, int nl)
|
||||
{
|
||||
struct iovec iovec[32];
|
||||
size_t totlen = 0;
|
||||
size_t sent = 0;
|
||||
int vec = 0;
|
||||
|
||||
if (!maxlen)
|
||||
maxlen = ~0;
|
||||
|
||||
/* keep one char for a possible trailing '\n' in any case */
|
||||
maxlen--;
|
||||
|
||||
/* make an iovec from the concatenation of all parts of the original
|
||||
* message. Skip empty fields and truncate the whole message to maxlen,
|
||||
* leaving one spare iovec for the '\n'.
|
||||
*/
|
||||
while (vec < (sizeof(iovec) / sizeof(iovec[0]) - 1)) {
|
||||
if (!npfx) {
|
||||
pfx = msg;
|
||||
npfx = nmsg;
|
||||
nmsg = 0;
|
||||
if (!npfx)
|
||||
break;
|
||||
}
|
||||
|
||||
iovec[vec].iov_base = pfx->ptr;
|
||||
iovec[vec].iov_len = MIN(maxlen, pfx->len);
|
||||
maxlen -= iovec[vec].iov_len;
|
||||
totlen += iovec[vec].iov_len;
|
||||
if (iovec[vec].iov_len)
|
||||
vec++;
|
||||
pfx++; npfx--;
|
||||
};
|
||||
|
||||
if (nl) {
|
||||
iovec[vec].iov_base = "\n";
|
||||
iovec[vec].iov_len = 1;
|
||||
vec++;
|
||||
}
|
||||
|
||||
HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock);
|
||||
sent = writev(fd, iovec, vec);
|
||||
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
|
||||
|
||||
/* sent > 0 if the message was delivered */
|
||||
return sent;
|
||||
}
|
||||
|
||||
#if defined(USE_CLOSEFROM)
|
||||
void my_closefrom(int start)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user