The following examples illustrates how to construct a list data node. The list nodes have several limitations and special handling nuances. The following list summarize the most important:

  • NETCONF does not require entries to be sorted by index. It only requires the order to be maintained if “ordered-by user” is configured in the YANG module.  The server will maintain the order or instances given in the <edit-config> or startup or other sources. It will maintain YANG schema order so the objects will be returned in the correct order according to the YANG module.

  • val_gen_index_chain MUST be called after all the index leafs have been added to the list.  This can be done before or after any additional child nodes are added to the list.

  • The index (key) nodes should be added first, before any other nodes are added.


There are multiple variants of val_child_add. Sometimes the value is only created so it can be output in XML or JSON, and not to be stored in the database.

The API functions in val_child should be used instead of val.c. The val.c API functions still works, but the new functions should be used in new code. The new functions can fail with an error, so it is important to check the return value in server code.

The yangcli-pro and compiler programs will use val_child_add_force by default, since they do not store the data nodes in a database.


Function
Description
val_child_add
Replaces val_add_child andval_add_child_sorted
val_child_add_force
Allows AVL tree insertion to be skipped forduplicates or incomplete list entries
val_child_insert
Replaces val_insert_child



The following example illustrates how to construct the list data node with multiple children:


******************************************************************** 
* FUNCTION create_list_entry
* 
* Make a list entry based on the key 
* 
* INPUTS: 
*   res = return status 
* 
* RETURNS: 
*    val_value_t of listval entry if no error 
*    else NULL 
* 
*********************************************************************/ 
static val_value_t * 
    create_list_entry(obj_template_t *parentobj, 
                      int32 key, 
                      status_t *res) 
{
    /* get the obj template for the list obj */ 
    obj_template_t *list_obj = 
        obj_find_child(parentobj, 
                       (const xmlChar *)”my-module”, 
                       (const xmlChar *)”my-list”); 
    if (!list_obj) { 
        *res = ERR_NCX_DEF_NOT_FOUND; 
        return NULL; 
    } 

    /* make the list node */ 
    val_value_t *list_value = val_new_value(); 
    if (!list_value) { 
        *res = ERR_INTERNAL_MEM; 
        return NULL; 
    } 
    val_init_from_template(list_value, list_obj); 

    /* make key leaf entry */ 
    val_value_t *child = 
        agt_make_int_leaf(list_obj, 
                          keyname, 
                          key, 
                          res); 
    if (!child) { 
        val_free_value(list_value); 
        return NULL; 
    } 
    *res = val_child_add(child, list_value); 
    if (*res != NO_ERR) {
        val_free_value(child);
        val_free_value(list_value);
        return NULL;
    }

    /* make an extra leaf entry */ 
    child = 
        agt_make_uint_leaf(list_obj, 
                           (const xmlChar *)”my-other-leaf”, 
                           (uint32)32, 
                           res); 
    if (!child) { 
        val_free_value(list_value); 
        return NULL; 
    } 
    *res = val_child_add(child, list_value); 
    if (*res != NO_ERR) {
        val_free_value(child);
        val_free_value(list_value);
        return NULL;
    }

    /* generate the internal index Q chain */ 
    *res = val_gen_index_chain(list_obj, list_value); 
    if (*res != NO_ERR) { 
        val_free_value(list_value); 
        return NULL; 
    }
    return list_value; 

} /* create_list_entry */


This above function is an example function and can be changed according to the required goal. By using this function, we create one list entry that we can now add to the parent or repeat thesame steps but with different key value in order to generate another list entry.

The following example illustrates how to generate multiple list entries using the sample function above and add them to parent container value:


  ...

    /* malloced and construct list values */ 
    status_t res = NO_ERR;
    int32 key = 0; 
    for (key = 10; key <= 15; key++) { 
        val_value_t *list_value =
            create_list_entry(container_obj, 
                              key, 
                              &res); 
        if (!list_value) { 
            return res; 
        } 

        /* add a new list entry into target container */ 
        res = val_child_add(list_value, contvalue); 
        if (res != NO_ERR) {
            val_free_value(list_value);
            return res;
        }
    } 

   ...


As a result we generated container with 5 list entries.