MINOR: ring: make the applet code not depend on the CLI
The ring to applet communication was only made to deal with CLI functions but it's generic. Let's have generic appctx functions and have the CLI rely on these instead. This patch introduces ring_attach_appctx() and ring_detach_appctx().
This commit is contained in:
parent
9597cbd17a
commit
928068a74b
|
@ -30,6 +30,8 @@ struct ring *ring_new(size_t size);
|
||||||
struct ring *ring_resize(struct ring *ring, size_t size);
|
struct ring *ring_resize(struct ring *ring, size_t size);
|
||||||
void ring_free(struct ring *ring);
|
void ring_free(struct ring *ring);
|
||||||
ssize_t ring_write(struct ring *ring, size_t maxlen, const struct ist pfx[], size_t npfx, const struct ist msg[], size_t nmsg);
|
ssize_t ring_write(struct ring *ring, size_t maxlen, const struct ist pfx[], size_t npfx, const struct ist msg[], size_t nmsg);
|
||||||
|
int ring_attach_appctx(struct ring *ring, struct appctx *appctx);
|
||||||
|
void ring_detach_appctx(struct ring *ring, struct appctx *appctx, size_t ofs);
|
||||||
int ring_attach_cli(struct ring *ring, struct appctx *appctx);
|
int ring_attach_cli(struct ring *ring, struct appctx *appctx);
|
||||||
int cli_io_handler_show_ring(struct appctx *appctx);
|
int cli_io_handler_show_ring(struct appctx *appctx);
|
||||||
void cli_io_release_show_ring(struct appctx *appctx);
|
void cli_io_release_show_ring(struct appctx *appctx);
|
||||||
|
|
65
src/ring.c
65
src/ring.c
|
@ -199,6 +199,44 @@ ssize_t ring_write(struct ring *ring, size_t maxlen, const struct ist pfx[], siz
|
||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tries to attach appctx <appctx> as a new reader on ring <ring>. This is
|
||||||
|
* meant to be used by low level appctx code such as CLI or ring forwarding.
|
||||||
|
* For higher level functions, please see the relevant parts in appctx or CLI.
|
||||||
|
* It returns non-zero on success or zero on failure if too many users are
|
||||||
|
* already attached. On success, the caller MUST call ring_detach_appctx()
|
||||||
|
* to detach itself, even if it was never woken up.
|
||||||
|
*/
|
||||||
|
int ring_attach_appctx(struct ring *ring, struct appctx *appctx)
|
||||||
|
{
|
||||||
|
int users = ring->readers_count;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (users >= 255)
|
||||||
|
return 0;
|
||||||
|
} while (!_HA_ATOMIC_CAS(&ring->readers_count, &users, users + 1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* detach an appctx from a ring. The appctx is expected to be waiting at
|
||||||
|
* offset <ofs>. Nothing is done if <ring> is NULL.
|
||||||
|
*/
|
||||||
|
void ring_detach_appctx(struct ring *ring, struct appctx *appctx, size_t ofs)
|
||||||
|
{
|
||||||
|
if (!ring)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HA_RWLOCK_WRLOCK(LOGSRV_LOCK, &ring->lock);
|
||||||
|
if (ofs != ~0) {
|
||||||
|
/* reader was still attached */
|
||||||
|
ofs -= ring->ofs;
|
||||||
|
BUG_ON(ofs >= b_size(&ring->buf));
|
||||||
|
LIST_DEL_INIT(&appctx->wait_entry);
|
||||||
|
HA_ATOMIC_SUB(b_peek(&ring->buf, ofs), 1);
|
||||||
|
}
|
||||||
|
HA_ATOMIC_SUB(&ring->readers_count, 1);
|
||||||
|
HA_RWLOCK_WRUNLOCK(LOGSRV_LOCK, &ring->lock);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tries to attach CLI handler <appctx> as a new reader on ring <ring>. This is
|
/* Tries to attach CLI handler <appctx> as a new reader on ring <ring>. This is
|
||||||
* meant to be used when registering a CLI function to dump a buffer, so it
|
* meant to be used when registering a CLI function to dump a buffer, so it
|
||||||
* returns zero on success, or non-zero on failure with a message in the appctx
|
* returns zero on success, or non-zero on failure with a message in the appctx
|
||||||
|
@ -207,15 +245,10 @@ ssize_t ring_write(struct ring *ring, size_t maxlen, const struct ist pfx[], siz
|
||||||
*/
|
*/
|
||||||
int ring_attach_cli(struct ring *ring, struct appctx *appctx)
|
int ring_attach_cli(struct ring *ring, struct appctx *appctx)
|
||||||
{
|
{
|
||||||
int users = ring->readers_count;
|
if (!ring_attach_appctx(ring, appctx))
|
||||||
|
return cli_err(appctx,
|
||||||
do {
|
"Sorry, too many watchers (255) on this ring buffer. "
|
||||||
if (users >= 255)
|
"What could it have so interesting to attract so many watchers ?");
|
||||||
return cli_err(appctx,
|
|
||||||
"Sorry, too many watchers (255) on this ring buffer. "
|
|
||||||
"What could it have so interesting to attract so many watchers ?");
|
|
||||||
|
|
||||||
} while (!_HA_ATOMIC_CAS(&ring->readers_count, &users, users + 1));
|
|
||||||
|
|
||||||
if (!appctx->io_handler)
|
if (!appctx->io_handler)
|
||||||
appctx->io_handler = cli_io_handler_show_ring;
|
appctx->io_handler = cli_io_handler_show_ring;
|
||||||
|
@ -341,19 +374,7 @@ void cli_io_release_show_ring(struct appctx *appctx)
|
||||||
struct ring *ring = appctx->ctx.cli.p0;
|
struct ring *ring = appctx->ctx.cli.p0;
|
||||||
size_t ofs = appctx->ctx.cli.o0;
|
size_t ofs = appctx->ctx.cli.o0;
|
||||||
|
|
||||||
if (!ring)
|
ring_detach_appctx(ring, appctx, ofs);
|
||||||
return;
|
|
||||||
|
|
||||||
HA_RWLOCK_WRLOCK(LOGSRV_LOCK, &ring->lock);
|
|
||||||
if (ofs != ~0) {
|
|
||||||
/* reader was still attached */
|
|
||||||
ofs -= ring->ofs;
|
|
||||||
BUG_ON(ofs >= b_size(&ring->buf));
|
|
||||||
LIST_DEL_INIT(&appctx->wait_entry);
|
|
||||||
HA_ATOMIC_SUB(b_peek(&ring->buf, ofs), 1);
|
|
||||||
}
|
|
||||||
HA_ATOMIC_SUB(&ring->readers_count, 1);
|
|
||||||
HA_RWLOCK_WRUNLOCK(LOGSRV_LOCK, &ring->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue