struct list updated_servers = LIST_HEAD_INIT(updated_servers);
__decl_hathreads(HA_SPINLOCK_T updated_servers_lock);
-static void srv_register_update(struct server *srv);
+static void srv_update_status(struct server *s);
static void srv_update_state(struct server *srv, int version, char **params);
static int srv_apply_lastaddr(struct server *srv, int *err_code);
static int srv_set_fqdn(struct server *srv, const char *fqdn, int dns_locked);
s->op_st_chg.duration = check->duration;
}
- srv_register_update(s);
for (srv = s->trackers; srv; srv = srv->tracknext) {
HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_stopped(srv, NULL, NULL);
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
}
+
+ /* propagate changes */
+ thread_isolate();
+ srv_update_status(s);
+ thread_release();
}
/* Marks server <s> up regardless of its checks' statuses and provided it isn't
if (s->slowstart <= 0)
s->next_state = SRV_ST_RUNNING;
- srv_register_update(s);
for (srv = s->trackers; srv; srv = srv->tracknext) {
HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_running(srv, NULL, NULL);
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
}
+
+ /* propagate changes */
+ thread_isolate();
+ srv_update_status(s);
+ thread_release();
}
/* Marks server <s> stopping regardless of its checks' statuses and provided it
s->op_st_chg.duration = check->duration;
}
- srv_register_update(s);
for (srv = s->trackers; srv; srv = srv->tracknext) {
HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
srv_set_stopping(srv, NULL, NULL);
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
}
+
+ /* propagate changes */
+ thread_isolate();
+ srv_update_status(s);
+ thread_release();
}
/* Enables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
if (cause)
strlcpy2(s->adm_st_chg_cause, cause, sizeof(s->adm_st_chg_cause));
- srv_register_update(s);
-
/* stop going down if the equivalent flag was already present (forced or inherited) */
if (((mode & SRV_ADMF_MAINT) && (s->next_admin & ~mode & SRV_ADMF_MAINT)) ||
((mode & SRV_ADMF_DRAIN) && (s->next_admin & ~mode & SRV_ADMF_DRAIN)))
- return;
+ goto end;
/* compute the inherited flag to propagate */
if (mode & SRV_ADMF_MAINT)
srv_set_admin_flag(srv, mode, cause);
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
}
+
+ end:
+ /* propagate changes */
+ thread_isolate();
+ srv_update_status(s);
+ thread_release();
}
/* Disables admin flag <mode> (among SRV_ADMF_*) on server <s>. This is used to
s->next_admin &= ~mode;
- srv_register_update(s);
-
/* stop going down if the equivalent flag is still present (forced or inherited) */
if (((mode & SRV_ADMF_MAINT) && (s->next_admin & SRV_ADMF_MAINT)) ||
((mode & SRV_ADMF_DRAIN) && (s->next_admin & SRV_ADMF_DRAIN)))
- return;
+ goto end;
if (mode & SRV_ADMF_MAINT)
mode = SRV_ADMF_IMAINT;
srv_clr_admin_flag(srv, mode);
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
}
+
+ end:
+ /* propagate changes */
+ thread_isolate();
+ srv_update_status(s);
+ thread_release();
}
/* principle: propagate maint and drain to tracking servers. This is useful
/* Recomputes the server's eweight based on its state, uweight, the current time,
* and the proxy's algorihtm. To be used after updating sv->uweight. The warmup
- * state is automatically disabled if the time is elapsed.
+ * state is automatically disabled if the time is elapsed. If <must_update> is
+ * not zero, the update will be propagated immediately.
*/
-void server_recalc_eweight(struct server *sv)
+void server_recalc_eweight(struct server *sv, int must_update)
{
struct proxy *px = sv->proxy;
unsigned w;
sv->next_eweight = (sv->uweight * w + px->lbprm.wmult - 1) / px->lbprm.wmult;
- srv_register_update(sv);
+ /* propagate changes only if needed (i.e. not recursively) */
+ if (must_update) {
+ thread_isolate();
+ srv_update_status(sv);
+ thread_release();
+ }
}
/*
return "Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.\n";
sv->uweight = w;
- server_recalc_eweight(sv);
+ server_recalc_eweight(sv, 1);
return NULL;
}
return NULL;
}
-/* Registers changes to be applied asynchronously */
-static void srv_register_update(struct server *srv)
-{
- if (LIST_ISEMPTY(&srv->update_status)) {
- HA_SPIN_LOCK(UPDATED_SERVERS_LOCK, &updated_servers_lock);
- if (LIST_ISEMPTY(&srv->update_status))
- LIST_ADDQ(&updated_servers, &srv->update_status);
- HA_SPIN_UNLOCK(UPDATED_SERVERS_LOCK, &updated_servers_lock);
- }
-}
-
/* Update a server state using the parameters available in the params list */
static void srv_update_state(struct server *srv, int version, char **params)
{
if (srv_iweight == srv->iweight) {
srv->uweight = srv_uweight;
}
- server_recalc_eweight(srv);
+ server_recalc_eweight(srv, 1);
/* load server IP address */
if (strcmp(params[0], "-"))
* is designed to be called asynchronously.
*
*/
-void srv_update_status(struct server *s)
+static void srv_update_status(struct server *s)
{
struct check *check = &s->check;
int xferred;
int log_level;
struct buffer *tmptrash = NULL;
-
/* If currently main is not set we try to apply pending state changes */
if (!(s->cur_admin & SRV_ADMF_MAINT)) {
int next_admin;
if (s->next_state == SRV_ST_STARTING)
task_schedule(s->warmup, tick_add(now_ms, MS_TO_TICKS(MAX(1000, s->slowstart / 20))));
- server_recalc_eweight(s);
+ server_recalc_eweight(s, 0);
/* now propagate the status change to any LB algorithms */
if (px->lbprm.update_server_eweight)
px->lbprm.update_server_eweight(s);
tmptrash = NULL;
}
- server_recalc_eweight(s);
+ server_recalc_eweight(s, 0);
/* now propagate the status change to any LB algorithms */
if (px->lbprm.update_server_eweight)
px->lbprm.update_server_eweight(s);
if (s->last_change < now.tv_sec) // ignore negative times
s->down_time += now.tv_sec - s->last_change;
s->last_change = now.tv_sec;
- server_recalc_eweight(s);
+ server_recalc_eweight(s, 0);
tmptrash = alloc_trash_chunk();
if (tmptrash) {