mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-08 08:07:10 +02:00
MAJOR: threads/map: Make acls/maps thread safe
locks have been added in pat_ref and pattern_expr structures to protect all accesses to an instance of on of them. Moreover, a global lock has been added to protect the LRU cache used for pattern matching. Patterns are now duplicated after a successfull matching, to avoid modification by other threads when the result is used. Finally, the function reloading a pattern list has been modified to be thread-safe.
This commit is contained in:
parent
8ba59148ae
commit
b5997f740b
@ -160,6 +160,9 @@ enum lock_label {
|
|||||||
STRMS_LOCK,
|
STRMS_LOCK,
|
||||||
SSL_LOCK,
|
SSL_LOCK,
|
||||||
SSL_GEN_CERTS_LOCK,
|
SSL_GEN_CERTS_LOCK,
|
||||||
|
PATREF_LOCK,
|
||||||
|
PATEXP_LOCK,
|
||||||
|
PATLRU_LOCK,
|
||||||
LOCK_LABELS
|
LOCK_LABELS
|
||||||
};
|
};
|
||||||
struct lock_stat {
|
struct lock_stat {
|
||||||
@ -246,7 +249,8 @@ static inline void show_lock_stats()
|
|||||||
"TASK_RQ", "TASK_WQ", "POOL",
|
"TASK_RQ", "TASK_WQ", "POOL",
|
||||||
"LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER",
|
"LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER",
|
||||||
"UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS",
|
"UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS",
|
||||||
"APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS"};
|
"APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS",
|
||||||
|
"PATREF", "PATEXP", "PATLRU" };
|
||||||
int lbl;
|
int lbl;
|
||||||
|
|
||||||
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
|
for (lbl = 0; lbl < LOCK_LABELS; lbl++) {
|
||||||
|
@ -107,6 +107,9 @@ struct pat_ref {
|
|||||||
char *display; /* String displayed to identify the pattern origin. */
|
char *display; /* String displayed to identify the pattern origin. */
|
||||||
struct list head; /* The head of the list of struct pat_ref_elt. */
|
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. */
|
struct list pat; /* The head of the list of struct pattern_expr. */
|
||||||
|
#ifdef USE_THREAD
|
||||||
|
HA_SPINLOCK_T lock; /* Lock used to protect pat ref elements */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is a part of struct pat_ref. Each entry contain one
|
/* This is a part of struct pat_ref. Each entry contain one
|
||||||
@ -199,6 +202,9 @@ struct pattern_expr {
|
|||||||
struct eb_root pattern_tree; /* may be used for lookup in large datasets */
|
struct eb_root pattern_tree; /* may be used for lookup in large datasets */
|
||||||
struct eb_root pattern_tree_2; /* may be used for different types */
|
struct eb_root pattern_tree_2; /* may be used for different types */
|
||||||
int mflags; /* flags relative to the parsing or matching method. */
|
int mflags; /* flags relative to the parsing or matching method. */
|
||||||
|
#ifdef USE_THREAD
|
||||||
|
HA_RWLOCK_T lock; /* lock used to protect patterns */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is a list of expression. A struct pattern_expr can be used by
|
/* This is a list of expression. A struct pattern_expr can be used by
|
||||||
|
33
src/map.c
33
src/map.c
@ -325,12 +325,17 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
|
|||||||
* this pointer. We know we have reached the end when this
|
* this pointer. We know we have reached the end when this
|
||||||
* pointer points back to the head of the streams list.
|
* pointer points back to the head of the streams list.
|
||||||
*/
|
*/
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
LIST_INIT(&appctx->ctx.map.bref.users);
|
LIST_INIT(&appctx->ctx.map.bref.users);
|
||||||
appctx->ctx.map.bref.ref = appctx->ctx.map.ref->head.n;
|
appctx->ctx.map.bref.ref = appctx->ctx.map.ref->head.n;
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
appctx->st2 = STAT_ST_LIST;
|
appctx->st2 = STAT_ST_LIST;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case STAT_ST_LIST:
|
case STAT_ST_LIST:
|
||||||
|
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users)) {
|
if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users)) {
|
||||||
LIST_DEL(&appctx->ctx.map.bref.users);
|
LIST_DEL(&appctx->ctx.map.bref.users);
|
||||||
LIST_INIT(&appctx->ctx.map.bref.users);
|
LIST_INIT(&appctx->ctx.map.bref.users);
|
||||||
@ -354,15 +359,16 @@ static int cli_io_handler_pat_list(struct appctx *appctx)
|
|||||||
/* let's try again later from this stream. We add ourselves into
|
/* let's try again later from this stream. We add ourselves into
|
||||||
* this stream's users so that it can remove us upon termination.
|
* this stream's users so that it can remove us upon termination.
|
||||||
*/
|
*/
|
||||||
si_applet_cant_put(si);
|
|
||||||
LIST_ADDQ(&elt->back_refs, &appctx->ctx.map.bref.users);
|
LIST_ADDQ(&elt->back_refs, &appctx->ctx.map.bref.users);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
|
si_applet_cant_put(si);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get next list entry and check the end of the list */
|
/* get next list entry and check the end of the list */
|
||||||
appctx->ctx.map.bref.ref = elt->list.n;
|
appctx->ctx.map.bref.ref = elt->list.n;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
appctx->st2 = STAT_ST_FIN;
|
appctx->st2 = STAT_ST_FIN;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
@ -450,6 +456,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case STAT_ST_LIST:
|
case STAT_ST_LIST:
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
/* for each lookup type */
|
/* for each lookup type */
|
||||||
while (appctx->ctx.map.expr) {
|
while (appctx->ctx.map.expr) {
|
||||||
/* initialise chunk to build new message */
|
/* initialise chunk to build new message */
|
||||||
@ -460,6 +467,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
|
|||||||
sample.flags = SMP_F_CONST;
|
sample.flags = SMP_F_CONST;
|
||||||
sample.data.u.str.len = appctx->ctx.map.chunk.len;
|
sample.data.u.str.len = appctx->ctx.map.chunk.len;
|
||||||
sample.data.u.str.str = appctx->ctx.map.chunk.str;
|
sample.data.u.str.str = appctx->ctx.map.chunk.str;
|
||||||
|
|
||||||
if (appctx->ctx.map.expr->pat_head->match &&
|
if (appctx->ctx.map.expr->pat_head->match &&
|
||||||
sample_convert(&sample, appctx->ctx.map.expr->pat_head->expect_type))
|
sample_convert(&sample, appctx->ctx.map.expr->pat_head->expect_type))
|
||||||
pat = appctx->ctx.map.expr->pat_head->match(&sample, appctx->ctx.map.expr, 1);
|
pat = appctx->ctx.map.expr->pat_head->match(&sample, appctx->ctx.map.expr, 1);
|
||||||
@ -534,6 +542,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
|
|||||||
/* let's try again later from this stream. We add ourselves into
|
/* let's try again later from this stream. We add ourselves into
|
||||||
* this stream's users so that it can remove us upon termination.
|
* this stream's users so that it can remove us upon termination.
|
||||||
*/
|
*/
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
si_applet_cant_put(si);
|
si_applet_cant_put(si);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -542,7 +551,7 @@ static int cli_io_handler_map_lookup(struct appctx *appctx)
|
|||||||
appctx->ctx.map.expr = pat_expr_get_next(appctx->ctx.map.expr,
|
appctx->ctx.map.expr = pat_expr_get_next(appctx->ctx.map.expr,
|
||||||
&appctx->ctx.map.ref->pat);
|
&appctx->ctx.map.ref->pat);
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
appctx->st2 = STAT_ST_FIN;
|
appctx->st2 = STAT_ST_FIN;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
@ -619,8 +628,10 @@ static int cli_parse_get_map(char **args, struct appctx *appctx, void *private)
|
|||||||
static void cli_release_show_map(struct appctx *appctx)
|
static void cli_release_show_map(struct appctx *appctx)
|
||||||
{
|
{
|
||||||
if (appctx->st2 == STAT_ST_LIST) {
|
if (appctx->st2 == STAT_ST_LIST) {
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users))
|
if (!LIST_ISEMPTY(&appctx->ctx.map.bref.users))
|
||||||
LIST_DEL(&appctx->ctx.map.bref.users);
|
LIST_DEL(&appctx->ctx.map.bref.users);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,26 +728,32 @@ static int cli_parse_set_map(char **args, struct appctx *appctx, void *private)
|
|||||||
|
|
||||||
/* Try to delete the entry. */
|
/* Try to delete the entry. */
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (!pat_ref_set_by_id(appctx->ctx.map.ref, ref, args[4], &err)) {
|
if (!pat_ref_set_by_id(appctx->ctx.map.ref, ref, args[4], &err)) {
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (err)
|
if (err)
|
||||||
memprintf(&err, "%s.\n", err);
|
memprintf(&err, "%s.\n", err);
|
||||||
appctx->ctx.cli.err = err;
|
appctx->ctx.cli.err = err;
|
||||||
appctx->st0 = CLI_ST_PRINT_FREE;
|
appctx->st0 = CLI_ST_PRINT_FREE;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Else, use the entry identifier as pattern
|
/* Else, use the entry identifier as pattern
|
||||||
* string, and update the value.
|
* string, and update the value.
|
||||||
*/
|
*/
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (!pat_ref_set(appctx->ctx.map.ref, args[3], args[4], &err)) {
|
if (!pat_ref_set(appctx->ctx.map.ref, args[3], args[4], &err)) {
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (err)
|
if (err)
|
||||||
memprintf(&err, "%s.\n", err);
|
memprintf(&err, "%s.\n", err);
|
||||||
appctx->ctx.cli.err = err;
|
appctx->ctx.cli.err = err;
|
||||||
appctx->st0 = CLI_ST_PRINT_FREE;
|
appctx->st0 = CLI_ST_PRINT_FREE;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The set is done, send message. */
|
/* The set is done, send message. */
|
||||||
@ -808,10 +825,12 @@ static int cli_parse_add_map(char **args, struct appctx *appctx, void *private)
|
|||||||
|
|
||||||
/* Add value. */
|
/* Add value. */
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
if (appctx->ctx.map.display_flags == PAT_REF_MAP)
|
||||||
ret = pat_ref_add(appctx->ctx.map.ref, args[3], args[4], &err);
|
ret = pat_ref_add(appctx->ctx.map.ref, args[3], args[4], &err);
|
||||||
else
|
else
|
||||||
ret = pat_ref_add(appctx->ctx.map.ref, args[3], NULL, &err);
|
ret = pat_ref_add(appctx->ctx.map.ref, args[3], NULL, &err);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (err)
|
if (err)
|
||||||
memprintf(&err, "%s.\n", err);
|
memprintf(&err, "%s.\n", err);
|
||||||
@ -891,25 +910,31 @@ static int cli_parse_del_map(char **args, struct appctx *appctx, void *private)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try to delete the entry. */
|
/* Try to delete the entry. */
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (!pat_ref_delete_by_id(appctx->ctx.map.ref, ref)) {
|
if (!pat_ref_delete_by_id(appctx->ctx.map.ref, ref)) {
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
/* The entry is not found, send message. */
|
/* The entry is not found, send message. */
|
||||||
appctx->ctx.cli.severity = LOG_ERR;
|
appctx->ctx.cli.severity = LOG_ERR;
|
||||||
appctx->ctx.cli.msg = "Key not found.\n";
|
appctx->ctx.cli.msg = "Key not found.\n";
|
||||||
appctx->st0 = CLI_ST_PRINT;
|
appctx->st0 = CLI_ST_PRINT;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Else, use the entry identifier as pattern
|
/* Else, use the entry identifier as pattern
|
||||||
* string and try to delete the entry.
|
* string and try to delete the entry.
|
||||||
*/
|
*/
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
if (!pat_ref_delete(appctx->ctx.map.ref, args[3])) {
|
if (!pat_ref_delete(appctx->ctx.map.ref, args[3])) {
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
/* The entry is not found, send message. */
|
/* The entry is not found, send message. */
|
||||||
appctx->ctx.cli.severity = LOG_ERR;
|
appctx->ctx.cli.severity = LOG_ERR;
|
||||||
appctx->ctx.cli.msg = "Key not found.\n";
|
appctx->ctx.cli.msg = "Key not found.\n";
|
||||||
appctx->st0 = CLI_ST_PRINT;
|
appctx->st0 = CLI_ST_PRINT;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The deletion is done, send message. */
|
/* The deletion is done, send message. */
|
||||||
@ -958,7 +983,9 @@ static int cli_parse_clear_map(char **args, struct appctx *appctx, void *private
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all. */
|
/* Clear all. */
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
pat_ref_prune(appctx->ctx.map.ref);
|
pat_ref_prune(appctx->ctx.map.ref);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock);
|
||||||
|
|
||||||
/* return response */
|
/* return response */
|
||||||
appctx->st0 = CLI_ST_PROMPT;
|
appctx->st0 = CLI_ST_PROMPT;
|
||||||
|
295
src/pattern.c
295
src/pattern.c
@ -148,12 +148,16 @@ int pat_match_types[PAT_MATCH_NUM] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* this struct is used to return information */
|
/* this struct is used to return information */
|
||||||
static struct pattern static_pattern;
|
static THREAD_LOCAL struct pattern static_pattern;
|
||||||
|
static THREAD_LOCAL struct sample_data static_sample_data;
|
||||||
|
|
||||||
/* This is the root of the list of all pattern_ref avalaibles. */
|
/* This is the root of the list of all pattern_ref avalaibles. */
|
||||||
struct list pattern_reference = LIST_HEAD_INIT(pattern_reference);
|
struct list pattern_reference = LIST_HEAD_INIT(pattern_reference);
|
||||||
|
|
||||||
static struct lru64_head *pat_lru_tree;
|
static struct lru64_head *pat_lru_tree;
|
||||||
|
#ifdef USE_THREAD
|
||||||
|
HA_SPINLOCK_T pat_lru_tree_lock;
|
||||||
|
#endif
|
||||||
static unsigned long long pat_lru_seed;
|
static unsigned long long pat_lru_seed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -485,12 +489,20 @@ struct pattern *pat_match_str(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
if (pat_lru_tree) {
|
if (pat_lru_tree) {
|
||||||
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
||||||
|
|
||||||
|
SPIN_LOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
||||||
pat_lru_tree, expr, expr->revision);
|
pat_lru_tree, expr, expr->revision);
|
||||||
if (lru && lru->domain)
|
if (!lru) {
|
||||||
return lru->data;
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
else if (lru->domain) {
|
||||||
|
ret = lru->data;
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
list_for_each_entry(lst, &expr->patterns, list) {
|
list_for_each_entry(lst, &expr->patterns, list) {
|
||||||
pattern = &lst->pat;
|
pattern = &lst->pat;
|
||||||
|
|
||||||
@ -505,8 +517,10 @@ struct pattern *pat_match_str(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lru)
|
if (lru) {
|
||||||
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -522,10 +536,17 @@ struct pattern *pat_match_bin(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
if (pat_lru_tree) {
|
if (pat_lru_tree) {
|
||||||
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
||||||
|
|
||||||
|
SPIN_LOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
||||||
pat_lru_tree, expr, expr->revision);
|
pat_lru_tree, expr, expr->revision);
|
||||||
if (lru && lru->domain)
|
if (!lru) {
|
||||||
return lru->data;
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
else if (lru->domain) {
|
||||||
|
ret = lru->data;
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(lst, &expr->patterns, list) {
|
list_for_each_entry(lst, &expr->patterns, list) {
|
||||||
@ -540,8 +561,10 @@ struct pattern *pat_match_bin(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lru)
|
if (lru) {
|
||||||
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -583,10 +606,17 @@ struct pattern *pat_match_reg(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
if (pat_lru_tree) {
|
if (pat_lru_tree) {
|
||||||
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
||||||
|
|
||||||
|
SPIN_LOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
||||||
pat_lru_tree, expr, expr->revision);
|
pat_lru_tree, expr, expr->revision);
|
||||||
if (lru && lru->domain)
|
if (!lru) {
|
||||||
return lru->data;
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
else if (lru->domain) {
|
||||||
|
ret = lru->data;
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(lst, &expr->patterns, list) {
|
list_for_each_entry(lst, &expr->patterns, list) {
|
||||||
@ -598,8 +628,10 @@ struct pattern *pat_match_reg(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lru)
|
if (lru) {
|
||||||
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -643,10 +675,17 @@ struct pattern *pat_match_beg(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
if (pat_lru_tree) {
|
if (pat_lru_tree) {
|
||||||
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
||||||
|
|
||||||
|
SPIN_LOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
||||||
pat_lru_tree, expr, expr->revision);
|
pat_lru_tree, expr, expr->revision);
|
||||||
if (lru && lru->domain)
|
if (!lru) {
|
||||||
return lru->data;
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
else if (lru->domain) {
|
||||||
|
ret = lru->data;
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(lst, &expr->patterns, list) {
|
list_for_each_entry(lst, &expr->patterns, list) {
|
||||||
@ -664,8 +703,10 @@ struct pattern *pat_match_beg(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lru)
|
if (lru) {
|
||||||
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -682,10 +723,17 @@ struct pattern *pat_match_end(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
if (pat_lru_tree) {
|
if (pat_lru_tree) {
|
||||||
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
||||||
|
|
||||||
|
SPIN_LOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
||||||
pat_lru_tree, expr, expr->revision);
|
pat_lru_tree, expr, expr->revision);
|
||||||
if (lru && lru->domain)
|
if (!lru) {
|
||||||
return lru->data;
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
else if (lru->domain) {
|
||||||
|
ret = lru->data;
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(lst, &expr->patterns, list) {
|
list_for_each_entry(lst, &expr->patterns, list) {
|
||||||
@ -703,8 +751,10 @@ struct pattern *pat_match_end(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lru)
|
if (lru) {
|
||||||
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -725,10 +775,17 @@ struct pattern *pat_match_sub(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
if (pat_lru_tree) {
|
if (pat_lru_tree) {
|
||||||
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
unsigned long long seed = pat_lru_seed ^ (long)expr;
|
||||||
|
|
||||||
|
SPIN_LOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
lru = lru64_get(XXH64(smp->data.u.str.str, smp->data.u.str.len, seed),
|
||||||
pat_lru_tree, expr, expr->revision);
|
pat_lru_tree, expr, expr->revision);
|
||||||
if (lru && lru->domain)
|
if (!lru) {
|
||||||
return lru->data;
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
else if (lru->domain) {
|
||||||
|
ret = lru->data;
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(lst, &expr->patterns, list) {
|
list_for_each_entry(lst, &expr->patterns, list) {
|
||||||
@ -760,8 +817,10 @@ struct pattern *pat_match_sub(struct sample *smp, struct pattern_expr *expr, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
leave:
|
leave:
|
||||||
if (lru)
|
if (lru) {
|
||||||
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
lru64_commit(lru, ret, expr, expr->revision, NULL);
|
||||||
|
SPIN_UNLOCK(PATLRU_LOCK, &pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1600,6 +1659,8 @@ int pat_ref_delete_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt)
|
|||||||
list_for_each_entry(expr, &ref->pat, list)
|
list_for_each_entry(expr, &ref->pat, list)
|
||||||
pattern_delete(expr, elt);
|
pattern_delete(expr, elt);
|
||||||
|
|
||||||
|
/* pat_ref_elt is trashed once all expr
|
||||||
|
are cleaned and there is no ref remaining */
|
||||||
LIST_DEL(&elt->list);
|
LIST_DEL(&elt->list);
|
||||||
free(elt->sample);
|
free(elt->sample);
|
||||||
free(elt->pattern);
|
free(elt->pattern);
|
||||||
@ -1638,6 +1699,8 @@ int pat_ref_delete(struct pat_ref *ref, const char *key)
|
|||||||
list_for_each_entry(expr, &ref->pat, list)
|
list_for_each_entry(expr, &ref->pat, list)
|
||||||
pattern_delete(expr, elt);
|
pattern_delete(expr, elt);
|
||||||
|
|
||||||
|
/* pat_ref_elt is trashed once all expr
|
||||||
|
are cleaned and there is no ref remaining */
|
||||||
LIST_DEL(&elt->list);
|
LIST_DEL(&elt->list);
|
||||||
free(elt->sample);
|
free(elt->sample);
|
||||||
free(elt->pattern);
|
free(elt->pattern);
|
||||||
@ -1695,9 +1758,6 @@ static inline int pat_ref_set_elt(struct pat_ref *ref, struct pat_ref_elt *elt,
|
|||||||
memprintf(err, "out of memory error");
|
memprintf(err, "out of memory error");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
free(elt->sample);
|
|
||||||
elt->sample = sample;
|
|
||||||
|
|
||||||
/* Load sample in each reference. All the conversion are tested
|
/* Load sample in each reference. All the conversion are tested
|
||||||
* below, normally these calls dosn't fail.
|
* below, normally these calls dosn't fail.
|
||||||
*/
|
*/
|
||||||
@ -1705,11 +1765,18 @@ static inline int pat_ref_set_elt(struct pat_ref *ref, struct pat_ref_elt *elt,
|
|||||||
if (!expr->pat_head->parse_smp)
|
if (!expr->pat_head->parse_smp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
data = pattern_find_smp(expr, elt);
|
data = pattern_find_smp(expr, elt);
|
||||||
if (data && *data && !expr->pat_head->parse_smp(sample, *data))
|
if (data && *data && !expr->pat_head->parse_smp(sample, *data))
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* free old sample only when all exprs are updated */
|
||||||
|
free(elt->sample);
|
||||||
|
elt->sample = sample;
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1805,7 +1872,7 @@ struct pat_ref *pat_ref_new(const char *reference, const char *display, unsigned
|
|||||||
|
|
||||||
LIST_INIT(&ref->head);
|
LIST_INIT(&ref->head);
|
||||||
LIST_INIT(&ref->pat);
|
LIST_INIT(&ref->pat);
|
||||||
|
SPIN_INIT(&ref->lock);
|
||||||
LIST_ADDQ(&pattern_reference, &ref->list);
|
LIST_ADDQ(&pattern_reference, &ref->list);
|
||||||
|
|
||||||
return ref;
|
return ref;
|
||||||
@ -1924,11 +1991,14 @@ int pat_ref_push(struct pat_ref_elt *elt, struct pattern_expr *expr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
/* index pattern */
|
/* index pattern */
|
||||||
if (!expr->pat_head->index(expr, &pattern, err)) {
|
if (!expr->pat_head->index(expr, &pattern, err)) {
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
free(data);
|
free(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1983,6 +2053,7 @@ int pat_ref_add(struct pat_ref *ref,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1995,34 +2066,19 @@ int pat_ref_add(struct pat_ref *ref,
|
|||||||
void pat_ref_reload(struct pat_ref *ref, struct pat_ref *replace)
|
void pat_ref_reload(struct pat_ref *ref, struct pat_ref *replace)
|
||||||
{
|
{
|
||||||
struct pattern_expr *expr;
|
struct pattern_expr *expr;
|
||||||
struct pat_ref_elt *elt;
|
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
|
|
||||||
pat_ref_prune(ref);
|
|
||||||
|
|
||||||
LIST_ADD(&replace->head, &ref->head);
|
|
||||||
LIST_DEL(&replace->head);
|
|
||||||
|
|
||||||
list_for_each_entry(elt, &ref->head, list) {
|
|
||||||
list_for_each_entry(expr, &ref->pat, list) {
|
|
||||||
if (!pat_ref_push(elt, expr, 0, &err)) {
|
|
||||||
send_log(NULL, LOG_NOTICE, "%s", err);
|
|
||||||
free(err);
|
|
||||||
err = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function prune all entries of <ref>. This function
|
|
||||||
* prune the associated pattern_expr.
|
|
||||||
*/
|
|
||||||
void pat_ref_prune(struct pat_ref *ref)
|
|
||||||
{
|
|
||||||
struct pat_ref_elt *elt, *safe;
|
struct pat_ref_elt *elt, *safe;
|
||||||
struct pattern_expr *expr;
|
|
||||||
struct bref *bref, *back;
|
struct bref *bref, *back;
|
||||||
|
struct sample_data *data;
|
||||||
|
struct pattern pattern;
|
||||||
|
|
||||||
|
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &ref->lock);
|
||||||
|
list_for_each_entry(expr, &ref->pat, list) {
|
||||||
|
RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all expr are locked, we can safely remove all pat_ref */
|
||||||
list_for_each_entry_safe(elt, safe, &ref->head, list) {
|
list_for_each_entry_safe(elt, safe, &ref->head, list) {
|
||||||
list_for_each_entry_safe(bref, back, &elt->back_refs, users) {
|
list_for_each_entry_safe(bref, back, &elt->back_refs, users) {
|
||||||
/*
|
/*
|
||||||
@ -2041,8 +2097,95 @@ void pat_ref_prune(struct pat_ref *ref)
|
|||||||
free(elt);
|
free(elt);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(expr, &ref->pat, list)
|
/* switch pat_ret_elt lists */
|
||||||
|
LIST_ADD(&replace->head, &ref->head);
|
||||||
|
LIST_DEL(&replace->head);
|
||||||
|
|
||||||
|
list_for_each_entry(expr, &ref->pat, list) {
|
||||||
expr->pat_head->prune(expr);
|
expr->pat_head->prune(expr);
|
||||||
|
list_for_each_entry(elt, &ref->head, list) {
|
||||||
|
/* Create sample */
|
||||||
|
if (elt->sample && expr->pat_head->parse_smp) {
|
||||||
|
/* New sample. */
|
||||||
|
data = malloc(sizeof(*data));
|
||||||
|
if (!data)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Parse value. */
|
||||||
|
if (!expr->pat_head->parse_smp(elt->sample, data)) {
|
||||||
|
memprintf(&err, "unable to parse '%s'", elt->sample);
|
||||||
|
send_log(NULL, LOG_NOTICE, "%s", err);
|
||||||
|
free(err);
|
||||||
|
free(data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
/* initialise pattern */
|
||||||
|
memset(&pattern, 0, sizeof(pattern));
|
||||||
|
pattern.data = data;
|
||||||
|
pattern.ref = elt;
|
||||||
|
|
||||||
|
/* parse pattern */
|
||||||
|
if (!expr->pat_head->parse(elt->pattern, &pattern, expr->mflags, &err)) {
|
||||||
|
send_log(NULL, LOG_NOTICE, "%s", err);
|
||||||
|
free(err);
|
||||||
|
free(data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* index pattern */
|
||||||
|
if (!expr->pat_head->index(expr, &pattern, &err)) {
|
||||||
|
send_log(NULL, LOG_NOTICE, "%s", err);
|
||||||
|
free(err);
|
||||||
|
free(data);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
|
}
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function prune all entries of <ref>. This function
|
||||||
|
* prune the associated pattern_expr.
|
||||||
|
*/
|
||||||
|
void pat_ref_prune(struct pat_ref *ref)
|
||||||
|
{
|
||||||
|
struct pat_ref_elt *elt, *safe;
|
||||||
|
struct pattern_expr *expr;
|
||||||
|
struct bref *bref, *back;
|
||||||
|
|
||||||
|
list_for_each_entry(expr, &ref->pat, list) {
|
||||||
|
RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
|
expr->pat_head->prune(expr);
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we trash pat_ref_elt in a second time to ensure that data is
|
||||||
|
free once there is no ref on it */
|
||||||
|
list_for_each_entry_safe(elt, safe, &ref->head, list) {
|
||||||
|
list_for_each_entry_safe(bref, back, &elt->back_refs, users) {
|
||||||
|
/*
|
||||||
|
* we have to unlink all watchers. We must not relink them if
|
||||||
|
* this elt was the last one in the list.
|
||||||
|
*/
|
||||||
|
LIST_DEL(&bref->users);
|
||||||
|
LIST_INIT(&bref->users);
|
||||||
|
if (elt->list.n != &ref->head)
|
||||||
|
LIST_ADDQ(&LIST_ELEM(elt->list.n, struct stream *, list)->back_refs, &bref->users);
|
||||||
|
bref->ref = elt->list.n;
|
||||||
|
}
|
||||||
|
LIST_DEL(&elt->list);
|
||||||
|
free(elt->pattern);
|
||||||
|
free(elt->sample);
|
||||||
|
free(elt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function lookup for existing reference <ref> in pattern_head <head>. */
|
/* This function lookup for existing reference <ref> in pattern_head <head>. */
|
||||||
@ -2124,6 +2267,8 @@ struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref
|
|||||||
|
|
||||||
expr->ref = ref;
|
expr->ref = ref;
|
||||||
|
|
||||||
|
RWLOCK_INIT(&expr->lock);
|
||||||
|
|
||||||
/* We must free this pattern if it is no more used. */
|
/* We must free this pattern if it is no more used. */
|
||||||
list->do_free = 1;
|
list->do_free = 1;
|
||||||
}
|
}
|
||||||
@ -2434,9 +2579,41 @@ struct pattern *pattern_exec_match(struct pattern_head *head, struct sample *smp
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
list_for_each_entry(list, &head->head, list) {
|
list_for_each_entry(list, &head->head, list) {
|
||||||
|
RWLOCK_RDLOCK(PATEXP_LOCK, &list->expr->lock);
|
||||||
pat = head->match(smp, list->expr, fill);
|
pat = head->match(smp, list->expr, fill);
|
||||||
if (pat)
|
if (pat) {
|
||||||
|
/* We duplicate the pattern cause it could be modified
|
||||||
|
by another thread */
|
||||||
|
if (pat != &static_pattern) {
|
||||||
|
memcpy(&static_pattern, pat, sizeof(struct pattern));
|
||||||
|
pat = &static_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We also duplicate the sample data for
|
||||||
|
same reason */
|
||||||
|
if (pat->data && (pat->data != &static_sample_data)) {
|
||||||
|
switch(pat->type) {
|
||||||
|
case SMP_T_STR:
|
||||||
|
static_sample_data.type = SMP_T_STR;
|
||||||
|
static_sample_data.u.str = *get_trash_chunk();
|
||||||
|
static_sample_data.u.str.len = pat->data->u.str.len;
|
||||||
|
if (static_sample_data.u.str.len >= static_sample_data.u.str.size)
|
||||||
|
static_sample_data.u.str.len = static_sample_data.u.str.size - 1;
|
||||||
|
memcpy(static_sample_data.u.str.str, pat->data->u.str.str, static_sample_data.u.str.len);
|
||||||
|
static_sample_data.u.str.str[static_sample_data.u.str.len] = 0;
|
||||||
|
case SMP_T_IPV4:
|
||||||
|
case SMP_T_IPV6:
|
||||||
|
case SMP_T_SINT:
|
||||||
|
memcpy(&static_sample_data, pat->data, sizeof(struct sample_data));
|
||||||
|
default:
|
||||||
|
pat->data = NULL;
|
||||||
|
}
|
||||||
|
pat->data = &static_sample_data;
|
||||||
|
}
|
||||||
|
RWLOCK_RDUNLOCK(PATEXP_LOCK, &list->expr->lock);
|
||||||
return pat;
|
return pat;
|
||||||
|
}
|
||||||
|
RWLOCK_RDUNLOCK(PATEXP_LOCK, &list->expr->lock);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -2450,7 +2627,9 @@ void pattern_prune(struct pattern_head *head)
|
|||||||
LIST_DEL(&list->list);
|
LIST_DEL(&list->list);
|
||||||
if (list->do_free) {
|
if (list->do_free) {
|
||||||
LIST_DEL(&list->expr->list);
|
LIST_DEL(&list->expr->list);
|
||||||
|
RWLOCK_WRLOCK(PATEXP_LOCK, &list->expr->lock);
|
||||||
head->prune(list->expr);
|
head->prune(list->expr);
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &list->expr->lock);
|
||||||
free(list->expr);
|
free(list->expr);
|
||||||
}
|
}
|
||||||
free(list);
|
free(list);
|
||||||
@ -2497,7 +2676,9 @@ struct sample_data **pattern_find_smp(struct pattern_expr *expr, struct pat_ref_
|
|||||||
*/
|
*/
|
||||||
int pattern_delete(struct pattern_expr *expr, struct pat_ref_elt *ref)
|
int pattern_delete(struct pattern_expr *expr, struct pat_ref_elt *ref)
|
||||||
{
|
{
|
||||||
|
RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
expr->pat_head->delete(expr, ref);
|
expr->pat_head->delete(expr, ref);
|
||||||
|
RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2511,8 +2692,10 @@ void pattern_finalize_config(void)
|
|||||||
struct list pr = LIST_HEAD_INIT(pr);
|
struct list pr = LIST_HEAD_INIT(pr);
|
||||||
|
|
||||||
pat_lru_seed = random();
|
pat_lru_seed = random();
|
||||||
if (global.tune.pattern_cache)
|
if (global.tune.pattern_cache) {
|
||||||
pat_lru_tree = lru64_new(global.tune.pattern_cache);
|
pat_lru_tree = lru64_new(global.tune.pattern_cache);
|
||||||
|
SPIN_INIT(&pat_lru_tree_lock);
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry(ref, &pattern_reference, list) {
|
list_for_each_entry(ref, &pattern_reference, list) {
|
||||||
if (ref->unique_id == -1) {
|
if (ref->unique_id == -1) {
|
||||||
|
@ -2621,7 +2621,9 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream
|
|||||||
|
|
||||||
/* perform update */
|
/* perform update */
|
||||||
/* returned code: 1=ok, 0=ko */
|
/* returned code: 1=ok, 0=ko */
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &ref->lock);
|
||||||
pat_ref_delete(ref, key->str);
|
pat_ref_delete(ref, key->str);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
|
||||||
|
|
||||||
free_trash_chunk(key);
|
free_trash_chunk(key);
|
||||||
break;
|
break;
|
||||||
@ -2647,8 +2649,10 @@ http_req_get_intercept_rule(struct proxy *px, struct list *rules, struct stream
|
|||||||
|
|
||||||
/* perform update */
|
/* perform update */
|
||||||
/* add entry only if it does not already exist */
|
/* add entry only if it does not already exist */
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &ref->lock);
|
||||||
if (pat_ref_find_elt(ref, key->str) == NULL)
|
if (pat_ref_find_elt(ref, key->str) == NULL)
|
||||||
pat_ref_add(ref, key->str, NULL, NULL);
|
pat_ref_add(ref, key->str, NULL, NULL);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
|
||||||
|
|
||||||
free_trash_chunk(key);
|
free_trash_chunk(key);
|
||||||
break;
|
break;
|
||||||
@ -2911,7 +2915,9 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct stream
|
|||||||
|
|
||||||
/* perform update */
|
/* perform update */
|
||||||
/* returned code: 1=ok, 0=ko */
|
/* returned code: 1=ok, 0=ko */
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &ref->lock);
|
||||||
pat_ref_delete(ref, key->str);
|
pat_ref_delete(ref, key->str);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
|
||||||
|
|
||||||
free_trash_chunk(key);
|
free_trash_chunk(key);
|
||||||
break;
|
break;
|
||||||
@ -2974,13 +2980,14 @@ http_res_get_intercept_rule(struct proxy *px, struct list *rules, struct stream
|
|||||||
value->str[value->len] = '\0';
|
value->str[value->len] = '\0';
|
||||||
|
|
||||||
/* perform update */
|
/* perform update */
|
||||||
|
SPIN_LOCK(PATREF_LOCK, &ref->lock);
|
||||||
if (pat_ref_find_elt(ref, key->str) != NULL)
|
if (pat_ref_find_elt(ref, key->str) != NULL)
|
||||||
/* update entry if it exists */
|
/* update entry if it exists */
|
||||||
pat_ref_set(ref, key->str, value->str, NULL);
|
pat_ref_set(ref, key->str, value->str, NULL);
|
||||||
else
|
else
|
||||||
/* insert a new entry */
|
/* insert a new entry */
|
||||||
pat_ref_add(ref, key->str, value->str, NULL);
|
pat_ref_add(ref, key->str, value->str, NULL);
|
||||||
|
SPIN_UNLOCK(PATREF_LOCK, &ref->lock);
|
||||||
free_trash_chunk(key);
|
free_trash_chunk(key);
|
||||||
free_trash_chunk(value);
|
free_trash_chunk(value);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user