profile
viewpoint

Ask questionssr_get_data returns libyang error during SR_EV_CHANGE with leaf-list default values

Hi Michal,

sorry about the long title, I tried to make it as concise as possible. More complete description of the problem follows.

Given the following yang model:

module example {
  yang-version 1.1;
  namespace "urn:example";
  prefix example;

  typedef foo {
    type enumeration {
      enum "bar1";
      enum "bar2";
      enum "bar3";
    }
  }

  container config {
    container system {
      presence "";
      leaf enabled {
        type boolean;
        default true;
      }
      leaf-list val {
        type foo;
        default "bar1";
        default "bar2";
        default "bar3";
      }
    }
  }
}

And the following patch applied to examples/application_changes_example.c:

diff --git a/examples/application_changes_example.c b/examples/application_changes_example.c
index 9f561f465753..1eea523c14d5 100644
--- a/examples/application_changes_example.c
+++ b/examples/application_changes_example.c
@@ -137,26 +137,23 @@ print_change(sr_change_oper_t op, sr_val_t *old_val, sr_val_t *new_val)
     }
 }
 
-static void
-print_current_config(sr_session_ctx_t *session, const char *module_name)
+static int
+print_current_config(sr_session_ctx_t *session, const char *xpath)
 {
-    sr_val_t *values = NULL;
-    size_t count = 0;
-    int rc = SR_ERR_OK;
-    char *xpath;
+    struct lyd_node *config = NULL;
+    int rc;
 
-    asprintf(&xpath, "/%s:*//.", module_name);
-
-    rc = sr_get_items(session, xpath, 0, 0, &values, &count);
-    free(xpath);
-    if (rc != SR_ERR_OK) {
-        return;
+    if ((rc = sr_get_data(session, xpath, 0, 0, 0, &config)) != SR_ERR_OK) {
+        printf("failed to get data: %s\n", sr_strerror(rc));
+        return rc;
     }
-
-    for (size_t i = 0; i < count; i++){
-        print_val(&values[i]);
+    if (lyd_print_file(stdout, config, LYD_XML, LYP_FORMAT | LYP_WD_ALL)) {
+        printf("failed to print config\n");
+        return SR_ERR_LY;
     }
-    sr_free_values(values, count);
+    lyd_free_withsiblings(config);
+
+    return SR_ERR_OK;
 }
 
 const char *
@@ -202,10 +199,10 @@ module_change_cb(sr_session_ctx_t *session, const char *module_name, const char
 
     printf("\n ========== END OF CHANGES =======================================");
 
-    if (event == SR_EV_DONE) {
-        printf("\n\n ========== CONFIG HAS CHANGED, CURRENT RUNNING CONFIG: ==========\n\n");
-        print_current_config(session, module_name);
-    }
+        printf("\n\n ========== CONFIG %s: ==========\n\n", ev_to_str(event));
+        if ((rc = print_current_config(session, xpath)) != SR_ERR_OK) {
+            return rc;
+        }
 
 cleanup:
     sr_free_change_iter(it);
@@ -257,7 +254,7 @@ main(int argc, char **argv)
 
     /* read current config */
     printf("\n ========== READING RUNNING CONFIG: ==========\n\n");
-    print_current_config(session, mod_name);
+    print_current_config(session, xpath);
 
     /* subscribe for changes in running config */
     rc = sr_module_change_subscribe(session, mod_name, xpath, module_change_cb, NULL, 0, 0, &subscription);

After installing the yang model, the application is started:

~# sysrepoctl -a -i example.yang
~# ./examples/application_changes_example example /example:config &
[1] 5736
Application will watch for changes in "/example:config".

 ========== READING RUNNING CONFIG: ==========

~# cat > config.xml
<config xmlns="urn:example">
  <system>
    <enabled>true</enabled>
    <val>bar1</val>
  </system>
</config>
~# sysrepocfg --import=config.xml -m example -d running

 ========== EVENT change CHANGES: ====================================

CREATED: /example:config/system (container)
CREATED: /example:config/system/enabled = true
CREATED: /example:config/system/val = bar1

 ========== END OF CHANGES =======================================

 ========== CONFIG change: ==========

<config xmlns="urn:example">
  <system>
    <enabled>true</enabled>
    <val>bar1</val>
  </system>
</config>


 ========== EVENT done CHANGES: ====================================

CREATED: /example:config/system (container)
CREATED: /example:config/system/enabled = true
CREATED: /example:config/system/val = bar1

 ========== END OF CHANGES =======================================

 ========== CONFIG done: ==========

<config xmlns="urn:example">
  <system>
    <enabled>true</enabled>
    <val>bar1</val>
  </system>
</config>

~# cat > config.xml
<config xmlns="urn:example">
  <system>
    <enabled>false</enabled>
  </system>
</config>
~# sysrepocfg --import=config.xml -m example -d running

 ========== EVENT change CHANGES: ====================================

MODIFIED: /example:config/system/enabled = true
to /example:config/system/enabled = false
CREATED: /example:config/system/val = bar2 [default]
CREATED: /example:config/system/val = bar3 [default]

 ========== END OF CHANGES =======================================

 ========== CONFIG change: ==========

[ERR]: Insert request refers node (/example:config/system/val[.='bar1']) that is going to be auto-deleted.
failed to get data: libyang error
[ERR]: libyang error
sysrepocfg error: Replace config failed (User callback failed)

If sr_get_data is called only on SR_EV_DONE, there is no error. The problem occurs only when calling sr_get_data on SR_EV_CHANGE when there are leaf-list with default values that are "restored".

I ran the example with gdb to spot the exact cause for the problem, it occurs here:

https://github.com/sysrepo/sysrepo/blob/master/src/edit_diff.c#L2571

Thanks in advance for your help.

sysrepo/sysrepo

Answer questions rjarry

Hi Michal,

I am having the problem with version: 5d5ac78e1247 (devel branch, from April 16th). I am trying with the latest version.

useful!

Related questions

why "There is a not enabled node in ietf-system module, it can not be committed to the running" occured when I try to call "sr_set_item" in running datastore? hot 1
sysrepocfg error using config false in a YANG file hot 1
New sysrepo: leafref can't be used as a list key hot 1
possibility send notification in another thread during subtree_change callback hot 1
Can't connect to netopeer2-server via a unix socket when sysrepo is run as an unprivilieged process hot 1
Filling up startup datastore hot 1
[New-Sysrepo] sr_main_lock not released when install new netopeer2-server hot 1
Can't connect to netopeer2-server via a unix socket when sysrepo is run as an unprivilieged process hot 1
Sysrepo Api to lock DB hot 1
Python global_loop() replacement hot 1
Github User Rank List