]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
lib: add meta_hash to connection, eliminate hash_offt
authorStefan Eissing <stefan@eissing.org>
Fri, 18 Apr 2025 09:03:29 +0000 (11:03 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 22 Apr 2025 13:57:18 +0000 (15:57 +0200)
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

18 files changed:
docs/internals/HASH.md
docs/internals/UINT_SETS.md
lib/Makefile.inc
lib/doh.c
lib/easy.c
lib/http2.c
lib/multi_ev.c
lib/multi_ev.h
lib/uint-hash.c [moved from lib/hash_offt.c with 55% similarity]
lib/uint-hash.h [moved from lib/hash_offt.h with 70% similarity]
lib/url.c
lib/url.h
lib/urldata.h
lib/vquic/curl_msh3.c
lib/vquic/curl_ngtcp2.c
lib/vquic/curl_quiche.c
tests/data/test1616
tests/unit/unit1616.c

index 5a5bdc9838114dc74735796fb9ad48c854e4f2a4..9534eb7d1ac9a7496c26371e6fd064944595737c 100644 (file)
@@ -149,40 +149,3 @@ Called repeatedly, it iterates over all the entries in the hash table.
 
 Note: it only guarantees functionality if the hash table remains untouched
 during its iteration.
-
-# `curl_off_t` dedicated hash functions
-
-## `Curl_hash_offt_init`
-
-~~~c
-void Curl_hash_offt_init(struct Curl_hash *h,
-                         size_t slots,
-                         Curl_hash_dtor dtor);
-~~~
-
-Initializes a hash table for `curl_off_t` values. Pass in desired number of
-`slots` and `dtor` function.
-
-## `Curl_hash_offt_set`
-
-~~~c
-void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem);
-~~~
-
-Associate a custom `elem` pointer with the given `id`.
-
-## `Curl_hash_offt_remove`
-
-~~~c
-int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id);
-~~~
-
-Remove the `id` from the hash.
-
-## `Curl_hash_offt_get`
-
-~~~c
-void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id);
-~~~
-
-Get the pointer associated with the specified `id`.
index 38509e308de286e74bd74b55b91e3fa3c92d6cd7..de00b9b47a301453cde48415998287615de8f494 100644 (file)
@@ -126,6 +126,3 @@ Iterating a sparse bitset works the same as for bitset and table.
 At last, there are places in libcurl such as the HTTP/2 and HTTP/3 protocol implementations that need
 to store their own data related to a transfer. `uint_hash` allows then to associate an unsigned int,
 e.g. the transfer's `mid`, to their own data.
-
-This is just a variation of `hash_offt` that can associate data with a `connection_id`. Which
-is a specialization of the generic `Curl_hash`.
index 0b034df92ee13e53f1027c66966429df653f2234..414c9559457b7c09dd15367a76a1f2e0a074c0ee 100644 (file)
@@ -164,7 +164,6 @@ LIB_CFILES =         \
   getinfo.c          \
   gopher.c           \
   hash.c             \
-  hash_offt.c        \
   headers.c          \
   hmac.c             \
   hostip.c           \
@@ -237,6 +236,7 @@ LIB_CFILES =         \
   timeval.c          \
   transfer.c         \
   uint-bset.c        \
+  uint-hash.c        \
   uint-spbset.c      \
   uint-table.c       \
   url.c              \
@@ -314,7 +314,6 @@ LIB_HFILES =         \
   getinfo.h          \
   gopher.h           \
   hash.h             \
-  hash_offt.h        \
   headers.h          \
   hostip.h           \
   hsts.h             \
@@ -380,6 +379,7 @@ LIB_HFILES =         \
   timeval.h          \
   transfer.h         \
   uint-bset.h        \
+  uint-hash.h        \
   uint-spbset.h      \
   uint-table.h       \
   url.h              \
index 25d4fc43d25d2b54f8c1edf3222528a2599c1d62..027b138e2577ec1fa9d4a7e08f11e084b27a6e15 100644 (file)
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -249,7 +249,7 @@ static void doh_probe_done(struct Curl_easy *data,
                                Curl_dyn_len(&doh_req->resp_body));
         Curl_dyn_free(&doh_req->resp_body);
       }
-      Curl_meta_clear(doh, CURL_EZM_DOH_PROBE);
+      Curl_meta_remove(doh, CURL_EZM_DOH_PROBE);
     }
 
     if(result)
