mirror of
https://github.com/curl/curl.git
synced 2026-08-25 14:53:34 +03:00
time-keeping: keep timestamp in multi, always update
Always use curlx_now() when calling Curl_pgrs_now(data). Tests with the "manual" updates to now proved differ more then 100ms in parallel testing. Add `curlx_nowp()` to set current time into a struct curltime. Add `curlx_ptimediff_ms() and friends, passing pointers. Update documentation. Closes #19998
This commit is contained in:
parent
308c347c8b
commit
b4be1f271e
61 changed files with 471 additions and 502 deletions
|
|
@ -206,7 +206,6 @@ void Curl_cpool_destroy(struct cpool *cpool)
|
|||
cpool->share ? "[SHARE] " : "", cpool->num_conn);
|
||||
/* Move all connections to the shutdown list */
|
||||
sigpipe_init(&pipe_st);
|
||||
Curl_pgrs_now_set(cpool->idata);
|
||||
CPOOL_LOCK(cpool, cpool->idata);
|
||||
conn = cpool_get_first(cpool);
|
||||
while(conn) {
|
||||
|
|
@ -275,7 +274,7 @@ static struct cpool_bundle *cpool_add_bundle(struct cpool *cpool,
|
|||
|
||||
static struct connectdata *
|
||||
cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle,
|
||||
struct curltime *pnow)
|
||||
const struct curltime *pnow)
|
||||
{
|
||||
struct Curl_llist_node *curr;
|
||||
timediff_t highscore = -1;
|
||||
|
|
@ -289,7 +288,7 @@ cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle,
|
|||
|
||||
if(!CONN_INUSE(conn)) {
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
score = curlx_timediff_ms(*pnow, conn->lastused);
|
||||
score = curlx_ptimediff_ms(pnow, &conn->lastused);
|
||||
|
||||
if(score > highscore) {
|
||||
highscore = score;
|
||||
|
|
@ -302,7 +301,7 @@ cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle,
|
|||
}
|
||||
|
||||
static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool,
|
||||
struct curltime *pnow)
|
||||
const struct curltime *pnow)
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_node *curr;
|
||||
|
|
@ -325,7 +324,7 @@ static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool,
|
|||
if(CONN_INUSE(conn) || conn->bits.close || conn->connect_only)
|
||||
continue;
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
score = curlx_timediff_ms(*pnow, conn->lastused);
|
||||
score = curlx_ptimediff_ms(pnow, &conn->lastused);
|
||||
if(score > highscore) {
|
||||
highscore = score;
|
||||
oldest_idle = conn;
|
||||
|
|
@ -356,7 +355,6 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
|
|||
if(!dest_limit && !total_limit)
|
||||
return CPOOL_LIMIT_OK;
|
||||
|
||||
Curl_pgrs_now_update(cpool->idata, data);
|
||||
CPOOL_LOCK(cpool, cpool->idata);
|
||||
if(dest_limit) {
|
||||
size_t live;
|
||||
|
|
@ -377,7 +375,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
|
|||
/* The bundle is full. Extract the oldest connection that may
|
||||
* be removed now, if there is one. */
|
||||
oldest_idle = cpool_bundle_get_oldest_idle(bundle,
|
||||
&data->progress.now);
|
||||
Curl_pgrs_now(data));
|
||||
if(!oldest_idle)
|
||||
break;
|
||||
/* disconnect the old conn and continue */
|
||||
|
|
@ -409,7 +407,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
|
|||
}
|
||||
else {
|
||||
struct connectdata *oldest_idle =
|
||||
cpool_get_oldest_idle(cpool, &data->progress.now);
|
||||
cpool_get_oldest_idle(cpool, Curl_pgrs_now(data));
|
||||
if(!oldest_idle)
|
||||
break;
|
||||
/* disconnect the old conn and continue */
|
||||
|
|
@ -429,7 +427,6 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
|
|||
|
||||
out:
|
||||
CPOOL_UNLOCK(cpool, cpool->idata);
|
||||
Curl_pgrs_now_update(data, cpool->idata);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -539,7 +536,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
|
|||
maxconnects = data->multi->maxconnects;
|
||||
}
|
||||
|
||||
conn->lastused = data->progress.now; /* it was used up until now */
|
||||
conn->lastused = *Curl_pgrs_now(data); /* it was used up until now */
|
||||
if(cpool && maxconnects) {
|
||||
/* may be called form a callback already under lock */
|
||||
bool do_lock = !CPOOL_IS_LOCKED(cpool);
|
||||
|
|
@ -549,7 +546,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
|
|||
infof(data, "Connection pool is full, closing the oldest of %zu/%u",
|
||||
cpool->num_conn, maxconnects);
|
||||
|
||||
oldest_idle = cpool_get_oldest_idle(cpool, &data->progress.now);
|
||||
oldest_idle = cpool_get_oldest_idle(cpool, Curl_pgrs_now(data));
|
||||
kept = (oldest_idle != conn);
|
||||
if(oldest_idle) {
|
||||
Curl_conn_terminate(data, oldest_idle, FALSE);
|
||||
|
|
@ -636,7 +633,6 @@ static void cpool_discard_conn(struct cpool *cpool,
|
|||
* If we do a shutdown for an aborted transfer, the server might think
|
||||
* it was successful otherwise (for example an ftps: upload). This is
|
||||
* not what we want. */
|
||||
Curl_pgrs_now_update(cpool->idata, data);
|
||||
if(aborted)
|
||||
done = TRUE;
|
||||
if(!done) {
|
||||
|
|
@ -702,13 +698,24 @@ void Curl_conn_terminate(struct Curl_easy *data,
|
|||
CPOOL_UNLOCK(cpool, data);
|
||||
}
|
||||
|
||||
struct cpool_reaper_ctx {
|
||||
size_t checked;
|
||||
size_t reaped;
|
||||
};
|
||||
|
||||
static int cpool_reap_dead_cb(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param)
|
||||
{
|
||||
(void)param;
|
||||
if((!CONN_INUSE(conn) && conn->bits.no_reuse) ||
|
||||
Curl_conn_seems_dead(conn, data)) {
|
||||
struct cpool_reaper_ctx *reaper = param;
|
||||
bool terminate = !CONN_INUSE(conn) && conn->bits.no_reuse;
|
||||
|
||||
if(!terminate) {
|
||||
reaper->checked++;
|
||||
terminate = Curl_conn_seems_dead(conn, data);
|
||||
}
|
||||
if(terminate) {
|
||||
/* stop the iteration here, pass back the connection that was pruned */
|
||||
reaper->reaped++;
|
||||
Curl_conn_terminate(data, conn, FALSE);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -725,18 +732,20 @@ static int cpool_reap_dead_cb(struct Curl_easy *data,
|
|||
void Curl_cpool_prune_dead(struct Curl_easy *data)
|
||||
{
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct cpool_reaper_ctx reaper;
|
||||
timediff_t elapsed;
|
||||
|
||||
if(!cpool)
|
||||
return;
|
||||
|
||||
memset(&reaper, 0, sizeof(reaper));
|
||||
CPOOL_LOCK(cpool, data);
|
||||
elapsed = curlx_timediff_ms(data->progress.now, cpool->last_cleanup);
|
||||
elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &cpool->last_cleanup);
|
||||
|
||||
if(elapsed >= 1000L) {
|
||||
while(cpool_foreach(data, cpool, NULL, cpool_reap_dead_cb))
|
||||
while(cpool_foreach(data, cpool, &reaper, cpool_reap_dead_cb))
|
||||
;
|
||||
cpool->last_cleanup = data->progress.now;
|
||||
cpool->last_cleanup = *Curl_pgrs_now(data);
|
||||
}
|
||||
CPOOL_UNLOCK(cpool, data);
|
||||
}
|
||||
|
|
@ -745,8 +754,8 @@ static int conn_upkeep(struct Curl_easy *data,
|
|||
struct connectdata *conn,
|
||||
void *param)
|
||||
{
|
||||
struct curltime *now = param;
|
||||
Curl_conn_upkeep(data, conn, now);
|
||||
(void)param;
|
||||
Curl_conn_upkeep(data, conn);
|
||||
return 0; /* continue iteration */
|
||||
}
|
||||
|
||||
|
|
@ -758,7 +767,7 @@ CURLcode Curl_cpool_upkeep(struct Curl_easy *data)
|
|||
return CURLE_OK;
|
||||
|
||||
CPOOL_LOCK(cpool, data);
|
||||
cpool_foreach(data, cpool, &data->progress.now, conn_upkeep);
|
||||
cpool_foreach(data, cpool, NULL, conn_upkeep);
|
||||
CPOOL_UNLOCK(cpool, data);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue