]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
hash_offt: standalone hash for curl_off_t
authorStefan Eissing <stefan@eissing.org>
Sun, 23 Feb 2025 11:20:17 +0000 (12:20 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 1 Mar 2025 17:42:10 +0000 (18:42 +0100)
Add a standalong hash table for curl_offt_t as key. This allows a
smaller memory footprint and faster lookups as we do not need to deal
with variable key lengths.

Use in all places we had the standard hash for this purpose.

Closes #16442

14 files changed:
lib/Makefile.inc
lib/hash.c
lib/hash.h
lib/hash_offt.c [new file with mode: 0644]
lib/hash_offt.h [new file with mode: 0644]
lib/http2.c
lib/multi_ev.c
lib/multi_ev.h
lib/urldata.h
lib/vquic/curl_msh3.c
lib/vquic/curl_ngtcp2.c
lib/vquic/curl_osslq.c
lib/vquic/curl_quiche.c
tests/unit/unit1616.c

index cb48733ae7447c2fafce8cb76a2ec0b322dc9091..543b4d4ca67e301e57b99dbbfa587060f58be633 100644 (file)
@@ -164,6 +164,7 @@ LIB_CFILES =         \
   getinfo.c          \
   gopher.c           \
   hash.c             \
+  hash_offt.c        \
   headers.c          \
   hmac.c             \
   hostasyn.c         \
@@ -312,6 +313,7 @@ LIB_HFILES =         \
   getinfo.h          \
   gopher.h           \
   hash.h             \
+  hash_offt.h        \
   headers.h          \
   hostip.h           \
   hsts.h             \
index a710e53935c82048c027ecdb2c67d40503edf3b6..680b9386218bb478edb83c19eec019f0a04d4313 100644 (file)
@@ -400,25 +400,3 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter)
 
   return iter->current;
 }
-
-void Curl_hash_offt_init(struct Curl_hash *h,
-                         size_t slots,
-                         Curl_hash_dtor dtor)
-{
-  Curl_hash_init(h, slots, Curl_hash_str, Curl_str_key_compare, dtor);
-}
-
-void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem)
-{
-  return Curl_hash_add(h, &id, sizeof(id), elem);
-}
-
-int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id)
-{
-  return Curl_hash_delete(h, &id, sizeof(id));
-}
-
-void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id)
-{
-  return Curl_hash_pick(h, &id, sizeof(id));
-}
index 20680a9da5917a41517ac23ce9697c938b7d6283..f429c76ccf9b1bf7d9240272ec6f8763808a83e3 100644 (file)
@@ -108,13 +108,4 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter);
 void Curl_hash_print(struct Curl_hash *h,
                      void (*func)(void *));
 
-/* Hash for `curl_off_t` as key */
-void Curl_hash_offt_init(struct Curl_hash *h, size_t slots,
-                         Curl_hash_dtor dtor);
-
-void *Curl_hash_offt_set(struct Curl_hash *h, curl_off_t id, void *elem);
-int Curl_hash_offt_remove(struct Curl_hash *h, curl_off_t id);
-void *Curl_hash_offt_get(struct Curl_hash *h, curl_off_t id);
-
-
 #endif /* HEADER_CURL_HASH_H */
diff --git a/lib/hash_offt.c b/lib/hash_offt.c
new file mode 100644 (file)
index 0000000..2edc81a
--- /dev/null
@@ -0,0 +1,242 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#include "hash_offt.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;
+}
+
+void Curl_hash_offt_visit(struct Curl_hash_offt *h,
+                          Curl_hash_offt_visit_cb *cb,
+                          void *user_data)
+{
+  if(h && h->table && cb) {
+    struct Curl_hash_offt_entry *he;
+    size_t i;
+    DEBUGASSERT(h->init == CURL_HASHOFFTINIT);
+    for(i = 0; i < h->slots; ++i) {
+      for(he = h->table[i]; he; he = he->next) {
+        if(!cb(he->id, he->value, user_data))
+          return;
+      }
+    }
+  }
+}
diff --git a/lib/hash_offt.h b/lib/hash_offt.h
new file mode 100644 (file)
index 0000000..02cbec1
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef HEADER_CURL_HASH_OFFT_H
+#define HEADER_CURL_HASH_OFFT_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <stddef.h>
+
+#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);
+
+
+typedef bool Curl_hash_offt_visit_cb(curl_off_t id, void *value,
+                                     void *user_data);
+
+void Curl_hash_offt_visit(struct Curl_hash_offt *h,
+                          Curl_hash_offt_visit_cb *cb,
+                          void *user_data);
+
+
+#endif /* HEADER_CURL_HASH_OFFT_H */
index c7ad2652bfe5ed4bcee2487f2c7f61a941358400..45436ff83a817b56a3dbac8462f1374af19c851d 100644 (file)
@@ -29,7 +29,7 @@
 #include <nghttp2/nghttp2.h>
 #include "urldata.h"
 #include "bufq.h"
-#include "hash.h"
+#include "hash_offt.h"
 #include "http1.h"
 #include "http2.h"
 #include "http.h"
@@ -135,7 +135,7 @@ struct cf_h2_ctx {
   struct bufc_pool stream_bufcp; /* spares for stream buffers */
   struct dynbuf scratch;        /* scratch buffer for temp use */
 
-  struct Curl_hash streams; /* hash of `data->mid` to `h2_stream_ctx` */
+  struct Curl_hash_offt streams; /* hash of `data->mid` to `h2_stream_ctx` */
   size_t drain_total; /* sum of all stream's UrlState drain */
   uint32_t max_concurrent_streams;
   uint32_t goaway_error;        /* goaway error code from server */
@@ -155,7 +155,7 @@ struct cf_h2_ctx {
 #define CF_CTX_CALL_DATA(cf)  \
   ((struct cf_h2_ctx *)(cf)->ctx)->call_data
 
-static void h2_stream_hash_free(void *stream);
+static void h2_stream_hash_free(curl_off_t id, void *stream);
 
 static void cf_h2_ctx_init(struct cf_h2_ctx *ctx, bool via_h1_upgrade)
 {
@@ -176,8 +176,7 @@ static void cf_h2_ctx_free(struct cf_h2_ctx *ctx)
     Curl_bufq_free(&ctx->outbufq);
     Curl_bufcp_free(&ctx->stream_bufcp);
     Curl_dyn_free(&ctx->scratch);
-    Curl_hash_clean(&ctx->streams);
-    Curl_hash_destroy(&ctx->streams);
+    Curl_hash_offt_destroy(&ctx->streams);
     memset(ctx, 0, sizeof(*ctx));
   }
   free(ctx);
@@ -267,8 +266,9 @@ static void h2_stream_ctx_free(struct h2_stream_ctx *stream)
   free(stream);
 }
 
-static void h2_stream_hash_free(void *stream)
+static void h2_stream_hash_free(curl_off_t id, void *stream)
 {
+  (void)id;
   DEBUGASSERT(stream);
   h2_stream_ctx_free((struct h2_stream_ctx *)stream);
 }
index 64a810e1b1a1c056d092d8d4d88e019d28637c41..110f37a130756e4c2d55bb0ea34617b06c45631b 100644 (file)
@@ -54,8 +54,8 @@ static void mev_in_callback(struct Curl_multi *multi, bool value)
  * what to supervise (CURL_POLL_IN/CURL_POLL_OUT/CURL_POLL_REMOVE)
  */
 struct mev_sh_entry {
-  struct Curl_hash xfers; /* hash of transfers using this socket */
-  struct Curl_hash conns; /* hash of connections using this socket */
+  struct Curl_hash_offt xfers; /* hash of transfers using this socket */
+  struct Curl_hash_offt conns; /* hash of connections using this socket */
   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 */
@@ -81,8 +81,8 @@ static size_t mev_sh_entry_compare(void *k1, size_t k1_len,
 static void mev_sh_entry_dtor(void *freethis)
 {
   struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis;
-  Curl_hash_destroy(&entry->xfers);
-  Curl_hash_destroy(&entry->conns);
+  Curl_hash_offt_destroy(&entry->xfers);
+  Curl_hash_offt_destroy(&entry->conns);
   free(entry);
 }
 
@@ -97,11 +97,6 @@ mev_sh_entry_get(struct Curl_hash *sh, curl_socket_t s)
   return NULL;
 }
 
-static void mev_nop_dtor(void *e)
-{
-  (void)e; /* does nothing */
-}
-
 /* make sure this socket is present in the hash for this handle */
 static struct mev_sh_entry *
 mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
@@ -119,8 +114,8 @@ mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
   if(!check)
     return NULL; /* major failure */
 
-  Curl_hash_offt_init(&check->xfers, CURL_MEV_XFER_HASH_SIZE, mev_nop_dtor);
-  Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, mev_nop_dtor);
+  Curl_hash_offt_init(&check->xfers, CURL_MEV_XFER_HASH_SIZE, NULL);
+  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)) {
@@ -139,7 +134,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_hash_count(&e->xfers) + Curl_hash_count(&e->conns);
+  return Curl_hash_offt_count(&e->xfers) + Curl_hash_offt_count(&e->conns);
 }
 
 static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e,
