mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
MINOR: pattern: introduce pat_ref_delete_by_ptr() to delete a valid reference
Till now the only way to remove a known reference was via pat_ref_delete_by_id() which scans the whole list to find a matching pointer. Let's add pat_ref_delete_by_ptr() which takes a valid pointer. It can be called by the function above after the pointer is found, and can also be used to roll back a failed insertion much more efficiently.
This commit is contained in:
parent
a98b2882ac
commit
1fd52f70e5
@ -187,6 +187,7 @@ int pat_ref_add(struct pat_ref *ref, const char *pattern, const char *sample, ch
|
||||
int pat_ref_set(struct pat_ref *ref, const char *pattern, const char *sample, char **err);
|
||||
int pat_ref_set_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt, const char *value, char **err);
|
||||
int pat_ref_delete(struct pat_ref *ref, const char *key);
|
||||
void pat_ref_delete_by_ptr(struct pat_ref *ref, struct pat_ref_elt *elt);
|
||||
int pat_ref_delete_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt);
|
||||
int pat_ref_prune(struct pat_ref *ref);
|
||||
int pat_ref_load(struct pat_ref *ref, struct pattern_expr *expr, int patflags, int soe, char **err);
|
||||
|
106
src/pattern.c
106
src/pattern.c
@ -1485,100 +1485,78 @@ struct pat_ref *pat_ref_lookupid(int unique_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function removes from the pattern reference <ref> all the patterns
|
||||
* attached to the reference element <elt>, and the element itself. The
|
||||
* reference must be locked.
|
||||
*/
|
||||
void pat_ref_delete_by_ptr(struct pat_ref *ref, struct pat_ref_elt *elt)
|
||||
{
|
||||
struct pattern_expr *expr;
|
||||
struct bref *bref, *back;
|
||||
|
||||
/*
|
||||
* we have to unlink all watchers from this reference pattern. We must
|
||||
* not relink them if this elt was the last one in the list.
|
||||
*/
|
||||
list_for_each_entry_safe(bref, back, &elt->back_refs, users) {
|
||||
LIST_DEL(&bref->users);
|
||||
LIST_INIT(&bref->users);
|
||||
if (elt->list.n != &ref->head)
|
||||
LIST_ADDQ(&LIST_ELEM(elt->list.n, typeof(elt), list)->back_refs, &bref->users);
|
||||
bref->ref = elt->list.n;
|
||||
}
|
||||
|
||||
/* delete all entries from all expressions for this pattern */
|
||||
list_for_each_entry(expr, &ref->pat, list)
|
||||
HA_RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||
|
||||
pat_delete_gen(ref, elt);
|
||||
|
||||
list_for_each_entry(expr, &ref->pat, list)
|
||||
HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||
|
||||
LIST_DEL(&elt->list);
|
||||
free(elt->sample);
|
||||
free(elt->pattern);
|
||||
free(elt);
|
||||
}
|
||||
|
||||
/* This function removes all the patterns matching the pointer <refelt> from
|
||||
* the reference and from each expr member of this reference. This function
|
||||
* returns 1 if the entry was found and deleted, otherwise zero.
|
||||
*/
|
||||
int pat_ref_delete_by_id(struct pat_ref *ref, struct pat_ref_elt *refelt)
|
||||
{
|
||||
struct pattern_expr *expr;
|
||||
struct pat_ref_elt *elt, *safe;
|
||||
struct bref *bref, *back;
|
||||
|
||||
/* delete pattern from reference */
|
||||
list_for_each_entry_safe(elt, safe, &ref->head, list) {
|
||||
if (elt == refelt) {
|
||||
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, typeof(elt), list)->back_refs, &bref->users);
|
||||
bref->ref = elt->list.n;
|
||||
}
|
||||
|
||||
/* delete all entries from all expressions for this pattern */
|
||||
list_for_each_entry(expr, &ref->pat, list)
|
||||
HA_RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||
|
||||
pat_delete_gen(ref, elt);
|
||||
|
||||
list_for_each_entry(expr, &ref->pat, list)
|
||||
HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||
|
||||
/* pat_ref_elt is trashed once all expr
|
||||
are cleaned and there is no ref remaining */
|
||||
LIST_DEL(&elt->list);
|
||||
free(elt->sample);
|
||||
free(elt->pattern);
|
||||
free(elt);
|
||||
pat_ref_delete_by_ptr(ref, elt);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function remove all pattern match <key> from the the reference
|
||||
/* This function removes all patterns matching <key> from the reference
|
||||
* and from each expr member of the reference. This function returns 1
|
||||
* if the deletion is done and return 0 is the entry is not found.
|
||||
* if the deletion is done and returns 0 is the entry is not found.
|
||||
*/
|
||||
int pat_ref_delete(struct pat_ref *ref, const char *key)
|
||||
{
|
||||
struct pattern_expr *expr;
|
||||
struct pat_ref_elt *elt, *safe;
|
||||
struct bref *bref, *back;
|
||||
int found = 0;
|
||||
|
||||
/* delete pattern from reference */
|
||||
list_for_each_entry_safe(elt, safe, &ref->head, list) {
|
||||
if (strcmp(key, elt->pattern) == 0) {
|
||||
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, typeof(elt), list)->back_refs, &bref->users);
|
||||
bref->ref = elt->list.n;
|
||||
}
|
||||
|
||||
list_for_each_entry(expr, &ref->pat, list)
|
||||
HA_RWLOCK_WRLOCK(PATEXP_LOCK, &expr->lock);
|
||||
|
||||
pat_delete_gen(ref, elt);
|
||||
|
||||
list_for_each_entry(expr, &ref->pat, list)
|
||||
HA_RWLOCK_WRUNLOCK(PATEXP_LOCK, &expr->lock);
|
||||
|
||||
/* pat_ref_elt is trashed once all expr
|
||||
are cleaned and there is no ref remaining */
|
||||
LIST_DEL(&elt->list);
|
||||
free(elt->sample);
|
||||
free(elt->pattern);
|
||||
free(elt);
|
||||
|
||||
pat_ref_delete_by_ptr(ref, elt);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return 0;
|
||||
return 1;
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1897,7 +1875,7 @@ int pat_ref_add(struct pat_ref *ref,
|
||||
list_for_each_entry(expr, &ref->pat, list) {
|
||||
if (!pat_ref_push(elt, expr, 0, err)) {
|
||||
/* If the insertion fails, try to delete all the added entries. */
|
||||
pat_ref_delete_by_id(ref, elt);
|
||||
pat_ref_delete_by_ptr(ref, elt);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user