index f63c73c8af7aeacbd734450ef9d25a789fecb2e0..8e95fe7311b6cd8c9b25dcb52be4da7d5afe658e 100644 (file)
@@ -1419,7 +1419,7 @@ CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
   return CURLE_OK;
 }
 
-void Curl_meta_clear(struct Curl_easy *data, const char *key)
+void Curl_meta_remove(struct Curl_easy *data, const char *key)
 {
   Curl_hash_delete(&data->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
 }
index 9423a5d2a149ff1c9757dabf29d54e85e232fcc1..84be0797a9110de667d337c5cebc20075d3f60f9 100644 (file)
@@ -29,7 +29,7 @@
 #include <nghttp2/nghttp2.h>
 #include "urldata.h"
 #include "bufq.h"
-#include "hash_offt.h"
+#include "uint-hash.h"
 #include "http1.h"
 #include "http2.h"
 #include "http.h"
index 96595387c6c9902a2b65c9388f07efd1489cc3eb..9e2b039edfca1fcc288e46e2bf60ef95e554dacb 100644 (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);
 }
index 3aa6cca24ce9c8becf562dc019919a8f83d46468..06be842fb96ebe218861dce2fa8d28ce9e0261c1 100644 (file)
  ***************************************************************************/
 
 #include "hash.h"
-#include "hash_offt.h"
 
 struct Curl_easy;
 struct Curl_multi;
 struct easy_pollset;
 struct uint_bset;
 
+/* meta key for event pollset at easy handle or connection */
+#define CURL_META_MEV_POLLSET   "meta:mev:ps"
+
 struct curl_multi_ev {
   struct Curl_hash sh_entries;
-  struct uint_hash xfer_pollsets;
-  struct Curl_hash_offt conn_pollsets;
 };
 
 /* Setup/teardown of multi event book-keeping. */
similarity index 55%
rename from lib/hash_offt.c
rename to lib/uint-hash.c
index cef29742a2068b3fb777cbab5bb7d6e3c06cfb76..afeb684d0cab341cba8d3fd1b6641c303ece2697 100644 (file)
 
 #include <curl/curl.h>
 
-#include "hash_offt.h"
+#include "uint-hash.h"
 #include "curl_memory.h"
 
 /* The last #include file should be: */
 #include "memdebug.h"
 
