From cbae73e1dd95946597ea74ccb580c30f78e3fa73 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 20 Apr 2017 15:10:04 +0200 Subject: [PATCH] llist: no longer uses malloc The 'list element' struct now has to be within the data that is being added to the list. Removes 16.6% (tiny) mallocs from a simple HTTP transfer. (96 => 80) Also removed return codes since the llist functions can't fail now. Test 1300 updated accordingly. Closes #1435 --- lib/conncache.c | 8 ++- lib/fileinfo.c | 14 ++--- lib/fileinfo.h | 12 +++-- lib/ftplistparser.c | 49 +++++++++-------- lib/hash.c | 14 ++--- lib/hash.h | 1 + lib/llist.c | 34 ++++++------ lib/llist.h | 15 +++--- lib/multi.c | 45 ++++++++-------- lib/multihandle.h | 1 + lib/pipeline.c | 52 +++++++----------- lib/urldata.h | 4 ++ tests/unit/unit1300.c | 119 ++++++++++++++++++------------------------ 13 files changed, 165 insertions(+), 203 deletions(-) diff --git a/lib/conncache.c b/lib/conncache.c index 0590ec631..c79d22764 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -72,13 +72,11 @@ static void bundle_destroy(struct connectbundle *cb_ptr) /* Add a connection to a bundle */ static CURLcode bundle_add_conn(struct connectbundle *cb_ptr, - struct connectdata *conn) + struct connectdata *conn) { - if(!Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn)) - return CURLE_OUT_OF_MEMORY; - + Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, + &conn->bundle_node); conn->bundle = cb_ptr; - cb_ptr->num_connections++; return CURLE_OK; } diff --git a/lib/fileinfo.c b/lib/fileinfo.c index 144c65b1d..387298847 100644 --- a/lib/fileinfo.c +++ b/lib/fileinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 2010 - 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,23 +28,19 @@ /* The last #include file should be: */ #include "memdebug.h" -struct curl_fileinfo *Curl_fileinfo_alloc(void) +struct fileinfo *Curl_fileinfo_alloc(void) { - struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo)); - if(!tmp) - return NULL; - memset(tmp, 0, sizeof(struct curl_fileinfo)); - return tmp; + return calloc(1, sizeof(struct fileinfo)); } void Curl_fileinfo_dtor(void *user, void *element) { - struct curl_fileinfo *finfo = element; + struct fileinfo *finfo = element; (void) user; if(!finfo) return; - Curl_safefree(finfo->b_data); + Curl_safefree(finfo->info.b_data); free(finfo); } diff --git a/lib/fileinfo.h b/lib/fileinfo.h index 5324f1a40..c5d0ee5b6 100644 --- a/lib/fileinfo.h +++ b/lib/fileinfo.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2010, Daniel Stenberg, , et al. + * Copyright (C) 2010, 2017, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,11 +23,15 @@ ***************************************************************************/ #include +#include "llist.h" -struct curl_fileinfo *Curl_fileinfo_alloc(void); +struct fileinfo { + struct curl_fileinfo info; + struct curl_llist_element list; +}; + +struct fileinfo *Curl_fileinfo_alloc(void); void Curl_fileinfo_dtor(void *, void *); -struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src); - #endif /* HEADER_CURL_FILEINFO_H */ diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index bc186805f..2acce31d8 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -165,7 +165,7 @@ struct ftp_parselist_data { } state; CURLcode error; - struct curl_fileinfo *file_data; + struct fileinfo *file_data; unsigned int item_length; size_t item_offset; struct { @@ -275,7 +275,7 @@ static void PL_ERROR(struct connectdata *conn, CURLcode err) } static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, - struct curl_fileinfo *finfo) + struct fileinfo *infop) { curl_fnmatch_callback compare; struct WildcardData *wc = &conn->data->wildcard; @@ -283,6 +283,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, struct curl_llist *llist = &wc->filelist; struct ftp_parselist_data *parser = tmpdata->parser; bool add = TRUE; + struct curl_fileinfo *finfo = &infop->info; /* move finfo pointers to b_data */ char *str = finfo->b_data; @@ -316,11 +317,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, } if(add) { - if(!Curl_llist_insert_next(llist, llist->tail, finfo)) { - Curl_fileinfo_dtor(NULL, finfo); - tmpdata->parser->file_data = NULL; - return CURLE_OUT_OF_MEMORY; - } + Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list); } else { Curl_fileinfo_dtor(NULL, finfo); @@ -337,6 +334,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, struct connectdata *conn = (struct connectdata *)connptr; struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; struct ftp_parselist_data *parser = tmpdata->parser; + struct fileinfo *infop; struct curl_fileinfo *finfo; unsigned long i = 0; CURLcode result; @@ -366,17 +364,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->error = CURLE_OUT_OF_MEMORY; return bufflen; } - parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); - if(!parser->file_data->b_data) { + parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE); + if(!parser->file_data->info.b_data) { PL_ERROR(conn, CURLE_OUT_OF_MEMORY); return bufflen; } - parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; + parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE; parser->item_offset = 0; parser->item_length = 0; } - finfo = parser->file_data; + infop = parser->file_data; + finfo = &infop->info; finfo->b_data[finfo->b_used++] = c; if(finfo->b_used >= finfo->b_size - 1) { @@ -498,8 +497,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; } - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM; - parser->file_data->perm = perm; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM; + parser->file_data->info.perm = perm; parser->offsets.perm = parser->item_offset; parser->item_length = 0; @@ -530,8 +529,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; - parser->file_data->hardlinks = hlinks; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; + parser->file_data->info.hardlinks = hlinks; } parser->item_length = 0; parser->item_offset = 0; @@ -613,8 +612,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10); if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && fsize != CURL_OFF_T_MIN) { - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; - parser->file_data->size = fsize; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->info.size = fsize; } parser->item_length = 0; parser->item_offset = 0; @@ -731,7 +730,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.filename = parser->item_offset; parser->state.UNIX.main = PL_UNIX_FILETYPE; - result = ftp_pl_insert_finfo(conn, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -743,7 +742,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.filename = parser->item_offset; parser->state.UNIX.main = PL_UNIX_FILETYPE; - result = ftp_pl_insert_finfo(conn, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -838,7 +837,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, else if(c == '\n') { finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.symlink_target = parser->item_offset; - result = ftp_pl_insert_finfo(conn, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -850,7 +849,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, if(c == '\n') { finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.symlink_target = parser->item_offset; - result = ftp_pl_insert_finfo(conn, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -953,10 +952,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, return bufflen; } /* correct file type */ - parser->file_data->filetype = CURLFILETYPE_FILE; + parser->file_data->info.filetype = CURLFILETYPE_FILE; } - parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; parser->item_length = 0; parser->state.NT.main = PL_WINNT_FILENAME; parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; @@ -983,7 +982,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->offsets.filename = parser->item_offset; finfo->b_data[finfo->b_used - 1] = 0; parser->offsets.filename = parser->item_offset; - result = ftp_pl_insert_finfo(conn, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; @@ -995,7 +994,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, case PL_WINNT_FILENAME_WINEOL: if(c == '\n') { parser->offsets.filename = parser->item_offset; - result = ftp_pl_insert_finfo(conn, finfo); + result = ftp_pl_insert_finfo(conn, infop); if(result) { PL_ERROR(conn, result); return bufflen; diff --git a/lib/hash.c b/lib/hash.c index b7305a572..6afeaa12c 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -124,17 +124,9 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) he = mk_hash_element(key, key_len, p); if(he) { - if(Curl_llist_insert_next(l, l->tail, he)) { - ++h->size; - return p; /* return the new entry */ - } - /* - * Couldn't insert it, destroy the 'he' element and the key again. We - * don't call hash_element_dtor() since that would also call the - * "destructor" for the actual data 'p'. When we fail, we shall not touch - * that data. - */ - free(he); + Curl_llist_insert_next(l, l->tail, he, &he->list); + ++h->size; + return p; /* return the new entry */ } return NULL; /* failure */ diff --git a/lib/hash.h b/lib/hash.h index a345c8c87..90a25d1ca 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -57,6 +57,7 @@ struct curl_hash { }; struct curl_hash_element { + struct curl_llist_element list; void *ptr; size_t key_len; char key[1]; /* allocated memory following the struct */ diff --git a/lib/llist.c b/lib/llist.c index b8836bbcc..15cac825a 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -49,18 +49,17 @@ Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor) * entry is NULL and the list already has elements, the new one will be * inserted first in the list. * + * The 'ne' argument should be a pointer into the object to store. + * * Returns: 1 on success and 0 on failure. * * @unittest: 1300 */ -int +void Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, - const void *p) + const void *p, + struct curl_llist_element *ne) { - struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element)); - if(!ne) - return 0; - ne->ptr = (void *) p; if(list->size == 0) { list->head = ne; @@ -87,19 +86,18 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, } ++list->size; - - return 1; } /* * @unittest: 1300 */ -int +void Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, void *user) { + void *ptr; if(e == NULL || list->size == 0) - return 1; + return; if(e == list->head) { list->head = e->next; @@ -117,16 +115,16 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e, e->next->prev = e->prev; } - list->dtor(user, e->ptr); + ptr = e->ptr; e->ptr = NULL; e->prev = NULL; e->next = NULL; - free(e); --list->size; - return 1; + /* call the dtor() last for when it actually frees the 'e' memory itself */ + list->dtor(user, ptr); } void @@ -147,13 +145,13 @@ Curl_llist_count(struct curl_llist *list) /* * @unittest: 1300 */ -int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, - struct curl_llist *to_list, - struct curl_llist_element *to_e) +void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, + struct curl_llist *to_list, + struct curl_llist_element *to_e) { /* Remove element from list */ if(e == NULL || list->size == 0) - return 0; + return; if(e == list->head) { list->head = e->next; @@ -193,6 +191,4 @@ int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e, } ++to_list->size; - - return 1; } diff --git a/lib/llist.h b/lib/llist.h index 47935ad1f..6b644b99c 100644 --- a/lib/llist.h +++ b/lib/llist.h @@ -29,7 +29,6 @@ typedef void (*curl_llist_dtor)(void *, void *); struct curl_llist_element { void *ptr; - struct curl_llist_element *prev; struct curl_llist_element *next; }; @@ -37,21 +36,19 @@ struct curl_llist_element { struct curl_llist { struct curl_llist_element *head; struct curl_llist_element *tail; - curl_llist_dtor dtor; - size_t size; }; void Curl_llist_init(struct curl_llist *, curl_llist_dtor); -int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, - const void *); -int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, - void *); +void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, + const void *, struct curl_llist_element *node); +void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, + void *); size_t Curl_llist_count(struct curl_llist *); void Curl_llist_destroy(struct curl_llist *, void *); -int Curl_llist_move(struct curl_llist *, struct curl_llist_element *, - struct curl_llist *, struct curl_llist_element *); +void Curl_llist_move(struct curl_llist *, struct curl_llist_element *, + struct curl_llist *, struct curl_llist_element *); #endif /* HEADER_CURL_LLIST_H */ diff --git a/lib/multi.c b/lib/multi.c index b24ce19dd..f16776033 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -280,9 +280,8 @@ static int sh_init(struct curl_hash *hash, int hashsize) static CURLMcode multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg) { - if(!Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg)) - return CURLM_OUT_OF_MEMORY; - + Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg, + &msg->list); return CURLM_OK; } @@ -1432,10 +1431,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_CONNECT_PEND); /* add this handle to the list of connect-pending handles */ - if(!Curl_llist_insert_next(&multi->pending, multi->pending.tail, data)) - result = CURLE_OUT_OF_MEMORY; - else - result = CURLE_OK; + Curl_llist_insert_next(&multi->pending, multi->pending.tail, data, + &data->connect_queue); + result = CURLE_OK; break; } @@ -2483,7 +2481,10 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s) } } - +struct time_node { + struct curl_llist_element list; + struct timeval time; +}; /* * add_next_timeout() @@ -2504,13 +2505,16 @@ static CURLMcode add_next_timeout(struct timeval now, struct timeval *tv = &d->state.expiretime; struct curl_llist *list = &d->state.timeoutlist; struct curl_llist_element *e; + struct time_node *node = NULL; /* move over the timeout list for this specific handle and remove all timeouts that are now passed tense and store the next pending timeout in *tv */ for(e = list->head; e;) { struct curl_llist_element *n = e->next; - time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now); + time_t diff; + node = (struct time_node *)e->ptr; + diff = curlx_tvdiff(node->time, now); if(diff <= 0) /* remove outdated entry */ Curl_llist_remove(list, e, NULL); @@ -2528,7 +2532,7 @@ static CURLMcode add_next_timeout(struct timeval now, } else { /* copy the first entry to 'tv' */ - memcpy(tv, e->ptr, sizeof(*tv)); + memcpy(tv, &node->time, sizeof(*tv)); /* remove first entry from list */ Curl_llist_remove(list, e, NULL); @@ -2879,21 +2883,21 @@ multi_addtimeout(struct curl_llist *timeoutlist, struct timeval *stamp) { struct curl_llist_element *e; - struct timeval *timedup; + struct time_node *node; struct curl_llist_element *prev = NULL; - timedup = malloc(sizeof(*timedup)); - if(!timedup) + node = malloc(sizeof(struct time_node)); + if(!node) return CURLM_OUT_OF_MEMORY; /* copy the timestamp */ - memcpy(timedup, stamp, sizeof(*timedup)); + memcpy(&node->time, stamp, sizeof(*stamp)); if(Curl_llist_count(timeoutlist)) { /* find the correct spot in the list */ for(e = timeoutlist->head; e; e = e->next) { - struct timeval *checktime = e->ptr; - time_t diff = curlx_tvdiff(*checktime, *timedup); + struct time_node *check = (struct time_node *)e->ptr; + time_t diff = curlx_tvdiff(check->time, node->time); if(diff > 0) break; prev = e; @@ -2903,11 +2907,7 @@ multi_addtimeout(struct curl_llist *timeoutlist, /* else this is the first timeout on the list */ - if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) { - free(timedup); - return CURLM_OUT_OF_MEMORY; - } - + Curl_llist_insert_next(timeoutlist, prev, node, &node->list); return CURLM_OK; } @@ -3044,8 +3044,9 @@ void Curl_expire_clear(struct Curl_easy *data) infof(data, "Internal error clearing splay node = %d\n", rc); /* flush the timeout list too */ - while(list->size > 0) + while(list->size > 0) { Curl_llist_remove(list, list->tail, NULL); + } #ifdef DEBUGBUILD infof(data, "Expire cleared\n"); diff --git a/lib/multihandle.h b/lib/multihandle.h index 915b857fe..e6ffbf5b6 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -25,6 +25,7 @@ #include "conncache.h" struct Curl_message { + struct curl_llist_element list; /* the 'CURLMsg' is the part that is visible to the external user */ struct CURLMsg extmsg; }; diff --git a/lib/pipeline.c b/lib/pipeline.c index 4a14fddfe..72b9fb843 100644 --- a/lib/pipeline.c +++ b/lib/pipeline.c @@ -38,16 +38,15 @@ #include "memdebug.h" struct site_blacklist_entry { - char *hostname; + struct curl_llist_element list; unsigned short port; + char hostname[1]; }; static void site_blacklist_llist_dtor(void *user, void *element) { struct site_blacklist_entry *entry = element; (void)user; - - Curl_safefree(entry->hostname); free(entry); } @@ -94,8 +93,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data, static CURLcode addHandleToPipeline(struct Curl_easy *data, struct curl_llist *pipeline) { - if(!Curl_llist_insert_next(pipeline, pipeline->tail, data)) - return CURLE_OUT_OF_MEMORY; + Curl_llist_insert_next(pipeline, pipeline->tail, data, + &data->pipeline_queue); return CURLE_OK; } @@ -202,24 +201,17 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites, /* Parse the URLs and populate the list */ while(*sites) { - char *hostname; char *port; struct site_blacklist_entry *entry; - hostname = strdup(*sites); - if(!hostname) { - Curl_llist_destroy(list, NULL); - return CURLM_OUT_OF_MEMORY; - } - - entry = malloc(sizeof(struct site_blacklist_entry)); + entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites)); if(!entry) { - free(hostname); Curl_llist_destroy(list, NULL); return CURLM_OUT_OF_MEMORY; } + strcpy(entry->hostname, *sites); - port = strchr(hostname, ':'); + port = strchr(entry->hostname, ':'); if(port) { *port = '\0'; port++; @@ -230,14 +222,7 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites, entry->port = 80; } - entry->hostname = hostname; - - if(!Curl_llist_insert_next(list, list->tail, entry)) { - site_blacklist_llist_dtor(NULL, entry); - Curl_llist_destroy(list, NULL); - return CURLM_OUT_OF_MEMORY; - } - + Curl_llist_insert_next(list, list->tail, entry, &entry->list); sites++; } } @@ -274,6 +259,11 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, return FALSE; } +struct blacklist_node { + struct curl_llist_element list; + char server_name[1]; +}; + CURLMcode Curl_pipeline_set_server_blacklist(char **servers, struct curl_llist *list) { @@ -286,20 +276,18 @@ CURLMcode Curl_pipeline_set_server_blacklist(char **servers, /* Parse the URLs and populate the list */ while(*servers) { - char *server_name; + struct blacklist_node *n; + size_t len = strlen(*servers); - server_name = strdup(*servers); - if(!server_name) { + n = malloc(sizeof(struct blacklist_node) + len); + if(!n) { Curl_llist_destroy(list, NULL); return CURLM_OUT_OF_MEMORY; } + strcpy(n->server_name, *servers); - if(!Curl_llist_insert_next(list, list->tail, server_name)) { - Curl_llist_destroy(list, NULL); - Curl_safefree(server_name); - return CURLM_OUT_OF_MEMORY; - } - + Curl_llist_insert_next(list, list->tail, n->server_name, + &n->list); servers++; } } diff --git a/lib/urldata.h b/lib/urldata.h index 3c94553a1..34e18ecde 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -898,6 +898,8 @@ struct connectdata { connection is used! */ struct Curl_easy *data; + struct curl_llist_element bundle_node; /* conncache */ + /* chunk is for HTTP chunked encoding, but is in the general connectdata struct only because we can do just about any protocol through a HTTP proxy and a HTTP proxy may in fact respond using chunked encoding */ @@ -1804,6 +1806,8 @@ struct Curl_easy { struct Curl_easy *prev; struct connectdata *easy_conn; /* the "unit's" connection */ + struct curl_llist_element connect_queue; + struct curl_llist_element pipeline_queue; CURLMstate mstate; /* the handle's state */ CURLcode result; /* previous result */ diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c index dec81e623..8ec32a8c9 100644 --- a/tests/unit/unit1300.c +++ b/tests/unit/unit1300.c @@ -48,15 +48,20 @@ static void unit_stop(void) } UNITTEST_START +{ int unusedData_case1 = 1; int unusedData_case2 = 2; int unusedData_case3 = 3; + struct curl_llist_element case1_list; + struct curl_llist_element case2_list; + struct curl_llist_element case3_list; + struct curl_llist_element case4_list; + struct curl_llist_element case5_list; struct curl_llist_element *head; struct curl_llist_element *element_next; struct curl_llist_element *element_prev; struct curl_llist_element *to_remove; size_t llist_size = Curl_llist_count(&llist); - int curlErrCode = 0; /** * testing llist_init @@ -85,67 +90,49 @@ UNITTEST_START * 3: list tail will be the same as list head */ - curlErrCode = Curl_llist_insert_next(&llist, llist.head, &unusedData_case1); - if(curlErrCode == 1) { - fail_unless(Curl_llist_count(&llist) == 1, - "List size should be 1 after adding a new element"); - /*test that the list head data holds my unusedData */ - fail_unless(llist.head->ptr == &unusedData_case1, - "List size should be 1 after adding a new element"); - /*same goes for the list tail */ - fail_unless(llist.tail == llist.head, - "List size should be 1 after adding a new element"); + Curl_llist_insert_next(&llist, llist.head, &unusedData_case1, &case1_list); - /** - * testing Curl_llist_insert_next - * case 2: - * list has 1 element, adding one element after the head - * @assumptions: - * 1: the element next to head should be our newly created element - * 2: the list tail should be our newly created element - */ + fail_unless(Curl_llist_count(&llist) == 1, + "List size should be 1 after adding a new element"); + /*test that the list head data holds my unusedData */ + fail_unless(llist.head->ptr == &unusedData_case1, + "head ptr should be first entry"); + /*same goes for the list tail */ + fail_unless(llist.tail == llist.head, + "tail and head should be the same"); - curlErrCode = Curl_llist_insert_next(&llist, llist.head, - &unusedData_case3); - if(curlErrCode == 1) { - fail_unless(llist.head->next->ptr == &unusedData_case3, - "the node next to head is not getting set correctly"); - fail_unless(llist.tail->ptr == &unusedData_case3, - "the list tail is not getting set correctly"); - } - else { - printf("skipping Curl_llist_insert_next as a non " - "success error code was returned\n"); - } + /** + * testing Curl_llist_insert_next + * case 2: + * list has 1 element, adding one element after the head + * @assumptions: + * 1: the element next to head should be our newly created element + * 2: the list tail should be our newly created element + */ - /** - * testing Curl_llist_insert_next - * case 3: - * list has >1 element, adding one element after "NULL" - * @assumptions: - * 1: the element next to head should be our newly created element - * 2: the list tail should different from newly created element - */ + Curl_llist_insert_next(&llist, llist.head, + &unusedData_case3, &case3_list); + fail_unless(llist.head->next->ptr == &unusedData_case3, + "the node next to head is not getting set correctly"); + fail_unless(llist.tail->ptr == &unusedData_case3, + "the list tail is not getting set correctly"); - curlErrCode = Curl_llist_insert_next(&llist, llist.head, - &unusedData_case2); - if(curlErrCode == 1) { - fail_unless(llist.head->next->ptr == &unusedData_case2, - "the node next to head is not getting set correctly"); - /* better safe than sorry, check that the tail isn't corrupted */ - fail_unless(llist.tail->ptr != &unusedData_case2, - "the list tail is not getting set correctly"); - } - else { - printf("skipping Curl_llist_insert_next as a non " - "success error code was returned\n"); - } + /** + * testing Curl_llist_insert_next + * case 3: + * list has >1 element, adding one element after "NULL" + * @assumptions: + * 1: the element next to head should be our newly created element + * 2: the list tail should different from newly created element + */ - } - else { - printf("skipping Curl_llist_insert_next as a non " - "success error code was returned\n"); - } + Curl_llist_insert_next(&llist, llist.head, + &unusedData_case2, &case2_list); + fail_unless(llist.head->next->ptr == &unusedData_case2, + "the node next to head is not getting set correctly"); + /* better safe than sorry, check that the tail isn't corrupted */ + fail_unless(llist.tail->ptr != &unusedData_case2, + "the list tail is not getting set correctly"); /* unit tests for Curl_llist_remove */ @@ -183,8 +170,11 @@ UNITTEST_START * 2: element->previous->next will be element->next * 3: element->next->previous will be element->previous */ - Curl_llist_insert_next(&llist, llist.head, &unusedData_case3); + Curl_llist_insert_next(&llist, llist.head, &unusedData_case3, + &case4_list); llist_size = Curl_llist_count(&llist); + fail_unless(llist_size == 3, "should be 3 list members"); + to_remove = llist.head->next; abort_unless(to_remove, "to_remove is NULL"); element_next = to_remove->next; @@ -248,20 +238,17 @@ UNITTEST_START * add one element to the list */ - curlErrCode = Curl_llist_insert_next(&llist, llist.head, &unusedData_case1); + Curl_llist_insert_next(&llist, llist.head, &unusedData_case1, + &case5_list); /* necessary assertions */ - abort_unless(curlErrCode == 1, - "Curl_llist_insert_next returned an error, Can't move on with test"); abort_unless(Curl_llist_count(&llist) == 1, "Number of list elements is not as expected, Aborting"); abort_unless(Curl_llist_count(&llist_destination) == 0, "Number of list elements is not as expected, Aborting"); /*actual testing code*/ - curlErrCode = Curl_llist_move(&llist, llist.head, &llist_destination, NULL); - abort_unless(curlErrCode == 1, - "Curl_llist_move returned an error, Can't move on with test"); + Curl_llist_move(&llist, llist.head, &llist_destination, NULL); fail_unless(Curl_llist_count(&llist) == 0, "moving element from llist didn't decrement the size"); @@ -279,7 +266,5 @@ UNITTEST_START fail_unless(llist_destination.tail == llist_destination.tail, "llist_destination tail doesn't equal llist_destination head"); - - - +} UNITTEST_STOP