Edit Transaction Examples
Edit transactions are used to modify configuration datastores. The Database Operations section explains the callback functions that are used to implement an edit transaction. This section provides guidelines and examples for handling various editing procedures.
There are several operations that cause an edit transaction to be executed. The Database Deployment Variants section describes the different internal database deployment options. The Databases variant used on the server will determine which operations are available.
Database Edit APIs (DB-API)
Newval and Curval Parameters
The newval
and curval
parameters that are passed
to SIL and SIL-SA callback functions can be used to
implement YANG instrumentation for configuration data nodes.
The properties and usage of these parameters is explained
in this section.
newval
: edit callback input parameternon-NULL: The new value that will be set if the edit succeeds.
NULL: no new value if the edit is a delete operation
curval
: edit callback input parameternon-NULL: The current value that will be replaced if the edit succeeds.
NULL: There is no current value for the node.
A data node can either be created by YANG default or created by a client edit operation. The edit transaction processing details for YANG defaults depend on the --default-style parameter value used on the server and the YANG data model being processed.
The following example use-cases will be examined:
Leaf with a Default
Leaf without a Default
Non-Presence Container with a Default
Non-Presence Container without a Default
Presence Container with a Default
Presence Container without a Default
The default processing is handled during an edit operation before the SIL or SIL-SA callbacks are invoked. This section contains the following examples:
the details for a first edit to a node by a client operation
the details for an edit to an existing node by a client operation
the details for a delete edit to an existing node by a client operation
The actual edit operations can change in different scenarios. For example, a 'delete' operation followed by a 'create' operation on the <candidate> datastore can be changed to a 'replace' operation on the <running> datastore.
Printing the Value Path String from a SIL Edit Callback
It is very common to print a debug trace when entering a SIL callback function. There is such a debug trace in the auto-generated code by yangdump-pro.
The 'val_gen_instance_id' function is used to get the string value for the path string of the object node for the callback.
-
status_t val_gen_instance_id(xml_msg_hdr_t *mhdr, const val_value_t *val, ncx_instfmt_t format, xmlChar **buff)
Malloc and Generate the instance ID string for this value node,.
- Parameters:
mhdr -- [inout] message hdr w/ prefix map or NULL to just use the internal prefix mappings
mhdr.pmap may have entries added if prefixes used in the instance identifier which are not already in the pmap
val -- node to generate the instance ID for
format -- desired output format (NCX or Xpath)
buff -- [out] pointer to address of buffer to use
*buff malloced buffer with the instance ID
- Returns:
status
The following example uses this small YANG module to show path strings for the 'test3' list node:
container test1 {
list test2 {
key "a b";
leaf a { type int32; }
leaf b { type string; }
list test3 {
key "c d";
leaf c { type string; }
leaf d { type string; }
}
}
}
The following code snippet shows how this function can be used.
if (LOGDEBUG) {
log_debug("\nEnter u_tlist_test3_edit callback for %s phase",
agt_cbtype_name(cbtyp));
/* print the edit operation */
log_debug_append(" op=%s", op_editop_name(editop));
/* print the path string */
val_value_t *useval = newval;
if (useval == NULL) {
useval = curval;
}
if (useval != NULL) {
ncx_instfmt_t format = NCX_IFMT_XPATH2;
xmlChar *buff = NULL;
res = val_gen_instance_id(RPC_MHDR(msg),
useval,
format,
&buff);
if ((res == NO_ERR) && (buff != NULL)) {
log_debug_append("\nPath: %s", buff);
}
m__free(buff);
}
}
The following log trace shows an example list entry being created:
Enter test3_edit callback for commit phase
Enter u_tlist_test3_edit callback for commit phase op=create
Path: /tlist:test1/tlist:test2[tlist:a="100"][tlist:b="test-b"]/tlist:test3[tlist:c="test-c"][tlist:d="test-d"]
Example YANG Module: testdef2
The YANG module modules/test/pass/testdef2.yang
is used as an example for default handling.
module testdef2 {
yang-version 1.1;
namespace "urn:yumaworks:params:xml:ns:yang:testdef2";
prefix "tdef2";
revision 2023-04-07;
leaf defleaf {
type uint32;
default 42;
}
leaf nodefleaf {
type uint32;
}
container npcon {
leaf defleaf2 {
type uint32;
default 142;
}
leaf nodefleaf2 {
type uint32;
}
}
container pcon {
presence "enabled";
leaf defleaf3 {
type uint32;
default 242;
}
leaf nodefleaf3 {
type uint32;
}
}
}
Each example shows the value and source of
the newval
and curval
parameters that are passed to the
edit callback function.
A simple debug trace function was added to the edit functions:
static void dump_edit_vals (val_value_t *newval,
val_value_t *curval)
{
if (!LOGDEBUG) {
return;
}
log_debug("\nEdit values:");
if (newval) {
log_debug_append("\nnewval set %s",
val_set_by_default(newval) ?
"by default" : "by client");
val_dump_value(newval, 2, DBG);
} else {
log_debug_append("\nnewval NULL");
}
if (curval) {
log_debug_append("\ncurval set %s",
val_set_by_default(curval) ?
"by default" : "by client");
val_dump_value(curval, 2, DBG);
} else {
log_debug_append("\ncurval NULL");
}
} /* dump_edit_vals */
Default Nodes Created During Load Config
The server will usually create default leafs and NP containers during the system <load-config> operation. The defaults are added to an empty datastore or to a datastore with the previous contents from non-volatile storage.
A val_value_t data structure is created for both default and non-default nodes leafs:
The
newval
orcurval
parameters could be set by defaultUse function
val_set_by_default
to check if the value was added by the systemUse function
val_is_default
to check if the value is equal to the YANG default value
For this example it is assumed the initial datastore is empty. This is possible many ways, included by use of the --no-startup parameter.
The
curval
is NULL during a load since the datastore is initially empty.The
newval
is set by default.The editop will be
OP_EDITOP_LOAD
The --default-style parameter is ignored during processing.
The
newval
will be set-by-default in all 3 default stylesThe datastore will be <running>.
In this example, there will be SIL callbacks for the 2 nodes that are created by default.
Leaf /defleaf = 42
Start invoking validate SIL callback for load on testdef2:defleaf Enter defleaf_edit callback for validate phase Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by default tdef2:defleaf 42 curval NULL Finished invoking user callback on testdef2:defleaf
Container /npcon (contains defleaf2 = 142)
Enter npcon_edit callback for validate phase Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by default tdef2:npcon { defleaf2 142 } curval NULL Finished invoking user callback on testdef2:defleaf
Edit Processing For Leafs
The callback details for a leaf are is the simplest of all YANG objects. There is only one instance possible of a leaf.
For non-delete operations:
The
newval
is non-NULL and is set by a client.The
curval
is non-NULL is there is an existing value for the leaf.The edit operation is a 'set' operation if the editop is one of:
OP_EDITOP_CREATE
OP_EDITOP_MERGE
OP_EDITOP_REPLACE
These operations mean the same thing for leafs and should be treated the same.
For delete operations:
The
newval
is NULLThe
curval
is set-by-default or NULLThe edit operation is a 'delete' operation if the editop is one of:
OP_EDITOP_DELETE
OP_EDITOP_REMOVE
For SIL or SIL-SA callback purposes the value of editop will always be
OP_EDITOP_DELETE
for any form of delete operation used by the client.
Leaf with a Default Value
create /defleaf value=100
Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by client tdef2:defleaf 100 curval set by default tdef2:defleaf 42 Finished invoking user callback on testdef2:defleaf
There is always a current value for a leaf with a YANG default, even if it is deleted.
replace /defleaf value=101
Enter defleaf_edit callback for validate phase Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by client tdef2:defleaf 101 curval set by client tdef2:defleaf 100 Finished invoking user callback on testdef2:defleaf
delete /defleaf
Enter u_tdef2_defleaf_edit callback for validate phase Edit values: newval set by default tdef2:defleaf 42 curval set by client tdef2:defleaf 101 Finished invoking user callback on testdef2:defleaf
Leaf Without a Default Value
create /nodefleaf value=200
Enter u_tdef2_nodefleaf_edit callback for validate phase Edit values: newval set by client tdef2:nodefleaf 200 curval NULL Finished invoking user callback on testdef2:nodefleaf
replace /nodefleaf value=201
Enter u_tdef2_nodefleaf_edit callback for validate phase Edit values: newval set by client tdef2:nodefleaf 201 curval set by client tdef2:nodefleaf 200 Finished invoking user callback on testdef2:nodefleaf
delete /nodefleaf
Enter u_tdef2_nodefleaf_edit callback for commit phase Edit values: newval NULL curval set by client tdef2:nodefleaf 201 Finished invoking user callback on testdef2:nodefleaf
Edit Processing For Containers and Lists
There are 2 types of YANG data nodes that can have child nodes:
non-presence container:
These nodes are created automatically.
The --create-empty-npcontainers parameter controls this behavior during edit operations.
The value can either be set-by-default or set-by-client
presence container or list:
These nodes are not created automatically.
The value is always set-by-client
For non-delete operations:
The
newval
is non-NULL and is set by a client.The
curval
is non-NULL is there is an existing value for the node.The edit operation is a 'set' operation if the editop is one of:
OP_EDITOP_CREATE
OP_EDITOP_MERGE
OP_EDITOP_REPLACE
These operations mean the same thing only if the current value is set-by-default or NULL.
For delete operations:
The
newval
is NULLThe
curval
is set-by-default or NULLThe edit operation is a 'delete' operation if the editop is one of:
OP_EDITOP_DELETE
OP_EDITOP_REMOVE
For SIL or SIL-SA callback purposes the value of editop will always be
OP_EDITOP_DELETE
for any form of delete operation used by the client.If the --allow-list-delete-all parameter is 'true' then the following edit operations can be in the edit request. -
OP_EDITOP_DELETE_ALL
-OP_EDITOP_REMOVE_ALL
The server will set editop to
OP_EDITOP_DELETE
for each individual list instance.
Non Presence Container with a Default Value
create /npcon (defleaf2 = 242, nodefleaf2 = 243)
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by client tdef2:npcon { defleaf2 242 nodefleaf2 243 } curval set by default tdef2:npcon { defleaf2 142 } Finished invoking user callback on testdef2:npcon
replace /npcon (defleaf2 = 143, nodefleaf2 NOT SET)
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by client tdef2:npcon { defleaf2 143 } curval set by client tdef2:npcon { defleaf2 242 nodefleaf2 243 } Finished invoking user callback on testdef2:npcon
There is no instance of the 'nodefleaf2' node in 'newval'. The SIL callback for 'npcon' must remove any internal value held for this leaf if its configuration instance is removed.
replace /npcon (defleaf2 NOT SET, nodefleaf2 = 256)
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by client tdef2:npcon { defleaf2 142 nodefleaf2 256 } curval set by client tdef2:npcon { defleaf2 143 } Finished invoking user callback on testdef2:npcon
There is a set-by-default instance of the 'defleaf2' node in 'newval'.
delete /npcon
Enter u_tdef2_npcon_edit callback for validate phase Edit values: newval set by default tdef2:npcon { defleaf2 142 } curval set by client tdef2:npcon { defleaf2 142 nodefleaf2 256 } Finished invoking user callback on testdef2:npcon
Presence Containers and Lists
An example for a presence container pcon
is shown.
The callbacks would be quite similar for lists, except
additional key leaf parameters are used.
create /pcon (defleaf3 = 300, nodefleaf3 = 400)
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval set by client tdef2:pcon { defleaf3 300 nodefleaf3 400 } curval NULL Finished invoking user callback on testdef2:pcon
replace /pcon (defleaf3 = 243, nodefleaf3 NOT SET)
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval set by client tdef2:pcon { defleaf3 243 } curval set by client tdef2:pcon { defleaf3 300 nodefleaf3 400 } Finished invoking user callback on testdef2:pcon
The 'defleaf3' node is set-by-client in this case and the 'nodefleaf3' node is not present and needs to be deleted internally.
replace /npcon (defleaf3 NOT SET, nodefleaf3 = 256)
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval set by client tdef2:pcon { defleaf3 242 nodefleaf3 256 } curval set by client tdef2:pcon { defleaf3 243 } Finished invoking user callback on testdef2:pcon
The 'defleaf3' node is set-by-default in this case and the 'nodefleaf3' node is set-by-client.
delete /pcon
Enter u_tdef2_pcon_edit callback for validate phase Edit values: newval NULL curval set by client tdef2:pcon { defleaf3 242 nodefleaf3 256 } Finished invoking user callback on testdef2:pcon