-/* random patterns for API verification */
-#ifdef DEBUGBUILD
-#define CURL_HASHOFFTINIT 0x7117e781
-#endif
-
-static size_t hash_offt_hash(curl_off_t id, size_t slots)
-{
-  return (size_t)((id >= 0) ? (id % slots) : (-id % slots));
-}
-
-struct Curl_hash_offt_entry {
-  curl_off_t id;
-  struct Curl_hash_offt_entry *next;
-  void   *value;
-};
-
-void Curl_hash_offt_init(struct Curl_hash_offt *h,
-                         size_t slots,
-                         Curl_hash_offt_dtor *dtor)
-{
-  DEBUGASSERT(h);
-  DEBUGASSERT(slots);
-
-  h->table = NULL;
-  h->dtor = dtor;
-  h->size = 0;
-  h->slots = slots;
-#ifdef DEBUGBUILD
-  h->init = CURL_HASHOFFTINIT;
-#endif
-}
-
-static struct Curl_hash_offt_entry *
-hash_offt_mk_entry(curl_off_t id, void *value)
-{
-  struct Curl_hash_offt_entry *e;
-
-  /* allocate the struct for the hash entry */
-  e = malloc(sizeof(*e));
-  if(e) {
-    e->id = id;
-    e->next = NULL;
-    e->value = value;
-  }
-  return e;
-}
-
-static void hash_offt_entry_clear(struct Curl_hash_offt *h,
-                                  struct Curl_hash_offt_entry *e)
-{
-  DEBUGASSERT(h);
-  DEBUGASSERT(e);
-  if(e->value) {
-    if(h->dtor)
-      h->dtor(e->id, e->value);
-    e->value = NULL;
-  }
-}
-
-static void hash_offt_entry_destroy(struct Curl_hash_offt *h,
-                                    struct Curl_hash_offt_entry *e)
-{
-  hash_offt_entry_clear(h, e);
-  free(e);
-}
-
-static void hash_offt_entry_unlink(struct Curl_hash_offt *h,
-                                   struct Curl_hash_offt_entry **he_anchor,
-                                   struct Curl_hash_offt_entry *he)
-{
-  *he_anchor = he->next;
-  --h->size;
-}
-
-static void hash_offtr_elem_link(struct Curl_hash_offt *h,
-                                 struct Curl_hash_offt_entry **he_anchor,
-                                 struct Curl_hash_offt_entry *he)
-{
-  he->next = *he_anchor;
-  *he_anchor = he;
-  ++h->size;
-}
-
-#define CURL_HASH_OFFT_SLOT(h,id)  h->table[hash_offt_hash(id, h->slots)]
-#define CURL_HASH_OFFT_SLOT_ADDR(h,id) &CURL_HASH_OFFT_SLOT(h,id)
-
-bool Curl_hash_offt_set(struct Curl_hash_offt *h, curl_off_t id, void *value)
-{
-  struct Curl_hash_offt_entry *he, **slot;
-
-  DEBUGASSERT(h);
-  DEBUGASSERT(h->slots);
-  DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
-  if(!h->table) {
-    h->table = calloc(h->slots, sizeof(*he));
-    if(!h->table)
-      return FALSE; /* OOM */
-  }
-
-  slot = CURL_HASH_OFFT_SLOT_ADDR(h, id);
-  for(he = *slot; he; he = he->next) {
-    if(he->id == id) {
-      /* existing key entry, overwrite by clearing old pointer */
-      hash_offt_entry_clear(h, he);
-      he->value = value;
-      return TRUE;
-    }
-  }
-
-  he = hash_offt_mk_entry(id, value);
-  if(!he)
-    return FALSE; /* OOM */
-
-  hash_offtr_elem_link(h, slot, he);
-  return TRUE;
-}
-
-bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id)
-{
-  DEBUGASSERT(h);
-  DEBUGASSERT(h->slots);
-  DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
-  if(h->table) {
-    struct Curl_hash_offt_entry *he, **he_anchor;
-
-    he_anchor = CURL_HASH_OFFT_SLOT_ADDR(h, id);
-    while(*he_anchor) {
-      he = *he_anchor;
-      if(id == he->id) {
-        hash_offt_entry_unlink(h, he_anchor, he);
-        hash_offt_entry_destroy(h, he);
-        return TRUE;
-      }
-      he_anchor = &he->next;
-    }
-  }
-  return FALSE;
-}
-
-void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id)
-{
-  DEBUGASSERT(h);
-  DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
-  if(h->table) {
-    struct Curl_hash_offt_entry *he;
-    DEBUGASSERT(h->slots);
-    he = CURL_HASH_OFFT_SLOT(h, id);
-    while(he) {
-      if(id == he->id) {
-        return he->value;
-      }
-      he = he->next;
-    }
-  }
-  return NULL;
-}
-
-void Curl_hash_offt_clear(struct Curl_hash_offt *h)
-{
-  if(h && h->table) {
-    struct Curl_hash_offt_entry *he, **he_anchor;
-    size_t i;
-    DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
-    for(i = 0; i < h->slots; ++i) {
-      he_anchor = &h->table[i];
-      while(*he_anchor) {
-        he = *he_anchor;
-        hash_offt_entry_unlink(h, he_anchor, he);
-        hash_offt_entry_destroy(h, he);
-      }
-    }
-  }
-}
-
-void
-Curl_hash_offt_destroy(struct Curl_hash_offt *h)
-{
-  DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
-  if(h->table) {
-    Curl_hash_offt_clear(h);
-    Curl_safefree(h->table);
-  }
-  DEBUGASSERT(h->size == 0);
-  h->slots = 0;
-}
-
-size_t Curl_hash_offt_count(struct Curl_hash_offt *h)
-{
-  DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
-  return h->size;
-}
-
-/* FOR NOW: basically a duplicate of Curl_hash_offt, BUT we hope to
- * eliminate the offt variant in the near future. */
-
 /* random patterns for API verification */
 #ifdef DEBUGBUILD
 #define CURL_UINTHASHINIT 0x7117e779
@@ -311,7 +116,7 @@ static void uint_hash_elem_link(struct uint_hash *h,
 }
 
 #define CURL_UINT_HASH_SLOT(h,id)  h->table[uint_hash_hash(id, h->slots)]
-#define CURL_UINT_HASH_SLOT_ADDR(h,id) &CURL_HASH_OFFT_SLOT(h,id)
+#define CURL_UINT_HASH_SLOT_ADDR(h,id) &CURL_UINT_HASH_SLOT(h,id)
 
 bool Curl_uint_hash_set(struct uint_hash *h, unsigned int id, void *value)
 {
@@ -401,8 +206,12 @@ static void uint_hash_clear(struct uint_hash *h)
   }
 }
 
-void
-Curl_uint_hash_destroy(struct uint_hash *h)
+void Curl_uint_hash_clear(struct uint_hash *h)
+{
+  uint_hash_clear(h);
+}
+
+void Curl_uint_hash_destroy(struct uint_hash *h)
 {
   DEBUGASSERT(h->init == CURL_UINTHASHINIT);
   if(h->table) {
similarity index 70%
rename from lib/hash_offt.h
rename to lib/uint-hash.h
index 80bab95c2a105a3b71643b3fff12f5e138c0b74e..1b52dba4c470c958081ff045eba8af3219bc1d23 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_HASH_OFFT_H
-#define HEADER_CURL_HASH_OFFT_H
+#ifndef HEADER_CURL_UINT_HASH_H
+#define HEADER_CURL_UINT_HASH_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
 
 #include "llist.h"
 
-struct Curl_hash_offt_entry;
-typedef void Curl_hash_offt_dtor(curl_off_t id, void *value);
-
-/* Hash for `curl_off_t` as key */
-struct Curl_hash_offt {
-  struct Curl_hash_offt_entry **table;
-  Curl_hash_offt_dtor *dtor;
-  size_t slots;
-  size_t size;
-#ifdef DEBUGBUILD
-  int init;
-#endif
-};
-
-void Curl_hash_offt_init(struct Curl_hash_offt *h,
-                         size_t slots,
-                         Curl_hash_offt_dtor *dtor);
-void Curl_hash_offt_destroy(struct Curl_hash_offt *h);
-
-bool Curl_hash_offt_set(struct Curl_hash_offt *h, curl_off_t id, void *value);
-bool Curl_hash_offt_remove(struct Curl_hash_offt *h, curl_off_t id);
-void *Curl_hash_offt_get(struct Curl_hash_offt *h, curl_off_t id);
-void Curl_hash_offt_clear(struct Curl_hash_offt *h);
-size_t Curl_hash_offt_count(struct Curl_hash_offt *h);
-
-
 /* A version with unsigned int as key */
 typedef void Curl_uint_hash_dtor(unsigned int id, void *value);
 struct uint_hash_entry;
@@ -76,6 +50,7 @@ void Curl_uint_hash_init(struct uint_hash *h,
                          unsigned int slots,
                          Curl_uint_hash_dtor *dtor);
 void Curl_uint_hash_destroy(struct uint_hash *h);
+void Curl_uint_hash_clear(struct uint_hash *h);
 
 bool Curl_uint_hash_set(struct uint_hash *h, unsigned int id, void *value);
 bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id);
@@ -90,4 +65,4 @@ void Curl_uint_hash_visit(struct uint_hash *h,
                           Curl_uint_hash_visit_cb *cb,
                           void *user_data);
 
-#endif /* HEADER_CURL_HASH_OFFT_H */
+#endif /* HEADER_CURL_UINT_HASH_H */
index 473582ca40146cfa3ea08a93fb40c726717db0f7..9d17ce9779a3d9753a46abfc3922d2056380fae0 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -601,6 +601,7 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn)
 #endif
   Curl_safefree(conn->destination);
   Curl_uint_spbset_destroy(&conn->xfers_attached);
+  Curl_hash_destroy(&conn->meta_hash);
 
   free(conn); /* free all the connection oriented data */
 }
@@ -3322,6 +3323,15 @@ static void reuse_conn(struct Curl_easy *data,
   Curl_conn_free(data, temp);
 }
 