@@ -174,7 +169,7 @@ static bool mev_sh_entry_conn_add(struct mev_sh_entry *e,
 static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e,
                                      struct Curl_easy *data)
 {
-  return !Curl_hash_offt_remove(&e->xfers, data->id);
+  return Curl_hash_offt_remove(&e->xfers, data->id);
 }
 
 /* Purge any information about socket `s`.
@@ -341,8 +336,8 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
                  ", total=%zu/%zu (xfer/conn)", s,
                  conn ? "connection" : "transfer",
                  conn ? conn->connection_id : data->id,
-                 Curl_hash_count(&entry->xfers),
-                 Curl_hash_count(&entry->conns));
+                 Curl_hash_offt_count(&entry->xfers),
+                 Curl_hash_offt_count(&entry->conns));
     }
     else {
       for(j = 0; j < prev_ps->num; j++) {
@@ -399,8 +394,8 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
         return mresult;
       CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, "
                  "total=%zu/%zu (xfer/conn)", s,
-                 Curl_hash_count(&entry->xfers),
-                 Curl_hash_count(&entry->conns));
+                 Curl_hash_offt_count(&entry->xfers),
+                 Curl_hash_offt_count(&entry->conns));
     }
     else {
       mresult = mev_forget_socket(multi, data, s, "last user gone");
@@ -415,7 +410,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
 }
 
 static struct easy_pollset*
-mev_add_new_pollset(struct Curl_hash *h, curl_off_t id)
+mev_add_new_pollset(struct Curl_hash_offt *h, curl_off_t id)
 {
   struct easy_pollset *ps;
 
@@ -522,6 +517,20 @@ CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi,
   return CURLM_OK;
 }
 
+static bool mev_xfer_expire_cb(curl_off_t id, void *value, void *user_data)
+{
+  const struct curltime *nowp = user_data;
+  struct Curl_easy *data = value;
+
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
+  if(data && id >= 0) {
+    /* Expire with out current now, so we will get it below when
+     * asking the splaytree for expired transfers. */
+    Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW);
+  }
+  return TRUE;
+}
 
 void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
                                 curl_socket_t s,
@@ -539,24 +548,9 @@ void Curl_multi_ev_expire_xfers(struct Curl_multi *multi,
      asked to get removed, so thus we better survive stray socket actions
      and just move on. */
   if(entry) {
-    struct Curl_hash_iterator iter;
-    struct Curl_hash_element *he;
-
-    /* the socket can be shared by many transfers, iterate */
-    Curl_hash_start_iterate(&entry->xfers, &iter);
-    for(he = Curl_hash_next_element(&iter); he;
-        he = Curl_hash_next_element(&iter)) {
-      struct Curl_easy *data = (struct Curl_easy *)he->ptr;
-      DEBUGASSERT(data);
-      DEBUGASSERT(data->magic == CURLEASY_MAGIC_NUMBER);
-      DEBUGASSERT(data->id >= 0); /* we should not track internal handles */
-
-      /* Expire with out current now, so we will get it below when
-       * asking the splaytree for expired transfers. */
-      Curl_expire_ex(data, nowp, 0, EXPIRE_RUN_NOW);
-    }
+    Curl_hash_offt_visit(&entry->xfers, mev_xfer_expire_cb, (void *)nowp);
 
-    if(Curl_hash_count(&entry->conns))
+    if(Curl_hash_offt_count(&entry->conns))
       *run_cpool = TRUE;
   }
 }
