MINOR: server: add srv->rid (revision id) value

With current design, we could not distinguish between
previously existing deleted server and a new server reusing
the deleted server name/id.

This can cause some confusion when auditing stats/events/logs,
because the new server will look similar to the old
one.

To address this, we're adding a new value in server structure: rid

rid (revision id) value is an unsigned 32bits value that is set upon
server creation. Value is derived from a global counter that starts
at 0 and is incremented each time one or multiple server deletions are
followed by a server addition (meaning that old name/id reuse could occur).

Thanks to this revision id, it is now easy to tell whether the server
we're looking at is the same as before or if it has been deleted and
re-added in the meantime.
(combining server name/id + server revision id yields a process-wide unique
identifier)
This commit is contained in:
Aurelien DARRAGON 2022-11-17 16:10:35 +01:00 committed by Christopher Faulet
parent 7f59d68fe2
commit 61e3894dfe
2 changed files with 43 additions and 0 deletions

View File

@ -264,6 +264,7 @@ struct server {
int slowstart; /* slowstart time in seconds (ms in the conf) */
char *id; /* just for identification */
uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */
unsigned iweight,uweight, cur_eweight; /* initial weight, user-specified weight, and effective weight */
unsigned wscore; /* weight score, used during srv map computation */
unsigned next_eweight; /* next pending eweight to commit */

View File

@ -72,6 +72,31 @@ struct eb_root idle_conn_srv = EB_ROOT;
struct task *idle_conn_task __read_mostly = NULL;
struct list servers_list = LIST_HEAD_INIT(servers_list);
/* SERVER DELETE(n)->ADD global tracker:
* This is meant to provide srv->rid (revision id) value.
* Revision id allows to differentiate between a previously existing
* deleted server and a new server reusing deleted server name/id.
*
* start value is 0 (even value)
* LSB is used to specify that one or multiple srv delete in a row
* were performed.
* When adding a new server, increment by 1 if current
* value is odd (odd = LSB set),
* because adding a new server after one or
* multiple deletions means we could potentially be reusing old names:
* Increase the revision id to prevent mixups between old and new names.
*
* srv->rid is calculated from cnt even values only.
* sizeof(srv_id_reuse_cnt) must be twice sizeof(srv->rid)
*
* Wraparound is expected and should not cause issues
* (with current design we allow up to 4 billion unique revisions)
*
* Counter is only used under thread_isolate (cli_add/cli_del),
* no need for atomic ops.
*/
static uint64_t srv_id_reuse_cnt = 0;
/* The server names dictionary */
struct dict server_key_dict = {
.name = "server keys",
@ -2635,6 +2660,9 @@ static int _srv_parse_init(struct server **srv, char **args, int *cur_arg,
else
newsrv->tmpl_info.prefix = strdup(args[1]);
/* revision defaults to 0 */
newsrv->rid = 0;
/* several ways to check the port component :
* - IP => port=+0, relative (IPv4 only)
* - IP: => port=+0, relative
@ -4854,6 +4882,17 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
if (srv->addr_node.key)
ebis_insert(&be->used_server_addr, &srv->addr_node);
/* check if LSB bit (odd bit) is set for reuse_cnt */
if (srv_id_reuse_cnt & 1) {
/* cnt must be increased */
srv_id_reuse_cnt++;
}
/* srv_id_reuse_cnt is always even at this stage, divide by 2 to
* save some space
* (sizeof(srv->rid) is half of sizeof(srv_id_reuse_cnt))
*/
srv->rid = (srv_id_reuse_cnt) ? (srv_id_reuse_cnt / 2) : 0;
thread_release();
/* Start the check task. The server must be fully initialized.
@ -5022,6 +5061,9 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
/* remove srv from idle_node tree for idle conn cleanup */
eb32_delete(&srv->idle_node);
/* set LSB bit (odd bit) for reuse_cnt */
srv_id_reuse_cnt |= 1;
thread_release();
ha_notice("Server deleted.\n");