Implement simple record boundary tracking in sbuf(9) to avoid record splitting
during drain operations. When an sbuf is configured to use this feature by way of the SBUF_DRAINTOEOR sbuf_new() flag, top-level sections started with sbuf_start_section() create a record boundary marker that is used to avoid flushing partial records. Reviewed by: cem,imp,wblock MFC after: 2 weeks Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D8536
This commit is contained in:
parent
cefde59f8f
commit
0923281ac1
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 5, 2017
|
||||
.Dd August 17, 2017
|
||||
.Dt SBUF 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -271,6 +271,14 @@ This indicates that the storage buffer may be extended as necessary, so long
|
||||
as resources allow, to hold additional data.
|
||||
.It Dv SBUF_INCLUDENUL
|
||||
This causes the final nulterm byte to be counted in the length of the data.
|
||||
.It Dv SBUF_DRAINTOEOR
|
||||
Treat top-level sections started with
|
||||
.Fn sbuf_start_section
|
||||
as a record boundary marker that will be used during drain operations to avoid
|
||||
records being split.
|
||||
If a record grows sufficiently large such that it fills the
|
||||
.Fa sbuf
|
||||
and therefore cannot be drained without being split, an error of EDEADLK is set.
|
||||
.El
|
||||
.Pp
|
||||
Note that if
|
||||
|
@ -73,6 +73,8 @@ static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
|
||||
#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
|
||||
#define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION)
|
||||
#define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL)
|
||||
#define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR)
|
||||
#define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s))
|
||||
|
||||
/*
|
||||
* Set / clear flags
|
||||
@ -308,6 +310,7 @@ sbuf_clear(struct sbuf *s)
|
||||
SBUF_CLEARFLAG(s, SBUF_FINISHED);
|
||||
s->s_error = 0;
|
||||
s->s_len = 0;
|
||||
s->s_rec_off = 0;
|
||||
s->s_sect_len = 0;
|
||||
}
|
||||
|
||||
@ -362,7 +365,10 @@ sbuf_drain(struct sbuf *s)
|
||||
|
||||
KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
|
||||
KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s));
|
||||
len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len);
|
||||
if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0)
|
||||
return (s->s_error = EDEADLK);
|
||||
len = s->s_drain_func(s->s_drain_arg, s->s_buf,
|
||||
SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len);
|
||||
if (len < 0) {
|
||||
s->s_error = -len;
|
||||
return (s->s_error);
|
||||
@ -370,6 +376,7 @@ sbuf_drain(struct sbuf *s)
|
||||
KASSERT(len > 0 && len <= s->s_len,
|
||||
("Bad drain amount %d for sbuf %p", len, s));
|
||||
s->s_len -= len;
|
||||
s->s_rec_off -= len;
|
||||
/*
|
||||
* Fast path for the expected case where all the data was
|
||||
* drained.
|
||||
@ -835,6 +842,7 @@ sbuf_start_section(struct sbuf *s, ssize_t *old_lenp)
|
||||
("s_sect_len != 0 when starting a section"));
|
||||
if (old_lenp != NULL)
|
||||
*old_lenp = -1;
|
||||
s->s_rec_off = s->s_len;
|
||||
SBUF_SETFLAG(s, SBUF_INSECTION);
|
||||
} else {
|
||||
KASSERT(old_lenp != NULL,
|
||||
@ -865,7 +873,7 @@ sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c)
|
||||
}
|
||||
len = s->s_sect_len;
|
||||
if (old_len == -1) {
|
||||
s->s_sect_len = 0;
|
||||
s->s_rec_off = s->s_sect_len = 0;
|
||||
SBUF_CLEARFLAG(s, SBUF_INSECTION);
|
||||
} else {
|
||||
s->s_sect_len += old_len;
|
||||
|
@ -49,6 +49,7 @@ struct sbuf {
|
||||
#define SBUF_FIXEDLEN 0x00000000 /* fixed length buffer (default) */
|
||||
#define SBUF_AUTOEXTEND 0x00000001 /* automatically extend buffer */
|
||||
#define SBUF_INCLUDENUL 0x00000002 /* nulterm byte is counted in len */
|
||||
#define SBUF_DRAINTOEOR 0x00000004 /* use section 0 as drain EOR marker */
|
||||
#define SBUF_USRFLAGMSK 0x0000ffff /* mask of flags the user may specify */
|
||||
#define SBUF_DYNAMIC 0x00010000 /* s_buf must be freed */
|
||||
#define SBUF_FINISHED 0x00020000 /* set by sbuf_finish() */
|
||||
@ -56,6 +57,7 @@ struct sbuf {
|
||||
#define SBUF_INSECTION 0x00100000 /* set by sbuf_start_section() */
|
||||
int s_flags; /* flags */
|
||||
ssize_t s_sect_len; /* current length of section */
|
||||
ssize_t s_rec_off; /* current record start offset */
|
||||
};
|
||||
|
||||
#ifndef HD_COLUMN_MASK
|
||||
|
Loading…
x
Reference in New Issue
Block a user