2019-08-08 09:28:52 -04:00
|
|
|
/*
|
2020-06-03 13:43:35 -04:00
|
|
|
* include/haproxy/ring.h
|
|
|
|
|
* Exported functions for ring buffers used for disposable data.
|
2019-08-08 09:28:52 -04:00
|
|
|
*
|
|
|
|
|
* Copyright (C) 2000-2019 Willy Tarreau - w@1wt.eu
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
|
|
|
* exclusively.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
2020-06-03 13:43:35 -04:00
|
|
|
#ifndef _HAPROXY_RING_H
|
|
|
|
|
#define _HAPROXY_RING_H
|
2019-08-08 09:28:52 -04:00
|
|
|
|
2019-08-27 05:44:13 -04:00
|
|
|
#include <stdlib.h>
|
2020-05-27 10:21:26 -04:00
|
|
|
#include <import/ist.h>
|
2020-06-03 13:43:35 -04:00
|
|
|
#include <haproxy/ring-t.h>
|
2024-02-27 03:17:45 -05:00
|
|
|
#include <haproxy/vecpair.h>
|
2019-08-08 09:28:52 -04:00
|
|
|
|
2022-08-12 03:31:16 -04:00
|
|
|
struct appctx;
|
|
|
|
|
|
2019-08-08 09:28:52 -04:00
|
|
|
struct ring *ring_new(size_t size);
|
MAJOR: ring: insert an intermediary ring_storage level
We'll need to add more complex structures in the ring, such as wait
queues. That's far too much to be stored into the area in case of
file-backed contents, so let's split the ring definition and its
storage once for all.
This patch introduces a struct ring_storage which is assigned to
ring->storage, which contains minimal information to represent the
storage layout, i.e. for now only the buffer, and all the rest
remains in the ring itself. The storage is appended immediately after
it and the buffer's pointer always points to that area. It has the
benefit of remaining 100% compatible with the existing file-backed
layout. In memory, the allocation loses the size of a struct buffer.
It's not even certain it's worth placing the size there, given that it's
constant and that a dump of a ring wouldn't really need it (the file size
is sufficient). But for now everything comes with the struct buffer, and
later this will change once split into head and tail. Also this area may
be completed with more information in the future (e.g. storage version,
format, endianness, word size etc).
2024-03-03 11:20:10 -05:00
|
|
|
struct ring *ring_make_from_area(void *area, size_t size, int reset);
|
|
|
|
|
void ring_init(struct ring *ring, void *area, size_t size, int reset);
|
2019-08-08 09:28:52 -04:00
|
|
|
struct ring *ring_resize(struct ring *ring, size_t size);
|
|
|
|
|
void ring_free(struct ring *ring);
|
2019-08-27 05:44:13 -04:00
|
|
|
ssize_t ring_write(struct ring *ring, size_t maxlen, const struct ist pfx[], size_t npfx, const struct ist msg[], size_t nmsg);
|
2020-05-28 08:39:30 -04:00
|
|
|
int ring_attach(struct ring *ring);
|
2020-05-19 13:14:42 -04:00
|
|
|
void ring_detach_appctx(struct ring *ring, struct appctx *appctx, size_t ofs);
|
2022-05-05 09:18:57 -04:00
|
|
|
int ring_attach_cli(struct ring *ring, struct appctx *appctx, uint flags);
|
2019-08-27 05:55:39 -04:00
|
|
|
int cli_io_handler_show_ring(struct appctx *appctx);
|
|
|
|
|
void cli_io_release_show_ring(struct appctx *appctx);
|
2019-08-08 09:28:52 -04:00
|
|
|
|
2023-06-26 13:22:38 -04:00
|
|
|
size_t ring_max_payload(const struct ring *ring);
|
2024-02-27 10:54:18 -05:00
|
|
|
int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t *last_ofs_ptr, uint flags,
|
2025-03-31 12:17:35 -04:00
|
|
|
ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len, char delim),
|
|
|
|
|
char delim,
|
2024-07-22 05:17:08 -04:00
|
|
|
size_t *processed);
|
2023-06-26 13:22:38 -04:00
|
|
|
|
2024-05-21 05:13:46 -04:00
|
|
|
/* returns the ring storage's usable area */
|
2024-03-06 10:40:39 -05:00
|
|
|
static inline void *ring_area(const struct ring *ring)
|
|
|
|
|
{
|
2024-02-27 03:17:45 -05:00
|
|
|
return ring->storage->area;
|
2024-03-06 10:40:39 -05:00
|
|
|
}
|
|
|
|
|
|
2024-05-21 05:13:46 -04:00
|
|
|
/* returns the allocated area for the ring. It covers the whole
|
|
|
|
|
* area made of both the ring_storage and the usable area.
|
|
|
|
|
*/
|
|
|
|
|
static inline void *ring_allocated_area(const struct ring *ring)
|
|
|
|
|
{
|
|
|
|
|
return ring->storage;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-27 03:12:19 -05:00
|
|
|
/* returns the number of bytes in the ring */
|
|
|
|
|
static inline size_t ring_data(const struct ring *ring)
|
|
|
|
|
{
|
2024-02-28 03:37:47 -05:00
|
|
|
size_t tail = HA_ATOMIC_LOAD(&ring->storage->tail) & ~RING_TAIL_LOCK;
|
|
|
|
|
|
|
|
|
|
return ((ring->storage->head <= tail) ?
|
|
|
|
|
0 : ring->storage->size) + tail - ring->storage->head;
|
2024-02-27 03:12:19 -05:00
|
|
|
}
|
|
|
|
|
|
2024-04-15 02:25:03 -04:00
|
|
|
/* returns the usable size in bytes for the ring. It is smaller than
|
|
|
|
|
* the allocate size by the size of the ring_storage header.
|
|
|
|
|
*/
|
2024-02-27 12:53:40 -05:00
|
|
|
static inline size_t ring_size(const struct ring *ring)
|
|
|
|
|
{
|
2024-02-27 03:17:45 -05:00
|
|
|
return ring->storage->size;
|
2024-02-27 12:53:40 -05:00
|
|
|
}
|
|
|
|
|
|
2024-04-15 02:25:03 -04:00
|
|
|
/* returns the allocated size in bytes for the ring. It covers the whole
|
|
|
|
|
* area made of both the ring_storage and the usable area.
|
|
|
|
|
*/
|
|
|
|
|
static inline size_t ring_allocated_size(const struct ring *ring)
|
|
|
|
|
{
|
|
|
|
|
return ring->storage->size + ring->storage->rsvd;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 10:40:39 -05:00
|
|
|
/* returns the head offset of the ring */
|
|
|
|
|
static inline size_t ring_head(const struct ring *ring)
|
|
|
|
|
{
|
2024-02-27 03:17:45 -05:00
|
|
|
return ring->storage->head;
|
2024-03-06 10:40:39 -05:00
|
|
|
}
|
|
|
|
|
|
2024-02-28 03:37:47 -05:00
|
|
|
/* returns the ring's tail offset without the lock bit */
|
2024-03-06 10:40:39 -05:00
|
|
|
static inline size_t ring_tail(const struct ring *ring)
|
|
|
|
|
{
|
2024-02-28 03:37:47 -05:00
|
|
|
return HA_ATOMIC_LOAD(&ring->storage->tail) & ~RING_TAIL_LOCK;
|
2024-03-06 10:40:39 -05:00
|
|
|
}
|
|
|
|
|
|
2024-02-27 13:52:00 -05:00
|
|
|
/* duplicates ring <src> over ring <dst> for no more than <max> bytes or no
|
|
|
|
|
* more than the amount of data present in <src>. It's assumed that the
|
|
|
|
|
* destination ring is always large enough for <max>. The number of bytes
|
|
|
|
|
* copied (the min of src's size and max) is returned.
|
|
|
|
|
*/
|
|
|
|
|
static inline size_t ring_dup(struct ring *dst, const struct ring *src, size_t max)
|
|
|
|
|
{
|
2024-02-27 03:17:45 -05:00
|
|
|
struct ist v1, v2;
|
|
|
|
|
|
|
|
|
|
vp_ring_to_data(&v1, &v2, ring_area(src), ring_size(src), ring_head(src), ring_tail(src));
|
|
|
|
|
|
2024-02-27 13:52:00 -05:00
|
|
|
if (max > ring_data(src))
|
|
|
|
|
max = ring_data(src);
|
|
|
|
|
|
2024-04-15 02:31:01 -04:00
|
|
|
BUG_ON(max > ring_size(dst));
|
|
|
|
|
|
2024-02-27 03:17:45 -05:00
|
|
|
vp_peek_ofs(v1, v2, 0, ring_area(dst), max);
|
|
|
|
|
dst->storage->head = 0;
|
|
|
|
|
dst->storage->tail = max;
|
2024-02-27 13:52:00 -05:00
|
|
|
return max;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-03 13:43:35 -04:00
|
|
|
#endif /* _HAPROXY_RING_H */
|
2019-08-08 09:28:52 -04:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Local variables:
|
|
|
|
|
* c-indent-level: 8
|
|
|
|
|
* c-basic-offset: 8
|
|
|
|
|
* End:
|
|
|
|
|
*/
|