From: Alan T. DeKok Date: Sat, 7 May 2022 12:19:49 +0000 (-0400) Subject: add "ignore this list" entries. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4f999f569201fac377e36af4f4ee76873a2b0ed1;p=thirdparty%2Ffreeradius-server.git add "ignore this list" entries. If we're inserting a new structural member, then we don't need to undo edits to any children in it's lists. Those edits will be undone automatically when the parent pair is undone. We keep a separate list of "lists to ignore", and check that before doing anything. If the list can be ignored, then we discard delete / clear / etc. In inserts, if the VP is structural, then remember its child list, so that we can ignore edits to it, too. --- diff --git a/src/lib/util/edit.c b/src/lib/util/edit.c index ee67dced781..6ed8a188576 100644 --- a/src/lib/util/edit.c +++ b/src/lib/util/edit.c @@ -60,6 +60,8 @@ struct fr_edit_list_s { */ fr_dlist_head_t undo; + fr_dlist_head_t ignore; //!< lists to ignore + /* * VPs which were inserted, and then over-written by a * later edit. @@ -86,6 +88,10 @@ typedef struct { }; } fr_edit_t; +typedef struct { + fr_dlist_t entry; //!< linked list of edits + fr_pair_list_t *list; //!< list to ignore (never dereferenced) +} fr_edit_ignore_t; /** Undo one particular edit. */ @@ -198,6 +204,34 @@ static int edit_record(fr_edit_list_t *el, fr_edit_op_t op, fr_pair_t *vp, fr_pa fr_assert(el != NULL); fr_assert(vp != NULL); + /* + * When we insert a structural type, we also want to + * ignore edits to it's children. The "ignore list" + * allows us to track that. + */ + fr_dlist_foreach(&el->ignore, fr_edit_ignore_t, i) { + if (i->list == list) { + /* + * We only need to check inserts for + * lists which are marked "ignore" + */ + if (op != FR_EDIT_INSERT) return 0; + + /* + * And then only if it's a structural type. + */ + if (!fr_type_is_structural(vp->da->type)) return 0; + + /* + * Otherwise we're inserting a VP which + * has a child list. Remember that we + * need to ignore edits to this list, + * too. + */ + goto insert_ignore; + } + } + /* * Search for previous edits. * @@ -396,6 +430,21 @@ static int edit_record(fr_edit_list_t *el, fr_edit_op_t op, fr_pair_t *vp, fr_pa } fr_dlist_insert_tail(&el->undo, e); + + /* + * Insert an "ignore" entry. + */ + if ((op == FR_EDIT_INSERT) && fr_type_is_structural(vp->da->type)) { + fr_edit_ignore_t *i; + + insert_ignore: + i = talloc_zero(el, fr_edit_ignore_t); + if (!i) return 0; + + i->list = list; + fr_dlist_insert_tail(&el->ignore, i); + } + return 0; } @@ -581,6 +630,7 @@ fr_edit_list_t *fr_edit_list_alloc(TALLOC_CTX *ctx, int hint) if (!el) return NULL; fr_dlist_init(&el->undo, fr_edit_t, entry); + fr_dlist_init(&el->ignore, fr_edit_ignore_t, entry); fr_pair_list_init(&el->deleted_pairs);