The FreeRADIUS server
$Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
|
Functions to edit pair lists, and track undo operations. More...
#include <freeradius-devel/util/value.h>
#include <freeradius-devel/util/talloc.h>
#include "edit.h"
#include "calc.h"
Go to the source code of this file.
Data Structures | |
struct | fr_edit_ignore_t |
struct | fr_edit_list_s |
Track a series of edits. More... | |
struct | fr_edit_t |
Track one particular edit. More... | |
union | fr_edit_t.__unnamed124__ |
union | fr_edit_t.__unnamed124__.__unnamed126__ |
struct | fr_edit_t.__unnamed124__.__unnamed128__ |
Macros | |
#define | COPY(_x) |
#define | COPY |
#define | NEXT_A do { a = an; an = fr_pair_list_next(&dst->children, a); } while (0) |
#define | NEXT_B do { b = bn; bn = fr_pair_list_next(src, b); } while (0) |
Enumerations | |
enum | fr_edit_op_t { FR_EDIT_INVALID = 0 , FR_EDIT_DELETE , FR_EDIT_VALUE , FR_EDIT_CLEAR , FR_EDIT_INSERT , FR_EDIT_CHILD } |
Functions to edit pair lists, and track undo operations.
This file implements an "edit list" for changing values of fr_pair_t. After some investigation, it turns out that it's much easier to have an "undo list" than to track partially applied transactions. Tracking partial transactions means that none of the fr_pair_foo() functions will work, as some pairs are in the "old" list and some in the "new" list. Also, a transaction may still fail when we finalize it by moving the pairs around.
In contrast, an "undo" list means that all of the fr_pair_foo() functions will work, as any list contains only "active" pairs. And we never need to "finalize" a transaction, as the lists are already in their final form. The only thing needed for finalization is to free the undo list. Which can never fail.
Note that the functions here require the input VPs to already have the correct talloc parent! The only thing the edit list does is to record "undo" actions.
The only exception to this is fr_edit_list_apply_list_assignment(). Which does call talloc_steal, and then also frees any pairs which weren't applied to the LHS.
Definition in file edit.c.
struct fr_edit_ignore_t |
Data Fields | ||
---|---|---|
fr_dlist_t | entry | |
fr_pair_list_t * | list | list to ignore (never dereferenced) |
struct fr_edit_list_s |
Data Fields | ||
---|---|---|
fr_pair_list_t | deleted_pairs | |
fr_edit_t * | e | so we don't have to loop over parent edits on abort |
fr_dlist_head_t | ignore | lists to ignore |
fr_edit_list_t * | parent | for nested transactions |
fr_dlist_head_t | undo |
struct fr_edit_t |
Data Fields | ||
---|---|---|
union fr_edit_t | __unnamed__ | |
fr_dlist_t | entry | linked list of edits |
fr_edit_op_t | op | edit operation to perform |
fr_pair_t * | vp | pair edited, deleted, or inserted |
union fr_edit_t.__unnamed124__ |
Data Fields | ||
---|---|---|
__unnamed124__ | __unnamed__ | |
__unnamed124__ | __unnamed__ |
union fr_edit_t.__unnamed124__.__unnamed126__ |
Data Fields | ||
---|---|---|
fr_edit_list_t * | child_edit | |
fr_pair_list_t | children | original child list, for "clear" |
fr_value_box_t | data | original data |
struct fr_edit_t.__unnamed124__.__unnamed128__ |
Data Fields | ||
---|---|---|
fr_pair_list_t * | list | parent list |
fr_pair_t * | ref | reference pair for delete, insert before/after |
#define COPY | ( | _x | ) |
#define COPY |
#define NEXT_A do { a = an; an = fr_pair_list_next(&dst->children, a); } while (0) |
#define NEXT_B do { b = bn; bn = fr_pair_list_next(src, b); } while (0) |
enum fr_edit_op_t |
|
static |
|
static |
Record one particular edit.
For INSERT / DELETE, this function will also insert / delete the VP.
For VALUE changes, this function must be called BEFORE the value is changed. Once this function has been called, it is then safe to edit the value in place.
Note that VALUE changes for structural types are allowed ONLY when using T_OP_SET, which over-writes previous values. For every other modification to structural types, we MUST instead call insert / delete on the vp_group.
Definition at line 247 of file edit.c.
|
static |
void fr_edit_list_abort | ( | fr_edit_list_t * | el | ) |
fr_edit_list_t* fr_edit_list_alloc | ( | TALLOC_CTX * | ctx, |
int | hint, | ||
fr_edit_list_t * | parent | ||
) |
Allocate an edit list.
Edit lists can be nested. If the child list commits, then it does nothing until the parent list commits. On the other hand, if the child list aborts, then the parent list might continue.
ctx | talloc context. Ignored if parent!=NULL |
hint | how many edits we are likely to allocate |
parent | a parent edit list |
Definition at line 790 of file edit.c.
int fr_edit_list_apply_list_assignment | ( | fr_edit_list_t * | el, |
fr_pair_t * | dst, | ||
fr_token_t | op, | ||
fr_pair_list_t * | src, | ||
bool | copy | ||
) |
Apply operators to lists.
= is "if found vp, do nothing. Otherwise call fr_edit_list_insert_pair_tail()
The src list is sorted, but is otherwise not modified.
Definition at line 1487 of file edit.c.
int fr_edit_list_apply_pair_assignment | ( | fr_edit_list_t * | el, |
fr_pair_t * | vp, | ||
fr_token_t | op, | ||
fr_value_box_t const * | in | ||
) |
Apply operators to pairs.
:= is "if found vp, call fr_edit_list_pair_replace(). Otherwise call fr_edit_list_insert_pair_tail() = is "if found vp, do nothing. Otherwise call fr_edit_list_insert_pair_tail()
Definition at line 976 of file edit.c.
void fr_edit_list_commit | ( | fr_edit_list_t * | el | ) |
|
static |
|
static |
int fr_edit_list_free_pair_children | ( | fr_edit_list_t * | el, |
fr_pair_t * | vp | ||
) |
Free children of a structural pair.
This function mirrors fr_pair_replace().
After this function returns, the new VP has replaced the old one, and the new one can be edited.
Definition at line 709 of file edit.c.
int fr_edit_list_insert_list_after | ( | fr_edit_list_t * | el, |
fr_pair_list_t * | list, | ||
fr_pair_t * | pos, | ||
fr_pair_list_t * | to_insert | ||
) |
Notes.
Unlike "update" sections, edits are not hierarchical. If we're editing values a list, then the list has to exist. If we're inserting pairs in a list, then we find the lowest existing pair, and add pairs there.
The functions tmpl_extents_find() and tmpl_extents_build_to_leaf_parent() should help us figure out where the VPs exist or not.
The overall "update" algorithm is now:
alloc(edit list) foreach entry in the things to do expand LHS if needed to local TMPL expand RHS if needed to local box / cursor / TMPL use LHS/RHS cursors to find VPs edit VPs, recording edits free temporary map commit(edit list)
Insert a list after a particular point in another list.
This function mirrors fr_pair_list_append(), but with a bit more control over where the to_insert list ends up.
There's nothing magical about this function, it's just easier to have it here than in multiple places in the code.
Definition at line 888 of file edit.c.
int fr_edit_list_insert_pair_after | ( | fr_edit_list_t * | el, |
fr_pair_list_t * | list, | ||
fr_pair_t * | pos, | ||
fr_pair_t * | vp | ||
) |
Insert a new VP after an existing one.
This function mirrors fr_pair_insert_after().
After this function returns, the new VP has been inserted into the list.
Definition at line 562 of file edit.c.
int fr_edit_list_pair_delete | ( | fr_edit_list_t * | el, |
fr_pair_list_t * | list, | ||
fr_pair_t * | vp | ||
) |
Delete a VP.
This function mirrors fr_pair_delete()
After this function returns, the VP has been removed from the list.
Definition at line 575 of file edit.c.
int fr_edit_list_pair_delete_by_da | ( | fr_edit_list_t * | el, |
fr_pair_list_t * | list, | ||
fr_dict_attr_t const * | da | ||
) |
Delete VPs with a matching da.
This function mirrors fr_pair_delete_by_da()
Definition at line 594 of file edit.c.
int fr_edit_list_replace_pair | ( | fr_edit_list_t * | el, |
fr_pair_list_t * | list, | ||
fr_pair_t * | to_replace, | ||
fr_pair_t * | vp | ||
) |
Replace a pair with another one.
This function mirrors fr_pair_replace().
After this function returns, the new VP has replaced the old one, and the new one can be edited.
Definition at line 658 of file edit.c.
int fr_edit_list_replace_pair_value | ( | fr_edit_list_t * | el, |
fr_pair_t * | vp, | ||
fr_value_box_t * | box | ||
) |
Write a new value to the fr_value_box_t.
After this function returns, the value has been updated.
Definition at line 635 of file edit.c.
int fr_edit_list_save_pair_value | ( | fr_edit_list_t * | el, |
fr_pair_t * | vp | ||
) |
Record the value of a leaf fr_value_box_t.
After this function returns, it's safe to edit the pair.
Definition at line 622 of file edit.c.
|
static |
|
static |
|
static |
|
static |