@@ -587,8 +581,9 @@ void Curl_multi_ev_conn_done(struct Curl_multi *multi,
 
 #define CURL_MEV_PS_HASH_SLOTS   (991)  /* nice prime */
 
-static void mev_hash_pollset_free(void *entry)
+static void mev_hash_pollset_free(curl_off_t id, void *entry)
 {
+  (void)id;
   free(entry);
 }
 
@@ -605,6 +600,6 @@ void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize)
 void Curl_multi_ev_cleanup(struct Curl_multi *multi)
 {
   Curl_hash_destroy(&multi->ev.sh_entries);
-  Curl_hash_destroy(&multi->ev.xfer_pollsets);
-  Curl_hash_destroy(&multi->ev.conn_pollsets);
+  Curl_hash_offt_destroy(&multi->ev.xfer_pollsets);
+  Curl_hash_offt_destroy(&multi->ev.conn_pollsets);
 }
index f0745db29ebed2d58ae190b0ffc932cf8bb4d3ef..20e052e003d72dfefea584bef50dba017c68fc3d 100644 (file)
  *
  ***************************************************************************/
 
+#include "hash.h"
+#include "hash_offt.h"
+
 struct Curl_easy;
 struct Curl_multi;
 struct easy_pollset;
 
 struct curl_multi_ev {
   struct Curl_hash sh_entries;
-  struct Curl_hash xfer_pollsets;
-  struct Curl_hash conn_pollsets;
+  struct Curl_hash_offt xfer_pollsets;
+  struct Curl_hash_offt conn_pollsets;
 };
 
 /* Setup/teardown of multi event book-keeping. */
index 0f6278e201979504eb3d3a4a4fd5cd408b7b1999..c2b50e6fe98c1e8b3cdd203065846b33202c9f6b 100644 (file)
@@ -159,6 +159,7 @@ 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"
index 8f23e90ece9a781055e8585dff6ec1c31b8eb6bc..a4bffbeb72a23e670bbdc891dcaa55d9643a8767 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "urldata.h"
 #include "hash.h"
+#include "hash_offt.h"
 #include "timeval.h"
 #include "multiif.h"
 #include "sendf.h"
@@ -119,7 +120,7 @@ struct cf_msh3_ctx {
   struct cf_call_data call_data;
   struct curltime connect_started;   /* time the current attempt started */
   struct curltime handshake_at;      /* time connect handshake finished */
-  struct Curl_hash streams;          /* hash `data->mid` to `stream_ctx` */
+  struct Curl_hash_offt streams;     /* hash `data->mid` to `stream_ctx` */
   /* Flags written by msh3/msquic thread */
   bool handshake_complete;
   bool handshake_succeeded;
@@ -130,7 +131,7 @@ struct cf_msh3_ctx {
   BIT(active);
 };
 
-static void h3_stream_hash_free(void *stream);
+static void h3_stream_hash_free(curl_off_t id, void *stream);
 
 static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
                                  const struct Curl_addrinfo *ai)
@@ -154,7 +155,7 @@ static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
 static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx)
 {
   if(ctx && ctx->initialized) {
-    Curl_hash_destroy(&ctx->streams);
+    Curl_hash_offt_destroy(&ctx->streams);
   }
   free(ctx);
 }
@@ -196,8 +197,9 @@ static void h3_stream_ctx_free(struct stream_ctx *stream)
   free(stream);
 }
 
-static void h3_stream_hash_free(void *stream)
+static void h3_stream_hash_free(curl_off_t id, void *stream)
 {
+  (void)id;
   DEBUGASSERT(stream);
   h3_stream_ctx_free((struct stream_ctx *)stream);
 }
index 3afdf1a84b738c486c0e8171c5f4f95402d572ce..2a90167ac528dce1767ef719b6e3e9958374ebe3 100644 (file)
@@ -45,7 +45,7 @@
 #endif
 
 #include "urldata.h"
-#include "hash.h"
+#include "hash_offt.h"
 #include "sendf.h"
 #include "strdup.h"
 #include "rand.h"