+static void conn_meta_freeentry(void *p)
+{
+  (void)p;
+  /* Will always be FALSE. Cannot use a 0 assert here since compilers
+   * are not in agreement if they then want a NORETURN attribute or
+   * not. *sigh* */
+  DEBUGASSERT(p == NULL);
+}
+
 /**
  * create_conn() sets up a new connectdata struct, or reuses an already
  * existing one, and resolves hostname.
@@ -3377,6 +3387,9 @@ static CURLcode create_conn(struct Curl_easy *data,
   *in_connect = conn;
 
   /* Do the unfailable inits first, before checks that may early return */
+  Curl_hash_init(&conn->meta_hash, 23,
+               Curl_hash_str, Curl_str_key_compare, conn_meta_freeentry);
+
   /* GSSAPI related inits */
   Curl_sec_conn_init(conn);
 
@@ -3944,3 +3957,23 @@ void Curl_data_priority_clear_state(struct Curl_easy *data)
 }
 
 #endif /* defined(USE_HTTP2) || defined(USE_HTTP3) */
+
+
+CURLcode Curl_conn_meta_set(struct connectdata *conn, const char *key,
+                            void *meta_data, Curl_meta_dtor *meta_dtor)
+{
+  if(!Curl_hash_add2(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1,
+                     meta_data, meta_dtor)) {
+    meta_dtor(CURL_UNCONST(key), strlen(key) + 1, meta_data);
+  }
+  return CURLE_OK;
+}
+void Curl_conn_meta_remove(struct connectdata *conn, const char *key)
+{
+  Curl_hash_delete(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
+}
+
+void *Curl_conn_meta_get(struct connectdata *conn, const char *key)
+{
+  return Curl_hash_pick(&conn->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
+}
index aa687228abc46fe54cb66ff43ce276ab890f8ece..76a935eceea3490816179f8ef809db49651d06eb 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -54,10 +54,18 @@ typedef void Curl_meta_dtor(void *key, size_t key_len, void *meta_data);
  * Takes ownership of `meta_data` and destroys it when the call fails. */
 CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
                        void *meta_data, Curl_meta_dtor *meta_dtor);
-void Curl_meta_clear(struct Curl_easy *data, const char *key);
+void Curl_meta_remove(struct Curl_easy *data, const char *key);
 void *Curl_meta_get(struct Curl_easy *data, const char *key);
 void Curl_meta_reset(struct Curl_easy *data);
 
+/* Set connection meta data for the key. Any existing entry for that
+ * key will be destroyed.
+ * Takes ownership of `meta_data` and destroys it when the call fails. */
+CURLcode Curl_conn_meta_set(struct connectdata *conn, const char *key,
+                            void *meta_data, Curl_meta_dtor *meta_dtor);
+void Curl_conn_meta_remove(struct connectdata *conn, const char *key);
+void *Curl_conn_meta_get(struct connectdata *conn, const char *key);
+
 /* Get protocol handler for a URI scheme
  * @param scheme URI scheme, case-insensitive
  * @return NULL of handler not found
index e76d4a1043e5c0b6e960330d175e0cfd326db65a..eddcb0a2b7a3865b49f36aaeff3b14459bac37ca 100644 (file)
@@ -152,7 +152,6 @@ typedef unsigned int curl_prot_t;
 #include "http_chunks.h" /* for the structs and enum stuff */
 #include "hostip.h"
 #include "hash.h"
-#include "hash_offt.h"
 #include "splay.h"
 #include "dynbuf.h"
 #include "dynhds.h"
@@ -750,6 +749,12 @@ struct connectdata {
                                track the connections in the log output */
   char *destination; /* string carrying normalized hostname+port+scope */
 
+  /* `meta_hash` is a general key-value store for implementations
+   * with the lifetime of the connection.
+   * Elements need to be added with their own destructor to be invoked when
+   * the connection is cleaned up (see Curl_hash_add2()).*/
+  struct Curl_hash meta_hash;
+
   /* 'dns_entry' is the particular host we use. This points to an entry in the
      DNS cache and it will not get pruned while locked. It gets unlocked in
      multi_done(). This entry will be NULL if the connection is reused as then
index 7dca1dc115beb43238f72823bf2ac4eab1bf9b79..cd85fd5fb965b594281df5db659d8b69403f9824 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "../urldata.h"
 #include "../hash.h"
-#include "../hash_offt.h"
+#include "../uint-hash.h"
 #include "../timeval.h"
 #include "../multiif.h"
 #include "../sendf.h"
index fc22f18f99a0d4d203d9a1e6822424d1853e32fe..9827a89517ada2555707dfbabc3b72b0f6fe3e70 100644 (file)
@@ -47,7 +47,7 @@
 #endif
 
 #include "../urldata.h"
-#include "../hash_offt.h"
+#include "../uint-hash.h"
 #include "../sendf.h"
 #include "../strdup.h"
 #include "../rand.h"
index caae5f30829d7bc30d1069a3c2e454c797485d18..869a2bc1b0c4806318ab23258f5b5230347baf3e 100644 (file)
@@ -29,7 +29,7 @@
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 #include "../bufq.h"
-#include "../hash_offt.h"
+#include "../uint-hash.h"
 #include "../urldata.h"
 #include "../cfilters.h"
 #include "../cf-socket.h"
index cce79c122a8365a0191f3b5ba87813f1903191af..a203c95b01f6596f26541d80f6758e12a5856975 100644 (file)
@@ -2,7 +2,7 @@
 <info>
 <keywords>
 unittest
-hash
+uint_hash
 </keywords>
 </info>
 
@@ -16,7 +16,7 @@ none
 unittest
 </features>
 <name>
-Internal hash_offt create/add/destroy testing, exercising clean functions
+Internal uint_hash create/add/destroy testing, exercising clean functions
 </name>
 </client>
 </testcase>
index e6608a793805c7a672fd2183b5fee5bb7306324a..3fe0c0c20dc688c00f29eb3441411208cde95ddb 100644 (file)
 
 #include "curlx.h"
 
-#include "hash_offt.h"
+#include "uint-hash.h"
 
 #include "memdebug.h" /* LAST include file */
 
-static struct Curl_hash_offt hash_static;
+static struct uint_hash hash_static;
 
-static void mydtor(curl_off_t id, void *elem)
+static void mydtor(unsigned int id, void *elem)
 {
   int *ptr = (int *)elem;
   (void)id;
@@ -40,13 +40,13 @@ static void mydtor(curl_off_t id, void *elem)
 
 static CURLcode unit_setup(void)
 {
-  Curl_hash_offt_init(&hash_static, 15, mydtor);
+  Curl_uint_hash_init(&hash_static, 15, mydtor);
   return CURLE_OK;
 }
 
 static void unit_stop(void)
 {
-  Curl_hash_offt_destroy(&hash_static);
+  Curl_uint_hash_destroy(&hash_static);
 }
 
 UNITTEST_START
@@ -54,34 +54,34 @@ UNITTEST_START
   int *value2;
   bool ok;
 
-  curl_off_t key = 20;
-  curl_off_t key2 = 25;
+  unsigned int key = 20;
+  unsigned int key2 = 25;
 
 
   value = malloc(sizeof(int));
   abort_unless(value != NULL, "Out of memory");
   *value = 199;
-  ok = Curl_hash_offt_set(&hash_static, key, value);
+  ok = Curl_uint_hash_set(&hash_static, key, value);
   if(!ok)
     free(value);
   abort_unless(ok, "insertion into hash failed");
-  v = Curl_hash_offt_get(&hash_static, key);
+  v = Curl_uint_hash_get(&hash_static, key);
   abort_unless(v == value, "lookup present entry failed");
-  v = Curl_hash_offt_get(&hash_static, key2);
+  v = Curl_uint_hash_get(&hash_static, key2);
   abort_unless(!v, "lookup missing entry failed");
-  Curl_hash_offt_clear(&hash_static);
+  Curl_uint_hash_clear(&hash_static);
 
   /* Attempt to add another key/value pair */
   value2 = malloc(sizeof(int));
   abort_unless(value2 != NULL, "Out of memory");
   *value2 = 204;
-  ok = Curl_hash_offt_set(&hash_static, key2, value2);
+  ok = Curl_uint_hash_set(&hash_static, key2, value2);
   if(!ok)
     free(value2);
   abort_unless(ok, "insertion into hash failed");
-  v = Curl_hash_offt_get(&hash_static, key2);
+  v = Curl_uint_hash_get(&hash_static, key2);
   abort_unless(v == value2, "lookup present entry failed");
-  v = Curl_hash_offt_get(&hash_static, key);
+  v = Curl_uint_hash_get(&hash_static, key);
   abort_unless(!v, "lookup missing entry failed");
 
 UNITTEST_STOP