lib: add meta_hash to connection, eliminate hash_offt

With a meta_hash at each connection (similar to easy handle, let
multi_ev.c store its pollsets as meta data, no longer needing its own
hashes.

This eliminates the last use of Curl_hash_offt. Remove it.

Closes #17095
This commit is contained in:
Stefan Eissing 2025-04-18 11:03:29 +02:00 committed by Daniel Stenberg
parent 1d66a769d7
commit 657aae79c0
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
18 changed files with 126 additions and 343 deletions

View file

@ -27,6 +27,7 @@
#include <curl/curl.h>
#include "urldata.h"
#include "url.h"
#include "cfilters.h"
#include "curl_trc.h"
#include "multiif.h"
@ -57,7 +58,7 @@ static void mev_in_callback(struct Curl_multi *multi, bool value)
*/
struct mev_sh_entry {
struct uint_spbset xfers; /* bitset of transfers `mid`s on this socket */
struct Curl_hash_offt conns; /* hash of connections using this socket */
struct connectdata *conn; /* connection using this socket or NULL */
void *user_data; /* libcurl app data via curl_multi_assign() */
unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the
* libcurl application to watch out for */
@ -84,7 +85,6 @@ static void mev_sh_entry_dtor(void *freethis)
{
struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis;
Curl_uint_spbset_destroy(&entry->xfers);
Curl_hash_offt_destroy(&entry->conns);
free(entry);
}
@ -117,7 +117,6 @@ mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
return NULL; /* major failure */
Curl_uint_spbset_init(&check->xfers);
Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, NULL);
/* make/add new hash entry */
if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
@ -136,7 +135,7 @@ static void mev_sh_entry_kill(struct Curl_multi *multi, curl_socket_t s)
static size_t mev_sh_entry_user_count(struct mev_sh_entry *e)
{
return Curl_uint_spbset_count(&e->xfers) + Curl_hash_offt_count(&e->conns);
return Curl_uint_spbset_count(&e->xfers) + (e->conn ? 1 : 0);
}
static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e,
@ -148,7 +147,7 @@ static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e,
static bool mev_sh_entry_conn_known(struct mev_sh_entry *e,
struct connectdata *conn)
{
return !!Curl_hash_offt_get(&e->conns, conn->connection_id);
return (e->conn == conn);
}
static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e,
@ -164,7 +163,11 @@ static bool mev_sh_entry_conn_add(struct mev_sh_entry *e,
{
/* detect weird values */
DEBUGASSERT(mev_sh_entry_user_count(e) < 100000);
return !!Curl_hash_offt_set(&e->conns, conn->connection_id, conn);
DEBUGASSERT(!e->conn);
if(e->conn)
return FALSE;
e->conn = conn;
return TRUE;
}
@ -180,7 +183,12 @@ static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e,
static bool mev_sh_entry_conn_remove(struct mev_sh_entry *e,
struct connectdata *conn)
{
return Curl_hash_offt_remove(&e->conns, conn->connection_id);
DEBUGASSERT(e->conn == conn);
if(e->conn == conn) {
e->conn = NULL;
return TRUE;
}
return FALSE;
}
/* Purge any information about socket `s`.
@ -344,11 +352,11 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
return CURLM_OUT_OF_MEMORY;
}
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", added %s #%" FMT_OFF_T
", total=%u/%zu (xfer/conn)", s,
", total=%u/%d (xfer/conn)", s,
conn ? "connection" : "transfer",
conn ? conn->connection_id : data->mid,
Curl_uint_spbset_count(&entry->xfers),
Curl_hash_offt_count(&entry->conns));
entry->conn ? 1 : 0);
}
else {
for(j = 0; j < prev_ps->num; j++) {
@ -414,9 +422,9 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
if(mresult)
return mresult;
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, "
"total=%u/%zu (xfer/conn)", s,
"total=%u/%d (xfer/conn)", s,
Curl_uint_spbset_count(&entry->xfers),
Curl_hash_offt_count(&entry->conns));
entry->conn ? 1 : 0);
}
else {
mresult = mev_forget_socket(multi, data, s, "last user gone");
@ -430,15 +438,22 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
return CURLM_OK;
}
static void mev_pollset_dtor(void *key, size_t klen, void *entry)
{
(void)key;
(void)klen;
free(entry);
}
static struct easy_pollset*
mev_add_new_conn_pollset(struct Curl_hash_offt *h, curl_off_t id)
mev_add_new_conn_pollset(struct connectdata *conn)
{
struct easy_pollset *ps;
ps = calloc(1, sizeof(*ps));
if(!ps)
return NULL;
if(!Curl_hash_offt_set(h, id, ps)) {
if(Curl_conn_meta_set(conn, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor)) {
free(ps);
return NULL;
}
@ -446,14 +461,14 @@ mev_add_new_conn_pollset(struct Curl_hash_offt *h, curl_off_t id)
}
static struct easy_pollset*
mev_add_new_xfer_pollset(struct uint_hash *h, unsigned int id)
mev_add_new_xfer_pollset(struct Curl_easy *data)
{
struct easy_pollset *ps;
ps = calloc(1, sizeof(*ps));
if(!ps)
return NULL;
if(!Curl_uint_hash_set(h, id, ps)) {
if(Curl_meta_set(data, CURL_META_MEV_POLLSET, ps, mev_pollset_dtor)) {
free(ps);
return NULL;
}
@ -461,16 +476,14 @@ mev_add_new_xfer_pollset(struct uint_hash *h, unsigned int id)
}
static struct easy_pollset *
mev_get_last_pollset(struct Curl_multi *multi,
struct Curl_easy *data,
mev_get_last_pollset(struct Curl_easy *data,
struct connectdata *conn)
{
if(data) {
if(conn)
return Curl_hash_offt_get(&multi->ev.conn_pollsets,
conn->connection_id);
return Curl_conn_meta_get(conn, CURL_META_MEV_POLLSET);
else if(data)
return Curl_uint_hash_get(&multi->ev.xfer_pollsets, data->mid);
return Curl_meta_get(data, CURL_META_MEV_POLLSET);
}
return NULL;
}
@ -494,15 +507,13 @@ static CURLMcode mev_assess(struct Curl_multi *multi,
struct easy_pollset ps, *last_ps;
mev_init_cur_pollset(&ps, data, conn);
last_ps = mev_get_last_pollset(multi, data, conn);
last_ps = mev_get_last_pollset(data, conn);
if(!last_ps && ps.num) {
if(conn)
last_ps = mev_add_new_conn_pollset(&multi->ev.conn_pollsets,
conn->connection_id);
last_ps = mev_add_new_conn_pollset(conn);
else
last_ps = mev_add_new_xfer_pollset(&multi->ev.xfer_pollsets,
data->mid);
last_ps = mev_add_new_xfer_pollset(data);
if(!last_ps)
return CURLM_OUT_OF_MEMORY;
}
@ -588,7 +599,7 @@ void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
while(Curl_uint_spbset_next(&entry->xfers, mid, &mid));
}
if(Curl_hash_offt_count(&entry->conns))
if(entry->conn)
*run_cpool = TRUE;
}
}
@ -605,7 +616,7 @@ void Curl_multi_ev_xfer_done(struct Curl_multi *multi,
DEBUGASSERT(!data->conn); /* transfer should have been detached */
if(data != multi->admin) {
(void)mev_assess(multi, data, NULL);
Curl_uint_hash_remove(&multi->ev.xfer_pollsets, data->mid);
Curl_meta_remove(data, CURL_META_MEV_POLLSET);
}
}
@ -614,36 +625,18 @@ void Curl_multi_ev_conn_done(struct Curl_multi *multi,
struct connectdata *conn)
{
(void)mev_assess(multi, data, conn);
Curl_hash_offt_remove(&multi->ev.conn_pollsets, conn->connection_id);
Curl_conn_meta_remove(conn, CURL_META_MEV_POLLSET);
}
#define CURL_MEV_PS_HASH_SLOTS (991) /* nice prime */
static void mev_hash_conn_pollset_free(curl_off_t id, void *entry)
{
(void)id;
free(entry);
}
static void mev_hash_xfer_pollset_free(unsigned int id, void *entry)
{
(void)id;
free(entry);
}
void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize)
{
Curl_hash_init(&multi->ev.sh_entries, hashsize, mev_sh_entry_hash,
mev_sh_entry_compare, mev_sh_entry_dtor);
Curl_uint_hash_init(&multi->ev.xfer_pollsets,
CURL_MEV_PS_HASH_SLOTS, mev_hash_xfer_pollset_free);
Curl_hash_offt_init(&multi->ev.conn_pollsets,
CURL_MEV_PS_HASH_SLOTS, mev_hash_conn_pollset_free);
}
void Curl_multi_ev_cleanup(struct Curl_multi *multi)
{
Curl_hash_destroy(&multi->ev.sh_entries);
Curl_uint_hash_destroy(&multi->ev.xfer_pollsets);
Curl_hash_offt_destroy(&multi->ev.conn_pollsets);
}