mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-17 11:06:54 +00:00
MINOR: pattern: Each pattern is identified by unique id.
The pattern reference are stored with two identifiers: the unique_id and the reference. The reference identify a file. Each file with the same name point to the same reference. We can register many times one file. If the file is modified, all his dependencies are also modified. The reference can be used with map or acl. The unique_id identify inline acl. The unique id is unique for each acl. You cannot force the same id in the configuration file, because this repport an error. The format of the acl and map listing through the "socket" has changed for displaying these new ids.
This commit is contained in:
parent
5d34408785
commit
af5a29d5f8
@ -40,7 +40,7 @@
|
||||
* The function returns 1 if the processing is ok, return 0
|
||||
* if the parser fails, with <err> message filled.
|
||||
*/
|
||||
int pattern_register(struct pattern_head *head, char *reference, int refflags, const char *arg, struct sample_storage *smp, int patflags, char **err);
|
||||
int pattern_register(struct pattern_head *head, int unique_id, int refflags, const char *arg, struct sample_storage *smp, int patflags, char **err);
|
||||
void pattern_finalize_config(void);
|
||||
|
||||
/* return the PAT_MATCH_* index for match name "name", or < 0 if not found */
|
||||
@ -197,7 +197,9 @@ struct pattern *pat_match_reg(struct sample *smp, struct pattern_expr *expr, int
|
||||
* pattern_ref manipulation.
|
||||
*/
|
||||
struct pat_ref *pat_ref_lookup(const char *reference);
|
||||
struct pat_ref *pat_ref_lookupid(int unique_id);
|
||||
struct pat_ref *pat_ref_new(const char *reference, unsigned int flags);
|
||||
struct pat_ref *pat_ref_newid(int unique_id, unsigned int flags);
|
||||
int pat_ref_append(struct pat_ref *ref, char *pattern, char *sample, int line);
|
||||
int pat_ref_add(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
|
||||
int pat_ref_set(struct pat_ref *ref, const char *pattern, const char *sample);
|
||||
|
@ -97,6 +97,7 @@ struct pat_ref {
|
||||
struct list list; /* Used to chain refs. */
|
||||
unsigned int flags; /* flags PAT_REF_*. */
|
||||
char *reference; /* The reference name. */
|
||||
int unique_id; /* Each pattern reference have unique id. */
|
||||
struct list head; /* The head of the list of struct pat_ref_elt. */
|
||||
struct list pat; /* The head of the list of struct pattern_expr. */
|
||||
};
|
||||
|
@ -598,7 +598,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
|
||||
}
|
||||
}
|
||||
|
||||
if (!pattern_register(&expr->pat, NULL, PAT_REF_ACL, arg, NULL, patflags, err))
|
||||
if (!pattern_register(&expr->pat, -1, PAT_REF_ACL, arg, NULL, patflags, err))
|
||||
goto out_free_expr;
|
||||
args++;
|
||||
}
|
||||
|
@ -982,6 +982,27 @@ struct pat_ref *pat_list_get_next(struct pat_ref *getnext, struct list *end,
|
||||
}
|
||||
}
|
||||
|
||||
static inline
|
||||
struct pat_ref *pat_ref_lookup_ref(const char *reference)
|
||||
{
|
||||
int id;
|
||||
char *error;
|
||||
|
||||
/* If the reference starts by a '#', this is numeric id. */
|
||||
if (reference[0] == '#') {
|
||||
/* Try to convert the numeric id. If the conversion fails, the lookup fails. */
|
||||
id = strtol(reference + 1, &error, 10);
|
||||
if (*error != '\0')
|
||||
return NULL;
|
||||
|
||||
/* Perform the unique id lookup. */
|
||||
return pat_ref_lookupid(id);
|
||||
}
|
||||
|
||||
/* Perform the string lookup. */
|
||||
return pat_ref_lookup(reference);
|
||||
}
|
||||
|
||||
/* This function is used with map and acl management. It permits to browse
|
||||
* each reference.
|
||||
*/
|
||||
@ -1123,13 +1144,13 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
}
|
||||
|
||||
/* lookup into the refs and check the map flag */
|
||||
appctx->ctx.map.ref = pat_ref_lookup(args[2]);
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
|
||||
if (!appctx->ctx.map.ref ||
|
||||
!(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
|
||||
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use #<id> or <name>.\n";
|
||||
else
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use #<id> or <name>.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
@ -1222,13 +1243,13 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
}
|
||||
|
||||
/* lookup into the refs and check the map flag */
|
||||
appctx->ctx.map.ref = pat_ref_lookup(args[2]);
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
|
||||
if (!appctx->ctx.map.ref ||
|
||||
!(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
|
||||
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use #<id> or <name>.\n";
|
||||
else
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use #<id> or <name>.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
@ -1293,12 +1314,12 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
}
|
||||
|
||||
/* lookup into the maps */
|
||||
appctx->ctx.map.ref = pat_ref_lookup(args[2]);
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
|
||||
if (!appctx->ctx.map.ref) {
|
||||
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use #<id> or <name>.\n";
|
||||
else
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use #<id> or <name>.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
@ -1605,9 +1626,9 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
}
|
||||
|
||||
/* Lookup the reference in the maps. */
|
||||
appctx->ctx.map.ref = pat_ref_lookup(args[2]);
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
|
||||
if (!appctx->ctx.map.ref) {
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use #<id> or <name>.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
@ -1872,10 +1893,10 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
}
|
||||
|
||||
/* Lookup the reference in the maps. */
|
||||
appctx->ctx.map.ref = pat_ref_lookup(args[2]);
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
|
||||
if (!appctx->ctx.map.ref ||
|
||||
!(appctx->ctx.map.ref->flags & appctx->ctx.map.display_flags)) {
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use #<id> or <name>.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
@ -1929,12 +1950,12 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
}
|
||||
|
||||
/* Lookup for the reference. */
|
||||
appctx->ctx.map.ref = pat_ref_lookup(args[2]);
|
||||
appctx->ctx.map.ref = pat_ref_lookup_ref(args[2]);
|
||||
if (!appctx->ctx.map.ref) {
|
||||
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown map identifier. Please use #<id> or <name>.\n";
|
||||
else
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use <name>.\n";
|
||||
appctx->ctx.cli.msg = "Unknown ACL identifier. Please use #<id> or <name>.\n";
|
||||
appctx->st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
@ -4736,6 +4757,14 @@ static int stats_pats_list(struct stream_interface *si)
|
||||
|
||||
switch (appctx->st2) {
|
||||
case STAT_ST_INIT:
|
||||
/* Display the column headers. If the message cannot be sent,
|
||||
* quit the fucntion with returning 0. The function is called
|
||||
* later and restart at the state "STAT_ST_INIT".
|
||||
*/
|
||||
chunk_reset(&trash);
|
||||
chunk_appendf(&trash, "# id (name)\n");
|
||||
if (bi_putchk(si->ib, &trash) == -1)
|
||||
return 0;
|
||||
|
||||
/* Now, we start the browsing of the references lists.
|
||||
* Note that the following call to LIST_ELEM return bad pointer. The only
|
||||
@ -4750,24 +4779,23 @@ static int stats_pats_list(struct stream_interface *si)
|
||||
|
||||
case STAT_ST_LIST:
|
||||
while (appctx->ctx.map.ref) {
|
||||
|
||||
chunk_reset(&trash);
|
||||
|
||||
/* Build messages. If the reference is used by another category than
|
||||
* the listed categorie, display the information in the massage.
|
||||
*/
|
||||
if ((appctx->ctx.map.display_flags & PAT_REF_MAP) &&
|
||||
(appctx->ctx.map.ref->flags & PAT_REF_ACL)) {
|
||||
chunk_appendf(&trash, "%s (also used by an ACL)\n",
|
||||
appctx->ctx.map.ref->reference);
|
||||
chunk_appendf(&trash, "%d (%s)", appctx->ctx.map.ref->unique_id,
|
||||
appctx->ctx.map.ref->reference ? appctx->ctx.map.ref->reference : "");
|
||||
|
||||
if (appctx->ctx.map.display_flags & PAT_REF_MAP) {
|
||||
if (appctx->ctx.map.ref->flags & PAT_REF_ACL)
|
||||
chunk_appendf(&trash, " - also used by an ACL");
|
||||
}
|
||||
else if ((appctx->ctx.map.display_flags & PAT_REF_ACL) &&
|
||||
(appctx->ctx.map.ref->flags & PAT_REF_MAP)) {
|
||||
chunk_appendf(&trash, "%s (also used by a map)\n",
|
||||
appctx->ctx.map.ref->reference);
|
||||
else {
|
||||
if (appctx->ctx.map.ref->flags & PAT_REF_MAP)
|
||||
chunk_appendf(&trash, " - also used by a map");
|
||||
}
|
||||
else
|
||||
chunk_appendf(&trash, "%s\n", appctx->ctx.map.ref->reference);
|
||||
chunk_appendf(&trash, "\n");
|
||||
|
||||
if (bi_putchk(si->ib, &trash) == -1) {
|
||||
/* let's try again later from this session. We add ourselves into
|
||||
|
@ -89,6 +89,7 @@
|
||||
#include <proto/hdr_idx.h>
|
||||
#include <proto/listener.h>
|
||||
#include <proto/log.h>
|
||||
#include <proto/pattern.h>
|
||||
#include <proto/protocol.h>
|
||||
#include <proto/proto_http.h>
|
||||
#include <proto/proxy.h>
|
||||
@ -693,6 +694,8 @@ void init(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pattern_finalize_config();
|
||||
|
||||
err_code |= check_config_validity();
|
||||
if (err_code & (ERR_ABORT|ERR_FATAL)) {
|
||||
Alert("Fatal errors found in configuration.\n");
|
||||
|
150
src/pattern.c
150
src/pattern.c
@ -1562,6 +1562,23 @@ void pattern_init_head(struct pattern_head *head)
|
||||
* value as string form.
|
||||
*
|
||||
* This is used with modifiable ACL and MAPS
|
||||
*
|
||||
* The pattern reference are stored with two identifiers: the unique_id and
|
||||
* the reference.
|
||||
*
|
||||
* The reference identify a file. Each file with the same name point to the
|
||||
* same reference. We can register many times one file. If the file is modified,
|
||||
* all his dependencies are also modified. The reference can be used with map or
|
||||
* acl.
|
||||
*
|
||||
* The unique_id identify inline acl. The unique id is unique for each acl.
|
||||
* You cannot force the same id in the configuration file, because this repoort
|
||||
* an error.
|
||||
*
|
||||
* A particular case appears if the filename is a number. In this case, the
|
||||
* unique_id is set with the number represented by the filename and the
|
||||
* reference is also set. This method prevent double unique_id.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This function lookup for reference. If the reference is found, they return
|
||||
@ -1572,7 +1589,20 @@ struct pat_ref *pat_ref_lookup(const char *reference)
|
||||
struct pat_ref *ref;
|
||||
|
||||
list_for_each_entry(ref, &pattern_reference, list)
|
||||
if (strcmp(reference, ref->reference) == 0)
|
||||
if (ref->reference && strcmp(reference, ref->reference) == 0)
|
||||
return ref;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function lookup for unique id. If the reference is found, they return
|
||||
* pointer to the struct pat_ref, else return NULL.
|
||||
*/
|
||||
struct pat_ref *pat_ref_lookupid(int unique_id)
|
||||
{
|
||||
struct pat_ref *ref;
|
||||
|
||||
list_for_each_entry(ref, &pattern_reference, list)
|
||||
if (ref->unique_id == unique_id)
|
||||
return ref;
|
||||
return NULL;
|
||||
}
|
||||
@ -1663,6 +1693,34 @@ struct pat_ref *pat_ref_new(const char *reference, unsigned int flags)
|
||||
}
|
||||
|
||||
ref->flags = flags;
|
||||
ref->unique_id = -1;
|
||||
|
||||
LIST_INIT(&ref->head);
|
||||
LIST_INIT(&ref->pat);
|
||||
|
||||
LIST_ADDQ(&pattern_reference, &ref->list);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
/* This function create new reference. <unique_id> is the unique id. If
|
||||
* the value of <unique_id> is -1, the unique id is calculated later.
|
||||
* <flags> are PAT_REF_*. /!\ The reference is not checked, and must
|
||||
* be unique. The user must check the reference with "pat_ref_lookup()"
|
||||
* or pat_ref_lookupid before calling this function. If the function
|
||||
* fail, it return NULL, else return new struct pat_ref.
|
||||
*/
|
||||
struct pat_ref *pat_ref_newid(int unique_id, unsigned int flags)
|
||||
{
|
||||
struct pat_ref *ref;
|
||||
|
||||
ref = malloc(sizeof(*ref));
|
||||
if (!ref)
|
||||
return NULL;
|
||||
|
||||
ref->reference = NULL;
|
||||
ref->flags = flags;
|
||||
ref->unique_id = unique_id;
|
||||
LIST_INIT(&ref->head);
|
||||
LIST_INIT(&ref->pat);
|
||||
|
||||
@ -1961,7 +2019,7 @@ struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref
|
||||
* return -2 if out of memory
|
||||
*/
|
||||
int pattern_register(struct pattern_head *head,
|
||||
char *reference, int refflags,
|
||||
int unique_id, int refflags,
|
||||
const char *arg,
|
||||
struct sample_storage *smp,
|
||||
int patflags, char **err)
|
||||
@ -1969,30 +2027,27 @@ int pattern_register(struct pattern_head *head,
|
||||
struct pattern_expr *expr;
|
||||
struct pat_ref *ref;
|
||||
|
||||
/* If reference is set, look up for existing reference. If the
|
||||
* reference is not found, create it.
|
||||
*/
|
||||
if (reference) {
|
||||
ref = pat_ref_lookup(reference);
|
||||
if (!ref) {
|
||||
ref = pat_ref_new(reference, refflags);
|
||||
if (!ref) {
|
||||
memprintf(err, "out of memory");
|
||||
return 0;
|
||||
}
|
||||
/* Look if the unique id already exists. If exists, abort the acl creation. */
|
||||
if (unique_id >= 0) {
|
||||
ref = pat_ref_lookupid(unique_id);
|
||||
if (ref) {
|
||||
memprintf(err, "The unique id \"%d\" is already used.", unique_id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
ref = NULL;
|
||||
|
||||
/* look for reference or create it */
|
||||
expr = pattern_lookup_expr(head, ref);
|
||||
if (!expr) {
|
||||
expr = pattern_new_expr(head, ref, err);
|
||||
if (!expr)
|
||||
return 0;
|
||||
/* Create new reference. */
|
||||
ref = pat_ref_newid(unique_id, refflags);
|
||||
if (!ref) {
|
||||
memprintf(err, "out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create new pattern_expr. */
|
||||
expr = pattern_new_expr(head, ref, err);
|
||||
if (!expr)
|
||||
return 0;
|
||||
|
||||
/* Index value. */
|
||||
return pattern_add(expr, arg, smp, patflags, err);
|
||||
}
|
||||
@ -2060,10 +2115,10 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
|
||||
struct pat_ref *ref;
|
||||
struct pattern_expr *expr;
|
||||
|
||||
/* Look for existing reference. If the reference doesn't exists,
|
||||
* create it and load file.
|
||||
*/
|
||||
/* Lookup for the existing reference. */
|
||||
ref = pat_ref_lookup(filename);
|
||||
|
||||
/* If the reference doesn't exists, create it and load associated file. */
|
||||
if (!ref) {
|
||||
ref = pat_ref_new(filename, refflags);
|
||||
if (!ref) {
|
||||
@ -2170,3 +2225,50 @@ int pattern_delete(const char *key, struct pattern_expr *expr, char **err)
|
||||
expr->pat_head->delete(expr, &pattern);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function finalize the configuration parsing. Its set all the
|
||||
* automatic ids
|
||||
*/
|
||||
void pattern_finalize_config(void)
|
||||
{
|
||||
int i = 0;
|
||||
struct pat_ref *ref, *ref2, *ref3;
|
||||
struct list pr = LIST_HEAD_INIT(pr);
|
||||
|
||||
list_for_each_entry(ref, &pattern_reference, list) {
|
||||
if (ref->unique_id == -1) {
|
||||
/* Look for the first free id. */
|
||||
while (1) {
|
||||
list_for_each_entry(ref2, &pattern_reference, list) {
|
||||
if (ref2->unique_id == i) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (&ref2->list == &pattern_reference);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Uses the unique id and increment it for the next entry. */
|
||||
ref->unique_id = i;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* This sort the reference list by id. */
|
||||
list_for_each_entry_safe(ref, ref2, &pattern_reference, list) {
|
||||
LIST_DEL(&ref->list);
|
||||
list_for_each_entry(ref3, &pr, list) {
|
||||
if (ref->unique_id < ref3->unique_id) {
|
||||
LIST_ADDQ(&ref3->list, &ref->list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (&ref3->list == &pr)
|
||||
LIST_ADDQ(&pr, &ref->list);
|
||||
}
|
||||
|
||||
/* swap root */
|
||||
LIST_ADD(&pr, &pattern_reference);
|
||||
LIST_DEL(&pr);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user