@@ -133,7 +133,7 @@ struct cf_ngtcp2_ctx {
   struct curltime handshake_at;      /* time connect handshake finished */
   struct bufc_pool stream_bufcp;     /* chunk pool for streams */
   struct dynbuf scratch;             /* temp buffer for header construction */
-  struct Curl_hash streams;          /* hash `data->mid` to `h3_stream_ctx` */
+  struct Curl_hash_offt streams;     /* hash `data->mid` to `h3_stream_ctx` */
   size_t max_stream_window;          /* max flow window for one stream */
   uint64_t max_idle_ms;              /* max idle time for QUIC connection */
   uint64_t used_bidi_streams;        /* bidi streams we have opened */
@@ -156,7 +156,7 @@ struct cf_ngtcp2_ctx {
 #define CF_CTX_CALL_DATA(cf)  \
   ((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
 
-static void h3_stream_hash_free(void *stream);
+static void h3_stream_hash_free(curl_off_t id, void *stream);
 
 static void cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx)
 {
@@ -179,8 +179,7 @@ static void cf_ngtcp2_ctx_free(struct cf_ngtcp2_ctx *ctx)
     vquic_ctx_free(&ctx->q);
     Curl_bufcp_free(&ctx->stream_bufcp);
     Curl_dyn_free(&ctx->scratch);
-    Curl_hash_clean(&ctx->streams);
-    Curl_hash_destroy(&ctx->streams);
+    Curl_hash_offt_destroy(&ctx->streams);
     Curl_ssl_peer_cleanup(&ctx->peer);
   }
   free(ctx);
@@ -225,8 +224,9 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
   free(stream);
 }
 
-static void h3_stream_hash_free(void *stream)
+static void h3_stream_hash_free(curl_off_t id, void *stream)
 {
+  (void)id;
   DEBUGASSERT(stream);
   h3_stream_ctx_free((struct h3_stream_ctx *)stream);
 }
index 59cfc4b0384e57ceb4aa8f62ccce9694c469cb71..a69da56803d15b6b29a11c85713fc643507d8c4d 100644 (file)
@@ -285,7 +285,7 @@ struct cf_osslq_ctx {
   struct curltime handshake_at;      /* time connect handshake finished */
   struct curltime first_byte_at;     /* when first byte was recvd */
   struct bufc_pool stream_bufcp;     /* chunk pool for streams */
-  struct Curl_hash streams;          /* hash `data->mid` to `h3_stream_ctx` */
+  struct Curl_hash_offt streams;     /* hash `data->mid` to `h3_stream_ctx` */
   size_t max_stream_window;          /* max flow window for one stream */
   uint64_t max_idle_ms;              /* max idle time for QUIC connection */
   SSL_POLL_ITEM *poll_items;         /* Array for polling on writable state */
@@ -299,7 +299,7 @@ struct cf_osslq_ctx {
   BIT(need_send);                    /* QUIC connection needs to send */
 };
 
-static void h3_stream_hash_free(void *stream);
+static void h3_stream_hash_free(curl_off_t id, void *stream);
 
 static void cf_osslq_ctx_init(struct cf_osslq_ctx *ctx)
 {
@@ -317,8 +317,7 @@ static void cf_osslq_ctx_free(struct cf_osslq_ctx *ctx)
 {
   if(ctx && ctx->initialized) {
     Curl_bufcp_free(&ctx->stream_bufcp);
-    Curl_hash_clean(&ctx->streams);
-    Curl_hash_destroy(&ctx->streams);
+    Curl_hash_offt_destroy(&ctx->streams);
     Curl_ssl_peer_cleanup(&ctx->peer);
     free(ctx->poll_items);
     free(ctx->curl_items);
@@ -603,8 +602,9 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
   free(stream);
 }
 
-static void h3_stream_hash_free(void *stream)
+static void h3_stream_hash_free(curl_off_t id, void *stream)
 {
+  (void)id;
   DEBUGASSERT(stream);
   h3_stream_ctx_free((struct h3_stream_ctx *)stream);
 }
index 649ddbf98f0a580bf601ce2b7cdd2536875dc704..0c2bc3309e13e3583ad604f7eafdbefc70fe119e 100644 (file)
@@ -29,7 +29,7 @@
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 #include "bufq.h"
-#include "hash.h"
+#include "hash_offt.h"
 #include "urldata.h"
 #include "cfilters.h"
 #include "cf-socket.h"
@@ -97,7 +97,7 @@ struct cf_quiche_ctx {
   struct curltime started_at;        /* time the current attempt started */
   struct curltime handshake_at;      /* time connect handshake finished */
   struct bufc_pool stream_bufcp;     /* chunk pool for streams */
-  struct Curl_hash streams;          /* hash `data->mid` to `stream_ctx` */
+  struct Curl_hash_offt streams;     /* hash `data->mid` to `stream_ctx` */
   curl_off_t data_recvd;
   BIT(initialized);
   BIT(goaway);                       /* got GOAWAY from server */
@@ -115,7 +115,7 @@ static void quiche_debug_log(const char *line, void *argp)
 }
 #endif
 
-static void h3_stream_hash_free(void *stream);
+static void h3_stream_hash_free(curl_off_t id, void *stream);
 
 static void cf_quiche_ctx_init(struct cf_quiche_ctx *ctx)
 {
@@ -142,8 +142,7 @@ static void cf_quiche_ctx_free(struct cf_quiche_ctx *ctx)
     Curl_ssl_peer_cleanup(&ctx->peer);
     vquic_ctx_free(&ctx->q);
     Curl_bufcp_free(&ctx->stream_bufcp);
-    Curl_hash_clean(&ctx->streams);
-    Curl_hash_destroy(&ctx->streams);
+    Curl_hash_offt_destroy(&ctx->streams);
   }
   free(ctx);
 }
@@ -190,8 +189,9 @@ static void h3_stream_ctx_free(struct stream_ctx *stream)
   free(stream);
 }
 
-static void h3_stream_hash_free(void *stream)
+static void h3_stream_hash_free(curl_off_t id, void *stream)
 {
+  (void)id;
   DEBUGASSERT(stream);
   h3_stream_ctx_free((struct stream_ctx *)stream);
 }
index 6bccdb9cae86ce1785c009acd76b512f1ae602d0..e6608a793805c7a672fd2183b5fee5bb7306324a 100644 (file)
 
 #include "curlx.h"
 
-#include "hash.h"
+#include "hash_offt.h"
 
 #include "memdebug.h" /* LAST include file */
 
-static struct Curl_hash hash_static;
+static struct Curl_hash_offt hash_static;
 
-static void mydtor(void *elem)
+static void mydtor(curl_off_t id, void *elem)
 {
   int *ptr = (int *)elem;
+  (void)id;
   free(ptr);
 }
 
@@ -45,13 +46,13 @@ static CURLcode unit_setup(void)
 
 static void unit_stop(void)
 {
-  Curl_hash_destroy(&hash_static);
+  Curl_hash_offt_destroy(&hash_static);
 }
 
 UNITTEST_START
   int *value, *v;
   int *value2;
-  int *nodep;
+  bool ok;
 
   curl_off_t key = 20;
   curl_off_t key2 = 25;
@@ -60,24 +61,24 @@ UNITTEST_START
   value = malloc(sizeof(int));
   abort_unless(value != NULL, "Out of memory");
   *value = 199;
-  nodep = Curl_hash_offt_set(&hash_static, key, value);
-  if(!nodep)
+  ok = Curl_hash_offt_set(&hash_static, key, value);
+  if(!ok)
     free(value);
-  abort_unless(nodep, "insertion into hash failed");
+  abort_unless(ok, "insertion into hash failed");
   v = Curl_hash_offt_get(&hash_static, key);
   abort_unless(v == value, "lookup present entry failed");
   v = Curl_hash_offt_get(&hash_static, key2);
   abort_unless(!v, "lookup missing entry failed");
-  Curl_hash_clean(&hash_static);
+  Curl_hash_offt_clear(&hash_static);
 
   /* Attempt to add another key/value pair */
   value2 = malloc(sizeof(int));
   abort_unless(value2 != NULL, "Out of memory");
   *value2 = 204;
-  nodep = Curl_hash_offt_set(&hash_static, key2, value2);
-  if(!nodep)
+  ok = Curl_hash_offt_set(&hash_static, key2, value2);
+  if(!ok)
     free(value2);
-  abort_unless(nodep, "insertion into hash failed");
+  abort_unless(ok, "insertion into hash failed");
   v = Curl_hash_offt_get(&hash_static, key2);
   abort_unless(v == value2, "lookup present entry failed");
   v = Curl_hash_offt_get(&hash_static, key);