struct eb_root *lb_tree; /* we want to know in what tree the server is */
struct tree_occ *lb_nodes; /* lb_nodes_tot * struct tree_occ */
+ struct tasklet *requeue_tasklet; /* tasklet to call to asynchronously requeue the server */
unsigned lb_nodes_tot; /* number of allocated lb_nodes (C-HASH) */
unsigned lb_nodes_now; /* number of lb_nodes placed in the tree (C-HASH) */
enum srv_hash_key hash_key; /* method to compute node hash (C-HASH) */
srv_update_status(sv, 0, SRV_OP_STCHGC_NONE);
}
+/* requeuing tasklet used to asynchronously queue the server into its tree in
+ * case of extreme contention. It is woken up by the code that failed to grab
+ * an important lock.
+ */
+struct task *server_requeue(struct task *t, void *context, unsigned int state)
+{
+ struct server *srv = context;
+
+ /* let's call the LB's requeue function. If it fails, it will itself
+ * wake us up.
+ */
+ if (srv->proxy->lbprm.server_requeue)
+ srv->proxy->lbprm.server_requeue(srv);
+ return t;
+}
+
/*
* Parses weight_str and configures sv accordingly.
* Returns NULL on success, error message string otherwise.
guid_remove(&srv->guid);
+ if (srv->requeue_tasklet)
+ tasklet_kill(srv->requeue_tasklet);
task_destroy(srv->warmup);
task_destroy(srv->srvrq_check);
}
REGISTER_POST_SERVER_CHECK(init_srv_slowstart);
+
+/* allocate the tasklet that's meant to permit a server */
+static int init_srv_requeue(struct server *srv)
+{
+ struct tasklet *t;
+
+ if ((t = tasklet_new()) == NULL) {
+ ha_alert("Cannot allocate a server requeuing tasklet for server %s/%s: out of memory.\n", srv->proxy->id, srv->id);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ srv->requeue_tasklet = t;
+ t->process = server_requeue;
+ t->context = srv;
+ return ERR_NONE;
+}
+REGISTER_POST_SERVER_CHECK(init_srv_requeue);
+
/* Memory allocation and initialization of the per_thr field.
* Returns 0 if the field has been successfully initialized, -1 on failure.
*/
if (init_srv_slowstart(srv))
goto out;
+ if (init_srv_requeue(srv) != 0)
+ goto out;
+
/* Attach the server to the end of the proxy linked list. Note that this
* operation is not thread-safe so this is executed under thread
* isolation.