Maapi session: database is locked by session failure

I was trying to write to the cdb using maapi.
I can see the two parameters that I wrote to cdb just fine with the show command… however, if I try to overwrite either of them, I am getting a message that says “database is locked by session” and it is pointing to the maapi_start_user_session()
Any ideas what I am missing here?

    syslog(LOG_INFO, "%s: ", __FUNCTION__);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(CONFD_PORT);

    if ((msock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
        syslog(LOG_ERR, "%s: Failed to open socket", __FUNCTION__);
        return CN_ERROR;
    }

    /* using MAAPI to connect to CDB to update configuration data */
    if (maapi_connect(msock, (struct sockaddr*) &addr,
                      sizeof(struct sockaddr_in)) < 0) {
        syslog(LOG_ERR, "%s: Failed to maapi_connect() to confd", __FUNCTION__);
        maapi_close(msock);
        return CN_ERROR;
    }

    if (maapi_load_schemas(msock) != CONFD_OK) {
        syslog(LOG_ERR, "%s: Failed to maapi_load_schemas() to confd", __FUNCTION__);
        maapi_close(msock);
        return CN_ERROR;
    }

    ip.af = AF_INET;
    inet_pton(AF_INET, "0.0.0.0", &ip.ip.v4);

    if ((maapi_start_user_session(msock, NULL, "system", NULL, 0,
                            &ip, CONFD_PROTO_TCP)) != CONFD_OK) {
        syslog(LOG_ERR, "%s: Failed to start maapi user session", __FUNCTION__);
        maapi_close(msock);
        return CONFD_ERR;
    }

    iDB = CONFD_RUNNING;
   // Start MAAPI transaction
    if ((maapi_thandle = maapi_start_trans(
                msock, (enum confd_dbname)iDB, CONFD_READ_WRITE)) < 0 ) {
        syslog(LOG_ERR, "%s: failed to start maapi transaction", __FUNCTION__);
        maapi_close(msock);
        return CONFD_ERR;
    }

    syslog(LOG_INFO, "setting link mode to be differerntiated");
    maapi_set_namespace(msock, maapi_thandle, link__ns);
    if (maapi_set_elem2(msock, maapi_thandle, "differentiated", "/link/mode") != CONFD_OK) {
        syslog(LOG_ERR, "link-mode init failed");
    }

    syslog(LOG_INFO, "setting cos-classifier to be pcp");
    if (maapi_set_elem2(msock, maapi_thandle, "pcp", "/link/cos-classifier") != CONFD_OK) {
        syslog(LOG_ERR, "cos-classifier init to pcp failed");
    }

    if (maapi_apply_trans(msock, maapi_thandle, 0) != CONFD_OK) {
        syslog(LOG_ERR, "%s: failed to apply transaction", __FUNCTION__);
    }

    if (maapi_finish_trans(msock, maapi_thandle) != CONFD_OK) {
        syslog(LOG_ERR, "%s: failed to finish transaction", __FUNCTION__);
    }
    syslog(LOG_INFO, "%s: Changes applied to CDB successfully", __FUNCTION__);

    if (maapi_end_user_session(msock) != CONFD_OK) {
        syslog(LOG_ERR, "%s: failed to end user session", __FUNCTION__);
    }

    maapi_close(msock);

Actually I just realized from the logs that it is the maapi_apply_trans() that failed. I am not sure what I am doing wrong…

My yang definitions are:

     leaf mode {
          type cndlp-types:cndlp-link-mode;
          tailf:info "Mode of operation for traffic treatment";
      }
      leaf cos-classifier {
          when "../mode = 'differentiated'";
          type cndlp-types:cndlp-classifier-mode;
          tailf:info "Mode of traffic treatment based on vlan or pcp";
      }

From syslog, I see the following (dpm is name of my daemon):

<INFO>: 2017-09-18T21:05:21.3063 qemux86-64 dpm: update_config_cdb:
<INFO>: 2017-09-18T21:05:21.3437 qemux86-64 dpm: setting link mode to be differerntiated
<INFO>: 2017-09-18T21:05:21.4014 qemux86-64 dpm: setting cos-classifier to be pcp
<ERR>: 2017-09-18T21:05:51.4173 qemux86-64 confd[1067]: - CDB client (dpm) timed out, waiting for call to sync_subscription
<INFO>: 2017-09-18T21:05:51.4182 qemux86-64 confd[1067]: devel-cdb Restored running from snapshot
<ERR>: 2017-09-18T21:05:51.4264 qemux86-64 dpm: update_config_cdb: failed to apply transaction

You might want to understand why the Sync Subscription is not done by your daemon.

Check also who has a read lock. I think this is the reason why you can’t update the second time.

@nabil, can you please help me out how to find

  • who has read lock
  • how to see why sync subscription is not done? Is there any API that I am missing to invoke?

BTW. This is happening when I try to handle delete command that deletes all configuration but I had to update the CDB with default values. I was triggering maapi calls to CDB to update few parameters to default values during COMMIT phase.

This needs some look up in the code and some debugging.
Don’t trigger MAAPI calls during a transaction commit, to change configuration. This is where you are getting deadlocked, unless you implement transaction hooks.

I recommend you look at transaction hooks that will allow your application to participate in a configuration change transaction. This way you can attach a MAAPI Session to the transaction and do whatever you need before the validation phase kicks in.

You can find information about this in the user guide:
10.6. Hooks