mirror of
https://github.com/curl/curl.git
synced 2026-07-11 16:47:15 +03:00
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:
parent
1d66a769d7
commit
657aae79c0
18 changed files with 126 additions and 343 deletions
|
|
@ -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
|
Note: it only guarantees functionality if the hash table remains untouched
|
||||||
during its iteration.
|
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`.
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
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,
|
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.
|
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`.
|
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,6 @@ LIB_CFILES = \
|
||||||
getinfo.c \
|
getinfo.c \
|
||||||
gopher.c \
|
gopher.c \
|
||||||
hash.c \
|
hash.c \
|
||||||
hash_offt.c \
|
|
||||||
headers.c \
|
headers.c \
|
||||||
hmac.c \
|
hmac.c \
|
||||||
hostip.c \
|
hostip.c \
|
||||||
|
|
@ -237,6 +236,7 @@ LIB_CFILES = \
|
||||||
timeval.c \
|
timeval.c \
|
||||||
transfer.c \
|
transfer.c \
|
||||||
uint-bset.c \
|
uint-bset.c \
|
||||||
|
uint-hash.c \
|
||||||
uint-spbset.c \
|
uint-spbset.c \
|
||||||
uint-table.c \
|
uint-table.c \
|
||||||
url.c \
|
url.c \
|
||||||
|
|
@ -314,7 +314,6 @@ LIB_HFILES = \
|
||||||
getinfo.h \
|
getinfo.h \
|
||||||
gopher.h \
|
gopher.h \
|
||||||
hash.h \
|
hash.h \
|
||||||
hash_offt.h \
|
|
||||||
headers.h \
|
headers.h \
|
||||||
hostip.h \
|
hostip.h \
|
||||||
hsts.h \
|
hsts.h \
|
||||||
|
|
@ -380,6 +379,7 @@ LIB_HFILES = \
|
||||||
timeval.h \
|
timeval.h \
|
||||||
transfer.h \
|
transfer.h \
|
||||||
uint-bset.h \
|
uint-bset.h \
|
||||||
|
uint-hash.h \
|
||||||
uint-spbset.h \
|
uint-spbset.h \
|
||||||
uint-table.h \
|
uint-table.h \
|
||||||
url.h \
|
url.h \
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ static void doh_probe_done(struct Curl_easy *data,
|
||||||
Curl_dyn_len(&doh_req->resp_body));
|
Curl_dyn_len(&doh_req->resp_body));
|
||||||
Curl_dyn_free(&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)
|
if(result)
|
||||||
|
|
|
||||||
|
|
@ -1419,7 +1419,7 @@ CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
|
||||||
return CURLE_OK;
|
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);
|
Curl_hash_delete(&data->meta_hash, CURL_UNCONST(key), strlen(key) + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "bufq.h"
|
#include "bufq.h"
|
||||||
#include "hash_offt.h"
|
#include "uint-hash.h"
|
||||||
#include "http1.h"
|
#include "http1.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
|
#include "url.h"
|
||||||
#include "cfilters.h"
|
#include "cfilters.h"
|
||||||
#include "curl_trc.h"
|
#include "curl_trc.h"
|
||||||
#include "multiif.h"
|
#include "multiif.h"
|
||||||
|
|
@ -57,7 +58,7 @@ static void mev_in_callback(struct Curl_multi *multi, bool value)
|
||||||
*/
|
*/
|
||||||
struct mev_sh_entry {
|
struct mev_sh_entry {
|
||||||
struct uint_spbset xfers; /* bitset of transfers `mid`s on this socket */
|
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() */
|
void *user_data; /* libcurl app data via curl_multi_assign() */
|
||||||
unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the
|
unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the
|
||||||
* libcurl application to watch out for */
|
* 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;
|
struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis;
|
||||||
Curl_uint_spbset_destroy(&entry->xfers);
|
Curl_uint_spbset_destroy(&entry->xfers);
|
||||||
Curl_hash_offt_destroy(&entry->conns);
|
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +117,6 @@ mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s)
|
||||||
return NULL; /* major failure */
|
return NULL; /* major failure */
|
||||||
|
|
||||||
Curl_uint_spbset_init(&check->xfers);
|
Curl_uint_spbset_init(&check->xfers);
|
||||||
Curl_hash_offt_init(&check->conns, CURL_MEV_CONN_HASH_SIZE, NULL);
|
|
||||||
|
|
||||||
/* make/add new hash entry */
|
/* make/add new hash entry */
|
||||||
if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) {
|
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)
|
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,
|
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,
|
static bool mev_sh_entry_conn_known(struct mev_sh_entry *e,
|
||||||
struct connectdata *conn)
|
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,
|
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 */
|
/* detect weird values */
|
||||||
DEBUGASSERT(mev_sh_entry_user_count(e) < 100000);
|
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,
|
static bool mev_sh_entry_conn_remove(struct mev_sh_entry *e,
|
||||||
struct connectdata *conn)
|
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`.
|
/* Purge any information about socket `s`.
|
||||||
|
|
@ -344,11 +352,11 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
|
||||||
return CURLM_OUT_OF_MEMORY;
|
return CURLM_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", added %s #%" FMT_OFF_T
|
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 ? "connection" : "transfer",
|
||||||
conn ? conn->connection_id : data->mid,
|
conn ? conn->connection_id : data->mid,
|
||||||
Curl_uint_spbset_count(&entry->xfers),
|
Curl_uint_spbset_count(&entry->xfers),
|
||||||
Curl_hash_offt_count(&entry->conns));
|
entry->conn ? 1 : 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for(j = 0; j < prev_ps->num; j++) {
|
for(j = 0; j < prev_ps->num; j++) {
|
||||||
|
|
@ -414,9 +422,9 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi,
|
||||||
if(mresult)
|
if(mresult)
|
||||||
return mresult;
|
return mresult;
|
||||||
CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, "
|
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_uint_spbset_count(&entry->xfers),
|
||||||
Curl_hash_offt_count(&entry->conns));
|
entry->conn ? 1 : 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mresult = mev_forget_socket(multi, data, s, "last user gone");
|
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;
|
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*
|
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;
|
struct easy_pollset *ps;
|
||||||
|
|
||||||
ps = calloc(1, sizeof(*ps));
|
ps = calloc(1, sizeof(*ps));
|
||||||
if(!ps)
|
if(!ps)
|
||||||
return NULL;
|
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);
|
free(ps);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -446,14 +461,14 @@ mev_add_new_conn_pollset(struct Curl_hash_offt *h, curl_off_t id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct easy_pollset*
|
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;
|
struct easy_pollset *ps;
|
||||||
|
|
||||||
ps = calloc(1, sizeof(*ps));
|
ps = calloc(1, sizeof(*ps));
|
||||||
if(!ps)
|
if(!ps)
|
||||||
return NULL;
|
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);
|
free(ps);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -461,16 +476,14 @@ mev_add_new_xfer_pollset(struct uint_hash *h, unsigned int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct easy_pollset *
|
static struct easy_pollset *
|
||||||
mev_get_last_pollset(struct Curl_multi *multi,
|
mev_get_last_pollset(struct Curl_easy *data,
|
||||||
struct Curl_easy *data,
|
|
||||||
struct connectdata *conn)
|
struct connectdata *conn)
|
||||||
{
|
{
|
||||||
if(data) {
|
if(data) {
|
||||||
if(conn)
|
if(conn)
|
||||||
return Curl_hash_offt_get(&multi->ev.conn_pollsets,
|
return Curl_conn_meta_get(conn, CURL_META_MEV_POLLSET);
|
||||||
conn->connection_id);
|
|
||||||
else if(data)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -494,15 +507,13 @@ static CURLMcode mev_assess(struct Curl_multi *multi,
|
||||||
struct easy_pollset ps, *last_ps;
|
struct easy_pollset ps, *last_ps;
|
||||||
|
|
||||||
mev_init_cur_pollset(&ps, data, conn);
|
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(!last_ps && ps.num) {
|
||||||
if(conn)
|
if(conn)
|
||||||
last_ps = mev_add_new_conn_pollset(&multi->ev.conn_pollsets,
|
last_ps = mev_add_new_conn_pollset(conn);
|
||||||
conn->connection_id);
|
|
||||||
else
|
else
|
||||||
last_ps = mev_add_new_xfer_pollset(&multi->ev.xfer_pollsets,
|
last_ps = mev_add_new_xfer_pollset(data);
|
||||||
data->mid);
|
|
||||||
if(!last_ps)
|
if(!last_ps)
|
||||||
return CURLM_OUT_OF_MEMORY;
|
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));
|
while(Curl_uint_spbset_next(&entry->xfers, mid, &mid));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Curl_hash_offt_count(&entry->conns))
|
if(entry->conn)
|
||||||
*run_cpool = TRUE;
|
*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 */
|
DEBUGASSERT(!data->conn); /* transfer should have been detached */
|
||||||
if(data != multi->admin) {
|
if(data != multi->admin) {
|
||||||
(void)mev_assess(multi, data, NULL);
|
(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)
|
struct connectdata *conn)
|
||||||
{
|
{
|
||||||
(void)mev_assess(multi, data, 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 */
|
#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)
|
void Curl_multi_ev_init(struct Curl_multi *multi, size_t hashsize)
|
||||||
{
|
{
|
||||||
Curl_hash_init(&multi->ev.sh_entries, hashsize, mev_sh_entry_hash,
|
Curl_hash_init(&multi->ev.sh_entries, hashsize, mev_sh_entry_hash,
|
||||||
mev_sh_entry_compare, mev_sh_entry_dtor);
|
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)
|
void Curl_multi_ev_cleanup(struct Curl_multi *multi)
|
||||||
{
|
{
|
||||||
Curl_hash_destroy(&multi->ev.sh_entries);
|
Curl_hash_destroy(&multi->ev.sh_entries);
|
||||||
Curl_uint_hash_destroy(&multi->ev.xfer_pollsets);
|
|
||||||
Curl_hash_offt_destroy(&multi->ev.conn_pollsets);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,17 @@
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "hash_offt.h"
|
|
||||||
|
|
||||||
struct Curl_easy;
|
struct Curl_easy;
|
||||||
struct Curl_multi;
|
struct Curl_multi;
|
||||||
struct easy_pollset;
|
struct easy_pollset;
|
||||||
struct uint_bset;
|
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_multi_ev {
|
||||||
struct Curl_hash sh_entries;
|
struct Curl_hash sh_entries;
|
||||||
struct uint_hash xfer_pollsets;
|
|
||||||
struct Curl_hash_offt conn_pollsets;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Setup/teardown of multi event book-keeping. */
|
/* Setup/teardown of multi event book-keeping. */
|
||||||
|
|
|
||||||
|
|
@ -26,207 +26,12 @@
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "hash_offt.h"
|
#include "uint-hash.h"
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#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 */
|
/* random patterns for API verification */
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
#define CURL_UINTHASHINIT 0x7117e779
|
#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(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)
|
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
|
void Curl_uint_hash_clear(struct uint_hash *h)
|
||||||
Curl_uint_hash_destroy(struct uint_hash *h)
|
{
|
||||||
|
uint_hash_clear(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curl_uint_hash_destroy(struct uint_hash *h)
|
||||||
{
|
{
|
||||||
DEBUGASSERT(h->init == CURL_UINTHASHINIT);
|
DEBUGASSERT(h->init == CURL_UINTHASHINIT);
|
||||||
if(h->table) {
|
if(h->table) {
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef HEADER_CURL_HASH_OFFT_H
|
#ifndef HEADER_CURL_UINT_HASH_H
|
||||||
#define HEADER_CURL_HASH_OFFT_H
|
#define HEADER_CURL_UINT_HASH_H
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* _ _ ____ _
|
* _ _ ____ _
|
||||||
* Project ___| | | | _ \| |
|
* Project ___| | | | _ \| |
|
||||||
|
|
@ -30,32 +30,6 @@
|
||||||
|
|
||||||
#include "llist.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);
|
|
||||||
|
|
||||||
|
|
||||||
/* A version with unsigned int as key */
|
/* A version with unsigned int as key */
|
||||||
typedef void Curl_uint_hash_dtor(unsigned int id, void *value);
|
typedef void Curl_uint_hash_dtor(unsigned int id, void *value);
|
||||||
struct uint_hash_entry;
|
struct uint_hash_entry;
|
||||||
|
|
@ -76,6 +50,7 @@ void Curl_uint_hash_init(struct uint_hash *h,
|
||||||
unsigned int slots,
|
unsigned int slots,
|
||||||
Curl_uint_hash_dtor *dtor);
|
Curl_uint_hash_dtor *dtor);
|
||||||
void Curl_uint_hash_destroy(struct uint_hash *h);
|
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_set(struct uint_hash *h, unsigned int id, void *value);
|
||||||
bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id);
|
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,
|
Curl_uint_hash_visit_cb *cb,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
#endif /* HEADER_CURL_HASH_OFFT_H */
|
#endif /* HEADER_CURL_UINT_HASH_H */
|
||||||
33
lib/url.c
33
lib/url.c
|
|
@ -601,6 +601,7 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn)
|
||||||
#endif
|
#endif
|
||||||
Curl_safefree(conn->destination);
|
Curl_safefree(conn->destination);
|
||||||
Curl_uint_spbset_destroy(&conn->xfers_attached);
|
Curl_uint_spbset_destroy(&conn->xfers_attached);
|
||||||
|
Curl_hash_destroy(&conn->meta_hash);
|
||||||
|
|
||||||
free(conn); /* free all the connection oriented data */
|
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);
|
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
|
* create_conn() sets up a new connectdata struct, or reuses an already
|
||||||
* existing one, and resolves hostname.
|
* existing one, and resolves hostname.
|
||||||
|
|
@ -3377,6 +3387,9 @@ static CURLcode create_conn(struct Curl_easy *data,
|
||||||
*in_connect = conn;
|
*in_connect = conn;
|
||||||
|
|
||||||
/* Do the unfailable inits first, before checks that may early return */
|
/* 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 */
|
/* GSSAPI related inits */
|
||||||
Curl_sec_conn_init(conn);
|
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) */
|
#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);
|
||||||
|
}
|
||||||
|
|
|
||||||
10
lib/url.h
10
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. */
|
* Takes ownership of `meta_data` and destroys it when the call fails. */
|
||||||
CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
|
CURLcode Curl_meta_set(struct Curl_easy *data, const char *key,
|
||||||
void *meta_data, Curl_meta_dtor *meta_dtor);
|
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_get(struct Curl_easy *data, const char *key);
|
||||||
void Curl_meta_reset(struct Curl_easy *data);
|
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
|
/* Get protocol handler for a URI scheme
|
||||||
* @param scheme URI scheme, case-insensitive
|
* @param scheme URI scheme, case-insensitive
|
||||||
* @return NULL of handler not found
|
* @return NULL of handler not found
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,6 @@ typedef unsigned int curl_prot_t;
|
||||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||||
#include "hostip.h"
|
#include "hostip.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "hash_offt.h"
|
|
||||||
#include "splay.h"
|
#include "splay.h"
|
||||||
#include "dynbuf.h"
|
#include "dynbuf.h"
|
||||||
#include "dynhds.h"
|
#include "dynhds.h"
|
||||||
|
|
@ -750,6 +749,12 @@ struct connectdata {
|
||||||
track the connections in the log output */
|
track the connections in the log output */
|
||||||
char *destination; /* string carrying normalized hostname+port+scope */
|
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_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
|
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
|
multi_done(). This entry will be NULL if the connection is reused as then
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include "../urldata.h"
|
#include "../urldata.h"
|
||||||
#include "../hash.h"
|
#include "../hash.h"
|
||||||
#include "../hash_offt.h"
|
#include "../uint-hash.h"
|
||||||
#include "../timeval.h"
|
#include "../timeval.h"
|
||||||
#include "../multiif.h"
|
#include "../multiif.h"
|
||||||
#include "../sendf.h"
|
#include "../sendf.h"
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../urldata.h"
|
#include "../urldata.h"
|
||||||
#include "../hash_offt.h"
|
#include "../uint-hash.h"
|
||||||
#include "../sendf.h"
|
#include "../sendf.h"
|
||||||
#include "../strdup.h"
|
#include "../strdup.h"
|
||||||
#include "../rand.h"
|
#include "../rand.h"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include "../bufq.h"
|
#include "../bufq.h"
|
||||||
#include "../hash_offt.h"
|
#include "../uint-hash.h"
|
||||||
#include "../urldata.h"
|
#include "../urldata.h"
|
||||||
#include "../cfilters.h"
|
#include "../cfilters.h"
|
||||||
#include "../cf-socket.h"
|
#include "../cf-socket.h"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<info>
|
<info>
|
||||||
<keywords>
|
<keywords>
|
||||||
unittest
|
unittest
|
||||||
hash
|
uint_hash
|
||||||
</keywords>
|
</keywords>
|
||||||
</info>
|
</info>
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ none
|
||||||
unittest
|
unittest
|
||||||
</features>
|
</features>
|
||||||
<name>
|
<name>
|
||||||
Internal hash_offt create/add/destroy testing, exercising clean functions
|
Internal uint_hash create/add/destroy testing, exercising clean functions
|
||||||
</name>
|
</name>
|
||||||
</client>
|
</client>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,13 @@
|
||||||
|
|
||||||
#include "curlx.h"
|
#include "curlx.h"
|
||||||
|
|
||||||
#include "hash_offt.h"
|
#include "uint-hash.h"
|
||||||
|
|
||||||
#include "memdebug.h" /* LAST include file */
|
#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;
|
int *ptr = (int *)elem;
|
||||||
(void)id;
|
(void)id;
|
||||||
|
|
@ -40,13 +40,13 @@ static void mydtor(curl_off_t id, void *elem)
|
||||||
|
|
||||||
static CURLcode unit_setup(void)
|
static CURLcode unit_setup(void)
|
||||||
{
|
{
|
||||||
Curl_hash_offt_init(&hash_static, 15, mydtor);
|
Curl_uint_hash_init(&hash_static, 15, mydtor);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unit_stop(void)
|
static void unit_stop(void)
|
||||||
{
|
{
|
||||||
Curl_hash_offt_destroy(&hash_static);
|
Curl_uint_hash_destroy(&hash_static);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNITTEST_START
|
UNITTEST_START
|
||||||
|
|
@ -54,34 +54,34 @@ UNITTEST_START
|
||||||
int *value2;
|
int *value2;
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
curl_off_t key = 20;
|
unsigned int key = 20;
|
||||||
curl_off_t key2 = 25;
|
unsigned int key2 = 25;
|
||||||
|
|
||||||
|
|
||||||
value = malloc(sizeof(int));
|
value = malloc(sizeof(int));
|
||||||
abort_unless(value != NULL, "Out of memory");
|
abort_unless(value != NULL, "Out of memory");
|
||||||
*value = 199;
|
*value = 199;
|
||||||
ok = Curl_hash_offt_set(&hash_static, key, value);
|
ok = Curl_uint_hash_set(&hash_static, key, value);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
free(value);
|
free(value);
|
||||||
abort_unless(ok, "insertion into hash failed");
|
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");
|
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");
|
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 */
|
/* Attempt to add another key/value pair */
|
||||||
value2 = malloc(sizeof(int));
|
value2 = malloc(sizeof(int));
|
||||||
abort_unless(value2 != NULL, "Out of memory");
|
abort_unless(value2 != NULL, "Out of memory");
|
||||||
*value2 = 204;
|
*value2 = 204;
|
||||||
ok = Curl_hash_offt_set(&hash_static, key2, value2);
|
ok = Curl_uint_hash_set(&hash_static, key2, value2);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
free(value2);
|
free(value2);
|
||||||
abort_unless(ok, "insertion into hash failed");
|
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");
|
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");
|
abort_unless(!v, "lookup missing entry failed");
|
||||||
|
|
||||||
UNITTEST_STOP
|
UNITTEST_STOP
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue